OSDN Git Service

f133295e477a48526f05d18cd43048ec5cf2f281
[bbk/bchanf.git] / src / tad / tadfragment.c
1 /*
2  * tadfragment.c
3  *
4  * Copyright (c) 2013 project bchan
5  *
6  * This software is provided 'as-is', without any express or implied
7  * warranty. In no event will the authors be held liable for any damages
8  * arising from the use of this software.
9  *
10  * Permission is granted to anyone to use this software for any purpose,
11  * including commercial applications, and to alter it and redistribute it
12  * freely, subject to the following restrictions:
13  *
14  * 1. The origin of this software must not be misrepresented; you must not
15  *    claim that you wrote the original software. If you use this software
16  *    in a product, an acknowledgment in the product documentation would be
17  *    appreciated but is not required.
18  *
19  * 2. Altered source versions must be plainly marked as such, and must not be
20  *    misrepresented as being the original software.
21  *
22  * 3. This notice may not be removed or altered from any source
23  *    distribution.
24  *
25  */
26
27 #include "tadfragment.h"
28
29 #include        <basic.h>
30 #include        <bstdio.h>
31
32 #include    <coll/bytearray.h>
33 #include    <coll/wordarray.h>
34 #include    "tadlexer_le.h"
35
36 #ifdef BCHAN_CONFIG_DEBUG
37 # define DP(arg) printf arg
38 # define DP_ER(msg, err) printf("%s (%d/%x)\n", msg, err>>16, err)
39 #else
40 # define DP(arg) /**/
41 # define DP_ER(msg, err) /**/
42 #endif
43
44 #if 0
45 # define DP_STATE(state) printf("%s\n", state)
46 #else
47 # define DP_STATE(state) /**/
48 #endif
49
50 struct tadfragment_pos_iterator_t_ {
51         enum {
52                 TADFRAGMENT_POS_ITERATOR_STATE_BEFORE_SEGSTART,
53                 TADFRAGMENT_POS_ITERATOR_STATE_READING_TLANG,
54                 TADFRAGMENT_POS_ITERATOR_STATE_READING,
55                 TADFRAGMENT_POS_ITERATOR_STATE_COMPLETED,
56                 TADFRAGMENT_POS_ITERATOR_STATE_ERROR,
57         } state;
58         UB *data;
59         W len;
60         W pos;
61         tadlexer_le_t lexer;
62         struct {
63                 tadlexer_le_result *result;
64                 W len;
65                 W pos;
66         } lexer_result_handling;
67 };
68 typedef struct tadfragment_pos_iterator_t_ tadfragment_pos_iterator_t;
69
70 struct tadfragment_pos_iterator_result_ {
71         enum {
72                 TADFRAGMENT_POS_ITERATOR_RESULT_TYPE_SEGMENT,
73                 TADFRAGMENT_POS_ITERATOR_RESULT_TYPE_ERROR,
74         } type;
75         W index;
76 };
77 typedef struct tadfragment_pos_iterator_result_ tadfragment_pos_iterator_result;
78
79 LOCAL W tadfragment_pos_iterator_input(tadfragment_pos_iterator_t *iterator, tadlexer_le_result *result, Bool *segstart)
80 {
81         Bool fixed;
82         W err = 0;
83
84         *segstart = False;
85
86         switch (iterator->state) {
87         case TADFRAGMENT_POS_ITERATOR_STATE_BEFORE_SEGSTART:
88                 DP_STATE("BEFORE_SEGSTART");
89                 iterator->state = TADFRAGMENT_POS_ITERATOR_STATE_READING;
90                 *segstart = True;
91                 break;
92         case TADFRAGMENT_POS_ITERATOR_STATE_READING_TLANG:
93                 DP_STATE("READING_TLANG");
94                 if (result->type == TADLEXER_LE_RESULTTYPE_SEGMENT_END) {
95                         fixed = tadlexer_le_result_is_fixedsegment(result);
96                         if (fixed == False) {
97                                 iterator->state = TADFRAGMENT_POS_ITERATOR_STATE_ERROR;
98                                 err = -1; /* TODO */
99                                 break;
100                         }
101                         if (result->val.ch == 0xFEFE) {
102                                 break;
103                         }
104                         if ((result->val.ch & 0xFF00) != 0xFE00) {
105                                 iterator->state = TADFRAGMENT_POS_ITERATOR_STATE_ERROR;
106                                 err = -1; /* TODO */
107                                 break;
108                         }
109                         iterator->state = TADFRAGMENT_POS_ITERATOR_STATE_BEFORE_SEGSTART;
110                 }
111                 break;
112         case TADFRAGMENT_POS_ITERATOR_STATE_READING:
113                 DP_STATE("READING");
114                 if (result->type != TADLEXER_LE_RESULTTYPE_SEGMENT_END) {
115                         break;
116                 }
117                 fixed = tadlexer_le_result_is_fixedsegment(result);
118                 if ((fixed != False)&&(result->val.ch == 0xFEFE)) {
119                         iterator->state = TADFRAGMENT_POS_ITERATOR_STATE_READING_TLANG;
120                         break;
121                 }
122                 iterator->state = TADFRAGMENT_POS_ITERATOR_STATE_BEFORE_SEGSTART;
123                 break;
124         case TADFRAGMENT_POS_ITERATOR_STATE_COMPLETED:
125                 DP_STATE("COMPLETED");
126                 break;
127         case TADFRAGMENT_POS_ITERATOR_STATE_ERROR:
128                 DP_STATE("ERROR");
129                 err = -1; /* TODO */
130                 break;
131         }
132
133         return err;
134 }
135
136 LOCAL Bool tadfragment_pos_iterator_next(tadfragment_pos_iterator_t *iterator, tadfragment_pos_iterator_result *result)
137 {
138         UB ch;
139         W pos, len, err;
140         Bool segstart;
141         tadlexer_le_result *lexer_result;
142
143         for (; iterator->lexer_result_handling.pos < iterator->lexer_result_handling.len; ) {
144                 pos = iterator->lexer_result_handling.pos++;
145                 lexer_result = iterator->lexer_result_handling.result + pos;
146                 err = tadfragment_pos_iterator_input(iterator, lexer_result, &segstart);
147                 if (err < 0) {
148                         result->type = TADFRAGMENT_POS_ITERATOR_RESULT_TYPE_ERROR;
149                         return False;
150                 }
151                 if (segstart != False) {
152                         result->type = TADFRAGMENT_POS_ITERATOR_RESULT_TYPE_SEGMENT;
153                         result->index = iterator->pos - 1;
154                         return True;
155                 }
156         }
157
158         for (; iterator->pos < iterator->len;) {
159                 ch = iterator->data[iterator->pos++];
160                 tadlexer_le_inputbyte(&iterator->lexer, ch, &lexer_result, &len);
161                 iterator->lexer_result_handling.result = lexer_result;
162                 iterator->lexer_result_handling.len = len;
163                 iterator->lexer_result_handling.pos = 0;
164
165                 for (; iterator->lexer_result_handling.pos < iterator->lexer_result_handling.len; ) {
166                         pos = iterator->lexer_result_handling.pos++;
167                         lexer_result = iterator->lexer_result_handling.result + pos;
168                         err = tadfragment_pos_iterator_input(iterator, lexer_result, &segstart);
169                         if (err < 0) {
170                                 result->type = TADFRAGMENT_POS_ITERATOR_RESULT_TYPE_ERROR;
171                                 return False;
172                         }
173                         if (segstart != False) {
174                                 result->type = TADFRAGMENT_POS_ITERATOR_RESULT_TYPE_SEGMENT;
175                                 result->index = iterator->pos - 1;
176                                 return True;
177                         }
178                 }
179         }
180
181         if (iterator->state == TADFRAGMENT_POS_ITERATOR_STATE_BEFORE_SEGSTART) {
182                 iterator->state = TADFRAGMENT_POS_ITERATOR_STATE_COMPLETED;
183                 result->type = TADFRAGMENT_POS_ITERATOR_RESULT_TYPE_SEGMENT;
184                 result->index = iterator->len;
185         } else {
186                 result->type = TADFRAGMENT_POS_ITERATOR_RESULT_TYPE_ERROR;
187         }
188
189         return False;
190 }
191
192 LOCAL VOID tadfragment_pos_iterator_initialize(tadfragment_pos_iterator_t *iterator, UB *data, W len)
193 {
194         tadlexer_le_initialize(&iterator->lexer);
195         iterator->state = TADFRAGMENT_POS_ITERATOR_STATE_BEFORE_SEGSTART;
196         iterator->data = data;
197         iterator->len = len;
198         iterator->pos = 0;
199         iterator->lexer_result_handling.result = NULL;
200         iterator->lexer_result_handling.len = 0;
201         iterator->lexer_result_handling.pos = 0;
202 }
203
204 LOCAL VOID tadfragment_pos_iterator_finalize(tadfragment_pos_iterator_t *iterator)
205 {
206         tadlexer_le_finalize(&iterator->lexer);
207 }
208
209 LOCAL Bool tadfragment_verifydata(UB *data, W len)
210 {
211         tadfragment_pos_iterator_t iterator;
212         tadfragment_pos_iterator_result result;
213         Bool cont, ret = True;
214
215         tadfragment_pos_iterator_initialize(&iterator, data, len);
216         for (;;) {
217                 cont = tadfragment_pos_iterator_next(&iterator, &result);
218                 if (cont == False) {
219                         break;
220                 }
221                 if (result.type == TADFRAGMENT_POS_ITERATOR_RESULT_TYPE_SEGMENT) {
222                 } else {
223                         ret = False;
224                         break;
225                 }
226         }
227         tadfragment_pos_iterator_finalize(&iterator);
228
229         return True;
230 }
231
232 EXPORT UB* tadfragment_getbuffer(tadfragment_t *fragment)
233 {
234         return bytearray_getbuffer(&fragment->rawdata);
235 }
236
237 EXPORT W tadfragment_getsegmentlength(tadfragment_t *fragment)
238 {
239         return wordarray_getlength(&fragment->pos);
240 }
241
242 EXPORT W tadfragment_getbufferlength(tadfragment_t *fragment)
243 {
244         return bytearray_getlength(&fragment->rawdata);
245 }
246
247 EXPORT W tadfragment_pushback(tadfragment_t *fragment, UB *data, W len)
248 {
249         tadfragment_cursor_t cursor;
250         W num, err;
251
252         tadfragment_cursor_initialize(&cursor, fragment);
253
254         num = tadfragment_getsegmentlength(fragment);
255         tadfragment_cursor_move(&cursor, num);
256
257         err = tadfragment_cursor_insert(&cursor, data, len);
258
259         tadfragment_cursor_finalize(&cursor);
260
261         return err;
262 }
263
264 EXPORT W tadfragment_popback(tadfragment_t *fragment)
265 {
266         W len, val, i, size;
267
268         len = wordarray_getlength(&fragment->pos);
269         if (len == 0) {
270                 return -1; /* TODO */
271         }
272
273         wordarray_getat(&fragment->pos, len-1, &val);
274         size = bytearray_getlength(&fragment->rawdata);
275
276         for (i = 0; i < size - val; i++) {
277                 bytearray_popback(&fragment->rawdata);
278         }
279         wordarray_popback(&fragment->pos);
280
281         return 0;
282 }
283
284 EXPORT W tadfragment_initialize(tadfragment_t *fragment)
285 {
286         W err;
287
288         err = bytearray_initialize(&fragment->rawdata);
289         if (err < 0) {
290                 return err;
291         }
292         err = wordarray_initialize(&fragment->pos);
293         if (err < 0) {
294                 bytearray_finalize(&fragment->rawdata);
295                 return err;
296         }
297
298         return 0;
299 }
300
301 EXPORT VOID tadfragment_finalize(tadfragment_t *fragment)
302 {
303         wordarray_finalize(&fragment->pos);
304         bytearray_finalize(&fragment->rawdata);
305 }
306
307 EXPORT W tadfragment_cursor_move(tadfragment_cursor_t *cursor, W diff)
308 {
309         return wordarray_cursor_move(&cursor->base, diff);
310 }
311
312 EXPORT W tadfragment_cursor_erase(tadfragment_cursor_t *cursor, W len)
313 {
314         bytearray_cursor_t bytecursor;
315         Bool isend;
316         W start_pos, end_pos, diff, val, count, err;
317
318         if (len < 0) {
319                 return -1; /* TODO */
320         }
321
322         isend = tadfragment_cursor_isend(cursor);
323         if (isend != False) {
324                 return -1; /* TODO */
325         }
326
327         wordarray_cursor_getW(&cursor->base, &start_pos);
328         err = tadfragment_cursor_move(cursor, len);
329         if (err < 0) {
330                 diff = bytearray_getlength(&cursor->target->rawdata) - start_pos;
331         } else {
332                 wordarray_cursor_getW(&cursor->base, &end_pos);
333                 tadfragment_cursor_move(cursor, -len);
334
335                 diff = end_pos - start_pos;
336         }
337
338         wordarray_cursor_erase(&cursor->base, len);
339
340         bytearray_cursor_initialize(&bytecursor, &cursor->target->rawdata);
341         bytearray_cursor_move(&bytecursor, start_pos);
342         bytearray_cursor_erase(&bytecursor, diff);
343         bytearray_cursor_finalize(&bytecursor);
344
345         count = 0;
346         for (;;) {
347                 err = wordarray_cursor_getW(&cursor->base, &val);
348                 if (err < 0) {
349                         /* TODO: error or end position */
350                         break;
351                 }
352                 wordarray_cursor_setW(&cursor->base, val - diff);
353                 wordarray_cursor_move(&cursor->base, 1);
354                 count++;
355         }
356         wordarray_cursor_move(&cursor->base, -count);
357
358         return 0;
359 }
360
361 LOCAL W tadfragment_cursor_getnextpos(tadfragment_cursor_t *cursor, W *pos)
362 {
363         W err;
364         Bool isend;
365
366         err = tadfragment_cursor_move(cursor, 1);
367         if (err < 0) {
368                 return err;
369         }
370         isend = tadfragment_cursor_isend(cursor);
371         if (isend != False) {
372                 *pos = bytearray_getlength(&cursor->target->rawdata);
373                 tadfragment_cursor_move(cursor, -1);
374                 return 0;
375         }
376
377         err = wordarray_cursor_getW(&cursor->base, pos);
378         tadfragment_cursor_move(cursor, -1);
379
380         return err;
381 }
382
383 EXPORT W tadfragment_cursor_insert(tadfragment_cursor_t *cursor, UB *data, W len)
384 {
385         bytearray_cursor_t bytecursor;
386         tadfragment_pos_iterator_t iterator;
387         tadfragment_pos_iterator_result result;
388         Bool ok, cont, isend;
389         W offset, val, err, err2;
390
391         if (len < 0) {
392                 return -1; /* TODO */
393         }
394         if (len == 0) {
395                 return 0;
396         }
397
398         ok = tadfragment_verifydata(data, len);
399         if (ok == False) {
400                 return -1; /* TODO */
401         }
402
403         isend = tadfragment_cursor_isend(cursor);
404         if (isend == False) {
405                 err = wordarray_cursor_getW(&cursor->base, &offset);
406                 if (err < 0) {
407                         printf("BBB\n");
408                         return err;
409                 }
410         } else {
411                 offset = bytearray_getlength(&cursor->target->rawdata);
412         }
413
414         bytearray_cursor_initialize(&bytecursor, &cursor->target->rawdata);
415         bytearray_cursor_move(&bytecursor, offset);
416         err = bytearray_cursor_insert(&bytecursor, data, len);
417         bytearray_cursor_finalize(&bytecursor);
418         if (err < 0) {
419                 return err;
420         }
421
422         tadfragment_pos_iterator_initialize(&iterator, data, len);
423         for (;;) {
424                 cont = tadfragment_pos_iterator_next(&iterator, &result);
425                 if (cont == False) {
426                         break;
427                 }
428                 if (result.type == TADFRAGMENT_POS_ITERATOR_RESULT_TYPE_SEGMENT) {
429                         val = result.index + offset;
430                         err = wordarray_cursor_insert(&cursor->base, &val, 1);
431                         if (err < 0) {
432                                 break;
433                         }
434                         wordarray_cursor_move(&cursor->base, 1);
435                 }
436         }
437         tadfragment_pos_iterator_finalize(&iterator);
438
439         for (;;) {
440                 err2 = wordarray_cursor_getW(&cursor->base, &val);
441                 if (err2 < 0) {
442                         /* TODO: error or end position */
443                         break;
444                 }
445                 wordarray_cursor_setW(&cursor->base, val + len);
446                 wordarray_cursor_move(&cursor->base, 1);
447         }
448
449         return err;
450 }
451
452 EXPORT Bool tadfragment_cursor_isend(tadfragment_cursor_t *cursor)
453 {
454         return wordarray_cursor_isend(&cursor->base);
455 }
456
457 EXPORT W tadfragment_cursor_getdata(tadfragment_cursor_t *cursor, tadfragment_cursor_segment *p)
458 {
459         Bool end;
460         W offset, offset_next, err;
461         UH ch;
462
463         end = tadfragment_cursor_isend(cursor);
464         if (end != False) {
465                 return -1; // TODO
466         }
467
468         err = wordarray_cursor_getW(&cursor->base, &offset);
469         if (err < 0) {
470                 return err;
471         }
472         err = tadfragment_cursor_getnextpos(cursor, &offset_next);
473         if (err < 0) {
474                 return err;
475         }
476
477         p->p = bytearray_getbuffer(&cursor->target->rawdata) + offset;
478         p->len = offset_next - offset;
479
480         ch = *(UH*)p->p;
481         if ((ch & 0xFF80) == 0xFF80) {
482                 p->type = TADFRAGMENT_CURSOR_SEGMENTTYPE_VARIABLE;
483         } else if ((ch & 0xFE00) == 0xFE00) {
484                 p->type = TADFRAGMENT_CURSOR_SEGMENTTYPE_LANGCODE;
485         } else {
486                 p->type = TADFRAGMENT_CURSOR_SEGMENTTYPE_CHAR;
487         }
488
489         return 0;
490 }
491
492 EXPORT VOID tadfragment_cursor_initialize(tadfragment_cursor_t *cursor, tadfragment_t *fragment)
493 {
494         cursor->target = fragment;
495         wordarray_cursor_initialize(&cursor->base, &fragment->pos);
496 }
497
498 EXPORT VOID tadfragment_cursor_finalize(tadfragment_cursor_t *cursor)
499 {
500         wordarray_cursor_finalize(&cursor->base);
501 }