Rev 116 | Go to most recent revision | 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 |
||
45 | new_data = (char *) realloc (buffer->data, buffer->size + data_size); |
||
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 |
||
51 | buffer->size += data_size; // and increment buffer size |
||
52 | |||
53 | return (1); // buffer appended successfully, return SUCCESS |
||
54 | } |
||
55 | |||
56 | |||
57 | int Buffer_Prepend (buffer_t *buffer, char *data, unsigned long data_size) |
||
58 | { |
||
59 | // this function prepends the content of data to a buffer's data. |
||
60 | // Returns 1 on success, 0 on error. |
||
61 | |||
62 | char *new_data; |
||
63 | |||
64 | // first, reallocate space to hold data_size bytes more |
||
65 | new_data = (char *) realloc (buffer->data, data_size + buffer->size); |
||
66 | if (new_data == NULL) |
||
67 | return (0); // on failure, return an error value |
||
68 | |||
69 | buffer->data = new_data; // save pointer to reallocated data |
||
70 | if (buffer->size > 0) |
||
71 | memmove (&buffer->data[data_size], buffer->data, buffer->size); // move existing data to the end |
||
72 | memcpy (buffer->data, data, data_size); // write new data at the beginning |
||
73 | buffer->size += data_size; // and increment buffer size |
||
74 | |||
75 | return (1); // buffer appended successfully, return SUCCESS |
||
76 | } |
||
77 | |||
78 | |||
79 | int Buffer_WriteAt (buffer_t *buffer, unsigned long write_index, char *data, unsigned long data_size) |
||
80 | { |
||
81 | // this function writes the content of data to a buffer's data at position write_index. |
||
82 | // Returns 1 on success, 0 on error. |
||
83 | |||
84 | char *new_data; |
||
154 | pmbaty | 85 | char *dest; |
116 | pmbaty | 86 | |
87 | // see if we need to grow the data |
||
88 | if (write_index + data_size > buffer->size) |
||
89 | { |
||
90 | // if so, reallocate data buffer at the right size |
||
91 | new_data = (char *) realloc (buffer->data, write_index + data_size); |
||
92 | if (new_data == NULL) |
||
93 | return (0); // on failure, return an error value |
||
94 | |||
95 | buffer->data = new_data; // save pointer to reallocated data |
||
96 | } |
||
97 | |||
154 | pmbaty | 98 | // do dest and source overlap ? |
99 | dest = &buffer->data[write_index]; |
||
100 | if (((data <= dest) && (data + data_size > dest)) || ((dest <= data) && (dest + data_size > data))) |
||
101 | memmove (&buffer->data[write_index], data, data_size); // if so, move data in place |
||
102 | else |
||
103 | memcpy (&buffer->data[write_index], data, data_size); // else write data in place (faster) |
||
116 | pmbaty | 104 | if (write_index + data_size > buffer->size) |
105 | buffer->size = write_index + data_size; // update data size only if it growed |
||
106 | |||
107 | return (1); // buffer written successfully, return SUCCESS |
||
108 | } |
||
109 | |||
110 | |||
111 | int Buffer_ReadFromFile (buffer_t *buffer, const char *file_pathname) |
||
112 | { |
||
113 | // this function copies the contents of file_pathname in a newly allocated data buffer |
||
114 | // and fills in the buffer size accordingly. It is up to the caller to free that buffer. |
||
115 | // Returns 1 on success, 0 on error. |
||
116 | |||
117 | struct stat stat_buffer; |
||
118 | FILE *fp; |
||
119 | |||
120 | // start by reporting a zero length |
||
121 | buffer->size = 0; |
||
122 | |||
123 | // figure out file existence and size |
||
124 | if (stat (file_pathname, &stat_buffer) != 0) |
||
125 | return (0); // on failure, return an error value |
||
126 | |||
127 | // allocate enough space for it |
||
128 | if ((buffer->data = (char *) malloc (stat_buffer.st_size)) == NULL) |
||
129 | return (0); // on failure, return an error value |
||
130 | |||
131 | // open it for binary reading |
||
132 | fopen_s (&fp, file_pathname, "rb"); |
||
133 | if (fp == NULL) |
||
134 | { |
||
135 | free (buffer->data); |
||
136 | return (0); // on failure, return an error value |
||
137 | } |
||
138 | |||
139 | // and read it at once |
||
140 | if (fread (buffer->data, 1, stat_buffer.st_size, fp) != (size_t) stat_buffer.st_size) |
||
141 | { |
||
142 | free (buffer->data); |
||
143 | return (0); // on failure, return an error value |
||
144 | } |
||
145 | |||
146 | fclose (fp); // finished, close file |
||
147 | buffer->size = stat_buffer.st_size; // report its size |
||
148 | |||
149 | return (1); // and return SUCCESS |
||
150 | } |
||
151 | |||
152 | |||
153 | int Buffer_ReadFromFileW (buffer_t *buffer, const wchar_t *file_pathname) |
||
154 | { |
||
155 | // this function copies the contents of file_pathname in a newly allocated data buffer |
||
156 | // and fills in the buffer size accordingly. It is up to the caller to free that buffer. |
||
157 | // Returns 1 on success, 0 on error. |
||
158 | |||
159 | struct _stat stat_buffer; |
||
160 | FILE *fp; |
||
161 | |||
162 | // start by reporting a zero length |
||
163 | buffer->size = 0; |
||
164 | |||
165 | // figure out file existence and size |
||
166 | if (_wstat (file_pathname, &stat_buffer) != 0) |
||
167 | return (0); // on failure, return an error value |
||
168 | |||
169 | // allocate enough space for it |
||
170 | if ((buffer->data = (char *) malloc (stat_buffer.st_size)) == NULL) |
||
171 | return (0); // on failure, return an error value |
||
172 | |||
173 | // open it for binary reading |
||
174 | _wfopen_s (&fp, file_pathname, L"rb"); |
||
175 | if (fp == NULL) |
||
176 | { |
||
177 | free (buffer->data); |
||
178 | return (0); // on failure, return an error value |
||
179 | } |
||
180 | |||
181 | // and read it at once |
||
182 | if (fread (buffer->data, 1, stat_buffer.st_size, fp) != (size_t) stat_buffer.st_size) |
||
183 | { |
||
184 | free (buffer->data); |
||
185 | return (0); // on failure, return an error value |
||
186 | } |
||
187 | |||
188 | fclose (fp); // finished, close file |
||
189 | buffer->size = stat_buffer.st_size; // report its size |
||
190 | |||
191 | return (1); // and return SUCCESS |
||
192 | } |
||
193 | |||
194 | |||
195 | int Buffer_WriteToFile (buffer_t *buffer, const char *file_pathname) |
||
196 | { |
||
197 | // this function copies the contents of buffer's data into the file pointed to by |
||
198 | // file_pathname. Returns 1 on success, 0 on error. |
||
199 | |||
200 | FILE *fp; |
||
201 | |||
202 | // open file for binary writing |
||
203 | fopen_s (&fp, file_pathname, "wb"); |
||
204 | if (fp == NULL) |
||
205 | return (0); |
||
206 | |||
207 | // and write it at once |
||
208 | if (fwrite (buffer->data, 1, buffer->size, fp) != (size_t) buffer->size) |
||
209 | return (0); |
||
210 | |||
211 | fclose (fp); // finished, close file |
||
212 | return (1); // and return SUCCESS |
||
213 | } |
||
214 | |||
215 | |||
216 | int Buffer_WriteToFileW (buffer_t *buffer, const wchar_t *file_pathname) |
||
217 | { |
||
218 | // this function copies the contents of buffer's data into the file pointed to by |
||
219 | // file_pathname. Returns 1 on success, 0 on error. |
||
220 | |||
221 | FILE *fp; |
||
222 | |||
223 | // open file for binary writing |
||
224 | _wfopen_s (&fp, file_pathname, L"wb"); |
||
225 | if (fp == NULL) |
||
226 | return (0); |
||
227 | |||
228 | // and write it at once |
||
229 | if (fwrite (buffer->data, 1, buffer->size, fp) != (size_t) buffer->size) |
||
230 | return (0); |
||
231 | |||
232 | fclose (fp); // finished, close file |
||
233 | return (1); // and return SUCCESS |
||
234 | } |
||
235 | |||
236 | |||
237 | char *Buffer_Find (buffer_t *buffer, char *needle, unsigned long needle_length) |
||
238 | { |
||
239 | // returns a pointer to the first occurence of needle in buffer haystack, or NULL if not found |
||
240 | |||
241 | unsigned long byte_index; |
||
242 | |||
243 | if (buffer->size < needle_length) |
||
244 | return (NULL); // consistency check: if buffer is too small for needle, return NULL |
||
245 | |||
246 | // parse buffer from start to end |
||
247 | for (byte_index = 0; byte_index < buffer->size - needle_length; byte_index++) |
||
248 | if (memcmp (&buffer->data[byte_index], needle, needle_length) == 0) |
||
249 | return (&buffer->data[byte_index]); // return the first match we find |
||
250 | |||
251 | return (NULL); // definitely no needle in buffer |
||
252 | } |
||
253 | |||
254 | |||
255 | int Buffer_Compare (buffer_t *buffer1, buffer_t *buffer2) |
||
256 | { |
||
257 | // compares two buffers and return 0 if they match, non-zero if they differ. |
||
258 | // If their size differ, the difference between both is returned. |
||
259 | // If their content differ, the result of memcmp() is returned. |
||
260 | |||
261 | if (buffer1->size != buffer2->size) |
||
262 | return (buffer2->size - buffer1->size); // buffers differ in size |
||
263 | |||
264 | return (memcmp (buffer1->data, buffer2->data, buffer1->size)); // do a memcmp() on both buffers |
||
265 | } |
||
266 | |||
267 | |||
268 | unsigned long Buffer_OffsetOf (buffer_t *buffer, void *something) |
||
269 | { |
||
270 | // returns the absolute offset of the data pointed to by something relatively to the beginning of buffer data |
||
271 | |||
272 | return ((unsigned long) something - (unsigned long) buffer->data); |
||
273 | } |