Rev 154 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
116 | pmbaty | 1 | // buffer.cpp |
2 | |||
3 | #include "common.h" |
||
4 | |||
5 | |||
6 | // cross-platform facilities |
||
7 | #ifndef _WIN32 |
||
8 | #define fopen_s(fp,filename,mode) *(fp) = fopen (filename, mode) |
||
9 | #endif // _WIN32 |
||
10 | |||
11 | |||
12 | void Buffer_Initialize (buffer_t *buffer) |
||
13 | { |
||
14 | // this function initializes a new buffer_t structure, resetting its data pointer and size. |
||
15 | |||
16 | buffer->data = NULL; // allocate max_size bytes for data |
||
17 | buffer->size = 0; // reset size |
||
18 | |||
19 | return; // finished, buffer structure is empty |
||
20 | } |
||
21 | |||
22 | |||
23 | void Buffer_Forget (buffer_t *buffer) |
||
24 | { |
||
25 | // this function forgets a buffer's contents, freeing its associated memory buffer, |
||
26 | // and resets the buffer_t structure. |
||
27 | |||
28 | if (buffer->data != NULL) |
||
29 | free (buffer->data); // free buffer data |
||
30 | buffer->data = NULL; |
||
31 | buffer->size = 0; // reset data size |
||
32 | |||
33 | return; // finished, buffer structure is virgin again |
||
34 | } |
||
35 | |||
36 | |||
37 | int Buffer_Append (buffer_t *buffer, char *data, unsigned long data_size) |
||
38 | { |
||
39 | // this function appends the content of data to a buffer's data. |
||
40 | // Returns 1 on success, 0 on error. |
||
41 | |||
42 | char *new_data; |
||
43 | |||
44 | // first, reallocate space to hold data_size bytes more |
||
186 | pmbaty | 45 | new_data = (char *) realloc (buffer->data, buffer->size + data_size + 2); |
116 | pmbaty | 46 | if (new_data == NULL) |
47 | return (0); // on failure, return an error value |
||
48 | |||
49 | buffer->data = new_data; // save pointer to reallocated data |
||
50 | memcpy (&buffer->data[buffer->size], data, data_size); // write new data at the end |
||
186 | pmbaty | 51 | buffer->data[buffer->size + data_size + 0] = 0; // always null-terminate buffers, silently |
52 | buffer->data[buffer->size + data_size + 1] = 0; // always null-terminate buffers, silently |
||
116 | pmbaty | 53 | buffer->size += data_size; // and increment buffer size |
54 | |||
55 | return (1); // buffer appended successfully, return SUCCESS |
||
56 | } |
||
57 | |||
58 | |||
59 | int Buffer_Prepend (buffer_t *buffer, char *data, unsigned long data_size) |
||
60 | { |
||
61 | // this function prepends the content of data to a buffer's data. |
||
62 | // Returns 1 on success, 0 on error. |
||
63 | |||
64 | char *new_data; |
||
65 | |||
66 | // first, reallocate space to hold data_size bytes more |
||
186 | pmbaty | 67 | new_data = (char *) realloc (buffer->data, data_size + buffer->size + 2); |
116 | pmbaty | 68 | if (new_data == NULL) |
69 | return (0); // on failure, return an error value |
||
70 | |||
71 | buffer->data = new_data; // save pointer to reallocated data |
||
72 | if (buffer->size > 0) |
||
73 | memmove (&buffer->data[data_size], buffer->data, buffer->size); // move existing data to the end |
||
74 | memcpy (buffer->data, data, data_size); // write new data at the beginning |
||
186 | pmbaty | 75 | buffer->data[buffer->size + data_size + 0] = 0; // always null-terminate buffers, silently |
76 | buffer->data[buffer->size + data_size + 1] = 0; // always null-terminate buffers, silently |
||
116 | pmbaty | 77 | buffer->size += data_size; // and increment buffer size |
78 | |||
79 | return (1); // buffer appended successfully, return SUCCESS |
||
80 | } |
||
81 | |||
82 | |||
83 | int Buffer_WriteAt (buffer_t *buffer, unsigned long write_index, char *data, unsigned long data_size) |
||
84 | { |
||
85 | // this function writes the content of data to a buffer's data at position write_index. |
||
86 | // Returns 1 on success, 0 on error. |
||
87 | |||
88 | char *new_data; |
||
154 | pmbaty | 89 | char *dest; |
116 | pmbaty | 90 | |
91 | // see if we need to grow the data |
||
92 | if (write_index + data_size > buffer->size) |
||
93 | { |
||
94 | // if so, reallocate data buffer at the right size |
||
186 | pmbaty | 95 | new_data = (char *) realloc (buffer->data, write_index + data_size + 2); |
116 | pmbaty | 96 | if (new_data == NULL) |
97 | return (0); // on failure, return an error value |
||
98 | |||
99 | buffer->data = new_data; // save pointer to reallocated data |
||
100 | } |
||
101 | |||
154 | pmbaty | 102 | // do dest and source overlap ? |
103 | dest = &buffer->data[write_index]; |
||
104 | if (((data <= dest) && (data + data_size > dest)) || ((dest <= data) && (dest + data_size > data))) |
||
105 | memmove (&buffer->data[write_index], data, data_size); // if so, move data in place |
||
106 | else |
||
107 | memcpy (&buffer->data[write_index], data, data_size); // else write data in place (faster) |
||
116 | pmbaty | 108 | if (write_index + data_size > buffer->size) |
186 | pmbaty | 109 | { |
110 | buffer->data[write_index + data_size + 0] = 0; // always null-terminate buffers, silently |
||
111 | buffer->data[write_index + data_size + 1] = 0; // always null-terminate buffers, silently |
||
116 | pmbaty | 112 | buffer->size = write_index + data_size; // update data size only if it growed |
186 | pmbaty | 113 | } |
116 | pmbaty | 114 | |
115 | return (1); // buffer written successfully, return SUCCESS |
||
116 | } |
||
117 | |||
118 | |||
119 | int Buffer_ReadFromFile (buffer_t *buffer, const char *file_pathname) |
||
120 | { |
||
121 | // this function copies the contents of file_pathname in a newly allocated data buffer |
||
122 | // and fills in the buffer size accordingly. It is up to the caller to free that buffer. |
||
123 | // Returns 1 on success, 0 on error. |
||
124 | |||
125 | struct stat stat_buffer; |
||
126 | FILE *fp; |
||
127 | |||
128 | // start by reporting a zero length |
||
129 | buffer->size = 0; |
||
130 | |||
131 | // figure out file existence and size |
||
132 | if (stat (file_pathname, &stat_buffer) != 0) |
||
133 | return (0); // on failure, return an error value |
||
134 | |||
135 | // allocate enough space for it |
||
186 | pmbaty | 136 | if ((buffer->data = (char *) malloc (stat_buffer.st_size + 2)) == NULL) |
116 | pmbaty | 137 | return (0); // on failure, return an error value |
138 | |||
139 | // open it for binary reading |
||
140 | fopen_s (&fp, file_pathname, "rb"); |
||
141 | if (fp == NULL) |
||
142 | { |
||
143 | free (buffer->data); |
||
144 | return (0); // on failure, return an error value |
||
145 | } |
||
146 | |||
147 | // and read it at once |
||
148 | if (fread (buffer->data, 1, stat_buffer.st_size, fp) != (size_t) stat_buffer.st_size) |
||
149 | { |
||
150 | free (buffer->data); |
||
151 | return (0); // on failure, return an error value |
||
152 | } |
||
153 | |||
154 | fclose (fp); // finished, close file |
||
186 | pmbaty | 155 | buffer->data[stat_buffer.st_size + 0] = 0; // always null-terminate buffers, silently |
156 | buffer->data[stat_buffer.st_size + 1] = 0; // always null-terminate buffers, silently |
||
116 | pmbaty | 157 | buffer->size = stat_buffer.st_size; // report its size |
158 | |||
159 | return (1); // and return SUCCESS |
||
160 | } |
||
161 | |||
162 | |||
163 | int Buffer_ReadFromFileW (buffer_t *buffer, const wchar_t *file_pathname) |
||
164 | { |
||
165 | // this function copies the contents of file_pathname in a newly allocated data buffer |
||
166 | // and fills in the buffer size accordingly. It is up to the caller to free that buffer. |
||
167 | // Returns 1 on success, 0 on error. |
||
168 | |||
169 | struct _stat stat_buffer; |
||
170 | FILE *fp; |
||
171 | |||
172 | // start by reporting a zero length |
||
173 | buffer->size = 0; |
||
174 | |||
175 | // figure out file existence and size |
||
176 | if (_wstat (file_pathname, &stat_buffer) != 0) |
||
177 | return (0); // on failure, return an error value |
||
178 | |||
179 | // allocate enough space for it |
||
186 | pmbaty | 180 | if ((buffer->data = (char *) malloc (stat_buffer.st_size + 2)) == NULL) |
116 | pmbaty | 181 | return (0); // on failure, return an error value |
182 | |||
186 | pmbaty | 183 | // open it for binary reading |
116 | pmbaty | 184 | _wfopen_s (&fp, file_pathname, L"rb"); |
185 | if (fp == NULL) |
||
186 | { |
||
187 | free (buffer->data); |
||
188 | return (0); // on failure, return an error value |
||
189 | } |
||
190 | |||
191 | // and read it at once |
||
192 | if (fread (buffer->data, 1, stat_buffer.st_size, fp) != (size_t) stat_buffer.st_size) |
||
193 | { |
||
194 | free (buffer->data); |
||
195 | return (0); // on failure, return an error value |
||
196 | } |
||
197 | |||
198 | fclose (fp); // finished, close file |
||
186 | pmbaty | 199 | buffer->data[stat_buffer.st_size + 0] = 0; // always null-terminate buffers, silently |
200 | buffer->data[stat_buffer.st_size + 1] = 0; // always null-terminate buffers, silently |
||
116 | pmbaty | 201 | buffer->size = stat_buffer.st_size; // report its size |
202 | |||
203 | return (1); // and return SUCCESS |
||
204 | } |
||
205 | |||
206 | |||
207 | int Buffer_WriteToFile (buffer_t *buffer, const char *file_pathname) |
||
208 | { |
||
209 | // this function copies the contents of buffer's data into the file pointed to by |
||
210 | // file_pathname. Returns 1 on success, 0 on error. |
||
211 | |||
212 | FILE *fp; |
||
213 | |||
214 | // open file for binary writing |
||
215 | fopen_s (&fp, file_pathname, "wb"); |
||
216 | if (fp == NULL) |
||
217 | return (0); |
||
218 | |||
219 | // and write it at once |
||
220 | if (fwrite (buffer->data, 1, buffer->size, fp) != (size_t) buffer->size) |
||
221 | return (0); |
||
222 | |||
223 | fclose (fp); // finished, close file |
||
224 | return (1); // and return SUCCESS |
||
225 | } |
||
226 | |||
227 | |||
228 | int Buffer_WriteToFileW (buffer_t *buffer, const wchar_t *file_pathname) |
||
229 | { |
||
230 | // this function copies the contents of buffer's data into the file pointed to by |
||
231 | // file_pathname. Returns 1 on success, 0 on error. |
||
232 | |||
233 | FILE *fp; |
||
234 | |||
235 | // open file for binary writing |
||
236 | _wfopen_s (&fp, file_pathname, L"wb"); |
||
237 | if (fp == NULL) |
||
238 | return (0); |
||
239 | |||
240 | // and write it at once |
||
241 | if (fwrite (buffer->data, 1, buffer->size, fp) != (size_t) buffer->size) |
||
242 | return (0); |
||
243 | |||
244 | fclose (fp); // finished, close file |
||
245 | return (1); // and return SUCCESS |
||
246 | } |
||
247 | |||
248 | |||
249 | char *Buffer_Find (buffer_t *buffer, char *needle, unsigned long needle_length) |
||
250 | { |
||
251 | // returns a pointer to the first occurence of needle in buffer haystack, or NULL if not found |
||
252 | |||
253 | unsigned long byte_index; |
||
254 | |||
255 | if (buffer->size < needle_length) |
||
256 | return (NULL); // consistency check: if buffer is too small for needle, return NULL |
||
257 | |||
258 | // parse buffer from start to end |
||
259 | for (byte_index = 0; byte_index < buffer->size - needle_length; byte_index++) |
||
260 | if (memcmp (&buffer->data[byte_index], needle, needle_length) == 0) |
||
261 | return (&buffer->data[byte_index]); // return the first match we find |
||
262 | |||
263 | return (NULL); // definitely no needle in buffer |
||
264 | } |
||
265 | |||
266 | |||
267 | int Buffer_Compare (buffer_t *buffer1, buffer_t *buffer2) |
||
268 | { |
||
269 | // compares two buffers and return 0 if they match, non-zero if they differ. |
||
270 | // If their size differ, the difference between both is returned. |
||
271 | // If their content differ, the result of memcmp() is returned. |
||
272 | |||
273 | if (buffer1->size != buffer2->size) |
||
274 | return (buffer2->size - buffer1->size); // buffers differ in size |
||
275 | |||
276 | return (memcmp (buffer1->data, buffer2->data, buffer1->size)); // do a memcmp() on both buffers |
||
277 | } |
||
278 | |||
279 | |||
280 | unsigned long Buffer_OffsetOf (buffer_t *buffer, void *something) |
||
281 | { |
||
282 | // returns the absolute offset of the data pointed to by something relatively to the beginning of buffer data |
||
283 | |||
284 | return ((unsigned long) something - (unsigned long) buffer->data); |
||
285 | } |