tb_str.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. // ================================================================================
  2. // == This file is a part of Turbo Badger. (C) 2011-2014, Emil Segerås ==
  3. // == See tb_core.h for more information. ==
  4. // ================================================================================
  5. #include "tb_str.h"
  6. #include <stdlib.h>
  7. #include <ctype.h>
  8. #include <stdarg.h>
  9. #include <stdio.h>
  10. #include <assert.h>
  11. namespace tb {
  12. static const char *empty = "";
  13. inline void safe_delete(char *&str)
  14. {
  15. if (str != empty && str)
  16. free(str);
  17. str = const_cast<char*>(empty);
  18. }
  19. const char *stristr(const char *arg1, const char *arg2)
  20. {
  21. const char *a, *b;
  22. for(;*arg1;arg1++)
  23. {
  24. a = arg1;
  25. b = arg2;
  26. while (toupper(*a++) == toupper(*b++))
  27. if (!*b)
  28. return arg1;
  29. }
  30. return nullptr;
  31. }
  32. // == TBStr ==========================================================
  33. TBStr::TBStr()
  34. : TBStrC(empty)
  35. {
  36. }
  37. TBStr::TBStr(const char* str)
  38. : TBStrC(str == empty ? empty : strdup(str))
  39. {
  40. if (!s)
  41. s = const_cast<char*>(empty);
  42. }
  43. TBStr::TBStr(const TBStr &str)
  44. : TBStrC(str.s == empty ? empty : strdup(str.s))
  45. {
  46. if (!s)
  47. s = const_cast<char*>(empty);
  48. }
  49. TBStr::TBStr(const char* str, int len)
  50. : TBStrC(empty)
  51. {
  52. Set(str, len);
  53. }
  54. TBStr::~TBStr()
  55. {
  56. safe_delete(s);
  57. }
  58. bool TBStr::Set(const char* str, int len)
  59. {
  60. safe_delete(s);
  61. if (len == TB_ALL_TO_TERMINATION)
  62. len = strlen(str);
  63. if (char *new_s = (char *) malloc(len + 1))
  64. {
  65. s = new_s;
  66. memcpy(s, str, len);
  67. s[len] = 0;
  68. return true;
  69. }
  70. return false;
  71. }
  72. bool TBStr::SetFormatted(const char* format, ...)
  73. {
  74. safe_delete(s);
  75. if (!format)
  76. return true;
  77. va_list ap;
  78. int max_len = 64;
  79. char *new_s = nullptr;
  80. while (true)
  81. {
  82. if (char *tris_try_new_s = (char *) realloc(new_s, max_len))
  83. {
  84. new_s = tris_try_new_s;
  85. va_start(ap, format);
  86. int ret = vsnprintf(new_s, max_len, format, ap);
  87. va_end(ap);
  88. if (ret > max_len) // Needed size is known (+2 for termination and avoid ambiguity)
  89. max_len = ret + 2;
  90. else if (ret == -1 || ret >= max_len - 1) // Handle some buggy vsnprintf implementations.
  91. max_len *= 2;
  92. else // Everything fit for sure
  93. {
  94. s = new_s;
  95. return true;
  96. }
  97. }
  98. else
  99. {
  100. // Out of memory
  101. free(new_s);
  102. break;
  103. }
  104. }
  105. return false;
  106. }
  107. void TBStr::Clear()
  108. {
  109. safe_delete(s);
  110. }
  111. void TBStr::Remove(int ofs, int len)
  112. {
  113. assert(ofs >= 0 && (ofs + len <= (int)strlen(s)));
  114. if (!len)
  115. return;
  116. char *dst = s + ofs;
  117. char *src = s + ofs + len;
  118. while (*src != 0)
  119. *(dst++) = *(src++);
  120. *dst = *src;
  121. }
  122. bool TBStr::Insert(int ofs, const char *ins, int ins_len)
  123. {
  124. int len1 = strlen(s);
  125. if (ins_len == TB_ALL_TO_TERMINATION)
  126. ins_len = strlen(ins);
  127. int newlen = len1 + ins_len;
  128. if (char *news = (char *) malloc(newlen + 1))
  129. {
  130. memcpy(&news[0], s, ofs);
  131. memcpy(&news[ofs], ins, ins_len);
  132. memcpy(&news[ofs + ins_len], &s[ofs], len1 - ofs);
  133. news[newlen] = 0;
  134. safe_delete(s);
  135. s = news;
  136. return true;
  137. }
  138. return false;
  139. }
  140. }; // namespace tb