added generic tool code
[anytun.git] / Sockets / MemFile.cpp
blobedbe619e2fc8251a43155af413c53f32aa1fbf1a
1 /** \file MemFile.cpp
2 ** \date 2005-04-25
3 ** \author grymse@alhem.net
4 **/
5 /*
6 Copyright (C) 2004-2007 Anders Hedstrom
8 This library is made available under the terms of the GNU GPL.
10 If you would like to use this library in a closed-source application,
11 a separate license agreement is available. For information about
12 the closed-source license agreement for the C++ sockets library,
13 please visit http://www.alhem.net/Sockets/license.html and/or
14 email license@alhem.net.
16 This program is free software; you can redistribute it and/or
17 modify it under the terms of the GNU General Public License
18 as published by the Free Software Foundation; either version 2
19 of the License, or (at your option) any later version.
21 This program is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 #ifdef _MSC_VER
31 #pragma warning(disable:4786)
32 #endif
33 #include <stdio.h>
34 #include <stdarg.h>
36 #include "MemFile.h"
39 #ifdef SOCKETS_NAMESPACE
40 namespace SOCKETS_NAMESPACE {
41 #endif
44 std::map<std::string,MemFile::block_t *> MemFile::m_files;
47 MemFile::MemFile()
48 :m_temporary(true)
49 ,m_base(new block_t)
50 ,m_current_read(m_base)
51 ,m_current_write(m_base)
52 ,m_current_write_nr(0)
53 ,m_read_ptr(0)
54 ,m_write_ptr(0)
55 ,m_b_read_caused_eof(false)
60 MemFile::MemFile(const std::string& path)
61 :m_path(path)
62 ,m_temporary(false)
63 ,m_base(m_files[path])
64 ,m_current_read(NULL)
65 ,m_current_write(NULL)
66 ,m_current_write_nr(0)
67 ,m_read_ptr(0)
68 ,m_write_ptr(0)
69 ,m_b_read_caused_eof(false)
71 if (!m_base)
73 m_base = new block_t;
74 m_files[path] = m_base;
76 m_current_read = m_base;
77 m_current_write = m_base;
81 MemFile::~MemFile()
83 while (m_base && m_temporary)
85 block_t *p = m_base;
86 m_base = p -> next;
87 delete p;
92 bool MemFile::fopen(const std::string& path, const std::string& mode)
94 return true;
98 void MemFile::fclose()
103 size_t MemFile::fread(char *ptr, size_t size, size_t nmemb) const
105 size_t p = m_read_ptr % BLOCKSIZE;
106 size_t sz = size * nmemb;
107 size_t available = m_write_ptr - m_read_ptr;
108 if (sz > available) // read beyond eof
110 sz = available;
111 m_b_read_caused_eof = true;
113 if (!sz)
115 return 0;
117 if (p + sz < BLOCKSIZE)
119 memcpy(ptr, m_current_read -> data + p, sz);
120 m_read_ptr += sz;
122 else
124 size_t sz1 = BLOCKSIZE - p;
125 size_t sz2 = sz - sz1;
126 memcpy(ptr, m_current_read -> data + p, sz1);
127 m_read_ptr += sz1;
128 while (sz2 > BLOCKSIZE)
130 if (m_current_read -> next)
132 m_current_read = m_current_read -> next;
133 memcpy(ptr + sz1, m_current_read -> data, BLOCKSIZE);
134 m_read_ptr += BLOCKSIZE;
135 sz1 += BLOCKSIZE;
136 sz2 -= BLOCKSIZE;
138 else
140 return sz1;
143 if (m_current_read -> next)
145 m_current_read = m_current_read -> next;
146 memcpy(ptr + sz1, m_current_read -> data, sz2);
147 m_read_ptr += sz2;
149 else
151 return sz1;
154 return sz;
158 size_t MemFile::fwrite(const char *ptr, size_t size, size_t nmemb)
160 size_t p = m_write_ptr % BLOCKSIZE;
161 int nr = (int)m_write_ptr / BLOCKSIZE;
162 size_t sz = size * nmemb;
163 if (m_current_write_nr < nr)
165 block_t *next = new block_t;
166 m_current_write -> next = next;
167 m_current_write = next;
168 m_current_write_nr++;
170 if (p + sz <= BLOCKSIZE)
172 memcpy(m_current_write -> data + p, ptr, sz);
173 m_write_ptr += sz;
175 else
177 size_t sz1 = BLOCKSIZE - p; // size left
178 size_t sz2 = sz - sz1;
179 memcpy(m_current_write -> data + p, ptr, sz1);
180 m_write_ptr += sz1;
181 while (sz2 > BLOCKSIZE)
183 if (m_current_write -> next)
185 m_current_write = m_current_write -> next;
186 m_current_write_nr++;
188 else
190 block_t *next = new block_t;
191 m_current_write -> next = next;
192 m_current_write = next;
193 m_current_write_nr++;
195 memcpy(m_current_write -> data, ptr + sz1, BLOCKSIZE);
196 m_write_ptr += BLOCKSIZE;
197 sz1 += BLOCKSIZE;
198 sz2 -= BLOCKSIZE;
200 if (m_current_write -> next)
202 m_current_write = m_current_write -> next;
203 m_current_write_nr++;
205 else
207 block_t *next = new block_t;
208 m_current_write -> next = next;
209 m_current_write = next;
210 m_current_write_nr++;
212 memcpy(m_current_write -> data, ptr + sz1, sz2);
213 m_write_ptr += sz2;
215 return sz;
220 char *MemFile::fgets(char *s, int size) const
222 int n = 0;
223 while (n < size - 1 && !eof())
225 char c;
226 size_t sz = fread(&c, 1, 1);
227 if (sz)
229 if (c == 10)
231 s[n] = 0;
232 return s;
234 s[n++] = c;
237 s[n] = 0;
238 return s;
242 void MemFile::fprintf(const char *format, ...)
244 va_list ap;
245 char tmp[BLOCKSIZE];
246 va_start(ap, format);
247 #ifdef _WIN32
248 vsprintf(tmp, format, ap);
249 #else
250 vsnprintf(tmp, BLOCKSIZE - 1, format, ap);
251 #endif
252 va_end(ap);
253 fwrite(tmp, 1, strlen(tmp));
257 off_t MemFile::size() const
259 return (off_t)m_write_ptr;
263 bool MemFile::eof() const
265 return m_b_read_caused_eof; //(m_read_ptr < m_write_ptr) ? false : true;
269 void MemFile::reset_read() const
271 m_read_ptr = 0;
272 m_current_read = m_base;
276 void MemFile::reset_write()
278 m_write_ptr = 0;
279 m_current_write = m_base;
280 m_current_write_nr = 0;
284 #ifdef SOCKETS_NAMESPACE
286 #endif