New file.
[m17n/m17n-test.git] / replace.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include <m17n-core.h>
6
7 #define NUM_PROPS 2
8
9 typedef struct
10 {
11   int nchars;
12   int chars[30];
13   char props[30][NUM_PROPS + 1];
14 } Text;
15
16 int chars[] =
17   { 'A', 'B', 'C', 'D',         /* 1-byte */
18     0xA0, 0x100, 0x400,         /* 2-byte */
19     0x800, 0x1000, 0xF000,      /* 3-byte */
20     0x10000, 0x20000            /* 4-byte */
21   };
22
23 int nchars = sizeof (chars) / sizeof (chars[0]);
24
25 struct Log {
26   Text orig;
27   int from, to;
28   Text new;
29 };
30
31 void
32 gen_text (MText *mt, Text *t)
33 {
34   int i;
35
36   mtext_del (mt, 0, mtext_len (mt));
37   memset (t, 0, sizeof (Text));
38   for (i = 0; i < nchars; i++)
39     if (rand () % 2)
40       {
41         mtext_cat_char (mt, chars[i]);
42         t->chars[t->nchars++] = chars[i];
43       }
44   for (i = 0; i < t->nchars; i++)
45     {
46       int nprops = rand () % (NUM_PROPS + 1);
47
48       t->props[i][nprops] = '\0';
49       while (nprops-- > 0)
50         {
51           int val = '0' + rand () % 10;
52
53           mtext_push_prop (mt, i, i + 1, Mt, (void *) val);
54           t->props[i][nprops] = val;
55         }
56     }
57 }
58
59 void
60 text_replace (Text *t1, int from1, int to1, Text *t2, int from2, int to2,
61               struct Log *log)
62 {
63   int len1 = to1 - from1;
64   int len2 = to2 - from2;
65   int i;
66
67   log->orig = *t1;
68   log->from = from1, log->to = to1;
69   log->new.nchars = len2;
70   for (i = 0; i < len2; i++)
71     log->new.chars[i] = t2->chars[from2 + i];
72
73   if (len1 != len2)
74     {
75       memmove (t1->chars + from1 + len2, t1->chars + to1,
76                sizeof (int) * (t1->nchars - to1));
77       memmove (t1->props[from1 + len2], t1->props[to1],
78                (NUM_PROPS + 1) * (t1->nchars - to1));
79     }
80   memcpy (t1->chars + from1, t2->chars + from2,
81           sizeof (int) * len2);
82   if (len1 > 0)
83     {
84       to2 = from1 + len2;
85       for (i = to1; i < to2; i++)
86         memcpy (t1->props[i], t1->props[to1 - 1], NUM_PROPS + 1);
87     }
88   t1->nchars += len2 - len1;
89 }
90
91 void
92 dump_text (const char *prefix, Text *t)
93 {
94   int i;
95
96   printf ("%s", prefix);
97   if (t->nchars == 0)
98     printf (" null text\n");
99   else
100     {
101       for (i = 0; i < t->nchars; i++)
102         printf (" %04X", t->chars[i]);
103       printf ("\n%s", prefix);
104       for (i = 0; i < t->nchars; i++)
105         printf (" %-4s", t->props[i]);
106       printf ("\n");
107     }
108 }
109
110 void
111 dump_mtext (const char *prefix, MText *mt)
112 {
113   int len = mtext_len (mt), i;
114
115   printf ("%s", prefix);
116   for (i = 0; i < len; i++)
117     printf (" %04X", mtext_ref_char (mt, i));
118   printf ("\n%s", prefix);
119   for (i = 0; i < len; i++)
120     {
121       void *values[NUM_PROPS];
122       int j, n;
123
124       n = mtext_get_prop_values (mt, i, Mt, values, NUM_PROPS);      
125       printf (" ");
126       for (j = n - 1; j >= 0; j--)
127         printf ("%c", (int) values[j]);
128       while (n++ < 4)
129         printf (" ");
130     }
131   printf ("\n");
132 }
133
134 void
135 error_exit (int count, struct Log *log, MText *mt, Text *t)
136 {
137   printf ("Count: %d, replace %d-%d with", count, log->from, log->to);
138   dump_text ("", &log->new);
139   dump_text ("Orig:  ", &log->orig);
140   dump_text ("Text:  ", t);
141   dump_mtext ("M-text:", mt);
142   exit (0);
143 }
144
145 int
146 compare (MText *mt, Text *t)
147 {
148   int i;
149
150   if (mtext_len (mt) != t->nchars)
151     return -1;
152   for (i = 0; i < t->nchars; i++)
153     {
154       void *values[NUM_PROPS];
155       int j, n;
156
157       if (mtext_ref_char (mt, i) != t->chars[i])
158         return -1;
159       n = mtext_get_prop_values (mt, i, Mt, values, NUM_PROPS);
160       for (j = 0; j < n; j++)
161         if ((int) values[j] != t->props[i][n - 1 - j])
162           return -1;
163     }
164   return 0;
165 }
166
167 #define DEFAULT_STEP 0x10000
168
169 int
170 main (int argc, char **argv)
171 {
172   MText *mt1, *mt2;
173   Text t1, t2;
174   int len1, len2;
175   int from1, to1, from2, to2;
176   int count;
177   int step = DEFAULT_STEP;
178   struct Log log;
179
180   M17N_INIT ();
181   mt1 = mtext ();
182   mt2 = mtext ();
183
184   {
185     char *stepchar = getenv ("STEP");
186
187     if (stepchar)
188       {
189         step = atoi (stepchar);
190         if (step <= 0)
191           step = DEFAULT_STEP;
192       }
193   }
194
195   for (count = 0; ; count++)
196     {
197       if (((count + 1) % step) == 0)
198         printf ("Count 0x%X\n", count + 1);
199
200       gen_text (mt1, &t1);
201       len1 = t1.nchars;
202       gen_text (mt2, &t2);
203       len2 = t2.nchars;
204
205       if (len1 > 0)
206         from1 = rand () % len1, to1 = from1 + (rand () % (len1 - from1));
207       else
208         from1 = to1 = 0;
209       if (len2 > 0)
210         from2 = rand () % len2, to2 = from2 + (rand () % (len2 - from2));
211       else
212         from2 = to2 = 0;
213       text_replace (&t1, from1, to1, &t2, from2, to2, &log);
214       if (mtext_replace (mt1, from1, to1, mt2, from2, to2) < 0
215           || compare (mt1, &t1) < 0)
216         error_exit (count, &log, mt1, &t1);
217     }
218   exit (0);
219 }