bbstring.h 10 KB

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