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 #include <stddef.h>
32 #include <string.h>
33 
34 #include "zend.h"
35 #include "mbfl_memory_device.h"
36 
37 /*
38  * memory device output functions
39  */
40 void
mbfl_memory_device_init(mbfl_memory_device * device,size_t initsz,size_t allocsz)41 mbfl_memory_device_init(mbfl_memory_device *device, size_t initsz, size_t allocsz)
42 {
43 	if (device) {
44 		device->length = 0;
45 		device->buffer = NULL;
46 		if (initsz > 0) {
47 			device->buffer = emalloc(initsz);
48 			device->length = initsz;
49 		}
50 		device->pos = 0;
51 		if (allocsz > MBFL_MEMORY_DEVICE_ALLOC_SIZE) {
52 			device->allocsz = allocsz;
53 		} else {
54 			device->allocsz = MBFL_MEMORY_DEVICE_ALLOC_SIZE;
55 		}
56 	}
57 }
58 
59 void
mbfl_memory_device_realloc(mbfl_memory_device * device,size_t initsz,size_t allocsz)60 mbfl_memory_device_realloc(mbfl_memory_device *device, size_t initsz, size_t allocsz)
61 {
62 	if (device) {
63 		if (initsz > device->length) {
64 			device->buffer = erealloc(device->buffer, initsz);
65 			device->length = initsz;
66 		}
67 		if (allocsz > MBFL_MEMORY_DEVICE_ALLOC_SIZE) {
68 			device->allocsz = allocsz;
69 		} else {
70 			device->allocsz = MBFL_MEMORY_DEVICE_ALLOC_SIZE;
71 		}
72 	}
73 }
74 
75 void
mbfl_memory_device_clear(mbfl_memory_device * device)76 mbfl_memory_device_clear(mbfl_memory_device *device)
77 {
78 	if (device) {
79 		if (device->buffer) {
80 			efree(device->buffer);
81 		}
82 		device->buffer = NULL;
83 		device->length = 0;
84 		device->pos = 0;
85 	}
86 }
87 
88 void
mbfl_memory_device_reset(mbfl_memory_device * device)89 mbfl_memory_device_reset(mbfl_memory_device *device)
90 {
91 	if (device) {
92 		device->pos = 0;
93 	}
94 }
95 
96 void
mbfl_memory_device_unput(mbfl_memory_device * device)97 mbfl_memory_device_unput(mbfl_memory_device *device)
98 {
99 	if (device->pos > 0) {
100 		device->pos--;
101 	}
102 }
103 
104 mbfl_string *
mbfl_memory_device_result(mbfl_memory_device * device,mbfl_string * result)105 mbfl_memory_device_result(mbfl_memory_device *device, mbfl_string *result)
106 {
107 	if (device && result) {
108 		result->len = device->pos;
109 		mbfl_memory_device_output('\0', device);
110 		result->val = device->buffer;
111 		device->buffer = NULL;
112 		device->length = 0;
113 		device->pos= 0;
114 		if (result->val == NULL) {
115 			result->len = 0;
116 			result = NULL;
117 		}
118 	} else {
119 		result = NULL;
120 	}
121 
122 	return result;
123 }
124 
125 int
mbfl_memory_device_output(int c,void * data)126 mbfl_memory_device_output(int c, void *data)
127 {
128 	mbfl_memory_device *device = (mbfl_memory_device *)data;
129 
130 	if (device->pos >= device->length) {
131 		/* reallocate buffer */
132 		size_t newlen;
133 
134 		if (device->length > SIZE_MAX - device->allocsz) {
135 			/* overflow */
136 			return -1;
137 		}
138 
139 		newlen = device->length + device->allocsz;
140 		device->buffer = erealloc(device->buffer, newlen);
141 		device->length = newlen;
142 	}
143 
144 	device->buffer[device->pos++] = (unsigned char)c;
145 	return c;
146 }
147 
148 int
mbfl_memory_device_strcat(mbfl_memory_device * device,const char * psrc)149 mbfl_memory_device_strcat(mbfl_memory_device *device, const char *psrc)
150 {
151 	return mbfl_memory_device_strncat(device, psrc, strlen(psrc));
152 }
153 
154 int
mbfl_memory_device_strncat(mbfl_memory_device * device,const char * psrc,size_t len)155 mbfl_memory_device_strncat(mbfl_memory_device *device, const char *psrc, size_t len)
156 {
157 	unsigned char *w;
158 
159 	if (len > device->length - device->pos) {
160 		/* reallocate buffer */
161 		size_t newlen;
162 
163 		if (len > SIZE_MAX - MBFL_MEMORY_DEVICE_ALLOC_SIZE
164 				|| device->length > SIZE_MAX - (len + MBFL_MEMORY_DEVICE_ALLOC_SIZE)) {
165 			/* overflow */
166 			return -1;
167 		}
168 
169 		newlen = device->length + len + MBFL_MEMORY_DEVICE_ALLOC_SIZE;
170 		device->buffer = erealloc(device->buffer, newlen);
171 		device->length = newlen;
172 	}
173 
174 	w = &device->buffer[device->pos];
175 	memcpy(w, psrc, len);
176 	device->pos += len;
177 
178 	return 0;
179 }
180 
181 int
mbfl_memory_device_devcat(mbfl_memory_device * dest,mbfl_memory_device * src)182 mbfl_memory_device_devcat(mbfl_memory_device *dest, mbfl_memory_device *src)
183 {
184 	return mbfl_memory_device_strncat(dest, (const char *) src->buffer, src->pos);
185 }
186 
187 void
mbfl_wchar_device_init(mbfl_wchar_device * device)188 mbfl_wchar_device_init(mbfl_wchar_device *device)
189 {
190 	if (device) {
191 		device->buffer = NULL;
192 		device->length = 0;
193 		device->pos= 0;
194 		device->allocsz = MBFL_MEMORY_DEVICE_ALLOC_SIZE;
195 	}
196 }
197 
198 void
mbfl_wchar_device_clear(mbfl_wchar_device * device)199 mbfl_wchar_device_clear(mbfl_wchar_device *device)
200 {
201 	if (device) {
202 		if (device->buffer) {
203 			efree(device->buffer);
204 		}
205 		device->buffer = NULL;
206 		device->length = 0;
207 		device->pos = 0;
208 	}
209 }
210 
211 int
mbfl_wchar_device_output(int c,void * data)212 mbfl_wchar_device_output(int c, void *data)
213 {
214 	mbfl_wchar_device *device = (mbfl_wchar_device *)data;
215 
216 	if (device->pos >= device->length) {
217 		/* reallocate buffer */
218 		size_t newlen;
219 
220 		if (device->length > SIZE_MAX - device->allocsz) {
221 			/* overflow */
222 			return -1;
223 		}
224 
225 		newlen = device->length + device->allocsz;
226 		if (newlen > SIZE_MAX / sizeof(int)) {
227 			/* overflow */
228 			return -1;
229 		}
230 
231 		device->buffer = erealloc(device->buffer, newlen*sizeof(int));
232 		device->length = newlen;
233 	}
234 
235 	device->buffer[device->pos++] = c;
236 
237 	return c;
238 }
239