1 /*
2  * "streamable kanji code filter and converter"
3  * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
4  *
5  * LICENSE NOTICES
6  *
7  * This file is part of "streamable kanji code filter and converter",
8  * which is distributed under the terms of GNU Lesser General Public
9  * License (version 2) as published by the Free Software Foundation.
10  *
11  * This software is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with "streamable kanji code filter and converter";
18  * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
19  * Suite 330, Boston, MA  02111-1307  USA
20  *
21  * The author of this file:
22  *
23  */
24 /*
25  * The source code included in this files was separated from mbfilter.c
26  * by Moriyoshi Koizumi <moriyoshi@php.net> on 20 Dec 2002. The file
27  * mbfilter.c is included in this package .
28  *
29  */
30 
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34 
35 #ifdef HAVE_STDDEF_H
36 #include <stddef.h>
37 #endif
38 
39 #include <string.h>
40 #include "mbfl_allocators.h"
41 #include "mbfl_string.h"
42 #include "mbfl_memory_device.h"
43 
44 /*
45  * memory device output functions
46  */
47 void
mbfl_memory_device_init(mbfl_memory_device * device,size_t initsz,size_t allocsz)48 mbfl_memory_device_init(mbfl_memory_device *device, size_t initsz, size_t allocsz)
49 {
50 	if (device) {
51 		device->length = 0;
52 		device->buffer = NULL;
53 		if (initsz > 0) {
54 			device->buffer = (unsigned char *)mbfl_malloc(initsz);
55 			if (device->buffer != NULL) {
56 				device->length = initsz;
57 			}
58 		}
59 		device->pos = 0;
60 		if (allocsz > MBFL_MEMORY_DEVICE_ALLOC_SIZE) {
61 			device->allocsz = allocsz;
62 		} else {
63 			device->allocsz = MBFL_MEMORY_DEVICE_ALLOC_SIZE;
64 		}
65 	}
66 }
67 
68 void
mbfl_memory_device_realloc(mbfl_memory_device * device,size_t initsz,size_t allocsz)69 mbfl_memory_device_realloc(mbfl_memory_device *device, size_t initsz, size_t allocsz)
70 {
71 	unsigned char *tmp;
72 
73 	if (device) {
74 		if (initsz > device->length) {
75 			tmp = (unsigned char *)mbfl_realloc((void *)device->buffer, initsz);
76 			if (tmp != NULL) {
77 				device->buffer = tmp;
78 				device->length = initsz;
79 			}
80 		}
81 		if (allocsz > MBFL_MEMORY_DEVICE_ALLOC_SIZE) {
82 			device->allocsz = allocsz;
83 		} else {
84 			device->allocsz = MBFL_MEMORY_DEVICE_ALLOC_SIZE;
85 		}
86 	}
87 }
88 
89 void
mbfl_memory_device_clear(mbfl_memory_device * device)90 mbfl_memory_device_clear(mbfl_memory_device *device)
91 {
92 	if (device) {
93 		if (device->buffer) {
94 			mbfl_free(device->buffer);
95 		}
96 		device->buffer = NULL;
97 		device->length = 0;
98 		device->pos = 0;
99 	}
100 }
101 
102 void
mbfl_memory_device_reset(mbfl_memory_device * device)103 mbfl_memory_device_reset(mbfl_memory_device *device)
104 {
105 	if (device) {
106 		device->pos = 0;
107 	}
108 }
109 
110 void
mbfl_memory_device_unput(mbfl_memory_device * device)111 mbfl_memory_device_unput(mbfl_memory_device *device)
112 {
113 	if (device->pos > 0) {
114 		device->pos--;
115 	}
116 }
117 
118 mbfl_string *
mbfl_memory_device_result(mbfl_memory_device * device,mbfl_string * result)119 mbfl_memory_device_result(mbfl_memory_device *device, mbfl_string *result)
120 {
121 	if (device && result) {
122 		result->len = device->pos;
123 		mbfl_memory_device_output('\0', device);
124 		result->val = device->buffer;
125 		device->buffer = NULL;
126 		device->length = 0;
127 		device->pos= 0;
128 		if (result->val == NULL) {
129 			result->len = 0;
130 			result = NULL;
131 		}
132 	} else {
133 		result = NULL;
134 	}
135 
136 	return result;
137 }
138 
139 int
mbfl_memory_device_output(int c,void * data)140 mbfl_memory_device_output(int c, void *data)
141 {
142 	mbfl_memory_device *device = (mbfl_memory_device *)data;
143 
144 	if (device->pos >= device->length) {
145 		/* reallocate buffer */
146 		size_t newlen;
147 		unsigned char *tmp;
148 
149 		if (device->length > SIZE_MAX - device->allocsz) {
150 			/* overflow */
151 			return -1;
152 		}
153 
154 		newlen = device->length + device->allocsz;
155 		tmp = (unsigned char *)mbfl_realloc((void *)device->buffer, newlen);
156 		if (tmp == NULL) {
157 			return -1;
158 		}
159 		device->length = newlen;
160 		device->buffer = tmp;
161 	}
162 
163 	device->buffer[device->pos++] = (unsigned char)c;
164 	return c;
165 }
166 
167 int
mbfl_memory_device_output2(int c,void * data)168 mbfl_memory_device_output2(int c, void *data)
169 {
170 	mbfl_memory_device *device = (mbfl_memory_device *)data;
171 
172 	if (2 > device->length - device->pos) {
173 		/* reallocate buffer */
174 		size_t newlen;
175 		unsigned char *tmp;
176 
177 		if (device->length > SIZE_MAX - device->allocsz) {
178 			/* overflow */
179 			return -1;
180 		}
181 
182 		newlen = device->length + device->allocsz;
183 		tmp = (unsigned char *)mbfl_realloc((void *)device->buffer, newlen);
184 		if (tmp == NULL) {
185 			return -1;
186 		}
187 		device->length = newlen;
188 		device->buffer = tmp;
189 	}
190 
191 	device->buffer[device->pos++] = (unsigned char)((c >> 8) & 0xff);
192 	device->buffer[device->pos++] = (unsigned char)(c & 0xff);
193 
194 	return c;
195 }
196 
197 int
mbfl_memory_device_output4(int c,void * data)198 mbfl_memory_device_output4(int c, void* data)
199 {
200 	mbfl_memory_device *device = (mbfl_memory_device *)data;
201 
202 	if (4 > device->length - device->pos) {
203 		/* reallocate buffer */
204 		size_t newlen;
205 		unsigned char *tmp;
206 
207 		if (device->length > SIZE_MAX - device->allocsz) {
208 			/* overflow */
209 			return -1;
210 		}
211 
212 		newlen = device->length + device->allocsz;
213 		tmp = (unsigned char *)mbfl_realloc((void *)device->buffer, newlen);
214 		if (tmp == NULL) {
215 			return -1;
216 		}
217 		device->length = newlen;
218 		device->buffer = tmp;
219 	}
220 
221 	device->buffer[device->pos++] = (unsigned char)((c >> 24) & 0xff);
222 	device->buffer[device->pos++] = (unsigned char)((c >> 16) & 0xff);
223 	device->buffer[device->pos++] = (unsigned char)((c >> 8) & 0xff);
224 	device->buffer[device->pos++] = (unsigned char)(c & 0xff);
225 
226 	return c;
227 }
228 
229 int
mbfl_memory_device_strcat(mbfl_memory_device * device,const char * psrc)230 mbfl_memory_device_strcat(mbfl_memory_device *device, const char *psrc)
231 {
232 	return mbfl_memory_device_strncat(device, psrc, strlen(psrc));
233 }
234 
235 int
mbfl_memory_device_strncat(mbfl_memory_device * device,const char * psrc,size_t len)236 mbfl_memory_device_strncat(mbfl_memory_device *device, const char *psrc, size_t len)
237 {
238 	unsigned char *w;
239 
240 	if (len > device->length - device->pos) {
241 		/* reallocate buffer */
242 		size_t newlen;
243 		unsigned char *tmp;
244 
245 		if (len > SIZE_MAX - MBFL_MEMORY_DEVICE_ALLOC_SIZE
246 				|| device->length > SIZE_MAX - (len + MBFL_MEMORY_DEVICE_ALLOC_SIZE)) {
247 			/* overflow */
248 			return -1;
249 		}
250 
251 		newlen = device->length + len + MBFL_MEMORY_DEVICE_ALLOC_SIZE;
252 		tmp = (unsigned char *)mbfl_realloc((void *)device->buffer, newlen);
253 		if (tmp == NULL) {
254 			return -1;
255 		}
256 
257 		device->length = newlen;
258 		device->buffer = tmp;
259 	}
260 
261 	w = &device->buffer[device->pos];
262 	memcpy(w, psrc, len);
263 	device->pos += len;
264 
265 	return 0;
266 }
267 
268 int
mbfl_memory_device_devcat(mbfl_memory_device * dest,mbfl_memory_device * src)269 mbfl_memory_device_devcat(mbfl_memory_device *dest, mbfl_memory_device *src)
270 {
271 	return mbfl_memory_device_strncat(dest, (const char *) src->buffer, src->pos);
272 }
273 
274 void
mbfl_wchar_device_init(mbfl_wchar_device * device)275 mbfl_wchar_device_init(mbfl_wchar_device *device)
276 {
277 	if (device) {
278 		device->buffer = NULL;
279 		device->length = 0;
280 		device->pos= 0;
281 		device->allocsz = MBFL_MEMORY_DEVICE_ALLOC_SIZE;
282 	}
283 }
284 
285 void
mbfl_wchar_device_clear(mbfl_wchar_device * device)286 mbfl_wchar_device_clear(mbfl_wchar_device *device)
287 {
288 	if (device) {
289 		if (device->buffer) {
290 			mbfl_free(device->buffer);
291 		}
292 		device->buffer = NULL;
293 		device->length = 0;
294 		device->pos = 0;
295 	}
296 }
297 
298 int
mbfl_wchar_device_output(int c,void * data)299 mbfl_wchar_device_output(int c, void *data)
300 {
301 	mbfl_wchar_device *device = (mbfl_wchar_device *)data;
302 
303 	if (device->pos >= device->length) {
304 		/* reallocate buffer */
305 		size_t newlen;
306 		unsigned int *tmp;
307 
308 		if (device->length > SIZE_MAX - device->allocsz) {
309 			/* overflow */
310 			return -1;
311 		}
312 
313 		newlen = device->length + device->allocsz;
314 		if (newlen > SIZE_MAX / sizeof(int)) {
315 			/* overflow */
316 			return -1;
317 		}
318 
319 		tmp = (unsigned int *)mbfl_realloc((void *)device->buffer, newlen*sizeof(int));
320 		if (tmp == NULL) {
321 			return -1;
322 		}
323 		device->length = newlen;
324 		device->buffer = tmp;
325 	}
326 
327 	device->buffer[device->pos++] = c;
328 
329 	return c;
330 }
331