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  */
mbfl_memory_device_init(mbfl_memory_device * device,size_t initsz,size_t allocsz)40 void mbfl_memory_device_init(mbfl_memory_device *device, size_t initsz, size_t allocsz)
41 {
42 	device->buffer = (initsz > 0) ? emalloc(initsz) : NULL;
43 	device->length = initsz;
44 	device->pos = 0;
45 	device->allocsz = MAX(allocsz, MBFL_MEMORY_DEVICE_ALLOC_SIZE);
46 }
47 
mbfl_memory_device_realloc(mbfl_memory_device * device,size_t initsz,size_t allocsz)48 void mbfl_memory_device_realloc(mbfl_memory_device *device, size_t initsz, size_t allocsz)
49 {
50 	if (initsz > device->length) {
51 		device->buffer = erealloc(device->buffer, initsz);
52 		device->length = initsz;
53 	}
54 	device->allocsz = MAX(allocsz, MBFL_MEMORY_DEVICE_ALLOC_SIZE);
55 }
56 
mbfl_memory_device_clear(mbfl_memory_device * device)57 void mbfl_memory_device_clear(mbfl_memory_device *device)
58 {
59 	if (device->buffer) {
60 		efree(device->buffer);
61 	}
62 	device->buffer = NULL;
63 	device->length = device->pos = 0;
64 }
65 
mbfl_memory_device_reset(mbfl_memory_device * device)66 void mbfl_memory_device_reset(mbfl_memory_device *device)
67 {
68 	device->pos = 0;
69 }
70 
mbfl_memory_device_unput(mbfl_memory_device * device)71 void mbfl_memory_device_unput(mbfl_memory_device *device)
72 {
73 	if (device->pos > 0) {
74 		device->pos--;
75 	}
76 }
77 
mbfl_memory_device_result(mbfl_memory_device * device,mbfl_string * result)78 mbfl_string* mbfl_memory_device_result(mbfl_memory_device *device, mbfl_string *result)
79 {
80 	result->len = device->pos;
81 	mbfl_memory_device_output('\0', device);
82 	result->val = device->buffer;
83 	device->buffer = NULL;
84 	device->length = device->pos = 0;
85 	return result;
86 }
87 
mbfl_memory_device_output(int c,void * data)88 int mbfl_memory_device_output(int c, void *data)
89 {
90 	mbfl_memory_device *device = (mbfl_memory_device *)data;
91 
92 	if (device->pos >= device->length) {
93 		/* reallocate buffer */
94 
95 		if (device->length > SIZE_MAX - device->allocsz) {
96 			/* overflow */
97 			return -1;
98 		}
99 
100 		size_t newlen = device->length + device->allocsz;
101 		device->buffer = erealloc(device->buffer, newlen);
102 		device->length = newlen;
103 	}
104 
105 	device->buffer[device->pos++] = (unsigned char)c;
106 	return 0;
107 }
108 
mbfl_memory_device_strcat(mbfl_memory_device * device,const char * psrc)109 int mbfl_memory_device_strcat(mbfl_memory_device *device, const char *psrc)
110 {
111 	return mbfl_memory_device_strncat(device, psrc, strlen(psrc));
112 }
113 
mbfl_memory_device_strncat(mbfl_memory_device * device,const char * psrc,size_t len)114 int mbfl_memory_device_strncat(mbfl_memory_device *device, const char *psrc, size_t len)
115 {
116 	if (len > device->length - device->pos) {
117 		/* reallocate buffer */
118 
119 		if (len > SIZE_MAX - MBFL_MEMORY_DEVICE_ALLOC_SIZE
120 				|| device->length > SIZE_MAX - (len + MBFL_MEMORY_DEVICE_ALLOC_SIZE)) {
121 			/* overflow */
122 			return -1;
123 		}
124 
125 		size_t newlen = device->length + len + MBFL_MEMORY_DEVICE_ALLOC_SIZE;
126 		device->buffer = erealloc(device->buffer, newlen);
127 		device->length = newlen;
128 	}
129 
130 	unsigned char *w = &device->buffer[device->pos];
131 	memcpy(w, psrc, len);
132 	device->pos += len;
133 
134 	return 0;
135 }
136 
mbfl_memory_device_devcat(mbfl_memory_device * dest,mbfl_memory_device * src)137 int mbfl_memory_device_devcat(mbfl_memory_device *dest, mbfl_memory_device *src)
138 {
139 	return mbfl_memory_device_strncat(dest, (const char*)src->buffer, src->pos);
140 }
141 
mbfl_wchar_device_init(mbfl_wchar_device * device)142 void mbfl_wchar_device_init(mbfl_wchar_device *device)
143 {
144 	device->buffer = NULL;
145 	device->length = 0;
146 	device->pos = 0;
147 	device->allocsz = MBFL_MEMORY_DEVICE_ALLOC_SIZE;
148 }
149 
mbfl_wchar_device_clear(mbfl_wchar_device * device)150 void mbfl_wchar_device_clear(mbfl_wchar_device *device)
151 {
152 	if (device->buffer) {
153 		efree(device->buffer);
154 	}
155 	device->buffer = NULL;
156 	device->length = device->pos = 0;
157 }
158 
mbfl_wchar_device_output(int c,void * data)159 int mbfl_wchar_device_output(int c, void *data)
160 {
161 	mbfl_wchar_device *device = (mbfl_wchar_device *)data;
162 
163 	if (device->pos >= device->length) {
164 		/* reallocate buffer */
165 		size_t newlen;
166 
167 		if (device->length > SIZE_MAX - device->allocsz) {
168 			/* overflow */
169 			return -1;
170 		}
171 
172 		newlen = device->length + device->allocsz;
173 		if (newlen > SIZE_MAX / sizeof(int)) {
174 			/* overflow */
175 			return -1;
176 		}
177 
178 		device->buffer = erealloc(device->buffer, newlen * sizeof(int));
179 		device->length = newlen;
180 	}
181 
182 	device->buffer[device->pos++] = c;
183 	return 0;
184 }
185