]> git.ipfire.org Git - thirdparty/squid.git/blob - src/parser/Tokenizer.cc
Merged from trunk
[thirdparty/squid.git] / src / parser / Tokenizer.cc
1 #include "squid.h"
2 #include "parser/Tokenizer.h"
3
4 bool
5 Parser::Tokenizer::token(SBuf &returnedToken, const CharacterSet &delimiters)
6 {
7 SBuf savebuf(buf_);
8 skip(delimiters);
9 SBuf::size_type tokenLen = buf_.findFirstOf(delimiters); // not found = npos => consume to end
10 if (tokenLen == SBuf::npos && !delimiters['\0']) {
11 // no delimiter found, nor is NUL/EOS/npos acceptible as one
12 buf_ = savebuf;
13 return false;
14 }
15 SBuf retval = buf_.consume(tokenLen);
16 skip(delimiters);
17 returnedToken = retval;
18 return true;
19 }
20
21 bool
22 Parser::Tokenizer::prefix(SBuf &returnedToken, const CharacterSet &tokenChars, const SBuf::size_type limit)
23 {
24 SBuf::size_type prefixLen = buf_.substr(0,limit).findFirstNotOf(tokenChars);
25 if (prefixLen == 0)
26 return false;
27 returnedToken = buf_.consume(prefixLen);
28 return true;
29 }
30
31 bool
32 Parser::Tokenizer::skip(const CharacterSet &tokenChars)
33 {
34 SBuf::size_type prefixLen = buf_.findFirstNotOf(tokenChars);
35 if (prefixLen == 0)
36 return false;
37 buf_.consume(prefixLen);
38 return true;
39 }
40
41 bool
42 Parser::Tokenizer::skip(const SBuf &tokenToSkip)
43 {
44 if (buf_.startsWith(tokenToSkip)) {
45 buf_.consume(tokenToSkip.length());
46 return true;
47 }
48 return false;
49 }
50
51 bool
52 Parser::Tokenizer::skip(const char tokenChar)
53 {
54 if (buf_[0] == tokenChar) {
55 buf_.consume(1);
56 return true;
57 }
58 return false;
59 }
60
61 /* reworked from compat/strtoll.c */
62 bool
63 Parser::Tokenizer::int64(int64_t & result, int base)
64 {
65 if (buf_.isEmpty())
66 return false;
67
68 //fixme: account for buf_.size()
69 bool neg = false;
70 const char *s = buf_.rawContent();
71 const char *end = buf_.rawContent() + buf_.length();
72
73 if (*s == '-') {
74 neg = true;
75 ++s;
76 } else if (*s == '+') {
77 ++s;
78 }
79 if (s >= end) return false;
80 if (( base == 0 || base == 16) && *s == '0' && (s+1 <= end ) &&
81 tolower(*(s+1)) == 'x') {
82 s += 2;
83 base = 16;
84 }
85 if (base == 0) {
86 if ( *s == '0') {
87 base = 8;
88 ++s;
89 } else {
90 base = 10;
91 }
92 }
93 if (s >= end) return false;
94
95 uint64_t cutoff;
96
97 cutoff = neg ? -static_cast<uint64_t>(INT64_MIN) : INT64_MAX;
98 int cutlim = cutoff % static_cast<int64_t>(base);
99 cutoff /= static_cast<uint64_t>(base);
100
101 int any = 0, c;
102 int64_t acc = 0;
103 for (c = *s++; s <= end; c = *s++) {
104 if (xisdigit(c)) {
105 c -= '0';
106 } else if (xisalpha(c)) {
107 c -= xisupper(c) ? 'A' - 10 : 'a' - 10;
108 } else {
109 break;
110 }
111 if (c >= base)
112 break;
113 if (any < 0 || static_cast<uint64_t>(acc) > cutoff || (static_cast<uint64_t>(acc) == cutoff && c > cutlim))
114 any = -1;
115 else {
116 any = 1;
117 acc *= base;
118 acc += c;
119 }
120 }
121
122 if (any == 0) // nothing was parsed
123 return false;
124 if (any < 0) {
125 acc = neg ? INT64_MIN : INT64_MAX;
126 errno = ERANGE;
127 return false;
128 } else if (neg)
129 acc = -acc;
130
131 result = acc;
132 buf_.consume(s - buf_.rawContent() -1);
133 return true;
134 }