/** @file | |
Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR> | |
This program and the accompanying materials | |
are licensed and made available under the terms and conditions of the BSD License | |
which accompanies this distribution. The full text of the license may be found at | |
http://opensource.org/licenses/bsd-license. | |
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
Copyright (c) 1990, 1993 | |
The Regents of the University of California. All rights reserved. | |
Redistribution and use in source and binary forms, with or without | |
modification, are permitted provided that the following conditions | |
are met: | |
1. Redistributions of source code must retain the above copyright | |
notice, this list of conditions and the following disclaimer. | |
2. Redistributions in binary form must reproduce the above copyright | |
notice, this list of conditions and the following disclaimer in the | |
documentation and/or other materials provided with the distribution. | |
3. Neither the name of the University nor the names of its contributors | |
may be used to endorse or promote products derived from this software | |
without specific prior written permission. | |
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
SUCH DAMAGE. | |
Original version ID: | |
@(#)strtol.c 8.1 (Berkeley) 6/4/93 | |
NetBSD: wcstol.c,v 1.1 2001/09/27 16:30:36 yamt Exp | |
Citrus: xpg4dl/FreeBSD/lib/libc/locale/wcstol.c,v 1.2 2001/09/21 16:11:41 yamt Exp | |
NetBSD: _wcstol.h,v 1.3 2005/11/29 03:11:59 christos Exp | |
*/ | |
/* | |
* function template for wcstol, wcstoll and wcstoimax. | |
* | |
* parameters: | |
* _FUNCNAME : function name | |
* __wINT : return type | |
* __wINT_MIN : lower limit of the return type | |
* __wINT_MAX : upper limit of the return type | |
*/ | |
__wINT | |
_FUNCNAME( | |
const wchar_t *nptr, | |
wchar_t **endptr, | |
int base | |
) | |
{ | |
const wchar_t *s; | |
__wINT acc, cutoff; | |
wint_t wc; | |
int i; | |
int neg, any, cutlim; | |
_DIAGASSERT(nptr != NULL); | |
/* endptr may be NULL */ | |
#ifdef __GNUC__ | |
(void)&acc; (void)&cutoff; | |
#endif | |
/* check base value */ | |
if (base && (base < 2 || base > 36)) { | |
errno = EINVAL; | |
return 0; | |
} | |
/* | |
* Skip white space and pick up leading +/- sign if any. | |
* If base is 0, allow 0x for hex and 0 for octal, else | |
* assume decimal; if base is already 16, allow 0x. | |
*/ | |
s = nptr; | |
do { | |
wc = (wchar_t) *s++; | |
} while (iswspace(wc)); | |
if (wc == L'-') { | |
neg = 1; | |
wc = *s++; | |
} else { | |
neg = 0; | |
if (wc == L'+') | |
wc = *s++; | |
} | |
if ((base == 0 || base == 16) && | |
wc == L'0' && (*s == L'x' || *s == L'X')) { | |
wc = s[1]; | |
s += 2; | |
base = 16; | |
} | |
if (base == 0) | |
base = ((wc == L'0') ? 8 : 10); | |
/* | |
* See strtol for comments as to the logic used. | |
*/ | |
cutoff = neg ? __wINT_MIN : __wINT_MAX; | |
cutlim = (int)(cutoff % base); | |
cutoff /= base; | |
if (neg) { | |
if (cutlim > 0) { | |
cutlim -= base; | |
cutoff += 1; | |
} | |
cutlim = -cutlim; | |
} | |
for (acc = 0, any = 0;; wc = (wchar_t) *s++) { | |
i = __wctoint((wchar_t)wc); | |
if (i == -1) | |
break; | |
if (i >= base) | |
break; | |
if (any < 0) | |
continue; | |
if (neg) { | |
if (acc < cutoff || (acc == cutoff && i > cutlim)) { | |
any = -1; | |
acc = __wINT_MIN; | |
errno = ERANGE; | |
} else { | |
any = 1; | |
acc *= base; | |
acc -= i; | |
} | |
} else { | |
if (acc > cutoff || (acc == cutoff && i > cutlim)) { | |
any = -1; | |
acc = __wINT_MAX; | |
errno = ERANGE; | |
} else { | |
any = 1; | |
acc *= base; | |
acc += i; | |
} | |
} | |
} | |
if (endptr != 0) | |
*endptr = __UNCONST(any ? s - 1 : nptr); | |
return (acc); | |
} |