1 
2 //  ------------------------------------------------------------------
3 //  The Goldware Library
4 //  Copyright (C) 1990-1999 Odinn Sorensen
5 //  Copyright (C) 1999-2000 Alexander S. Aganichev
6 //  ------------------------------------------------------------------
7 //  This program is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU General Public License as
9 //  published by the Free Software Foundation; either version 2 of the
10 //  License, or (at your option) any later version.
11 //
12 //  This program is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 //  General Public License for more details.
16 //
17 //  You should have received a copy of the GNU General Public License
18 //  along with this program; if not, write to the Free Software
19 //  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 //  ------------------------------------------------------------------
21 //  $Id: gstrutil.cpp,v 1.36 2011/10/19 23:31:31 stas_degteff Exp $
22 //  ------------------------------------------------------------------
23 //  Based on source from the CXL library by Mike Smedley.
24 //  String manipulation.
25 //  ------------------------------------------------------------------
26 
27 #include <gctype.h>
28 #include <cstdio>
29 #include <stdarg.h>
30 
31 // -------------------------------------------------------------------
32 // snprintf() and vsnprintf()
33 
34 #if  defined(_MSC_VER)
35 /* It is need a workaround for implementation "speciality" in snprintf() and vsnprintf() from Microsoft. */
snprintf(char * buffer,size_t sizeOfBuffer,const char * format,...)36 int snprintf( char *buffer, size_t sizeOfBuffer, const char *format, ... )
37 {
38   va_list argptr;
39   va_start(argptr, format);
40   int r = _vsnprintf( buffer, sizeOfBuffer, format, argptr );
41   if( r == -1 || r >= sizeOfBuffer )
42     buffer[sizeOfBuffer-1] = '\0';
43   va_end(argptr);
44   return r;
45 }
46 # define HAVE_SNPRINTF 1
vsnprintf(char * buffer,size_t sizeOfBuffer,const char * format,va_list argptr)47 int vsnprintf( char *buffer, size_t sizeOfBuffer, const char *format, va_list argptr )
48 {
49   int r = _vsnprintf( buffer, sizeOfBuffer, format, argptr );
50   if( r == -1 || r >= sizeOfBuffer )
51     buffer[sizeOfBuffer-1] = '\0';
52   return r;
53 }
54 # define HAVE_VSNPRINTF 1
55 #endif
56 
57 #ifndef HAVE_SNPRINTF
58 # if defined(HAVE__SNPRINTF)
59 #  define snprintf _snprintf
60 #  define HAVE_SNPRINTF 1
61 # endif
62 #endif
63 #ifndef HAVE_VSNPRINTF
64 # if defined(HAVE__VSNPRINTF)
65 #  define vsnprintf _vsnprintf
66 #  define HAVE_VSNPRINTF 1
67 # endif
68 #endif
69 
70 #if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
71 # include "snprintf.c"
72 # if !defined(HAVE__SNPRINTF)
73 #  define HAVE_SNPRINTF 1
74 # endif
75 # if !defined(HAVE__VSNPRINTF)
76 #  define HAVE_VSNPRINTF 1
77 # endif
78 #endif
79 
80 //--------------------------------------------------------------------
81 
82 #include <gstrall.h>
83 #include <glog.h>
84 #include <gdbgerr.h>
85 
86 extern glog LOG;
87 
88 
89 //  ------------------------------------------------------------------
90 //  Determines if a string is blank
91 
strblank(const char * str)92 bool strblank(const char* str) {
93 
94   const char* p;
95 
96   for(p = str; *p; p++)
97     if(not isspace(*p))
98       return false;
99 
100   return true;
101 }
102 
103 
104 //  ------------------------------------------------------------------
105 //  Changes all occurrences of one character to another
106 
strchg(char * str,char oldch,char newch)107 size_t strchg(char *str, char oldch, char newch)
108 {
109   size_t count = 0;
110 
111   for (char *p = str; *p; p++)
112   {
113     if (oldch == *p)
114     {
115       *p = newch;
116       count++;
117     }
118   }
119 
120   return count;
121 }
122 
123 
124 //  ------------------------------------------------------------------
125 //  Changes all occurrences of one character to another
126 
strchg(std::string & str,char oldch,char newch)127 size_t strchg(std::string &str, char oldch, char newch)
128 {
129   size_t count = 0;
130 
131   std::string::iterator it = str.begin();
132   std::string::iterator end = str.end();
133   for (; it != end; it++)
134   {
135     if (oldch == *it)
136     {
137       *it = newch;
138       count++;
139     }
140   }
141 
142   return count;
143 }
144 
145 
146 //  ------------------------------------------------------------------
147 //  Deletes a substring from within a string
148 
strdel(const char * substr,char * str)149 static char* strdel(const char* substr, char* str) {
150 
151   char* dest = strstr(str, substr);
152   if(!dest)
153     return NULL;
154   char* src = dest + strlen(substr);
155 //  strcpy(dest, src);  /* Source and destination overlap. This is rigth. */
156   memmove(dest, src, strlen(src)+1);
157 
158   return str;
159 }
160 
161 
162 //  ------------------------------------------------------------------
163 //  Deletes a substring from within a string, ignores case
164 
stridel(const char * substr,char * str)165 static char* stridel(const char* substr, char* str) {
166 
167   char* dest = (char*)striinc(substr, str);
168   if(!dest)
169     return NULL;
170   char* src = dest + strlen(substr);
171 //  strcpy(dest, src);
172   memmove(dest, src, strlen(src)+1);  /* Source and destination overlaps. */
173 
174   return str;
175 }
176 
177 
178 //  ------------------------------------------------------------------
179 //  Deletes all occurrences of one string inside another
180 
stridela(const char * substr,char * str)181 char* stridela(const char* substr, char* str) {
182 
183   int count = 0;
184   char* p = str;
185 
186   while((p = (char*)striinc(substr, p)) != NULL) {
187     stridel(substr, p);
188     count++;
189   }
190 
191   if(count)
192     return str;
193   return NULL;
194 }
195 
196 
197 //  ------------------------------------------------------------------
198 //  Compare two strings, allowing wildcards
199 
strnicmpw(const char * str1,const char * str2,int len)200 int strnicmpw(const char* str1, const char* str2, int len) {
201 
202   int cmp = 0;
203 
204   for(int n=0; n<len; n++) {
205     // Single char match?
206     if(str1[n] == '?')
207       continue;
208     // Matches rest of string?
209     else if(str1[n] == '*')
210       return 0;
211     // Compare chars
212     else if((cmp = compare_two(g_toupper(str1[n]), g_toupper(str2[n]))) != 0)
213       return cmp;
214   }
215 
216   return cmp;
217 }
218 
219 
220 //  ------------------------------------------------------------------
221 //  Determines if string1 is included in string2
222 
striinc(const char * str1,const char * str2)223 const char* striinc(const char* str1, const char* str2) {
224 
225   int max = strlen(str1);
226 
227   for(const char* p=str2; *p; p++)
228     if(!strnicmp(str1,p,max))
229       return p;
230 
231   return NULL;                         // string1 not found in string2
232 }
233 
234 
235 //  ------------------------------------------------------------------
236 //  Inserts one string into another
237 
strins(const char * instr,char * str,int st_pos)238 char* strins(const char* instr, char* str, int st_pos) {
239 
240   int i, leninstr;
241 
242   // get length of string to insert
243   leninstr = strlen(instr);
244 
245   // shift affected portion of str text to the right
246   for(i=strlen(str); i>=st_pos; i--)
247     *(str+leninstr+i) = *(str+i);
248 
249   // insert instr text
250   for(i=0; i<leninstr; i++)
251     *(str+st_pos+i) = *(instr+i);
252 
253   // return address of modified string
254   return str;
255 }
256 
257 
258 //  ------------------------------------------------------------------
259 //  String search and replace, case insensitive
260 
strisrep(char * str,const char * search,const char * replace)261 char* strisrep(char* str, const char* search, const char* replace) {
262 
263   char* p;
264 
265   if((p = (char*)striinc(search,str)) != NULL) {
266     stridel(search, str);
267     strins(replace, str, (int)(p-str));
268     p = str;
269   }
270 
271   return p;
272 }
273 
274 
275 //  ------------------------------------------------------------------
276 //  Changes all occurrences of one string to another
277 
strischg(char * str,const char * find,const char * replace)278 char* strischg(char* str, const char* find, const char* replace) {
279 
280   int count = 0;
281   char* p = str;
282 
283   int len = strlen(replace);
284   while((p = (char*)striinc(find, p)) != NULL) {
285     strisrep(p, find, replace);
286     p += len;
287     count++;
288   }
289 
290   if(count)
291     return str;
292   return NULL;
293 }
294 
295 
296 //  ------------------------------------------------------------------
297 //  Changes all occurrences of one string to another
298 
strischg(std::string & str,const char * find,const char * replace)299 void strischg(std::string &str, const char* find, const char* replace)
300 {
301   size_t lenf = strlen(find);
302   size_t lenr = strlen(replace);
303   size_t length = str.length();
304 
305   for (size_t pos = 0; pos < length; )
306   {
307     if (strnieql(&(str.c_str()[pos]), find, lenf))
308     {
309       str.replace(pos, lenf, replace, lenr);
310       pos += lenr;
311       length = str.length();
312     }
313     else
314       pos++;
315   }
316 }
317 
318 
319 //  ------------------------------------------------------------------
320 //  Takes a long number and makes a string with the form x.xxx.xxx.xxx
321 
longdotstr(long num)322 char* longdotstr(long num) {
323 
324   // 1234567890123
325   // 4.294.967.296
326 
327   static char buf[15];
328   return longdotstr(buf, num);
329 }
330 
331 
332 //  ------------------------------------------------------------------
333 //  Takes a long number and makes a string with the form x.xxx.xxx.xxx
334 
longdotstr(char * str,long num)335 char* longdotstr(char* str, long num) {
336 
337   char tmp[20], pos=0;
338 
339   char* out = str;
340   char* ptr = tmp;
341 
342   do {
343     if(pos == 3 or pos == 6 or pos == 9)
344       *ptr++ = '.';
345     pos++;
346     *ptr++ = (char)(num % 10 + '0');
347   } while((num = num/10) > 0);
348 
349   while(ptr-- > tmp)
350     *str++ = *ptr;
351   *str = NUL;
352 
353   return out;
354 }
355 
356 
357 //  ------------------------------------------------------------------
358 
strp2c(char * str)359 char* strp2c(char* str) {
360 
361   int len = *str;
362 
363   memmove(str, str+1, len);       // Copy data part
364   str[len] = NUL;                 // Set length
365   return str;
366 }
367 
368 
369 //  ------------------------------------------------------------------
370 
strnp2c(char * str,int n)371 char* strnp2c(char* str, int n) {
372 
373   int len = (n < *str) ? n : *str;
374 
375   memmove(str, str+1, len);     // Copy data part
376   str[len] = NUL;               // Set length
377   return str;
378 }
379 
380 
381 //  ------------------------------------------------------------------
382 
strnp2cc(char * dest,const char * str,int n)383 char* strnp2cc(char* dest, const char* str, int n) {
384 
385   int len = (n < *str) ? n : *str;
386 
387   memcpy(dest, str+1, len);           // Copy data part
388   dest[len] = NUL;                    // Set length
389   return dest;
390 }
391 
392 
393 //  ------------------------------------------------------------------
394 
strc2p(char * str)395 char* strc2p(char* str) {
396 
397   char len = (char)strlen(str);
398 
399   memmove(str+1, str, len);       // Copy data part
400   *str = len;                     // Set length
401   return str;
402 }
403 
404 
405 //  ------------------------------------------------------------------
406 //  Strip the quotes off a quoted string ("" or '')
407 
StripQuotes(char * str)408 char* StripQuotes(char* str) {
409 
410   int len;
411 
412   switch(*str) {
413     case '\'':
414     case '\"':
415       len = strlen(str);
416       switch(*(str+len-1)) {
417         case '\'':
418         case '\"':
419           memmove(str, str+1, len);
420           str[len-2] = NUL;
421       }
422   }
423   return str;
424 }
425 
426 
427 //  ------------------------------------------------------------------
428 //  Right justifies a string
429 
strrjust(char * str)430 char* strrjust(char* str) {
431 
432   char* p;
433   char* q;
434 
435   for(p=str; *p; p++)
436     ;   // find end of string
437   p--;
438   for(q=p; isspace(*q) and q>=str; q--)
439     ;   // find last non-space character
440   if(p != q) {
441     while(q >= str) {
442       *p-- = *q;
443       *q-- = ' ';
444     }
445   }
446   return str;
447 }
448 
449 
450 //  ------------------------------------------------------------------
451 //  Changes all occurrences of one string to another
452 
strschg(char * str,const char * find,const char * replace)453 char* strschg(char* str, const char* find, const char* replace) {
454 
455   int count = 0;
456   char* p = str;
457 
458   int len = strlen(replace);
459   while((p = strstr(p, find)) != NULL) {
460     strsrep(p, find, replace);
461     p += len;
462     count++;
463   }
464 
465   if(count)
466     return str;
467   return NULL;
468 }
469 
470 
471 //  ------------------------------------------------------------------
472 //  Adjusts the size of a string
473 
strsetsz(char * str,int newsize)474 char* strsetsz(char* str, int newsize) {
475 
476   int i;
477 
478   int len = strlen(str);
479   if(newsize < len)
480     *(str+newsize) = NUL;
481   else {
482     for(i=len; i<newsize; i++)
483       *(str+i) = ' ';
484     *(str+i) = NUL;
485   }
486 
487   return str;
488 }
489 
490 
491 //  ------------------------------------------------------------------
492 //  Shifts a string left
493 
strshl(char * str,int count)494 char* strshl(char* str, int count) {
495 
496   int i, j;
497 
498   if(*str) {
499     for(j=0; j<count; j++) {
500       for(i=0; *(str+i); i++)
501         *(str+i) = *(str+i+1);
502       *(str+i-1) = ' ';
503     }
504   }
505 
506   return str;
507 }
508 
509 
510 //  ------------------------------------------------------------------
511 //  Shifts a string right
512 
strshr(char * str,int count)513 char* strshr(char* str, int count) {
514 
515   int i, j, len;
516 
517   if(*str) {
518     len = strlen(str)-1;
519     for(j=0; j<count; j++) {
520       for(i=len; i>0; i--)
521         *(str+i) = *(str+i-1);
522       *(str) = ' ';
523     }
524   }
525 
526   return str;
527 }
528 
529 
530 //  ------------------------------------------------------------------
531 //  String search and replace, case sensitive
532 
strsrep(char * str,const char * search,const char * replace)533 char* strsrep(char* str, const char* search, const char* replace) {
534 
535   char* p;
536 
537   if((p = strstr(str, search)) != NULL) {
538     strdel(search, str);
539     strins(replace, str, (int)(p-str));
540     p = str;
541   }
542 
543   return p;
544 }
545 
546 
547 //  ------------------------------------------------------------------
548 //  Trims trailing spaces off of a string
549 
strtrim(char * p)550 char* strtrim(char* p) {
551 
552   int i;
553   for(i = strlen(p) - 1; (i >= 0) and (isspace(p[i]) or iscntrl(p[i])); i--) {}
554   p[i + 1] = NUL;
555   return p;
556 }
557 
558 
strtrim(std::string & str)559 std::string &strtrim(std::string &str)
560 {
561   if (!str.empty())
562   {
563     std::string::iterator begin = str.begin();
564     std::string::iterator trail = str.end();
565 
566     while (trail != begin)
567     {
568       --trail;
569       if (not isspace(*trail) and not iscntrl(*trail))
570       {
571         ++trail;
572         break;
573       }
574     }
575 
576     str.erase(trail, str.end());
577   }
578 
579   return str;
580 }
581 
582 
583 //  ------------------------------------------------------------------
584 //  Trims leading spaces off of a string
585 
strltrim(char * str)586 char* strltrim(char* str)
587 {
588   char* p;
589   char* q;
590 
591   p = q = str;
592   while(*p and (isspace(*p) or iscntrl(*p)))
593     p++;
594 
595   if(p != q) {
596     while(*p)
597       *q++ = *p++;
598     *q = NUL;
599   }
600 
601   return str;
602 }
603 
604 //  ------------------------------------------------------------------
605 
strltrim(std::string & str)606 std::string &strltrim(std::string &str)
607 {
608   if (!str.empty())
609   {
610     std::string::iterator begin = str.begin();
611     std::string::iterator end = str.end();
612     std::string::iterator it = begin;
613 
614     for (; (it != end) && isspace(*it); it++) { /**/ }
615     if (it != begin) str.erase(begin, it);
616   }
617 
618   return str;
619 }
620 
621 //  ------------------------------------------------------------------
622 
strlword(const char * str,const char * separator)623 const char* strlword(const char* str, const char *separator) {
624 
625   char buf[256];
626   static char left[40];
627 
628   *left = NUL;
629   if(*str) {
630     strxcpy(buf, str, sizeof(buf));
631     if(strtok(buf, (separator == NULL) ? " \t\n\r" : separator) != NULL) {
632       strxcpy(left, buf, sizeof(left));
633     }
634   }
635   return left;
636 }
637 
638 
639 //  ------------------------------------------------------------------
640 
strrword(const char * str,const char * separator)641 const char* strrword(const char* str, const char *separator) {
642 
643   char* ptr;
644   char* ptr2;
645   char buf[256];
646   static char right[40];
647 
648   *right = NUL;
649   if(*str) {
650     strxcpy(buf, str, sizeof(buf));
651     if(separator == NULL) {
652       separator = " \t\n\r";
653     }
654     ptr = strtok(buf, separator);
655     ptr2 = ptr;
656     while(ptr != NULL) {
657       ptr2 = ptr;
658       ptr = strtok(NULL, separator);
659     }
660     if(ptr2) {
661       strxcpy(right, ptr2, sizeof(right));
662     }
663   }
664   return right;
665 }
666 
667 
668 //  ------------------------------------------------------------------
669 //  copy not more n-1 bytes of "s" into "d", insert '\0' into end of string.
670 //  return d
strxcpy(TCHAR * d,const TCHAR * s,size_t n)671 TCHAR *strxcpy(TCHAR *d, const TCHAR *s, size_t n)
672 {
673 #if defined(_tcsncpy_s)
674   _tcsncpy_s(d, n, s, _TRUNCATE);
675 #else
676   if (n)
677   {
678     strncpy(d, s, n-1);
679     d[n-1] = NUL;
680   }
681   else
682     *d = NUL;
683 #endif
684   return d;
685 }
686 
687 
688 //  ------------------------------------------------------------------
689 
strxcat(char * dest,const char * src,size_t max)690 char *strxcat(char *dest, const char *src, size_t max)
691 {
692   while (*dest and (max > 0)) {
693     --max;
694     dest++;
695   }
696   while (*src and (max > 0)) {
697     --max;
698     *dest++ = *src++;
699   }
700   *dest = NUL;
701   return dest;
702 }
703 
704 
705 //  ------------------------------------------------------------------
706 
strxmerge(char * dest,size_t max,...)707 char *strxmerge(char *dest, size_t max, ...)
708 {
709   va_list a;
710   va_start(a, max);
711   for(; max > 0;) {
712     const char *src = va_arg(a, const char *);
713     if (src == NULL)
714       break;
715     while (*src and (max > 0)) {
716       --max;
717       *dest++ = *src++;
718     }
719   }
720   va_end(a);
721   *dest = NUL;
722   return dest;
723 }
724 
725 
726 //  ------------------------------------------------------------------
727 
gsprintf(TCHAR * buffer,size_t sizeOfBuffer,const TCHAR * __file,int __line,const TCHAR * format,...)728 int gsprintf(TCHAR* buffer, size_t sizeOfBuffer, const TCHAR* __file, int __line, const TCHAR* format, ...)
729 {
730   int ret = -1;
731 
732   if (!buffer || !format)
733   {
734     LOG.errpointer(__file, __line);
735     LOG.printf( "! Parameter is NULL pointer: gsprintf(%s,%lu,%s,...).",
736                 (buffer?"buffer":"NULL"), (unsigned long)sizeOfBuffer, (format?"format":"NULL") );
737     PointerErrorExit();
738     return -1;
739   }
740   if (!sizeOfBuffer)
741   {
742     LOG.errmemory(__file, __line);
743     LOG.printf("! Buffer size is 0: gsprintf(buf,0,...).");
744     MemoryErrorExit();
745     return -1;
746   }
747   if (!*format)
748   {
749     LOG.errtest(__file, __line);
750     LOG.printf("! Format is empty string: gsprintf(buffer,%lu,"",...).", (unsigned long)sizeOfBuffer);
751     return 0;
752   }
753 
754   {
755     va_list argptr;
756     va_start(argptr, format);
757 /* _vsnprintf_s() may cause exception. Need to test before enabling.
758 #   if __VISUAL_C_NOT_LESS(14,00)  // defined HAVE__VSTPRINTF_S // _vsnprintf_s() recommended in MSDN
759     ret = _vsnprintf_s(buffer, _TRUNCATE, format, argptr);
760     if (ret < 0)
761     {
762       if (sizeOfBuffer>7) strcpy(buffer," ERROR ");
763       else               buffer[sizeOfBuffer-1] = '\0';
764       LOG.errtest(__FILE__,__LINE__-5);
765       LOG.printf("! gsprintf()(buffer,%i,%s,...): _vsnprintf_s() error: \"%s\".", sizeOfBuffer, format, strerror(errno));
766       return -1;
767     }
768     buffer[sizeOfBuffer-1] = '\0';  // Microsoft implementation don't write final '\0' if buffer full.
769 #   elif __VISUAL_C_NOT_LESS(10,00)  // defined HAVE__VSTPRINTF // _vsnprintf() exist in VS6 and deprecated in VS2005
770 */
771 #   if __VISUAL_C_NOT_LESS(10,00)  // defined HAVE__VSTPRINTF // _vsnprintf() exist in VS6 and deprecated in VS2005
772 
773     char * b1 = new char[sizeOfBuffer+1];
774     const size_t endOfBuffer = sizeOfBuffer-1;
775     ret = _vsnprintf(b1, sizeOfBuffer+1, format, argptr);
776     if (ret == -1 || ret >= sizeOfBuffer) // Microsoft implementation returns -1 when buffer overflow.
777     {
778       strncpy(buffer,b1,endOfBuffer);
779       buffer[endOfBuffer] = '\0';  // Microsoft implementation don't write final '\0' when buffer full.
780       if (b1[sizeOfBuffer] && strlen(buffer)>=endOfBuffer)
781       {
782         LOG.printf("! %s", gerrinfo("Memory error", __file, __line));
783         LOG.printf("! gsprintf(buffer,%i,%s,...): buffer overflow, result in next line:", sizeOfBuffer, format);
784         LOG.printf("! %s", buffer);
785         if (sizeOfBuffer>17) memcpy(buffer, " ERROR, see log! ", 17);
786         else if (sizeOfBuffer>7) memcpy(buffer," ERROR ", 7);
787       }
788     }
789     else if (ret < 0)
790     {
791       LOG.errtest(__file, __line);
792       LOG.printf("! gsprintf()(buffer,%i,%s,...): _vsnprintf() error: \"%s\".", sizeOfBuffer, format, strerror(errno));
793       TestErrorExit();
794     }
795     else
796     {
797       strncpy(buffer,b1,endOfBuffer);
798       buffer[endOfBuffer] = '\0';
799     }
800 
801 #   elif defined HAVE_VSNPRINTF  // C99 and above
802 
803     ret = vsnprintf(buffer, sizeOfBuffer, format, argptr);
804     if (ret < 0) // Until glibc 2.0.6 vsnprintf() would return -1 when the output was truncated.
805     {
806       LOG.errtest(__file, __line);
807       char * errstring = strerror(errno);
808       LOG.printf("! gsprintf(buffer,%i,%s,...): vsnprintf() error: \"%s\".", sizeOfBuffer, format, errstring);
809       if ( strcmp(errstring, "Invalid or incomplete multibyte or wide character")==0 )
810       {
811         LOG.printf("! Possible reason: you don't set locale properly");
812       }
813       TestErrorExit();
814     }
815     else if (ret >= sizeOfBuffer)
816     {
817       if (sizeOfBuffer>17) strcpy(buffer, " ERROR, see log! ");
818       else if (sizeOfBuffer>7) strcpy(buffer," ERROR ");
819       else buffer[sizeOfBuffer-1] = '\0';
820       LOG.printf("! %s", gerrinfo("Memory error", __file, __line));
821       LOG.printf("! gsprintf(buffer,%i,%s,...): buffer overflow (need %i bytes).", sizeOfBuffer, format, ret);
822     }
823 
824 #   else
825 #   error Please look C library of your compiler for function like vsnprintf, what do not write more than size bytes into string.
826 #   endif
827     va_end(argptr);
828   }
829 
830   return ret;
831 }
832 
833 
834 //  ------------------------------------------------------------------
835 
GTok(char * sep)836 GTok::GTok(char* sep) {
837 
838   separator = sep ? sep : ", \t";
839 }
840 
841 
842 //  ------------------------------------------------------------------
843 
844 #if defined(__GNUC__) && !defined(__EMX__)
845 
strupr(char * s)846 char* strupr(char* s) {
847 
848   char* p = s;
849   while(*p) {
850     *p = g_toupper(*p);
851     p++;
852   }
853   return s;
854 }
855 
strlwr(char * s)856 char* strlwr(char* s) {
857 
858   char* p = s;
859   while(*p) {
860     *p = g_tolower(*p);
861     p++;
862   }
863   return s;
864 }
865 
866 #endif
867 
868 
869 //  ------------------------------------------------------------------
870 
tokenize(gstrarray & array,const TCHAR * str,const TCHAR * delim)871 void tokenize(gstrarray &array, const TCHAR* str, const TCHAR *delim)
872 {
873   if (delim == NULL) delim = ", \t";
874 
875 #if defined(_tcstok_s)
876   TCHAR *tmp = _strdup(str);
877   TCHAR *next_token;
878   TCHAR *token = _tcstok_s(tmp, delim, &next_token);
879 #else
880   TCHAR *tmp = strdup(str);
881   TCHAR *token = strtok(tmp, delim);
882 #endif
883 
884   while (token)
885   {
886     array.push_back(token);
887 #if defined(_tcstok_s)
888     token = _tcstok_s(NULL, delim, &next_token);
889 #else
890     token = strtok(NULL, delim);
891 #endif
892   }
893 
894   free(tmp);
895 }
896 
897 
898 //  ------------------------------------------------------------------
899 
FormatString(std::string & format,const char * token,const char * replace)900 std::string &FormatString(std::string &format, const char *token, const char *replace)
901 {
902   size_t tokenLen = strlen(token);
903   size_t pos = format.find(token);
904 
905   for (; pos != std::string::npos; pos = format.find(token))
906   {
907     format.replace(pos, tokenLen, replace);
908   }
909 
910   return format;
911 }
912 
913 
914 //  ------------------------------------------------------------------
915 
FormatString(std::string & format,const char * token,size_t replace)916 std::string &FormatString(std::string &format, const char *token, size_t replace)
917 {
918   char buff[128];
919   gsprintf(PRINTF_DECLARE_BUFFER(buff), "%u", replace);
920   return FormatString(format, token, buff);
921 }
922 
923 
924 //  ------------------------------------------------------------------
925