bbstring.h 11 KB

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