bbstring.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. #include "bbstring.h"
  2. #include "bbarray.h"
  3. bbString::Rep bbString::_nullRep;
  4. namespace{
  5. int countUtf8Chars( const char *p,int sz ){
  6. const char *e=p+sz;
  7. int n=0;
  8. while( p!=e ){
  9. int c=*p++;
  10. if( c & 0x80 ){
  11. if( (c & 0xe0)==0xc0 ){
  12. if( p==e || (p[0] & 0xc0)!=0x80 ) return -1;
  13. p+=1;
  14. }else if( (c & 0xf0)==0xe0 ){
  15. if( p==e || p+1==e || (p[0] & 0xc0)!=0x80 || (p[1] & 0xc0)!=0x80 ) return -1;
  16. p+=2;
  17. }else{
  18. return -1;
  19. }
  20. }
  21. n+=1;
  22. }
  23. return n;
  24. }
  25. int countNullTerminatedUtf8Chars( const char *p,int sz ){
  26. const char *e=p+sz;
  27. int n=0;
  28. while( p!=e && *p ){
  29. int c=*p++;
  30. if( c & 0x80 ){
  31. if( (c & 0xe0)==0xc0 ){
  32. if( p==e || (p[0] & 0xc0)!=0x80 ) return -1;
  33. p+=1;
  34. }else if( (c & 0xf0)==0xe0 ){
  35. if( p==e || p+1==e || (p[0] & 0xc0)!=0x80 || (p[1] & 0xc0)!=0x80 ) return -1;
  36. p+=2;
  37. }else{
  38. return -1;
  39. }
  40. }
  41. n+=1;
  42. }
  43. return n;
  44. }
  45. void charsToUtf8( const bbChar *p,int n,char *dst,int size ){
  46. char *end=dst+size;
  47. const bbChar *e=p+n;
  48. while( p<e && dst<end ){
  49. bbChar c=*p++;
  50. if( c<0x80 ){
  51. *dst++=c;
  52. }else if( c<0x800 ){
  53. if( dst+2>end ) break;
  54. *dst++=0xc0 | (c>>6);
  55. *dst++=0x80 | (c & 0x3f);
  56. }else{
  57. if( dst+3>end ) break;
  58. *dst++=0xe0 | (c>>12);
  59. *dst++=0x80 | ((c>>6) & 0x3f);
  60. *dst++=0x80 | (c & 0x3f);
  61. }
  62. }
  63. if( dst<end ) *dst++=0;
  64. }
  65. void utf8ToChars( const char *p,bbChar *dst,int n ){
  66. while( n-- ){
  67. int c=*p++;
  68. if( c & 0x80 ){
  69. if( (c & 0xe0)==0xc0 ){
  70. c=((c & 0x1f)<<6) | (p[0] & 0x3f);
  71. p+=1;
  72. }else if( (c & 0xf0)==0xe0 ){
  73. c=((c & 0x0f)<<12) | ((p[0] & 0x3f)<<6) | (p[1] & 0x3f);
  74. p+=2;
  75. }
  76. }
  77. *dst++=c;
  78. }
  79. }
  80. }
  81. int bbString::utf8Length()const{
  82. const bbChar *p=data();
  83. const bbChar *e=p+length();
  84. int n=0;
  85. while( p<e ){
  86. bbChar c=*p++;
  87. if( c<0x80 ){
  88. n+=1;
  89. }else if( c<0x800 ){
  90. n+=2;
  91. }else{
  92. n+=3;
  93. }
  94. }
  95. return n;
  96. }
  97. bbString::bbString( const void *p ){
  98. const char *cp=(const char*)p;
  99. if( !cp ){
  100. _rep=&_nullRep;
  101. return;
  102. }
  103. int sz=strlen( cp );
  104. int n=countNullTerminatedUtf8Chars( cp,sz );
  105. if( n==-1 || n==sz ){
  106. _rep=Rep::create( cp,sz );
  107. return;
  108. }
  109. _rep=Rep::alloc( n );
  110. utf8ToChars( cp,_rep->data,n );
  111. }
  112. bbString::bbString( const void *p,int sz ){
  113. const char *cp=(const char*)p;
  114. if( !cp ){
  115. _rep=&_nullRep;
  116. return;
  117. }
  118. int n=countUtf8Chars( cp,sz );
  119. if( n==-1 || n==sz ){
  120. _rep=Rep::create( cp,sz );
  121. return;
  122. }
  123. _rep=Rep::alloc( n );
  124. utf8ToChars( cp,_rep->data,n );
  125. }
  126. void bbString::toCString( void *buf,int size )const{
  127. charsToUtf8( _rep->data,_rep->length,(char*)buf,size );
  128. }
  129. void bbString::toWString( void *buf,int size )const{
  130. size=size/sizeof(wchar_t);
  131. if( size<=0 ) return;
  132. int sz=length();
  133. if( sz>size ) sz=size;
  134. for( int i=0;i<sz;++i ) ((wchar_t*)buf)[i]=data()[i];
  135. if( sz<size ) ((wchar_t*)buf)[sz]=0;
  136. }
  137. const char *bbString::c_str()const{
  138. static int _sz;
  139. static char *_tmp;
  140. int sz=utf8Length()+1;
  141. if( sz>_sz ){
  142. free( _tmp );
  143. _tmp=(char*)malloc( _sz=sz );
  144. }
  145. toCString( _tmp,sz );
  146. return _tmp;
  147. }
  148. bbString bbString::fromChar( int chr ){
  149. wchar_t chrs[]={ wchar_t(chr) };
  150. return bbString( chrs,1 );
  151. }
  152. bbArray<bbString> bbString::split( bbString sep )const{
  153. if( !sep.length() ){
  154. bbArray<bbString> bits=bbArray<bbString>( length() );
  155. for( int i=0;i<length();++i ){
  156. bits[i]=bbString( &data()[i],1 );
  157. }
  158. return bits;
  159. }
  160. int i=0,i2,n=1;
  161. while( (i2=find( sep,i ))!=-1 ){
  162. ++n;
  163. i=i2+sep.length();
  164. }
  165. bbArray<bbString> bits=bbArray<bbString>( n );
  166. if( n==1 ){
  167. bits[0]=*this;
  168. return bits;
  169. }
  170. i=0;n=0;
  171. while( (i2=find( sep,i ))!=-1 ){
  172. bits[n++]=slice( i,i2 );
  173. i=i2+sep.length();
  174. }
  175. bits[n]=slice( i );
  176. return bits;
  177. }
  178. bbString bbString::join( bbArray<bbString> bits )const{
  179. if( bits.length()==0 ) return bbString();
  180. if( bits.length()==1 ) return bits[0];
  181. int len=length() * (bits.length()-1);
  182. for( int i=0;i<bits.length();++i ) len+=bits[i].length();
  183. Rep *rep=Rep::alloc( len );
  184. bbChar *p=rep->data;
  185. p=t_memcpy( p,bits[0].data(),bits[0].length() );
  186. for( int i=1;i<bits.length();++i ){
  187. p=t_memcpy( p,data(),length() );
  188. p=t_memcpy( p,bits[i].data(),bits[i].length() );
  189. }
  190. return rep;
  191. }