stringUnit.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "console/console.h"
  23. #include "string/stringUnit.h"
  24. #include "string/stringTable.h"
  25. #include "stringUnit_ScriptBinding.h"
  26. namespace StringUnit
  27. {
  28. static char _returnBuffer[4096];
  29. StringTableEntry getStringTableUnit(const char* string, U32 index, const char* set)
  30. {
  31. return StringTable->insert( getUnit( string, index, set ) );
  32. }
  33. const char* getUnit(const char* string, U32 index, const char* set)
  34. {
  35. U32 sz;
  36. while(index--)
  37. {
  38. if(!*string)
  39. return "";
  40. sz = dStrcspn(string, set);
  41. if (string[sz] == 0)
  42. return "";
  43. string += (sz + 1);
  44. }
  45. sz = dStrcspn(string, set);
  46. if (sz == 0)
  47. return "";
  48. AssertFatal( sz + 1 < sizeof( _returnBuffer ), "Size of returned string too large for return buffer" );
  49. char *ret = &_returnBuffer[0];
  50. dStrncpy(ret, string, sz);
  51. ret[sz] = '\0';
  52. return ret;
  53. }
  54. const char* getUnits(const char* string, S32 startIndex, S32 endIndex, const char* set)
  55. {
  56. // [neo, 5/11/2007 - #2998]
  57. // Range check
  58. if( startIndex > endIndex )
  59. return "";
  60. S32 sz;
  61. S32 index = startIndex;
  62. while(index--)
  63. {
  64. if(!*string)
  65. return "";
  66. sz = dStrcspn(string, set);
  67. if (string[sz] == 0)
  68. return "";
  69. string += (sz + 1);
  70. }
  71. const char *startString = string;
  72. while(startIndex <= endIndex--)
  73. {
  74. sz = dStrcspn(string, set);
  75. string += sz;
  76. if (*string == 0)
  77. break;
  78. string++;
  79. }
  80. if(!*string)
  81. string++;
  82. // [neo, 5/11/2007 - #2998]
  83. // Another case of the U32 wrapping from 0 to boom! If totalSize < 0 it will
  84. // wrap to somewhere around U32 max and that is a lot for dStrncpy to overrun!
  85. //U32 totalSize = (U32(string - startString));
  86. S32 totalSize = (S32)(string - startString);
  87. AssertFatal( totalSize < sizeof( _returnBuffer ), "Size of returned string too large for return buffer" );
  88. if( totalSize > 0 )
  89. {
  90. char *ret = &_returnBuffer[0];
  91. dStrncpy(ret, startString, totalSize - 1);
  92. ret[totalSize-1] = '\0';
  93. return ret;
  94. }
  95. return "";
  96. }
  97. U32 getUnitCount(const char *string, const char *set)
  98. {
  99. U32 count = 0;
  100. U8 last = 0;
  101. while(*string)
  102. {
  103. last = *string++;
  104. for(U32 i =0; set[i]; i++)
  105. {
  106. if(last == set[i])
  107. {
  108. count++;
  109. last = 0;
  110. break;
  111. }
  112. }
  113. }
  114. if(last)
  115. count++;
  116. return count;
  117. }
  118. const char* setUnit(const char *string, U32 index, const char *replace, const char *set)
  119. {
  120. U32 sz;
  121. const char *start = string;
  122. AssertFatal( dStrlen(string) + dStrlen(replace) + 1 < sizeof( _returnBuffer ), "Size of returned string too large for return buffer" );
  123. char *ret = &_returnBuffer[0];
  124. ret[0] = '\0';
  125. U32 padCount = 0;
  126. while(index--)
  127. {
  128. sz = dStrcspn(string, set);
  129. if(string[sz] == 0)
  130. {
  131. string += sz;
  132. padCount = index + 1;
  133. break;
  134. }
  135. else
  136. string += (sz + 1);
  137. }
  138. // copy first chunk
  139. sz = (U32)(string-start);
  140. dStrncpy(ret, start, sz);
  141. for(U32 i = 0; i < padCount; i++)
  142. ret[sz++] = set[0];
  143. // replace this unit
  144. ret[sz] = '\0';
  145. dStrcat(ret, replace);
  146. // copy remaining chunks
  147. sz = dStrcspn(string, set); // skip chunk we're replacing
  148. if(!sz && !string[sz])
  149. return ret;
  150. string += sz;
  151. dStrcat(ret, string);
  152. return ret;
  153. }
  154. const char* removeUnit(const char *string, U32 index, const char *set)
  155. {
  156. U32 sz;
  157. const char *start = string;
  158. AssertFatal( dStrlen(string) + 1 < sizeof( _returnBuffer ), "Size of returned string too large for return buffer" );
  159. char *ret = &_returnBuffer[0];
  160. ret[0] = '\0';
  161. while(index--)
  162. {
  163. sz = dStrcspn(string, set);
  164. // if there was no unit out there... return the original string
  165. if(string[sz] == 0)
  166. return start;
  167. else
  168. string += (sz + 1);
  169. }
  170. // copy first chunk
  171. sz = (U32)(string-start);
  172. dStrncpy(ret, start, sz);
  173. ret[sz] = 0;
  174. // copy remaining chunks
  175. sz = dStrcspn(string, set); // skip chunk we're removing
  176. if(string[sz] == 0) { // if that was the last...
  177. if(string != start) {
  178. ret[string - start - 1] = 0; // then kill any trailing delimiter
  179. }
  180. return ret; // and bail
  181. }
  182. string += sz + 1; // skip the extra field delimiter
  183. dStrcat(ret, string);
  184. return ret;
  185. }
  186. };