1 // Utility subroutines
2
3 #include "util.h"
4
5 /////////////////////////////////////////////////////////////////////////////////////
6 // String functions
7 /////////////////////////////////////////////////////////////////////////////////////
8
split(const std::string & s,char c,std::vector<std::string> & v)9 void split(const std::string& s, char c, std::vector<std::string>& v) {
10 std::string::size_type i = 0;
11 std::string::size_type j = s.find(c);
12
13 while (j != std::string::npos) {
14 v.push_back(s.substr(i, j - i));
15 i = ++j;
16 j = s.find(c, j);
17 }
18
19 if (j == std::string::npos) {
20 v.push_back(s.substr(i, s.length()));
21 }
22 }
23
24 // Copy substring str[a,b] into substr and returns substr
substr(char * substr,char * str,int a,int b)25 char *substr(char* substr, char* str, int a, int b) {
26 if (b < a) {
27 int i = b;
28 b = a;
29 a = i;
30 }
31 if (b - a > 1000) {
32 printf("Function substr: >1000 chars to copy. Exiting.\n");
33 exit(6);
34 }
35 char* dest = substr;
36 char* source = str + a;
37 char* send = str + b;
38 while (*source != '\0' && source <= send)
39 *(dest++) = *(source++);
40 *dest = '\0';
41 return substr;
42 }
43
44 // Similar to Perl's tr/abc/ABC/: Replaces all chars in str found in one list with characters from the second list
45 // Returns the number of replaced characters
strtr(char * str,const char oldchars[],const char newchars[])46 int strtr(char* str, const char oldchars[], const char newchars[]) {
47 char* ptr;
48 const char *plist;
49 int ntr = 0;
50 for (ptr = str; *ptr != '\0'; ptr++)
51 for (plist = oldchars; *plist != '\0'; plist++)
52 if (*ptr == *plist) {
53 *ptr = newchars[plist - oldchars];
54 ntr++;
55 break;
56 }
57 return ntr;
58 }
59
60 // Similar to Perl's tr/abc//d: deletes all chars in str found in the list
61 // Returns number of removed characters
strtrd(char * str,const char chars[])62 int strtrd(char* str, const char chars[]) {
63 char* ptr0 = str;
64 char* ptr1 = str;
65 const char *plist;
66 while (*ptr1 != '\0') {
67 for (plist = chars; *plist != '\0'; plist++)
68 if (*ptr1 == *plist)
69 break;
70 if (*plist == '\0') {
71 *ptr0 = *ptr1;
72 ptr0++;
73 }
74 ptr1++;
75 }
76 *ptr0 = *ptr1;
77 return ptr1 - ptr0;
78 }
79
80 // Similar to Perl's tr/a-z//d: deletes all chars in str found in the list
81 // Returns number of removed characters
strtrd(char * str,char char1,char char2)82 int strtrd(char* str, char char1, char char2) {
83 char* ptr0 = str;
84 char* ptr1 = str;
85 while (*ptr1 != '\0') {
86 if (*ptr1 >= char1 && *ptr1 <= char2) {
87 *ptr0 = *ptr1;
88 ptr0++;
89 }
90 ptr1++;
91 }
92 *ptr0 = *ptr1;
93 return ptr1 - ptr0;
94 }
95
96 // Counts the number of characters in str that are in range between char1 and char2
strcount(char * str,char char1,char char2)97 int strcount(char* str, char char1, char char2) {
98 char* ptr = str;
99 int count = 0;
100 while (*ptr != '\0') {
101 if (*ptr >= char1 && *ptr <= char2)
102 count++;
103 ptr++;
104 }
105 return count;
106 }
107
108 // transforms str into an all uppercase string
uprstr(char * str)109 char* uprstr(char* str) {
110 char* s = str;
111 while (*s != '\0') {
112 if (*s >= 'a' && *s <= 'z')
113 *s += 'A' - 'a';
114 s++;
115 }
116 return (str);
117 }
118
119 // transforms str into an all uppercase string
lwrstr(char * str)120 char* lwrstr(char* str) {
121 char* s = str;
122 while (*s != '\0') {
123 if (*s >= 'A' && *s <= 'Z')
124 *s += 'a' - 'A';
125 s++;
126 }
127 return (str);
128 }
129
130 // Returns leftmost integer in ptr and sets the pointer to first char after
131 // the integer. If no integer is found, returns INT_MIN and sets pt to NULL
132
strint(char * & ptr)133 int strint(char*& ptr) {
134 const char* ptr0 = ptr;
135 if (!ptr)
136 return INT_MIN;
137 while (*ptr != '\0' && !(*ptr >= '0' && *ptr <= '9'))
138 ptr++;
139 if (*ptr == '\0') {
140 ptr = 0;
141 return INT_MIN;
142 }
143 int i;
144 if (ptr > ptr0 && *(ptr - 1) == '-')
145 i = -atoi(ptr);
146 else
147 i = atoi(ptr);
148 while (*ptr >= '0' && *ptr <= '9')
149 ptr++;
150 return i;
151 }
152
153 //
154 //int strint(const char* ptr) {
155 // const char* ptr0 = ptr;
156 // if (!ptr)
157 // return INT_MIN;
158 // while (*ptr != '\0' && !(*ptr >= '0' && *ptr <= '9'))
159 // ptr++;
160 // if (*ptr == '\0') {
161 // ptr = 0;
162 // return INT_MIN;
163 // }
164 // int i;
165 // if (ptr > ptr0 && *(ptr - 1) == '-')
166 // i = -atoi(ptr);
167 // else
168 // i = atoi(ptr);
169 // while (*ptr >= '0' && *ptr <= '9')
170 // ptr++;
171 // return i;
172 //}
173
174 // Same as strint, but interpretes '*' as default
strinta(char * & ptr,int deflt)175 int strinta(char*& ptr, int deflt) {
176 int i;
177 if (!ptr)
178 return INT_MIN;
179 while (*ptr != '\0' && !(*ptr >= '0' && *ptr <= '9') && *ptr != '*')
180 ptr++;
181 if (*ptr == '\0') {
182 ptr = 0;
183 return INT_MIN;
184 }
185 if (*ptr == '*') {
186 ptr++;
187 return deflt;
188 }
189 if (*(ptr - 1) == '-')
190 i = atoi(ptr - 1);
191 else
192 i = atoi(ptr);
193 while (*ptr >= '0' && *ptr <= '9')
194 ptr++;
195 return i;
196 }
197
198 // Returns leftmost float in ptr and sets the pointer to first char after
199 // the float. If no float is found, returns FLT_MIN and sets pt to NULL
strflt(char * & ptr)200 float strflt(char*& ptr) {
201 float i;
202 char* ptr0 = ptr;
203 if (!ptr)
204 return FLT_MIN;
205 while (*ptr != '\0' && !(*ptr >= '0' && *ptr <= '9'))
206 ptr++;
207 if (*ptr == '\0') {
208 ptr = 0;
209 return FLT_MIN;
210 }
211 if (ptr > ptr0 && *(ptr - 1) == '-')
212 i = -atof(ptr);
213 else
214 i = atof(ptr);
215 while ((*ptr >= '0' && *ptr <= '9') || *ptr == '.')
216 ptr++;
217 return i;
218 }
219
220 // Same as strint, but interpretes '*' as default
strflta(char * & ptr,float deflt)221 float strflta(char*& ptr, float deflt) {
222 float i;
223 if (!ptr)
224 return FLT_MIN;
225 while (*ptr != '\0' && !(*ptr >= '0' && *ptr <= '9') && *ptr != '*')
226 ptr++;
227 if (*ptr == '\0') {
228 ptr = 0;
229 return FLT_MIN;
230 }
231 if (*ptr == '*') {
232 ptr++;
233 return deflt;
234 }
235 if (*(ptr - 1) == '-')
236 i = -atof(ptr);
237 else
238 i = atof(ptr);
239 while ((*ptr >= '0' && *ptr <= '9') || *ptr == '.')
240 ptr++;
241 return i;
242 }
243
244 // QSort sorting routine. time complexity of O(N ln(N)) on average
245 // Sorts the index array k between elements i='left' and i='right' in such a way that afterwards
246 // v[k[i]] is sorted downwards (up=-1) or upwards (up=+1)
QSortInt(int v[],int k[],int left,int right,int up)247 void QSortInt(int v[], int k[], int left, int right, int up) {
248 int i;
249 int last; // last element to have been swapped
250
251 if (left >= right)
252 return; // do nothing if less then 2 elements to sort
253 // Put pivot element in the middle of the sort range to the side (to position 'left') ...
254 swapi(k, left, (left + right) / 2);
255 last = left;
256 // ... and swap all elements i SMALLER than the pivot
257 // with an element that is LARGER than the pivot (element last+1):
258 if (up == 1) {
259 for (i = left + 1; i <= right; i++)
260 if (v[k[i]] < v[k[left]])
261 swapi(k, ++last, i);
262 }
263 else
264 for (i = left + 1; i <= right; i++)
265 if (v[k[i]] > v[k[left]])
266 swapi(k, ++last, i);
267
268 // Put the pivot to the right of the elements which are SMALLER, left to elements which are LARGER
269 swapi(k, left, last);
270
271 // Sort the elements left from the pivot and right from the pivot
272 QSortInt(v, k, left, last - 1, up);
273 QSortInt(v, k, last + 1, right, up);
274 }
275
276 // QSort sorting routine. time complexity of O(N ln(N)) on average
277 // Sorts the index array k between elements i='left' and i='right' in such a way that afterwards
278 // v[k[i]] is sorted downwards (up=-1) or upwards (up=+1)
QSortFloat(float v[],int k[],int left,int right,int up)279 void QSortFloat(float v[], int k[], int left, int right, int up) {
280 int i;
281 int last; // last element to have been swapped
282 void swapi(int k[], int i, int j);
283
284 if (left >= right)
285 return; // do nothing if less then 2 elements to sort
286 // Put pivot element in the middle of the sort range to the side (to position 'left') ...
287 swapi(k, left, (left + right) / 2);
288 last = left;
289 // ... and swap all elements i SMALLER than the pivot
290 // with an element that is LARGER than the pivot (element last+1):
291 if (up == 1) {
292 for (i = left + 1; i <= right; i++)
293 if (v[k[i]] < v[k[left]])
294 swapi(k, ++last, i);
295 }
296 else
297 for (i = left + 1; i <= right; i++)
298 if (v[k[i]] > v[k[left]])
299 swapi(k, ++last, i);
300
301 // Put the pivot to the right of the elements which are SMALLER, left to elements which are LARGER
302 swapi(k, left, last);
303
304 // Sort the elements left from the pivot and right from the pivot
305 QSortFloat(v, k, left, last - 1, up);
306 QSortFloat(v, k, last + 1, right, up);
307 }
308
readU16(char ** ptr,uint16_t & result)309 void readU16(char** ptr, uint16_t &result) {
310 unsigned char array[2];
311
312 array[0] = (unsigned char) (**ptr);
313 (*ptr)++;
314 array[1] = (unsigned char) (**ptr);
315 (*ptr)++;
316
317 result = array[0] | (array[1] << 8);
318 }
319
readU32(char ** ptr,uint32_t & result)320 void readU32(char** ptr, uint32_t &result) {
321 unsigned char array[4];
322
323 array[0] = (unsigned char) (**ptr);
324 (*ptr)++;
325 array[1] = (unsigned char) (**ptr);
326 (*ptr)++;
327 array[2] = (unsigned char) (**ptr);
328 (*ptr)++;
329 array[3] = (unsigned char) (**ptr);
330 (*ptr)++;
331
332 result = array[0] | (array[1] << 8) | (array[2] << 16) | (array[3] << 24);
333 }
334