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