xref: /dflybsd-src/lib/libc/locale/wcstoll.c (revision 0d5acd7467c4e95f792ef49fceb3ab8e917ce86b)
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