root/branches/dmdfe-2.0/dchar.c

Revision 360, 7.6 kB (checked in by Gregor, 2 years ago)

Initial import.

Line 
1 // Copyright (c) 1999-2006 by Digital Mars
2 // All Rights Reserved
3 // written by Walter Bright
4 // www.digitalmars.com
5 // License for redistribution is by either the Artistic License
6 // in artistic.txt, or the GNU General Public License in gnu.txt.
7 // See the included readme.txt for details.
8
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <stdint.h>
13 #include <assert.h>
14
15 #include "dchar.h"
16 #include "mem.h"
17
18 #if M_UNICODE
19
20 // Converts a char string to Unicode
21
22 dchar *Dchar::dup(char *p)
23 {
24     dchar *s;
25     size_t len;
26
27     if (!p)
28     return NULL;
29     len = strlen(p);
30     s = (dchar *)mem.malloc((len + 1) * sizeof(dchar));
31     for (unsigned i = 0; i < len; i++)
32     {
33     s[i] = (dchar)(p[i] & 0xFF);
34     }
35     s[len] = 0;
36     return s;
37 }
38
39 dchar *Dchar::memchr(dchar *p, int c, int count)
40 {
41     int u;
42
43     for (u = 0; u < count; u++)
44     {
45     if (p[u] == c)
46         return p + u;
47     }
48     return NULL;
49 }
50
51 #if _WIN32 && __DMC__
52 __declspec(naked)
53 unsigned Dchar::calcHash(const dchar *str, unsigned len)
54 {
55     __asm
56     {
57     mov ECX,4[ESP]
58     mov EDX,8[ESP]
59     xor EAX,EAX
60     test    EDX,EDX
61     je  L92
62
63 LC8:    cmp EDX,1
64     je  L98
65     cmp EDX,2
66     je  LAE
67
68     add EAX,[ECX]
69 //  imul    EAX,EAX,025h
70     lea EAX,[EAX][EAX*8]
71     add ECX,4
72     sub EDX,2
73     jmp LC8
74
75 L98:    mov DX,[ECX]
76     and EDX,0FFFFh
77     add EAX,EDX
78     ret
79
80 LAE:    add EAX,[ECX]
81 L92:    ret
82     }
83 }
84 #else
85 hash_t Dchar::calcHash(const dchar *str, size_t len)
86 {
87     unsigned hash = 0;
88
89     for (;;)
90     {
91     switch (len)
92     {
93         case 0:
94         return hash;
95
96         case 1:
97         hash += *(const uint16_t *)str;
98         return hash;
99
100         case 2:
101         hash += *(const uint32_t *)str;
102         return hash;
103
104         default:
105         hash += *(const uint32_t *)str;
106         hash *= 37;
107         str += 2;
108         len -= 2;
109         break;
110     }
111     }
112 }
113 #endif
114
115 hash_t Dchar::icalcHash(const dchar *str, size_t len)
116 {
117     hash_t hash = 0;
118
119     for (;;)
120     {
121     switch (len)
122     {
123         case 0:
124         return hash;
125
126         case 1:
127         hash += *(const uint16_t *)str | 0x20;
128         return hash;
129
130         case 2:
131         hash += *(const uint32_t *)str | 0x200020;
132         return hash;
133
134         default:
135         hash += *(const uint32_t *)str | 0x200020;
136         hash *= 37;
137         str += 2;
138         len -= 2;
139         break;
140     }
141     }
142 }
143
144 #elif MCBS
145
146 hash_t Dchar::calcHash(const dchar *str, size_t len)
147 {
148     hash_t hash = 0;
149
150     while (1)
151     {
152     switch (len)
153     {
154         case 0:
155         return hash;
156
157         case 1:
158         hash *= 37;
159         hash += *(const uint8_t *)str;
160         return hash;
161
162         case 2:
163         hash *= 37;
164         hash += *(const uint16_t *)str;
165         return hash;
166
167         case 3:
168         hash *= 37;
169         hash += (*(const uint16_t *)str << 8) +
170             ((const uint8_t *)str)[2];
171         return hash;
172
173         default:
174         hash *= 37;
175         hash += *(const uint32_t *)str;
176         str += 4;
177         len -= 4;
178         break;
179     }
180     }
181 }
182
183 #elif UTF8
184
185 // Specification is: http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335
186
187 char Dchar::mblen[256] =
188 {
189     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
190     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
191     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
192     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
193     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
194     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
195     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
196     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
197     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
198     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
199     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
200     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
201     2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
202     2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
203     3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
204     4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1,
205 };
206
207 dchar *Dchar::dec(dchar *pstart, dchar *p)
208 {
209     while ((p[-1] & 0xC0) == 0x80)
210     p--;
211     return p;
212 }
213
214 int Dchar::get(dchar *p)
215 {
216     unsigned c;
217     unsigned char *q = (unsigned char *)p;
218
219     c = q[0];
220     switch (mblen[c])
221     {
222     case 2:
223         c = ((c    - 0xC0) << 6) |
224          (q[1] - 0x80);
225         break;
226
227     case 3:
228         c = ((c    - 0xE0) << 12) |
229         ((q[1] - 0x80) <<  6) |
230          (q[2] - 0x80);
231         break;
232
233     case 4:
234         c = ((c    - 0xF0) << 18) |
235         ((q[1] - 0x80) << 12) |
236         ((q[2] - 0x80) <<  6) |
237          (q[3] - 0x80);
238         break;
239
240     case 5:
241         c = ((c    - 0xF8) << 24) |
242         ((q[1] - 0x80) << 18) |
243         ((q[2] - 0x80) << 12) |
244         ((q[3] - 0x80) <<  6) |
245          (q[4] - 0x80);
246         break;
247
248     case 6:
249         c = ((c    - 0xFC) << 30) |
250         ((q[1] - 0x80) << 24) |
251         ((q[2] - 0x80) << 18) |
252         ((q[3] - 0x80) << 12) |
253         ((q[4] - 0x80) <<  6) |
254          (q[5] - 0x80);
255         break;
256     }
257     return c;
258 }
259
260 dchar *Dchar::put(dchar *p, unsigned c)
261 {
262     if (c <= 0x7F)
263     {
264     *p++ = c;
265     }
266     else if (c <= 0x7FF)
267     {
268     p[0] = 0xC0 + (c >> 6);
269     p[1] = 0x80 + (c & 0x3F);
270     p += 2;
271     }
272     else if (c <= 0xFFFF)
273     {
274     p[0] = 0xE0 + (c >> 12);
275     p[1] = 0x80 + ((c >> 6) & 0x3F);
276     p[2] = 0x80 + (c & 0x3F);
277     p += 3;
278     }
279     else if (c <= 0x1FFFFF)
280     {
281     p[0] = 0xF0 + (c >> 18);
282     p[1] = 0x80 + ((c >> 12) & 0x3F);
283     p[2] = 0x80 + ((c >> 6) & 0x3F);
284     p[3] = 0x80 + (c & 0x3F);
285     p += 4;
286     }
287     else if (c <= 0x3FFFFFF)
288     {
289     p[0] = 0xF8 + (c >> 24);
290     p[1] = 0x80 + ((c >> 18) & 0x3F);
291     p[2] = 0x80 + ((c >> 12) & 0x3F);
292     p[3] = 0x80 + ((c >> 6) & 0x3F);
293     p[4] = 0x80 + (c & 0x3F);
294     p += 5;
295     }
296     else if (c <= 0x7FFFFFFF)
297     {
298     p[0] = 0xFC + (c >> 30);
299     p[1] = 0x80 + ((c >> 24) & 0x3F);
300     p[2] = 0x80 + ((c >> 18) & 0x3F);
301     p[3] = 0x80 + ((c >> 12) & 0x3F);
302     p[4] = 0x80 + ((c >> 6) & 0x3F);
303     p[5] = 0x80 + (c & 0x3F);
304     p += 6;
305     }
306     else
307     assert(0);      // not a UCS-4 character
308     return p;
309 }
310
311 hash_t Dchar::calcHash(const dchar *str, size_t len)
312 {
313     hash_t hash = 0;
314
315     while (1)
316     {
317     switch (len)
318     {
319         case 0:
320         return hash;
321
322         case 1:
323         hash *= 37;
324         hash += *(const uint8_t *)str;
325         return hash;
326
327         case 2:
328         hash *= 37;
329 #if __I86__
330         hash += *(const uint16_t *)str;
331 #else
332         hash += str[0] * 256 + str[1];
333 #endif
334         return hash;
335
336         case 3:
337         hash *= 37;
338 #if __I86__
339         hash += (*(const uint16_t *)str << 8) +
340             ((const uint8_t *)str)[2];
341 #else
342         hash += (str[0] * 256 + str[1]) * 256 + str[2];
343 #endif
344         return hash;
345
346         default:
347         hash *= 37;
348 #if __I86__
349         hash += *(const uint32_t *)str;
350 #else
351         hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
352 #endif
353
354         str += 4;
355         len -= 4;
356         break;
357     }
358     }
359 }
360
361 #else // ascii
362
363 hash_t Dchar::calcHash(const dchar *str, size_t len)
364 {
365     hash_t hash = 0;
366
367     while (1)
368     {
369     switch (len)
370     {
371         case 0:
372         return hash;
373
374         case 1:
375         hash *= 37;
376         hash += *(const uint8_t *)str;
377         return hash;
378
379         case 2:
380         hash *= 37;
381 #if __I86__
382         hash += *(const uint16_t *)str;
383 #else
384         hash += str[0] * 256 + str[1];
385 #endif
386         return hash;
387
388         case 3:
389         hash *= 37;
390 #if __I86__
391         hash += (*(const uint16_t *)str << 8) +
392             ((const uint8_t *)str)[2];
393 #else
394         hash += (str[0] * 256 + str[1]) * 256 + str[2];
395 #endif
396         return hash;
397
398         default:
399         hash *= 37;
400 #if __I86__
401         hash += *(const uint32_t *)str;
402 #else
403         hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
404 #endif
405         str += 4;
406         len -= 4;
407         break;
408     }
409     }
410 }
411
412 hash_t Dchar::icalcHash(const dchar *str, size_t len)
413 {
414     hash_t hash = 0;
415
416     while (1)
417     {
418     switch (len)
419     {
420         case 0:
421         return hash;
422
423         case 1:
424         hash *= 37;
425         hash += *(const uint8_t *)str | 0x20;
426         return hash;
427
428         case 2:
429         hash *= 37;
430         hash += *(const uint16_t *)str | 0x2020;
431         return hash;
432
433         case 3:
434         hash *= 37;
435         hash += ((*(const uint16_t *)str << 8) +
436              ((const uint8_t *)str)[2]) | 0x202020;
437         return hash;
438
439         default:
440         hash *= 37;
441         hash += *(const uint32_t *)str | 0x20202020;
442         str += 4;
443         len -= 4;
444         break;
445     }
446     }
447 }
448
449 #endif
450
451 #if 0
452 #include <stdio.h>
453
454 void main()
455 {
456     // Print out values to hardcode into Dchar::mblen[]
457     int c;
458     int s;
459
460     for (c = 0; c < 256; c++)
461     {
462     s = 1;
463     if (c >= 0xC0 && c <= 0xDF)
464         s = 2;
465     if (c >= 0xE0 && c <= 0xEF)
466         s = 3;
467     if (c >= 0xF0 && c <= 0xF7)
468         s = 4;
469     if (c >= 0xF8 && c <= 0xFB)
470         s = 5;
471     if (c >= 0xFC && c <= 0xFD)
472         s = 6;
473
474     printf("%d", s);
475     if ((c & 15) == 15)
476         printf(",\n");
477     else
478         printf(",");
479     }
480 }
481 #endif
Note: See TracBrowser for help on using the browser.