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)
11 /* INCLUDES *****************************************************************/
13 #include <ddk/ntddk.h>
16 #include <internal/debug.h>
18 /* FUNCTIONS *****************************************************************/
20 wchar_t * wcsncat(wchar_t * dest
,const wchar_t * src
,size_t count
)
24 for (j
=0;dest
[j
]!=0;j
++);
37 wchar_t * wcsncpy(wchar_t * dest
,const wchar_t *src
,size_t count
)
53 wchar_t* wcsrchr(const wchar_t* str
, wchar_t ch
)
56 while (str
[len
]!=((wchar_t)0))
71 wchar_t* wcschr(wchar_t* str
, wchar_t ch
)
73 while ((*str
)!=((wchar_t)0))
84 wchar_t * wcscpy(wchar_t * str1
,const wchar_t * str2
)
86 while ( (*str1
)==(*str2
) )
90 if ( (*str1
)==((wchar_t)0) && (*str1
)==((wchar_t)0) )
95 return( (*str1
) - (*str2
) );
98 unsigned long wstrlen(PWSTR s
)
113 inline int wcscmp(const wchar_t* cs
,const wchar_t * ct
)
116 __asm__
__volatile__(
121 "testw %%eax,%%eax\n\t"
123 "xorl %%eax,%%eax\n\t"
125 "2:\tsbbl %%eax,%%eax\n\t"
128 :"=a" (__res
):"S" (cs
),"D" (ct
):"esi","edi");
132 #ifdef __MACHINE_STRING_FUNCTIONS
134 * Include machine specific inline routines
136 //#ifndef _I386_STRING_H_
137 //#define _I386_STRING_H_
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).
145 * Also, the byte strings actually work correctly. Forget
146 * the i486 routines for now as they may be broken..
149 #if FIXED_486_STRING && (CPU == 486 || CPU == 586)
150 #include <asm/string-486.h>
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 :-)
162 * Copyright (C) 1991, 1992 Linus Torvalds
167 #define __HAVE_ARCH_WCSCPY
168 extern inline wchar_t * wcscpy(wchar_t * dest
,const wchar_t *src
)
170 __asm__
__volatile__(
174 "testw %%eax,%%eax\n\t"
177 :"S" (src
),"D" (dest
):"esi","edi","eax","memory");
181 #define __HAVE_ARCH_WCSNCPY
182 inline wchar_t * wcsncpy(wchar_t * dest
,const wchar_t *src
,size_t count
)
184 __asm__
__volatile__(
190 "testw %%eax,%%eax\n\t"
196 :"S" (src
),"D" (dest
),"c" (count
):"esi","edi","eax","ecx","memory");
200 #define __HAVE_ARCH_WCSCAT
201 inline wchar_t * wcscat(wchar_t * dest
,const wchar_t * src
)
203 __asm__
__volatile__(
211 "testw %%eax,%%eax\n\t"
214 :"S" (src
),"D" (dest
),"a" (0),"c" (0xffffffff):"esi","edi","eax","ecx");
218 #define __HAVE_ARCH_WCSNCAT
219 inline wchar_t * wcsncat(wchar_t * dest
,const wchar_t * src
,size_t count
)
221 __asm__
__volatile__(
232 "testw %%eax,%%eax\n\t"
237 :"S" (src
),"D" (dest
),"a" (0),"c" (0xffffffff),"g" (count
)
238 :"esi","edi","eax","ecx","memory");
242 #define __HAVE_ARCH_WCSCMP
244 #define __HAVE_ARCH_WCSNCMP
245 inline int wcsncmp(const wchar_t * cs
,const wchar_t * ct
,size_t count
)
248 __asm__
__volatile__(
255 "testw %%eax,%%eax\n\t"
257 "2:\txorl %%eax,%%eax\n\t"
259 "3:\tsbbl %%eax,%%eax\n\t"
262 :"=a" (__res
):"S" (cs
),"D" (ct
),"c" (count
):"esi","edi","ecx");
266 #define __HAVE_ARCH_WCSCHR
267 inline wchar_t * wcschr(const wchar_t * s
, int c
)
269 register wchar_t * __res
;
270 __asm__
__volatile__(
274 "cmpw %%edx,%%eax\n\t"
276 "testw %%eax,%%eax\n\t"
282 :"=a" (__res
):"S" (s
),"0" (c
):"esi");
286 #define __HAVE_ARCH_WCSRCHR
287 inline wchar_t * wcsrchr(const wchar_t * s
, int c
)
289 register wchar_t * __res
;
290 __asm__
__volatile__(
294 "cmpw %%edx,%%eax\n\t"
296 "leal -2(%%esi),%0\n"
297 "2:\ttestw %%eax,%%eax\n\t"
299 :"=d" (__res
):"0" (0),"S" (s
),"a" (c
):"eax","esi");
303 #define __HAVE_ARCH_WCSSPN
304 inline size_t wcsspn(const wchar_t * cs
, const wchar_t * ct
)
306 register wchar_t * __res
;
307 __asm__
__volatile__(
316 "testw %%eax,%%eax\n\t"
319 "movl %%edx,%%ecx\n\t"
324 :"=S" (__res
):"a" (0),"c" (0xffffffff),"0" (cs
),"g" (ct
)
325 :"eax","ecx","edx","edi");
329 #define __HAVE_ARCH_WCSCSPN
330 inline size_t wcscspn(const wchar_t * cs
, const wchar_t * ct
)
332 register wchar_t * __res
;
333 __asm__
__volatile__(
342 "testw %%eax,%%eax\n\t"
345 "movl %%edx,%%ecx\n\t"
350 :"=S" (__res
):"a" (0),"c" (0xffffffff),"0" (cs
),"g" (ct
)
351 :"eax","ecx","edx","edi");
355 #define __HAVE_ARCH_STRPBRK
356 inline wchar_t * wcspbrk(const wchar_t * cs
,const wchar_t * ct
)
358 register wchar_t * __res
;
359 __asm__
__volatile__(
368 "testw %%eax,%%eax\n\t"
371 "movl %%edx,%%ecx\n\t"
379 :"=S" (__res
):"a" (0),"c" (0xffffffff),"0" (cs
),"g" (ct
)
380 :"eax","ecx","edx","edi");
384 #define __HAVE_ARCH_WCSSTR
385 inline wchar_t * wcsstr(const wchar_t * cs
,const wchar_t * ct
)
387 register wchar_t * __res
;
388 __asm__
__volatile__(
394 "decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */
396 "1:\tmovl %4,%%edi\n\t"
397 "movl %%esi,%%eax\n\t"
398 "movl %%edx,%%ecx\n\t"
401 "je 2f\n\t" /* also works for empty string, see above */
402 "xchgl %%eax,%%esi\n\t"
404 "cmpw $0,-1(%%eax)\n\t"
406 "xorl %%eax,%%eax\n\t"
408 :"=a" (__res
):"0" (0),"c" (0xffffffff),"S" (cs
),"g" (ct
)
409 :"ecx","edx","edi","esi");
414 #define __HAVE_ARCH_WCSLEN
415 inline size_t wcslen(const wchar_t * s
)
418 __asm__
__volatile__(
424 :"=c" (__res
):"D" (s
),"a" (0),"0" (0xffffffff):"edi");
430 #define __HAVE_ARCH_WCSTOK
433 inline wchar_t * wcstok(wchar_t * s
,const wchar_t * ct
)
436 register wchar_t * __res
;
437 __asm__
__volatile__(
445 "xorl %%eax,%%eax\n\t"
453 "je 7f\n\t" /* empty delimiter-string */
456 "testw %%eax,%%eax\n\t"
459 "movl %%edx,%%ecx\n\t"
469 "testw %%eax,%%eax\n\t"
472 "movl %%edx,%%ecx\n\t"
487 "6:\tcmpw $0,(%0)\n\t"
490 "7:\ttestl %0,%0\n\t"
494 :"=b" (__res
),"=S" (___wcstok
)
495 :"0" (___wcstok
),"1" (s
),"g" (ct
)
496 :"eax","ecx","edx","edi","memory");
502 #define __HAVE_ARCH_WCSNNLEN
503 inline size_t wcsnlen(const wchar_t * s
, size_t count
)
506 __asm__
__volatile__(
509 "1:\tcmpw $0,(%0)\n\t"
524 #define __HAVE_ARCH_WCSICMP
525 inline int wcsicmp(const wchar_t* cs
,const wchar_t * ct
)
530 __asm__
__volatile__(
532 "1:\tmovw (%%esi), %%eax\n\t"
533 "movw (%%edi), %%edx \n\t"
534 "cmpw $0x5A, %%eax\n\t"
536 "cmpw $0x40, %%eax\t\n"
538 "addw $0x20, %%eax\t\n"
539 "2:\t cmpw $0x5A, %%edx\t\n"
541 "cmpw $0x40, %%edx\t\n"
543 "addw $0x20, %%edx\t\n"
548 "cmpw %%eax, %%edx\t\n"
550 "cmpw $00, %%eax\n\t"
552 "xorl %%eax,%%eax\n\t"
554 "4:\tsbbl %%eax,%%eax\n\t"
557 :"=a" (__res
):"S" (cs
),"D" (ct
):"esi","edi");
563 #define __HAVE_ARCH_WCSNICMP
564 inline int wcsnicmp(const wchar_t* cs
,const wchar_t * ct
, size_t count
)
569 __asm__
__volatile__(
573 "movw (%%esi), %%eax\n\t"
574 "movw (%%edi), %%edx \n\t"
575 "cmpw $0x5A, %%eax\n\t"
577 "cmpw $0x40, %%eax\t\n"
579 "addw $0x20, %%eax\t\n"
580 "2:\t cmpw $0x5A, %%edx\t\n"
582 "cmpw $0x40, %%edx\t\n"
584 "addw $0x20, %%edx\t\n"
589 "cmpw %%eax, %%edx\t\n"
591 "cmpw $00, %%eax\n\t"
593 "6:xorl %%eax,%%eax\n\t"
595 "4:\tsbbl %%eax,%%eax\n\t"
598 :"=a" (__res
):"S" (cs
),"D" (ct
), "c" (count
):"esi","edi", "ecx");