strtoull.c revision 82982
1264790Sbapt/*- 2264790Sbapt * Copyright (c) 1992, 1993 3264790Sbapt * The Regents of the University of California. All rights reserved. 4264790Sbapt * 5264790Sbapt * Redistribution and use in source and binary forms, with or without 6264790Sbapt * modification, are permitted provided that the following conditions 7264790Sbapt * are met: 8264790Sbapt * 1. Redistributions of source code must retain the above copyright 9264790Sbapt * notice, this list of conditions and the following disclaimer. 10264790Sbapt * 2. Redistributions in binary form must reproduce the above copyright 11264790Sbapt * notice, this list of conditions and the following disclaimer in the 12264790Sbapt * documentation and/or other materials provided with the distribution. 13264790Sbapt * 3. All advertising materials mentioning features or use of this software 14264790Sbapt * must display the following acknowledgement: 15264790Sbapt * This product includes software developed by the University of 16264790Sbapt * California, Berkeley and its contributors. 17264790Sbapt * 4. Neither the name of the University nor the names of its contributors 18264790Sbapt * may be used to endorse or promote products derived from this software 19264790Sbapt * without specific prior written permission. 20264790Sbapt * 21264790Sbapt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22264790Sbapt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23264790Sbapt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24264790Sbapt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25264790Sbapt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26264790Sbapt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27264790Sbapt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28264790Sbapt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29264790Sbapt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30264790Sbapt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31264790Sbapt * SUCH DAMAGE. 32264790Sbapt */ 33264790Sbapt 34264790Sbapt#if defined(LIBC_SCCS) && !defined(lint) 35264790Sbaptstatic char sccsid[] = "@(#)strtouq.c 8.1 (Berkeley) 6/4/93"; 36264790Sbapt#endif /* LIBC_SCCS and not lint */ 37264790Sbapt 38264790Sbapt#ifndef lint 39264790Sbaptstatic const char rcsid[] = 40264790Sbapt "$FreeBSD: head/lib/libc/stdlib/strtoull.c 82982 2001-09-04 17:12:15Z ache $"; 41264790Sbapt#endif 42264790Sbapt 43264790Sbapt#include <sys/types.h> 44264790Sbapt 45264790Sbapt#include <limits.h> 46264790Sbapt#include <errno.h> 47264790Sbapt#include <ctype.h> 48264790Sbapt#include <stdlib.h> 49264790Sbapt 50264790Sbapt/* 51264790Sbapt * Convert a string to an unsigned long long integer. 52264790Sbapt * 53264790Sbapt * Assumes that the upper and lower case 54264790Sbapt * alphabets and digits are each contiguous. 55264790Sbapt */ 56264790Sbaptunsigned long long 57264790Sbaptstrtoull(nptr, endptr, base) 58264790Sbapt const char *nptr; 59264790Sbapt char **endptr; 60264790Sbapt register int base; 61264790Sbapt{ 62264790Sbapt register const char *s; 63264790Sbapt register unsigned long long acc; 64264790Sbapt register unsigned char c; 65264790Sbapt register unsigned long long cutoff; 66264790Sbapt register int neg, any, cutlim; 67264790Sbapt 68264790Sbapt /* 69264790Sbapt * See strtoq for comments as to the logic used. 70264790Sbapt */ 71264790Sbapt s = nptr; 72264790Sbapt do { 73264790Sbapt c = *s++; 74264790Sbapt } while (isspace(c)); 75264790Sbapt if (c == '-') { 76264790Sbapt neg = 1; 77264790Sbapt c = *s++; 78264790Sbapt } else { 79264790Sbapt neg = 0; 80264790Sbapt if (c == '+') 81264790Sbapt c = *s++; 82264790Sbapt } 83264790Sbapt if ((base == 0 || base == 16) && 84264790Sbapt c == '0' && (*s == 'x' || *s == 'X')) { 85264790Sbapt c = s[1]; 86264790Sbapt s += 2; 87264790Sbapt base = 16; 88264790Sbapt } 89264790Sbapt if (base == 0) 90264790Sbapt base = c == '0' ? 8 : 10; 91264790Sbapt acc = any = 0; 92264790Sbapt if (base < 2 || base > 36) 93264790Sbapt goto noconv; 94264790Sbapt 95264790Sbapt cutoff = ULLONG_MAX / base; 96264790Sbapt cutlim = ULLONG_MAX % base; 97264790Sbapt for ( ; ; c = *s++) { 98264790Sbapt if (!isascii(c)) 99264790Sbapt break; 100264790Sbapt if (isdigit(c)) 101264790Sbapt c -= '0'; 102264790Sbapt else if (isalpha(c)) 103264790Sbapt c -= isupper(c) ? 'A' - 10 : 'a' - 10; 104264790Sbapt else 105264790Sbapt break; 106264790Sbapt if (c >= base) 107264790Sbapt break; 108264790Sbapt if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) 109264790Sbapt any = -1; 110264790Sbapt else { 111264790Sbapt any = 1; 112264790Sbapt acc *= base; 113264790Sbapt acc += c; 114264790Sbapt } 115264790Sbapt } 116264790Sbapt if (any < 0) { 117264790Sbapt acc = ULLONG_MAX; 118264790Sbapt errno = ERANGE; 119264790Sbapt } else if (!any) { 120264790Sbaptnoconv: 121264790Sbapt errno = EINVAL; 122264790Sbapt } else if (neg) 123264790Sbapt acc = -acc; 124264790Sbapt if (endptr != NULL) 125264790Sbapt *endptr = (char *)(any ? s - 1 : nptr); 126264790Sbapt return (acc); 127264790Sbapt} 128264790Sbapt