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