Embedded Artistry libc
C Standard Library Support for Bare-metal Systems
strtoll.c File Reference
#include <ctype.h>
#include <limits.h>
#include <stdlib.h>
Include dependency graph for strtoll.c:

Go to the source code of this file.

Functions

long long int strtoll (const char *nptr, char **endptr, int base)
 

Function Documentation

◆ strtoll()

long long int strtoll ( const char *  nptr,
char **  endptr,
int  base 
)

Definition at line 43 of file strtoll.c.

44 {
45  const char* s;
46  /* LONGLONG */
47  long long int acc, cutoff;
48  int c;
49  int neg, any, cutlim;
50 
51  /* endptr may be NULL */
52 
53  // check base
54  if(base < 0 || base > 36)
55  {
56  // errno = EINVAL
57 
58  if(endptr)
59  {
60  *endptr = (char*)(uintptr_t)nptr;
61  }
62 
63  return 0;
64  }
65 
66 #ifdef __GNUC__
67  /* This outrageous construct just to shut up a GCC warning. */
68  (void)&acc;
69  (void)&cutoff;
70 #endif
71 
72  /*
73  * Skip white space and pick up leading +/- sign if any.
74  * If base is 0, allow 0x for hex and 0 for octal, else
75  * assume decimal; if base is already 16, allow 0x.
76  */
77  s = nptr;
78  do
79  {
80  c = (unsigned char)*s++;
81  } while(isspace(c));
82  if(c == '-')
83  {
84  neg = 1;
85  c = *s++;
86  }
87  else
88  {
89  neg = 0;
90  if(c == '+')
91  {
92  {
93  c = *s++;
94  }
95  }
96  }
97  if((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X'))
98  {
99  c = s[1];
100  s += 2;
101  base = 16;
102  }
103  if(base == 0)
104  {
105  {
106  base = c == '0' ? 8 : 10;
107  }
108  }
109 
110  /*
111  * Compute the cutoff value between legal numbers and illegal
112  * numbers. That is the largest legal value, divided by the
113  * base. An input number that is greater than this value, if
114  * followed by a legal input character, is too big. One that
115  * is equal to this value may be valid or not; the limit
116  * between valid and invalid numbers is then based on the last
117  * digit. For instance, if the range for long longs is
118  * [-9223372036854775808..9223372036854775807] and the input base
119  * is 10, cutoff will be set to 922337203685477580 and cutlim to
120  * either 7 (neg==0) or 8 (neg==1), meaning that if we have
121  * accumulated a value > 922337203685477580, or equal but the
122  * next digit is > 7 (or 8), the number is too big, and we will
123  * return a range error.
124  *
125  * Set any if any `digits' consumed; make it negative to indicate
126  * overflow.
127  */
128  cutoff = neg ? LLONG_MIN : LLONG_MAX;
129  cutlim = (int)(cutoff % base);
130  cutoff /= base;
131  if(neg)
132  {
133  if(cutlim > 0)
134  {
135  cutlim -= base;
136  cutoff += 1;
137  }
138  cutlim = -cutlim;
139  }
140  for(acc = 0, any = 0;; c = (unsigned char)*s++)
141  {
142  if(isdigit(c))
143  {
144  {
145  c -= '0';
146  }
147  }
148  else if(isalpha(c))
149  {
150  {
151  c -= isupper(c) ? 'A' - 10 : 'a' - 10;
152  }
153  }
154  else
155  {
156  {
157  break;
158  }
159  }
160  if(c >= base)
161  {
162  {
163  break;
164  }
165  }
166  if(any < 0)
167  {
168  {
169  continue;
170  }
171  }
172  if(neg)
173  {
174  if(acc < cutoff || (acc == cutoff && c > cutlim))
175  {
176  any = -1;
177  acc = LLONG_MIN;
178  // errno = ERANGE;
179  }
180  else
181  {
182  any = 1;
183  acc *= base;
184  acc -= c;
185  }
186  }
187  else
188  {
189  if(acc > cutoff || (acc == cutoff && c > cutlim))
190  {
191  any = -1;
192  acc = LLONG_MAX;
193  // errno = ERANGE;
194  }
195  else
196  {
197  any = 1;
198  acc *= base;
199  acc += c;
200  }
201  }
202  }
203  if(endptr != 0)
204  {
205  /* LINTED interface specification */
206  *endptr = (char*)(uintptr_t)(any ? s - 1 : nptr);
207  }
208  return (acc);
209 }
int isupper(int ch)
Checks if the given character is an uppercase character.
Definition: isupper.c:5
int isalpha(int ch)
Checks if the given character is an alphabetic character.
Definition: isalpha.c:5
#define LLONG_MIN
Definition: limits.h:64
int isspace(int ch)
Checks if the given character is a whitespace character.
Definition: isspace.c:5
int isdigit(int ch)
Checks if the given character is a numeric character.
Definition: isdigit.c:5

References isalpha(), isdigit(), isspace(), isupper(), and LLONG_MIN.