blitz_string.c 25 KB

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