glue.c 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353
  1. /*
  2. Copyright (c) 2018-2024 Bruce A Henderson
  3. This software is provided 'as-is', without any express or implied
  4. warranty. In no event will the authors be held liable for any damages
  5. arising from the use of this software.
  6. Permission is granted to anyone to use this software for any purpose,
  7. including commercial applications, and to alter it and redistribute it
  8. freely, subject to the following restrictions:
  9. 1. The origin of this software must not be misrepresented; you must not
  10. claim that you wrote the original software. If you use this software
  11. in a product, an acknowledgment in the product documentation would be
  12. appreciated but is not required.
  13. 2. Altered source versions must be plainly marked as such, and must not be
  14. misrepresented as being the original software.
  15. 3. This notice may not be removed or altered from any source distribution.
  16. */
  17. #include "glue.h"
  18. #include <errno.h>
  19. #include <limits.h>
  20. #include <stdlib.h>
  21. static int utf32strlen( const BBUINT *p ){
  22. const BBUINT *t=p;
  23. while( *t ) ++t;
  24. return t-p;
  25. }
  26. void bmx_stringbuilder_free(struct MaxStringBuilder * buf) {
  27. free(buf->buffer);
  28. free(buf);
  29. }
  30. struct MaxStringBuilder * bmx_stringbuilder_new(int initial) {
  31. struct MaxStringBuilder * buf = malloc(sizeof(struct MaxStringBuilder));
  32. buf->count = 0;
  33. buf->capacity = initial;
  34. buf->buffer = malloc(initial * sizeof(BBChar));
  35. buf->hash = 0;
  36. return buf;
  37. }
  38. /* make more capacity if requested size greater */
  39. void bmx_stringbuilder_resize(struct MaxStringBuilder * buf, int size) {
  40. if (buf->capacity < size) {
  41. if (buf->capacity * 2 > size) {
  42. size = buf->capacity * 2;
  43. }
  44. BBChar * newBuffer = (BBChar *)malloc(size * sizeof(BBChar));
  45. /* copy text to new buffer */
  46. memcpy(newBuffer, buf->buffer, buf->count * sizeof(BBChar));
  47. /* free old buffer */
  48. free(buf->buffer);
  49. buf->buffer = newBuffer;
  50. buf->capacity = size;
  51. buf->hash = 0;
  52. }
  53. }
  54. int bmx_stringbuilder_count(struct MaxStringBuilder * buf) {
  55. return buf->count;
  56. }
  57. int bmx_stringbuilder_capacity(struct MaxStringBuilder * buf) {
  58. return buf->capacity;
  59. }
  60. void bmx_stringbuilder_setlength(struct MaxStringBuilder * buf, int length) {
  61. bmx_stringbuilder_resize(buf, length);
  62. if (length < buf->count) {
  63. buf->count = length;
  64. buf->hash = 0;
  65. }
  66. }
  67. BBString * bmx_stringbuilder_tostring(struct MaxStringBuilder * buf) {
  68. if (!buf->count) {
  69. return &bbEmptyString;
  70. } else {
  71. return bbStringFromShorts(buf->buffer, buf->count);
  72. }
  73. }
  74. void bmx_stringbuilder_append_string(struct MaxStringBuilder * buf, BBString * value) {
  75. if (value != &bbEmptyString) {
  76. bmx_stringbuilder_resize(buf, buf->count + value->length);
  77. BBChar * p = buf->buffer + buf->count;
  78. memcpy(p, value->buf, value->length * sizeof(BBChar));
  79. buf->count += value->length;
  80. buf->hash = 0;
  81. }
  82. }
  83. void bmx_stringbuilder_remove(struct MaxStringBuilder * buf, int start, int end) {
  84. if (start < 0 || start > buf->count || start > end) {
  85. return;
  86. }
  87. /* trim end if it is too big */
  88. if (end > buf->count) {
  89. end = buf->count;
  90. }
  91. /* still something to remove ? */
  92. if (buf->count - end != 0) {
  93. memcpy(buf->buffer + start, buf->buffer + end, (buf->count - end) * sizeof(BBChar));
  94. }
  95. buf->count -= end - start;
  96. buf->hash = 0;
  97. }
  98. void bmx_stringbuilder_insert(struct MaxStringBuilder * buf, int offset, BBString * value) {
  99. if (value != &bbEmptyString) {
  100. if (offset < 0 || offset > buf->count) {
  101. return;
  102. }
  103. int length = value->length;
  104. bmx_stringbuilder_resize(buf, buf->count + length);
  105. /* make some space for the insertion */
  106. /* using memmove because data overlaps */
  107. memmove(buf->buffer + offset + length, buf->buffer + offset, (buf->count - offset) * sizeof(BBChar));
  108. /* insert the string */
  109. memcpy(buf->buffer + offset, value->buf, length * sizeof(BBChar));
  110. buf->count += length;
  111. buf->hash = 0;
  112. }
  113. }
  114. void bmx_stringbuilder_reverse(struct MaxStringBuilder * buf) {
  115. int i = buf->count >> 1;
  116. int n = buf->count - i;
  117. while (--i >= 0) {
  118. BBChar c = buf->buffer[i];
  119. buf->buffer[i] = buf->buffer[n];
  120. buf->buffer[n] = c;
  121. n++;
  122. }
  123. buf->hash = 0;
  124. }
  125. BBString * bmx_stringbuilder_substring(struct MaxStringBuilder * buf, int beginIndex, int endIndex) {
  126. if (!endIndex) {
  127. endIndex = buf->count;
  128. }
  129. if (beginIndex < 0 || endIndex > buf->count || endIndex < beginIndex) {
  130. return &bbEmptyString;
  131. }
  132. return bbStringFromShorts(buf->buffer + beginIndex, endIndex - beginIndex);
  133. }
  134. void bmx_stringbuilder_append_stringbuffer(struct MaxStringBuilder * buf, struct MaxStringBuilder * other) {
  135. if (other->count > 0) {
  136. bmx_stringbuilder_resize(buf, buf->count + other->count);
  137. memcpy(buf->buffer + buf->count, other->buffer, other->count * sizeof(BBChar));
  138. buf->count += other->count;
  139. buf->hash = 0;
  140. }
  141. }
  142. int bmx_stringbuilder_matches(struct MaxStringBuilder * buf, int offset, BBString * subString) {
  143. int length = subString->length;
  144. int index = 0;
  145. while (--length >= 0) {
  146. if (buf->buffer[offset++] != subString->buf[index++]) {
  147. return 0;
  148. }
  149. }
  150. return 1;
  151. }
  152. int bmx_stringbuilder_startswith(struct MaxStringBuilder * buf, BBString * subString, int startIndex) {
  153. if (startIndex < 0) {
  154. startIndex = 0;
  155. }
  156. if ((startIndex + subString->length) <= buf->count) {
  157. return bmx_stringbuilder_matches(buf, startIndex, subString);
  158. }
  159. return 0;
  160. }
  161. int bmx_stringbuilder_endswith(struct MaxStringBuilder * buf, BBString * subString) {
  162. if (subString->length <= buf->count) {
  163. return bmx_stringbuilder_matches(buf, buf->count - subString->length, subString);
  164. }
  165. return 0;
  166. }
  167. int bmx_stringbuilder_find(struct MaxStringBuilder * buf, BBString * subString, int startIndex) {
  168. if (startIndex < 0) {
  169. startIndex = 0;
  170. }
  171. int limit = buf->count - subString->length;
  172. while (startIndex <= limit) {
  173. if (bmx_stringbuilder_matches(buf, startIndex, subString)) {
  174. return startIndex;
  175. }
  176. startIndex++;
  177. }
  178. return -1;
  179. }
  180. int bmx_stringbuilder_findlast(struct MaxStringBuilder * buf, BBString * subString, int startIndex) {
  181. if (startIndex < 0) {
  182. startIndex = 0;
  183. }
  184. startIndex = buf->count - startIndex;
  185. if (startIndex + subString->length > buf->count) {
  186. startIndex = buf->count - subString->length;
  187. }
  188. while (startIndex >= 0) {
  189. if (bmx_stringbuilder_matches(buf, startIndex, subString)) {
  190. return startIndex;
  191. }
  192. startIndex--;
  193. }
  194. return -1;
  195. }
  196. void bmx_stringbuilder_tolower(struct MaxStringBuilder * buf) {
  197. int i;
  198. for (i = 0; i < buf->count; i++ ) {
  199. int c = buf->buffer[i];
  200. if (c < 192) {
  201. c = ( c >= 'A' && c <= 'Z') ? (c|32) : c;
  202. } else {
  203. int lo = 0, hi = 3828 / 4 - 1;
  204. while (lo <= hi) {
  205. int mid = (lo+hi)/2;
  206. if (c < bbToLowerData[mid*2]) {
  207. hi = mid-1;
  208. } else if (c > bbToLowerData[mid*2]) {
  209. lo = mid + 1;
  210. } else {
  211. c = bbToLowerData[mid*2+1];
  212. break;
  213. }
  214. }
  215. }
  216. buf->buffer[i]=c;
  217. }
  218. buf->hash = 0;
  219. }
  220. void bmx_stringbuilder_toupper(struct MaxStringBuilder * buf) {
  221. int i;
  222. for (i = 0; i < buf->count; i++) {
  223. int c = buf->buffer[i];
  224. if (c < 181) {
  225. c = (c >= 'a' && c <= 'z') ? (c&~32) : c;
  226. } else {
  227. int lo = 0, hi = 3860/4-1;
  228. while (lo<=hi) {
  229. int mid=(lo+hi)/2;
  230. if (c < bbToUpperData[mid*2]) {
  231. hi = mid - 1;
  232. } else if (c > bbToUpperData[mid*2]) {
  233. lo = mid + 1;
  234. } else {
  235. c = bbToUpperData[mid*2+1];
  236. break;
  237. }
  238. }
  239. }
  240. buf->buffer[i]=c;
  241. }
  242. buf->hash = 0;
  243. }
  244. void bmx_stringbuilder_trim(struct MaxStringBuilder * buf) {
  245. int start = 0;
  246. int end = buf->count;
  247. while (start < end && buf->buffer[start] <= ' ') {
  248. ++start;
  249. }
  250. if (start == end ) {
  251. buf->count = 0;
  252. buf->hash = 0;
  253. return;
  254. }
  255. while (buf->buffer[end - 1] <= ' ') {
  256. --end;
  257. }
  258. if (end - start == buf->count) {
  259. return;
  260. }
  261. memmove(buf->buffer, buf->buffer + start, (end - start) * sizeof(BBChar));
  262. buf->count = end - start;
  263. buf->hash = 0;
  264. }
  265. void bmx_stringbuilder_replace(struct MaxStringBuilder * buf, BBString * subString, BBString * withString) {
  266. if (!subString->length) {
  267. return;
  268. }
  269. struct MaxStringBuilder * newbuf = bmx_stringbuilder_new(16);
  270. int j, n;
  271. int i = 0;
  272. int p = 0;
  273. while( (j = bmx_stringbuilder_find(buf, subString, i)) != -1) {
  274. n = j - i;
  275. if (n) {
  276. bmx_stringbuilder_resize(newbuf, newbuf->count + n);
  277. memcpy(newbuf->buffer + p, buf->buffer + i, n * sizeof(BBChar));
  278. newbuf->count += n;
  279. p += n;
  280. }
  281. n = withString->length;
  282. bmx_stringbuilder_resize(newbuf, newbuf->count + n);
  283. memcpy(newbuf->buffer + p, withString->buf, n * sizeof(BBChar));
  284. newbuf->count += n;
  285. p += n;
  286. i = j + subString->length;
  287. }
  288. n = buf->count - i;
  289. if (n) {
  290. bmx_stringbuilder_resize(newbuf, newbuf->count + n);
  291. memcpy(newbuf->buffer + p, buf->buffer + i, n*sizeof(BBChar));
  292. newbuf->count += n;
  293. }
  294. bmx_stringbuilder_setlength(buf, 0);
  295. bmx_stringbuilder_append_stringbuffer(buf, newbuf);
  296. bmx_stringbuilder_free(newbuf);
  297. }
  298. void bmx_stringbuilder_join(struct MaxStringBuilder * buf, BBArray * bits, struct MaxStringBuilder * newbuf) {
  299. if(bits == &bbEmptyArray) {
  300. return;
  301. }
  302. int i;
  303. int n_bits = bits->scales[0];
  304. BBString **p = (BBString**)BBARRAYDATA( bits,1 );
  305. for(i = 0; i < n_bits; ++i) {
  306. if (i) {
  307. bmx_stringbuilder_append_stringbuffer(newbuf, buf);
  308. }
  309. BBString *bit = *p++;
  310. bmx_stringbuilder_append_string(newbuf, bit);
  311. }
  312. }
  313. void bmx_stringbuilder_join_strings(struct MaxStringBuilder * buf, BBArray * bits, BBString * joiner) {
  314. if (bits == &bbEmptyArray) {
  315. return;
  316. }
  317. int i;
  318. int n_bits = bits->scales[0];
  319. int n = joiner->length;
  320. BBString **p = (BBString**)BBARRAYDATA( bits,1 );
  321. for(i = 0; i < n_bits; ++i) {
  322. if (i && n) {
  323. bmx_stringbuilder_append_string(buf, joiner);
  324. }
  325. bmx_stringbuilder_append_string(buf, *p++);
  326. }
  327. }
  328. struct MaxSplitBuffer * bmx_stringbuilder_split(struct MaxStringBuilder * buf, BBString * separator) {
  329. struct MaxSplitBuffer * splitBuffer = malloc(sizeof(struct MaxSplitBuffer));
  330. splitBuffer->buffer = buf;
  331. int count = 1;
  332. int i = 0;
  333. int offset = 0;
  334. if (separator->length > 0) {
  335. /* get a count of fields */
  336. while ((offset = bmx_stringbuilder_find(buf, separator, i)) != -1 ) {
  337. ++count;
  338. i = offset + separator->length;
  339. }
  340. splitBuffer->count = count;
  341. splitBuffer->startIndex = malloc(count * sizeof(int));
  342. splitBuffer->endIndex = malloc(count * sizeof(int));
  343. i = 0;
  344. int * bufferStartIndex = splitBuffer->startIndex;
  345. int * bufferEndIndex = splitBuffer->endIndex;
  346. while( count-- ){
  347. offset = bmx_stringbuilder_find(buf, separator, i);
  348. if (offset == -1) {
  349. offset = buf->count;
  350. }
  351. *bufferStartIndex++ = i;
  352. *bufferEndIndex++ = offset;
  353. i = offset + separator->length;
  354. }
  355. } else {
  356. // TODO - properly handle Null separator
  357. splitBuffer->count = count;
  358. splitBuffer->startIndex = malloc(count * sizeof(int));
  359. splitBuffer->endIndex = malloc(count * sizeof(int));
  360. *splitBuffer->startIndex = 0;
  361. *splitBuffer->endIndex = buf->count;
  362. }
  363. return splitBuffer;
  364. }
  365. void bmx_stringbuilder_setcharat(struct MaxStringBuilder * buf, int index, int ch) {
  366. if (index < 0 || index > buf->count) {
  367. return;
  368. }
  369. buf->buffer[index] = ch;
  370. buf->hash = 0;
  371. }
  372. int bmx_stringbuilder_charat(struct MaxStringBuilder * buf, int index) {
  373. if (index < 0 || index > buf->count) {
  374. return 0;
  375. }
  376. return buf->buffer[index];
  377. }
  378. void bmx_stringbuilder_removecharat(struct MaxStringBuilder * buf, int index) {
  379. if (index < 0 || index >= buf->count) {
  380. return;
  381. }
  382. if (index < buf->count - 1) {
  383. memcpy(buf->buffer + index, buf->buffer + index + 1, (buf->count - index - 1) * sizeof(BBChar));
  384. }
  385. buf->count--;
  386. buf->hash = 0;
  387. }
  388. void bmx_stringbuilder_append_cstring(struct MaxStringBuilder * buf, const char * chars) {
  389. int length = strlen(chars);
  390. bmx_stringbuilder_append_cstringbytes(buf, chars, length);
  391. }
  392. void bmx_stringbuilder_append_cstringbytes(struct MaxStringBuilder * buf, const char * chars, int length) {
  393. if (length > 0) {
  394. int count = length;
  395. bmx_stringbuilder_resize(buf, buf->count + length);
  396. const char * p = chars;
  397. BBChar * b = buf->buffer + buf->count;
  398. while (length--) {
  399. *b++ = *p++;
  400. }
  401. buf->count += count;
  402. buf->hash = 0;
  403. }
  404. }
  405. void bmx_stringbuilder_append_utf8string(struct MaxStringBuilder * buf, const char * chars) {
  406. int length = strlen(chars);
  407. bmx_stringbuilder_append_utf8bytes(buf, chars, length);
  408. }
  409. void bmx_stringbuilder_append_utf8bytes(struct MaxStringBuilder * buf, const char * chars, int length) {
  410. if (length > 0) {
  411. int count = 0;
  412. bmx_stringbuilder_resize(buf, buf->count + length);
  413. char * p = chars;
  414. BBChar * b = buf->buffer + buf->count;
  415. while( length-- ){
  416. int c=*p++ & 0xff;
  417. if( c<0x80 ){
  418. *b++=c;
  419. }else{
  420. if (!length--) break;
  421. int d=*p++ & 0x3f;
  422. if( c<0xe0 ){
  423. *b++=((c&31)<<6) | d;
  424. }else{
  425. if (!length--) break;
  426. int e=*p++ & 0x3f;
  427. if( c<0xf0 ){
  428. *b++=((c&15)<<12) | (d<<6) | e;
  429. }else{
  430. if (!length--) break;
  431. int f=*p++ & 0x3f;
  432. int v=((c&7)<<18) | (d<<12) | (e<<6) | f;
  433. if( v & 0xffff0000 ) bbExThrowCString( "Unicode character out of UCS-2 range" );
  434. *b++=v;
  435. }
  436. }
  437. }
  438. count++;
  439. }
  440. buf->count += count;
  441. buf->hash = 0;
  442. }
  443. }
  444. void bmx_stringbuilder_append_double(struct MaxStringBuilder * buf, double value) {
  445. char chars[64];
  446. sprintf(chars,"%#.17lg", value);
  447. bmx_stringbuilder_append_cstring(buf, chars);
  448. }
  449. void bmx_stringbuilder_append_float(struct MaxStringBuilder * buf, float value) {
  450. char chars[64];
  451. sprintf(chars,"%#.9g", value);
  452. bmx_stringbuilder_append_cstring(buf, chars);
  453. }
  454. void bmx_stringbuilder_append_int(struct MaxStringBuilder * buf, int value) {
  455. char chars[32];
  456. sprintf(chars, "%d", value);
  457. bmx_stringbuilder_append_cstring(buf, chars);
  458. }
  459. void bmx_stringbuilder_append_long(struct MaxStringBuilder * buf, BBInt64 value) {
  460. char chars[64];
  461. sprintf(chars, "%lld", value);
  462. bmx_stringbuilder_append_cstring(buf, chars);
  463. }
  464. void bmx_stringbuilder_append_short(struct MaxStringBuilder * buf, BBSHORT value) {
  465. char chars[16];
  466. sprintf(chars, "%d", value);
  467. bmx_stringbuilder_append_cstring(buf, chars);
  468. }
  469. void bmx_stringbuilder_append_byte(struct MaxStringBuilder * buf, BBBYTE value) {
  470. char chars[8];
  471. sprintf(chars, "%d", value);
  472. bmx_stringbuilder_append_cstring(buf, chars);
  473. }
  474. void bmx_stringbuilder_append_uint(struct MaxStringBuilder * buf, unsigned int value) {
  475. char chars[16];
  476. sprintf(chars, "%u", value);
  477. bmx_stringbuilder_append_cstring(buf, chars);
  478. }
  479. void bmx_stringbuilder_append_ulong(struct MaxStringBuilder * buf, BBUInt64 value) {
  480. char chars[64];
  481. sprintf(chars, "%llu", value);
  482. bmx_stringbuilder_append_cstring(buf, chars);
  483. }
  484. void bmx_stringbuilder_append_sizet(struct MaxStringBuilder * buf, BBSIZET value) {
  485. char chars[64];
  486. #if UINTPTR_MAX == 0xffffffff
  487. sprintf(chars, "%u", value);
  488. #else
  489. sprintf(chars, "%llu", value);
  490. #endif
  491. bmx_stringbuilder_append_cstring(buf, chars);
  492. }
  493. void bmx_stringbuilder_append_shorts(struct MaxStringBuilder * buf, BBSHORT * shorts, int length) {
  494. if (length > 0) {
  495. bmx_stringbuilder_resize(buf, buf->count + length);
  496. BBChar * p = buf->buffer + buf->count;
  497. memcpy(p, shorts, length * sizeof(BBChar));
  498. buf->count += length;
  499. buf->hash = 0;
  500. }
  501. }
  502. void bmx_stringbuilder_append_char(struct MaxStringBuilder * buf, int value) {
  503. bmx_stringbuilder_resize(buf, buf->count + 1);
  504. BBChar * p = buf->buffer + buf->count;
  505. *p = (BBChar)value;
  506. buf->count++;
  507. buf->hash = 0;
  508. }
  509. BBString * bmx_stringbuilder_left(struct MaxStringBuilder * buf, int length) {
  510. if (length <= 0) {
  511. return &bbEmptyString;
  512. } else if (length >= buf->count) {
  513. return bbStringFromShorts(buf->buffer, buf->count);
  514. } else {
  515. return bbStringFromShorts(buf->buffer, length);
  516. }
  517. }
  518. BBString * bmx_stringbuilder_right(struct MaxStringBuilder * buf, int length) {
  519. if (length <= 0) {
  520. return &bbEmptyString;
  521. } else if (length >= buf->count) {
  522. return bbStringFromShorts(buf->buffer, buf->count);
  523. } else {
  524. return bbStringFromShorts(buf->buffer + (buf->count - length), length);
  525. }
  526. }
  527. int bmx_stringbuilder_compare(struct MaxStringBuilder * buf1, struct MaxStringBuilder * buf2) {
  528. if (buf1 == buf2) {
  529. return 0;
  530. }
  531. int c = buf1->count < buf2->count ? buf1->count : buf2->count;
  532. int n = 0;
  533. int i;
  534. for (i=0; i < c; ++i) {
  535. if ((n = buf1->buffer[i] - buf2->buffer[i])) {
  536. return n;
  537. }
  538. }
  539. return buf1->count - buf2->count;
  540. }
  541. int bmx_stringbuilder_equals(struct MaxStringBuilder * buf1, struct MaxStringBuilder * buf2) {
  542. if (buf1 == buf2) {
  543. return 1;
  544. }
  545. if (buf1->count-buf2->count != 0) return 0;
  546. if (buf1->hash > 0 && buf1->hash == buf2->hash) return 1;
  547. return memcmp(buf1->buffer, buf2->buffer, buf1->count * sizeof(BBChar)) == 0;
  548. }
  549. void bmx_stringbuilder_leftalign(struct MaxStringBuilder * buf, int length) {
  550. if (length == buf->count) {
  551. return;
  552. } else if (length > buf->count) {
  553. bmx_stringbuilder_resize(buf, length);
  554. int c = length - buf->count;
  555. BBChar * p = buf->buffer + buf->count;
  556. int i;
  557. for (i=0; i < c; ++i) {
  558. *p++ = (BBChar)' ';
  559. }
  560. }
  561. buf->count = length;
  562. buf->hash = 0;
  563. }
  564. void bmx_stringbuilder_rightalign(struct MaxStringBuilder * buf, int length) {
  565. if (length == buf->count) {
  566. return;
  567. } else if (length < buf->count) {
  568. int offset = buf->count - length;
  569. memmove(buf->buffer, buf->buffer + offset, buf->count * sizeof(BBChar));
  570. } else {
  571. bmx_stringbuilder_resize(buf, length);
  572. int offset = length - buf->count;
  573. if (offset == 0) {
  574. return;
  575. }
  576. memmove(buf->buffer + offset, buf->buffer, buf->count * sizeof(BBChar));
  577. BBChar * p = buf->buffer;
  578. int i;
  579. for (i=0; i < offset; ++i) {
  580. *p++ = (BBChar)' ';
  581. }
  582. }
  583. buf->count = length;
  584. buf->hash = 0;
  585. }
  586. char * bmx_stringbuilder_toutf8string(struct MaxStringBuilder * buf) {
  587. int i = 0;
  588. int count = buf->count;
  589. if (count == 0) {
  590. return NULL;
  591. }
  592. char *ubuf = (char*)bbMemAlloc( count * 4 + 1 );
  593. char *q = ubuf;
  594. unsigned short *p = buf->buffer;
  595. while (i < count) {
  596. unsigned int c=*p++;
  597. if (0xd800 <= c && c <= 0xdbff && i < count - 1) {
  598. /* surrogate pair */
  599. unsigned int c2 = *p;
  600. if(0xdc00 <= c2 && c2 <= 0xdfff) {
  601. /* valid second surrogate */
  602. c = ((c - 0xd800) << 10) + (c2 - 0xdc00) + 0x10000;
  603. ++p;
  604. ++i;
  605. }
  606. }
  607. if (c < 0x80) {
  608. *q++ = c;
  609. } else if (c < 0x800){
  610. *q++ = 0xc0 | (c >> 6);
  611. *q++ = 0x80 | (c & 0x3f);
  612. } else if (c < 0x10000) {
  613. *q++ = 0xe0 | (c >> 12);
  614. *q++ = 0x80 | ((c >> 6) & 0x3f);
  615. *q++ = 0x80 | (c & 0x3f);
  616. } else if (c <= 0x10ffff) {
  617. *q++ = 0xf0 | (c >> 18);
  618. *q++ = 0x80 | ((c >> 12) & 0x3f);
  619. *q++ = 0x80 | ((c >> 6) & 0x3f);
  620. *q++ = 0x80 | ((c & 0x3f));
  621. } else {
  622. bbExThrowCString( "Unicode character out of UTF-8 range" );
  623. }
  624. ++i;
  625. }
  626. *q=0;
  627. return ubuf;
  628. }
  629. BBChar * bmx_stringbuilder_towstring(struct MaxStringBuilder * buf) {
  630. int count = buf->count;
  631. if (count == 0) {
  632. return NULL;
  633. }
  634. BBChar *p = (BBChar*)bbMemAlloc((count + 1) * sizeof(BBChar));
  635. memcpy(p, buf->buffer, count * sizeof(BBChar));
  636. p[count] = 0;
  637. return p;
  638. }
  639. void bmx_stringbuilder_toutf8_buffer(BBString *str, char * buf, size_t length) {
  640. int i=0,len=str->length;
  641. int out=0;
  642. char *q=buf;
  643. unsigned short *p=str->buf;
  644. while (i < len && out < length) {
  645. unsigned int c=*p++;
  646. if(0xd800 <= c && c <= 0xdbff && i < len - 1) {
  647. /* surrogate pair */
  648. unsigned int c2 = *p;
  649. if(0xdc00 <= c2 && c2 <= 0xdfff) {
  650. /* valid second surrogate */
  651. c = ((c - 0xd800) << 10) + (c2 - 0xdc00) + 0x10000;
  652. ++p;
  653. ++i;
  654. }
  655. }
  656. if( c<0x80 ){
  657. *q++=c;
  658. out++;
  659. }else if( c<0x800 ){
  660. if (out > length - 2) {
  661. break;
  662. }
  663. *q++=0xc0|(c>>6);
  664. *q++=0x80|(c&0x3f);
  665. out += 2;
  666. }else if(c < 0x10000) {
  667. if (out > length - 3) {
  668. break;
  669. }
  670. *q++=0xe0|(c>>12);
  671. *q++=0x80|((c>>6)&0x3f);
  672. *q++=0x80|(c&0x3f);
  673. out += 3;
  674. }else if(c <= 0x10ffff) {
  675. if (out > length - 4) {
  676. break;
  677. }
  678. *q++ = 0xf0|(c>>18);
  679. *q++ = 0x80|((c>>12)&0x3f);
  680. *q++ = 0x80|((c>>6)&0x3f);
  681. *q++ = 0x80|((c&0x3f));
  682. out += 4;
  683. }else{
  684. bbExThrowCString( "Unicode character out of UTF-8 range" );
  685. }
  686. ++i;
  687. }
  688. *q=0;
  689. }
  690. void bmx_stringbuilder_toutf8_sbuffer(BBChar * p, int len, char * buf, size_t length) {
  691. int i=0;
  692. int out=0;
  693. char *q=buf;
  694. while (i < len && out < length) {
  695. unsigned int c=*p++;
  696. if(0xd800 <= c && c <= 0xdbff && i < len - 1) {
  697. /* surrogate pair */
  698. unsigned int c2 = *p;
  699. if(0xdc00 <= c2 && c2 <= 0xdfff) {
  700. /* valid second surrogate */
  701. c = ((c - 0xd800) << 10) + (c2 - 0xdc00) + 0x10000;
  702. ++p;
  703. ++i;
  704. }
  705. }
  706. if( c<0x80 ){
  707. *q++=c;
  708. out++;
  709. }else if( c<0x800 ){
  710. if (out > length - 2) {
  711. break;
  712. }
  713. *q++=0xc0|(c>>6);
  714. *q++=0x80|(c&0x3f);
  715. out += 2;
  716. }else if(c < 0x10000) {
  717. if (out > length - 3) {
  718. break;
  719. }
  720. *q++=0xe0|(c>>12);
  721. *q++=0x80|((c>>6)&0x3f);
  722. *q++=0x80|(c&0x3f);
  723. out += 3;
  724. }else if(c <= 0x10ffff) {
  725. if (out > length - 4) {
  726. break;
  727. }
  728. *q++ = 0xf0|(c>>18);
  729. *q++ = 0x80|((c>>12)&0x3f);
  730. *q++ = 0x80|((c>>6)&0x3f);
  731. *q++ = 0x80|((c&0x3f));
  732. out += 4;
  733. }else{
  734. bbExThrowCString( "Unicode character out of UTF-8 range" );
  735. }
  736. ++i;
  737. }
  738. *q=0;
  739. }
  740. void bmx_stringbuilder_format_string(struct MaxStringBuilder * buf, BBString * formatText, BBString * value) {
  741. char formatBuf[256];
  742. bmx_stringbuilder_toutf8_buffer(formatText, formatBuf, sizeof(formatBuf));
  743. char vbuffer[2048];
  744. bmx_stringbuilder_toutf8_buffer(value, vbuffer, sizeof(vbuffer));
  745. char buffer[2048];
  746. snprintf(buffer, sizeof(buffer), formatBuf, vbuffer);
  747. bmx_stringbuilder_append_utf8string(buf, buffer);
  748. }
  749. void bmx_stringbuilder_format_byte(struct MaxStringBuilder * buf, BBString * formatText, BBBYTE value) {
  750. char formatBuf[256];
  751. bmx_stringbuilder_toutf8_buffer(formatText, formatBuf, sizeof(formatBuf));
  752. char buffer[2048];
  753. snprintf(buffer, sizeof(buffer), formatBuf, value);
  754. bmx_stringbuilder_append_utf8string(buf, buffer);
  755. }
  756. void bmx_stringbuilder_format_short(struct MaxStringBuilder * buf, BBString * formatText, BBSHORT value) {
  757. char formatBuf[256];
  758. bmx_stringbuilder_toutf8_buffer(formatText, formatBuf, sizeof(formatBuf));
  759. char buffer[2048];
  760. snprintf(buffer, sizeof(buffer), formatBuf, value);
  761. bmx_stringbuilder_append_utf8string(buf, buffer);
  762. }
  763. void bmx_stringbuilder_format_int(struct MaxStringBuilder * buf, BBString * formatText, BBINT value) {
  764. char formatBuf[256];
  765. bmx_stringbuilder_toutf8_buffer(formatText, formatBuf, sizeof(formatBuf));
  766. char buffer[2048];
  767. snprintf(buffer, sizeof(buffer), formatBuf, value);
  768. bmx_stringbuilder_append_utf8string(buf, buffer);
  769. }
  770. void bmx_stringbuilder_format_uint(struct MaxStringBuilder * buf, BBString * formatText, BBUINT value) {
  771. char formatBuf[256];
  772. bmx_stringbuilder_toutf8_buffer(formatText, formatBuf, sizeof(formatBuf));
  773. char buffer[2048];
  774. snprintf(buffer, sizeof(buffer), formatBuf, value);
  775. bmx_stringbuilder_append_utf8string(buf, buffer);
  776. }
  777. void bmx_stringbuilder_format_long(struct MaxStringBuilder * buf, BBString * formatText, BBLONG value) {
  778. char formatBuf[256];
  779. bmx_stringbuilder_toutf8_buffer(formatText, formatBuf, sizeof(formatBuf));
  780. char buffer[2048];
  781. snprintf(buffer, sizeof(buffer), formatBuf, value);
  782. bmx_stringbuilder_append_utf8string(buf, buffer);
  783. }
  784. void bmx_stringbuilder_format_ulong(struct MaxStringBuilder * buf, BBString * formatText, BBULONG value) {
  785. char formatBuf[256];
  786. bmx_stringbuilder_toutf8_buffer(formatText, formatBuf, sizeof(formatBuf));
  787. char buffer[2048];
  788. snprintf(buffer, sizeof(buffer), formatBuf, value);
  789. bmx_stringbuilder_append_utf8string(buf, buffer);
  790. }
  791. void bmx_stringbuilder_format_sizet(struct MaxStringBuilder * buf, BBString * formatText, BBSIZET value) {
  792. char formatBuf[256];
  793. bmx_stringbuilder_toutf8_buffer(formatText, formatBuf, sizeof(formatBuf));
  794. char buffer[2048];
  795. snprintf(buffer, sizeof(buffer), formatBuf, value);
  796. bmx_stringbuilder_append_utf8string(buf, buffer);
  797. }
  798. void bmx_stringbuilder_format_float(struct MaxStringBuilder * buf, BBString * formatText, float value) {
  799. char formatBuf[256];
  800. bmx_stringbuilder_toutf8_buffer(formatText, formatBuf, sizeof(formatBuf));
  801. char buffer[2048];
  802. snprintf(buffer, sizeof(buffer), formatBuf, value);
  803. bmx_stringbuilder_append_utf8string(buf, buffer);
  804. }
  805. void bmx_stringbuilder_format_double(struct MaxStringBuilder * buf, BBString * formatText, double value) {
  806. char formatBuf[256];
  807. bmx_stringbuilder_toutf8_buffer(formatText, formatBuf, sizeof(formatBuf));
  808. char buffer[2048];
  809. snprintf(buffer, sizeof(buffer), formatBuf, value);
  810. bmx_stringbuilder_append_utf8string(buf, buffer);
  811. }
  812. BBULONG bmx_stringbuilder_hash(struct MaxStringBuilder * buf) {
  813. if (buf->hash > 0) return buf->hash;
  814. buf->hash = XXH3_64bits(buf->buffer, buf->count * sizeof(BBChar));
  815. return buf->hash;
  816. }
  817. void bmx_stringbuilder_append_utf32string(struct MaxStringBuilder * buf, BBUINT * chars) {
  818. int length = utf32strlen(chars);
  819. bmx_stringbuilder_append_utf32bytes(buf, chars, length);
  820. }
  821. void bmx_stringbuilder_append_utf32bytes(struct MaxStringBuilder * buf, BBUINT * chars, int length) {
  822. if( !chars || length <= 0 ) return;
  823. int len = length * 2;
  824. bmx_stringbuilder_resize(buf, buf->count + len);
  825. BBChar * be = buf->buffer + buf->count;
  826. BBChar * q = be;
  827. BBUINT* bp = chars;
  828. int i = 0;
  829. while (i++ < length) {
  830. BBUINT c = *bp++;
  831. if (c <= 0xffffu) {
  832. if (c >= 0xd800u && c <= 0xdfffu) {
  833. *q++ = 0xfffd;
  834. } else {
  835. *q++ = c;
  836. }
  837. } else if (c > 0x0010ffffu) {
  838. *q++ = 0xfffd;
  839. } else {
  840. c -= 0x0010000u;
  841. *q++ = (BBChar)((c >> 10) + 0xd800);
  842. *q++ = (BBChar)((c & 0x3ffu) + 0xdc00);
  843. }
  844. }
  845. buf->count += (q - be);
  846. buf->hash = 0;
  847. }
  848. /* ----------------------------------------------------- */
  849. int bmx_stringbuilder_splitbuffer_length(struct MaxSplitBuffer * buf) {
  850. return buf->count;
  851. }
  852. BBString * bmx_stringbuilder_splitbuffer_text(struct MaxSplitBuffer * buf, int index) {
  853. if (index < 0 || index >= buf->count) {
  854. return &bbEmptyString;
  855. }
  856. return bmx_stringbuilder_substring(buf->buffer, buf->startIndex[index], buf->endIndex[index]);
  857. }
  858. void bmx_stringbuilder_splitbuffer_free(struct MaxSplitBuffer * buf) {
  859. free(buf->startIndex);
  860. free(buf->endIndex);
  861. free(buf);
  862. }
  863. BBArray * bmx_stringbuilder_splitbuffer_toarray(struct MaxSplitBuffer * buf) {
  864. int i, n;
  865. BBString **p,*bit;
  866. BBArray *bits;
  867. n = buf->count;
  868. bits = bbArrayNew1D("$", n);
  869. p = (BBString**)BBARRAYDATA(bits, 1);
  870. i = 0;
  871. while (n--) {
  872. bit = bmx_stringbuilder_substring(buf->buffer, buf->startIndex[i], buf->endIndex[i]);
  873. BBINCREFS( bit );
  874. *p++ = bit;
  875. i++;
  876. }
  877. return bits;
  878. }
  879. struct MaxSplitBuffer * bmx_stringbuilder_splitbuffer_split(struct MaxSplitBuffer * splitBuffer, BBString * separator, int index) {
  880. if (index < 0 || index >= splitBuffer->count) {
  881. return NULL;
  882. }
  883. // Extract the segment we want to split further
  884. int start = splitBuffer->startIndex[index];
  885. int end = splitBuffer->endIndex[index];
  886. // Create a temporary buffer for just this segment
  887. struct MaxStringBuilder tempBuf;
  888. tempBuf.buffer = splitBuffer->buffer->buffer + start;
  889. tempBuf.count = end - start;
  890. tempBuf.capacity = end - start;
  891. tempBuf.hash = 0;
  892. // First, count how many new segments we will create
  893. int count = 1;
  894. int offset = 0;
  895. int i = 0;
  896. while ((offset = bmx_stringbuilder_find(&tempBuf, separator, i)) != -1) {
  897. ++count;
  898. i = offset + separator->length;
  899. }
  900. // Allocate memory for new split buffer
  901. struct MaxSplitBuffer * newSplitBuffer = malloc(sizeof(struct MaxSplitBuffer));
  902. newSplitBuffer->buffer = splitBuffer->buffer; // Reference the original buffer
  903. newSplitBuffer->count = count;
  904. newSplitBuffer->startIndex = malloc(count * sizeof(int));
  905. newSplitBuffer->endIndex = malloc(count * sizeof(int));
  906. int * bufferStartIndex = newSplitBuffer->startIndex;
  907. int * bufferEndIndex = newSplitBuffer->endIndex;
  908. // Perform the actual split
  909. i = 0;
  910. int subSegmentStart = 0;
  911. while ((offset = bmx_stringbuilder_find(&tempBuf, separator, i)) != -1) {
  912. *bufferStartIndex++ = start + subSegmentStart;
  913. *bufferEndIndex++ = start + offset;
  914. subSegmentStart = offset + separator->length;
  915. i = subSegmentStart;
  916. }
  917. // Handle the last segment (or the whole segment if no separator was found)
  918. *bufferStartIndex++ = start + subSegmentStart;
  919. *bufferEndIndex++ = end;
  920. return newSplitBuffer;
  921. }
  922. int bmx_stringbuilder_splitbuffer_toint(struct MaxSplitBuffer * splitBuffer, int index) {
  923. if (index < 0 || index >= splitBuffer->count) {
  924. return 0;
  925. }
  926. // Get the start and end positions of the segment in the original buffer
  927. int start = splitBuffer->startIndex[index];
  928. int end = splitBuffer->endIndex[index];
  929. int length = end - start;
  930. // If the segment is empty, return 0
  931. if (length == 0) {
  932. return 0;
  933. }
  934. BBChar *segment = (BBChar *)&(splitBuffer->buffer->buffer[start]);
  935. char numbuf[256];
  936. bmx_stringbuilder_toutf8_sbuffer(segment, length, numbuf, sizeof(numbuf));
  937. char *endPtr;
  938. errno = 0;
  939. long result = strtol(numbuf, &endPtr, 10);
  940. // Make sure that endPtr does not exceed the bounds of the segment
  941. if (endPtr > numbuf + length) {
  942. return 0;
  943. }
  944. if (errno == ERANGE || result > INT_MAX || result < INT_MIN || endPtr == numbuf) {
  945. return 0;
  946. }
  947. return (int)result;
  948. }
  949. unsigned int bmx_stringbuilder_splitbuffer_touint(struct MaxSplitBuffer * splitBuffer, int index) {
  950. if (index < 0 || index >= splitBuffer->count) {
  951. return 0;
  952. }
  953. int start = splitBuffer->startIndex[index];
  954. int end = splitBuffer->endIndex[index];
  955. int length = end - start;
  956. if (length == 0) {
  957. return 0;
  958. }
  959. BBChar *segment = (BBChar *) &(splitBuffer->buffer->buffer[start]);
  960. char numbuf[256];
  961. bmx_stringbuilder_toutf8_sbuffer(segment, length, numbuf, sizeof(numbuf));
  962. char *endPtr;
  963. errno = 0;
  964. unsigned long result = strtoul(numbuf, &endPtr, 10);
  965. if (endPtr > numbuf + length || errno == ERANGE || endPtr == numbuf || result > UINT_MAX) {
  966. return 0;
  967. }
  968. return (unsigned int)result;
  969. }
  970. float bmx_stringbuilder_splitbuffer_tofloat(struct MaxSplitBuffer * splitBuffer, int index) {
  971. if (index < 0 || index >= splitBuffer->count) {
  972. return 0.0f;
  973. }
  974. int start = splitBuffer->startIndex[index];
  975. int end = splitBuffer->endIndex[index];
  976. int length = end - start;
  977. if (length == 0) {
  978. return 0.0f;
  979. }
  980. BBChar *segment = (BBChar *) &(splitBuffer->buffer->buffer[start]);
  981. char numbuf[256];
  982. bmx_stringbuilder_toutf8_sbuffer(segment, length, numbuf, sizeof(numbuf));
  983. char *endPtr;
  984. errno = 0;
  985. float result = strtof(numbuf, &endPtr);
  986. if (endPtr > numbuf + length || errno == ERANGE || endPtr == numbuf) {
  987. return 0.0f;
  988. }
  989. return result;
  990. }
  991. double bmx_stringbuilder_splitbuffer_todouble(struct MaxSplitBuffer * splitBuffer, int index) {
  992. if (index < 0 || index >= splitBuffer->count) {
  993. return 0.0;
  994. }
  995. int start = splitBuffer->startIndex[index];
  996. int end = splitBuffer->endIndex[index];
  997. int length = end - start;
  998. if (length == 0) {
  999. return 0.0;
  1000. }
  1001. BBChar *segment = (BBChar *) &(splitBuffer->buffer->buffer[start]);
  1002. char numbuf[256];
  1003. bmx_stringbuilder_toutf8_sbuffer(segment, length, numbuf, sizeof(numbuf));
  1004. char *endPtr;
  1005. errno = 0;
  1006. double result = strtod(numbuf, &endPtr);
  1007. if (endPtr > numbuf + length || errno == ERANGE || endPtr == numbuf) {
  1008. return 0.0;
  1009. }
  1010. return result;
  1011. }
  1012. BBInt64 bmx_stringbuilder_splitbuffer_tolong(struct MaxSplitBuffer * splitBuffer, int index) {
  1013. if (index < 0 || index >= splitBuffer->count) {
  1014. return 0;
  1015. }
  1016. int start = splitBuffer->startIndex[index];
  1017. int end = splitBuffer->endIndex[index];
  1018. int length = end - start;
  1019. if (length == 0) {
  1020. return 0;
  1021. }
  1022. BBChar *segment = (BBChar *) &(splitBuffer->buffer->buffer[start]);
  1023. char numbuf[256];
  1024. bmx_stringbuilder_toutf8_sbuffer(segment, length, numbuf, sizeof(numbuf));
  1025. char *endPtr;
  1026. errno = 0;
  1027. BBInt64 result = strtoll(numbuf, &endPtr, 10);
  1028. if (endPtr > numbuf + length || errno == ERANGE || endPtr == numbuf) {
  1029. return 0;
  1030. }
  1031. return result;
  1032. }
  1033. BBUInt64 bmx_stringbuilder_splitbuffer_toulong(struct MaxSplitBuffer * splitBuffer, int index) {
  1034. if (index < 0 || index >= splitBuffer->count) {
  1035. return 0;
  1036. }
  1037. int start = splitBuffer->startIndex[index];
  1038. int end = splitBuffer->endIndex[index];
  1039. int length = end - start;
  1040. if (length == 0) {
  1041. return 0;
  1042. }
  1043. BBChar *segment = (BBChar *) &(splitBuffer->buffer->buffer[start]);
  1044. char numbuf[256];
  1045. bmx_stringbuilder_toutf8_sbuffer(segment, length, numbuf, sizeof(numbuf));
  1046. char *endPtr;
  1047. errno = 0;
  1048. BBUInt64 result = strtoull(numbuf, &endPtr, 10);
  1049. if (endPtr > numbuf + length || errno == ERANGE || endPtr == numbuf) {
  1050. return 0;
  1051. }
  1052. return result;
  1053. }
  1054. size_t bmx_stringbuilder_splitbuffer_tosizet(struct MaxSplitBuffer * splitBuffer, int index) {
  1055. if (index < 0 || index >= splitBuffer->count) {
  1056. return 0;
  1057. }
  1058. int start = splitBuffer->startIndex[index];
  1059. int end = splitBuffer->endIndex[index];
  1060. int length = end - start;
  1061. if (length == 0) {
  1062. return 0;
  1063. }
  1064. BBChar *segment = (BBChar *) &(splitBuffer->buffer->buffer[start]);
  1065. char numbuf[256];
  1066. bmx_stringbuilder_toutf8_sbuffer(segment, length, numbuf, sizeof(numbuf));
  1067. char *endPtr;
  1068. errno = 0;
  1069. unsigned long long result = strtoull(numbuf, &endPtr, 10);
  1070. if (endPtr > numbuf + length || errno == ERANGE || endPtr == numbuf) {
  1071. return 0;
  1072. }
  1073. return (size_t)result;
  1074. }
  1075. BBSHORT bmx_stringbuilder_splitbuffer_toshort(struct MaxSplitBuffer * splitBuffer, int index) {
  1076. if (index < 0 || index >= splitBuffer->count) {
  1077. return 0;
  1078. }
  1079. int start = splitBuffer->startIndex[index];
  1080. int end = splitBuffer->endIndex[index];
  1081. int length = end - start;
  1082. if (length == 0) {
  1083. return 0;
  1084. }
  1085. BBChar *segment = (BBChar *) &(splitBuffer->buffer->buffer[start]);
  1086. char numbuf[256];
  1087. bmx_stringbuilder_toutf8_sbuffer(segment, length, numbuf, sizeof(numbuf));
  1088. char *endPtr;
  1089. errno = 0;
  1090. long result = strtol(numbuf, &endPtr, 10);
  1091. if (endPtr > numbuf + length || errno == ERANGE || endPtr == numbuf || result < 0 || result > USHRT_MAX) {
  1092. return 0;
  1093. }
  1094. return (BBSHORT)result;
  1095. }
  1096. BBBYTE bmx_stringbuilder_splitbuffer_tobyte(struct MaxSplitBuffer * splitBuffer, int index) {
  1097. if (index < 0 || index >= splitBuffer->count) {
  1098. return 0;
  1099. }
  1100. int start = splitBuffer->startIndex[index];
  1101. int end = splitBuffer->endIndex[index];
  1102. int length = end - start;
  1103. if (length == 0) {
  1104. return 0;
  1105. }
  1106. BBChar *segment = (BBChar *) &(splitBuffer->buffer->buffer[start]);
  1107. char numbuf[256];
  1108. bmx_stringbuilder_toutf8_sbuffer(segment, length, numbuf, sizeof(numbuf));
  1109. char *endPtr;
  1110. errno = 0;
  1111. long result = strtol(numbuf, &endPtr, 10);
  1112. if (endPtr > numbuf + length || errno == ERANGE || endPtr == numbuf || result < 0 || result > UCHAR_MAX) {
  1113. return 0;
  1114. }
  1115. return (BBBYTE)result;
  1116. }