1 /*
2 * charset=UTF-8
3 */
4
5 /*
6 * "streamable kanji code filter and converter"
7 *
8 * Copyright (c) 1998,1999,2000,2001 HappySize, Inc. All rights reserved.
9 *
10 * This software is released under the GNU Lesser General Public License.
11 * (Version 2.1, February 1999)
12 * Please read the following detail of the licence (in japanese).
13 *
14 * ◆使用許諾条件◆
15 *
16 * このソフトウェアは株式会社ハッピーサイズによって開発されました。株式会社ハッ
17 * ピーサイズは、著作権法および万国著作権条約の定めにより、このソフトウェアに関
18 * するすべての権利を留保する権利を持ち、ここに行使します。株式会社ハッピーサイ
19 * ズは以下に明記した条件に従って、このソフトウェアを使用する排他的ではない権利
20 * をお客様に許諾します。何人たりとも、以下の条件に反してこのソフトウェアを使用
21 * することはできません。
22 *
23 * このソフトウェアを「GNU Lesser General Public License (Version 2.1, February
24 * 1999)」に示された条件で使用することを、全ての方に許諾します。「GNU Lesser
25 * General Public License」を満たさない使用には、株式会社ハッピーサイズから書面
26 * による許諾を得る必要があります。
27 *
28 * 「GNU Lesser General Public License」の全文は以下のウェブページから取得でき
29 * ます。「GNU Lesser General Public License」とは、これまでLibrary General
30 * Public Licenseと呼ばれていたものです。
31 * http://www.gnu.org/ --- GNUウェブサイト
32 * http://www.gnu.org/copyleft/lesser.html --- ライセンス文面
33 * このライセンスの内容がわからない方、守れない方には使用を許諾しません。
34 *
35 * しかしながら、当社とGNUプロジェクトとの特定の関係を示唆または主張するもので
36 * はありません。
37 *
38 * ◆保証内容◆
39 *
40 * このソフトウェアは、期待された動作・機能・性能を持つことを目標として設計され
41 * 開発されていますが、これを保証するものではありません。このソフトウェアは「こ
42 * のまま」の状態で提供されており、たとえばこのソフトウェアの有用性ないし特定の
43 * 目的に合致することといった、何らかの保証内容が、明示されたり暗黙に示されてい
44 * る場合であっても、その保証は無効です。このソフトウェアを使用した結果ないし使
45 * 用しなかった結果によって、直接あるいは間接に受けた身体的な傷害、財産上の損害
46 * 、データの損失あるいはその他の全ての損害については、その損害の可能性が使用者
47 * 、当社あるいは第三者によって警告されていた場合であっても、当社はその損害の賠
48 * 償および補填を行いません。この規定は他の全ての、書面上または書面に無い保証・
49 * 契約・規定に優先します。
50 *
51 * ◆著作権者の連絡先および使用条件についての問い合わせ先◆
52 *
53 * 〒102-0073
54 * 東京都千代田区九段北1-13-5日本地所第一ビル4F
55 * 株式会社ハッピーサイズ
56 * Phone: 03-3512-3655, Fax: 03-3512-3656
57 * Email: sales@happysize.co.jp
58 * Web: http://happysize.com/
59 *
60 * ◆著者◆
61 *
62 * 金本 茂 <sgk@happysize.co.jp>
63 *
64 * ◆履歴◆
65 *
66 * 1998/11/10 sgk implementation in C++
67 * 1999/4/25 sgk Cで書きなおし。
68 * 1999/4/26 sgk 入力フィルタを実装。漢字コードを推定しながらフィルタを追加。
69 * 1999/6/?? Unicodeサポート。
70 * 1999/6/22 sgk ライセンスをLGPLに変更。
71 *
72 */
73
74 /*
75 * Unicode support
76 *
77 * Portions copyright (c) 1999,2000,2001 by the PHP3 internationalization team.
78 * All rights reserved.
79 *
80 */
81
82 #include <stddef.h>
83 #include <string.h>
84
85 #include "mbfilter.h"
86 #include "mbfl_filter_output.h"
87 #include "mbfilter_8bit.h"
88 #include "mbfilter_wchar.h"
89 #include "mbstring.h"
90 #include "php_unicode.h"
91 #include "filters/mbfilter_base64.h"
92 #include "filters/mbfilter_qprint.h"
93 #include "filters/mbfilter_singlebyte.h"
94 #include "filters/mbfilter_utf8.h"
95
96 /*
97 * strcut
98 */
99 mbfl_string *
mbfl_strcut(mbfl_string * string,mbfl_string * result,size_t from,size_t length)100 mbfl_strcut(
101 mbfl_string *string,
102 mbfl_string *result,
103 size_t from,
104 size_t length)
105 {
106 const mbfl_encoding *encoding = string->encoding;
107 mbfl_memory_device device;
108
109 if (from >= string->len) {
110 from = string->len;
111 }
112
113 mbfl_string_init(result);
114 result->encoding = string->encoding;
115
116 if ((encoding->flag & (MBFL_ENCTYPE_SBCS | MBFL_ENCTYPE_WCS2 | MBFL_ENCTYPE_WCS4)) || encoding->mblen_table != NULL) {
117 const unsigned char *start = NULL;
118 const unsigned char *end = NULL;
119 unsigned char *w;
120 size_t sz;
121
122 if (encoding->flag & MBFL_ENCTYPE_WCS2) {
123 from &= -2;
124
125 if (length >= string->len - from) {
126 length = string->len - from;
127 }
128
129 start = string->val + from;
130 end = start + (length & -2);
131 } else if (encoding->flag & MBFL_ENCTYPE_WCS4) {
132 from &= -4;
133
134 if (length >= string->len - from) {
135 length = string->len - from;
136 }
137
138 start = string->val + from;
139 end = start + (length & -4);
140 } else if ((encoding->flag & MBFL_ENCTYPE_SBCS)) {
141 if (length >= string->len - from) {
142 length = string->len - from;
143 }
144
145 start = string->val + from;
146 end = start + length;
147 } else if (encoding->mblen_table != NULL) {
148 const unsigned char *mbtab = encoding->mblen_table;
149 const unsigned char *p, *q;
150 int m;
151
152 /* search start position */
153 for (m = 0, p = string->val, q = p + from;
154 p < q; p += (m = mbtab[*p]));
155
156 if (p > q) {
157 p -= m;
158 }
159
160 start = p;
161
162 /* search end position */
163 if (length >= string->len - (start - string->val)) {
164 end = string->val + string->len;
165 } else {
166 for (q = p + length; p < q; p += (m = mbtab[*p]));
167
168 if (p > q) {
169 p -= m;
170 }
171 end = p;
172 }
173 } else {
174 /* never reached */
175 return NULL;
176 }
177
178 /* allocate memory and copy string */
179 sz = end - start;
180 w = ecalloc(sz + 8, sizeof(unsigned char));
181
182 memcpy(w, start, sz);
183 w[sz] = '\0';
184 w[sz + 1] = '\0';
185 w[sz + 2] = '\0';
186 w[sz + 3] = '\0';
187
188 result->val = w;
189 result->len = sz;
190 } else {
191 mbfl_convert_filter *encoder = NULL;
192 mbfl_convert_filter *decoder = NULL;
193 const unsigned char *p, *q, *r;
194 struct {
195 mbfl_convert_filter encoder;
196 mbfl_convert_filter decoder;
197 const unsigned char *p;
198 size_t pos;
199 } bk, _bk;
200
201 /* output code filter */
202 if (!(decoder = mbfl_convert_filter_new(
203 &mbfl_encoding_wchar,
204 string->encoding,
205 mbfl_memory_device_output, 0, &device))) {
206 return NULL;
207 }
208
209 /* wchar filter */
210 if (!(encoder = mbfl_convert_filter_new(
211 string->encoding,
212 &mbfl_encoding_wchar,
213 mbfl_filter_output_null,
214 NULL, NULL))) {
215 mbfl_convert_filter_delete(decoder);
216 return NULL;
217 }
218
219 mbfl_memory_device_init(&device, length + 8, 0);
220
221 p = string->val;
222
223 /* search start position */
224 for (q = string->val + from; p < q; p++) {
225 (*encoder->filter_function)(*p, encoder);
226 }
227
228 /* switch the drain direction */
229 encoder->output_function = (output_function_t)decoder->filter_function;
230 encoder->flush_function = (flush_function_t)decoder->filter_flush;
231 encoder->data = decoder;
232
233 q = string->val + string->len;
234
235 /* save the encoder, decoder state and the pointer */
236 mbfl_convert_filter_copy(decoder, &_bk.decoder);
237 mbfl_convert_filter_copy(encoder, &_bk.encoder);
238 _bk.p = p;
239 _bk.pos = device.pos;
240
241 if (length > q - p) {
242 length = q - p;
243 }
244
245 if (length >= 20) {
246 /* output a little shorter than "length" */
247 /* XXX: the constant "20" was determined purely on the heuristics. */
248 for (r = p + length - 20; p < r; p++) {
249 (*encoder->filter_function)(*p, encoder);
250 }
251
252 /* if the offset of the resulting string exceeds the length,
253 * then restore the state */
254 if (device.pos > length) {
255 p = _bk.p;
256 device.pos = _bk.pos;
257 if (decoder->filter_dtor)
258 decoder->filter_dtor(decoder);
259 if (encoder->filter_dtor)
260 encoder->filter_dtor(encoder);
261 mbfl_convert_filter_copy(&_bk.decoder, decoder);
262 mbfl_convert_filter_copy(&_bk.encoder, encoder);
263 bk = _bk;
264 } else {
265 /* save the encoder, decoder state and the pointer */
266 mbfl_convert_filter_copy(decoder, &bk.decoder);
267 mbfl_convert_filter_copy(encoder, &bk.encoder);
268 bk.p = p;
269 bk.pos = device.pos;
270
271 /* flush the stream */
272 (*encoder->filter_flush)(encoder);
273
274 /* if the offset of the resulting string exceeds the length,
275 * then restore the state */
276 if (device.pos > length) {
277 if (bk.decoder.filter_dtor)
278 bk.decoder.filter_dtor(&bk.decoder);
279 if (bk.encoder.filter_dtor)
280 bk.encoder.filter_dtor(&bk.encoder);
281
282 p = _bk.p;
283 device.pos = _bk.pos;
284 if (decoder->filter_dtor)
285 decoder->filter_dtor(decoder);
286 if (encoder->filter_dtor)
287 encoder->filter_dtor(encoder);
288 mbfl_convert_filter_copy(&_bk.decoder, decoder);
289 mbfl_convert_filter_copy(&_bk.encoder, encoder);
290 bk = _bk;
291 } else {
292 if (_bk.decoder.filter_dtor)
293 _bk.decoder.filter_dtor(&_bk.decoder);
294 if (_bk.encoder.filter_dtor)
295 _bk.encoder.filter_dtor(&_bk.encoder);
296
297 p = bk.p;
298 device.pos = bk.pos;
299 if (decoder->filter_dtor)
300 decoder->filter_dtor(decoder);
301 if (encoder->filter_dtor)
302 encoder->filter_dtor(encoder);
303 mbfl_convert_filter_copy(&bk.decoder, decoder);
304 mbfl_convert_filter_copy(&bk.encoder, encoder);
305 }
306 }
307 } else {
308 bk = _bk;
309 }
310
311 /* detect end position */
312 while (p < q) {
313 (*encoder->filter_function)(*p, encoder);
314
315 if (device.pos > length) {
316 /* restore filter */
317 p = bk.p;
318 device.pos = bk.pos;
319 if (decoder->filter_dtor)
320 decoder->filter_dtor(decoder);
321 if (encoder->filter_dtor)
322 encoder->filter_dtor(encoder);
323 mbfl_convert_filter_copy(&bk.decoder, decoder);
324 mbfl_convert_filter_copy(&bk.encoder, encoder);
325 break;
326 }
327
328 p++;
329
330 /* backup current state */
331 mbfl_convert_filter_copy(decoder, &_bk.decoder);
332 mbfl_convert_filter_copy(encoder, &_bk.encoder);
333 _bk.pos = device.pos;
334 _bk.p = p;
335
336 (*encoder->filter_flush)(encoder);
337
338 if (device.pos > length) {
339 if (_bk.decoder.filter_dtor)
340 _bk.decoder.filter_dtor(&_bk.decoder);
341 if (_bk.encoder.filter_dtor)
342 _bk.encoder.filter_dtor(&_bk.encoder);
343
344 /* restore filter */
345 p = bk.p;
346 device.pos = bk.pos;
347 if (decoder->filter_dtor)
348 decoder->filter_dtor(decoder);
349 if (encoder->filter_dtor)
350 encoder->filter_dtor(encoder);
351 mbfl_convert_filter_copy(&bk.decoder, decoder);
352 mbfl_convert_filter_copy(&bk.encoder, encoder);
353 break;
354 }
355
356 if (bk.decoder.filter_dtor)
357 bk.decoder.filter_dtor(&bk.decoder);
358 if (bk.encoder.filter_dtor)
359 bk.encoder.filter_dtor(&bk.encoder);
360
361 p = _bk.p;
362 device.pos = _bk.pos;
363 if (decoder->filter_dtor)
364 decoder->filter_dtor(decoder);
365 if (encoder->filter_dtor)
366 encoder->filter_dtor(encoder);
367 mbfl_convert_filter_copy(&_bk.decoder, decoder);
368 mbfl_convert_filter_copy(&_bk.encoder, encoder);
369
370 bk = _bk;
371 }
372
373 decoder->illegal_mode = MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE;
374 (*encoder->filter_flush)(encoder);
375
376 if (bk.decoder.filter_dtor)
377 bk.decoder.filter_dtor(&bk.decoder);
378 if (bk.encoder.filter_dtor)
379 bk.encoder.filter_dtor(&bk.encoder);
380
381 result = mbfl_memory_device_result(&device, result);
382
383 mbfl_convert_filter_delete(encoder);
384 mbfl_convert_filter_delete(decoder);
385 }
386
387 return result;
388 }
389