xref: /dragonfly/lib/libc/locale/wcstoull.c (revision 213582eb)
19cb03a6aSJoerg Sonnenberger /*-
20d5acd74SJohn Marino  * Copyright (c) 1992, 1993
30d5acd74SJohn Marino  *	The Regents of the University of California.  All rights reserved.
40d5acd74SJohn Marino  *
50d5acd74SJohn Marino  * Copyright (c) 2011 The FreeBSD Foundation
69cb03a6aSJoerg Sonnenberger  * All rights reserved.
70d5acd74SJohn Marino  * Portions of this software were developed by David Chisnall
80d5acd74SJohn Marino  * under sponsorship from the FreeBSD Foundation.
99cb03a6aSJoerg Sonnenberger  *
109cb03a6aSJoerg Sonnenberger  * Redistribution and use in source and binary forms, with or without
119cb03a6aSJoerg Sonnenberger  * modification, are permitted provided that the following conditions
129cb03a6aSJoerg Sonnenberger  * are met:
139cb03a6aSJoerg Sonnenberger  * 1. Redistributions of source code must retain the above copyright
149cb03a6aSJoerg Sonnenberger  *    notice, this list of conditions and the following disclaimer.
159cb03a6aSJoerg Sonnenberger  * 2. Redistributions in binary form must reproduce the above copyright
169cb03a6aSJoerg Sonnenberger  *    notice, this list of conditions and the following disclaimer in the
179cb03a6aSJoerg Sonnenberger  *    documentation and/or other materials provided with the distribution.
18c66c7e2fSzrj  * 3. Neither the name of the University nor the names of its contributors
190d5acd74SJohn Marino  *    may be used to endorse or promote products derived from this software
200d5acd74SJohn Marino  *    without specific prior written permission.
219cb03a6aSJoerg Sonnenberger  *
220d5acd74SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
239cb03a6aSJoerg Sonnenberger  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
249cb03a6aSJoerg Sonnenberger  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
250d5acd74SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
269cb03a6aSJoerg Sonnenberger  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
279cb03a6aSJoerg Sonnenberger  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
289cb03a6aSJoerg Sonnenberger  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
299cb03a6aSJoerg Sonnenberger  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
309cb03a6aSJoerg Sonnenberger  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
319cb03a6aSJoerg Sonnenberger  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
329cb03a6aSJoerg Sonnenberger  * SUCH DAMAGE.
330d5acd74SJohn Marino  *
340d5acd74SJohn Marino  * @(#)strtouq.c	8.1 (Berkeley) 6/4/93
350d5acd74SJohn Marino  * $FreeBSD: head/lib/libc/locale/wcstoull.c 227753 2011-11-20 14:45:42Z theraven $
369cb03a6aSJoerg Sonnenberger  */
379cb03a6aSJoerg Sonnenberger 
380d5acd74SJohn Marino 
399cb03a6aSJoerg Sonnenberger #include <errno.h>
409cb03a6aSJoerg Sonnenberger #include <limits.h>
419cb03a6aSJoerg Sonnenberger #include <stdlib.h>
429cb03a6aSJoerg Sonnenberger #include <wchar.h>
439cb03a6aSJoerg Sonnenberger #include <wctype.h>
440d5acd74SJohn Marino #include "xlocale_private.h"
459cb03a6aSJoerg Sonnenberger 
460d5acd74SJohn Marino /*
470d5acd74SJohn Marino  * Convert a wide character string to an unsigned long long integer.
480d5acd74SJohn Marino  */
490d5acd74SJohn Marino unsigned long long
wcstoull_l(const wchar_t * __restrict nptr,wchar_t ** __restrict endptr,int base,locale_t locale)500d5acd74SJohn Marino wcstoull_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
510d5acd74SJohn Marino     int base, locale_t locale)
520d5acd74SJohn Marino {
530d5acd74SJohn Marino 	const wchar_t *s;
540d5acd74SJohn Marino 	unsigned long long acc;
550d5acd74SJohn Marino 	wchar_t c;
560d5acd74SJohn Marino 	unsigned long long cutoff;
570d5acd74SJohn Marino 	int neg, any, cutlim;
580d5acd74SJohn Marino 	FIX_LOCALE(locale);
599cb03a6aSJoerg Sonnenberger 
600d5acd74SJohn Marino 	/*
610d5acd74SJohn Marino 	 * See strtoull for comments as to the logic used.
620d5acd74SJohn Marino 	 */
630d5acd74SJohn Marino 	s = nptr;
640d5acd74SJohn Marino 	do {
650d5acd74SJohn Marino 		c = *s++;
660d5acd74SJohn Marino 	} while (iswspace_l(c, locale));
670d5acd74SJohn Marino 	if (c == L'-') {
680d5acd74SJohn Marino 		neg = 1;
690d5acd74SJohn Marino 		c = *s++;
700d5acd74SJohn Marino 	} else {
710d5acd74SJohn Marino 		neg = 0;
720d5acd74SJohn Marino 		if (c == L'+')
730d5acd74SJohn Marino 			c = *s++;
740d5acd74SJohn Marino 	}
750d5acd74SJohn Marino 	if ((base == 0 || base == 16) &&
76*213582ebSMatthew Dillon 	    c == L'0' &&
77*213582ebSMatthew Dillon 	    (*s == L'x' || *s == L'X') &&
78*213582ebSMatthew Dillon 	    iswxdigit_l(s[1], locale))
79*213582ebSMatthew Dillon 	{
800d5acd74SJohn Marino 		c = s[1];
810d5acd74SJohn Marino 		s += 2;
820d5acd74SJohn Marino 		base = 16;
830d5acd74SJohn Marino 	}
840d5acd74SJohn Marino 	if (base == 0)
850d5acd74SJohn Marino 		base = c == L'0' ? 8 : 10;
860d5acd74SJohn Marino 	acc = any = 0;
870d5acd74SJohn Marino 	if (base < 2 || base > 36)
880d5acd74SJohn Marino 		goto noconv;
899cb03a6aSJoerg Sonnenberger 
900d5acd74SJohn Marino 	cutoff = ULLONG_MAX / base;
910d5acd74SJohn Marino 	cutlim = ULLONG_MAX % base;
920d5acd74SJohn Marino 	for ( ; ; c = *s++) {
930d5acd74SJohn Marino #ifdef notyet
940d5acd74SJohn Marino 		if (iswdigit_l(c, locale))
950d5acd74SJohn Marino 			c = digittoint_l(c, locale);
960d5acd74SJohn Marino 		else
970d5acd74SJohn Marino #endif
980d5acd74SJohn Marino 		if (c >= L'0' && c <= L'9')
990d5acd74SJohn Marino 			c -= L'0';
1000d5acd74SJohn Marino 		else if (c >= L'A' && c <= L'Z')
1010d5acd74SJohn Marino 			c -= L'A' - 10;
1020d5acd74SJohn Marino 		else if (c >= L'a' && c <= L'z')
1030d5acd74SJohn Marino 			c -= L'a' - 10;
1040d5acd74SJohn Marino 		else
1050d5acd74SJohn Marino 			break;
1060d5acd74SJohn Marino 		if (c >= base)
1070d5acd74SJohn Marino 			break;
1080d5acd74SJohn Marino 		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
1090d5acd74SJohn Marino 			any = -1;
1100d5acd74SJohn Marino 		else {
1110d5acd74SJohn Marino 			any = 1;
1120d5acd74SJohn Marino 			acc *= base;
1130d5acd74SJohn Marino 			acc += c;
1140d5acd74SJohn Marino 		}
1150d5acd74SJohn Marino 	}
1160d5acd74SJohn Marino 	if (any < 0) {
1170d5acd74SJohn Marino 		acc = ULLONG_MAX;
1180d5acd74SJohn Marino 		errno = ERANGE;
1190d5acd74SJohn Marino 	} else if (!any) {
1200d5acd74SJohn Marino noconv:
1210d5acd74SJohn Marino 		errno = EINVAL;
1220d5acd74SJohn Marino 	} else if (neg)
1230d5acd74SJohn Marino 		acc = -acc;
1240d5acd74SJohn Marino 	if (endptr != NULL)
1250d5acd74SJohn Marino 		*endptr = (wchar_t *)(any ? s - 1 : nptr);
1260d5acd74SJohn Marino 	return (acc);
1270d5acd74SJohn Marino }
1280d5acd74SJohn Marino unsigned long long
wcstoull(const wchar_t * __restrict nptr,wchar_t ** __restrict endptr,int base)1290d5acd74SJohn Marino wcstoull(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
1300d5acd74SJohn Marino     int base)
1310d5acd74SJohn Marino {
1320d5acd74SJohn Marino 	return wcstoull_l(nptr, endptr, base, __get_locale());
1330d5acd74SJohn Marino }
134