bbstring.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  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 &s ):_rep( s._rep ){
  52. retain();
  53. }
  54. bbString( const void *data );
  55. bbString( const void *data,int length );
  56. bbString( const bbChar *data ):_rep( Rep::create( data ) ){
  57. }
  58. bbString( const bbChar *data,int length ):_rep( Rep::create( data,length ) ){
  59. }
  60. bbString( const wchar_t *data ):_rep( Rep::create( data ) ){
  61. }
  62. bbString( const wchar_t *data,int length ):_rep( Rep::create( data,length ) ){
  63. }
  64. #if __OBJC__
  65. bbString( NSString *str ):_rep( Rep::create( str.UTF8String ) ){
  66. }
  67. #endif
  68. explicit bbString( int n ){
  69. char data[64];
  70. sprintf( data,"%d",n );
  71. _rep=Rep::create( data );
  72. }
  73. explicit bbString( unsigned int n ){
  74. char data[64];
  75. sprintf( data,"%u",n );
  76. _rep=Rep::create( data );
  77. }
  78. explicit bbString( long n ){
  79. char data[64];
  80. sprintf( data,"%ld",n );
  81. _rep=Rep::create( data );
  82. }
  83. explicit bbString( unsigned long n ){
  84. char data[64];
  85. sprintf( data,"%lu",n );
  86. _rep=Rep::create( data );
  87. }
  88. explicit bbString( long long n ){
  89. char data[64];
  90. sprintf( data,"%lld",n );
  91. _rep=Rep::create( data );
  92. }
  93. explicit bbString( unsigned long long n ){
  94. char data[64];
  95. sprintf( data,"%llu",n );
  96. _rep=Rep::create( data );
  97. }
  98. explicit bbString( float n ){
  99. char data[64];
  100. sprintf( data,"%.9g",n );
  101. _rep=Rep::create( data );
  102. }
  103. explicit bbString( double n ){
  104. char data[64];
  105. sprintf( data,"%.17g",n );
  106. _rep=Rep::create( data );
  107. }
  108. ~bbString(){
  109. release();
  110. }
  111. const bbChar *data()const{
  112. return _rep->data;
  113. }
  114. int length()const{
  115. return _rep->length;
  116. }
  117. bbChar operator[]( int index )const{
  118. bbDebugAssert( index>=0 && index<length(),"String character index out of range" );
  119. return data()[index];
  120. }
  121. bbString operator+()const{
  122. return *this;
  123. }
  124. bbString operator-()const{
  125. Rep *rep=Rep::alloc( length() );
  126. const bbChar *p=data()+length();
  127. for( int i=0;i<rep->length;++i ) rep->data[i]=*--p;
  128. return rep;
  129. }
  130. bbString operator+( const bbString &str ){
  131. if( !length() ) return str;
  132. if( !str.length() ) return *this;
  133. Rep *rep=Rep::alloc( length()+str.length() );
  134. t_memcpy( rep->data,data(),length() );
  135. t_memcpy( rep->data+length(),str.data(),str.length() );
  136. return rep;
  137. }
  138. bbString operator+( const char *str ){
  139. return operator+( bbString( str ) );
  140. }
  141. bbString operator*( int n ){
  142. Rep *rep=Rep::alloc( length()*n );
  143. bbChar *p=rep->data;
  144. for( int j=0;j<n;++j ){
  145. for( int i=0;i<_rep->length;++i ) *p++=data()[i];
  146. }
  147. return rep;
  148. }
  149. bbString &operator=( const bbString &str ){
  150. str.retain();
  151. release();
  152. _rep=str._rep;
  153. return *this;
  154. }
  155. template<class C> bbString &operator=( const C *data ){
  156. release();
  157. _rep=Rep::create( data );
  158. return *this;
  159. }
  160. bbString &operator+=( const bbString &str ){
  161. *this=*this+str;
  162. return *this;
  163. }
  164. bbString &operator+=( const char *str ){
  165. return operator+=( bbString( str ) );
  166. }
  167. int find( bbString str,int from=0 )const{
  168. if( from<0 ) from=0;
  169. for( int i=from;i<=length()-str.length();++i ){
  170. if( !t_memcmp( data()+i,str.data(),str.length() ) ) return i;
  171. }
  172. return -1;
  173. }
  174. int findLast( const bbString &str,int from=0 )const{
  175. if( from<0 ) from=0;
  176. for( int i=length()-str.length();i>=from;--i ){
  177. if( !t_memcmp( data()+i,str.data(),str.length() ) ) return i;
  178. }
  179. return -1;
  180. }
  181. bool contains( const bbString &str )const{
  182. return find( str )!=-1;
  183. }
  184. bbString slice( int from )const{
  185. int length=this->length();
  186. if( from<0 ){
  187. from+=length;
  188. if( from<0 ) from=0;
  189. }else if( from>length ){
  190. from=length;
  191. }
  192. if( !from ) return *this;
  193. return bbString( data()+from,length-from );
  194. }
  195. bbString slice( int from,int term )const{
  196. int length=this->length();
  197. if( from<0 ){
  198. from+=length;
  199. if( from<0 ) from=0;
  200. }else if( from>length ){
  201. from=length;
  202. }
  203. if( term<0 ){
  204. term+=length;
  205. if( term<from ) term=from;
  206. }else if( term<from ){
  207. term=from;
  208. }else if( term>length ){
  209. term=length;
  210. }
  211. if( !from && term==length ) return *this;
  212. return bbString( data()+from,term-from );
  213. }
  214. bbString left( int count )const{
  215. return slice( 0,count );
  216. }
  217. bbString right( int count )const{
  218. return slice( -count );
  219. }
  220. bbString mid( int from,int count )const{
  221. return slice( from,from+count );
  222. }
  223. bool startsWith( const bbString &str )const{
  224. if( str.length()>length() ) return false;
  225. return t_memcmp( data(),str.data(),str.length() )==0;
  226. }
  227. bool endsWith( const bbString &str )const{
  228. if( str.length()>length() ) return false;
  229. return t_memcmp( data()+(length()-str.length()),str.data(),str.length() )==0;
  230. }
  231. bbString toUpper()const{
  232. Rep *rep=Rep::alloc( length() );
  233. for( int i=0;i<length();++i ) rep->data[i]=std::toupper( data()[i] );
  234. return rep;
  235. }
  236. bbString toLower()const{
  237. Rep *rep=Rep::alloc( length() );
  238. for( int i=0;i<length();++i ) rep->data[i]=std::tolower( data()[i] );
  239. return rep;
  240. }
  241. bbString capitalize()const{
  242. if( !length() ) return &_nullRep;
  243. Rep *rep=Rep::alloc( length() );
  244. rep->data[0]=std::toupper( data()[0] );
  245. for( int i=1;i<length();++i ) rep->data[i]=data()[i];
  246. return rep;
  247. }
  248. bbString trim()const{
  249. const bbChar *beg=data();
  250. const bbChar *end=data()+length();
  251. while( beg!=end && *beg<=32 ) ++beg;
  252. while( beg!=end && *(end-1)<=32 ) --end;
  253. if( end-beg==length() ) return *this;
  254. return bbString( beg,end-beg );
  255. }
  256. bbString trimStart()const{
  257. const bbChar *beg=data();
  258. const bbChar *end=data()+length();
  259. while( beg!=end && *beg<=32 ) ++beg;
  260. if( end-beg==length() ) return *this;
  261. return bbString( beg,end-beg );
  262. }
  263. bbString trimEnd()const{
  264. const bbChar *beg=data();
  265. const bbChar *end=data()+length();
  266. while( beg!=end && *(end-1)<=32 ) --end;
  267. if( end-beg==length() ) return *this;
  268. return bbString( beg,end-beg );
  269. }
  270. bbString dup( int n )const{
  271. Rep *rep=Rep::alloc( length()*n );
  272. bbChar *p=rep->data;
  273. for( int j=0;j<n;++j ){
  274. for( int i=0;i<_rep->length;++i ) *p++=data()[i];
  275. }
  276. return rep;
  277. }
  278. bbString replace( const bbString &str,const bbString &repl )const{
  279. int n=0;
  280. for( int i=0;; ){
  281. i=find( str,i );
  282. if( i==-1 ) break;
  283. i+=str.length();
  284. ++n;
  285. }
  286. if( !n ) return *this;
  287. Rep *rep=Rep::alloc( length()+n*(repl.length()-str.length()) );
  288. bbChar *dst=rep->data;
  289. for( int i=0;; ){
  290. int i2=find( str,i );
  291. if( i2==-1 ){
  292. t_memcpy( dst,data()+i,(length()-i) );
  293. break;
  294. }
  295. t_memcpy( dst,data()+i,(i2-i) );
  296. dst+=(i2-i);
  297. t_memcpy( dst,repl.data(),repl.length() );
  298. dst+=repl.length();
  299. i=i2+str.length();
  300. }
  301. return rep;
  302. }
  303. bbArray<bbString> split( bbString sep )const;
  304. bbString join( bbArray<bbString> bits )const;
  305. int compare( const bbString &t )const{
  306. int len=length()<t.length() ? length() : t.length();
  307. for( int i=0;i<len;++i ){
  308. if( int n=data()[i]-t.data()[i] ) return n;
  309. }
  310. return length()-t.length();
  311. }
  312. bool operator<( const bbString &t )const{
  313. return compare( t )<0;
  314. }
  315. bool operator>( const bbString &t )const{
  316. return compare( t )>0;
  317. }
  318. bool operator<=( const bbString &t )const{
  319. return compare( t )<=0;
  320. }
  321. bool operator>=( const bbString &t )const{
  322. return compare( t )>=0;
  323. }
  324. bool operator==( const bbString &t )const{
  325. return compare( t )==0;
  326. }
  327. bool operator!=( const bbString &t )const{
  328. return compare( t )!=0;
  329. }
  330. operator bbBool()const{
  331. return length();
  332. }
  333. operator bbInt()const{
  334. return std::atoi( c_str() );
  335. }
  336. operator bbByte()const{
  337. return operator bbInt() & 0xff;
  338. }
  339. operator bbUByte()const{
  340. return operator bbInt() & 0xffu;
  341. }
  342. operator bbShort()const{
  343. return operator bbInt() & 0xffff;
  344. }
  345. operator bbUShort()const{
  346. return operator bbInt() & 0xffffu;
  347. }
  348. operator bbUInt()const{
  349. bbUInt n;
  350. sscanf( c_str(),"%u",&n );
  351. return n;
  352. }
  353. operator bbLong()const{
  354. bbLong n;
  355. sscanf( c_str(),"%lld",&n );
  356. return n;
  357. }
  358. operator bbULong()const{
  359. bbULong n;
  360. sscanf( c_str(),"%llu",&n );
  361. return n;
  362. }
  363. operator float()const{
  364. return std::atof( c_str() );
  365. }
  366. operator double()const{
  367. return std::atof( c_str() );
  368. }
  369. int utf8Length()const;
  370. void toCString( void *buf,int size )const;
  371. void toWString( void *buf,int size )const;
  372. #if __OBJC__
  373. NSString *ToNSString()const{
  374. return [NSString stringWithUTF8String:c_str()];
  375. }
  376. #endif
  377. static bbString fromChar( int chr );
  378. static bbString fromChars( bbArray<int> chrs );
  379. static bbString fromCString( const void *data ){ return bbString( data ); }
  380. static bbString fromCString( const void *data,int size ){ return bbString( data,size ); }
  381. static bbString fromWString( const void *data ){ return bbString( (const wchar_t*)data ); }
  382. static bbString fromWString( const void *data,int size ){ return bbString( (const wchar_t*)data,size ); }
  383. };
  384. class bbCString{
  385. char *_data;
  386. public:
  387. bbCString( const bbString &str ){
  388. int size=str.utf8Length()+1;
  389. _data=(char*)malloc( size );
  390. str.toCString( _data,size );
  391. }
  392. ~bbCString(){
  393. free( _data );
  394. }
  395. operator char*()const{
  396. return _data;
  397. }
  398. operator signed char*()const{
  399. return (signed char*)_data;
  400. }
  401. operator unsigned char*()const{
  402. return (unsigned char*)_data;
  403. }
  404. };
  405. class bbWString{
  406. wchar_t *_data;
  407. public:
  408. bbWString( const bbString &str ){
  409. int size=(str.length()+1)*sizeof(wchar_t);
  410. _data=(wchar_t*)malloc( size );
  411. str.toWString( _data,size );
  412. }
  413. ~bbWString(){
  414. free( _data );
  415. }
  416. operator wchar_t*()const{
  417. return _data;
  418. }
  419. };
  420. template<class C> bbString operator+( const C *str,const bbString &str2 ){
  421. return bbString::fromCString( str )+str2;
  422. }
  423. inline bbString BB_T( const char *p ){
  424. return bbString::fromCString( p );
  425. }
  426. #endif