stringbuilder.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. #include "stringbuilder.h"
  2. #include <string.h>
  3. #include <stdio.h>
  4. #include <inttypes.h>
  5. stringbuilder_node::stringbuilder_node()
  6. {
  7. // This constructor is only used for fast_nodes.
  8. }
  9. stringbuilder_node::stringbuilder_node(datastring node,bool should_delete)
  10. {
  11. data.item = node;
  12. need_to_delete = should_delete;
  13. is_number = false;
  14. }
  15. stringbuilder_node::stringbuilder_node(int64_t value)
  16. {
  17. data.number = value;
  18. need_to_delete = false;
  19. is_number = true;
  20. }
  21. void stringbuilder_node::clear()
  22. {
  23. if ((!is_number) && (data.item.data != nullptr)) {
  24. if (need_to_delete) {
  25. delete data.item.data;
  26. }
  27. data.item.data = nullptr;
  28. }
  29. return;
  30. }
  31. stringbuilder::stringbuilder()
  32. {
  33. index = 0;
  34. }
  35. stringbuilder::~stringbuilder()
  36. {
  37. clear();
  38. }
  39. stringbuilder &stringbuilder::addparameter(int item)
  40. {
  41. // Appends the number, then a comma.
  42. return addparameter((int64_t)item);
  43. }
  44. stringbuilder &stringbuilder::addparameter(int64_t item)
  45. {
  46. // Appends the number, then a comma.
  47. operator+=(item);
  48. operator+=(",");
  49. return *this;
  50. }
  51. stringbuilder &stringbuilder::addparameter(datastring item)
  52. {
  53. // Appends the length first, then a comma, then the data.
  54. operator+=(item.length);
  55. operator+=(",");
  56. append(item,false);
  57. return *this;
  58. }
  59. stringbuilder &stringbuilder::operator+=(const char *item)
  60. {
  61. datastring temp;
  62. temp.data = (char *)item;
  63. temp.length = item == nullptr ? 0 : strlen(item);
  64. temp.null_terminated = true;
  65. append(temp, false);
  66. return *this;
  67. }
  68. stringbuilder &stringbuilder::operator+=(datastring item)
  69. {
  70. append(item, false);
  71. return *this;
  72. }
  73. stringbuilder &stringbuilder::operator+=(int item)
  74. {
  75. return append((int64_t)item);
  76. }
  77. stringbuilder &stringbuilder::operator+=(int64_t item)
  78. {
  79. return append(item);
  80. }
  81. stringbuilder &stringbuilder::append(int64_t item)
  82. {
  83. auto node = nodes[index];
  84. node->used = true;
  85. if (index < FAST_NODE_COUNT) {
  86. node->item = fast_nodes + index;
  87. node->item->data.number = item;
  88. node->item->is_number = true;
  89. node->item->need_to_delete = false;
  90. } else {
  91. node->item = new stringbuilder_node(item);
  92. }
  93. index++;
  94. return *this;
  95. }
  96. stringbuilder &stringbuilder::append(datastring item, bool need_to_delete)
  97. {
  98. auto node = nodes[index];
  99. node->used = true;
  100. if (index < FAST_NODE_COUNT) {
  101. node->item = fast_nodes + index;
  102. node->item->data.item = item;
  103. node->item->is_number = false;
  104. node->item->need_to_delete = need_to_delete;
  105. } else {
  106. node->item = new stringbuilder_node(item,need_to_delete);
  107. }
  108. index++;
  109. return *this;
  110. }
  111. int stringbuilder::length()
  112. {
  113. int loop;
  114. int total = 0;
  115. int64_t number;
  116. for(loop=0;loop<index;loop++) {
  117. auto node = nodes[loop];
  118. if (node->item->is_number) {
  119. // Figure out the length of the number when converted to base 10.
  120. number = node->item->data.number;
  121. if (number < 0) {
  122. // Minus sign.
  123. number = -number;
  124. total++;
  125. }
  126. total++; // First digit.
  127. // Count other digits.
  128. while (number >= 10000) {
  129. total += 4;
  130. number /= 10000;
  131. }
  132. while (number >= 10) {
  133. total++;
  134. number /= 10;
  135. }
  136. } else {
  137. total += node->item->data.item.length;
  138. }
  139. }
  140. return total;
  141. }
  142. void stringbuilder::clear()
  143. {
  144. // Clears the list and deletes any allocated items.
  145. int loop;
  146. for(loop=0;loop<index;loop++) {
  147. auto node = nodes[loop];
  148. node->item->clear();
  149. if (loop >= FAST_NODE_COUNT) {
  150. delete node->item;
  151. }
  152. node->item = nullptr;
  153. node->used = false;
  154. }
  155. index = 0;
  156. return;
  157. }
  158. void stringbuilder::print()
  159. {
  160. biglist<stringbuilder_node *>nodes;
  161. biglist_iterator<stringbuilder_node *>loop(&nodes);
  162. while(!loop.eof()) {
  163. if (loop.item->is_number) {
  164. printf("%" PRId64,loop.item->data.number);
  165. } else {
  166. loop.item->data.item.print();
  167. }
  168. loop.movenext();
  169. }
  170. return;
  171. }
  172. void stringbuilder::println()
  173. {
  174. print();
  175. printf("\n");
  176. }
  177. int stringbuilder::tostring(char *buffer)
  178. {
  179. // Save this string to a buffer.
  180. // It assumes that the buffer was allocated already
  181. // by calling the length() function.
  182. // Be sure to allow an extra byte for the end of line.
  183. int message_length;
  184. int buffersize;
  185. char *pos;
  186. int node_loop;
  187. int item_length;
  188. int node_count;
  189. int64_t number;
  190. int64_t divisor;
  191. int64_t remainder;
  192. bool showzero;
  193. pos = buffer;
  194. node_count = index;
  195. for(node_loop=0;node_loop<node_count;node_loop++) {
  196. auto node = nodes[node_loop];
  197. auto node_item = node->item;
  198. if (node_item->is_number) {
  199. number = node->item->data.number;
  200. if (number < 0) {
  201. number = -number;
  202. *(pos++) = '-';
  203. }
  204. divisor = 1000000000000000000L;
  205. showzero = false;
  206. while (true) {
  207. remainder = number / divisor;
  208. if ((showzero) || (remainder > 0) || (divisor == 1)) {
  209. *(pos++) = (char)remainder + '0';
  210. showzero = true;
  211. number -= divisor * remainder;
  212. }
  213. if (divisor == 1) {
  214. break;
  215. }
  216. divisor /= 10;
  217. }
  218. } else {
  219. item_length = node_item->data.item.length;
  220. if (item_length > 0) {
  221. memcpy(pos,node_item->data.item.data,item_length);
  222. pos+=item_length;
  223. }
  224. }
  225. }
  226. *pos = 0;
  227. return pos - buffer;
  228. }