DSL
GenLib.cpp
1 //@AUTOHEADER@BEGIN@
2 /***********************************************************************\
3 | Drift Standard Libraries v1.01 |
4 | Copyright 2010-2023 Drift Solutions / Indy Sams |
5 | Docs and more information available at https://www.driftsolutions.dev |
6 | This file released under the 3-clause BSD license, |
7 | see included DSL.LICENSE.TXT file for details. |
8 \***********************************************************************/
9 //@AUTOHEADER@END@
10 
11 #ifdef _WIN32
12 #define NOMINMAX
13 #endif
14 #include <drift/dslcore.h>
15 #include <drift/GenLib.h>
16 #include <drift/Mutex.h>
17 #include <drift/rwops.h>
18 #include <algorithm>
19 
20 #if defined(WIN32)
21 time_t filetime_2_time_t(FILETIME ft) {
22  ULARGE_INTEGER tmp;
23  tmp.LowPart = ft.dwLowDateTime;
24  tmp.HighPart = ft.dwHighDateTime;
25  uint64 ret = (tmp.QuadPart - 0x19DB1DED53E8000) / 10000000;
26  return ret;
27 }
28 #endif
29 
30 StrTokenizer::StrTokenizer(char * str, char separater, bool do_strdup) {
31  b_strdup = do_strdup;
32  if (b_strdup) {
33  string = dsl_strdup(str);
34  } else {
35  string = str;
36  }
37  sep = separater;
38  sep_str[0] = sep;
39 
40  bool ends_in_sep = false;
41  if (string[strlen(string) - 1] == sep) {
42  ends_in_sep = true;
43  }
44 
45  num_tokens = 0;
46  tokens = NULL;
47  char * p2 = NULL;
48  char * p = strtok_r(string, sep_str, &p2);
49  while (p) {
50  num_tokens++;
51  tokens = (char **)dsl_realloc(tokens, sizeof(char *) * num_tokens);
52  tokens[num_tokens - 1] = p;
53  p = strtok_r(NULL, sep_str, &p2);
54  }
55  if (ends_in_sep) {
56  num_tokens++;
57  tokens = (char **)dsl_realloc(tokens, sizeof(char *) * num_tokens);
58  tokens[num_tokens - 1] = p2;
59  }
60 
61  //printf("numtok: %u\n", num_tokens);
62 }
63 
64 StrTokenizer::~StrTokenizer() {
65  if (b_strdup) {
66  dsl_free(string);
67  }
68  dsl_freenn(tokens);
69 }
70 
71 size_t StrTokenizer::NumTok() {
72  return num_tokens;
73 }
74 
75 char * StrTokenizer::GetTok(size_t first, size_t last) {
76 
77  size_t lSize=1;
78  char * ret = (char *)dsl_malloc(lSize);
79  ret[0]=0;
80 
81  first = clamp<size_t>(first, 1, num_tokens);
82  last = clamp<size_t>(last, 1, num_tokens);
83  for (size_t i = (first - 1); i < last; i++) {
84  if (lSize > 1) {
85  lSize += strlen(tokens[i]) + 1; // string + separater
86  ret = (char *)dsl_realloc(ret, lSize);
87  strlcat(ret, sep_str, lSize);
88  strlcat(ret, tokens[i], lSize);
89  } else {
90  lSize += strlen(tokens[i]);
91  ret = (char *)dsl_realloc(ret, lSize);
92  strlcpy(ret, tokens[i], lSize);
93  }
94  }
95 
96  return ret;
97 }
98 
99 char * StrTokenizer::GetSingleTok(size_t num) {
100  return GetTok(num, num);
101 };
102 
103 void StrTokenizer::FreeString(char * buf) {
104  dsl_free(buf);
105 }
106 
107 std::string StrTokenizer::stdGetTok(size_t first, size_t last) {
108  //size_t num=0;
109  std::string ret;
110 
111  first = clamp<size_t>(first, 1, num_tokens);
112  last = clamp<size_t>(last, 1, num_tokens);
113  for (size_t i = (first - 1); i < last; i++) {
114  if (ret.length()) {
115  ret += sep_str;
116  ret += tokens[i];
117  } else {
118  ret = tokens[i];
119  }
120  }
121 
122  return ret;
123 }
124 
125 std::string StrTokenizer::stdGetSingleTok(size_t num) {
126  return stdGetTok(num, num);
127 };
128 
129 char * DSL_CC bin2hex(const uint8_t * data, size_t datalen, char * out, size_t outsize) {
130  unsigned short i;
131  unsigned char j;
132 
133  if (outsize < (datalen * 2) + 1) {
134  if (outsize > 0) {
135  out[0] = 0;
136  }
137  return NULL;
138  }
139 
140  //uint8 * data = (uint8 *)dsl_malloc(datalen);
141  //memcpy(data, tdata, datalen);
142 
143  for (i = 0; i < datalen; i++) {
144  j = (data[i] >> 4) & 0xf;
145  if (j <= 9) {
146  out[i * 2] = (j + '0');
147  } else {
148  out[i * 2] = (j + 'a' - 10);
149  }
150  j = data[i] & 0xf;
151  if (j <= 9) {
152  out[i * 2 + 1] = (j + '0');
153  } else {
154  out[i * 2 + 1] = (j + 'a' - 10);
155  }
156  };
157  out[datalen * 2] = 0;
158  //dsl_free(data);
159  return out;
160 }
161 
162 string DSL_CC bin2hex(const uint8_t * data, size_t datalen) {
163  string ret;
164  size_t len = (datalen * 2) + 1;
165  char * tmp = (char *)dsl_malloc(len);
166  if (bin2hex(data, datalen, tmp, len)) {
167  ret = tmp;
168  }
169  dsl_free(tmp);
170  return ret;
171 }
172 
173 inline uint8 hex_digit_value(uint8 c) {
174  if (c >= '0' && c <= '9') {
175  return c - '0';
176  } else if (c >= 'a' && c <= 'f') {
177  return (c - 'a') + 10;
178  } else if (c >= 'A' && c <= 'F') {
179  return (c - 'A') + 10;
180  }
181  return 0xFF;
182 }
183 
184 bool DSL_CC hex2bin(const char * in, size_t len, uint8 * out, size_t outsize) {
185  if ((len % 2) == 0 && outsize >= len / 2) {
186  const char * p = in;
187  for (size_t i = 0; i < len / 2 && *p != 0; i++, out++) {
188  uint8 val = hex_digit_value(*p++);
189  if (val == 0xFF) { return false; }
190  *out = (val << 4) & 0xF0;
191  val = hex_digit_value(*p++);
192  if (val == 0xFF) { return false; }
193  *out |= val;
194  }
195  return true;
196  }
197 
198  memset(out, 0, outsize);
199  return false;
200 }
201 
202 bool DSL_CC hex2bin(const char * in, uint8 * out, size_t outsize) {
203  size_t len = strlen(in);
204  return hex2bin(in, len, out, outsize);
205 }
206 
207 bool DSL_CC hex2bin(const string str, vector<uint8_t>& bin) {
208  if (str.length() % 2 != 0) {
209  return false;
210  }
211  size_t len = str.length() / 2;
212  bin.resize(len);
213  return hex2bin(str.c_str(), str.length(), bin.data(), len);
214 }
215 
216 void DSL_CC PrintData(FILE * fp, const uint8 * ptr, size_t len) {
217  unsigned int step = 0;
218  for (size_t beg = 0; beg < len; beg += 16) {
219  size_t tostep = ((len - beg) >= 16) ? 16 : (len - beg);
220 
221  fprintf(fp, "%08zxh: ", beg);
222 
223  for (step = 0; step < tostep; step++) {
224  fprintf(fp, "%02X ", ptr[beg + step] & 0xFF);
225  }
226  while (step < 16) {
227  fprintf(fp, " ");
228  step++;
229  }
230  fprintf(fp, " ; ");
231  for (step = 0; step < tostep; step++) {
232  char c = ptr[beg + step] & 0xFF;
233  if (c < 32) { c = '.'; }
234  fprintf(fp, "%c", c);
235  }
236  while (step < 16) {
237  fprintf(fp, " ");
238  step++;
239  }
240 
241  fprintf(fp, "\n");
242  }
243  fflush(fp);
244 }
245 
246 const char * DSL_CC nopathA(const char *fn) {
247 #ifdef WIN32
248  const char *p = strrchr(fn,'\\');
249  if (!p) { p = strrchr(fn,'/'); }
250 #else
251  const char *p = strrchr(fn,'/');
252  if (!p) { p = strrchr(fn,'\\'); }
253 #endif
254  if (p) { return ++p; }
255  return fn;
256 }
257 
258 char * DSL_CC nopathA(char *fn) {
259 #ifdef WIN32
260  char *p = strrchr(fn,'\\');
261  if (!p) { p = strrchr(fn,'/'); }
262 #else
263  char *p = strrchr(fn,'/');
264  if (!p) { p = strrchr(fn,'\\'); }
265 #endif
266  if (p) { return ++p; }
267  return fn;
268 }
269 
270 const wchar_t * DSL_CC nopathW(const wchar_t *fn) {
271 #ifdef WIN32
272  const wchar_t *p = wcsrchr(fn,'\\');
273  if (!p) { p = wcsrchr(fn,'/'); }
274 #else
275  const wchar_t *p = wcsrchr(fn,'/');
276  if (!p) { p = wcsrchr(fn,'\\'); }
277 #endif
278  if (p) { return ++p; }
279  return fn;
280 }
281 
282 wchar_t * DSL_CC nopathW(wchar_t *fn) {
283 #ifdef WIN32
284  wchar_t *p = wcsrchr(fn,'\\');
285  if (!p) { p = wcsrchr(fn,'/'); }
286 #else
287  wchar_t *p = wcsrchr(fn,'/');
288  if (!p) { p = wcsrchr(fn,'\\'); }
289 #endif
290  if (p) { return ++p; }
291  return fn;
292 }
293 
294 DSL_API char * DSL_CC strtrim(char *buf, const char * trim, uint8 sides) {
295  size_t i=0;
296  size_t len = strlen(trim);
297  if (sides & TRIM_LEFT) {
298  size_t n = strspn(buf, trim);
299  if (n) {
300  memmove(buf, buf + n, strlen(buf) - n + 1);
301  }
302  }
303  if ((sides & TRIM_RIGHT) && buf[0]) {
304  char * p = &buf[strlen(buf)-1];
305  for (i=0; i < len; i++) {
306  if (*p == trim[i]) {
307  *p = 0;
308  p--;
309  if (p < buf) { break; }
310  i=-1;
311  }
312  }
313  }
314  return buf;
315 }
316 
317 #if defined(WIN32)
318 char * DSL_CC strtok_r(char *string, const char * delimiters, char ** save_str) {
319  //char *token;
320 
321  if (string == NULL) {
322  string = *save_str;
323  }
324 
325  string += strspn (string, delimiters);
326  if (*string == 0) {
327  *save_str = string;
328  return NULL;
329  }
330 
331  /* Find the end of the token. */
332  char * tok = string;
333  string = strpbrk (tok, delimiters);
334  if (string == NULL) {
335  *save_str = strchr(tok, 0);
336  } else {
337  *string = 0;
338  *save_str = string + 1;
339  }
340  return tok;
341 }
342 
343 const char * DSL_CC stristr(const char * haystack, const char * needle) {
344  size_t len = strlen(needle);
345  while (*haystack) {
346  if (toupper(*haystack) == toupper(*needle)) {
347  if (strnicmp(haystack, needle, len) == 0) {
348  return haystack;
349  }
350  }
351  haystack++;
352  }
353  return NULL;
354 }
355 
356 char * DSL_CC stristr(char * haystack, const char * needle) {
357  size_t len = strlen(needle);
358  while (*haystack) {
359  if (toupper(*haystack) == toupper(*needle)) {
360  if (strnicmp(haystack, needle, len) == 0) {
361  return haystack;
362  }
363  }
364  haystack++;
365  }
366  return NULL;
367 }
368 
369 #else
370 
371 char * DSL_CC strlwr(char *str) {
372  for(char * p = str; *p; p++) {
373  *p = tolower((unsigned char)*p);
374  }
375  return str;
376 }
377 
378 #endif
379 
380 bool DSL_CC dsl_mkdir_r(const char * fullpath, int mode) {
381  if (fullpath == NULL) {
382  return false;
383  }
384 
385  char * newdir = dsl_strdup(fullpath);
386  char * p = newdir;
387 #ifdef WIN32
388  char * q = strchr(p, ':');
389  if (q != NULL) {
390  // skip drive letter
391  p = q + 1;
392  }
393 #endif
394  while (*p == PATH_SEP) {
395  //skip any initial slashes (Linux path or network/UNC path on Windows)
396  p++;
397  }
398  if (newdir[strlen(newdir) - 1] == PATH_SEP) {
399  //trim off any trailing slashes
400  newdir[strlen(newdir) - 1] = 0;
401  }
402  if (access(newdir, F_OK) == 0) {
403  dsl_free(newdir);
404  return true;
405  }
406 
407  char * tmp = dsl_strdup(fullpath);
408  while ((p = strchr(p, PATH_SEP)) != NULL) {
409  size_t len = p - newdir;
410  strncpy(tmp, newdir, len);
411  tmp[len] = 0;
412  tmp = tmp;
413  if (access(tmp, F_OK) != 0) {
414  dsl_mkdir(tmp, mode);
415  }
416  p++;
417  }
418  bool ret = (dsl_mkdir(newdir, mode) == 0 || errno == EEXIST);
419  dsl_free(tmp);
420  dsl_free(newdir);
421  return ret;
422 }
423 
424 bool DSL_CC strempty(const char * p) {
425  if (p == NULL) { return true; }
426  return (*p == 0) ? true:false;
427 }
428 
429 int64 DSL_CC dsl_clamp(int64 val, int64 vMin, int64 vMax) {
430  return std::min(vMax, std::max(vMin, val));
431 }
432 
433 int DSL_CC wildcmp(const char *wild, const char *string) {
434  // Written by Jack Handy - <A href="mailto:[email protected]">[email protected]</A>
435  // He posted it on codeproject with no explicit license, assuming public domain: https://www.codeproject.com/Articles/1088/Wildcard-string-compare-globbing
436  // return 0 for no match, other for match
437  const char *cp = NULL, *mp = NULL;
438 
439  while ((*string) && (*wild != '*')) {
440  if ((*wild != *string) && (*wild != '?')) {
441  return 0;
442  }
443  wild++;
444  string++;
445  }
446 
447  while (*string) {
448  if (*wild == '*') {
449  if (!*++wild) {
450  return 1;
451  }
452  mp = wild;
453  cp = string+1;
454  } else if ((*wild == *string) || (*wild == '?')) {
455  wild++;
456  string++;
457  } else {
458  wild = mp;
459  string = cp++;
460  }
461  }
462 
463  while (*wild == '*') {
464  wild++;
465  }
466  return !*wild;
467 }
468 
469 int DSL_CC wildicmp(const char *wild, const char *string) {
470  // Written by Jack Handy - <A href="mailto:[email protected]">[email protected]</A>
471  // He posted it on codeproject with no explicit license, assuming public domain: https://www.codeproject.com/Articles/1088/Wildcard-string-compare-globbing
472  // return 0 for no match, other for match
473  const char *cp = NULL, *mp = NULL;
474 
475  while ((*string) && (*wild != '*')) {
476  if ((tolower(*wild) != tolower(*string)) && (*wild != '?')) {
477  return 0;
478  }
479  wild++;
480  string++;
481  }
482 
483  while (*string) {
484  if (*wild == '*') {
485  if (!*++wild) {
486  return 1;
487  }
488  mp = wild;
489  cp = string+1;
490  } else if ((tolower(*wild) == tolower(*string)) || (*wild == '?')) {
491  wild++;
492  string++;
493  } else {
494  wild = mp;
495  string = cp++;
496  }
497  }
498 
499  while (*wild == '*') {
500  wild++;
501  }
502  return !*wild;
503 }
504 
505 int DSL_CC wildicmp_multi(const char *wild, const char *string, const char *sep) {
506  int ret = 0;
507  char * tmp = dsl_strdup((char *)wild);
508  char * p2 = NULL;
509  char * p = strtok_r(tmp, sep, &p2);
510  while (p) {
511  ret = wildicmp(p, string);
512  if (ret != 0) { break; }
513  p = strtok_r(NULL, sep, &p2);
514  }
515  dsl_free(tmp);
516  return ret;
517 }
518 
519 int64 DSL_CC fseek64(FILE * fp, int64 offset, int whence) {
520 #if defined(WIN32)
521  return _fseeki64(fp, offset, whence);
522 #else
523  return fseeko(fp, offset, whence);
524 #endif
525 }
526 
527 int64 DSL_CC ftell64(FILE * fp) {
528 #if defined(WIN32)
529  return _ftelli64(fp);
530 #else
531  return ftello(fp);
532 #endif
533 }
534 
535 int64 DSL_CC filesize(const char * fn) {
536  struct stat64 st;
537  if (stat64(fn, &st) == 0) {
538  return st.st_size;
539  }
540  return -1;
541 }
542 
543 #if defined(WIN32)
544 int DSL_CC truncate(const char * fn, int64 size) {
545  int fd = open(fn, O_RDWR);
546  if (fd != -1) {
547  int ret = ftruncate(fd, size);
548  close(fd);
549  return ret;
550  }
551  return -1;
552 }
553 #endif
554 
555 char * DSL_CC escapeshellarg(const char * p, char * out, size_t outSize) {
556  memset(out, 0, outSize);
557 
558  outSize -= 3; // sub for potential final escaped char, final ", and null term
559 
560  strlcpy(out, "\"", outSize);
561  char *x = out + 1;
562  size_t len = 1;
563  while (*p && len < outSize) {
564  if (*p == '"') {
565  *x = '\\';
566  x++;
567  len++;
568  }
569  *x = *p;
570  p++;
571  x++;
572  len++;
573  }
574  strlcat(out, "\"", outSize);
575  return out;
576 }
577 
578 string DSL_CC escapeshellarg(const string& str) {
579  string ret = "\"";
580  const char *p = str.c_str();
581  while (*p != 0) {
582  if (*p == '"') {
583  ret += '\\';
584  }
585  ret += *p;
586  p++;
587  }
588  ret += "\"";
589  return ret;
590 }
591 
592 int DSL_CC str_replaceA(char *Str, size_t BufSize, const char *FindStr, const char *ReplStr) {
593  char *p = NULL;
594  int ret = 0;
595  size_t OldLen = strlen(FindStr);
596  size_t NewLen = strlen(ReplStr);
597  while ((p = strstr(Str, FindStr))) {
598  if ((strlen(Str) + NewLen - OldLen) > BufSize) {
599  break;
600  }
601  if (NewLen != OldLen) {
602  memmove(p + NewLen, p + OldLen, strlen(p+OldLen)+1);
603  }
604  memcpy(p, ReplStr, NewLen);
605  Str = p+NewLen;
606  ret++;
607  }
608  return ret;
609 }
610 
611 #if !defined(FREEBSD)
612 int DSL_CC str_replaceW(wchar_t * Str, size_t BufSize, wchar_t *FindStr, wchar_t *ReplStr) {
613  wchar_t * p, *End, *Begin;
614  size_t len=0;
615  wchar_t fmt[32];
616  int ret=0;
617  size_t OldLen = wcslen(FindStr);
618  size_t NewLen = wcslen(ReplStr);
619  while ((p = wcsstr(Str, FindStr))) {
620  if ((wcslen(Str) + NewLen - OldLen + 1) > BufSize) {
621  break;
622  }
623  End = dsl_wcsdup(p+OldLen);
624  Begin = dsl_wcsdup(Str);
625  len = p - Str;
626  snwprintf(fmt, 32, L"%%.%zus%%s%%s", len);
627  snwprintf(Str, BufSize, fmt, Begin, ReplStr, End);
628  dsl_free(End);
629  dsl_free(Begin);
630  ret++;
631  }
632  return ret;
633 }
634 #endif
635 
636 string DSL_CC str_replaceA(const string& src, const string& FindStr, const string& ReplStr) {
637  size_t pos;
638  string str = src;
639  while ((pos = str.find(FindStr)) != str.npos) {
640  str.replace(pos, FindStr.length(), ReplStr);
641  }
642  return str;
643 }
644 
645 #if !defined(FREEBSD)
646 wstring DSL_CC str_replaceW(const wstring& src, const wstring& FindStr, const wstring& ReplStr) {
647  size_t pos;
648  wstring str = src;
649  while ((pos = str.find(FindStr)) != str.npos) {
650  str.replace(pos, FindStr.length(), ReplStr);
651  }
652  return str;
653 }
654 #endif // FREEBSD
655 
656 char * DSL_CC GetUserConfigFolderA(const char * name) {
657  char buf[MAX_PATH]={0};
658 #if defined(WIN32)
659  char * p = getenv("APPDATA");
660  if (p == NULL || *p == 0) {
661  p = getenv("USERPROFILE");
662  }
663  if (p == NULL || *p == 0) {
664  GetModuleFileNameA(NULL, buf, sizeof(buf));
665  char * q = strrchr(buf, '\\');
666  if (q) {
667  *q = 0;
668  }
669  } else {
670  sstrcpy(buf, p);
671  }
672 #else
673  char * p = getenv("HOME");
674  if (p && *p) {
675  sstrcpy(buf, p);
676  } else if (getcwd(buf, sizeof(buf)) == NULL) {
677  strcpy(buf, "./");
678  }
679 #endif
680  if (buf[strlen(buf)-1] != PATH_SEP) {
681  sstrcat(buf, PATH_SEPS);
682  }
683 #if !defined(WIN32)
684  sstrcat(buf, ".");
685 #endif
686  sstrcat(buf, name);
687  struct stat st;
688  if (stat(buf, &st) != 0) {
689  dsl_mkdir(buf, 0700);
690  }
691  strcat(buf, PATH_SEPS);
692  return dsl_strdup(buf);
693 }
694 
695 string DSL_CC GetUserConfigFolderA(const string& name) {
696  char * tmp = GetUserConfigFolderA(name.c_str());
697  string ret = tmp;
698  dsl_free(tmp);
699  return ret;
700 }
701 
702 char * DSL_CC GetUserConfigFileA(const char * name, const char * fn) {
703  char * dir = GetUserConfigFolderA(name);
704  char * ret = dsl_mprintf("%s%s", dir, fn);
705  dsl_free(dir);
706  return ret;
707 }
708 
709 string DSL_CC GetUserConfigFileA(const string& name, const string& fn) {
710  char * dir = GetUserConfigFolderA(name.c_str());
711  string ret = mprintf("%s%s", dir, fn.c_str());
712  dsl_free(dir);
713  return ret;
714 }
715 
716 wchar_t * DSL_CC GetUserConfigFolderW(const wchar_t * name) {
717  wchar_t buf[MAX_PATH]={0};
718 #if defined(WIN32)
719  wchar_t * p = wgetenv(L"APPDATA");
720  if (!p || !wcslen(p)) {
721  p = wgetenv(L"USERPROFILE");
722  }
723  if (!p || !wcslen(p)) {
724  GetModuleFileNameW(NULL, buf, sizeof(buf));
725  wchar_t * q = wcsrchr(buf, '\\');
726  if (q) {
727  q[1]=0;
728  }
729  } else {
730  wcscpy(buf, p);
731  }
732 #else
733 /*
734  wchar_t * p = getenv("HOME");
735  if (p && *p) {
736  wcscpy(buf, p);
737  } else {
738  getcwd(buf, sizeof(buf)/sizeof(wchar_t));
739  }
740  */
741  wcscpy(buf, L".");
742 #endif
743  if (buf[wcslen(buf)-1] != PATH_SEP) {
744  wcscat(buf, WPATH_SEPS);
745  }
746  return dsl_wcsdup(buf);
747 }
748 
749 wchar_t * DSL_CC GetUserConfigFileW(const wchar_t * name, const wchar_t * fn) {
750  wchar_t * dir = GetUserConfigFolderW(name);
751  wchar_t * ret = dsl_wmprintf(L"%s%s", dir, fn);
752  dsl_free(dir);
753  return ret;
754 }
755 
756 char * DSL_CC GetUserDocumentsFolderA(const char * name) {
757  char buf[MAX_PATH] = { 0 };
758 #if defined(WIN32)
759  char * p = getenv("USERPROFILE");
760  if (p == NULL || *p == 0) {
761  GetModuleFileNameA(NULL, buf, sizeof(buf));
762  char * q = strrchr(buf, '\\');
763  if (q) {
764  *q = 0;
765  }
766  } else {
767  strlcpy(buf, p, sizeof(buf));
768  }
769 #else
770  char * p = getenv("HOME");
771  if (p && *p) {
772  strlcpy(buf, p, sizeof(buf));
773  } else if (getcwd(buf, sizeof(buf)) == NULL) {
774  strcpy(buf, "./");
775  }
776 #endif
777  if (buf[strlen(buf) - 1] != PATH_SEP) {
778  sstrcat(buf, PATH_SEPS);
779  }
780  sstrcat(buf, "Documents" PATH_SEPS "");
781  sstrcat(buf, name);
782  struct stat st;
783  if (stat(buf, &st) != 0) {
784  dsl_mkdir(buf, 0700);
785  }
786  strcat(buf, PATH_SEPS);
787  return dsl_strdup(buf);
788 }
789 
790 #if !defined(WIN32)
791 DSL_API uint32 DSL_CC GetTickCount() {
792  return (uint32)GetTickCount64();
793 }
794 
795 DSL_API uint64 DSL_CC GetTickCount64() {
796  static timeval tv_start = {0,0};
797  if (tv_start.tv_sec == 0) {
798  gettimeofday (&tv_start, NULL);
799  tv_start.tv_usec = 0;
800  return 0;
801  }
802  timeval tv;
803  gettimeofday(&tv, NULL);
804  uint64 ret = uint64(tv.tv_sec - tv_start.tv_sec) * 1000;
805  ret += uint64(tv.tv_usec / 1000);
806  return ret;
807 }
808 
809 #endif
810 
811 DSL_API char * DSL_CC tcstombsA(const char * str) {
812  return dsl_strdup(str);
813 }
814 
815 DSL_API char * DSL_CC tcstombsW(const wchar_t * str) {
816  size_t len = wcstombs(NULL, str, 0);
817  if (len == (size_t)-1) {
818  return dsl_strdup("ERROR in wcstombs");
819  }
820  char * buf = (char *)dsl_malloc(len+1);
821  buf[len] = 0;
822  wcstombs(buf, str, len);
823  return buf;
824 };
825 
826 DSL_API wchar_t * DSL_CC tcstowcsW(const wchar_t * str) {
827  return dsl_wcsdup(str);
828 }
829 DSL_API wchar_t * DSL_CC tcstowcsA(const char * str) {
830  size_t len = mbstowcs(NULL, str, 0);
831  if (len == (size_t)-1) {
832  return dsl_wcsdup(L"ERROR in mbstowcs");
833  }
834  size_t llen = (len+1)*sizeof(wchar_t);
835  wchar_t * buf = (wchar_t *)dsl_malloc(llen);
836  memset(buf, 0, llen);
837  mbstowcs(buf, str, len);
838  return buf;
839 };
840 
841 DSL_API char * DSL_CC mbstotcsA(const char * str) {
842  return dsl_strdup(str);
843 }
844 DSL_API char * DSL_CC wcstotcsA(const wchar_t * str) {
845  size_t len = wcstombs(NULL, str, 0);
846  if (len == (size_t)-1) {
847  return dsl_strdup("ERROR in wcstombs");
848  }
849  char * buf = (char *)dsl_malloc(len+1);
850  buf[len] = 0;
851  wcstombs(buf, str, len);
852  return buf;
853 }
854 
855 DSL_API wchar_t * DSL_CC mbstotcsW(const char * str) {
856  size_t len = mbstowcs(NULL, str, 0);
857  if (len == (size_t)-1) {
858  return dsl_wcsdup(L"ERROR in mbstowcs");
859  }
860  size_t llen = (len+1)*sizeof(wchar_t);
861  wchar_t * buf = (wchar_t *)dsl_malloc(llen);
862  memset(buf, 0, llen);
863  mbstowcs(buf, str, len);
864  return buf;
865 }
866 
867 DSL_API wchar_t * DSL_CC wcstotcsW(const wchar_t * str) {
868  return dsl_wcsdup(str);
869 }
870 
871 DSL_API size_t DSL_CC wcscnt(const wchar_t * ptr) {
872  size_t n = 0;
873  for (; *ptr; ptr++)
874  n += sizeof(wchar_t);
875  return n;
876 }
877 
878 #if !defined(HAVE_STRLCPY)
879 DSL_API size_t DSL_CC strlcat(char *dst, const char *src, size_t siz) {
880  char *d = dst;
881  const char *s = src;
882  size_t n = siz;
883  size_t dlen;
884 
885  /* Find the end of dst and adjust bytes left but don't go past end */
886  while (n-- != 0 && *d != '\0')
887  d++;
888  dlen = d - dst;
889  n = siz - dlen;
890 
891  if (n == 0)
892  return(dlen + strlen(s));
893  while (*s != '\0') {
894  if (n != 1) {
895  *d++ = *s;
896  n--;
897  }
898  s++;
899  }
900  *d = '\0';
901 
902  return(dlen + (s - src)); /* count does not include NUL */
903 }
904 
905 DSL_API size_t DSL_CC strlcpy(char *dst, const char *src, size_t siz)
906 {
907  char *d = dst;
908  const char *s = src;
909  size_t n = siz;
910 
911  /* Copy as many bytes as will fit */
912  if (n != 0) {
913  while (--n != 0) {
914  if ((*d++ = *s++) == '\0')
915  break;
916  }
917  }
918 
919  /* Not enough room in dst, add NUL and traverse rest of src */
920  if (n == 0) {
921  if (siz != 0)
922  *d = '\0'; /* NUL-terminate dst */
923  while (*s++)
924  ;
925  }
926 
927  return(s - src - 1); /* count does not include NUL */
928 }
929 #endif
930 
931 #if defined(MACOSX)
932 DSL_API wchar_t * DSL_CC wcsdup(const wchar_t *s) {
933  size_t len = (wcscnt(s) + 1) * sizeof(wchar_t);
934  wchar_t * copy = (wchar_t *)malloc(len);
935  if (copy == NULL) { return NULL; }
936  memcpy(copy, s, len);
937  return copy;
938 }
939 #endif
940 
941 #if defined(WIN32)
942 struct tm * DSL_CC localtime_r(const time_t * tme, struct tm * out) {
943  if (!tme || !out) return NULL;
944  if (localtime_s(out, tme) != 0) {
945  memset(out, 0, sizeof(struct tm));
946  }
947  return out;
948 }
949 struct tm * DSL_CC gmtime_r(const time_t * tme, struct tm * out) {
950  if (!tme || !out) return NULL;
951  if (gmtime_s(out, tme) != 0) {
952  memset(out, 0, sizeof(struct tm));
953  }
954  return out;
955 }
956 #endif
957 
958 inline bool _file_get_contents_begin(const string& fn, int64 maxSize, int64& len, FILE ** fp) {
959  *fp = fopen(fn.c_str(), "rb");
960  if (*fp == NULL) {
961  return false;
962  }
963  fseek64(*fp, 0, SEEK_END);
964  len = ftell64(*fp);
965  if (len > maxSize || len < 0) {
966  return false;
967  }
968  fseek64(*fp, 0, SEEK_SET);
969  return true;
970 }
971 
972 DSL_API_CLASS bool DSL_CC file_get_contents(const string& fn, vector<uint8>& data, int64 maxSize) {
973  FILE * fp;
974  int64 len;
975  if (!_file_get_contents_begin(fn, maxSize, len, &fp)) {
976  return false;
977  }
978 
979  data.resize(len);
980  bool ret = (fread(data.data(), len, 1, fp) == 1);
981  fclose(fp);
982  return ret;
983 }
984 
985 DSL_API_CLASS bool DSL_CC file_get_contents(const string& fn, string& data, int64 maxSize) {
986  FILE * fp;
987  int64 len;
988  if (!_file_get_contents_begin(fn, maxSize, len, &fp)) {
989  return false;
990  }
991 
992  data.resize(len);
993  bool ret = (fread(&data[0], len, 1, fp) == 1);
994  fclose(fp);
995  return ret;
996 }
997 
998 DSL_API_CLASS bool DSL_CC file_get_contents(const string& fn, uint8 ** data, int64& len, int64 maxSize) {
999  FILE * fp;
1000  if (!_file_get_contents_begin(fn, maxSize, len, &fp)) {
1001  return false;
1002  }
1003 
1004  *data = (uint8 *)dsl_malloc(len);
1005  if (*data == NULL) {
1006  return false;
1007  }
1008  bool ret = (fread(*data, len, 1, fp) == 1);
1009  if (!ret) {
1010  dsl_free(*data);
1011  *data = NULL;
1012  }
1013  fclose(fp);
1014  return ret;
1015 }
1016 
1017 bool DSL_CC file_put_contents(const string& fn, const vector<uint8>& data, bool append) {
1018  FILE * fp = fopen(fn.c_str(), append ? "ab" : "wb");
1019  if (fp == NULL) {
1020  return false;
1021  }
1022 
1023  bool ret = (fwrite(data.data(), data.size(), 1, fp) == 1);
1024  fclose(fp);
1025  return ret;
1026 }
1027 
1028 bool DSL_CC file_put_contents(const string& fn, const string& data, bool append) {
1029  FILE * fp = fopen(fn.c_str(), append ? "ab" : "wb");
1030  if (fp == NULL) {
1031  return false;
1032  }
1033 
1034  bool ret = (fwrite(data.c_str(), data.length(), 1, fp) == 1);
1035  fclose(fp);
1036  return ret;
1037 }
1038 
1039 bool DSL_CC file_put_contents(const string& fn, const uint8 * data, size_t fileSize, bool append) {
1040  FILE * fp = fopen(fn.c_str(), append ? "ab" : "wb");
1041  if (fp == NULL) {
1042  return false;
1043  }
1044 
1045  bool ret = (fwrite(data, fileSize, 1, fp) == 1);
1046  fclose(fp);
1047  return ret;
1048 }
1049 
1050 int64 DSL_CC copy_file(const string& src, const string& dest, bool allow_overwrite) {
1051 #ifdef WIN32
1052  int64 ret = filesize(src.c_str());
1053  if (ret >= 0 && CopyFile(src.c_str(), dest.c_str(), !allow_overwrite)) {
1054  return ret;
1055  }
1056  return -1;
1057 #else
1058  int fdi = open(src.c_str(), O_RDONLY);
1059  if (fdi == -1) {
1060  return -1;
1061  }
1062 
1063  int flags = O_WRONLY | O_CREAT;
1064  if (allow_overwrite) {
1065  flags |= O_TRUNC;
1066  } else {
1067  flags |= O_EXCL;
1068  }
1069  int fdo = open(dest.c_str(), flags);
1070  if (fdo == -1) {
1071  close(fdi);
1072  return -1;
1073  }
1074 
1075  int64 ret = 0;
1076  #if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 27))
1077  ret = copy_file_range(fdi, NULL, fdo, NULL, SIZE_MAX, 0);
1078  #else
1079  uint8 buf[32768];
1080  int n;
1081  while ((n = read(fdi, buf, sizeof(buf))) > 0) {
1082  if (write(fdo, buf, n) != n) {
1083  n = -1;
1084  break;
1085  }
1086  ret += n;
1087  }
1088  if (n < 0) {
1089  ret = -1;
1090  }
1091  #endif
1092 
1093  close(fdo);
1094  close(fdi);
1095  return ret;
1096 #endif
1097 }
1098 
1099 /* Remaining functions past this line were borrowed from PhysicsFS */
1100 
1101 DSL_API uint16 DSL_CC ByteSwap16(uint16 X) {
1102  return ( ((X >> 8)) | (X << 8) );
1103 }
1104 
1105 DSL_API uint32 DSL_CC ByteSwap32(uint32 X) {
1106  return( (X<<24) | ((X<<8) & 0x00FF0000) | ((X>>8) & 0x0000FF00) | (X>>24) );
1107 }
1108 
1109 DSL_API uint64 DSL_CC ByteSwap64(uint64 val) {
1110  uint32 lo = (uint32)(val&0xFFFFFFFF);
1111  val >>= 32;
1112  uint32 hi = (uint32)(val&0xFFFFFFFF);
1113  val = ByteSwap32(lo);
1114  val <<= 32;
1115  val |= ByteSwap32(hi);
1116  return(val);
1117 }
1118 
1119 #ifdef LITTLE_ENDIAN
1120 DSL_API uint16 DSL_CC Get_ULE16(uint16 x) { return(x); }
1121 DSL_API int16 DSL_CC Get_SLE16(int16 x) { return(x); }
1122 DSL_API uint32 DSL_CC Get_ULE32(uint32 x) { return(x); }
1123 DSL_API int32 DSL_CC Get_SLE32(int32 x) { return(x); }
1124 DSL_API uint64 DSL_CC Get_ULE64(uint64 x) { return(x); }
1125 DSL_API int64 DSL_CC Get_SLE64(int64 x) { return(x); }
1126 
1127 DSL_API uint16 DSL_CC Get_UBE16(uint16 x) { return(ByteSwap16(x)); }
1128 DSL_API int16 DSL_CC Get_SBE16(int16 x) { return(ByteSwap16(x)); }
1129 DSL_API uint32 DSL_CC Get_UBE32(uint32 x) { return(ByteSwap32(x)); }
1130 DSL_API int32 DSL_CC Get_SBE32(int32 x) { return(ByteSwap32(x)); }
1131 DSL_API uint64 DSL_CC Get_UBE64(uint64 x) { return(ByteSwap64(x)); }
1132 DSL_API int64 DSL_CC Get_SBE64(int64 x) { return(ByteSwap64(x)); }
1133 #else
1134 DSL_API uint16 DSL_CC Get_ULE16(uint16 x) { return(ByteSwap16(x)); }
1135 DSL_API int16 DSL_CC Get_SLE16(int16 x) { return(ByteSwap16(x)); }
1136 DSL_API uint32 DSL_CC Get_ULE32(uint32 x) { return(ByteSwap32(x)); }
1137 DSL_API int32 DSL_CC Get_SLE32(int32 x) { return(ByteSwap32(x)); }
1138 DSL_API uint64 DSL_CC Get_ULE64(uint64 x) { return(ByteSwap64(x)); }
1139 DSL_API int64 DSL_CC Get_SLE64(int64 x) { return(ByteSwap64(x)); }
1140 
1141 DSL_API uint16 DSL_CC Get_UBE16(uint16 x) { return(x); }
1142 DSL_API int16 DSL_CC Get_SBE16(int16 x) { return(x); }
1143 DSL_API uint32 DSL_CC Get_UBE32(uint32 x) { return(x); }
1144 DSL_API int32 DSL_CC Get_SBE32(int32 x) { return(x); }
1145 DSL_API uint64 DSL_CC Get_UBE64(uint64 x) { return(x); }
1146 DSL_API int64 DSL_CC Get_SBE64(int64 x) { return(x); }
1147 #endif
1148 
1149 DSL_API bool DSL_CC IsValidUTF8(const char *s) {
1150  return (FirstInvalidUTF8(s) == NULL);
1151 }
1152 
1153 DSL_API const char * DSL_CC FirstInvalidUTF8(const char *p) {
1154  const uint8 *s = (const uint8 *)p;
1155  while (*s) {
1156  if (*s < 0x80)
1157  /* 0xxxxxxx */
1158  s++;
1159  else if ((s[0] & 0xe0) == 0xc0) {
1160  /* 110XXXXx 10xxxxxx */
1161  if ((s[1] & 0xc0) != 0x80 ||
1162  (s[0] & 0xfe) == 0xc0) /* overlong? */
1163  return (char *)s;
1164  else
1165  s += 2;
1166  } else if ((s[0] & 0xf0) == 0xe0) {
1167  /* 1110XXXX 10Xxxxxx 10xxxxxx */
1168  if ((s[1] & 0xc0) != 0x80 ||
1169  (s[2] & 0xc0) != 0x80 ||
1170  (s[0] == 0xe0 && (s[1] & 0xe0) == 0x80) || /* overlong? */
1171  (s[0] == 0xed && (s[1] & 0xe0) == 0xa0) || /* surrogate? */
1172  (s[0] == 0xef && s[1] == 0xbf &&
1173  (s[2] & 0xfe) == 0xbe)) /* U+FFFE or U+FFFF? */
1174  return (char *)s;
1175  else
1176  s += 3;
1177  } else if ((s[0] & 0xf8) == 0xf0) {
1178  /* 11110XXX 10XXxxxx 10xxxxxx 10xxxxxx */
1179  if ((s[1] & 0xc0) != 0x80 ||
1180  (s[2] & 0xc0) != 0x80 ||
1181  (s[3] & 0xc0) != 0x80 ||
1182  (s[0] == 0xf0 && (s[1] & 0xf0) == 0x80) || /* overlong? */
1183  (s[0] == 0xf4 && s[1] > 0x8f) || s[0] > 0xf4) /* > U+10FFFF? */
1184  return (char *)s;
1185  else
1186  s += 4;
1187  } else
1188  return (char *)s;
1189  }
1190 
1191  return NULL;
1192 }
void FreeString(char *buf)
You must call this on any string returned by GetTok/GetSingleTok.
Definition: GenLib.cpp:103
StrTokenizer(char *str, char separater, bool do_strdup=true)
Definition: GenLib.cpp:30
DSL_API uint64 DSL_CC Get_ULE64(uint64 x)
Convert from the native endianness to Little Endian.
Definition: GenLib.cpp:1138
DSL_API int64 DSL_CC Get_SBE64(int64 x)
Convert from the native endianness to Big Endian.
Definition: GenLib.cpp:1146
DSL_API uint16 DSL_CC ByteSwap16(uint16 X)
Byte swap a 16-bit unsigned integer.
Definition: GenLib.cpp:1101
DSL_API int32 DSL_CC Get_SBE32(int32 x)
Convert from the native endianness to Big Endian.
Definition: GenLib.cpp:1144
DSL_API int32 DSL_CC Get_SLE32(int32 x)
Convert from the native endianness to Little Endian.
Definition: GenLib.cpp:1137
DSL_API uint16 DSL_CC Get_UBE16(uint16 x)
Convert from the native endianness to Big Endian.
Definition: GenLib.cpp:1141
DSL_API uint64 DSL_CC ByteSwap64(uint64 val)
Byte swap a 64-bit unsigned integer.
Definition: GenLib.cpp:1109
DSL_API int16 DSL_CC Get_SBE16(int16 x)
Convert from the native endianness to Big Endian.
Definition: GenLib.cpp:1142
DSL_API uint32 DSL_CC Get_ULE32(uint32 x)
Convert from the native endianness to Little Endian.
Definition: GenLib.cpp:1136
DSL_API int16 DSL_CC Get_SLE16(int16 x)
Convert from the native endianness to Little Endian.
Definition: GenLib.cpp:1135
DSL_API uint32 DSL_CC Get_UBE32(uint32 x)
Convert from the native endianness to Big Endian.
Definition: GenLib.cpp:1143
DSL_API uint32 DSL_CC ByteSwap32(uint32 X)
Byte swap a 32-bit unsigned integer.
Definition: GenLib.cpp:1105
DSL_API uint64 DSL_CC Get_UBE64(uint64 x)
Convert from the native endianness to Big Endian.
Definition: GenLib.cpp:1145
DSL_API uint16 DSL_CC Get_ULE16(uint16 x)
Convert from the native endianness to Little Endian.
Definition: GenLib.cpp:1134
DSL_API int64 DSL_CC Get_SLE64(int64 x)
Convert from the native endianness to Little Endian.
Definition: GenLib.cpp:1139
DSL_API_CLASS string mprintf(const string fmt,...)
Definition: dsl.cpp:294
DSL_API wchar_t *DSL_CC dsl_wmprintf(const wchar_t *fmt,...)
Definition: dsl.cpp:320
DSL_API void DSL_CC dsl_free(void *ptr)
Definition: dsl.cpp:345
#define dsl_freenn(ptr)
Definition: dslcore.h:190
DSL_API char *DSL_CC dsl_mprintf(const char *fmt,...)
Definition: dsl.cpp:287
char *DSL_CC strlwr(char *str)
Linux version of strlwr.
Definition: GenLib.cpp:371
DSL_API uint64 DSL_CC GetTickCount64()
Linux version of GetTickCount64.
Definition: GenLib.cpp:795
DSL_API bool DSL_CC IsValidUTF8(const char *s)
Checks if the string is valid UTF-8 (no invalid UTF-8 sequences, etc.)
Definition: GenLib.cpp:1149
int64 DSL_CC copy_file(const string &src, const string &dest, bool allow_overwrite)
Definition: GenLib.cpp:1050
DSL_API size_t DSL_CC strlcpy(char *dst, const char *src, size_t siz)
Definition: GenLib.cpp:905
char *DSL_CC bin2hex(const uint8_t *data, size_t datalen, char *out, size_t outsize)
Definition: GenLib.cpp:129
bool DSL_CC hex2bin(const char *in, size_t len, uint8 *out, size_t outsize)
Definition: GenLib.cpp:184
bool DSL_CC dsl_mkdir_r(const char *fullpath, int mode)
Cross-platform recursive mkdir()
Definition: GenLib.cpp:380
wchar_t *DSL_CC GetUserConfigFolderW(const wchar_t *name)
Unicode version of...
Definition: GenLib.cpp:716
bool DSL_CC strempty(const char *p)
Returns true if a string is empty (p == NULL || *p == 0)
Definition: GenLib.cpp:424
int DSL_CC str_replaceA(char *Str, size_t BufSize, const char *FindStr, const char *ReplStr)
Simple string replacement.
Definition: GenLib.cpp:592
void DSL_CC PrintData(FILE *fp, const uint8 *ptr, size_t len)
Prints binary data in a pretty format.
Definition: GenLib.cpp:216
const char *DSL_CC nopathA(const char *fn)
Returns just the file portion of the full path and filename.
Definition: GenLib.cpp:246
int64 DSL_CC ftell64(FILE *fp)
Cross-platform 64-bit ftell.
Definition: GenLib.cpp:527
char *DSL_CC GetUserConfigFileA(const char *name, const char *fn)
Definition: GenLib.cpp:702
char *DSL_CC GetUserConfigFolderA(const char *name)
Definition: GenLib.cpp:656
DSL_API size_t DSL_CC strlcat(char *dst, const char *src, size_t siz)
Definition: GenLib.cpp:879
const wchar_t *DSL_CC nopathW(const wchar_t *fn)
Returns just the file portion of the full path and filename.
Definition: GenLib.cpp:270
int DSL_CC wildicmp(const char *wild, const char *string)
Definition: GenLib.cpp:469
int DSL_CC wildcmp(const char *wild, const char *string)
Definition: GenLib.cpp:433
wstring DSL_CC str_replaceW(const wstring &src, const wstring &FindStr, const wstring &ReplStr)
Simple string replacement.
Definition: GenLib.cpp:646
#define sstrcpy(x, y)
Definition: GenLib.h:102
#define sstrcat(x, y)
Definition: GenLib.h:106
char *DSL_CC GetUserDocumentsFolderA(const char *name)
Definition: GenLib.cpp:756
int64 DSL_CC filesize(const char *fn)
Get the size in bytes of a file.
Definition: GenLib.cpp:535
int64 DSL_CC fseek64(FILE *fp, int64 offset, int whence)
Cross-platform 64-bit fseek.
Definition: GenLib.cpp:519
DSL_API char *DSL_CC strtrim(char *buf, const char *trim, uint8 sides)
Definition: GenLib.cpp:294
int DSL_CC wildicmp_multi(const char *wild, const char *string, const char *sep)
Definition: GenLib.cpp:505
wchar_t *DSL_CC GetUserConfigFileW(const wchar_t *name, const wchar_t *fn)
Unicode version of...
Definition: GenLib.cpp:749
char *DSL_CC escapeshellarg(const char *p, char *out, size_t outSize)
Escapes an argument for passing to shell functions, only escapes quotes atm so keep that in mind.
Definition: GenLib.cpp:555
DSL_API_CLASS bool DSL_CC file_get_contents(const string &fn, vector< uint8 > &data, int64 maxSize)
Definition: GenLib.cpp:972
DSL_API uint32 DSL_CC GetTickCount()
Linux version of GetTickCount.
Definition: GenLib.cpp:791
int64 DSL_CC dsl_clamp(int64 val, int64 vMin, int64 vMax)
Clamps a given value to the range of vMin to vMax (inclusive)
Definition: GenLib.cpp:429