1 module more.parse;
2 
3 // returns: ubyte.max on error
4 ubyte hexValue(char c)
5 {
6     if(c <= '9') {
7         return (c >= '0') ? cast(ubyte)(c - '0') : ubyte.max;
8     }
9     if(c >= 'a') {
10         return (c <= 'f') ? cast(ubyte)(c + 10 - 'a') : ubyte.max;
11     }
12     if(c >= 'A' && c <= 'F') {
13         return cast(ubyte)(c + 10 - 'A');
14     }
15     return ubyte.max;
16 }
17 unittest
18 {
19     assert(ubyte.max == hexValue('/'));
20     assert(0 == hexValue('0'));
21     assert(9 == hexValue('9'));
22     assert(ubyte.max == hexValue(':'));
23 
24     assert(ubyte.max == hexValue('@'));
25     assert(10 == hexValue('A'));
26     assert(15 == hexValue('F'));
27     assert(ubyte.max == hexValue('G'));
28 
29     assert(ubyte.max == hexValue('`'));
30     assert(10 == hexValue('a'));
31     assert(15 == hexValue('f'));
32     assert(ubyte.max == hexValue('g'));
33 
34     for(int cAsInt = char.min; cAsInt <= char.max; cAsInt++) {
35         char c = cast(char)cAsInt;
36         if(c >= '0' && c <= '9') {
37             assert(c - '0' == hexValue(c));
38         } else if(c >= 'a' && c <= 'f') {
39             assert(c + 10 - 'a' == hexValue(c));
40         } else if(c >= 'A' && c <= 'F') {
41             assert(c + 10 - 'A' == hexValue(c));
42         } else {
43             assert(ubyte.max == hexValue(c));
44         }
45     }
46 }
47 
48 bool hasCharSet(string charSet)(const(char)* str, const(char)* limit)
49 {
50     for(;; str++)
51     {
52         if (str >= limit)
53             return false;
54         auto c = *str;
55         foreach(charSetChar; charSet) {
56             if(c == charSetChar) {
57                 return true;
58             }
59         }
60     }
61 }
62 pragma(inline)
63 bool hasCharSet(string charSet)(const(char)[] str)
64 {
65     return hasCharSet!charSet(str.ptr, str.ptr + str.length);
66 }
67 
68 /**
69 Iterates over the given string and returns a pointer to the first character that
70 is not in the given $(D charSet).
71 */
72 inout(char)* skipCharSet(string charSet)(inout(char)* str)
73 {
74   STR_LOOP:
75     for(;;)
76     {
77         auto c = *str;
78         foreach(charSetChar; charSet) {
79             if(c == charSetChar) {
80                 str++;
81                 continue STR_LOOP;
82             }
83         }
84         break;
85     }
86     return str;
87 }
88 /// ditto
89 inout(char)* skipCharSet(string charSet)(inout(char)* str, const(char)* limit)
90 {
91   STR_LOOP:
92     for(;str < limit;)
93     {
94         auto c = *str;
95         foreach(charSetChar; charSet) {
96             if(c == charSetChar) {
97                 str++;
98                 continue STR_LOOP;
99             }
100         }
101         break;
102     }
103     return str;
104 }
105 /**
106 Iterates over the given string and returns a pointer to the first character that
107 is not a space.
108 */
109 pragma(inline) inout(char)* skipSpace(inout(char)* str)
110 {
111     return skipCharSet!" "(str);
112 }
113 pragma(inline) inout(char)* skipSpace(inout(char)* str, const(char)* limit)
114 {
115     return skipCharSet!" "(str, limit);
116 }
117 
118 // TODO: create more overloads
119 bool startsWith(const(char)* str, const(char)* limit, const(char)[] needle)
120 {
121     auto size = limit - str;
122     if(size < needle.length)
123     {
124         return false;
125     }
126     return str[0..needle.length] == needle[];
127 }
128 
129 /** Returns a pointer to the first occurence of $(D c) or $(D sentinal).
130 */
131 inout(char)* findCharPtr(char sentinal = '\0')(inout(char)* str, char c)
132 {
133     for(;;str++) {
134         if(*str == c || *str == sentinal) {
135             return str;
136         }
137     }
138 }
139 /** Returns a pointer to the first occurence of $(D c).  If no $(D c) is found
140     then the limit is returned.
141  */
142 inout(char)* findCharPtr(inout(char)* str, const(char)* limit, char c)
143 {
144     for(;;str++) {
145         if(str >= limit || *str == c) {
146            return str;
147         }
148     }
149 }
150 /// ditto
151 pragma(inline)
152 inout(char)* findCharPtr(inout(char)[] str, char c)
153 {
154     return findCharPtr(str.ptr, str.ptr + str.length, c);
155 }
156 
157 /** Returns the index of the first occurence of $(D c).  If no $(D c) is found
158     then the length of the string is returned.
159  */
160 size_t findCharIndex(char sentinal = '\0')(const(char)* str, char c)
161 {
162     auto saveStart = str;
163     for(;;str++) {
164         if(*str == c || *str == sentinal) {
165             return str - saveStart;
166         }
167     }
168 }
169 size_t findCharIndex(const(char)* str, const(char)* limit, char c)
170 {
171     auto saveStart = str;
172     for(;;str++) {
173         if(str >= limit || *str == c) {
174            return str - saveStart;
175         }
176     }
177 }
178 size_t findCharIndex(const(char)[] str, char c)
179 {
180     foreach(i, strChar; str) {
181         if(c == strChar) {
182             return i;
183         }
184     }
185     return str.length;
186 }