strtoull.c revision 140577
1231200Smm/*- 2231200Smm * Copyright (c) 1992, 1993 3231200Smm * The Regents of the University of California. All rights reserved. 4231200Smm * 5231200Smm * Redistribution and use in source and binary forms, with or without 6231200Smm * modification, are permitted provided that the following conditions 7231200Smm * are met: 8231200Smm * 1. Redistributions of source code must retain the above copyright 9231200Smm * notice, this list of conditions and the following disclaimer. 10231200Smm * 2. Redistributions in binary form must reproduce the above copyright 11231200Smm * notice, this list of conditions and the following disclaimer in the 12231200Smm * documentation and/or other materials provided with the distribution. 13231200Smm * 3. All advertising materials mentioning features or use of this software 14231200Smm * must display the following acknowledgement: 15231200Smm * This product includes software developed by the University of 16231200Smm * California, Berkeley and its contributors. 17231200Smm * 4. Neither the name of the University nor the names of its contributors 18231200Smm * may be used to endorse or promote products derived from this software 19231200Smm * without specific prior written permission. 20231200Smm * 21231200Smm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22231200Smm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23231200Smm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24231200Smm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25231200Smm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26231200Smm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27231200Smm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28231200Smm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29231200Smm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30231200Smm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31231200Smm * SUCH DAMAGE. 32231200Smm */ 33231200Smm 34231200Smm#if defined(LIBC_SCCS) && !defined(lint) 35231200Smmstatic char sccsid[] = "@(#)strtouq.c 8.1 (Berkeley) 6/4/93"; 36231200Smm#endif /* LIBC_SCCS and not lint */ 37231200Smm#include <sys/cdefs.h> 38231200Smm__FBSDID("$FreeBSD: head/lib/libc/stdlib/strtoull.c 140577 2005-01-21 13:31:02Z ache $"); 39231200Smm 40231200Smm#include <limits.h> 41231200Smm#include <errno.h> 42231200Smm#include <ctype.h> 43231200Smm#include <stdlib.h> 44231200Smm 45231200Smm/* 46231200Smm * Convert a string to an unsigned long long integer. 47231200Smm * 48231200Smm * Assumes that the upper and lower case 49231200Smm * alphabets and digits are each contiguous. 50231200Smm */ 51231200Smmunsigned long long 52231200Smmstrtoull(const char * __restrict nptr, char ** __restrict endptr, int base) 53231200Smm{ 54231200Smm const char *s; 55231200Smm unsigned long long acc; 56231200Smm char c; 57231200Smm unsigned long long cutoff; 58231200Smm int neg, any, cutlim; 59231200Smm 60231200Smm /* 61231200Smm * See strtoq for comments as to the logic used. 62231200Smm */ 63231200Smm s = nptr; 64231200Smm do { 65231200Smm c = *s++; 66231200Smm } while (isspace((unsigned char)c)); 67231200Smm if (c == '-') { 68231200Smm neg = 1; 69231200Smm c = *s++; 70231200Smm } else { 71231200Smm neg = 0; 72231200Smm if (c == '+') 73231200Smm c = *s++; 74231200Smm } 75231200Smm if ((base == 0 || base == 16) && 76231200Smm c == '0' && (*s == 'x' || *s == 'X') && 77231200Smm ((s[1] >= '0' && s[1] <= '9') || 78231200Smm (s[1] >= 'A' && s[1] <= 'F') || 79231200Smm (s[1] >= 'a' && s[1] <= 'f'))) { 80231200Smm c = s[1]; 81231200Smm s += 2; 82231200Smm base = 16; 83231200Smm } 84231200Smm if (base == 0) 85231200Smm base = c == '0' ? 8 : 10; 86231200Smm acc = any = 0; 87231200Smm if (base < 2 || base > 36) 88231200Smm goto noconv; 89231200Smm 90231200Smm cutoff = ULLONG_MAX / base; 91231200Smm cutlim = ULLONG_MAX % base; 92231200Smm for ( ; ; c = *s++) { 93231200Smm if (c >= '0' && c <= '9') 94231200Smm c -= '0'; 95231200Smm else if (c >= 'A' && c <= 'Z') 96231200Smm c -= 'A' - 10; 97231200Smm else if (c >= 'a' && c <= 'z') 98231200Smm c -= 'a' - 10; 99231200Smm else 100231200Smm break; 101231200Smm if (c >= base) 102231200Smm break; 103231200Smm if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) 104231200Smm any = -1; 105231200Smm else { 106231200Smm any = 1; 107231200Smm acc *= base; 108231200Smm acc += c; 109231200Smm } 110231200Smm } 111231200Smm if (any < 0) { 112231200Smm acc = ULLONG_MAX; 113231200Smm errno = ERANGE; 114231200Smm } else if (!any) { 115231200Smmnoconv: 116231200Smm errno = EINVAL; 117231200Smm } else if (neg) 118231200Smm acc = -acc; 119231200Smm if (endptr != NULL) 120231200Smm *endptr = (char *)(any ? s - 1 : nptr); 121231200Smm return (acc); 122231200Smm} 123231200Smm