bbstring.h 10 KB

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