2
0

blitz_string.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104
  1. #include "blitz.h"
  2. #include "bdwgc/libatomic_ops/src/atomic_ops.h"
  3. #include "blitz_unicode.h"
  4. #define XXH_IMPLEMENTATION
  5. #define XXH_STATIC_LINKING_ONLY
  6. #include "hash/xxh3.h"
  7. static void bbStringFree( BBObject *o );
  8. static BBDebugScope debugScope={
  9. BBDEBUGSCOPE_USERTYPE,
  10. "String",
  11. {
  12. {
  13. BBDEBUGDECL_END
  14. }
  15. }
  16. };
  17. struct BBClass_String bbStringClass={
  18. &bbObjectClass, //super
  19. bbStringFree, //free
  20. &debugScope, //DebugScope
  21. 0, //instance_size
  22. 0, //ctor
  23. 0, //dtor
  24. (BBString*(*)(BBObject*))bbStringToString,
  25. (int(*)(BBObject*,BBObject*))bbStringCompare,
  26. bbObjectSendMessage,
  27. 0, //interface
  28. 0, //extra
  29. 0,
  30. 0, //instance_count
  31. offsetof(BBString, hash), //fields_offset
  32. bbStringFind,
  33. bbStringFindLast,
  34. bbStringTrim,
  35. bbStringReplace,
  36. bbStringToLower,
  37. bbStringToUpper,
  38. bbStringToInt,
  39. bbStringToLong,
  40. bbStringToFloat,
  41. bbStringToDouble,
  42. bbStringToCString,
  43. bbStringToWString,
  44. bbStringFromInt,
  45. bbStringFromLong,
  46. bbStringFromFloat,
  47. bbStringFromDouble,
  48. bbStringFromCString,
  49. bbStringFromWString,
  50. bbStringFromBytes,
  51. bbStringFromShorts,
  52. bbStringStartsWith,
  53. bbStringEndsWith,
  54. bbStringContains,
  55. bbStringSplit,
  56. bbStringJoin,
  57. bbStringFromUTF8String,
  58. bbStringToUTF8String,
  59. bbStringFromUTF8Bytes,
  60. bbStringToSizet,
  61. bbStringFromSizet,
  62. bbStringToUInt,
  63. bbStringFromUInt,
  64. bbStringToULong,
  65. bbStringFromULong,
  66. #ifdef _WIN32
  67. bbStringToWParam,
  68. bbStringFromWParam,
  69. bbStringToLParam,
  70. bbStringFromLParam,
  71. #endif
  72. bbStringToUTF8StringBuffer,
  73. bbStringHash,
  74. bbStringToUTF32String,
  75. bbStringFromUTF32String,
  76. bbStringFromUTF32Bytes
  77. };
  78. BBString bbEmptyString={
  79. (BBClass*)&bbStringClass, //clas
  80. 0x776eddfb6bfd9195, // hash
  81. 0 //length
  82. };
  83. static int wstrlen( const BBChar *p ){
  84. const BBChar *t=p;
  85. while( *t ) ++t;
  86. return t-p;
  87. }
  88. static int utf32strlen( const BBUINT *p ){
  89. const BBUINT *t=p;
  90. while( *t ) ++t;
  91. return t-p;
  92. }
  93. static int charsEqual( unsigned short *a,unsigned short *b,int n ){
  94. while( n-- ){
  95. if (*a!=*b) return 0;
  96. a++;b++;
  97. }
  98. return 1;
  99. }
  100. //***** Note: Not called in THREADED mode.
  101. static void bbStringFree( BBObject *o ){
  102. if (bbCountInstances) {
  103. bbAtomicAdd((int*)&bbStringClass.instance_count, -1);
  104. }
  105. }
  106. BBString *bbStringNew( int len ){
  107. BBString *str;
  108. if( !len ) return &bbEmptyString;
  109. str=(BBString*)bbGCAllocObject( sizeof(BBString)+len*sizeof(BBChar),(BBClass*)&bbStringClass,BBGC_ATOMIC );
  110. str->hash=0;
  111. str->length=len;
  112. return str;
  113. }
  114. BBString *bbStringFromChar( int c ){
  115. BBString *str=bbStringNew(1);
  116. str->buf[0]=c;
  117. return str;
  118. }
  119. BBString *bbStringFromInt( int n ){
  120. char buf[64];
  121. sprintf(buf, "%d", n);
  122. return bbStringFromBytes( (unsigned char*)buf, strlen(buf) );
  123. }
  124. BBString *bbStringFromUInt( unsigned int n ){
  125. char buf[64];
  126. sprintf(buf, "%u", n);
  127. return bbStringFromBytes( (unsigned char*)buf, strlen(buf) );
  128. }
  129. BBString *bbStringFromLong( BBInt64 n ){
  130. char buf[64];
  131. sprintf(buf, "%lld", n);
  132. return bbStringFromBytes( (unsigned char*)buf,strlen(buf) );
  133. }
  134. BBString *bbStringFromULong( BBUInt64 n ){
  135. char buf[64];
  136. sprintf(buf, "%llu", n);
  137. return bbStringFromBytes( (unsigned char*)buf, strlen(buf) );
  138. }
  139. BBString *bbStringFromSizet( BBSIZET n ){
  140. char buf[64];
  141. #if UINTPTR_MAX == 0xffffffff
  142. sprintf(buf, "%u", n);
  143. #else
  144. sprintf(buf, "%llu", n);
  145. #endif
  146. return bbStringFromBytes( (unsigned char*)buf, strlen(buf) );
  147. }
  148. BBString *bbStringFromFloat( float n ){
  149. char buf[64];
  150. sprintf( buf,"%#.9g",n );
  151. return bbStringFromCString(buf);
  152. }
  153. BBString *bbStringFromDouble( double n ){
  154. char buf[64];
  155. sprintf( buf,"%#.17lg",n );
  156. return bbStringFromCString(buf);
  157. }
  158. BBString *bbStringFromBytes( const unsigned char *p,int n ){
  159. int k;
  160. BBString *str;
  161. if( !n ) return &bbEmptyString;
  162. str=bbStringNew( n );
  163. for( k=0;k<n;++k ) str->buf[k]=p[k];
  164. return str;
  165. }
  166. BBString *bbStringFromShorts( const unsigned short *p,int n ){
  167. BBString *str;
  168. if( !n ) return &bbEmptyString;
  169. str=bbStringNew( n );
  170. bbMemCopy( str->buf,p,n*sizeof(short) );
  171. return str;
  172. }
  173. BBString *bbStringFromInts( const int *p,int n ){
  174. int k;
  175. BBString *str;
  176. if( !n ) return &bbEmptyString;
  177. str=bbStringNew( n );
  178. for( k=0;k<n;++k ) str->buf[k]=p[k];
  179. return str;
  180. }
  181. BBString *bbStringFromUInts( const unsigned int *p,int n ){
  182. int k;
  183. BBString *str;
  184. if( !n ) return &bbEmptyString;
  185. str=bbStringNew( n );
  186. for( k=0;k<n;++k ) str->buf[k]=p[k];
  187. return str;
  188. }
  189. BBString *bbStringFromArray( BBArray *arr ){
  190. int n;
  191. void *p;
  192. if( arr->dims!=1 ) return &bbEmptyString;
  193. n=arr->scales[0];
  194. p=BBARRAYDATA(arr,arr->dims);
  195. switch( arr->type[0] ){
  196. case 'b':return bbStringFromBytes( (unsigned char*)p,n );
  197. case 's':return bbStringFromShorts( p,n );
  198. case 'i':return bbStringFromInts( p,n );
  199. }
  200. return &bbEmptyString;
  201. }
  202. BBString *bbStringFromCString( const char *p ){
  203. return p ? bbStringFromBytes( (unsigned char*)p,strlen(p) ) : &bbEmptyString;
  204. }
  205. BBString *bbStringFromWString( const BBChar *p ){
  206. return p ? bbStringFromShorts( p,wstrlen(p) ) : &bbEmptyString;
  207. }
  208. BBString *bbStringFromUTF8String( const unsigned char *p ){
  209. return p ? bbStringFromUTF8Bytes( p,strlen((char*)p) ) : &bbEmptyString;
  210. }
  211. BBString *bbStringFromUTF8Bytes( const unsigned char *p,int n ){
  212. int c;
  213. unsigned short *d,*q;
  214. BBString *str;
  215. if( !p || n <= 0 ) return &bbEmptyString;
  216. d=(unsigned short*)malloc( n*2 );
  217. q=d;
  218. while( n-- && (c=*p++ & 0xff)){
  219. if( c<0x80 ){
  220. *q++=c;
  221. }else{
  222. if (!n--) continue;
  223. int d=*p++ & 0x3f;
  224. if( c<0xe0 ){
  225. *q++=((c&31)<<6) | d;
  226. }else{
  227. if (!n--) continue;
  228. int e=*p++ & 0x3f;
  229. if( c<0xf0 ){
  230. *q++=((c&15)<<12) | (d<<6) | e;
  231. }else{
  232. if (!n--) continue;
  233. int f=*p++ & 0x3f;
  234. int v=((c&7)<<18) | (d<<12) | (e<<6) | f;
  235. if( v & 0xffff0000 ) {
  236. v -= 0x10000;
  237. d = ((v >> 10) & 0x7ff) + 0xd800;
  238. e = (v & 0x3ff) + 0xdc00;
  239. *q++=d;
  240. *q++=e;
  241. }else{
  242. *q++=v;
  243. }
  244. }
  245. }
  246. }
  247. }
  248. str=bbStringFromShorts( d,q-d );
  249. free( d );
  250. return str;
  251. }
  252. BBString *bbStringToString( BBString *t ){
  253. return t;
  254. }
  255. int bbStringCompare( BBString *x,BBString *y ){
  256. int k,n,sz;
  257. sz=x->length<y->length ? x->length : y->length;
  258. for( k=0;k<sz;++k ) if( (n=x->buf[k]-y->buf[k]) ) return n;
  259. return x->length-y->length;
  260. }
  261. int bbStringStartsWith( BBString *x,BBString *y ){
  262. BBChar *p,*q;
  263. int k,sz=y->length;
  264. if( x->length<sz ) return 0;
  265. p=x->buf;
  266. q=y->buf;
  267. for( k=0;k<sz;++k ) if( *p++!=*q++ ) return 0;
  268. return 1;
  269. }
  270. int bbStringEndsWith( BBString *x,BBString *y ){
  271. BBChar *p,*q;
  272. int k,sz=y->length;
  273. if( x->length<sz ) return 0;
  274. p=x->buf+x->length-sz;
  275. q=y->buf;
  276. for( k=0;k<sz;++k ) if( *p++!=*q++ ) return 0;
  277. return 1;
  278. }
  279. int bbStringContains( BBString *x,BBString *y ){
  280. return bbStringFind( x,y,0 )!=-1;
  281. }
  282. BBString *bbStringConcat( BBString *x,BBString *y ){
  283. int len=x->length+y->length;
  284. BBString *t=bbStringNew(len);
  285. memcpy( t->buf,x->buf,x->length*sizeof(BBChar) );
  286. memcpy( t->buf+x->length,y->buf,y->length*sizeof(BBChar) );
  287. return t;
  288. }
  289. BBString *bbStringSlice( BBString *in,int beg,int end ){
  290. BBChar *p;
  291. BBString *out;
  292. int k,n,len,inlen;
  293. len=end-beg;
  294. if( len<=0 ) return &bbEmptyString;
  295. out=bbStringNew( len );
  296. p=out->buf;
  297. inlen=in->length;
  298. if( (n=-beg)>0 ){
  299. if( beg+n>end ) n=end-beg;
  300. for( k=0;k<n;++k ) *p++=' ';
  301. if( (beg+=n)==end ) return out;
  302. }
  303. if( (n=inlen-beg)>0 ){
  304. BBChar *q=in->buf+beg;
  305. if( beg+n>end ) n=end-beg;
  306. for( k=0;k<n;++k ) *p++=*q++;
  307. if( (beg+=n)==end ) return out;
  308. }
  309. if( (n=end-beg)>0 ){
  310. for( k=0;k<n;++k ) *p++=' ';
  311. }
  312. return out;
  313. }
  314. BBString *bbStringTrim( BBString *str ){
  315. int b=0,e=str->length;
  316. while( b<e && str->buf[b]<=' ' ) ++b;
  317. if( b==e ) return &bbEmptyString;
  318. while( str->buf[e-1]<=' ' ) --e;
  319. if( e-b==str->length ) return str;
  320. return bbStringFromShorts( str->buf+b,e-b );
  321. }
  322. BBString *bbStringReplace( BBString *str,BBString *sub,BBString *rep ){
  323. int i,d,n,j,p;
  324. if( !sub->length ) return str;
  325. i=0;n=0;
  326. while( (i=bbStringFind(str,sub,i))!=-1 ) {i+=sub->length;n++;}
  327. if (!n) return str;
  328. d=rep->length-sub->length;
  329. BBString *t=bbStringNew( str->length+d*n );
  330. i=0;p=0;
  331. while( (j=bbStringFind(str,sub,i))!=-1 )
  332. {
  333. n=j-i;if (n) {memcpy( t->buf+p,str->buf+i,n*sizeof(BBChar) );p+=n;}
  334. n=rep->length;memcpy( t->buf+p,rep->buf,n*sizeof(BBChar) );p+=n;
  335. i=j+sub->length;
  336. }
  337. n=str->length-i;
  338. if (n) memcpy( t->buf+p,str->buf+i,n*sizeof(BBChar) );
  339. return t;
  340. }
  341. int bbStringAsc( BBString *t ){
  342. return t->length ? t->buf[0] : -1;
  343. }
  344. int bbStringFind( BBString *x,BBString *y,int i ){
  345. if( i<0 ) i=0;
  346. while( i+y->length<=x->length ){
  347. if( charsEqual( x->buf+i,y->buf,y->length ) ) return i;
  348. ++i;
  349. }
  350. return -1;
  351. }
  352. int bbStringFindLast( BBString *x,BBString *y,int i ){
  353. bbassert( i>=0 );
  354. i=x->length-i;
  355. if (i+y->length>x->length) i=x->length-y->length;
  356. while (i>=0)
  357. {
  358. if( charsEqual( x->buf+i,y->buf,y->length ) ) return i;
  359. --i;
  360. }
  361. return -1;
  362. }
  363. int bbStringToInt( BBString *t ){
  364. int i=0,neg=0,n=0;
  365. while( i<t->length && isspace(t->buf[i]) ) ++i;
  366. if( i==t->length ) return 0;
  367. if( t->buf[i]=='+' ) ++i;
  368. else if( (neg=(t->buf[i]=='-')) ) ++i;
  369. if( i==t->length ) return 0;
  370. if( t->buf[i]=='%' ){
  371. for( ++i;i<t->length;++i ){
  372. int c=t->buf[i];
  373. if( c!='0' && c!='1' ) break;
  374. n=n*2+(c-'0');
  375. }
  376. }else if( t->buf[i]=='$' ){
  377. for( ++i;i<t->length;++i ){
  378. int c=toupper(t->buf[i]);
  379. if( !isxdigit(c) ) break;
  380. if( c>='A' ) c-=('A'-'0'-10);
  381. n=n*16+(c-'0');
  382. }
  383. }else{
  384. for( ;i<t->length;++i ){
  385. int c=t->buf[i];
  386. if( !isdigit(c) ) break;
  387. n=n*10+(c-'0');
  388. }
  389. }
  390. return neg ? -n : n;
  391. }
  392. unsigned int bbStringToUInt( BBString *t ){
  393. int i=0,neg=0;
  394. unsigned n=0;
  395. while( i<t->length && isspace(t->buf[i]) ) ++i;
  396. if( i==t->length ) return 0;
  397. if( t->buf[i]=='+' ) ++i;
  398. else if( (neg = t->buf[i]=='-') ) ++i;
  399. if( i==t->length ) return 0;
  400. if( t->buf[i]=='%' ){
  401. for( ++i;i<t->length;++i ){
  402. int c=t->buf[i];
  403. if( c!='0' && c!='1' ) break;
  404. n=n*2+(c-'0');
  405. }
  406. }else if( t->buf[i]=='$' ){
  407. for( ++i;i<t->length;++i ){
  408. int c=toupper(t->buf[i]);
  409. if( !isxdigit(c) ) break;
  410. if( c>='A' ) c-=('A'-'0'-10);
  411. n=n*16+(c-'0');
  412. }
  413. }else{
  414. for( ;i<t->length;++i ){
  415. int c=t->buf[i];
  416. if( !isdigit(c) ) break;
  417. n=n*10+(c-'0');
  418. }
  419. }
  420. return neg ? -n : n;
  421. }
  422. BBInt64 bbStringToLong( BBString *t ){
  423. int i=0,neg=0;
  424. BBInt64 n=0;
  425. while( i<t->length && isspace(t->buf[i]) ) ++i;
  426. if( i==t->length ){ return 0; }
  427. if( t->buf[i]=='+' ) ++i;
  428. else if( (neg=(t->buf[i]=='-')) ) ++i;
  429. if( i==t->length ){ return 0; }
  430. if( t->buf[i]=='%' ){
  431. for( ++i;i<t->length;++i ){
  432. int c=t->buf[i];
  433. if( c!='0' && c!='1' ) break;
  434. n=n*2+(c-'0');
  435. }
  436. }else if( t->buf[i]=='$' ){
  437. for( ++i;i<t->length;++i ){
  438. int c=toupper(t->buf[i]);
  439. if( !isxdigit(c) ) break;
  440. if( c>='A' ) c-=('A'-'0'-10);
  441. n=n*16+(c-'0');
  442. }
  443. }else{
  444. for( ;i<t->length;++i ){
  445. int c=t->buf[i];
  446. if( !isdigit(c) ) break;
  447. n=n*10+(c-'0');
  448. }
  449. }
  450. //*r=neg ? -n : n;
  451. return neg ? -n : n;
  452. }
  453. BBUInt64 bbStringToULong( BBString *t ){
  454. int i=0,neg=0;
  455. BBUInt64 n=0;
  456. while( i<t->length && isspace(t->buf[i]) ) ++i;
  457. if( i==t->length ){ return 0; }
  458. if( t->buf[i]=='+' ) ++i;
  459. else if( (neg = t->buf[i]=='-') ) ++i;
  460. if( i==t->length ){ return 0; }
  461. if( t->buf[i]=='%' ){
  462. for( ++i;i<t->length;++i ){
  463. int c=t->buf[i];
  464. if( c!='0' && c!='1' ) break;
  465. n=n*2+(c-'0');
  466. }
  467. }else if( t->buf[i]=='$' ){
  468. for( ++i;i<t->length;++i ){
  469. int c=toupper(t->buf[i]);
  470. if( !isxdigit(c) ) break;
  471. if( c>='A' ) c-=('A'-'0'-10);
  472. n=n*16+(c-'0');
  473. }
  474. }else{
  475. for( ;i<t->length;++i ){
  476. int c=t->buf[i];
  477. if( !isdigit(c) ) break;
  478. n=n*10+(c-'0');
  479. }
  480. }
  481. return neg ? -n : n;
  482. }
  483. BBSIZET bbStringToSizet( BBString *t ){
  484. int i=0,neg=0;
  485. BBSIZET n=0;
  486. while( i<t->length && isspace(t->buf[i]) ) ++i;
  487. if( i==t->length ){ return 0; }
  488. if( t->buf[i]=='+' ) ++i;
  489. else if( (neg=(t->buf[i]=='-')) ) ++i;
  490. if( i==t->length ){ return 0; }
  491. if( t->buf[i]=='%' ){
  492. for( ++i;i<t->length;++i ){
  493. int c=t->buf[i];
  494. if( c!='0' && c!='1' ) break;
  495. n=n*2+(c-'0');
  496. }
  497. }else if( t->buf[i]=='$' ){
  498. for( ++i;i<t->length;++i ){
  499. int c=toupper(t->buf[i]);
  500. if( !isxdigit(c) ) break;
  501. if( c>='A' ) c-=('A'-'0'-10);
  502. n=n*16+(c-'0');
  503. }
  504. }else{
  505. for( ;i<t->length;++i ){
  506. int c=t->buf[i];
  507. if( !isdigit(c) ) break;
  508. n=n*10+(c-'0');
  509. }
  510. }
  511. //*r=neg ? -n : n;
  512. return neg ? -n : n;
  513. }
  514. float bbStringToFloat( BBString *t ){
  515. char *p=(char*)bbStringToCString( t );
  516. float n=atof( p );
  517. bbMemFree( p );
  518. return n;
  519. }
  520. double bbStringToDouble( BBString *t ){
  521. char *p=(char*)bbStringToCString( t );
  522. double n=atof( p );
  523. bbMemFree( p );
  524. return n;
  525. }
  526. #ifdef _WIN32
  527. WPARAM bbStringToWParam( BBString *t ){
  528. int i=0,neg=0;
  529. WPARAM n=0;
  530. while( i<t->length && isspace(t->buf[i]) ) ++i;
  531. if( i==t->length ) return 0;
  532. if( t->buf[i]=='+' ) ++i;
  533. else if( (neg = t->buf[i]=='-') ) ++i;
  534. if( i==t->length ) return 0;
  535. if( t->buf[i]=='%' ){
  536. for( ++i;i<t->length;++i ){
  537. int c=t->buf[i];
  538. if( c!='0' && c!='1' ) break;
  539. n=n*2+(c-'0');
  540. }
  541. }else if( t->buf[i]=='$' ){
  542. for( ++i;i<t->length;++i ){
  543. int c=toupper(t->buf[i]);
  544. if( !isxdigit(c) ) break;
  545. if( c>='A' ) c-=('A'-'0'-10);
  546. n=n*16+(c-'0');
  547. }
  548. }else{
  549. for( ;i<t->length;++i ){
  550. int c=t->buf[i];
  551. if( !isdigit(c) ) break;
  552. n=n*10+(c-'0');
  553. }
  554. }
  555. return neg ? -n : n;
  556. }
  557. BBString *bbStringFromWParam( WPARAM n ){
  558. char buf[64];
  559. #ifdef __x86_64__
  560. sprintf(buf, "%llu", n);
  561. #else
  562. sprintf(buf, "%u", n);
  563. #endif
  564. return bbStringFromBytes( (unsigned char*)buf, strlen(buf) );
  565. }
  566. LPARAM bbStringToLParam( BBString *t ){
  567. int i=0,neg=0;
  568. LPARAM n=0;
  569. while( i<t->length && isspace(t->buf[i]) ) ++i;
  570. if( i==t->length ) return 0;
  571. if( t->buf[i]=='+' ) ++i;
  572. else if( (neg=(t->buf[i]=='-')) ) ++i;
  573. if( i==t->length ) return 0;
  574. if( t->buf[i]=='%' ){
  575. for( ++i;i<t->length;++i ){
  576. int c=t->buf[i];
  577. if( c!='0' && c!='1' ) break;
  578. n=n*2+(c-'0');
  579. }
  580. }else if( t->buf[i]=='$' ){
  581. for( ++i;i<t->length;++i ){
  582. int c=toupper(t->buf[i]);
  583. if( !isxdigit(c) ) break;
  584. if( c>='A' ) c-=('A'-'0'-10);
  585. n=n*16+(c-'0');
  586. }
  587. }else{
  588. for( ;i<t->length;++i ){
  589. int c=t->buf[i];
  590. if( !isdigit(c) ) break;
  591. n=n*10+(c-'0');
  592. }
  593. }
  594. return neg ? -n : n;
  595. }
  596. BBString *bbStringFromLParam( LPARAM n ){
  597. char buf[64];
  598. #ifdef __x86_64__
  599. sprintf(buf, "%lld", n);
  600. #else
  601. sprintf(buf, "%d", n);
  602. #endif
  603. return bbStringFromBytes( (unsigned char*)buf, strlen(buf) );
  604. }
  605. #endif
  606. BBString *bbStringToLower( BBString *str ){
  607. int k;
  608. BBString *t;
  609. int n = 0;
  610. while (n < str->length) {
  611. int c=str->buf[n];
  612. // ascii upper or other unicode char
  613. if (c >= 192 || (c>='A' && c<='Z')) {
  614. break;
  615. }
  616. ++n;
  617. }
  618. if (n == str->length) {
  619. return str;
  620. }
  621. t=bbStringNew( str->length );
  622. if (n > 0) {
  623. memcpy(t->buf, str->buf, n * sizeof(BBChar));
  624. }
  625. for( k=n;k<str->length;++k ){
  626. int c=str->buf[k];
  627. if( c<192 ){
  628. c=(c>='A' && c<='Z') ? (c|32) : c;
  629. }else{
  630. int lo=0,hi=3828/4-1; // sizeof(bbToLowerData)=3828
  631. while( lo<=hi ){
  632. int mid=(lo+hi)/2;
  633. if( c<bbToLowerData[mid*2] ){
  634. hi=mid-1;
  635. }else if( c>bbToLowerData[mid*2] ){
  636. lo=mid+1;
  637. }else{
  638. c=bbToLowerData[mid*2+1];
  639. break;
  640. }
  641. }
  642. }
  643. t->buf[k]=c;
  644. }
  645. return t;
  646. }
  647. BBString *bbStringToUpper( BBString *str ){
  648. int k;
  649. BBString *t;
  650. int n = 0;
  651. while (n < str->length) {
  652. int c=str->buf[n];
  653. // ascii lower or other unicode char
  654. if (c >= 181 || (c>='a' && c<='z')) {
  655. break;
  656. }
  657. ++n;
  658. }
  659. if (n == str->length) {
  660. return str;
  661. }
  662. t=bbStringNew( str->length );
  663. if (n > 0) {
  664. memcpy(t->buf, str->buf, n * sizeof(BBChar));
  665. }
  666. for( k=n;k<str->length;++k ){
  667. int c=str->buf[k];
  668. if( c<181 ){
  669. c=(c>='a' && c<='z') ? (c&~32) : c;
  670. }else{
  671. int lo=0,hi= 3860/4-1; // sizeof(bbToUpperData)= 3860
  672. while( lo<=hi ){
  673. int mid=(lo+hi)/2;
  674. if( c<bbToUpperData[mid*2] ){
  675. hi=mid-1;
  676. }else if( c>bbToUpperData[mid*2] ){
  677. lo=mid+1;
  678. }else{
  679. c=bbToUpperData[mid*2+1];
  680. break;
  681. }
  682. }
  683. }
  684. t->buf[k]=c;
  685. }
  686. return t;
  687. }
  688. unsigned char *bbStringToCString( BBString *str ){
  689. unsigned char *p;
  690. int k,sz=str->length;
  691. p=(unsigned char*)bbMemAlloc( sz+1 );
  692. for( k=0;k<sz;++k ) p[k]=str->buf[k];
  693. p[sz]=0;
  694. return p;
  695. }
  696. BBChar *bbStringToWString( BBString *str ){
  697. BBChar *p;
  698. int sz=str->length;
  699. p=(BBChar*)bbMemAlloc( (sz+1)*sizeof(BBChar) );
  700. memcpy(p,str->buf,sz*sizeof(BBChar));
  701. p[sz]=0;
  702. return p;
  703. }
  704. unsigned char *bbStringToUTF8String( BBString *str ){
  705. int len=str->length;
  706. size_t buflen = len * 4 + 1;
  707. unsigned char *buf=(unsigned char*)bbMemAlloc( buflen );
  708. return bbStringToUTF8StringBuffer(str, buf, &buflen);
  709. }
  710. unsigned char *bbStringToUTF8StringBuffer( BBString *str, unsigned char * buf, size_t * length ){
  711. int i=0,len=str->length;
  712. size_t buflen = *length;
  713. unsigned char *q=buf;
  714. unsigned short *p=str->buf;
  715. while (i < len) {
  716. unsigned int c=*p++;
  717. if(0xd800 <= c && c <= 0xdbff && i < len - 1) {
  718. /* surrogate pair */
  719. unsigned int c2 = *p;
  720. if(0xdc00 <= c2 && c2 <= 0xdfff) {
  721. /* valid second surrogate */
  722. c = ((c - 0xd800) << 10) + (c2 - 0xdc00) + 0x10000;
  723. ++p;
  724. ++i;
  725. }
  726. }
  727. int n = q - buf;
  728. if( c<0x80 ){
  729. if (buflen <= n+1) break;
  730. *q++=c;
  731. }else if( c<0x800 ){
  732. if (buflen <= n+2) break;
  733. *q++=0xc0|(c>>6);
  734. *q++=0x80|(c&0x3f);
  735. }else if(c < 0x10000) {
  736. if (buflen <= n+3) break;
  737. *q++=0xe0|(c>>12);
  738. *q++=0x80|((c>>6)&0x3f);
  739. *q++=0x80|(c&0x3f);
  740. }else if(c <= 0x10ffff) {
  741. if (buflen <= n+4) break;
  742. *q++ = 0xf0|(c>>18);
  743. *q++ = 0x80|((c>>12)&0x3f);
  744. *q++ = 0x80|((c>>6)&0x3f);
  745. *q++ = 0x80|((c&0x3f));
  746. }else{
  747. bbExThrowCString( "Unicode character out of UTF-8 range" );
  748. }
  749. ++i;
  750. }
  751. *q=0;
  752. *length = q - buf;
  753. return buf;
  754. }
  755. BBArray *bbStringSplit( BBString *str,BBString *sep ){
  756. int i,i2,n;
  757. BBString **p,*bit;
  758. BBArray *bits;
  759. if( sep->length ){
  760. i=0;n=1;
  761. while( (i2=bbStringFind( str,sep,i ))!=-1 ){
  762. ++n;
  763. i=i2+sep->length;
  764. }
  765. bits=bbArrayNew1D( "$",n );
  766. p=(BBString**)BBARRAYDATA( bits,1 );
  767. i=0;
  768. while( n-- ){
  769. i2=bbStringFind( str,sep,i );
  770. if( i2==-1 ) i2=str->length;
  771. bit=bbStringSlice( str,i,i2 );
  772. //BBINCREFS( bit );
  773. *p++=bit;
  774. i=i2+sep->length;
  775. }
  776. return bits;
  777. }
  778. i=0;n=0;
  779. for(;;){
  780. while( i!=str->length && str->buf[i]<33 ) ++i;
  781. if( i++==str->length ) break;
  782. while( i!=str->length && str->buf[i]>32 ) ++i;
  783. ++n;
  784. }
  785. if( !n ) return &bbEmptyArray;
  786. bits=bbArrayNew1D( "$",n );
  787. p=(BBString**)BBARRAYDATA( bits,1 );
  788. i=0;
  789. while( n-- ){
  790. while( str->buf[i]<33 ) ++i;
  791. i2=i++;
  792. while( i!=str->length && str->buf[i]>32 ) ++i;
  793. bit=bbStringSlice( str,i2,i );
  794. //BBINCREFS( bit );
  795. *p++=bit;
  796. }
  797. return bits;
  798. }
  799. BBString *bbStringJoin( BBString *sep,BBArray *bits ){
  800. int i,sz=0;
  801. int n_bits=bits->scales[0];
  802. BBString **p,*str;
  803. BBChar *t;
  804. if( bits==&bbEmptyArray ){
  805. return &bbEmptyString;
  806. }
  807. p=(BBString**)BBARRAYDATA( bits,1 );
  808. for( i=0;i<n_bits;++i ){
  809. BBString *bit=*p++;
  810. sz+=bit->length;
  811. }
  812. sz+=(n_bits-1)*sep->length;
  813. str=bbStringNew( sz );
  814. t=str->buf;
  815. p=(BBString**)BBARRAYDATA( bits,1 );
  816. for( i=0;i<n_bits;++i ){
  817. if( i ){
  818. memcpy( t,sep->buf,sep->length*sizeof(BBChar) );
  819. t+=sep->length;
  820. }
  821. BBString *bit=*p++;
  822. memcpy( t,bit->buf,bit->length*sizeof(BBChar) );
  823. t+=bit->length;
  824. }
  825. return str;
  826. }
  827. #ifndef __ANDROID__
  828. #ifndef __EMSCRIPTEN__
  829. static void mktmp( void *p ){
  830. static AO_t i;
  831. static void *bufs[32];
  832. int n=AO_fetch_and_add1( &i ) & 31;
  833. bbMemFree( bufs[n] );
  834. bufs[n]=p;
  835. }
  836. #else
  837. static void mktmp( void *p ){
  838. static int i;
  839. static void *bufs[32];
  840. int n=++i & 31;
  841. bbMemFree( bufs[n] );
  842. bufs[n]=p;
  843. }
  844. #endif
  845. #else
  846. static void mktmp( void *p ){
  847. static int i;
  848. static void *bufs[32];
  849. int n= __sync_fetch_and_add( &i, 1 ) & 31;
  850. bbMemFree( bufs[n] );
  851. bufs[n]=p;
  852. }
  853. #endif
  854. char *bbTmpCString( BBString *str ){
  855. printf("Use of bbTmpCString is deprecated\n");fflush(stdout);
  856. char *p=(char*)bbStringToCString( str );
  857. mktmp( p );
  858. return p;
  859. }
  860. BBChar *bbTmpWString( BBString *str ){
  861. printf("Use of bbTmpWString is deprecated\n");fflush(stdout);
  862. BBChar *p=bbStringToWString( str );
  863. mktmp( p );
  864. return p;
  865. }
  866. char *bbTmpUTF8String( BBString *str ){
  867. printf("Use of bbTmpUTF8String is deprecated\n");fflush(stdout);
  868. char *p=(char*)bbStringToUTF8String( str );
  869. mktmp( p );
  870. return p;
  871. }
  872. #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
  873. extern int bbStringEquals( BBString *x,BBString *y);
  874. extern int bbObjectIsEmptyString(BBObject * o);
  875. extern BBULONG bbStringHash( BBString * x );
  876. #else
  877. int bbStringEquals( BBString *x,BBString *y ){
  878. if (x->length-y->length != 0) return 0;
  879. if (x->hash != 0 && x->hash == y->hash) return 1;
  880. BBChar * bx = x->buf;
  881. BBChar * by = y->buf;
  882. int k = x->length;
  883. while( k-- ) if ( *bx++ - *by++ != 0 ) return 0;
  884. return 1;
  885. }
  886. int bbObjectIsEmptyString(BBObject * o) {
  887. return (BBString*)o == &bbEmptyString;
  888. }
  889. BBULONG bbStringHash( BBString * x ) {
  890. if (x->hash > 0) return x->hash;
  891. x->hash = XXH3_64bits(x->buf, x->length * sizeof(BBChar));
  892. return x->hash;
  893. }
  894. #endif
  895. BBUINT* bbStringToUTF32String( BBString *str ) {
  896. int len=str->length;
  897. int n = 0;
  898. size_t buflen = len * 4 + 4;
  899. BBUINT *buf=(BBUINT*)bbMemAlloc( buflen );
  900. BBChar *p=str->buf;
  901. BBUINT *bp = buf;
  902. while( *p ) {
  903. n++;
  904. BBChar c = *p++;
  905. if (!((c - 0xd800u) < 2048u)) {
  906. *bp++ = c;
  907. } else {
  908. if (((c & 0xfffffc00) == 0xd800) && n < len && ((*p & 0xfffffc00) == 0xdc00)) {
  909. *bp++ = (c << 10) + (*p++) - 0x35fdc00;
  910. } else {
  911. bbExThrowCString( "Failed to create UTF32. Invalid surrogate pair." );
  912. }
  913. }
  914. }
  915. *bp = 0;
  916. return buf;
  917. }
  918. BBString* bbStringFromUTF32String( const BBUINT *p ) {
  919. return p ? bbStringFromUTF32Bytes(p, utf32strlen(p)) : &bbEmptyString;
  920. }
  921. BBString* bbStringFromUTF32Bytes( const BBUINT *p, int n ) {
  922. if( !p || n <= 0 ) return &bbEmptyString;
  923. int len = n * 2;
  924. unsigned short * d=(unsigned short*)malloc( n * sizeof(BBChar) * 2 );
  925. unsigned short * q=d;
  926. BBUINT* bp = p;
  927. int i = 0;
  928. while (i++ < n) {
  929. BBUINT c = *bp++;
  930. if (c <= 0xffffu) {
  931. if (c >= 0xd800u && c <= 0xdfffu) {
  932. *q++ = 0xfffd;
  933. } else {
  934. *q++ = c;
  935. }
  936. } else if (c > 0x0010ffffu) {
  937. *q++ = 0xfffd;
  938. } else {
  939. c -= 0x0010000u;
  940. *q++ = (BBChar)((c >> 10) + 0xd800);
  941. *q++ = (BBChar)((c & 0x3ffu) + 0xdc00);
  942. }
  943. }
  944. BBString * str=bbStringFromShorts( d,q-d );
  945. free( d );
  946. return str;
  947. }