Release 970914
[wine] / memory / string.c
1 /*
2  * String functions
3  *
4  * Copyright 1993 Yngvi Sigurjonsson
5  * Copyright 1996 Alexandre Julliard
6  */
7
8 #include <ctype.h>
9 #include <string.h>
10 #include "windows.h"
11 #include "winerror.h"
12 #include "ldt.h"
13 #include "stddebug.h"
14 #include "debug.h"
15
16 static const BYTE STRING_Oem2Ansi[256] =
17 "\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\244"
18 "\020\021\022\023\266\247\026\027\030\031\032\033\034\035\036\037"
19 "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
20 "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
21 "\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
22 "\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
23 "\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
24 "\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
25 "\307\374\351\342\344\340\345\347\352\353\350\357\356\354\304\305"
26 "\311\346\306\364\366\362\373\371\377\326\334\242\243\245\120\203"
27 "\341\355\363\372\361\321\252\272\277\137\254\275\274\241\253\273"
28 "\137\137\137\246\246\246\246\053\053\246\246\053\053\053\053\053"
29 "\053\055\055\053\055\053\246\246\053\053\055\055\246\055\053\055"
30 "\055\055\055\053\053\053\053\053\053\053\053\137\137\246\137\137"
31 "\137\337\137\266\137\137\265\137\137\137\137\137\137\137\137\137"
32 "\137\261\137\137\137\137\367\137\260\225\267\137\156\262\137\137";
33
34 static const BYTE STRING_Ansi2Oem[256] =
35 "\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017"
36 "\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
37 "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
38 "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
39 "\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
40 "\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
41 "\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
42 "\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
43 "\200\201\054\237\054\137\375\374\210\045\123\074\117\215\216\217"
44 "\220\140\047\042\042\371\055\137\230\231\163\076\157\235\236\131"
45 "\040\255\233\234\017\235\335\025\042\143\246\256\252\055\162\137"
46 "\370\361\375\063\047\346\024\372\054\061\247\257\254\253\137\250"
47 "\101\101\101\101\216\217\222\200\105\220\105\105\111\111\111\111"
48 "\104\245\117\117\117\117\231\170\117\125\125\125\232\131\137\341"
49 "\205\240\203\141\204\206\221\207\212\202\210\211\215\241\214\213"
50 "\144\244\225\242\223\157\224\366\157\227\243\226\201\171\137\230";
51
52 #define OEM_TO_ANSI(ch) (STRING_Oem2Ansi[(unsigned char)(ch)])
53 #define ANSI_TO_OEM(ch) (STRING_Ansi2Oem[(unsigned char)(ch)])
54
55
56 /***********************************************************************
57  *           hmemcpy   (KERNEL.348)
58  */
59 void WINAPI hmemcpy( LPVOID dst, LPCVOID src, LONG count )
60 {
61     memcpy( dst, src, count );
62 }
63
64
65 /***********************************************************************
66  *           lstrcat16   (KERNEL.89)
67  */
68 SEGPTR WINAPI lstrcat16( SEGPTR dst, LPCSTR src )
69 {
70     lstrcat32A( (LPSTR)PTR_SEG_TO_LIN(dst), src );
71     return dst;
72 }
73
74
75 /***********************************************************************
76  *           lstrcat32A   (KERNEL32.599)
77  */
78 LPSTR WINAPI lstrcat32A( LPSTR dst, LPCSTR src )
79 {
80     dprintf_string(stddeb,"strcat: Append '%s' to '%s'\n",
81                  (src)?src:"NULL",(dst)?dst:"NULL");
82     strcat( dst, src );
83     return dst;
84 }
85
86
87 /***********************************************************************
88  *           lstrcat32W   (KERNEL32.600)
89  */
90 LPWSTR WINAPI lstrcat32W( LPWSTR dst, LPCWSTR src )
91 {
92     register LPWSTR p = dst;
93     while (*p) p++;
94     while ((*p++ = *src++));
95     return dst;
96 }
97
98
99 /***********************************************************************
100  *           lstrcatn16   (KERNEL.352)
101  */
102 SEGPTR WINAPI lstrcatn16( SEGPTR dst, LPCSTR src, INT16 n )
103 {
104     lstrcatn32A( (LPSTR)PTR_SEG_TO_LIN(dst), src, n );
105     return dst;
106 }
107
108
109 /***********************************************************************
110  *           lstrcatn32A   (Not a Windows API)
111  */
112 LPSTR WINAPI lstrcatn32A( LPSTR dst, LPCSTR src, INT32 n )
113 {
114     register LPSTR p = dst;
115     dprintf_string(stddeb,"strcatn add %d chars from '%s' to '%s'\n",
116                  n,(src)?src:"NULL",(dst)?dst:"NULL");
117     while (*p) p++;
118     if ((n -= (INT32)(p - dst)) <= 0) return dst;
119     lstrcpyn32A( p, src, n );
120     return dst;
121 }
122
123
124 /***********************************************************************
125  *           lstrcatn32W   (Not a Windows API)
126  */
127 LPWSTR WINAPI lstrcatn32W( LPWSTR dst, LPCWSTR src, INT32 n )
128 {
129     register LPWSTR p = dst;
130     while (*p) p++;
131     if ((n -= (INT32)(p - dst)) <= 0) return dst;
132     lstrcpyn32W( p, src, n );
133     return dst;
134 }
135
136
137 /***********************************************************************
138  *           lstrcmp16   (USER.430)
139  */
140 INT16 WINAPI lstrcmp16( LPCSTR str1, LPCSTR str2 )
141 {
142     return (INT16)lstrcmp32A( str1, str2 );
143 }
144
145
146 /***********************************************************************
147  *           lstrcmp32A   (KERNEL.602)
148  */
149 INT32 WINAPI lstrcmp32A( LPCSTR str1, LPCSTR str2 )
150 {
151     /* Win95 KERNEL32.DLL does it that way. Hands off! */
152     if (!str1 || !str2) {
153         SetLastError(ERROR_INVALID_PARAMETER);
154         return 0;
155     }
156
157     dprintf_string(stddeb,"strcmp: '%s' and '%s'\n",
158                  (str1)?str1:"NULL",(str2)?str2:"NULL");
159     return (INT32)strcmp( str1, str2 );
160 }
161
162
163 /***********************************************************************
164  *           lstrcmp32W   (KERNEL.603)
165  */
166 INT32 WINAPI lstrcmp32W( LPCWSTR str1, LPCWSTR str2 )
167 {
168     if (!str1 || !str2) {
169         SetLastError(ERROR_INVALID_PARAMETER);
170         return 0;
171     }
172     while (*str1 && (*str1 == *str2)) { str1++; str2++; }
173     return (INT32)(*str1 - *str2);
174 }
175
176
177 /***********************************************************************
178  *           lstrcmpi16   (USER.471)
179  */
180 INT16 WINAPI lstrcmpi16( LPCSTR str1, LPCSTR str2 )
181 {
182     return (INT16)lstrcmpi32A( str1, str2 );
183 }
184
185
186 /***********************************************************************
187  *           lstrcmpi32A   (KERNEL32.605)
188  */
189 INT32 WINAPI lstrcmpi32A( LPCSTR str1, LPCSTR str2 )
190 {
191     INT32 res;
192
193     if (!str1 || !str2) {
194         SetLastError(ERROR_INVALID_PARAMETER);
195         return 0;
196     }
197     dprintf_string(stddeb,"strcmpi '%s' and '%s'\n",
198                  (str1)?str1:"NULL",(str2)?str2:"NULL");
199     while (*str1)
200     {
201         if ((res = toupper(*str1) - toupper(*str2)) != 0) return res;
202         str1++;
203         str2++;
204     }
205     return toupper(*str1) - toupper(*str2);
206 }
207
208
209 /***********************************************************************
210  *           lstrcmpi32W   (KERNEL32.606)
211  */
212 INT32 WINAPI lstrcmpi32W( LPCWSTR str1, LPCWSTR str2 )
213 {
214     INT32 res;
215
216     if (!str1 || !str2) {
217         SetLastError(ERROR_INVALID_PARAMETER);
218         return 0;
219     }
220     while (*str1)
221     {
222         /* FIXME: Unicode */
223         if ((res = toupper(*str1) - toupper(*str2)) != 0) return res;
224         str1++;
225         str2++;
226     }
227     return toupper(*str1) - toupper(*str2);
228 }
229
230
231 /***********************************************************************
232  *           lstrcpy16   (KERNEL.88)
233  */
234 SEGPTR WINAPI lstrcpy16( SEGPTR dst, LPCSTR src )
235 {
236     lstrcpy32A( (LPSTR)PTR_SEG_TO_LIN(dst), src );
237     return dst;
238 }
239
240
241 /***********************************************************************
242  *           lstrcpy32A   (KERNEL32.608)
243  */
244 LPSTR WINAPI lstrcpy32A( LPSTR dst, LPCSTR src )
245 {
246     dprintf_string(stddeb,"strcpy '%s'\n",
247                  (src)?src:"NULL");
248     if (!src || !dst) return NULL;
249     strcpy( dst, src );
250     return dst;
251 }
252
253
254 /***********************************************************************
255  *           lstrcpy32W   (KERNEL32.609)
256  */
257 LPWSTR WINAPI lstrcpy32W( LPWSTR dst, LPCWSTR src )
258 {
259     register LPWSTR p = dst;
260     while ((*p++ = *src++));
261     return dst;
262 }
263
264
265 /***********************************************************************
266  *           lstrcpyn16   (KERNEL.353)
267  */
268 SEGPTR WINAPI lstrcpyn16( SEGPTR dst, LPCSTR src, INT16 n )
269 {
270     lstrcpyn32A( (LPSTR)PTR_SEG_TO_LIN(dst), src, n );
271     return dst;
272 }
273
274
275 /***********************************************************************
276  *           lstrcpyn32A   (KERNEL32.611)
277  */
278 LPSTR WINAPI lstrcpyn32A( LPSTR dst, LPCSTR src, INT32 n )
279 {
280     LPSTR p = dst;
281     dprintf_string(stddeb,"strcpyn '%s' for %d chars\n",
282                  (src)?src:"NULL",n);
283     while ((n-- > 1) && *src) *p++ = *src++;
284     *p = 0;
285     return dst;
286 }
287
288
289 /***********************************************************************
290  *           lstrcpyn32W   (KERNEL32.612)
291  */
292 LPWSTR WINAPI lstrcpyn32W( LPWSTR dst, LPCWSTR src, INT32 n )
293 {
294     LPWSTR p = dst;
295     while ((n-- > 1) && *src) *p++ = *src++;
296     *p = 0;
297     return dst;
298 }
299
300
301 /***********************************************************************
302  *           lstrlen16   (KERNEL.90)
303  */
304 INT16 WINAPI lstrlen16( LPCSTR str )
305 {
306     return (INT16)lstrlen32A( str );
307 }
308
309
310 /***********************************************************************
311  *           lstrlen32A   (KERNEL32.614)
312  */
313 INT32 WINAPI lstrlen32A( LPCSTR str )
314 {
315     /* looks weird, but win3.1 KERNEL got a GeneralProtection handler
316      * in lstrlen() ... we check only for NULL pointer reference.
317      * - Marcus Meissner
318      */
319     dprintf_string(stddeb,"strlen '%s'\n", (str)?str:"NULL");
320     if (!str) return 0;
321     return (INT32)strlen(str);
322 }
323
324
325 /***********************************************************************
326  *           lstrlen32W   (KERNEL32.615)
327  */
328 INT32 WINAPI lstrlen32W( LPCWSTR str )
329 {
330     INT32 len = 0;
331     if (!str) return 0;
332     while (*str++) len++;
333     return len;
334 }
335
336
337 /***********************************************************************
338  *           lstrncmp32A   (Not a Windows API)
339  */
340 INT32 WINAPI lstrncmp32A( LPCSTR str1, LPCSTR str2, INT32 n )
341 {
342     dprintf_string(stddeb,"strncmp '%s' and '%s' for %d chars\n",
343                  (str1)?str1:"NULL",(str2)?str2:"NULL",n);
344     return (INT32)strncmp( str1, str2, n );
345 }
346
347
348 /***********************************************************************
349  *           lstrncmp32W   (Not a Windows API)
350  */
351 INT32 WINAPI lstrncmp32W( LPCWSTR str1, LPCWSTR str2, INT32 n )
352 {
353     if (!n) return 0;
354     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
355     return (INT32)(*str1 - *str2);
356 }
357
358
359 /***********************************************************************
360  *           lstrncmpi32A   (Not a Windows API)
361  */
362 INT32 WINAPI lstrncmpi32A( LPCSTR str1, LPCSTR str2, INT32 n )
363 {
364     INT32 res;
365
366     dprintf_string(stddeb,"strncmpi '%s' and '%s' for %d chars\n",
367                  (str1)?str1:"NULL",(str2)?str2:"NULL",n);
368     if (!n) return 0;
369     while ((--n > 0) && *str1)
370       if ( (res = toupper(*str1++) - toupper(*str2++)) ) return res;
371
372     return toupper(*str1) - toupper(*str2);
373 }
374
375
376 /***********************************************************************
377  *           lstrncmpi32W   (Not a Windows API)
378  */
379 INT32 WINAPI lstrncmpi32W( LPCWSTR str1, LPCWSTR str2, INT32 n )
380 {
381     INT32 res;
382
383     if (!n) return 0;
384     while ((--n > 0) && *str1)
385     {
386         /* FIXME: Unicode */
387         if ((res = toupper(*str1) - toupper(*str2)) != 0) return res;
388         str1++;
389         str2++;
390     }
391     return toupper(*str1) - toupper(*str2);
392 }
393
394
395 /***********************************************************************
396  *           lstrcpyAtoW   (Not a Windows API)
397  */
398 LPWSTR WINAPI lstrcpyAtoW( LPWSTR dst, LPCSTR src )
399 {
400     register LPWSTR p = dst;
401     while ((*p++ = (WCHAR)(unsigned char)*src++));
402     return dst;
403 }
404
405
406 /***********************************************************************
407  *           lstrcpyWtoA   (Not a Windows API)
408  */
409 LPSTR WINAPI lstrcpyWtoA( LPSTR dst, LPCWSTR src )
410 {
411     register LPSTR p = dst;
412     while ((*p++ = (CHAR)*src++));
413     return dst;
414 }
415
416
417 /***********************************************************************
418  *           lstrcpynAtoW   (Not a Windows API)
419  */
420 LPWSTR WINAPI lstrcpynAtoW( LPWSTR dst, LPCSTR src, INT32 n )
421 {
422     LPWSTR p = dst;
423     while ((n-- > 1) && *src) *p++ = (WCHAR)(unsigned char)*src++;
424     *p = 0;
425     return dst;
426 }
427
428
429 /***********************************************************************
430  *           lstrcpynWtoA   (Not a Windows API)
431  */
432 LPSTR WINAPI lstrcpynWtoA( LPSTR dst, LPCWSTR src, INT32 n )
433 {
434     LPSTR p = dst;
435     while ((n-- > 1) && *src) *p++ = (CHAR)*src++;
436     *p = 0;
437     return dst;
438 }
439
440
441 /***********************************************************************
442  *           Copy   (GDI.250)
443  */
444 void WINAPI Copy( LPVOID src, LPVOID dst, WORD size )
445 {
446     memcpy( dst, src, size );
447 }
448
449
450 /***********************************************************************
451  *           RtlFillMemory   (KERNEL32.441)
452  */
453 VOID WINAPI RtlFillMemory( LPVOID ptr, UINT32 len, UINT32 fill )
454 {
455     memset( ptr, fill, len );
456 }
457
458
459 /***********************************************************************
460  *           RtlMoveMemory   (KERNEL32.442)
461  */
462 VOID WINAPI RtlMoveMemory( LPVOID dst, LPCVOID src, UINT32 len )
463 {
464     memmove( dst, src, len );
465 }
466
467
468 /***********************************************************************
469  *           RtlZeroMemory   (KERNEL32.444)
470  */
471 VOID WINAPI RtlZeroMemory( LPVOID ptr, UINT32 len )
472 {
473     memset( ptr, 0, len );
474 }
475
476
477 /***********************************************************************
478  *           AnsiToOem16   (KEYBOARD.5)
479  */
480 INT16 WINAPI AnsiToOem16( LPCSTR s, LPSTR d )
481 {
482     CharToOem32A( s, d );
483     return -1;
484 }
485
486
487 /***********************************************************************
488  *           OemToAnsi16   (KEYBOARD.6)
489  */
490 INT16 WINAPI OemToAnsi16( LPCSTR s, LPSTR d )
491 {
492     OemToChar32A( s, d );
493     return -1;
494 }
495
496
497 /***********************************************************************
498  *           AnsiToOemBuff16   (KEYBOARD.134)
499  */
500 void WINAPI AnsiToOemBuff16( LPCSTR s, LPSTR d, UINT16 len )
501 {
502     CharToOemBuff32A( s, d, len ? len : 65536 );
503 }
504
505
506 /***********************************************************************
507  *           OemToAnsiBuff16   (KEYBOARD.135)
508  */
509 void WINAPI OemToAnsiBuff16( LPCSTR s, LPSTR d, UINT16 len )
510 {
511     OemToCharBuff32A( s, d, len ? len : 65536 );
512 }
513
514
515 /***********************************************************************
516  *           CharToOem32A   (USER32.36)
517  */
518 BOOL32 WINAPI CharToOem32A( LPCSTR s, LPSTR d )
519 {
520     if (!s || !d) return TRUE;
521     dprintf_string(stddeb,"CharToOem '%s'\n", (s)?s:"NULL");
522     while ((*d++ = ANSI_TO_OEM(*s++)));
523     dprintf_string(stddeb," to '%s'\n", (d)?d:"NULL");
524     return TRUE;
525 }
526
527
528 /***********************************************************************
529  *           CharToOemBuff32A   (USER32.37)
530  */
531 BOOL32 WINAPI CharToOemBuff32A( LPCSTR s, LPSTR d, DWORD len )
532 {
533     while (len--) *d++ = ANSI_TO_OEM(*s++);
534     return TRUE;
535 }
536
537
538 /***********************************************************************
539  *           CharToOemBuff32W   (USER32.38)
540  */
541 BOOL32 WINAPI CharToOemBuff32W( LPCWSTR s, LPSTR d, DWORD len )
542 {
543     while (len--) *d++ = ANSI_TO_OEM(*s++);
544     return TRUE;
545 }
546
547
548 /***********************************************************************
549  *           CharToOem32W   (USER32.39)
550  */
551 BOOL32 WINAPI CharToOem32W( LPCWSTR s, LPSTR d )
552 {
553     while ((*d++ = ANSI_TO_OEM(*s++)));
554     return TRUE;
555 }
556
557
558 /***********************************************************************
559  *           OemToChar32A   (USER32.401)
560  */
561 BOOL32 WINAPI OemToChar32A( LPCSTR s, LPSTR d )
562 {
563     dprintf_string(stddeb,"OemToChar '%s'\n", (s)?s:"NULL");
564     while ((*d++ = OEM_TO_ANSI(*s++)));
565     dprintf_string(stddeb," to '%s'\n", (d)?d:"NULL");
566     return TRUE;
567 }
568
569
570 /***********************************************************************
571  *           OemToCharBuff32A   (USER32.402)
572  */
573 BOOL32 WINAPI OemToCharBuff32A( LPCSTR s, LPSTR d, DWORD len )
574 {
575     dprintf_string(stddeb,"OemToCharBuff '%s' for %ld chars\n", (s)?s:"NULL",len);
576     while (len--) *d++ = OEM_TO_ANSI(*s++);
577     return TRUE;
578 }
579
580
581 /***********************************************************************
582  *           OemToCharBuff32W   (USER32.403)
583  */
584 BOOL32 WINAPI OemToCharBuff32W( LPCSTR s, LPWSTR d, DWORD len )
585 {
586     while (len--) *d++ = (WCHAR)OEM_TO_ANSI(*s++);
587     return TRUE;
588 }
589
590
591 /***********************************************************************
592  *           OemToChar32W   (USER32.404)
593  */
594 BOOL32 WINAPI OemToChar32W( LPCSTR s, LPWSTR d )
595 {
596     while ((*d++ = (WCHAR)OEM_TO_ANSI(*s++)));
597     return TRUE;
598 }