blob: 8ad108d9f7c6168720c0459e3dc3353e870c6bb7 [file] [log] [blame]
xiaohu.huangf3ffd7b2022-11-01 15:14:52 +08001/*
2 * Copyright (c) 2021-2022 Amlogic, Inc. All rights reserved.
3 *
4 * SPDX-License-Identifier: MIT
5 */
6
7#include <limits.h>
8#include <errno.h>
9#include <stdlib.h>
10#include "aml_strtoul.h"
11#include "aml_isdigit.h"
12#include "aml_isspace.h"
13#include "aml_isalpha.h"
14#include "aml_isupper.h"
15
16unsigned long strtoul(const char *nptr, char **endptr, int base)
17{
18 const char *s = nptr;
19 unsigned long acc;
20 int c;
21 unsigned long cutoff;
22 int neg = 0, any, cutlim;
23
24 /*
25 * See strtol for comments as to the logic used.
26 */
27 do {
28 c = *s++;
29 } while (isspace(c));
30 if (c == '-') {
31 neg = 1;
32 c = *s++;
33 } else if (c == '+') {
34 c = *s++;
35 }
36
37 if ((base == 0 || base == 16) &&
38 c == '0' && (*s == 'x' || *s == 'X')) {
39 c = s[1];
40 s += 2;
41 base = 16;
42 }
43
44 if (base == 0)
45 base = c == '0' ? 8 : 10;
46
47 cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
48 cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
49 for (acc = 0, any = 0;; c = *s++) {
50 if (isdigit(c))
51 c -= '0';
52 else if (isalpha(c))
53 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
54 else
55 break;
56
57 if (c >= base)
58 break;
59 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
60 any = -1;
61 else {
62 any = 1;
63 acc *= base;
64 acc += c;
65 }
66 }
67 if (any < 0) {
68 acc = ULONG_MAX;
69 errno = ERANGE;
70 } else if (neg)
71 acc = -acc;
72 if (endptr != NULL)
73 *endptr = (char *)(any ? s - 1 : nptr);
74
75 return acc;
76}