This commit was generated by cvs2svn to compensate for changes in r52,
[reactos.git] / reactos / ntoskrnl / rtl / wstring.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/rtl/wstring.c
5 * PURPOSE: Wide string functions
6 * PROGRAMMER: David Welch (welch@mcmail.com)
7 * UPDATE HISTORY:
8 * Created 22/05/98
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ddk/ntddk.h>
14 #include <wstring.h>
15
16 #include <internal/debug.h>
17
18 /* FUNCTIONS *****************************************************************/
19
20 wchar_t * wcsncat(wchar_t * dest,const wchar_t * src,size_t count)
21 {
22 int i,j;
23
24 for (j=0;dest[j]!=0;j++);
25 for (i=0;i<count;i++)
26 {
27 dest[j+i] = src[i];
28 if (src[i] == 0)
29 {
30 return(dest);
31 }
32 }
33 dest[j+i]=0;
34 return(dest);
35 }
36
37 wchar_t * wcsncpy(wchar_t * dest,const wchar_t *src,size_t count)
38 {
39 int i;
40
41 for (i=0;i<count;i++)
42 {
43 dest[i] = src[i];
44 if (src[i] == 0)
45 {
46 return(dest);
47 }
48 }
49 dest[i]=0;
50 return(dest);
51 }
52
53 wchar_t* wcsrchr(const wchar_t* str, wchar_t ch)
54 {
55 unsigned int len = 0;
56 while (str[len]!=((wchar_t)0))
57 {
58 len++;
59 }
60
61 for (;len>0;len--)
62 {
63 if (str[len-1]==ch)
64 {
65 return(&str[len-1]);
66 }
67 }
68 return(NULL);
69 }
70
71 wchar_t* wcschr(wchar_t* str, wchar_t ch)
72 {
73 while ((*str)!=((wchar_t)0))
74 {
75 if ((*str)==ch)
76 {
77 return(str);
78 }
79 str++;
80 }
81 return(NULL);
82 }
83
84 wchar_t * wcscpy(wchar_t * str1,const wchar_t * str2)
85 {
86 while ( (*str1)==(*str2) )
87 {
88 str1++;
89 str2++;
90 if ( (*str1)==((wchar_t)0) && (*str1)==((wchar_t)0) )
91 {
92 return(0);
93 }
94 }
95 return( (*str1) - (*str2) );
96 }
97
98 unsigned long wstrlen(PWSTR s)
99 {
100 WCHAR c=' ';
101 unsigned int len=0;
102
103 while(c!=0) {
104 c=*s;
105 s++;
106 len++;
107 };
108 s-=len;
109
110 return len-1;
111 }
112
113 inline int wcscmp(const wchar_t* cs,const wchar_t * ct)
114 {
115 register int __res;
116 __asm__ __volatile__(
117 "cld\n"
118 "1:\tlodsw\n\t"
119 "scasw\n\t"
120 "jne 2f\n\t"
121 "testw %%eax,%%eax\n\t"
122 "jne 1b\n\t"
123 "xorl %%eax,%%eax\n\t"
124 "jmp 3f\n"
125 "2:\tsbbl %%eax,%%eax\n\t"
126 "orw $1,%%eax\n"
127 "3:"
128 :"=a" (__res):"S" (cs),"D" (ct):"esi","edi");
129 return __res;
130 }
131
132 #ifdef __MACHINE_STRING_FUNCTIONS
133 /*
134 * Include machine specific inline routines
135 */
136 //#ifndef _I386_STRING_H_
137 //#define _I386_STRING_H_
138
139 /*
140 * On a 486 or Pentium, we are better off not using the
141 * byte string operations. But on a 386 or a PPro the
142 * byte string ops are faster than doing it by hand
143 * (MUCH faster on a Pentium).
144 *
145 * Also, the byte strings actually work correctly. Forget
146 * the i486 routines for now as they may be broken..
147 */
148
149 #if FIXED_486_STRING && (CPU == 486 || CPU == 586)
150 #include <asm/string-486.h>
151 #else
152
153 /*
154 * This string-include defines all string functions as inline
155 * functions. Use gcc. It also assumes ds=es=data space, this should be
156 * normal. Most of the string-functions are rather heavily hand-optimized,
157 * see especially wcstok,wcsstr,wcs[c]spn. They should work, but are not
158 * very easy to understand. Everything is done entirely within the register
159 * set, making the functions fast and clean. String instructions have been
160 * used through-out, making for "slightly" unclear code :-)
161 *
162 * Copyright (C) 1991, 1992 Linus Torvalds
163 */
164
165
166
167 #define __HAVE_ARCH_WCSCPY
168 extern inline wchar_t * wcscpy(wchar_t * dest,const wchar_t *src)
169 {
170 __asm__ __volatile__(
171 "cld\n"
172 "1:\tlodsw\n\t"
173 "stosw\n\t"
174 "testw %%eax,%%eax\n\t"
175 "jne 1b"
176 : /* no output */
177 :"S" (src),"D" (dest):"esi","edi","eax","memory");
178 return dest;
179 }
180
181 #define __HAVE_ARCH_WCSNCPY
182 inline wchar_t * wcsncpy(wchar_t * dest,const wchar_t *src,size_t count)
183 {
184 __asm__ __volatile__(
185 "cld\n"
186 "1:\tdecl %2\n\t"
187 "js 2f\n\t"
188 "lodsw\n\t"
189 "stosw\n\t"
190 "testw %%eax,%%eax\n\t"
191 "jne 1b\n\t"
192 "rep\n\t"
193 "stosw\n"
194 "2:"
195 : /* no output */
196 :"S" (src),"D" (dest),"c" (count):"esi","edi","eax","ecx","memory");
197 return dest;
198 }
199
200 #define __HAVE_ARCH_WCSCAT
201 inline wchar_t * wcscat(wchar_t * dest,const wchar_t * src)
202 {
203 __asm__ __volatile__(
204 "cld\n\t"
205 "repnz\n\t"
206 "scasw\n\t"
207 "decl %1\n"
208 "decl %1\n\t"
209 "1:\tlodsw\n\t"
210 "stosw\n\t"
211 "testw %%eax,%%eax\n\t"
212 "jne 1b"
213 : /* no output */
214 :"S" (src),"D" (dest),"a" (0),"c" (0xffffffff):"esi","edi","eax","ecx");
215 return dest;
216 }
217
218 #define __HAVE_ARCH_WCSNCAT
219 inline wchar_t * wcsncat(wchar_t * dest,const wchar_t * src,size_t count)
220 {
221 __asm__ __volatile__(
222 "cld\n\t"
223 "repnz\n\t"
224 "scasw\n\t"
225 "decl %1\n\t"
226 "movl %4,%3\n"
227 "decl %1\n\t"
228 "1:\tdecl %3\n\t"
229 "js 2f\n\t"
230 "lodsw\n\t"
231 "stosw\n\t"
232 "testw %%eax,%%eax\n\t"
233 "jne 1b\n"
234 "2:\txorl %2,%2\n\t"
235 "stosw"
236 : /* no output */
237 :"S" (src),"D" (dest),"a" (0),"c" (0xffffffff),"g" (count)
238 :"esi","edi","eax","ecx","memory");
239 return dest;
240 }
241
242 #define __HAVE_ARCH_WCSCMP
243
244 #define __HAVE_ARCH_WCSNCMP
245 inline int wcsncmp(const wchar_t * cs,const wchar_t * ct,size_t count)
246 {
247 register int __res;
248 __asm__ __volatile__(
249 "cld\n"
250 "1:\tdecl %3\n\t"
251 "js 2f\n\t"
252 "lodsw\n\t"
253 "scasw\n\t"
254 "jne 3f\n\t"
255 "testw %%eax,%%eax\n\t"
256 "jne 1b\n"
257 "2:\txorl %%eax,%%eax\n\t"
258 "jmp 4f\n"
259 "3:\tsbbl %%eax,%%eax\n\t"
260 "orw $1,%%eax\n"
261 "4:"
262 :"=a" (__res):"S" (cs),"D" (ct),"c" (count):"esi","edi","ecx");
263 return __res;
264 }
265
266 #define __HAVE_ARCH_WCSCHR
267 inline wchar_t * wcschr(const wchar_t * s, int c)
268 {
269 register wchar_t * __res;
270 __asm__ __volatile__(
271 "cld\n\t"
272 "movw %%eax,%%edx\n"
273 "1:\tlodsw\n\t"
274 "cmpw %%edx,%%eax\n\t"
275 "je 2f\n\t"
276 "testw %%eax,%%eax\n\t"
277 "jne 1b\n\t"
278 "movl $1,%1\n"
279 "2:\tmovl %1,%0\n\t"
280 "decl %0\n\t"
281 "decl %0\n\t"
282 :"=a" (__res):"S" (s),"0" (c):"esi");
283 return __res;
284 }
285
286 #define __HAVE_ARCH_WCSRCHR
287 inline wchar_t * wcsrchr(const wchar_t * s, int c)
288 {
289 register wchar_t * __res;
290 __asm__ __volatile__(
291 "cld\n\t"
292 "movw %%eax,%%edx\n"
293 "1:\tlodsw\n\t"
294 "cmpw %%edx,%%eax\n\t"
295 "jne 2f\n\t"
296 "leal -2(%%esi),%0\n"
297 "2:\ttestw %%eax,%%eax\n\t"
298 "jne 1b"
299 :"=d" (__res):"0" (0),"S" (s),"a" (c):"eax","esi");
300 return __res;
301 }
302
303 #define __HAVE_ARCH_WCSSPN
304 inline size_t wcsspn(const wchar_t * cs, const wchar_t * ct)
305 {
306 register wchar_t * __res;
307 __asm__ __volatile__(
308 "cld\n\t"
309 "movl %4,%%edi\n\t"
310 "repne\n\t"
311 "scasw\n\t"
312 "notl %%ecx\n\t"
313 "decl %%ecx\n\t"
314 "movl %%ecx,%%edx\n"
315 "1:\tlodsw\n\t"
316 "testw %%eax,%%eax\n\t"
317 "je 2f\n\t"
318 "movl %4,%%edi\n\t"
319 "movl %%edx,%%ecx\n\t"
320 "repne\n\t"
321 "scasb\n\t"
322 "je 1b\n"
323 "2:\tdecl %0"
324 :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
325 :"eax","ecx","edx","edi");
326 return __res-cs;
327 }
328
329 #define __HAVE_ARCH_WCSCSPN
330 inline size_t wcscspn(const wchar_t * cs, const wchar_t * ct)
331 {
332 register wchar_t * __res;
333 __asm__ __volatile__(
334 "cld\n\t"
335 "movl %4,%%edi\n\t"
336 "repne\n\t"
337 "scasw\n\t"
338 "notl %%ecx\n\t"
339 "decl %%ecx\n\t"
340 "movl %%ecx,%%edx\n"
341 "1:\tlodsw\n\t"
342 "testw %%eax,%%eax\n\t"
343 "je 2f\n\t"
344 "movl %4,%%edi\n\t"
345 "movl %%edx,%%ecx\n\t"
346 "repne\n\t"
347 "scasw\n\t"
348 "jne 1b\n"
349 "2:\tdecl %0"
350 :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
351 :"eax","ecx","edx","edi");
352 return __res-cs;
353 }
354
355 #define __HAVE_ARCH_STRPBRK
356 inline wchar_t * wcspbrk(const wchar_t * cs,const wchar_t * ct)
357 {
358 register wchar_t * __res;
359 __asm__ __volatile__(
360 "cld\n\t"
361 "movl %4,%%edi\n\t"
362 "repne\n\t"
363 "scasw\n\t"
364 "notl %%ecx\n\t"
365 "decl %%ecx\n\t"
366 "movl %%ecx,%%edx\n"
367 "1:\tlodsw\n\t"
368 "testw %%eax,%%eax\n\t"
369 "je 2f\n\t"
370 "movl %4,%%edi\n\t"
371 "movl %%edx,%%ecx\n\t"
372 "repne\n\t"
373 "scasw\n\t"
374 "jne 1b\n\t"
375 "decl %0\n\t"
376 "jmp 3f\n"
377 "2:\txorl %0,%0\n"
378 "3:"
379 :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
380 :"eax","ecx","edx","edi");
381 return __res;
382 }
383
384 #define __HAVE_ARCH_WCSSTR
385 inline wchar_t * wcsstr(const wchar_t * cs,const wchar_t * ct)
386 {
387 register wchar_t * __res;
388 __asm__ __volatile__(
389 "cld\n\t" \
390 "movl %4,%%edi\n\t"
391 "repne\n\t"
392 "scasw\n\t"
393 "notl %%ecx\n\t"
394 "decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */
395 "movl %%ecx,%%edx\n"
396 "1:\tmovl %4,%%edi\n\t"
397 "movl %%esi,%%eax\n\t"
398 "movl %%edx,%%ecx\n\t"
399 "repe\n\t"
400 "cmpsw\n\t"
401 "je 2f\n\t" /* also works for empty string, see above */
402 "xchgl %%eax,%%esi\n\t"
403 "incl %%esi\n\t"
404 "cmpw $0,-1(%%eax)\n\t"
405 "jne 1b\n\t"
406 "xorl %%eax,%%eax\n\t"
407 "2:"
408 :"=a" (__res):"0" (0),"c" (0xffffffff),"S" (cs),"g" (ct)
409 :"ecx","edx","edi","esi");
410 return __res;
411 }
412
413
414 #define __HAVE_ARCH_WCSLEN
415 inline size_t wcslen(const wchar_t * s)
416 {
417 register int __res;
418 __asm__ __volatile__(
419 "cld\n\t"
420 "repne\n\t"
421 "scasw\n\t"
422 "notl %0\n\t"
423 "decl %0"
424 :"=c" (__res):"D" (s),"a" (0),"0" (0xffffffff):"edi");
425 return __res;
426 }
427
428
429
430 #define __HAVE_ARCH_WCSTOK
431
432
433 inline wchar_t * wcstok(wchar_t * s,const wchar_t * ct)
434 {
435
436 register wchar_t * __res;
437 __asm__ __volatile__(
438 "testl %1,%1\n\t"
439 "jne 1f\n\t"
440 "testl %0,%0\n\t"
441 "je 8f\n\t"
442 "movl %0,%1\n"
443 "1:\txorl %0,%0\n\t"
444 "movl $-1,%%ecx\n\t"
445 "xorl %%eax,%%eax\n\t"
446 "cld\n\t"
447 "movl %4,%%edi\n\t"
448 "repnz\n\t"
449 "scasw\n\t"
450 "notl %%ecx\n\t"
451 "decl %%ecx\n\t"
452 "decl %%ecx\n\t"
453 "je 7f\n\t" /* empty delimiter-string */
454 "movl %%ecx,%%edx\n"
455 "2:\tlodsw\n\t"
456 "testw %%eax,%%eax\n\t"
457 "je 7f\n\t"
458 "movl %4,%%edi\n\t"
459 "movl %%edx,%%ecx\n\t"
460 "repne\n\t"
461 "scasw\n\t"
462 "je 2b\n\t"
463 "decl %1\n\t"
464 "decl %1\n\t"
465 "cmpw $0,(%1)\n\t"
466 "je 7f\n\t"
467 "movl %1,%0\n"
468 "3:\tlodsw\n\t"
469 "testw %%eax,%%eax\n\t"
470 "je 5f\n\t"
471 "movl %4,%%edi\n\t"
472 "movl %%edx,%%ecx\n\t"
473 "repne\n\t"
474 "scasw\n\t"
475 "jne 3b\n\t"
476 "decl %1\n\t"
477 "decl %1\n\t"
478 "decl %1\n\t"
479 "decl %1\n\t"
480 "cmpw $0,(%1)\n\t"
481 "je 5f\n\t"
482 "movw $0,(%1)\n\t"
483 "incl %1\n\t"
484 "incl %1\n\t"
485 "jmp 6f\n"
486 "5:\txorl %1,%1\n"
487 "6:\tcmpw $0,(%0)\n\t"
488 "jne 7f\n\t"
489 "xorl %0,%0\n"
490 "7:\ttestl %0,%0\n\t"
491 "jne 8f\n\t"
492 "movl %0,%1\n"
493 "8:"
494 :"=b" (__res),"=S" (___wcstok)
495 :"0" (___wcstok),"1" (s),"g" (ct)
496 :"eax","ecx","edx","edi","memory");
497
498 return __res;
499 }
500
501
502 #define __HAVE_ARCH_WCSNNLEN
503 inline size_t wcsnlen(const wchar_t * s, size_t count)
504 {
505 register int __res;
506 __asm__ __volatile__(
507 "movl %1,%0\n\t"
508 "jmp 2f\n"
509 "1:\tcmpw $0,(%0)\n\t"
510 "je 3f\n\t"
511 "incl %0\n"
512 "2:\tdecl %2\n\t"
513 "cmpl $-1,%2\n\t"
514 "jne 1b\n"
515 "3:\tsubl %1,%0"
516 :"=a" (__res)
517 :"c" (s),"d" (count)
518 :"edx");
519 return __res;
520 }
521
522
523
524 #define __HAVE_ARCH_WCSICMP
525 inline int wcsicmp(const wchar_t* cs,const wchar_t * ct)
526 {
527 register int __res;
528
529
530 __asm__ __volatile__(
531 "cld\n"
532 "1:\tmovw (%%esi), %%eax\n\t"
533 "movw (%%edi), %%edx \n\t"
534 "cmpw $0x5A, %%eax\n\t"
535 "ja 2f\t\n"
536 "cmpw $0x40, %%eax\t\n"
537 "jbe 2f\t\n"
538 "addw $0x20, %%eax\t\n"
539 "2:\t cmpw $0x5A, %%edx\t\n"
540 "ja 3f\t\n"
541 "cmpw $0x40, %%edx\t\n"
542 "jbe 3f\t\n"
543 "addw $0x20, %%edx\t\n"
544 "3:\t inc %%esi\t\n"
545 "inc %%esi\t\n"
546 "inc %%edi\t\n"
547 "inc %%edi\t\n"
548 "cmpw %%eax, %%edx\t\n"
549 "jne 4f\n\t"
550 "cmpw $00, %%eax\n\t"
551 "jne 1b\n\t"
552 "xorl %%eax,%%eax\n\t"
553 "jmp 5f\n"
554 "4:\tsbbl %%eax,%%eax\n\t"
555 "orw $1,%%eax\n"
556 "5:"
557 :"=a" (__res):"S" (cs),"D" (ct):"esi","edi");
558
559 return __res;
560 }
561
562
563 #define __HAVE_ARCH_WCSNICMP
564 inline int wcsnicmp(const wchar_t* cs,const wchar_t * ct, size_t count)
565 {
566 register int __res;
567
568
569 __asm__ __volatile__(
570 "cld\n"
571 "1:\t decl %3\n\t"
572 "js 6f\n\t"
573 "movw (%%esi), %%eax\n\t"
574 "movw (%%edi), %%edx \n\t"
575 "cmpw $0x5A, %%eax\n\t"
576 "ja 2f\t\n"
577 "cmpw $0x40, %%eax\t\n"
578 "jbe 2f\t\n"
579 "addw $0x20, %%eax\t\n"
580 "2:\t cmpw $0x5A, %%edx\t\n"
581 "ja 3f\t\n"
582 "cmpw $0x40, %%edx\t\n"
583 "jbe 3f\t\n"
584 "addw $0x20, %%edx\t\n"
585 "3:\t inc %%esi\t\n"
586 "inc %%esi\t\n"
587 "inc %%edi\t\n"
588 "inc %%edi\t\n"
589 "cmpw %%eax, %%edx\t\n"
590 "jne 4f\n\t"
591 "cmpw $00, %%eax\n\t"
592 "jne 1b\n\t"
593 "6:xorl %%eax,%%eax\n\t"
594 "jmp 5f\n"
595 "4:\tsbbl %%eax,%%eax\n\t"
596 "orw $1,%%eax\n"
597 "5:"
598 :"=a" (__res):"S" (cs),"D" (ct), "c" (count):"esi","edi", "ecx");
599
600
601 return __res;
602 }
603
604 #endif
605 #endif