1 /**
2  * Part of the D programming language runtime library.
3  */
4 
5 /*
6  *  Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
7  *  Written by Walter Bright
8  *
9  *  This software is provided 'as-is', without any express or implied
10  *  warranty. In no event will the authors be held liable for any damages
11  *  arising from the use of this software.
12  *
13  *  Permission is granted to anyone to use this software for any purpose,
14  *  including commercial applications, and to alter it and redistribute it
15  *  freely, in both source and binary form, subject to the following
16  *  restrictions:
17  *
18  *  o  The origin of this software must not be misrepresented; you must not
19  *     claim that you wrote the original software. If you use this software
20  *     in a product, an acknowledgment in the product documentation would be
21  *     appreciated but is not required.
22  *  o  Altered source versions must be plainly marked as such, and must not
23  *     be misrepresented as being the original software.
24  *  o  This notice may not be removed or altered from any source
25  *     distribution.
26  */
27 
28 module rt.compiler.gdc.rt.aApply;
29 
30 /*
31  *  Modified by Sean Kelly <sean@f4.ca> for use with Tango.
32  */
33 
34 /* This code handles decoding UTF strings for foreach loops.
35  * There are 6 combinations of conversions between char, wchar,
36  * and dchar, and 2 of each of those.
37  */
38 
39 private import rt.compiler.util.utf;
40 
41 /**********************************************
42  */
43 
44 // dg is D, but _aApplycd() is C
45 extern (D) typedef int delegate(void *) dg_t;
46 
47 extern (C) int _aApplycd1(char[] aa, dg_t dg)
48 {   int result;
49     size_t i;
50     size_t len = aa.length;
51 
52     debug(apply) printf("_aApplycd1(), len = %d\n", len);
53     for (i = 0; i < len; )
54     {   dchar d;
55 
56         d = aa[i];
57         if (d & 0x80)
58             d = decode(aa, i);
59         else
60             i++;
61         result = dg(cast(void *)&d);
62         if (result)
63             break;
64     }
65     return result;
66 }
67 
68 extern (C) int _aApplywd1(wchar[] aa, dg_t dg)
69 {   int result;
70     size_t i;
71     size_t len = aa.length;
72 
73     debug(apply) printf("_aApplywd1(), len = %d\n", len);
74     for (i = 0; i < len; )
75     {   dchar d;
76 
77         d = aa[i];
78         if (d & ~0x7F)
79             d = decode(aa, i);
80         else
81             i++;
82         result = dg(cast(void *)&d);
83         if (result)
84             break;
85     }
86     return result;
87 }
88 
89 extern (C) int _aApplycw1(char[] aa, dg_t dg)
90 {   int result;
91     size_t i;
92     size_t len = aa.length;
93 
94     debug(apply) printf("_aApplycw1(), len = %d\n", len);
95     for (i = 0; i < len; )
96     {   dchar d;
97         wchar w;
98 
99         w = aa[i];
100         if (w & 0x80)
101         {   d = decode(aa, i);
102             if (d <= 0xFFFF)
103                 w = cast(wchar) d;
104             else
105             {
106                 w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
107                 result = dg(cast(void *)&w);
108                 if (result)
109                     break;
110                 w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00);
111             }
112         }
113         else
114             i++;
115         result = dg(cast(void *)&w);
116         if (result)
117             break;
118     }
119     return result;
120 }
121 
122 extern (C) int _aApplywc1(wchar[] aa, dg_t dg)
123 {   int result;
124     size_t i;
125     size_t len = aa.length;
126 
127     debug(apply) printf("_aApplywc1(), len = %d\n", len);
128     for (i = 0; i < len; )
129     {   dchar d;
130         wchar w;
131         char c;
132 
133         w = aa[i];
134         if (w & ~0x7F)
135         {
136             char[4] buf;
137 
138             d = decode(aa, i);
139             auto b = toUTF8(buf, d);
140             foreach (char c2; b)
141             {
142                 result = dg(cast(void *)&c2);
143                 if (result)
144                     return result;
145             }
146             continue;
147         }
148         else
149         {   c = cast(char)w;
150             i++;
151         }
152         result = dg(cast(void *)&c);
153         if (result)
154             break;
155     }
156     return result;
157 }
158 
159 extern (C) int _aApplydc1(dchar[] aa, dg_t dg)
160 {   int result;
161 
162     debug(apply) printf("_aApplydc1(), len = %d\n", aa.length);
163     foreach (dchar d; aa)
164     {
165         char c;
166 
167         if (d & ~0x7F)
168         {
169             char[4] buf;
170 
171             auto b = toUTF8(buf, d);
172             foreach (char c2; b)
173             {
174                 result = dg(cast(void *)&c2);
175                 if (result)
176                     return result;
177             }
178             continue;
179         }
180         else
181         {
182             c = cast(char)d;
183         }
184         result = dg(cast(void *)&c);
185         if (result)
186             break;
187     }
188     return result;
189 }
190 
191 extern (C) int _aApplydw1(dchar[] aa, dg_t dg)
192 {   int result;
193 
194     debug(apply) printf("_aApplydw1(), len = %d\n", aa.length);
195     foreach (dchar d; aa)
196     {
197         wchar w;
198 
199         if (d <= 0xFFFF)
200             w = cast(wchar) d;
201         else
202         {
203             w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
204             result = dg(cast(void *)&w);
205             if (result)
206                 break;
207             w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00);
208         }
209         result = dg(cast(void *)&w);
210         if (result)
211             break;
212     }
213     return result;
214 }
215 
216 
217 /****************************************************************************/
218 
219 // dg is D, but _aApplycd2() is C
220 extern (D) typedef int delegate(void *, void *) dg2_t;
221 
222 extern (C) int _aApplycd2(char[] aa, dg2_t dg)
223 {   int result;
224     size_t i;
225     size_t n;
226     size_t len = aa.length;
227 
228     debug(apply) printf("_aApplycd2(), len = %d\n", len);
229     for (i = 0; i < len; i += n)
230     {   dchar d;
231 
232         d = aa[i];
233         if (d & 0x80)
234         {
235             n = i;
236             d = decode(aa, n);
237             n -= i;
238         }
239         else
240             n = 1;
241         result = dg(&i, cast(void *)&d);
242         if (result)
243             break;
244     }
245     return result;
246 }
247 
248 extern (C) int _aApplywd2(wchar[] aa, dg2_t dg)
249 {   int result;
250     size_t i;
251     size_t n;
252     size_t len = aa.length;
253 
254     debug(apply) printf("_aApplywd2(), len = %d\n", len);
255     for (i = 0; i < len; i += n)
256     {   dchar d;
257 
258         d = aa[i];
259         if (d & ~0x7F)
260         {
261             n = i;
262             d = decode(aa, n);
263             n -= i;
264         }
265         else
266             n = 1;
267         result = dg(&i, cast(void *)&d);
268         if (result)
269             break;
270     }
271     return result;
272 }
273 
274 extern (C) int _aApplycw2(char[] aa, dg2_t dg)
275 {   int result;
276     size_t i;
277     size_t n;
278     size_t len = aa.length;
279 
280     debug(apply) printf("_aApplycw2(), len = %d\n", len);
281     for (i = 0; i < len; i += n)
282     {   dchar d;
283         wchar w;
284 
285         w = aa[i];
286         if (w & 0x80)
287         {   n = i;
288             d = decode(aa, n);
289             n -= i;
290             if (d <= 0xFFFF)
291                 w = cast(wchar) d;
292             else
293             {
294                 w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
295                 result = dg(&i, cast(void *)&w);
296                 if (result)
297                     break;
298                 w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
299             }
300         }
301         else
302             n = 1;
303         result = dg(&i, cast(void *)&w);
304         if (result)
305             break;
306     }
307     return result;
308 }
309 
310 extern (C) int _aApplywc2(wchar[] aa, dg2_t dg)
311 {   int result;
312     size_t i;
313     size_t n;
314     size_t len = aa.length;
315 
316     debug(apply) printf("_aApplywc2(), len = %d\n", len);
317     for (i = 0; i < len; i += n)
318     {   dchar d;
319         wchar w;
320         char c;
321 
322         w = aa[i];
323         if (w & ~0x7F)
324         {
325             char[4] buf;
326 
327             n = i;
328             d = decode(aa, n);
329             n -= i;
330             auto b = toUTF8(buf, d);
331             foreach (char c2; b)
332             {
333                 result = dg(&i, cast(void *)&c2);
334                 if (result)
335                     return result;
336             }
337             continue;
338         }
339         else
340         {   c = cast(char)w;
341             n = 1;
342         }
343         result = dg(&i, cast(void *)&c);
344         if (result)
345             break;
346     }
347     return result;
348 }
349 
350 extern (C) int _aApplydc2(dchar[] aa, dg2_t dg)
351 {   int result;
352     size_t i;
353     size_t len = aa.length;
354 
355     debug(apply) printf("_aApplydc2(), len = %d\n", len);
356     for (i = 0; i < len; i++)
357     {   dchar d;
358         char c;
359 
360         d = aa[i];
361         if (d & ~0x7F)
362         {
363             char[4] buf;
364 
365             auto b = toUTF8(buf, d);
366             foreach (char c2; b)
367             {
368                 result = dg(&i, cast(void *)&c2);
369                 if (result)
370                     return result;
371             }
372             continue;
373         }
374         else
375         {   c = cast(char)d;
376         }
377         result = dg(&i, cast(void *)&c);
378         if (result)
379             break;
380     }
381     return result;
382 }
383 
384 extern (C) int _aApplydw2(dchar[] aa, dg2_t dg)
385 {   int result;
386 
387     debug(apply) printf("_aApplydw2(), len = %d\n", aa.length);
388     foreach (size_t i, dchar d; aa)
389     {
390         wchar w;
391         auto j = i;
392 
393         if (d <= 0xFFFF)
394             w = cast(wchar) d;
395         else
396         {
397             w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
398             result = dg(&j, cast(void *)&w);
399             if (result)
400                 break;
401             w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
402         }
403         result = dg(&j, cast(void *)&w);
404         if (result)
405             break;
406     }
407     return result;
408 }