OSDN Git Service

add handling tad segments array structure.
authorornse01 <ornse01@users.sourceforge.jp>
Fri, 15 Nov 2013 18:26:36 +0000 (18:26 +0000)
committerornse01 <ornse01@users.sourceforge.jp>
Fri, 15 Nov 2013 18:26:36 +0000 (18:26 +0000)
git-svn-id: http://svn.sourceforge.jp/svnroot/bchan/bchanf/trunk@571 20a0b8eb-f62a-4a12-8fe1-b598822500fb

src/tad/tadfragment.c [new file with mode: 0644]
src/tad/tadfragment.h [new file with mode: 0644]
src/tad/test_tadfragment.c [new file with mode: 0644]

diff --git a/src/tad/tadfragment.c b/src/tad/tadfragment.c
new file mode 100644 (file)
index 0000000..f133295
--- /dev/null
@@ -0,0 +1,501 @@
+/*
+ * tadfragment.c
+ *
+ * Copyright (c) 2013 project bchan
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source
+ *    distribution.
+ *
+ */
+
+#include "tadfragment.h"
+
+#include       <basic.h>
+#include       <bstdio.h>
+
+#include    <coll/bytearray.h>
+#include    <coll/wordarray.h>
+#include    "tadlexer_le.h"
+
+#ifdef BCHAN_CONFIG_DEBUG
+# define DP(arg) printf arg
+# define DP_ER(msg, err) printf("%s (%d/%x)\n", msg, err>>16, err)
+#else
+# define DP(arg) /**/
+# define DP_ER(msg, err) /**/
+#endif
+
+#if 0
+# define DP_STATE(state) printf("%s\n", state)
+#else
+# define DP_STATE(state) /**/
+#endif
+
+struct tadfragment_pos_iterator_t_ {
+       enum {
+               TADFRAGMENT_POS_ITERATOR_STATE_BEFORE_SEGSTART,
+               TADFRAGMENT_POS_ITERATOR_STATE_READING_TLANG,
+               TADFRAGMENT_POS_ITERATOR_STATE_READING,
+               TADFRAGMENT_POS_ITERATOR_STATE_COMPLETED,
+               TADFRAGMENT_POS_ITERATOR_STATE_ERROR,
+       } state;
+       UB *data;
+       W len;
+       W pos;
+       tadlexer_le_t lexer;
+       struct {
+               tadlexer_le_result *result;
+               W len;
+               W pos;
+       } lexer_result_handling;
+};
+typedef struct tadfragment_pos_iterator_t_ tadfragment_pos_iterator_t;
+
+struct tadfragment_pos_iterator_result_ {
+       enum {
+               TADFRAGMENT_POS_ITERATOR_RESULT_TYPE_SEGMENT,
+               TADFRAGMENT_POS_ITERATOR_RESULT_TYPE_ERROR,
+       } type;
+       W index;
+};
+typedef struct tadfragment_pos_iterator_result_ tadfragment_pos_iterator_result;
+
+LOCAL W tadfragment_pos_iterator_input(tadfragment_pos_iterator_t *iterator, tadlexer_le_result *result, Bool *segstart)
+{
+       Bool fixed;
+       W err = 0;
+
+       *segstart = False;
+
+       switch (iterator->state) {
+       case TADFRAGMENT_POS_ITERATOR_STATE_BEFORE_SEGSTART:
+               DP_STATE("BEFORE_SEGSTART");
+               iterator->state = TADFRAGMENT_POS_ITERATOR_STATE_READING;
+               *segstart = True;
+               break;
+       case TADFRAGMENT_POS_ITERATOR_STATE_READING_TLANG:
+               DP_STATE("READING_TLANG");
+               if (result->type == TADLEXER_LE_RESULTTYPE_SEGMENT_END) {
+                       fixed = tadlexer_le_result_is_fixedsegment(result);
+                       if (fixed == False) {
+                               iterator->state = TADFRAGMENT_POS_ITERATOR_STATE_ERROR;
+                               err = -1; /* TODO */
+                               break;
+                       }
+                       if (result->val.ch == 0xFEFE) {
+                               break;
+                       }
+                       if ((result->val.ch & 0xFF00) != 0xFE00) {
+                               iterator->state = TADFRAGMENT_POS_ITERATOR_STATE_ERROR;
+                               err = -1; /* TODO */
+                               break;
+                       }
+                       iterator->state = TADFRAGMENT_POS_ITERATOR_STATE_BEFORE_SEGSTART;
+               }
+               break;
+       case TADFRAGMENT_POS_ITERATOR_STATE_READING:
+               DP_STATE("READING");
+               if (result->type != TADLEXER_LE_RESULTTYPE_SEGMENT_END) {
+                       break;
+               }
+               fixed = tadlexer_le_result_is_fixedsegment(result);
+               if ((fixed != False)&&(result->val.ch == 0xFEFE)) {
+                       iterator->state = TADFRAGMENT_POS_ITERATOR_STATE_READING_TLANG;
+                       break;
+               }
+               iterator->state = TADFRAGMENT_POS_ITERATOR_STATE_BEFORE_SEGSTART;
+               break;
+       case TADFRAGMENT_POS_ITERATOR_STATE_COMPLETED:
+               DP_STATE("COMPLETED");
+               break;
+       case TADFRAGMENT_POS_ITERATOR_STATE_ERROR:
+               DP_STATE("ERROR");
+               err = -1; /* TODO */
+               break;
+       }
+
+       return err;
+}
+
+LOCAL Bool tadfragment_pos_iterator_next(tadfragment_pos_iterator_t *iterator, tadfragment_pos_iterator_result *result)
+{
+       UB ch;
+       W pos, len, err;
+       Bool segstart;
+       tadlexer_le_result *lexer_result;
+
+       for (; iterator->lexer_result_handling.pos < iterator->lexer_result_handling.len; ) {
+               pos = iterator->lexer_result_handling.pos++;
+               lexer_result = iterator->lexer_result_handling.result + pos;
+               err = tadfragment_pos_iterator_input(iterator, lexer_result, &segstart);
+               if (err < 0) {
+                       result->type = TADFRAGMENT_POS_ITERATOR_RESULT_TYPE_ERROR;
+                       return False;
+               }
+               if (segstart != False) {
+                       result->type = TADFRAGMENT_POS_ITERATOR_RESULT_TYPE_SEGMENT;
+                       result->index = iterator->pos - 1;
+                       return True;
+               }
+       }
+
+       for (; iterator->pos < iterator->len;) {
+               ch = iterator->data[iterator->pos++];
+               tadlexer_le_inputbyte(&iterator->lexer, ch, &lexer_result, &len);
+               iterator->lexer_result_handling.result = lexer_result;
+               iterator->lexer_result_handling.len = len;
+               iterator->lexer_result_handling.pos = 0;
+
+               for (; iterator->lexer_result_handling.pos < iterator->lexer_result_handling.len; ) {
+                       pos = iterator->lexer_result_handling.pos++;
+                       lexer_result = iterator->lexer_result_handling.result + pos;
+                       err = tadfragment_pos_iterator_input(iterator, lexer_result, &segstart);
+                       if (err < 0) {
+                               result->type = TADFRAGMENT_POS_ITERATOR_RESULT_TYPE_ERROR;
+                               return False;
+                       }
+                       if (segstart != False) {
+                               result->type = TADFRAGMENT_POS_ITERATOR_RESULT_TYPE_SEGMENT;
+                               result->index = iterator->pos - 1;
+                               return True;
+                       }
+               }
+       }
+
+       if (iterator->state == TADFRAGMENT_POS_ITERATOR_STATE_BEFORE_SEGSTART) {
+               iterator->state = TADFRAGMENT_POS_ITERATOR_STATE_COMPLETED;
+               result->type = TADFRAGMENT_POS_ITERATOR_RESULT_TYPE_SEGMENT;
+               result->index = iterator->len;
+       } else {
+               result->type = TADFRAGMENT_POS_ITERATOR_RESULT_TYPE_ERROR;
+       }
+
+       return False;
+}
+
+LOCAL VOID tadfragment_pos_iterator_initialize(tadfragment_pos_iterator_t *iterator, UB *data, W len)
+{
+       tadlexer_le_initialize(&iterator->lexer);
+       iterator->state = TADFRAGMENT_POS_ITERATOR_STATE_BEFORE_SEGSTART;
+       iterator->data = data;
+       iterator->len = len;
+       iterator->pos = 0;
+       iterator->lexer_result_handling.result = NULL;
+       iterator->lexer_result_handling.len = 0;
+       iterator->lexer_result_handling.pos = 0;
+}
+
+LOCAL VOID tadfragment_pos_iterator_finalize(tadfragment_pos_iterator_t *iterator)
+{
+       tadlexer_le_finalize(&iterator->lexer);
+}
+
+LOCAL Bool tadfragment_verifydata(UB *data, W len)
+{
+       tadfragment_pos_iterator_t iterator;
+       tadfragment_pos_iterator_result result;
+       Bool cont, ret = True;
+
+       tadfragment_pos_iterator_initialize(&iterator, data, len);
+       for (;;) {
+               cont = tadfragment_pos_iterator_next(&iterator, &result);
+               if (cont == False) {
+                       break;
+               }
+               if (result.type == TADFRAGMENT_POS_ITERATOR_RESULT_TYPE_SEGMENT) {
+               } else {
+                       ret = False;
+                       break;
+               }
+       }
+       tadfragment_pos_iterator_finalize(&iterator);
+
+       return True;
+}
+
+EXPORT UB* tadfragment_getbuffer(tadfragment_t *fragment)
+{
+       return bytearray_getbuffer(&fragment->rawdata);
+}
+
+EXPORT W tadfragment_getsegmentlength(tadfragment_t *fragment)
+{
+       return wordarray_getlength(&fragment->pos);
+}
+
+EXPORT W tadfragment_getbufferlength(tadfragment_t *fragment)
+{
+       return bytearray_getlength(&fragment->rawdata);
+}
+
+EXPORT W tadfragment_pushback(tadfragment_t *fragment, UB *data, W len)
+{
+       tadfragment_cursor_t cursor;
+       W num, err;
+
+       tadfragment_cursor_initialize(&cursor, fragment);
+
+       num = tadfragment_getsegmentlength(fragment);
+       tadfragment_cursor_move(&cursor, num);
+
+       err = tadfragment_cursor_insert(&cursor, data, len);
+
+       tadfragment_cursor_finalize(&cursor);
+
+       return err;
+}
+
+EXPORT W tadfragment_popback(tadfragment_t *fragment)
+{
+       W len, val, i, size;
+
+       len = wordarray_getlength(&fragment->pos);
+       if (len == 0) {
+               return -1; /* TODO */
+       }
+
+       wordarray_getat(&fragment->pos, len-1, &val);
+       size = bytearray_getlength(&fragment->rawdata);
+
+       for (i = 0; i < size - val; i++) {
+               bytearray_popback(&fragment->rawdata);
+       }
+       wordarray_popback(&fragment->pos);
+
+       return 0;
+}
+
+EXPORT W tadfragment_initialize(tadfragment_t *fragment)
+{
+       W err;
+
+       err = bytearray_initialize(&fragment->rawdata);
+       if (err < 0) {
+               return err;
+       }
+       err = wordarray_initialize(&fragment->pos);
+       if (err < 0) {
+               bytearray_finalize(&fragment->rawdata);
+               return err;
+       }
+
+       return 0;
+}
+
+EXPORT VOID tadfragment_finalize(tadfragment_t *fragment)
+{
+       wordarray_finalize(&fragment->pos);
+       bytearray_finalize(&fragment->rawdata);
+}
+
+EXPORT W tadfragment_cursor_move(tadfragment_cursor_t *cursor, W diff)
+{
+       return wordarray_cursor_move(&cursor->base, diff);
+}
+
+EXPORT W tadfragment_cursor_erase(tadfragment_cursor_t *cursor, W len)
+{
+       bytearray_cursor_t bytecursor;
+       Bool isend;
+       W start_pos, end_pos, diff, val, count, err;
+
+       if (len < 0) {
+               return -1; /* TODO */
+       }
+
+       isend = tadfragment_cursor_isend(cursor);
+       if (isend != False) {
+               return -1; /* TODO */
+       }
+
+       wordarray_cursor_getW(&cursor->base, &start_pos);
+       err = tadfragment_cursor_move(cursor, len);
+       if (err < 0) {
+               diff = bytearray_getlength(&cursor->target->rawdata) - start_pos;
+       } else {
+               wordarray_cursor_getW(&cursor->base, &end_pos);
+               tadfragment_cursor_move(cursor, -len);
+
+               diff = end_pos - start_pos;
+       }
+
+       wordarray_cursor_erase(&cursor->base, len);
+
+       bytearray_cursor_initialize(&bytecursor, &cursor->target->rawdata);
+       bytearray_cursor_move(&bytecursor, start_pos);
+       bytearray_cursor_erase(&bytecursor, diff);
+       bytearray_cursor_finalize(&bytecursor);
+
+       count = 0;
+       for (;;) {
+               err = wordarray_cursor_getW(&cursor->base, &val);
+               if (err < 0) {
+                       /* TODO: error or end position */
+                       break;
+               }
+               wordarray_cursor_setW(&cursor->base, val - diff);
+               wordarray_cursor_move(&cursor->base, 1);
+               count++;
+       }
+       wordarray_cursor_move(&cursor->base, -count);
+
+       return 0;
+}
+
+LOCAL W tadfragment_cursor_getnextpos(tadfragment_cursor_t *cursor, W *pos)
+{
+       W err;
+       Bool isend;
+
+       err = tadfragment_cursor_move(cursor, 1);
+       if (err < 0) {
+               return err;
+       }
+       isend = tadfragment_cursor_isend(cursor);
+       if (isend != False) {
+               *pos = bytearray_getlength(&cursor->target->rawdata);
+               tadfragment_cursor_move(cursor, -1);
+               return 0;
+       }
+
+       err = wordarray_cursor_getW(&cursor->base, pos);
+       tadfragment_cursor_move(cursor, -1);
+
+       return err;
+}
+
+EXPORT W tadfragment_cursor_insert(tadfragment_cursor_t *cursor, UB *data, W len)
+{
+       bytearray_cursor_t bytecursor;
+       tadfragment_pos_iterator_t iterator;
+       tadfragment_pos_iterator_result result;
+       Bool ok, cont, isend;
+       W offset, val, err, err2;
+
+       if (len < 0) {
+               return -1; /* TODO */
+       }
+       if (len == 0) {
+               return 0;
+       }
+
+       ok = tadfragment_verifydata(data, len);
+       if (ok == False) {
+               return -1; /* TODO */
+       }
+
+       isend = tadfragment_cursor_isend(cursor);
+       if (isend == False) {
+               err = wordarray_cursor_getW(&cursor->base, &offset);
+               if (err < 0) {
+                       printf("BBB\n");
+                       return err;
+               }
+       } else {
+               offset = bytearray_getlength(&cursor->target->rawdata);
+       }
+
+       bytearray_cursor_initialize(&bytecursor, &cursor->target->rawdata);
+       bytearray_cursor_move(&bytecursor, offset);
+       err = bytearray_cursor_insert(&bytecursor, data, len);
+       bytearray_cursor_finalize(&bytecursor);
+       if (err < 0) {
+               return err;
+       }
+
+       tadfragment_pos_iterator_initialize(&iterator, data, len);
+       for (;;) {
+               cont = tadfragment_pos_iterator_next(&iterator, &result);
+               if (cont == False) {
+                       break;
+               }
+               if (result.type == TADFRAGMENT_POS_ITERATOR_RESULT_TYPE_SEGMENT) {
+                       val = result.index + offset;
+                       err = wordarray_cursor_insert(&cursor->base, &val, 1);
+                       if (err < 0) {
+                               break;
+                       }
+                       wordarray_cursor_move(&cursor->base, 1);
+               }
+       }
+       tadfragment_pos_iterator_finalize(&iterator);
+
+       for (;;) {
+               err2 = wordarray_cursor_getW(&cursor->base, &val);
+               if (err2 < 0) {
+                       /* TODO: error or end position */
+                       break;
+               }
+               wordarray_cursor_setW(&cursor->base, val + len);
+               wordarray_cursor_move(&cursor->base, 1);
+       }
+
+       return err;
+}
+
+EXPORT Bool tadfragment_cursor_isend(tadfragment_cursor_t *cursor)
+{
+       return wordarray_cursor_isend(&cursor->base);
+}
+
+EXPORT W tadfragment_cursor_getdata(tadfragment_cursor_t *cursor, tadfragment_cursor_segment *p)
+{
+       Bool end;
+       W offset, offset_next, err;
+       UH ch;
+
+       end = tadfragment_cursor_isend(cursor);
+       if (end != False) {
+               return -1; // TODO
+       }
+
+       err = wordarray_cursor_getW(&cursor->base, &offset);
+       if (err < 0) {
+               return err;
+       }
+       err = tadfragment_cursor_getnextpos(cursor, &offset_next);
+       if (err < 0) {
+               return err;
+       }
+
+       p->p = bytearray_getbuffer(&cursor->target->rawdata) + offset;
+       p->len = offset_next - offset;
+
+       ch = *(UH*)p->p;
+       if ((ch & 0xFF80) == 0xFF80) {
+               p->type = TADFRAGMENT_CURSOR_SEGMENTTYPE_VARIABLE;
+       } else if ((ch & 0xFE00) == 0xFE00) {
+               p->type = TADFRAGMENT_CURSOR_SEGMENTTYPE_LANGCODE;
+       } else {
+               p->type = TADFRAGMENT_CURSOR_SEGMENTTYPE_CHAR;
+       }
+
+       return 0;
+}
+
+EXPORT VOID tadfragment_cursor_initialize(tadfragment_cursor_t *cursor, tadfragment_t *fragment)
+{
+       cursor->target = fragment;
+       wordarray_cursor_initialize(&cursor->base, &fragment->pos);
+}
+
+EXPORT VOID tadfragment_cursor_finalize(tadfragment_cursor_t *cursor)
+{
+       wordarray_cursor_finalize(&cursor->base);
+}
diff --git a/src/tad/tadfragment.h b/src/tad/tadfragment.h
new file mode 100644 (file)
index 0000000..57edf0c
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * tadfragment.h
+ *
+ * Copyright (c) 2013 project bchan
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source
+ *    distribution.
+ *
+ */
+
+/* Vendor name: */
+/* Functionality name: tadfragment */
+/* Detail name: */
+
+#include    <basic.h>
+#include       <btron/dp.h>
+#include    <tad.h>
+
+#include    <coll/bytearray.h>
+#include    <coll/wordarray.h>
+
+#ifndef __TADFRAGMENT_H__
+#define __TADFRAGMENT_H__
+
+/* Functionality name: tadfragment */
+/* Detail name: */
+struct tadfragment_t_ {
+       bytearray_t rawdata;
+       wordarray_t pos;
+};
+typedef struct tadfragment_t_ tadfragment_t;
+
+/* Functionality name: tadfragment */
+/* Detail name: cursor */
+struct tadfragment_cursor_t_ {
+       tadfragment_t *target;
+       wordarray_cursor_t base;
+};
+typedef struct tadfragment_cursor_t_ tadfragment_cursor_t;
+
+/* Functionality name: tadfragment */
+/* Detail name: cursor */
+/* Data structure identifier: segment */
+struct tadfragment_cursor_segment_ {
+       enum TADFRAGMENT_CURSOR_SEGMENTTYPE {
+               TADFRAGMENT_CURSOR_SEGMENTTYPE_VARIABLE,
+               TADFRAGMENT_CURSOR_SEGMENTTYPE_CHAR,
+               TADFRAGMENT_CURSOR_SEGMENTTYPE_LANGCODE,
+       } type;
+       UB *p;
+       W len;
+};
+typedef struct tadfragment_cursor_segment_ tadfragment_cursor_segment;
+
+IMPORT W tadfragment_initialize(tadfragment_t *fragment);
+IMPORT VOID tadfragment_finalize(tadfragment_t *fragment);
+IMPORT UB* tadfragment_getbuffer(tadfragment_t *fragment);
+IMPORT W tadfragment_getsegmentlength(tadfragment_t *fragment);
+IMPORT W tadfragment_getbufferlength(tadfragment_t *fragment);
+IMPORT W tadfragment_pushback(tadfragment_t *fragment, UB *data, W len);
+IMPORT W tadfragment_popback(tadfragment_t *fragment);
+
+IMPORT VOID tadfragment_cursor_initialize(tadfragment_cursor_t *cursor, tadfragment_t *fragment);
+IMPORT VOID tadfragment_cursor_finalize(tadfragment_cursor_t *cursor);
+IMPORT W tadfragment_cursor_move(tadfragment_cursor_t *cursor, W diff);
+IMPORT W tadfragment_cursor_erase(tadfragment_cursor_t *cursor, W len);
+IMPORT W tadfragment_cursor_insert(tadfragment_cursor_t *cursor, UB *data, W len);
+IMPORT Bool tadfragment_cursor_isend(tadfragment_cursor_t *cursor);
+IMPORT W tadfragment_cursor_getdata(tadfragment_cursor_t *cursor, tadfragment_cursor_segment *p);
+
+#endif
diff --git a/src/tad/test_tadfragment.c b/src/tad/test_tadfragment.c
new file mode 100644 (file)
index 0000000..c674076
--- /dev/null
@@ -0,0 +1,917 @@
+/*
+ * test_taditerator.c
+ *
+ * Copyright (c) 2013 project bchan
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source
+ *    distribution.
+ *
+ */
+
+#include "test_tad.h"
+
+#include "tadfragment.h"
+
+#include       <basic.h>
+#include       <bstdio.h>
+#include       <bstdlib.h>
+#include       <tcode.h>
+
+#include    <unittest_driver.h>
+
+typedef struct {
+       TC *input;
+       W input_len;
+       W segment_num;
+} test_tadfragment_pushback_t;
+
+LOCAL UNITTEST_RESULT test_tadfragment_pushback_common(test_tadfragment_pushback_t *testdata)
+{
+       tadfragment_t fragment;
+       W len, err;
+       UNITTEST_RESULT result = UNITTEST_RESULT_PASS;
+
+       err = tadfragment_initialize(&fragment);
+       if (err < 0) {
+               return UNITTEST_RESULT_FAIL;
+       }
+
+       err = tadfragment_pushback(&fragment, (UB*)testdata->input, testdata->input_len);
+       if (err < 0) {
+               printf("tadfragment_pushback error\n");
+               result = UNITTEST_RESULT_FAIL;
+       }
+
+       len = tadfragment_getsegmentlength(&fragment);
+       if (len != testdata->segment_num) {
+               printf("tadfragment_getsegmentlength fail: expected = %d, result = %d\n", testdata->segment_num, len);
+               result = UNITTEST_RESULT_FAIL;
+       }
+
+       len = tadfragment_getbufferlength(&fragment);
+       if (len != testdata->input_len) {
+               printf("tadfragment_getbufferlength fail: expected = %d, result = %d\n", testdata->input_len, len);
+               result = UNITTEST_RESULT_FAIL;
+       }
+
+       tadfragment_finalize(&fragment);
+
+       return result;
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_pushback_1()
+{
+       TC tad[] = {TK_A, TK_B, TK_C};
+       W tad_len = sizeof(tad);
+       W seg_len = 3;
+       test_tadfragment_pushback_t testdata = {
+               tad, tad_len, seg_len
+       };
+       return test_tadfragment_pushback_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_pushback_2()
+{
+       TC tad[] = {TK_A, TK_B, TK_C, TK_D};
+       W tad_len = sizeof(tad);
+       W seg_len = 4;
+       test_tadfragment_pushback_t testdata = {
+               tad, tad_len, seg_len
+       };
+       return test_tadfragment_pushback_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_pushback_3()
+{
+       TC tad[] = {TK_A, 0xFF80, 0x0002, 0x0000, TK_C};
+       W tad_len = sizeof(tad);
+       W seg_len = 3;
+       test_tadfragment_pushback_t testdata = {
+               tad, tad_len, seg_len
+       };
+       return test_tadfragment_pushback_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_pushback_4()
+{
+       TC tad[] = {TK_A, TK_B, 0xFE21};
+       W tad_len = sizeof(tad);
+       W seg_len = 3;
+       test_tadfragment_pushback_t testdata = {
+               tad, tad_len, seg_len
+       };
+       return test_tadfragment_pushback_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_pushback_5()
+{
+       TC tad[] = {TK_A, TK_B, 0xFE21, TK_D};
+       W tad_len = sizeof(tad);
+       W seg_len = 4;
+       test_tadfragment_pushback_t testdata = {
+               tad, tad_len, seg_len
+       };
+       return test_tadfragment_pushback_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_pushback_6()
+{
+       TC tad[] = {TK_A, TK_B, 0xFEFE, 0xFE21};
+       W tad_len = sizeof(tad);
+       W seg_len = 3;
+       test_tadfragment_pushback_t testdata = {
+               tad, tad_len, seg_len
+       };
+       return test_tadfragment_pushback_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_pushback_7()
+{
+       TC tad[] = {TK_A, TK_B, 0xFEFE, 0xFE21, TK_C};
+       W tad_len = sizeof(tad);
+       W seg_len = 4;
+       test_tadfragment_pushback_t testdata = {
+               tad, tad_len, seg_len
+       };
+       return test_tadfragment_pushback_common(&testdata);
+}
+
+typedef struct {
+       TC *input;
+       W input_len;
+       W segment_num;
+       W expected_len;
+} test_tadfragment_popback_t;
+
+LOCAL UNITTEST_RESULT test_tadfragment_popback_common(test_tadfragment_popback_t *testdata)
+{
+       tadfragment_t fragment;
+       W len, err;
+       UNITTEST_RESULT result = UNITTEST_RESULT_PASS;
+
+       err = tadfragment_initialize(&fragment);
+       if (err < 0) {
+               return UNITTEST_RESULT_FAIL;
+       }
+
+       err = tadfragment_pushback(&fragment, (UB*)testdata->input, testdata->input_len);
+       if (err < 0) {
+               printf("tadfragment_pushback error\n");
+               result = UNITTEST_RESULT_FAIL;
+       }
+       err = tadfragment_popback(&fragment);
+       if (err < 0) {
+               printf("tadfragment_popback error\n");
+               result = UNITTEST_RESULT_FAIL;
+       }
+
+       len = tadfragment_getsegmentlength(&fragment);
+       if (len != testdata->segment_num) {
+               printf("tadfragment_getsegmentlength fail: expected = %d, result = %d\n", testdata->segment_num, len);
+               result = UNITTEST_RESULT_FAIL;
+       }
+
+       len = tadfragment_getbufferlength(&fragment);
+       if (len != testdata->expected_len) {
+               printf("tadfragment_getbufferlength fail: expected = %d, result = %d\n", testdata->expected_len, len);
+               result = UNITTEST_RESULT_FAIL;
+       }
+
+       tadfragment_finalize(&fragment);
+
+       return result;
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_popback_1()
+{
+       TC tad[] = {TK_A, TK_B, TK_C};
+       W tad_len = sizeof(tad);
+       W expected_len = tad_len - sizeof(TC);
+       W seg_len = 2;
+       test_tadfragment_popback_t testdata = {
+               tad, tad_len, seg_len, expected_len
+       };
+       return test_tadfragment_popback_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_popback_2()
+{
+       TC tad[] = {TK_A, TK_B, TK_C, TK_D};
+       W tad_len = sizeof(tad);
+       W expected_len = tad_len - sizeof(TC);
+       W seg_len = 3;
+       test_tadfragment_popback_t testdata = {
+               tad, tad_len, seg_len, expected_len
+       };
+       return test_tadfragment_popback_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_popback_3()
+{
+       TC tad[] = {TK_A, 0xFF80, 0x0002, 0x0000, TK_C};
+       W tad_len = sizeof(tad);
+       W expected_len = tad_len - sizeof(TC);
+       W seg_len = 2;
+       test_tadfragment_popback_t testdata = {
+               tad, tad_len, seg_len, expected_len
+       };
+       return test_tadfragment_popback_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_popback_4()
+{
+       TC tad[] = {TK_A, TK_B, 0xFF80, 0x0002, 0x0000};
+       W tad_len = sizeof(tad);
+       W expected_len = tad_len - sizeof(TC)*3;
+       W seg_len = 2;
+       test_tadfragment_popback_t testdata = {
+               tad, tad_len, seg_len, expected_len
+       };
+       return test_tadfragment_popback_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_popback_5()
+{
+       TC tad[] = {TK_A, TK_B, 0xFE21};
+       W tad_len = sizeof(tad);
+       W expected_len = tad_len - sizeof(TC);
+       W seg_len = 2;
+       test_tadfragment_popback_t testdata = {
+               tad, tad_len, seg_len, expected_len
+       };
+       return test_tadfragment_popback_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_popback_6()
+{
+       TC tad[] = {TK_A, TK_B, 0xFE21, TK_D};
+       W tad_len = sizeof(tad);
+       W expected_len = tad_len - sizeof(TC);
+       W seg_len = 3;
+       test_tadfragment_popback_t testdata = {
+               tad, tad_len, seg_len, expected_len
+       };
+       return test_tadfragment_popback_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_popback_7()
+{
+       TC tad[] = {TK_A, TK_B, 0xFEFE, 0xFE21};
+       W tad_len = sizeof(tad);
+       W expected_len = tad_len - sizeof(TC)*2;
+       W seg_len = 2;
+       test_tadfragment_popback_t testdata = {
+               tad, tad_len, seg_len, expected_len
+       };
+       return test_tadfragment_popback_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_popback_8()
+{
+       TC tad[] = {TK_A, TK_B, 0xFEFE, 0xFE21, TK_C};
+       W tad_len = sizeof(tad);
+       W expected_len = tad_len - sizeof(TC);
+       W seg_len = 3;
+       test_tadfragment_popback_t testdata = {
+               tad, tad_len, seg_len, expected_len
+       };
+       return test_tadfragment_popback_common(&testdata);
+}
+
+typedef struct {
+       TC *original;
+       W original_len;
+       TC *insert;
+       W insert_len;
+       W insert_pos;
+       TC *expected;
+       W expected_len;
+       W expected_segment_num;
+} test_tadfragment_cursor_insert_t;
+
+LOCAL UNITTEST_RESULT test_tadfragment_cursor_insert_common(test_tadfragment_cursor_insert_t *testdata)
+{
+       tadfragment_t fragment;
+       tadfragment_cursor_t cursor;
+       W len, err;
+       UB *buf;
+       UNITTEST_RESULT result = UNITTEST_RESULT_PASS;
+
+       err = tadfragment_initialize(&fragment);
+       if (err < 0) {
+               return UNITTEST_RESULT_FAIL;
+       }
+
+       err = tadfragment_pushback(&fragment, (UB*)testdata->original, testdata->original_len);
+       if (err < 0) {
+               printf("tadfragment_pushback error\n");
+               result = UNITTEST_RESULT_FAIL;
+       }
+
+       tadfragment_cursor_initialize(&cursor, &fragment);
+
+       err = tadfragment_cursor_move(&cursor, testdata->insert_pos);
+       if (err < 0) {
+               printf("tadfragment_cursor_move error\n");
+               result = UNITTEST_RESULT_FAIL;
+       }
+       err = tadfragment_cursor_insert(&cursor, (UB*)testdata->insert, testdata->insert_len);
+       if (err < 0) {
+               printf("tadfragment_cursor_insert error\n");
+               result = UNITTEST_RESULT_FAIL;
+       }
+
+       tadfragment_cursor_finalize(&cursor);
+
+       len = tadfragment_getsegmentlength(&fragment);
+       if (len != testdata->expected_segment_num) {
+               printf("tadfragment_getsegmentlength fail: expected = %d, result = %d\n", testdata->expected_segment_num, len);
+               result = UNITTEST_RESULT_FAIL;
+       }
+
+       len = tadfragment_getbufferlength(&fragment);
+       if (len != testdata->expected_len) {
+               printf("tadfragment_getbufferlength fail: expected = %d, result = %d\n", testdata->expected_len, len);
+               result = UNITTEST_RESULT_FAIL;
+       }
+
+       buf = tadfragment_getbuffer(&fragment);
+       if (memcmp(buf, testdata->expected, testdata->expected_len) != 0) {
+               printf("tadfragment_getbuffer fail\n");
+               {
+                       W i;
+                       for (i = 0; i < testdata->expected_len; i++) {
+                               printf("%02x, %02x\n", buf[i], ((UB*)testdata->expected)[i]);
+                       }
+               }
+               result = UNITTEST_RESULT_FAIL;
+       }
+
+       tadfragment_finalize(&fragment);
+
+       return result;
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_cursor_insert_1()
+{
+       TC original[] = {TK_A, TK_B, TK_C};
+       W original_len = sizeof(original);
+       TC insert[] = {TK_D, TK_E};
+       W insert_len = sizeof(insert);
+       W insert_pos = 0;
+       TC expected[] = {TK_D, TK_E, TK_A, TK_B, TK_C};
+       W expected_len = sizeof(expected);
+       W expected_segment_num = 5;
+       test_tadfragment_cursor_insert_t testdata = {
+               original, original_len,
+               insert, insert_len, insert_pos,
+               expected, expected_len, expected_segment_num
+       };
+       return test_tadfragment_cursor_insert_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_cursor_insert_2()
+{
+       TC original[] = {TK_A, TK_B, TK_C};
+       W original_len = sizeof(original);
+       TC insert[] = {TK_D, TK_E};
+       W insert_len = sizeof(insert);
+       W insert_pos = 1;
+       TC expected[] = {TK_A, TK_D, TK_E, TK_B, TK_C};
+       W expected_len = sizeof(expected);
+       W expected_segment_num = 5;
+       test_tadfragment_cursor_insert_t testdata = {
+               original, original_len,
+               insert, insert_len, insert_pos,
+               expected, expected_len, expected_segment_num
+       };
+       return test_tadfragment_cursor_insert_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_cursor_insert_3()
+{
+       TC original[] = {TK_A, TK_B, TK_C};
+       W original_len = sizeof(original);
+       TC insert[] = {TK_D, TK_E};
+       W insert_len = sizeof(insert);
+       W insert_pos = 2;
+       TC expected[] = {TK_A, TK_B, TK_D, TK_E, TK_C};
+       W expected_len = sizeof(expected);
+       W expected_segment_num = 5;
+       test_tadfragment_cursor_insert_t testdata = {
+               original, original_len,
+               insert, insert_len, insert_pos,
+               expected, expected_len, expected_segment_num
+       };
+       return test_tadfragment_cursor_insert_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_cursor_insert_4()
+{
+       TC original[] = {TK_A, TK_B, TK_C};
+       W original_len = sizeof(original);
+       TC insert[] = {TK_D, TK_E};
+       W insert_len = sizeof(insert);
+       W insert_pos = 3;
+       TC expected[] = {TK_A, TK_B, TK_C, TK_D, TK_E};
+       W expected_len = sizeof(expected);
+       W expected_segment_num = 5;
+       test_tadfragment_cursor_insert_t testdata = {
+               original, original_len,
+               insert, insert_len, insert_pos,
+               expected, expected_len, expected_segment_num
+       };
+       return test_tadfragment_cursor_insert_common(&testdata);
+}
+
+LOCAL Bool test_tadfragment_common_verify_segment(tadfragment_cursor_segment *segment, tadfragment_cursor_segment *expected)
+{
+       Bool result = True;
+
+       if (segment->type != expected->type) {
+               printf("segment type fail: expected = %d, result = %d\n", expected->type, segment->type);
+               result = False;
+       }
+       if (segment->len != expected->len) {
+               printf("segment length fail: expected = %d, result = %d\n", expected->len, segment->len);
+               result = False;
+       }
+       if (memcmp(segment->p, expected->p, segment->len) != 0) {
+               printf("segment data fail\n");
+               result = False;
+       }
+
+       return result;
+}
+
+LOCAL Bool test_tadfragment_common_verify_segments(tadfragment_cursor_t *cursor, tadfragment_cursor_segment *expected, W expected_len)
+{
+       tadfragment_cursor_segment segment;
+       W i, err;
+       Bool result = True, verify;
+
+       for (i = 0;; i++) {
+               err = tadfragment_cursor_getdata(cursor, &segment);
+               if (i < expected_len) {
+                       if (err < 0) {
+                               printf("tadfragment_pushback error\n");
+                               result = False;
+                       }
+
+                       verify = test_tadfragment_common_verify_segment(&segment, expected + i);
+                       if (verify == False) {
+                               printf("segment %d is not expected\n", i);
+                               result = False;
+                       }
+               }
+
+               err = tadfragment_cursor_move(cursor, 1);
+               if (err < 0) {
+                       break;
+               }
+       }
+       if (i != expected_len) {
+               printf("tadfragment_cursor_move time fail: expected = %d, result = %d\n", expected_len, i);
+               result = False;
+       }
+
+       return result;
+}
+
+typedef struct {
+       TC *input;
+       W input_len;
+       tadfragment_cursor_segment *expected;
+       W expected_len;
+} test_tadfragment_cursor_getdata_t;
+
+LOCAL UNITTEST_RESULT test_tadfragment_cursor_getdata_common(test_tadfragment_cursor_getdata_t *testdata)
+{
+       tadfragment_t fragment;
+       tadfragment_cursor_t cursor;
+       W err;
+       Bool verify;
+       UNITTEST_RESULT result = UNITTEST_RESULT_PASS;
+
+       err = tadfragment_initialize(&fragment);
+       if (err < 0) {
+               return UNITTEST_RESULT_FAIL;
+       }
+
+       err = tadfragment_pushback(&fragment, (UB*)testdata->input, testdata->input_len);
+       if (err < 0) {
+               printf("tadfragment_pushback error\n");
+               result = UNITTEST_RESULT_FAIL;
+       }
+
+       tadfragment_cursor_initialize(&cursor, &fragment);
+
+       verify = test_tadfragment_common_verify_segments(&cursor, testdata->expected, testdata->expected_len);
+       if (verify == False) {
+               result = UNITTEST_RESULT_FAIL;
+       }
+
+       tadfragment_cursor_finalize(&cursor);
+
+       tadfragment_finalize(&fragment);
+
+       return result;
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_cursor_getdata_1()
+{
+       TC input[] = {TK_A, TK_B, TK_C};
+       W input_len = sizeof(input);
+       tadfragment_cursor_segment expected[] = {
+               {TADFRAGMENT_CURSOR_SEGMENTTYPE_CHAR, (UB*)(TC[]){TK_A}, 2},
+               {TADFRAGMENT_CURSOR_SEGMENTTYPE_CHAR, (UB*)(TC[]){TK_B}, 2},
+               {TADFRAGMENT_CURSOR_SEGMENTTYPE_CHAR, (UB*)(TC[]){TK_C}, 2},
+       };
+       W expected_len = 3;
+       test_tadfragment_cursor_getdata_t testdata = {
+               input, input_len,
+               expected, expected_len
+       };
+       return test_tadfragment_cursor_getdata_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_cursor_getdata_2()
+{
+       TC input[] = {TK_A, 0xFF80, 0x0002, 0x0000, TK_C};
+       W input_len = sizeof(input);
+       tadfragment_cursor_segment expected[] = {
+               {TADFRAGMENT_CURSOR_SEGMENTTYPE_CHAR, (UB*)(TC[]){TK_A}, 2},
+               {TADFRAGMENT_CURSOR_SEGMENTTYPE_VARIABLE, (UB*)(TC[]){0xFF80, 0x0002, 0x0000}, 6},
+               {TADFRAGMENT_CURSOR_SEGMENTTYPE_CHAR, (UB*)(TC[]){TK_C}, 2},
+       };
+       W expected_len = 3;
+       test_tadfragment_cursor_getdata_t testdata = {
+               input, input_len,
+               expected, expected_len
+       };
+       return test_tadfragment_cursor_getdata_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_cursor_getdata_3()
+{
+       TC input[] = {TK_A, TK_B, 0xFE21};
+       W input_len = sizeof(input);
+       tadfragment_cursor_segment expected[] = {
+               {TADFRAGMENT_CURSOR_SEGMENTTYPE_CHAR, (UB*)(TC[]){TK_A}, 2},
+               {TADFRAGMENT_CURSOR_SEGMENTTYPE_CHAR, (UB*)(TC[]){TK_B}, 2},
+               {TADFRAGMENT_CURSOR_SEGMENTTYPE_LANGCODE, (UB*)(TC[]){0xFE21}, 2},
+       };
+       W expected_len = 3;
+       test_tadfragment_cursor_getdata_t testdata = {
+               input, input_len,
+               expected, expected_len
+       };
+       return test_tadfragment_cursor_getdata_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_cursor_getdata_4()
+{
+       TC input[] = {TK_A, 0xFEFE, 0xFE21, TK_C};
+       W input_len = sizeof(input);
+       tadfragment_cursor_segment expected[] = {
+               {TADFRAGMENT_CURSOR_SEGMENTTYPE_CHAR, (UB*)(TC[]){TK_A}, 2},
+               {TADFRAGMENT_CURSOR_SEGMENTTYPE_LANGCODE, (UB*)(TC[]){0xFEFE, 0xFE21}, 4},
+               {TADFRAGMENT_CURSOR_SEGMENTTYPE_CHAR, (UB*)(TC[]){TK_C}, 2},
+       };
+       W expected_len = 3;
+       test_tadfragment_cursor_getdata_t testdata = {
+               input, input_len,
+               expected, expected_len
+       };
+       return test_tadfragment_cursor_getdata_common(&testdata);
+}
+
+typedef struct {
+       TC *input;
+       W input_len;
+       W erase_pos;
+       W erase_len;
+       Bool expected_pos_after_erase_is_end;
+       tadfragment_cursor_segment *expected_pos_after_erase;
+       tadfragment_cursor_segment *expected;
+       W expected_len;
+} test_tadfragment_cursor_erase_t;
+
+LOCAL UNITTEST_RESULT test_tadfragment_cursor_erase_common(test_tadfragment_cursor_erase_t *testdata)
+{
+       tadfragment_t fragment;
+       tadfragment_cursor_t cursor;
+       tadfragment_cursor_segment segment;
+       W err;
+       Bool verify;
+       UNITTEST_RESULT result = UNITTEST_RESULT_PASS;
+
+       err = tadfragment_initialize(&fragment);
+       if (err < 0) {
+               return UNITTEST_RESULT_FAIL;
+       }
+
+       err = tadfragment_pushback(&fragment, (UB*)testdata->input, testdata->input_len);
+       if (err < 0) {
+               printf("tadfragment_pushback error\n");
+               result = UNITTEST_RESULT_FAIL;
+       }
+
+       tadfragment_cursor_initialize(&cursor, &fragment);
+       tadfragment_cursor_move(&cursor, testdata->erase_pos);
+       err = tadfragment_cursor_erase(&cursor, testdata->erase_len);
+       if (err < 0) {
+               printf("tadfragment_erase error\n");
+               result = UNITTEST_RESULT_FAIL;
+       }
+       if (testdata->expected_pos_after_erase_is_end != False) {
+               if (tadfragment_cursor_isend(&cursor) == False) {
+                       printf("tadfragment_cursor is not end error\n");
+                       result = UNITTEST_RESULT_FAIL;
+               }
+       } else {
+               err = tadfragment_cursor_getdata(&cursor, &segment);
+               if (err < 0) {
+                       printf("tadfragment_cursor_getdata error\n");
+                       result = UNITTEST_RESULT_FAIL;
+               }
+               verify = test_tadfragment_common_verify_segment(&segment, testdata->expected_pos_after_erase);
+               if (verify == False) {
+                       printf("tadfragment_cursor_erase position error\n");
+                       result = UNITTEST_RESULT_FAIL;
+               }
+       }
+       tadfragment_cursor_finalize(&cursor);
+
+
+       tadfragment_cursor_initialize(&cursor, &fragment);
+       if (test_tadfragment_common_verify_segments(&cursor, testdata->expected, testdata->expected_len) == False) {
+               result = UNITTEST_RESULT_FAIL;
+       }
+       tadfragment_cursor_finalize(&cursor);
+
+       tadfragment_finalize(&fragment);
+
+       return result;
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_cursor_erase_1()
+{
+       TC input[] = {TK_A, 0xFF80, 0x0002, 0x0000, TK_C};
+       W input_len = sizeof(input);
+       Bool expected_pos_after_erase_is_end = False;
+       tadfragment_cursor_segment expected_pos_after_erase = {
+               TADFRAGMENT_CURSOR_SEGMENTTYPE_VARIABLE,
+               (UB*)(TC[]){0xFF80, 0x0002, 0x0000},
+               6
+       };
+       W erase_pos = 0;
+       W erase_len = 1;
+       tadfragment_cursor_segment expected[] = {
+               {TADFRAGMENT_CURSOR_SEGMENTTYPE_VARIABLE, (UB*)(TC[]){0xFF80, 0x0002, 0x0000}, 6},
+               {TADFRAGMENT_CURSOR_SEGMENTTYPE_CHAR, (UB*)(TC[]){TK_C}, 2},
+       };
+       W expected_len = 2;
+       test_tadfragment_cursor_erase_t testdata = {
+               input, input_len,
+               erase_pos, erase_len,
+               expected_pos_after_erase_is_end, &expected_pos_after_erase,
+               expected, expected_len
+       };
+       return test_tadfragment_cursor_erase_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_cursor_erase_2()
+{
+       TC input[] = {TK_A, 0xFF80, 0x0002, 0x0000, TK_C};
+       W input_len = sizeof(input);
+       W erase_pos = 0;
+       W erase_len = 2;
+       Bool expected_pos_after_erase_is_end = False;
+       tadfragment_cursor_segment expected_pos_after_erase = {
+               TADFRAGMENT_CURSOR_SEGMENTTYPE_CHAR,
+               (UB*)(TC[]){TK_C},
+               2
+       };
+       tadfragment_cursor_segment expected[] = {
+               {TADFRAGMENT_CURSOR_SEGMENTTYPE_CHAR, (UB*)(TC[]){TK_C}, 2},
+       };
+       W expected_len = 1;
+       test_tadfragment_cursor_erase_t testdata = {
+               input, input_len,
+               erase_pos, erase_len,
+               expected_pos_after_erase_is_end, &expected_pos_after_erase,
+               expected, expected_len
+       };
+       return test_tadfragment_cursor_erase_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_cursor_erase_3()
+{
+       TC input[] = {TK_A, 0xFF80, 0x0002, 0x0000, TK_C};
+       W input_len = sizeof(input);
+       W erase_pos = 0;
+       W erase_len = 3;
+       Bool expected_pos_after_erase_is_end = True;
+       tadfragment_cursor_segment expected_pos_after_erase = {
+       };
+       tadfragment_cursor_segment expected[] = {
+       };
+       W expected_len = 0;
+       test_tadfragment_cursor_erase_t testdata = {
+               input, input_len,
+               erase_pos, erase_len,
+               expected_pos_after_erase_is_end, &expected_pos_after_erase,
+               expected, expected_len
+       };
+       return test_tadfragment_cursor_erase_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_cursor_erase_4()
+{
+       TC input[] = {TK_A, 0xFF80, 0x0002, 0x0000, TK_C};
+       W input_len = sizeof(input);
+       W erase_pos = 0;
+       W erase_len = 4;
+       Bool expected_pos_after_erase_is_end = True;
+       tadfragment_cursor_segment expected_pos_after_erase = {
+       };
+       tadfragment_cursor_segment expected[] = {
+       };
+       W expected_len = 0;
+       test_tadfragment_cursor_erase_t testdata = {
+               input, input_len,
+               erase_pos, erase_len,
+               expected_pos_after_erase_is_end, &expected_pos_after_erase,
+               expected, expected_len
+       };
+       return test_tadfragment_cursor_erase_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_cursor_erase_5()
+{
+       TC input[] = {TK_A, 0xFF80, 0x0002, 0x0000, TK_C};
+       W input_len = sizeof(input);
+       W erase_pos = 1;
+       W erase_len = 1;
+       Bool expected_pos_after_erase_is_end = False;
+       tadfragment_cursor_segment expected_pos_after_erase = {
+               TADFRAGMENT_CURSOR_SEGMENTTYPE_CHAR,
+               (UB*)(TC[]){TK_C},
+               2
+       };
+       tadfragment_cursor_segment expected[] = {
+               {TADFRAGMENT_CURSOR_SEGMENTTYPE_CHAR, (UB*)(TC[]){TK_A}, 2},
+               {TADFRAGMENT_CURSOR_SEGMENTTYPE_CHAR, (UB*)(TC[]){TK_C}, 2},
+       };
+       W expected_len = 2;
+       test_tadfragment_cursor_erase_t testdata = {
+               input, input_len,
+               erase_pos, erase_len,
+               expected_pos_after_erase_is_end, &expected_pos_after_erase,
+               expected, expected_len
+       };
+       return test_tadfragment_cursor_erase_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_cursor_erase_6()
+{
+       TC input[] = {TK_A, 0xFF80, 0x0002, 0x0000, TK_C};
+       W input_len = sizeof(input);
+       W erase_pos = 1;
+       W erase_len = 2;
+       Bool expected_pos_after_erase_is_end = True;
+       tadfragment_cursor_segment expected_pos_after_erase = {
+       };
+       tadfragment_cursor_segment expected[] = {
+               {TADFRAGMENT_CURSOR_SEGMENTTYPE_CHAR, (UB*)(TC[]){TK_A}, 2},
+       };
+       W expected_len = 1;
+       test_tadfragment_cursor_erase_t testdata = {
+               input, input_len,
+               erase_pos, erase_len,
+               expected_pos_after_erase_is_end, &expected_pos_after_erase,
+               expected, expected_len
+       };
+       return test_tadfragment_cursor_erase_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_cursor_erase_7()
+{
+       TC input[] = {TK_A, 0xFF80, 0x0002, 0x0000, TK_C};
+       W input_len = sizeof(input);
+       W erase_pos = 1;
+       W erase_len = 3;
+       Bool expected_pos_after_erase_is_end = True;
+       tadfragment_cursor_segment expected_pos_after_erase = {
+       };
+       tadfragment_cursor_segment expected[] = {
+               {TADFRAGMENT_CURSOR_SEGMENTTYPE_CHAR, (UB*)(TC[]){TK_A}, 2},
+       };
+       W expected_len = 1;
+       test_tadfragment_cursor_erase_t testdata = {
+               input, input_len,
+               erase_pos, erase_len,
+               expected_pos_after_erase_is_end, &expected_pos_after_erase,
+               expected, expected_len
+       };
+       return test_tadfragment_cursor_erase_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_cursor_erase_8()
+{
+       TC input[] = {TK_A, 0xFF80, 0x0002, 0x0000, TK_C};
+       W input_len = sizeof(input);
+       W erase_pos = 2;
+       W erase_len = 1;
+       Bool expected_pos_after_erase_is_end = True;
+       tadfragment_cursor_segment expected_pos_after_erase = {
+       };
+       tadfragment_cursor_segment expected[] = {
+               {TADFRAGMENT_CURSOR_SEGMENTTYPE_CHAR, (UB*)(TC[]){TK_A}, 2},
+               {TADFRAGMENT_CURSOR_SEGMENTTYPE_VARIABLE, (UB*)(TC[]){0xFF80, 0x0002, 0x0000}, 6},
+       };
+       W expected_len = 2;
+       test_tadfragment_cursor_erase_t testdata = {
+               input, input_len,
+               erase_pos, erase_len,
+               expected_pos_after_erase_is_end, &expected_pos_after_erase,
+               expected, expected_len
+       };
+       return test_tadfragment_cursor_erase_common(&testdata);
+}
+
+LOCAL UNITTEST_RESULT test_tadfragment_cursor_erase_9()
+{
+       TC input[] = {TK_A, 0xFF80, 0x0002, 0x0000, TK_C};
+       W input_len = sizeof(input);
+       W erase_pos = 2;
+       W erase_len = 2;
+       Bool expected_pos_after_erase_is_end = True;
+       tadfragment_cursor_segment expected_pos_after_erase = {
+       };
+       tadfragment_cursor_segment expected[] = {
+               {TADFRAGMENT_CURSOR_SEGMENTTYPE_CHAR, (UB*)(TC[]){TK_A}, 2},
+               {TADFRAGMENT_CURSOR_SEGMENTTYPE_VARIABLE, (UB*)(TC[]){0xFF80, 0x0002, 0x0000}, 6},
+       };
+       W expected_len = 2;
+       test_tadfragment_cursor_erase_t testdata = {
+               input, input_len,
+               erase_pos, erase_len,
+               expected_pos_after_erase_is_end, &expected_pos_after_erase,
+               expected, expected_len
+       };
+       return test_tadfragment_cursor_erase_common(&testdata);
+}
+
+EXPORT VOID test_tadfragment_main(unittest_driver_t *driver)
+{
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_pushback_1);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_pushback_2);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_pushback_3);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_pushback_4);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_pushback_5);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_pushback_6);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_pushback_7);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_popback_1);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_popback_2);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_popback_3);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_popback_4);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_popback_5);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_popback_6);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_popback_7);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_popback_8);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_cursor_insert_1);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_cursor_insert_2);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_cursor_insert_3);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_cursor_insert_4);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_cursor_getdata_1);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_cursor_getdata_2);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_cursor_getdata_3);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_cursor_getdata_4);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_cursor_erase_1);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_cursor_erase_2);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_cursor_erase_3);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_cursor_erase_4);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_cursor_erase_5);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_cursor_erase_6);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_cursor_erase_7);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_cursor_erase_8);
+       UNITTEST_DRIVER_REGIST(driver, test_tadfragment_cursor_erase_9);
+}