Initial Commit
[libctiny.git] / string.cc
blob9c2ad0daea84d5b4f2efa60bc3855b7ea9292f34
1 #include <windows.h>
2 #include <limits.h>
3 #include <stdlib.h>
5 #include "libctiny.h"
7 #ifndef _CONST_RETURN
8 #define _CONST_RETURN
9 #endif
11 /***
12 *wcsstr.c - search for one wide-character string inside another
14 * Copyright (c) Microsoft Corporation. All rights reserved.
16 *Purpose:
17 * defines wcsstr() - search for one wchar_t string inside another
19 *******************************************************************************/
21 /***
22 *wchar_t *wcsstr(string1, string2) - search for string2 in string1
23 * (wide strings)
25 *Purpose:
26 * finds the first occurrence of string2 in string1 (wide strings)
28 *Entry:
29 * wchar_t *string1 - string to search in
30 * wchar_t *string2 - string to search for
32 *Exit:
33 * returns a pointer to the first occurrence of string2 in
34 * string1, or NULL if string2 does not occur in string1
36 *Uses:
38 *Exceptions:
40 *******************************************************************************/
42 _CONST_RETURN wchar_t * __cdecl wcsstr(const wchar_t * wcs1,
43 const wchar_t * wcs2) {
44 wchar_t *cp = (wchar_t *) wcs1;
45 wchar_t *s1, *s2;
47 if (!*wcs2)
48 return (wchar_t *)wcs1;
50 while (*cp)
52 s1 = cp;
53 s2 = (wchar_t *) wcs2;
55 while (*s1 && *s2 && !(*s1-*s2))
56 s1++, s2++;
58 if (!*s2)
59 return(cp);
61 cp++;
64 return(NULL);
67 /***
68 *wcsrchr.c - find last occurrence of wchar_t character in wide string
70 * Copyright (c) Microsoft Corporation. All rights reserved.
72 *Purpose:
73 * defines wcsrchr() - find the last occurrence of a given character
74 * in a string (wide-characters).
76 *******************************************************************************/
78 /***
79 *wchar_t *wcsrchr(string, ch) - find last occurrence of ch in wide string
81 *Purpose:
82 * Finds the last occurrence of ch in string. The terminating
83 * null character is used as part of the search (wide-characters).
85 *Entry:
86 * wchar_t *string - string to search in
87 * wchar_t ch - character to search for
89 *Exit:
90 * returns a pointer to the last occurrence of ch in the given
91 * string
92 * returns NULL if ch does not occurr in the string
94 *Exceptions:
96 *******************************************************************************/
98 _CONST_RETURN wchar_t * __cdecl wcsrchr(const wchar_t * string, wchar_t ch) {
99 wchar_t *start = (wchar_t *)string;
101 while (*string++) /* find end of string */
103 /* search towards front */
104 while (--string != start && *string != (wchar_t)ch)
107 if (*string == (wchar_t)ch) /* wchar_t found ? */
108 return( (wchar_t *)string );
110 return(NULL);
113 /***
114 *wcschr.c - search a wchar_t string for a given wchar_t character
116 * Copyright (c) Microsoft Corporation. All rights reserved.
118 *Purpose:
119 * defines wcschr() - search a wchar_t string for a wchar_t character
121 *******************************************************************************/
123 /***
124 *wchar_t *wcschr(string, c) - search a string for a wchar_t character
126 *Purpose:
127 * Searches a wchar_t string for a given wchar_t character,
128 * which may be the null character L'\0'.
130 *Entry:
131 * wchar_t *string - wchar_t string to search in
132 * wchar_t c - wchar_t character to search for
134 *Exit:
135 * returns pointer to the first occurence of c in string
136 * returns NULL if c does not occur in string
138 *Exceptions:
140 *******************************************************************************/
142 _CONST_RETURN wchar_t * __cdecl wcschr(const wchar_t * string, wchar_t ch) {
143 while (*string && *string != (wchar_t)ch)
144 string++;
146 if (*string == (wchar_t)ch)
147 return((wchar_t *)string);
148 return(NULL);
151 /***
152 *xtoa.c - convert integers/longs to ASCII string
154 * Copyright (c) Microsoft Corporation. All rights reserved.
156 *Purpose:
157 * The module has code to convert integers/longs to ASCII strings. See
159 *******************************************************************************/
161 /***
162 *char *_itoa, *_ltoa, *_ultoa(val, buf, radix) - convert binary int to ASCII
163 * string
165 *Purpose:
166 * Converts an int to a character string.
168 *Entry:
169 * val - number to be converted (int, long or unsigned long)
170 * int radix - base to convert into
171 * char *buf - ptr to buffer to place result
173 *Exit:
174 * fills in space pointed to by buf with string result
175 * returns a pointer to this buffer
177 *Exceptions:
179 *******************************************************************************/
181 /* helper routine that does the main job. */
183 static void __cdecl xtoa(unsigned long val, char *buf, unsigned radix, int is_neg) {
184 char *p; /* pointer to traverse string */
185 char *firstdig; /* pointer to first digit */
186 char temp; /* temp char */
187 unsigned digval; /* value of digit */
189 p = buf;
191 if (is_neg) {
192 /* negative, so output '-' and negate */
193 *p++ = '-';
194 val = (unsigned long)(-(long)val);
197 firstdig = p; /* save pointer to first digit */
199 do {
200 digval = (unsigned) (val % radix);
201 val /= radix; /* get next digit */
203 /* convert to ascii and store */
204 if (digval > 9)
205 *p++ = (char) (digval - 10 + 'a'); /* a letter */
206 else
207 *p++ = (char) (digval + '0'); /* a digit */
208 } while (val > 0);
210 /* We now have the digit of the number in the buffer, but in reverse
211 order. Thus we reverse them now. */
213 *p-- = '\0'; /* terminate string; p points to last digit */
215 do {
216 temp = *p;
217 *p = *firstdig;
218 *firstdig = temp; /* swap *p and *firstdig */
219 --p;
220 ++firstdig; /* advance to next two digits */
221 } while (firstdig < p); /* repeat until halfway */
224 /* Actual functions just call conversion helper with neg flag set correctly,
225 and return pointer to buffer. */
227 extern "C" char * __cdecl _itoa(int val, char *buf, int radix) {
228 if (radix == 10 && val < 0)
229 xtoa((unsigned long)val, buf, radix, 1);
230 else
231 xtoa((unsigned long)(unsigned int)val, buf, radix, 0);
232 return buf;
235 /***
236 *strlen.c - contains strlen() routine
238 * Copyright (c) Microsoft Corporation. All rights reserved.
240 *Purpose:
241 * strlen returns the length of a null-terminated string,
242 * not including the null byte itself.
244 *******************************************************************************/
246 #ifdef _MSC_VER
247 #pragma function(strlen)
248 #endif /* _MSC_VER */
250 /***
251 *strlen - return the length of a null-terminated string
253 *Purpose:
254 * Finds the length in bytes of the given string, not including
255 * the final null character.
257 *Entry:
258 * const char * str - string whose length is to be computed
260 *Exit:
261 * length of the string "str", exclusive of the final null byte
263 *Exceptions:
265 *******************************************************************************/
267 size_t __cdecl strlen(const char * str) {
268 const char *eos = str;
270 while (*eos++) ;
272 return( (int)(eos - str - 1) );
275 /***
276 *wcsncpy.c - copy at most n characters of wide-character string
278 * Copyright (c) Microsoft Corporation. All rights reserved.
280 *Purpose:
281 * defines wcsncpy() - copy at most n characters of wchar_t string
283 *******************************************************************************/
285 /***
286 *wchar_t *wcsncpy(dest, source, count) - copy at most n wide characters
288 *Purpose:
289 * Copies count characters from the source string to the
290 * destination. If count is less than the length of source,
291 * NO NULL CHARACTER is put onto the end of the copied string.
292 * If count is greater than the length of sources, dest is padded
293 * with null characters to length count (wide-characters).
296 *Entry:
297 * wchar_t *dest - pointer to destination
298 * wchar_t *source - source string for copy
299 * size_t count - max number of characters to copy
301 *Exit:
302 * returns dest
304 *Exceptions:
306 *******************************************************************************/
308 wchar_t * __cdecl wcsncpy(wchar_t * dest, const wchar_t * source, size_t count) {
309 wchar_t *start = dest;
311 while (count && (*dest++ = *source++)) /* copy string */
312 count--;
314 if (count) /* pad out with zeroes */
315 while (--count)
316 *dest++ = L'\0';
318 return(start);
321 /***
322 *wcscmp.c - routine to compare two wchar_t strings (for equal, less, or greater)
324 * Copyright (c) Microsoft Corporation. All rights reserved.
326 *Purpose:
327 * Compares two wide-character strings, determining their lexical order.
329 *******************************************************************************/
331 /***
332 *wcscmp - compare two wchar_t strings,
333 * returning less than, equal to, or greater than
335 *Purpose:
336 * wcscmp compares two wide-character strings and returns an integer
337 * to indicate whether the first is less than the second, the two are
338 * equal, or whether the first is greater than the second.
340 * Comparison is done wchar_t by wchar_t on an UNSIGNED basis, which is to
341 * say that Null wchar_t(0) is less than any other character.
343 *Entry:
344 * const wchar_t * src - string for left-hand side of comparison
345 * const wchar_t * dst - string for right-hand side of comparison
347 *Exit:
348 * returns -1 if src < dst
349 * returns 0 if src == dst
350 * returns +1 if src > dst
352 *Exceptions:
354 *******************************************************************************/
356 int __cdecl wcscmp(const wchar_t * src, const wchar_t * dst) {
357 int ret = 0 ;
359 while (! (ret = (int)(*src - *dst)) && *dst)
360 ++src, ++dst;
362 if (ret < 0)
363 ret = -1 ;
364 else if (ret > 0)
365 ret = 1 ;
367 return( ret );
370 /***
371 *wcslen.c - contains wcslen() routine
373 * Copyright (c) Microsoft Corporation. All rights reserved.
375 *Purpose:
376 * wcslen returns the length of a null-terminated wide-character string,
377 * not including the null wchar_t itself.
379 *******************************************************************************/
381 /***
382 *wcslen - return the length of a null-terminated wide-character string
384 *Purpose:
385 * Finds the length in wchar_t's of the given string, not including
386 * the final null wchar_t (wide-characters).
388 *Entry:
389 * const wchar_t * wcs - string whose length is to be computed
391 *Exit:
392 * length of the string "wcs", exclusive of the final null wchar_t
394 *Exceptions:
396 *******************************************************************************/
398 size_t __cdecl wcslen(
399 const wchar_t * wcs
401 const wchar_t *eos = wcs;
403 while (*eos++) ;
405 return( (size_t)(eos - wcs - 1) );
408 /***
409 *strstr.c - search for one string inside another
411 * Copyright (c) Microsoft Corporation. All rights reserved.
413 *Purpose:
414 * defines strstr() - search for one string inside another
416 *******************************************************************************/
418 /***
419 *char *strstr(string1, string2) - search for string2 in string1
421 *Purpose:
422 * finds the first occurrence of string2 in string1
424 *Entry:
425 * char *string1 - string to search in
426 * char *string2 - string to search for
428 *Exit:
429 * returns a pointer to the first occurrence of string2 in
430 * string1, or NULL if string2 does not occur in string1
432 *Uses:
434 *Exceptions:
436 *******************************************************************************/
438 _CONST_RETURN char * __cdecl strstr(
439 const char * str1,
440 const char * str2
442 char *cp = (char *) str1;
443 char *s1, *s2;
445 if (!*str2)
446 return((char *)str1);
448 while (*cp)
450 s1 = cp;
451 s2 = (char *) str2;
453 while (*s1 && *s2 && !(*s1-*s2))
454 s1++, s2++;
456 if (!*s2)
457 return(cp);
459 cp++;
462 return(NULL);
466 /***
467 *strcmp.c - routine to compare two strings (for equal, less, or greater)
469 * Copyright (c) Microsoft Corporation. All rights reserved.
471 *Purpose:
472 * Compares two string, determining their lexical order.
474 *******************************************************************************/
476 #ifdef _MSC_VER
477 #pragma function(strcmp)
478 #endif /* _MSC_VER */
480 /***
481 *strcmp - compare two strings, returning less than, equal to, or greater than
483 *Purpose:
484 * STRCMP compares two strings and returns an integer
485 * to indicate whether the first is less than the second, the two are
486 * equal, or whether the first is greater than the second.
488 * Comparison is done byte by byte on an UNSIGNED basis, which is to
489 * say that Null (0) is less than any other character (1-255).
491 *Entry:
492 * const char * src - string for left-hand side of comparison
493 * const char * dst - string for right-hand side of comparison
495 *Exit:
496 * returns -1 if src < dst
497 * returns 0 if src == dst
498 * returns +1 if src > dst
500 *Exceptions:
502 *******************************************************************************/
504 int __cdecl strcmp(
505 const char * src,
506 const char * dst
508 int ret = 0 ;
510 while (! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
511 ++src, ++dst;
513 if (ret < 0)
514 ret = -1 ;
515 else if (ret > 0)
516 ret = 1 ;
518 return( ret );
521 #ifndef _MBSCAT
522 #ifdef _MSC_VER
523 #pragma function(strcpy)
524 #endif /* _MSC_VER */
525 #endif /* _MBSCAT */
527 /***
528 *char *strcpy(dst, src) - copy one string over another
530 *Purpose:
531 * Copies the string src into the spot specified by
532 * dest; assumes enough room.
534 *Entry:
535 * char * dst - string over which "src" is to be copied
536 * const char * src - string to be copied over "dst"
538 *Exit:
539 * The address of "dst"
541 *Exceptions:
542 *******************************************************************************/
544 char * __cdecl strcpy(char * dst, const char * src) {
545 char * cp = dst;
547 while (*cp++ = *src++)
548 ; /* Copy src over dst */
550 return( dst );
553 /***
554 *strncmp.c - compare first n characters of two strings
556 * Copyright (c) Microsoft Corporation. All rights reserved.
558 *Purpose:
559 * defines strncmp() - compare first n characters of two strings
560 * for lexical order.
562 *******************************************************************************/
564 /***
565 *int strncmp(first, last, count) - compare first count chars of strings
567 *Purpose:
568 * Compares two strings for lexical order. The comparison stops
569 * after: (1) a difference between the strings is found, (2) the end
570 * of the strings is reached, or (3) count characters have been
571 * compared.
573 *Entry:
574 * char *first, *last - strings to compare
575 * unsigned count - maximum number of characters to compare
577 *Exit:
578 * returns <0 if first < last
579 * returns 0 if first == last
580 * returns >0 if first > last
582 *Exceptions:
584 *******************************************************************************/
586 int __cdecl strncmp(
587 const char * first,
588 const char * last,
589 size_t count
591 if (!count)
592 return(0);
594 while (--count && *first && *first == *last)
596 first++;
597 last++;
600 return( *(unsigned char *)first - *(unsigned char *)last );
603 /***
604 *strchr.c - search a string for a given character
606 * Copyright (c) Microsoft Corporation. All rights reserved.
608 *Purpose:
609 * defines strchr() - search a string for a character
611 *******************************************************************************/
613 /***
614 *char *strchr(string, c) - search a string for a character
616 *Purpose:
617 * Searches a string for a given character, which may be the
618 * null character '\0'.
620 *Entry:
621 * char *string - string to search in
622 * char c - character to search for
624 *Exit:
625 * returns pointer to the first occurence of c in string
626 * returns NULL if c does not occur in string
628 *Exceptions:
630 *******************************************************************************/
632 _CONST_RETURN char * __cdecl strchr(
633 const char * string,
634 int ch
636 while (*string && *string != (char)ch)
637 string++;
639 if (*string == (char)ch)
640 return((char *)string);
641 return(NULL);
644 /***
645 *wcsncmp.c - compare first n characters of two wide-character strings
647 * Copyright (c) Microsoft Corporation. All rights reserved.
649 *Purpose:
650 * defines wcsncmp() - compare first n characters of two wchar_t strings
651 * for lexical order.
653 *******************************************************************************/
655 /***
656 *int wcsncmp(first, last, count) - compare first count chars of wchar_t strings
658 *Purpose:
659 * Compares two strings for lexical order. The comparison stops
660 * after: (1) a difference between the strings is found, (2) the end
661 * of the strings is reached, or (3) count characters have been
662 * compared (wide-character strings).
664 *Entry:
665 * wchar_t *first, *last - strings to compare
666 * size_t count - maximum number of characters to compare
668 *Exit:
669 * returns <0 if first < last
670 * returns 0 if first == last
671 * returns >0 if first > last
673 *Exceptions:
675 *******************************************************************************/
677 int __cdecl wcsncmp(
678 const wchar_t * first,
679 const wchar_t * last,
680 size_t count
682 if (!count)
683 return(0);
685 while (--count && *first && *first == *last)
687 first++;
688 last++;
691 return((int)(*first - *last));
694 /***
695 *wcsspn.c - find length of initial substring of chars from a control string
696 * (wide-character strings)
698 * Copyright (c) Microsoft Corporation. All rights reserved.
700 *Purpose:
701 * defines wcsspn() - finds the length of the initial substring of
702 * a string consisting entirely of characters from a control string
703 * (wide-character strings).
705 *******************************************************************************/
707 /***
708 *int wcsspn(string, control) - find init substring of control chars
710 *Purpose:
711 * Finds the index of the first character in string that does belong
712 * to the set of characters specified by control. This is
713 * equivalent to the length of the initial substring of string that
714 * consists entirely of characters from control. The L'\0' character
715 * that terminates control is not considered in the matching process
716 * (wide-character strings).
718 *Entry:
719 * wchar_t *string - string to search
720 * wchar_t *control - string containing characters not to search for
722 *Exit:
723 * returns index of first wchar_t in string not in control
725 *Exceptions:
727 *******************************************************************************/
729 size_t __cdecl wcsspn(
730 const wchar_t * string,
731 const wchar_t * control
733 wchar_t *str = (wchar_t *) string;
734 wchar_t *ctl;
736 /* 1st char not in control string stops search */
737 while (*str) {
738 for (ctl = (wchar_t *)control; *ctl != *str; ctl++) {
739 if (*ctl == (wchar_t)0) {
741 * reached end of control string without finding a match
743 return (size_t)(str - string);
746 str++;
749 * The whole string consisted of characters from control
751 return (size_t)(str - string);
754 /***
755 *wcscspn.c - find length of initial substring of wide characters
756 * not in a control string
758 * Copyright (c) Microsoft Corporation. All rights reserved.
760 *Purpose:
761 * defines wcscspn()- finds the length of the initial substring of
762 * a string consisting entirely of characters not in a control string
763 * (wide-character strings).
765 *******************************************************************************/
767 /***
768 *size_t wcscspn(string, control) - search for init substring w/o control wchars
770 *Purpose:
771 * returns the index of the first character in string that belongs
772 * to the set of characters specified by control. This is equivalent
773 * to the length of the length of the initial substring of string
774 * composed entirely of characters not in control. Null chars not
775 * considered (wide-character strings).
777 *Entry:
778 * wchar_t *string - string to search
779 * wchar_t *control - set of characters not allowed in init substring
781 *Exit:
782 * returns the index of the first wchar_t in string
783 * that is in the set of characters specified by control.
785 *Exceptions:
787 *******************************************************************************/
789 size_t __cdecl wcscspn(
790 const wchar_t * string,
791 const wchar_t * control
793 wchar_t *str = (wchar_t *) string;
794 wchar_t *wcset;
796 /* 1st char in control string stops search */
797 while (*str) {
798 for (wcset = (wchar_t *)control; *wcset; wcset++) {
799 if (*wcset == *str) {
800 return (size_t)(str - string);
803 str++;
805 return (size_t)(str - string);
808 /***
809 *wchar_t *wcscpy(dst, src) - copy one wchar_t string over another
811 *Purpose:
812 * Copies the wchar_t string src into the spot specified by
813 * dest; assumes enough room.
815 *Entry:
816 * wchar_t * dst - wchar_t string over which "src" is to be copied
817 * const wchar_t * src - wchar_t string to be copied over "dst"
819 *Exit:
820 * The address of "dst"
822 *Exceptions:
823 *******************************************************************************/
825 wchar_t * __cdecl wcscpy(wchar_t * dst, const wchar_t * src)
827 wchar_t * cp = dst;
829 while( *cp++ = *src++ )
830 ; /* Copy src over dst */
832 return( dst );
835 /***
836 *strtol, strtoul(nptr,endptr,ibase) - Convert ascii string to long un/signed
837 * int.
839 *Purpose:
840 * Convert an ascii string to a long 32-bit value. The base
841 * used for the caculations is supplied by the caller. The base
842 * must be in the range 0, 2-36. If a base of 0 is supplied, the
843 * ascii string must be examined to determine the base of the
844 * number:
845 * (a) First char = '0', second char = 'x' or 'X',
846 * use base 16.
847 * (b) First char = '0', use base 8
848 * (c) First char in range '1' - '9', use base 10.
850 * If the 'endptr' value is non-NULL, then strtol/strtoul places
851 * a pointer to the terminating character in this value.
852 * See ANSI standard for details
854 *Entry:
855 * nptr == NEAR/FAR pointer to the start of string.
856 * endptr == NEAR/FAR pointer to the end of the string.
857 * ibase == integer base to use for the calculations.
859 * string format: [whitespace] [sign] [0] [x] [digits/letters]
861 *Exit:
862 * Good return:
863 * result
865 * Overflow return:
866 * strtol -- LONG_MAX or LONG_MIN
867 * strtoul -- ULONG_MAX
868 * strtol/strtoul -- errno == ERANGE
870 * No digits or bad base return:
872 * endptr = nptr*
874 *Exceptions:
875 * None.
876 *******************************************************************************/
878 /* flag values */
879 #define FL_UNSIGNED 1 /* strtoul called */
880 #define FL_NEG 2 /* negative sign found */
881 #define FL_OVERFLOW 4 /* overflow occured */
882 #define FL_READDIGIT 8 /* we've read at least one correct digit */
884 // __ascii_isdigit returns a non-zero value if c is a decimal digit (0 – 9).
885 int __ascii_isdigit(int c)
887 return (c >= '0' && c <= '9');
890 // __ascii_isalpha returns a nonzero value if c is within
891 // the ranges A – Z or a – z.
892 int __ascii_isalpha(int c)
894 return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
897 // __ascii_toupper converts lowercase character to uppercase.
898 int __ascii_toupper(int c)
900 if (c >= 'a' && c <= 'z') return (c - ('a' - 'A'));
901 return c;
904 int isspace(int c)
906 static bool spaces[256] =
908 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, // 0-9
909 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 10-19
910 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20-29
911 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 30-39
912 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40-49
913 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 50-59
914 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60-69
915 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 70-79
916 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80-89
917 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 90-99
918 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 100-109
919 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 110-119
920 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 120-129
921 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 130-139
922 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 140-149
923 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 150-159
924 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160-169
925 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 170-179
926 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 180-189
927 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 190-199
928 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 200-209
929 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 210-219
930 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 220-229
931 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 230-239
932 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 240-249
933 0, 0, 0, 0, 0, 1, // 250-255
936 return spaces[static_cast<unsigned char>(c)] == 1;
939 static unsigned long __cdecl strtoxl (
940 const char *nptr,
941 const char **endptr,
942 int ibase,
943 int flags
946 const char *p;
947 char c;
948 unsigned long number;
949 unsigned digval;
950 unsigned long maxval;
952 p = nptr; /* p is our scanning pointer */
953 number = 0; /* start with zero */
955 c = *p++; /* read char */
956 while ( isspace((int)(unsigned char)c) )
957 c = *p++; /* skip whitespace */
959 if (c == '-') {
960 flags |= FL_NEG; /* remember minus sign */
961 c = *p++;
963 else if (c == '+')
964 c = *p++; /* skip sign */
966 if (ibase < 0 || ibase == 1 || ibase > 36) {
967 /* bad base! */
968 if (endptr)
969 /* store beginning of string in endptr */
970 *endptr = nptr;
971 return 0L; /* return 0 */
973 else if (ibase == 0) {
974 /* determine base free-lance, based on first two chars of
975 string */
976 if (c != '0')
977 ibase = 10;
978 else if (*p == 'x' || *p == 'X')
979 ibase = 16;
980 else
981 ibase = 8;
984 if (ibase == 16) {
985 /* we might have 0x in front of number; remove if there */
986 if (c == '0' && (*p == 'x' || *p == 'X')) {
987 ++p;
988 c = *p++; /* advance past prefix */
992 /* if our number exceeds this, we will overflow on multiply */
993 maxval = ULONG_MAX / ibase;
996 for (;;) { /* exit in middle of loop */
997 /* convert c to value */
998 if ( __ascii_isdigit((int)(unsigned char)c) )
999 digval = c - '0';
1000 else if ( __ascii_isalpha((int)(unsigned char)c) )
1001 digval = __ascii_toupper(c) - 'A' + 10;
1002 else
1003 break;
1004 if (digval >= (unsigned)ibase)
1005 break; /* exit loop if bad digit found */
1007 /* record the fact we have read one digit */
1008 flags |= FL_READDIGIT;
1010 /* we now need to compute number = number * base + digval,
1011 but we need to know if overflow occured. This requires
1012 a tricky pre-check. */
1014 if (number < maxval || (number == maxval &&
1015 (unsigned long)digval <= ULONG_MAX % ibase)) {
1016 /* we won't overflow, go ahead and multiply */
1017 number = number * ibase + digval;
1019 else {
1020 /* we would have overflowed -- set the overflow flag */
1021 flags |= FL_OVERFLOW;
1024 c = *p++; /* read next digit */
1027 --p; /* point to place that stopped scan */
1029 if (!(flags & FL_READDIGIT)) {
1030 /* no number there; return 0 and point to beginning of
1031 string */
1032 if (endptr)
1033 /* store beginning of string in endptr later on */
1034 p = nptr;
1035 number = 0L; /* return 0 */
1037 else if ( (flags & FL_OVERFLOW) ||
1038 ( !(flags & FL_UNSIGNED) &&
1039 ( ( (flags & FL_NEG) && (number > -LONG_MIN) ) ||
1040 ( !(flags & FL_NEG) && (number > LONG_MAX) ) ) ) )
1042 /* overflow or signed overflow occurred */
1043 // errno = ERANGE;
1044 if ( flags & FL_UNSIGNED )
1045 number = ULONG_MAX;
1046 else if ( flags & FL_NEG )
1047 number = (unsigned long)(-LONG_MIN);
1048 else
1049 number = LONG_MAX;
1052 if (endptr != NULL)
1053 /* store pointer to char that stopped the scan */
1054 *endptr = p;
1056 if (flags & FL_NEG)
1057 /* negate result if there was a neg sign */
1058 number = (unsigned long)(-(long)number);
1060 return number; /* done. */
1063 long __cdecl strtol (
1064 const char *nptr,
1065 char **endptr,
1066 int ibase
1069 return (long) strtoxl(nptr, (const char**)endptr, ibase, 0);
1072 unsigned long __cdecl strtoul (
1073 const char *nptr,
1074 char **endptr,
1075 int ibase
1078 return strtoxl(nptr, (const char**)endptr, ibase, FL_UNSIGNED);