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