File Coverage

strtoint64.h
Criterion Covered Total %
statement 39 41 95.1
branch 47 56 83.9
condition n/a
subroutine n/a
pod n/a
total 86 97 88.6


line stmt bran cond sub pod time code
1             /*
2             * Converts a string into a int64_t
3             *
4             * based on OpenBSD: strtoll.c,v 1.6 2005/11/10 10:00:17 espie Exp $
5             */
6            
7             /*-
8             * Copyright (c) 1992 The Regents of the University of California.
9             * All rights reserved.
10             *
11             * Redistribution and use in source and binary forms, with or without
12             * modification, are permitted provided that the following conditions
13             * are met:
14             * 1. Redistributions of source code must retain the above copyright
15             * notice, this list of conditions and the following disclaimer.
16             * 2. Redistributions in binary form must reproduce the above copyright
17             * notice, this list of conditions and the following disclaimer in the
18             * documentation and/or other materials provided with the distribution.
19             * 3. Neither the name of the University nor the names of its contributors
20             * may be used to endorse or promote products derived from this software
21             * without specific prior written permission.
22             *
23             * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24             * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25             * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26             * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27             * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28             * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29             * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30             * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31             * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32             * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33             * SUCH DAMAGE.
34             */
35            
36             #include
37            
38             /*
39             * Convert a string to an int64_t/uint64_t.
40             */
41            
42             static uint64_t
43 897           strtoint64(pTHX_ const char *s, int base, int sign)
44             {
45 897           uint64_t acc = 0;
46 897           int c, neg, between = 0;
47            
48 897           int mdoo = may_die_on_overflow; /* we copy it to avoid a race
49             condition */
50 897           uint64_t upper_mul_limit = 0;
51            
52             /*
53             * Skip white space and pick up leading +/- sign if any.
54             * If base is 0, allow 0x for hex and 0 for octal, else
55             * assume decimal; if base is already 16, allow 0x.
56             */
57             do {
58 897           c = (unsigned char) *s++;
59 897 50         } while (isspace(c));
60 897 100         if (c == '-') {
61 206           neg = 1;
62 206           c = *s++;
63 206 100         if (!sign) overflow(aTHX_ "negative sign found when parsing unsigned number");
64             } else {
65 691           neg = 0;
66 691 50         if (c == '+')
67 0           c = *s++;
68             }
69 895 100         if ((base == 0 || base == 16) &&
    100          
    100          
70 41 50         c == '0' && (*s == 'x' || *s == 'X')) {
    0          
71 41           c = s[1];
72 41           s += 2;
73 41           base = 16;
74             }
75 895 100         if (base == 0)
76 309 50         base = c == '0' ? 8 : 10;
77            
78 895 100         if (mdoo) upper_mul_limit = UINT64_MAX / base;
79            
80 19782           for (;; c = (unsigned char) *s++) {
81 20677 100         if (isdigit(c))
82 17168           c -= '0';
83 3509 100         else if (isalpha(c))
84 2513 100         c -= isupper(c) ? 'A' - 10 : 'a' - 10;
85 996 100         else if ((c == '_') && between)
    50          
86 105           continue; /* ignore underscores as Perl does */
87             else
88             break;
89 19681 50         if (c >= base)
90 0           break;
91 19681 100         if (mdoo) {
92 383 100         if (acc > upper_mul_limit) overflow(aTHX_ (sign ? out_of_bounds_error_s : out_of_bounds_error_u));
    100          
93 380           acc *= base;
94 380 100         if (UINT64_MAX - acc < c) overflow(aTHX_ (sign ? out_of_bounds_error_s : out_of_bounds_error_u));
    50          
95 379           acc += c;
96             }
97             else {
98 19298           acc = acc * base + c;
99             }
100 19677           between = 1;
101             }
102 903 100         if ( mdoo && sign &&
    100          
    100          
103 16 100         ( acc > (neg ? (~(uint64_t)INT64_MIN + 1) : INT64_MAX) ) ) overflow(aTHX_ out_of_bounds_error_s);
104            
105 889 100         return (neg ? ~acc + 1 : acc);
106             }
107