19cb03a6aSJoerg Sonnenberger /*- 2*0d5acd74SJohn Marino * Copyright (c) 1992, 1993 3*0d5acd74SJohn Marino * The Regents of the University of California. All rights reserved. 4*0d5acd74SJohn Marino * 5*0d5acd74SJohn Marino * Copyright (c) 2011 The FreeBSD Foundation 69cb03a6aSJoerg Sonnenberger * All rights reserved. 7*0d5acd74SJohn Marino * Portions of this software were developed by David Chisnall 8*0d5acd74SJohn 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*0d5acd74SJohn Marino * 4. Neither the name of the University nor the names of its contributors 19*0d5acd74SJohn Marino * may be used to endorse or promote products derived from this software 20*0d5acd74SJohn Marino * without specific prior written permission. 219cb03a6aSJoerg Sonnenberger * 22*0d5acd74SJohn 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 25*0d5acd74SJohn 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. 33*0d5acd74SJohn Marino * 34*0d5acd74SJohn Marino * @(#)strtoq.c 8.1 (Berkeley) 6/4/93 35*0d5acd74SJohn Marino * $FreeBSD: head/lib/libc/locale/wcstoll.c 227753 2011-11-20 14:45:42Z theraven $ 369cb03a6aSJoerg Sonnenberger */ 379cb03a6aSJoerg Sonnenberger 38*0d5acd74SJohn 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> 44*0d5acd74SJohn Marino #include "xlocale_private.h" 459cb03a6aSJoerg Sonnenberger 46*0d5acd74SJohn Marino /* 47*0d5acd74SJohn Marino * Convert a wide character string to a long long integer. 48*0d5acd74SJohn Marino */ 49*0d5acd74SJohn Marino long long 50*0d5acd74SJohn Marino wcstoll_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, 51*0d5acd74SJohn Marino int base, locale_t locale) 52*0d5acd74SJohn Marino { 53*0d5acd74SJohn Marino const wchar_t *s; 54*0d5acd74SJohn Marino unsigned long long acc; 55*0d5acd74SJohn Marino wchar_t c; 56*0d5acd74SJohn Marino unsigned long long cutoff; 57*0d5acd74SJohn Marino int neg, any, cutlim; 58*0d5acd74SJohn Marino FIX_LOCALE(locale); 599cb03a6aSJoerg Sonnenberger 60*0d5acd74SJohn Marino /* 61*0d5acd74SJohn Marino * See strtoll for comments as to the logic used. 62*0d5acd74SJohn Marino */ 63*0d5acd74SJohn Marino s = nptr; 64*0d5acd74SJohn Marino do { 65*0d5acd74SJohn Marino c = *s++; 66*0d5acd74SJohn Marino } while (iswspace_l(c, locale)); 67*0d5acd74SJohn Marino if (c == L'-') { 68*0d5acd74SJohn Marino neg = 1; 69*0d5acd74SJohn Marino c = *s++; 70*0d5acd74SJohn Marino } else { 71*0d5acd74SJohn Marino neg = 0; 72*0d5acd74SJohn Marino if (c == L'+') 73*0d5acd74SJohn Marino c = *s++; 74*0d5acd74SJohn Marino } 75*0d5acd74SJohn Marino if ((base == 0 || base == 16) && 76*0d5acd74SJohn Marino c == L'0' && (*s == L'x' || *s == L'X')) { 77*0d5acd74SJohn Marino c = s[1]; 78*0d5acd74SJohn Marino s += 2; 79*0d5acd74SJohn Marino base = 16; 80*0d5acd74SJohn Marino } 81*0d5acd74SJohn Marino if (base == 0) 82*0d5acd74SJohn Marino base = c == L'0' ? 8 : 10; 83*0d5acd74SJohn Marino acc = any = 0; 84*0d5acd74SJohn Marino if (base < 2 || base > 36) 85*0d5acd74SJohn Marino goto noconv; 869cb03a6aSJoerg Sonnenberger 87*0d5acd74SJohn Marino cutoff = neg ? (unsigned long long)-(LLONG_MIN + LLONG_MAX) + LLONG_MAX 88*0d5acd74SJohn Marino : LLONG_MAX; 89*0d5acd74SJohn Marino cutlim = cutoff % base; 90*0d5acd74SJohn Marino cutoff /= base; 91*0d5acd74SJohn Marino for ( ; ; c = *s++) { 92*0d5acd74SJohn Marino #ifdef notyet 93*0d5acd74SJohn Marino if (iswdigit_l(c, locale)) 94*0d5acd74SJohn Marino c = digittoint_l(c, locale); 95*0d5acd74SJohn Marino else 96*0d5acd74SJohn Marino #endif 97*0d5acd74SJohn Marino if (c >= L'0' && c <= L'9') 98*0d5acd74SJohn Marino c -= L'0'; 99*0d5acd74SJohn Marino else if (c >= L'A' && c <= L'Z') 100*0d5acd74SJohn Marino c -= L'A' - 10; 101*0d5acd74SJohn Marino else if (c >= L'a' && c <= L'z') 102*0d5acd74SJohn Marino c -= L'a' - 10; 103*0d5acd74SJohn Marino else 104*0d5acd74SJohn Marino break; 105*0d5acd74SJohn Marino if (c >= base) 106*0d5acd74SJohn Marino break; 107*0d5acd74SJohn Marino if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) 108*0d5acd74SJohn Marino any = -1; 109*0d5acd74SJohn Marino else { 110*0d5acd74SJohn Marino any = 1; 111*0d5acd74SJohn Marino acc *= base; 112*0d5acd74SJohn Marino acc += c; 113*0d5acd74SJohn Marino } 114*0d5acd74SJohn Marino } 115*0d5acd74SJohn Marino if (any < 0) { 116*0d5acd74SJohn Marino acc = neg ? LLONG_MIN : LLONG_MAX; 117*0d5acd74SJohn Marino errno = ERANGE; 118*0d5acd74SJohn Marino } else if (!any) { 119*0d5acd74SJohn Marino noconv: 120*0d5acd74SJohn Marino errno = EINVAL; 121*0d5acd74SJohn Marino } else if (neg) 122*0d5acd74SJohn Marino acc = -acc; 123*0d5acd74SJohn Marino if (endptr != NULL) 124*0d5acd74SJohn Marino *endptr = (wchar_t *)(any ? s - 1 : nptr); 125*0d5acd74SJohn Marino return (acc); 126*0d5acd74SJohn Marino } 127*0d5acd74SJohn Marino long long 128*0d5acd74SJohn Marino wcstoll(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base) 129*0d5acd74SJohn Marino { 130*0d5acd74SJohn Marino return wcstoll_l(nptr, endptr, base, __get_locale()); 131*0d5acd74SJohn Marino } 132