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. 18*c66c7e2fSzrj * 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 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) && 760d5acd74SJohn Marino c == L'0' && (*s == L'x' || *s == L'X')) { 770d5acd74SJohn Marino c = s[1]; 780d5acd74SJohn Marino s += 2; 790d5acd74SJohn Marino base = 16; 800d5acd74SJohn Marino } 810d5acd74SJohn Marino if (base == 0) 820d5acd74SJohn Marino base = c == L'0' ? 8 : 10; 830d5acd74SJohn Marino acc = any = 0; 840d5acd74SJohn Marino if (base < 2 || base > 36) 850d5acd74SJohn Marino goto noconv; 869cb03a6aSJoerg Sonnenberger 870d5acd74SJohn Marino cutoff = ULLONG_MAX / base; 880d5acd74SJohn Marino cutlim = ULLONG_MAX % base; 890d5acd74SJohn Marino for ( ; ; c = *s++) { 900d5acd74SJohn Marino #ifdef notyet 910d5acd74SJohn Marino if (iswdigit_l(c, locale)) 920d5acd74SJohn Marino c = digittoint_l(c, locale); 930d5acd74SJohn Marino else 940d5acd74SJohn Marino #endif 950d5acd74SJohn Marino if (c >= L'0' && c <= L'9') 960d5acd74SJohn Marino c -= L'0'; 970d5acd74SJohn Marino else if (c >= L'A' && c <= L'Z') 980d5acd74SJohn Marino c -= L'A' - 10; 990d5acd74SJohn Marino else if (c >= L'a' && c <= L'z') 1000d5acd74SJohn Marino c -= L'a' - 10; 1010d5acd74SJohn Marino else 1020d5acd74SJohn Marino break; 1030d5acd74SJohn Marino if (c >= base) 1040d5acd74SJohn Marino break; 1050d5acd74SJohn Marino if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) 1060d5acd74SJohn Marino any = -1; 1070d5acd74SJohn Marino else { 1080d5acd74SJohn Marino any = 1; 1090d5acd74SJohn Marino acc *= base; 1100d5acd74SJohn Marino acc += c; 1110d5acd74SJohn Marino } 1120d5acd74SJohn Marino } 1130d5acd74SJohn Marino if (any < 0) { 1140d5acd74SJohn Marino acc = ULLONG_MAX; 1150d5acd74SJohn Marino errno = ERANGE; 1160d5acd74SJohn Marino } else if (!any) { 1170d5acd74SJohn Marino noconv: 1180d5acd74SJohn Marino errno = EINVAL; 1190d5acd74SJohn Marino } else if (neg) 1200d5acd74SJohn Marino acc = -acc; 1210d5acd74SJohn Marino if (endptr != NULL) 1220d5acd74SJohn Marino *endptr = (wchar_t *)(any ? s - 1 : nptr); 1230d5acd74SJohn Marino return (acc); 1240d5acd74SJohn Marino } 1250d5acd74SJohn Marino unsigned long long 1260d5acd74SJohn Marino wcstoull(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, 1270d5acd74SJohn Marino int base) 1280d5acd74SJohn Marino { 1290d5acd74SJohn Marino return wcstoull_l(nptr, endptr, base, __get_locale()); 1300d5acd74SJohn Marino } 131