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