bbstring.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. #ifndef BB_STRING_H
  2. #define BB_STRING_H
  3. #include "bbtypes.h"
  4. #include "bbmemory.h"
  5. class bbCString;
  6. class bbString{
  7. struct Rep{
  8. int refs;
  9. int length;
  10. bbChar data[0];
  11. static Rep *alloc( int length ){
  12. if( !length ) return &_nullRep;
  13. Rep *rep=(Rep*)bbMalloc( sizeof(Rep)+length*sizeof(bbChar) );
  14. rep->refs=1;
  15. rep->length=length;
  16. return rep;
  17. }
  18. template<class C> static Rep *create( const C *p,int length ){
  19. Rep *rep=alloc( length );
  20. for( int i=0;i<length;++i ) rep->data[i]=p[i];
  21. return rep;
  22. }
  23. template<class C> static Rep *create( const C *p ){
  24. const C *e=p;
  25. while( *e ) ++e;
  26. return create( p,e-p );
  27. }
  28. };
  29. Rep *_rep;
  30. static Rep _nullRep;
  31. void retain()const{
  32. ++_rep->refs;
  33. }
  34. void release(){
  35. if( !--_rep->refs && _rep!=&_nullRep ) bbFree( _rep );
  36. }
  37. bbString( Rep *rep ):_rep( rep ){
  38. }
  39. template<class C> static int t_memcmp( const C *p1,const C *p2,int count ){
  40. return memcmp( p1,p2,count*sizeof(C) );
  41. }
  42. //returns END of dst!
  43. template<class C> static C *t_memcpy( C *dst,const C *src,int count ){
  44. return (C*)memcpy( dst,src,count*sizeof(C) )+count;
  45. }
  46. public:
  47. const char *c_str()const;
  48. bbString():_rep( &_nullRep ){
  49. }
  50. bbString( const bbString &str ):_rep( str._rep ){
  51. retain();
  52. }
  53. template<class C> bbString( const C *data ):_rep( Rep::create( data ) ){
  54. }
  55. template<class C> bbString( const C *data,int length ):_rep( Rep::create( data,length ) ){
  56. }
  57. bbString( bbInt n ){
  58. char data[64];
  59. sprintf( data,"%i",n );
  60. _rep=Rep::create( data );
  61. }
  62. bbString( bbUInt n ){
  63. char data[64];
  64. sprintf( data,"%u",n );
  65. _rep=Rep::create( data );
  66. }
  67. bbString( bbLong n ){
  68. char data[64];
  69. sprintf( data,"%lld",n );
  70. _rep=Rep::create( data );
  71. }
  72. bbString( bbULong n ){
  73. char data[64];
  74. sprintf( data,"%llu",n );
  75. _rep=Rep::create( data );
  76. }
  77. bbString( float n ){
  78. char data[64];
  79. sprintf( data,"%.9g",n );
  80. _rep=Rep::create( data );
  81. }
  82. bbString( double n ){
  83. char data[64];
  84. sprintf( data,"%.17g",n );
  85. _rep=Rep::create( data );
  86. }
  87. ~bbString(){
  88. release();
  89. }
  90. const bbChar *data()const{
  91. return _rep->data;
  92. }
  93. int length()const{
  94. return _rep->length;
  95. }
  96. bbChar operator[]( int index )const{
  97. return data()[index];
  98. }
  99. bbString operator+()const{
  100. return *this;
  101. }
  102. bbString operator-()const{
  103. Rep *rep=Rep::alloc( length() );
  104. const bbChar *p=data()+length();
  105. for( int i=0;i<rep->length;++i ) rep->data[i]=*--p;
  106. return rep;
  107. }
  108. bbString operator+( const bbString &str ){
  109. if( !length() ) return str;
  110. if( !str.length() ) return *this;
  111. Rep *rep=Rep::alloc( length()+str.length() );
  112. t_memcpy( rep->data,data(),length() );
  113. t_memcpy( rep->data+length(),str.data(),str.length() );
  114. return rep;
  115. }
  116. bbString operator+( const char *str ){
  117. return operator+( bbString( str ) );
  118. }
  119. bbString operator*( int n ){
  120. Rep *rep=Rep::alloc( length()*n );
  121. bbChar *p=rep->data;
  122. for( int j=0;j<n;++j ){
  123. for( int i=0;i<_rep->length;++i ) *p++=data()[i];
  124. }
  125. return rep;
  126. }
  127. bbString &operator=( const bbString &str ){
  128. str.retain();
  129. release();
  130. _rep=str._rep;
  131. return *this;
  132. }
  133. template<class C> bbString &operator=( const C *data ){
  134. release();
  135. _rep=Rep::create( data );
  136. return *this;
  137. }
  138. bbString &operator+=( const bbString &str ){
  139. *this=*this+str;
  140. return *this;
  141. }
  142. bbString &operator+=( const char *str ){
  143. return operator+=( bbString( str ) );
  144. }
  145. int find( bbString str,int from=0 )const{
  146. if( from<0 ) from=0;
  147. for( int i=from;i<=length()-str.length();++i ){
  148. if( !t_memcmp( data()+i,str.data(),str.length() ) ) return i;
  149. }
  150. return -1;
  151. }
  152. int findLast( const bbString &str,int from=0 )const{
  153. if( from<0 ) from=0;
  154. for( int i=length()-str.length();i>=from;--i ){
  155. if( !t_memcmp( data()+i,str.data(),str.length() ) ) return i;
  156. }
  157. return -1;
  158. }
  159. bool contains( const bbString &str )const{
  160. return find( str )!=-1;
  161. }
  162. bbString slice( int from )const{
  163. int length=this->length();
  164. if( from<0 ){
  165. from+=length;
  166. if( from<0 ) from=0;
  167. }else if( from>length ){
  168. from=length;
  169. }
  170. if( !from ) return *this;
  171. return bbString( data()+from,length-from );
  172. }
  173. bbString slice( int from,int term )const{
  174. int length=this->length();
  175. if( from<0 ){
  176. from+=length;
  177. if( from<0 ) from=0;
  178. }else if( from>length ){
  179. from=length;
  180. }
  181. if( term<0 ){
  182. term+=length;
  183. if( term<from ) term=from;
  184. }else if( term<from ){
  185. term=from;
  186. }else if( term>length ){
  187. term=length;
  188. }
  189. if( !from && term==length ) return *this;
  190. return bbString( data()+from,term-from );
  191. }
  192. bbString left( int count )const{
  193. return slice( 0,count );
  194. }
  195. bbString right( int count )const{
  196. return slice( -count );
  197. }
  198. bbString mid( int from,int count )const{
  199. return slice( from,from+count );
  200. }
  201. bool startsWith( const bbString &str )const{
  202. if( str.length()>length() ) return false;
  203. return t_memcmp( data(),str.data(),str.length() )==0;
  204. }
  205. bool endsWith( const bbString &str )const{
  206. if( str.length()>length() ) return false;
  207. return t_memcmp( data()+(length()-str.length()),str.data(),str.length() )==0;
  208. }
  209. bbString toUpper()const{
  210. Rep *rep=Rep::alloc( length() );
  211. for( int i=0;i<length();++i ) rep->data[i]=std::toupper( data()[i] );
  212. return rep;
  213. }
  214. bbString toLower()const{
  215. Rep *rep=Rep::alloc( length() );
  216. for( int i=0;i<length();++i ) rep->data[i]=std::tolower( data()[i] );
  217. return rep;
  218. }
  219. bbString capitalize()const{
  220. if( !length() ) return &_nullRep;
  221. Rep *rep=Rep::alloc( length() );
  222. rep->data[0]=std::toupper( data()[0] );
  223. for( int i=1;i<length();++i ) rep->data[i]=data()[i];
  224. return rep;
  225. }
  226. bbString trim()const{
  227. const bbChar *beg=data();
  228. const bbChar *end=data()+length();
  229. while( beg!=end && *beg<=32 ) ++beg;
  230. while( beg!=end && *(end-1)<=32 ) --end;
  231. if( end-beg==length() ) return *this;
  232. return bbString( beg,end-beg );
  233. }
  234. bbString trimStart()const{
  235. const bbChar *beg=data();
  236. const bbChar *end=data()+length();
  237. while( beg!=end && *beg<=32 ) ++beg;
  238. if( end-beg==length() ) return *this;
  239. return bbString( beg,end-beg );
  240. }
  241. bbString trimEnd()const{
  242. const bbChar *beg=data();
  243. const bbChar *end=data()+length();
  244. while( beg!=end && *(end-1)<=32 ) --end;
  245. if( end-beg==length() ) return *this;
  246. return bbString( beg,end-beg );
  247. }
  248. bbString dup( int n )const{
  249. Rep *rep=Rep::alloc( length()*n );
  250. bbChar *p=rep->data;
  251. for( int j=0;j<n;++j ){
  252. for( int i=0;i<_rep->length;++i ) *p++=data()[i];
  253. }
  254. return rep;
  255. }
  256. bbString replace( const bbString &str,const bbString &repl )const{
  257. int n=0;
  258. for( int i=0;; ){
  259. i=find( str,i );
  260. if( i==-1 ) break;
  261. i+=str.length();
  262. ++n;
  263. }
  264. if( !n ) return *this;
  265. Rep *rep=Rep::alloc( length()+n*(repl.length()-str.length()) );
  266. bbChar *dst=rep->data;
  267. for( int i=0;; ){
  268. int i2=find( str,i );
  269. if( i2==-1 ){
  270. t_memcpy( dst,data()+i,(length()-i) );
  271. break;
  272. }
  273. t_memcpy( dst,data()+i,(i2-i) );
  274. dst+=(i2-i);
  275. t_memcpy( dst,repl.data(),repl.length() );
  276. dst+=repl.length();
  277. i=i2+str.length();
  278. }
  279. return rep;
  280. }
  281. bbArray<bbString> *split( bbString sep )const;
  282. bbString join( bbArray<bbString> *bits )const;
  283. int compare( const bbString &t )const{
  284. int len=length()<t.length() ? length() : t.length();
  285. for( int i=0;i<len;++i ){
  286. if( int n=data()[i]-t.data()[i] ) return n;
  287. }
  288. return length()-t.length();
  289. }
  290. bool operator<( const bbString &t )const{
  291. return compare( t )<0;
  292. }
  293. bool operator>( const bbString &t )const{
  294. return compare( t )>0;
  295. }
  296. bool operator<=( const bbString &t )const{
  297. return compare( t )<=0;
  298. }
  299. bool operator>=( const bbString &t )const{
  300. return compare( t )>=0;
  301. }
  302. bool operator==( const bbString &t )const{
  303. return compare( t )==0;
  304. }
  305. bool operator!=( const bbString &t )const{
  306. return compare( t )!=0;
  307. }
  308. operator bbBool()const{
  309. return length();
  310. }
  311. operator bbInt()const{
  312. return std::atoi( c_str() );
  313. }
  314. operator bbByte()const{
  315. return operator bbInt() & 0xff;
  316. }
  317. operator bbUByte()const{
  318. return operator bbInt() & 0xffu;
  319. }
  320. operator bbShort()const{
  321. return operator bbInt() & 0xffff;
  322. }
  323. operator bbUShort()const{
  324. return operator bbInt() & 0xffffu;
  325. }
  326. operator bbUInt()const{
  327. bbUInt n;
  328. sscanf( c_str(),"%u",&n );
  329. return n;
  330. }
  331. operator bbLong()const{
  332. bbLong n;
  333. sscanf( c_str(),"%lld",&n );
  334. return n;
  335. }
  336. operator bbULong()const{
  337. bbULong n;
  338. sscanf( c_str(),"%llu",&n );
  339. return n;
  340. }
  341. operator float()const{
  342. return std::atof( c_str() );
  343. }
  344. operator double()const{
  345. return std::atof( c_str() );
  346. }
  347. int utf8Length()const;
  348. void toCString( void *buf,int size )const;
  349. void toWString( void *buf,int size )const;
  350. void toUtf8String( void *buf,int size )const;
  351. static bbString fromChar( int chr );
  352. static bbString fromCString( const void *data,int size=-1 );
  353. static bbString fromWString( const void *data,int size=-1 );
  354. static bbString fromUtf8String( const void *data,int size=-1 );
  355. static bbString fromTString( const void *data,int size=-1 ){
  356. #if _WIN32
  357. return fromCString( data,size );
  358. #else
  359. return fromUtf8String( data,size );
  360. #endif
  361. }
  362. };
  363. class bbCString{
  364. bbString _str;
  365. mutable char *_data=nullptr;
  366. public:
  367. bbCString( const bbString &str ):_str( str ){
  368. }
  369. bbCString( const bbCString &str ):_str( str._str ){
  370. }
  371. ~bbCString(){
  372. free( _data );
  373. }
  374. operator bbString()const{
  375. return _str;
  376. }
  377. bbCString &operator=( const bbCString &str ){
  378. free( _data );
  379. _data=nullptr;
  380. _str=str._str;
  381. return *this;
  382. }
  383. char *data()const{
  384. if( _data ) return _data;
  385. int size=_str.length()+1;
  386. _data=(char*)malloc( size );
  387. _str.toCString( _data,size );
  388. return _data;
  389. }
  390. operator char*()const{
  391. return data();
  392. }
  393. };
  394. class bbWString{
  395. bbString _str;
  396. mutable wchar_t *_data=nullptr;
  397. public:
  398. bbWString( const bbString &str ):_str( str ){
  399. }
  400. bbWString( const bbWString &str ):_str( str._str ){
  401. }
  402. ~bbWString(){
  403. free( _data );
  404. }
  405. operator bbString()const{
  406. return _str;
  407. }
  408. bbWString &operator=( const bbWString &str ){
  409. free( _data );
  410. _data=nullptr;
  411. _str=str._str;
  412. return *this;
  413. }
  414. wchar_t *data()const{
  415. if( _data ) return _data;
  416. int size=(_str.length()+1)*sizeof(wchar_t);
  417. _data=(wchar_t*)malloc( size );
  418. _str.toWString( _data,size );
  419. return _data;
  420. }
  421. operator wchar_t*()const{
  422. return data();
  423. }
  424. };
  425. class bbUtf8String{
  426. bbString _str;
  427. mutable unsigned char *_data=nullptr;
  428. public:
  429. bbUtf8String( const bbString &str ):_str( str ){
  430. }
  431. bbUtf8String( const bbUtf8String &str ):_str( str._str ){
  432. }
  433. ~bbUtf8String(){
  434. free( _data );
  435. }
  436. bbUtf8String &operator=( const bbUtf8String &str ){
  437. free( _data );
  438. _data=nullptr;
  439. _str=str._str;
  440. return *this;
  441. }
  442. operator bbString()const{
  443. return _str;
  444. }
  445. unsigned char *data()const{
  446. if( _data ) return _data;
  447. int size=_str.utf8Length()+1;
  448. _data=(unsigned char*)malloc( size );
  449. _str.toUtf8String( _data,size );
  450. return _data;
  451. }
  452. operator char*()const{
  453. return (char*)data();
  454. }
  455. operator unsigned char*()const{
  456. return data();
  457. }
  458. };
  459. #if _WIN32
  460. typedef bbCString bbTString;
  461. #else
  462. typedef bbUtf8String bbTString;
  463. #endif
  464. template<class C> bbString operator+( const C *str,const bbString &str2 ){
  465. return bbString( str )+str2;
  466. }
  467. template<class C> bbString BB_T( const C *p ){
  468. return bbString( p );
  469. }
  470. inline void bbGCMark( const bbString &t ){
  471. }
  472. #endif