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