string.h

Go to the documentation of this file.
00001 #ifndef _PFC_STRING_H_
00002 #define _PFC_STRING_H_
00003 
00004 namespace pfc {
00005 
00006         class NOVTABLE string_receiver {
00007         public:
00008                 virtual void add_string(const char * p_string,t_size p_string_size = infinite) = 0;
00009 
00010                 void add_char(t_uint32 c);//adds unicode char to the string
00011                 void add_byte(char c) {add_string(&c,1);}
00012                 void add_chars(t_uint32 p_char,t_size p_count) {for(;p_count;p_count--) add_char(p_char);}
00013         protected:
00014                 string_receiver() {}
00015                 ~string_receiver() {}
00016         };
00017 
00018         t_size scan_filename(const char * ptr);
00019 
00020         bool is_path_separator(unsigned c);
00021         bool is_path_bad_char(unsigned c);
00022         bool is_valid_utf8(const char * param,t_size max = infinite);
00023         bool is_lower_ascii(const char * param);
00024         bool is_multiline(const char * p_string,t_size p_len = infinite);
00025         bool has_path_bad_chars(const char * param);
00026         void recover_invalid_utf8(const char * src,char * out,unsigned replace);//out must be enough to hold strlen(char) + 1, or appropiately bigger if replace needs multiple chars
00027         void convert_to_lower_ascii(const char * src,t_size max,char * out,char replace = '?');//out should be at least strlen(src)+1 long
00028 
00029         inline char ascii_tolower(char c) {if (c >= 'A' && c <= 'Z') c += 'a' - 'A'; return c;}
00030         inline char ascii_toupper(char c) {if (c >= 'a' && c <= 'z') c += 'A' - 'a'; return c;}
00031 
00032         t_size string_find_first(const char * p_string,char p_tofind,t_size p_start = 0);       //returns infinite if not found
00033         t_size string_find_last(const char * p_string,char p_tofind,t_size p_start = ~0);       //returns infinite if not found
00034         t_size string_find_first(const char * p_string,const char * p_tofind,t_size p_start = 0);       //returns infinite if not found
00035         t_size string_find_last(const char * p_string,const char * p_tofind,t_size p_start = ~0);       //returns infinite if not found
00036 
00037         t_size string_find_first_ex(const char * p_string,t_size p_string_length,char p_tofind,t_size p_start = 0);     //returns infinite if not found
00038         t_size string_find_last_ex(const char * p_string,t_size p_string_length,char p_tofind,t_size p_start = ~0);     //returns infinite if not found
00039         t_size string_find_first_ex(const char * p_string,t_size p_string_length,const char * p_tofind,t_size p_tofind_length,t_size p_start = 0);      //returns infinite if not found
00040         t_size string_find_last_ex(const char * p_string,t_size p_string_length,const char * p_tofind,t_size p_tofind_length,t_size p_start = ~0);      //returns infinite if not found
00041 
00042         
00043         template<typename t_char>
00044         t_size strlen_max_t(const t_char * ptr,t_size max) {
00045                 if (ptr == NULL) return 0;
00046                 t_size n = 0;
00047                 while(n<max && ptr[n] != 0) n++;
00048                 return n;
00049         }
00050 
00051         inline t_size strlen_max(const char * ptr,t_size max) throw() {return strlen_max_t(ptr,max);}
00052         inline t_size wcslen_max(const wchar_t * ptr,t_size max) throw() {return strlen_max_t(ptr,max);}
00053 
00054 #ifdef _WINDOWS
00055         inline t_size tcslen_max(const TCHAR * ptr,t_size max) {return strlen_max_t(ptr,max);}
00056 #endif
00057         
00058         bool string_is_numeric(const char * p_string,t_size p_length = infinite) throw();
00059         inline bool char_is_numeric(char p_char) throw() {return p_char >= '0' && p_char <= '9';}
00060         inline bool char_is_ascii_alpha_upper(char p_char) throw() {return p_char >= 'A' && p_char <= 'Z';}
00061         inline bool char_is_ascii_alpha_lower(char p_char) throw() {return p_char >= 'a' && p_char <= 'z';}
00062         inline bool char_is_ascii_alpha(char p_char) throw() {return char_is_ascii_alpha_lower(p_char) || char_is_ascii_alpha_upper(p_char);}
00063         inline bool char_is_ascii_alphanumeric(char p_char) throw() {return char_is_ascii_alpha(p_char) || char_is_numeric(p_char);}
00064         
00065         unsigned atoui_ex(const char * ptr,t_size max);
00066         t_int64 atoi64_ex(const char * ptr,t_size max);
00067         t_uint64 atoui64_ex(const char * ptr,t_size max);
00068 
00069         t_size strlen_utf8(const char * s,t_size num = ~0) throw();//returns number of characters in utf8 string; num - no. of bytes (optional)
00070         t_size utf8_char_len(const char * s,t_size max = ~0) throw();//returns size of utf8 character pointed by s, in bytes, 0 on error
00071         t_size utf8_char_len_from_header(char c) throw();
00072         t_size utf8_chars_to_bytes(const char * string,t_size count) throw();
00073 
00074         t_size strcpy_utf8_truncate(const char * src,char * out,t_size maxbytes);
00075 
00076         t_size utf8_decode_char(const char * src,unsigned & out,t_size src_bytes) throw();//returns length in bytes
00077         t_size utf8_decode_char(const char * src,unsigned & out) throw();//returns length in bytes
00078 
00079         t_size utf8_encode_char(unsigned c,char * out) throw();//returns used length in bytes, max 6
00080         t_size utf16_decode_char(const wchar_t * p_source,unsigned * p_out,t_size p_source_length = ~0) throw();
00081         t_size utf16_encode_char(unsigned c,wchar_t * out) throw();
00082 
00083 
00084         t_size strstr_ex(const char * p_string,t_size p_string_len,const char * p_substring,t_size p_substring_len) throw();
00085 
00086 
00087         t_size skip_utf8_chars(const char * ptr,t_size count) throw();
00088         char * strdup_n(const char * src,t_size len);
00089         int stricmp_ascii(const char * s1,const char * s2) throw();
00090         int stricmp_ascii_ex(const char * s1,t_size len1,const char * s2,t_size len2) throw();
00091 
00092         int strcmp_ex(const char* p1,t_size n1,const char* p2,t_size n2) throw();
00093 
00094         unsigned utf8_get_char(const char * src);
00095 
00096         inline bool utf8_advance(const char * & var) throw() {
00097                 t_size delta = utf8_char_len(var);
00098                 var += delta;
00099                 return delta>0;
00100         }
00101 
00102         inline bool utf8_advance(char * & var) throw() {
00103                 t_size delta = utf8_char_len(var);
00104                 var += delta;
00105                 return delta>0;
00106         }
00107 
00108         inline const char * utf8_char_next(const char * src) throw() {return src + utf8_char_len(src);}
00109         inline char * utf8_char_next(char * src) throw() {return src + utf8_char_len(src);}
00110 
00111         class NOVTABLE string_base : public pfc::string_receiver {
00112         public:
00113                 virtual const char * get_ptr() const = 0;
00114                 virtual void add_string(const char * p_string,t_size p_length = ~0) = 0;//same as string_receiver method
00115                 virtual void set_string(const char * p_string,t_size p_length = ~0) {reset();add_string(p_string,p_length);}
00116                 virtual void truncate(t_size len)=0;
00117                 virtual t_size get_length() const {return strlen(get_ptr());}
00118                 virtual char * lock_buffer(t_size p_requested_length) = 0;
00119                 virtual void unlock_buffer() = 0;
00120 
00121                 inline const char * toString() const {return get_ptr();}
00122 
00124                 inline t_size length() const {return get_length();}
00125                 
00126                 inline void reset() {truncate(0);}
00127                 
00128                 inline bool is_empty() const {return *get_ptr()==0;}
00129                 
00130                 void skip_trailing_char(unsigned c = ' ');
00131 
00132                 bool is_valid_utf8() const {return pfc::is_valid_utf8(get_ptr());}
00133 
00134                 void convert_to_lower_ascii(const char * src,char replace = '?');
00135 
00136                 inline const string_base & operator= (const char * src) {set_string(src);return *this;}
00137                 inline const string_base & operator+= (const char * src) {add_string(src);return *this;}
00138                 inline const string_base & operator= (const string_base & src) {set_string(src);return *this;}
00139                 inline const string_base & operator+= (const string_base & src) {add_string(src);return *this;}
00140 
00141                 bool operator==(const string_base & p_other) const {return strcmp(*this,p_other) == 0;}
00142                 bool operator!=(const string_base & p_other) const {return strcmp(*this,p_other) != 0;}
00143                 bool operator>(const string_base & p_other) const {return strcmp(*this,p_other) > 0;}
00144                 bool operator<(const string_base & p_other) const {return strcmp(*this,p_other) < 0;}
00145                 bool operator>=(const string_base & p_other) const {return strcmp(*this,p_other) >= 0;}
00146                 bool operator<=(const string_base & p_other) const {return strcmp(*this,p_other) <= 0;}
00147 
00148                 inline operator const char * () const {return get_ptr();}
00149 
00150                 t_size scan_filename() const {return pfc::scan_filename(get_ptr());}
00151 
00152                 t_size find_first(char p_char,t_size p_start = 0) const {return pfc::string_find_first(get_ptr(),p_char,p_start);}
00153                 t_size find_last(char p_char,t_size p_start = ~0) const {return pfc::string_find_last(get_ptr(),p_char,p_start);}
00154                 t_size find_first(const char * p_string,t_size p_start = 0) const {return pfc::string_find_first(get_ptr(),p_string,p_start);}
00155                 t_size find_last(const char * p_string,t_size p_start = ~0) const {return pfc::string_find_last(get_ptr(),p_string,p_start);}
00156 
00157                 void fix_dir_separator(char p_char);
00158         protected:
00159                 string_base() {}
00160                 ~string_base() {}
00161         };
00162 
00163         template<t_size max_length>
00164         class string_fixed_t : public pfc::string_base {
00165         public:
00166                 inline string_fixed_t() {init();}
00167                 inline string_fixed_t(const string_fixed_t<max_length> & p_source) {init(); *this = p_source;}
00168                 inline string_fixed_t(const char * p_source) {init(); set_string(p_source);}
00169                 
00170                 inline const string_fixed_t<max_length> & operator=(const string_fixed_t<max_length> & p_source) {set_string(p_source);return *this;}
00171                 inline const string_fixed_t<max_length> & operator=(const char * p_source) {set_string(p_source);return *this;}
00172 
00173                 char * lock_buffer(t_size p_requested_length) {
00174                         if (p_requested_length >= max_length) return NULL;
00175                         memset(m_data,0,sizeof(m_data));
00176                         return m_data;
00177                 }
00178                 void unlock_buffer() {
00179                         m_length = strlen(m_data);
00180                 }
00181 
00182                 inline operator const char * () const {return m_data;}
00183                 
00184                 const char * get_ptr() const {return m_data;}
00185 
00186                 void add_string(const char * ptr,t_size len) {
00187                         len = strlen_max(ptr,len);
00188                         if (m_length + len < m_length || m_length + len > max_length) throw pfc::exception_overflow();
00189                         for(t_size n=0;n<len;n++) {
00190                                 m_data[m_length++] = ptr[n];
00191                         }
00192                         m_data[m_length] = 0;
00193                 }
00194                 void truncate(t_size len) {
00195                         if (len > max_length) len = max_length;
00196                         if (m_length > len) {
00197                                 m_length = len;
00198                                 m_data[len] = 0;
00199                         }
00200                 }
00201                 t_size get_length() const {return m_length;}
00202         private:
00203                 inline void init() {
00204                         pfc::static_assert<(max_length>1)>();
00205                         m_length = 0; m_data[0] = 0;
00206                 }
00207                 t_size m_length;
00208                 char m_data[max_length+1];
00209         };
00210 
00211         template<template<typename> class t_alloc>
00212         class string8_t : public pfc::string_base {
00213         private:
00214                 typedef string8_t<t_alloc> t_self;
00215         protected:
00216                 pfc::array_t<char,t_alloc> m_data;
00217                 t_size used;
00218 
00219                 inline void makespace(t_size s) {
00220                         if (t_alloc<char>::alloc_prioritizes_speed) {
00221                                 m_data.set_size(s);
00222                         } else {
00223                                 const t_size old_size = m_data.get_size();
00224                                 if (old_size < s)
00225                                         m_data.set_size(s + 16);
00226                                 else if (old_size > s + 32)
00227                                         m_data.set_size(s);
00228                         }
00229                 }
00230 
00231                 inline const char * _get_ptr() const throw() {return used > 0 ? m_data.get_ptr() : "";}
00232 
00233         public:
00234                 inline const t_self & operator= (const char * src) {set_string(src);return *this;}
00235                 inline const t_self & operator+= (const char * src) {add_string(src);return *this;}
00236                 inline const t_self & operator= (const string_base & src) {set_string(src);return *this;}
00237                 inline const t_self & operator+= (const string_base & src) {add_string(src);return *this;}
00238                 inline const t_self & operator= (const t_self & src) {set_string(src);return *this;}
00239                 inline const t_self & operator+= (const t_self & src) {add_string(src);return *this;}
00240 
00241                 inline operator const char * () const throw() {return _get_ptr();}
00242 
00243                 string8_t() : used(0) {}
00244                 string8_t(const char * p_string) : used(0) {set_string(p_string);}
00245                 string8_t(const char * p_string,t_size p_length) : used(0) {set_string(p_string,p_length);}
00246                 string8_t(const t_self & p_string) : used(0) {set_string(p_string);}
00247                 string8_t(const string_base & p_string) : used(0) {set_string(p_string);}
00248 
00249                 void prealloc(t_size p_size) {m_data.prealloc(p_size+1);}
00250 
00251                 const char * get_ptr() const throw() {return _get_ptr();}
00252 
00253                 void add_string(const char * p_string,t_size p_length = ~0);
00254                 void set_string(const char * p_string,t_size p_length = ~0);
00255 
00256                 void truncate(t_size len)
00257                 {
00258                         if (used>len) {used=len;m_data[len]=0;makespace(used+1);}
00259                 }
00260 
00261                 t_size get_length() const throw() {return used;}
00262 
00263 
00264                 void set_char(unsigned offset,char c);
00265 
00266                 t_size replace_nontext_chars(char p_replace = '_');
00267                 t_size replace_char(unsigned c1,unsigned c2,t_size start = 0);
00268                 t_size replace_byte(char c1,char c2,t_size start = 0);
00269                 void fix_filename_chars(char def = '_',char leave=0);//replace "bad" characters, leave parameter can be used to keep eg. path separators
00270                 void remove_chars(t_size first,t_size count); //slow
00271                 void insert_chars(t_size first,const char * src, t_size count);//slow
00272                 void insert_chars(t_size first,const char * src);
00273                 bool truncate_eol(t_size start = 0);
00274                 bool fix_eol(const char * append = " (...)",t_size start = 0);
00275                 bool limit_length(t_size length_in_chars,const char * append = " (...)");
00276 
00277                 //for string_buffer class
00278                 char * lock_buffer(t_size n)
00279                 {
00280                         if (n + 1 == 0) throw exception_overflow();
00281                         makespace(n+1);
00282                         pfc::memset_t(m_data,(char)0);
00283                         return m_data.get_ptr();;
00284                 }
00285 
00286                 void unlock_buffer() {
00287                         used=strlen(m_data.get_ptr());
00288                         makespace(used+1);
00289                 }
00290 
00291                 void force_reset() {used=0;m_data.force_reset();}
00292 
00293                 inline static void g_swap(t_self & p_item1,t_self & p_item2) {
00294                         pfc::swap_t(p_item1.m_data,p_item2.m_data);
00295                         pfc::swap_t(p_item1.used,p_item2.used);
00296                 }
00297         };
00298 
00299         typedef string8_t<pfc::alloc_standard> string8;
00300         typedef string8_t<pfc::alloc_fast> string8_fast;
00301         typedef string8_t<pfc::alloc_fast_aggressive> string8_fast_aggressive;
00302         //for backwards compatibility
00303         typedef string8_t<pfc::alloc_fast_aggressive> string8_fastalloc;
00304 
00305 
00306         template<template<typename> class t_alloc> class traits_t<string8_t<t_alloc> > : public pfc::combine_traits<pfc::traits_vtable,pfc::traits_t<pfc::array_t<char,t_alloc> > > {
00307         public:
00308                 enum {
00309                         needs_constructor = true,
00310                 };
00311         };
00312 }
00313 
00314 
00315 
00316 #include "string8_impl.h"
00317 
00318 #define PFC_DEPRECATE_PRINTF PFC_DEPRECATE("Use string8/string_fixed_t with operator<< overloads instead.")
00319 
00320 namespace pfc {
00321 
00322         class string_buffer {
00323         private:
00324                 string_base & m_owner;
00325                 char * m_buffer;
00326         public:
00327                 explicit string_buffer(string_base & p_string,t_size p_requeted_length) : m_owner(p_string) {m_buffer = m_owner.lock_buffer(p_requeted_length);}
00328                 ~string_buffer() {m_owner.unlock_buffer();}
00329                 operator char* () {return m_buffer;}
00330         };
00331 
00332         class PFC_DEPRECATE_PRINTF string_printf : public string8_fastalloc {
00333         public:
00334                 static void g_run(string_base & out,const char * fmt,va_list list);
00335                 void run(const char * fmt,va_list list);
00336 
00337                 explicit string_printf(const char * fmt,...);
00338         };
00339 
00340         class PFC_DEPRECATE_PRINTF string_printf_va : public string8_fastalloc {
00341         public:
00342                 string_printf_va(const char * fmt,va_list list);
00343         };
00344 
00345         class format_time {
00346         public:
00347                 format_time(t_uint64 p_seconds);
00348                 const char * get_ptr() const {return m_buffer;}
00349                 operator const char * () const {return m_buffer;}
00350         protected:
00351                 string_fixed_t<127> m_buffer;
00352         };
00353 
00354 
00355         class format_time_ex {
00356         public:
00357                 format_time_ex(double p_seconds,unsigned p_extra = 3);
00358                 const char * get_ptr() const {return m_buffer;}
00359                 operator const char * () const {return m_buffer;}
00360         private:
00361                 string_fixed_t<127> m_buffer;
00362         };
00363 
00364 
00365 
00366 
00367         class string_filename : public string8 {
00368         public:
00369                 explicit string_filename(const char * fn);
00370         };
00371 
00372         class string_filename_ext : public string8 {
00373         public:
00374                 explicit string_filename_ext(const char * fn);
00375         };
00376 
00377         class string_extension
00378         {
00379                 char buffer[32];
00380         public:
00381                 inline const char * get_ptr() const {return buffer;}
00382                 inline t_size length() const {return strlen(buffer);}
00383                 inline operator const char * () const {return buffer;}
00384                 inline const char * toString() const {return buffer;}
00385                 explicit string_extension(const char * src);
00386         };
00387 
00388 
00389         class string_replace_extension
00390         {
00391         public:
00392                 string_replace_extension(const char * p_path,const char * p_ext);
00393                 inline operator const char*() const {return m_data;}
00394         private:
00395                 string8 m_data;
00396         };
00397 
00398         class string_directory
00399         {
00400         public:
00401                 string_directory(const char * p_path);
00402                 inline operator const char*() const {return m_data;}
00403         private:
00404                 string8 m_data;
00405         };
00406 
00407         void float_to_string(char * out,t_size out_max,double val,unsigned precision,bool force_sign = false);//doesnt add E+X etc, has internal range limits, useful for storing float numbers as strings without having to bother with international coma/dot settings BS
00408         double string_to_float(const char * src,t_size len = infinite);
00409 
00410         template<>
00411         inline void swap_t(string8 & p_item1,string8 & p_item2)
00412         {
00413                 string8::g_swap(p_item1,p_item2);
00414         }
00415 
00416         class format_float
00417         {
00418         public:
00419                 format_float(double p_val,unsigned p_width = 0,unsigned p_prec = 7);
00420                 format_float(const format_float & p_source) {*this = p_source;}
00421 
00422                 inline const char * get_ptr() const {return m_buffer.get_ptr();}
00423                 inline const char * toString() const {return m_buffer.get_ptr();}
00424                 inline operator const char*() const {return m_buffer.get_ptr();}
00425         private:
00426                 string8 m_buffer;
00427         };
00428 
00429         class format_int
00430         {
00431         public:
00432                 format_int(t_int64 p_val,unsigned p_width = 0,unsigned p_base = 10);
00433                 format_int(const format_int & p_source) {*this = p_source;}
00434                 inline const char * get_ptr() const {return m_buffer;}
00435                 inline const char * toString() const {return m_buffer;}
00436                 inline operator const char*() const {return m_buffer;}
00437         private:
00438                 char m_buffer[64];
00439         };
00440 
00441 
00442         class format_uint {
00443         public:
00444                 format_uint(t_uint64 p_val,unsigned p_width = 0,unsigned p_base = 10);
00445                 format_uint(const format_uint & p_source) {*this = p_source;}
00446                 inline const char * get_ptr() const {return m_buffer;}
00447                 inline const char * toString() const {return m_buffer;}
00448                 inline operator const char*() const {return m_buffer;}
00449         private:
00450                 char m_buffer[64];
00451         };
00452 
00453         class format_hex
00454         {
00455         public:
00456                 format_hex(t_uint64 p_val,unsigned p_width = 0);
00457                 format_hex(const format_hex & p_source) {*this = p_source;}
00458                 inline const char * get_ptr() const {return m_buffer;}
00459                 inline const char * toString() const {return m_buffer;}
00460                 inline operator const char*() const {return m_buffer;}
00461         private:
00462                 char m_buffer[17];
00463         };
00464 
00465         class format_hex_lowercase
00466         {
00467         public:
00468                 format_hex_lowercase(t_uint64 p_val,unsigned p_width = 0);
00469                 format_hex_lowercase(const format_hex_lowercase & p_source) {*this = p_source;}
00470                 inline const char * get_ptr() const {return m_buffer;}
00471                 inline operator const char*() const {return m_buffer;}
00472                 inline const char * toString() const {return m_buffer;}
00473         private:
00474                 char m_buffer[17];
00475         };
00476 
00477 
00478         typedef string8_fastalloc string_formatter;
00479 
00480         class format_hexdump_ex {
00481         public:
00482                 template<typename TWord> format_hexdump_ex(const TWord * buffer, t_size bufLen, const char * spacing = " ") {
00483                         for(t_size n = 0; n < bufLen; n++) {
00484                                 if (n > 0 && spacing != NULL) m_formatter << spacing;
00485                                 m_formatter << format_hex(buffer[n],sizeof(TWord) * 2);
00486                         }
00487                 }
00488                 inline const char * get_ptr() const {return m_formatter;}
00489                 inline operator const char * () const {return m_formatter;}
00490                 inline const char * toString() const {return m_formatter;}
00491         private:
00492                 string_formatter m_formatter;
00493         };
00494 
00495         class format_hexdump
00496         {
00497         public:
00498                 format_hexdump(const void * p_buffer,t_size p_bytes,const char * p_spacing = " ");
00499 
00500                 inline const char * get_ptr() const {return m_formatter;}
00501                 inline operator const char * () const {return m_formatter;}
00502                 inline const char * toString() const {return m_formatter;}
00503         private:
00504                 string_formatter m_formatter;
00505         };
00506 
00507         class format_hexdump_lowercase
00508         {
00509         public:
00510                 format_hexdump_lowercase(const void * p_buffer,t_size p_bytes,const char * p_spacing = " ");
00511 
00512                 inline const char * get_ptr() const {return m_formatter;}
00513                 inline operator const char * () const {return m_formatter;}
00514                 inline const char * toString() const {return m_formatter;}
00515 
00516         private:
00517                 string_formatter m_formatter;
00518         };
00519 
00520         class format_fixedpoint
00521         {
00522         public:
00523                 format_fixedpoint(t_int64 p_val,unsigned p_point);
00524                 inline const char * get_ptr() const {return m_buffer;}
00525                 inline operator const char*() const {return m_buffer;}
00526                 inline const char * toString() const {return m_buffer;}
00527         private:
00528                 string_formatter m_buffer;
00529         };
00530 
00531         class format_char {
00532         public:
00533                 format_char(char p_char) {m_buffer[0] = p_char; m_buffer[1] = 0;}
00534                 inline const char * get_ptr() const {return m_buffer;}
00535                 inline operator const char*() const {return m_buffer;}
00536                 inline const char * toString() const {return m_buffer;}
00537         private:
00538                 char m_buffer[2];
00539         };
00540 
00541         template<typename t_stringbuffer = pfc::string8_fastalloc>
00542         class format_pad_left {
00543         public:
00544                 format_pad_left(t_size p_chars,t_uint32 p_padding /* = ' ' */,const char * p_string,t_size p_string_length = infinite) {
00545                         t_size source_len = 0, source_walk = 0;
00546                         
00547                         while(source_walk < p_string_length && source_len < p_chars) {
00548                                 unsigned dummy;
00549                                 t_size delta = pfc::utf8_decode_char(p_string + source_walk, dummy, p_string_length - source_walk);
00550                                 if (delta == 0) break;
00551                                 source_len++;
00552                                 source_walk += delta;
00553                         }
00554 
00555                         m_buffer.add_string(p_string,source_walk);
00556                         m_buffer.add_chars(p_padding,p_chars - source_len);
00557                 }
00558                 inline const char * get_ptr() const {return m_buffer;}
00559                 inline operator const char*() const {return m_buffer;}
00560                 inline const char * toString() const {return m_buffer;}
00561         private:
00562                 t_stringbuffer m_buffer;
00563         };
00564 
00565         template<typename t_stringbuffer = pfc::string8_fastalloc>
00566         class format_pad_right {
00567         public:
00568                 format_pad_right(t_size p_chars,t_uint32 p_padding /* = ' ' */,const char * p_string,t_size p_string_length = infinite) {
00569                         t_size source_len = 0, source_walk = 0;
00570                         
00571                         while(source_walk < p_string_length && source_len < p_chars) {
00572                                 unsigned dummy;
00573                                 t_size delta = pfc::utf8_decode_char(p_string + source_walk, dummy, p_string_length - source_walk);
00574                                 if (delta == 0) break;
00575                                 source_len++;
00576                                 source_walk += delta;
00577                         }
00578 
00579                         m_buffer.add_chars(p_padding,p_chars - source_len);
00580                         m_buffer.add_string(p_string,source_walk);
00581                 }
00582                 inline const char * get_ptr() const {return m_buffer;}
00583                 inline operator const char*() const {return m_buffer;}
00584                 inline const char * toString() const {return m_buffer;}
00585         private:
00586                 t_stringbuffer m_buffer;
00587         };
00588 
00589         class format_array : public string_formatter {
00590         public:
00591                 template<typename t_source> format_array(t_source const & source, const char * separator = ", ") {
00592                         const t_size count = array_size_t(source);
00593                         if (count > 0) {
00594                                 *this << source[0];
00595                                 for(t_size walk = 1; walk < count; ++walk) *this << separator << source[walk];
00596                         }
00597                 }
00598         };
00599 
00600 
00601         class format_file_size_short : public string_formatter {
00602         public:
00603                 format_file_size_short(t_uint64 size);
00604                 t_uint64 get_used_scale() const {return m_scale;}
00605         private:
00606                 t_uint64 m_scale;
00607         };
00608 
00609 }
00610 
00611 inline pfc::string_base & operator<<(pfc::string_base & p_fmt,const char * p_source) {p_fmt.add_string(p_source); return p_fmt;}
00612 inline pfc::string_base & operator<<(pfc::string_base & p_fmt,t_int32 p_val) {return p_fmt << pfc::format_int(p_val);}
00613 inline pfc::string_base & operator<<(pfc::string_base & p_fmt,t_uint32 p_val) {return p_fmt << pfc::format_uint(p_val);}
00614 inline pfc::string_base & operator<<(pfc::string_base & p_fmt,t_int64 p_val) {return p_fmt << pfc::format_int(p_val);}
00615 inline pfc::string_base & operator<<(pfc::string_base & p_fmt,t_uint64 p_val) {return p_fmt << pfc::format_uint(p_val);}
00616 inline pfc::string_base & operator<<(pfc::string_base & p_fmt,double p_val) {return p_fmt << pfc::format_float(p_val);}
00617 
00618 inline pfc::string_base & operator<<(pfc::string_base & p_fmt,std::exception const & p_exception) {return p_fmt << p_exception.what();}
00619 
00620 
00621 
00622 
00623 
00624 
00625 namespace pfc {
00626         template<typename t_char>
00627         class string_simple_t {
00628         private:
00629                 typedef string_simple_t<t_char> t_self;
00630         public:
00631                 t_size length(t_size p_limit = infinite) const {return pfc::strlen_t(get_ptr(),p_limit);}
00632                 bool is_empty() const {return length(1) == 0;}
00633                 void set_string(const t_char * p_source,t_size p_length = infinite) {
00634                         t_size length = pfc::strlen_t(p_source,p_length);
00635                         m_buffer.set_size(length + 1);
00636                         pfc::memcpy_t(m_buffer.get_ptr(),p_source,length);
00637                         m_buffer[length] = 0;
00638                 }
00639                 string_simple_t() {}
00640                 string_simple_t(const t_char * p_source,t_size p_length = infinite) {set_string(p_source,p_length);}
00641                 const t_self & operator=(const t_char * p_source) {set_string(p_source);return *this;}
00642                 operator const t_char* () const {return get_ptr();}
00643                 const t_char * get_ptr() const {return m_buffer.get_size() > 0 ? m_buffer.get_ptr() : pfc::empty_string_t<t_char>();}
00644         private:
00645                 pfc::array_t<t_char> m_buffer;
00646         };
00647 
00648         typedef string_simple_t<char> string_simple;
00649 
00650         template<typename t_char> class traits_t<string_simple_t<t_char> > : public traits_t<array_t<t_char> > {};
00651 }
00652 
00653 
00654 namespace pfc {
00655         class comparator_strcmp {
00656         public:
00657                 inline static int compare(const char * p_item1,const char * p_item2) {return strcmp(p_item1,p_item2);}
00658                 inline static int compare(const wchar_t * item1, const wchar_t * item2) {return wcscmp(item1, item2);}
00659         };
00660 
00661         class comparator_stricmp_ascii {
00662         public:
00663                 inline static int compare(const char * p_item1,const char * p_item2) {return pfc::stricmp_ascii(p_item1,p_item2);}
00664         };
00665 
00666 
00667 
00668 
00669         template<typename t_output, typename t_splitCheck>
00670         void splitStringEx(t_output & p_output, const t_splitCheck & p_check, const char * p_string, t_size p_stringLen = infinite) {
00671                 t_size walk = 0, splitBase = 0;
00672                 const t_size max = strlen_max(p_string,p_stringLen);
00673                 for(;walk < max;) {
00674                         t_size delta = p_check(p_string + walk,p_stringLen - walk);
00675                         if (delta > 0) {
00676                                 if (walk > splitBase) p_output(p_string + splitBase, walk - splitBase);
00677                                 splitBase = walk + delta;
00678                         } else {
00679                                 delta = utf8_char_len(p_string + walk, p_stringLen - walk);
00680                                 if (delta == 0) break;
00681                         }
00682                         walk += delta;
00683                 }
00684                 if (walk > splitBase) p_output(p_string + splitBase, walk - splitBase);
00685         }
00686 
00687         class __splitStringSimple_calculateSubstringCount {
00688         public:
00689                 __splitStringSimple_calculateSubstringCount() : m_count() {}
00690                 void operator() (const char *, t_size) {++m_count;}
00691                 t_size get() const {return m_count;}
00692         private:
00693                 t_size m_count;
00694         };
00695         class __splitStringSimple_check {
00696         public:
00697                 __splitStringSimple_check(const char * p_chars) {
00698                         m_chars.set_size(strlen_utf8(p_chars));
00699                         for(t_size walk = 0, ptr = 0; walk < m_chars.get_size(); ++walk) {
00700                                 ptr += utf8_decode_char(p_chars + ptr,m_chars[walk]);
00701                         }
00702                 }
00703                 t_size operator()(const char * p_string, t_size p_stringLen) const {
00704                         t_uint32 c;
00705                         t_size delta = utf8_decode_char(p_string, c, p_stringLen);
00706                         if (delta > 0) {
00707                                 for(t_size walk = 0; walk < m_chars.get_size(); ++walk) {
00708                                         if (m_chars[walk] == c) return delta;
00709                                 }
00710                         }
00711                         return 0;
00712                 }
00713         private:
00714                 array_t<t_uint32> m_chars;
00715         };
00716         template<typename t_array>
00717         class __splitStringSimple_arrayWrapper {
00718         public:
00719                 __splitStringSimple_arrayWrapper(t_array & p_array) : m_walk(), m_array(p_array) {}
00720                 void operator()(const char * p_string, t_size p_stringLen) {
00721                         m_array[m_walk++].set_string(p_string,p_stringLen);
00722                 }
00723         private:
00724                 t_size m_walk;
00725                 t_array & m_array;
00726         };
00727         template<typename t_list>
00728         class __splitStringSimple_listWrapper {
00729         public:
00730                 __splitStringSimple_listWrapper(t_list & p_list) : m_list(p_list) {}
00731                 void operator()(const char * p_string, t_size p_stringLen) {
00732                         m_temp.set_string(p_string,p_stringLen);
00733                         m_list.add_item(m_temp);
00734                 }
00735         private:
00736                 string8_fastalloc m_temp;
00737                 t_list & m_list;
00738         };
00739 
00740         template<typename t_array>
00741         void splitStringSimple_toArray(t_array & p_output, const char * p_splitChars, const char * p_string, t_size p_stringLen = infinite) {
00742                 __splitStringSimple_check check(p_splitChars);
00743 
00744                 {
00745                         __splitStringSimple_calculateSubstringCount wrapper;
00746                         splitStringEx(wrapper,check,p_string,p_stringLen);
00747                         p_output.set_size(wrapper.get());
00748                 }
00749 
00750                 {
00751                         __splitStringSimple_arrayWrapper<t_array> wrapper(p_output);
00752                         splitStringEx(wrapper,check,p_string,p_stringLen);
00753                 }
00754         }
00755         template<typename t_list>
00756         void splitStringSimple_toList(t_list & p_output, const char * p_splitChars, const char * p_string, t_size p_stringLen = infinite) {
00757                 __splitStringSimple_check check(p_splitChars);
00758 
00759                 __splitStringSimple_listWrapper<t_list> wrapper(p_output);
00760                 splitStringEx(wrapper,check,p_string,p_stringLen);
00761         }
00762 
00763         template<typename t_out> void splitStringByLines(t_out & out, const char * str) {
00764                 for(;;) {
00765                         const char * next = strchr(str, '\n');
00766                         if (next == NULL) {
00767                                 out.insert_last()->set_string(str); break;
00768                         }
00769                         const char * walk = next;
00770                         while(walk > str && walk[-1] == '\r') --walk;
00771                         out.insert_last()->set_string(str, walk - str);
00772                         str = next + 1;
00773                 }
00774         }
00775 
00776         void stringToUpperAppend(string_base & p_out, const char * p_source, t_size p_sourceLen);
00777         void stringToLowerAppend(string_base & p_out, const char * p_source, t_size p_sourceLen);
00778         int stringCompareCaseInsensitive(const char * s1, const char * s2);
00779         t_uint32 charLower(t_uint32 param);
00780         t_uint32 charUpper(t_uint32 param);
00781 
00782         template<typename T> inline const char * stringToPtr(T const& val) {return val.get_ptr();}
00783         inline const char * stringToPtr(const char* val) {return val;}
00784 
00785 
00786 
00787         class string_base_ref : public string_base {
00788         public:
00789                 string_base_ref(const char * ptr) : m_ptr(ptr), m_len(strlen(ptr)) {}
00790                 const char * get_ptr() const {return m_ptr;}
00791                 t_size get_length() const {return m_len;}
00792         private:
00793                 void add_string(const char * p_string,t_size p_length = ~0) {throw pfc::exception_not_implemented();}
00794                 void set_string(const char * p_string,t_size p_length = ~0) {throw pfc::exception_not_implemented();}
00795                 void truncate(t_size len) {throw pfc::exception_not_implemented();}
00796                 char * lock_buffer(t_size p_requested_length) {throw pfc::exception_not_implemented();}
00797                 void unlock_buffer() {throw pfc::exception_not_implemented();}
00798         private:
00799                 const char * const m_ptr;
00800                 t_size const m_len;
00801         };
00802 
00804         template<typename TChar, t_size len, typename TSource>
00805         void stringToBuffer(TChar (&buffer)[len], const TSource & source) {
00806                 pfc::static_assert<(len>0)>();
00807                 t_size walk;
00808                 for(walk = 0; walk < len - 1 && source[walk] != 0; ++walk) {
00809                         buffer[walk] = source[walk];
00810                 }
00811                 buffer[walk] = 0;
00812         }
00813 
00815         template<typename TChar, t_size len, typename TSource>
00816         void stringToBufferGuarded(TChar (&buffer)[len], const TSource & source) {
00817                 t_size walk;
00818                 for(walk = 0; source[walk] != 0; ++walk) {
00819                         if (walk >= len) throw exception_overflow();
00820                         buffer[walk] = source[walk];
00821                 }
00822                 if (walk >= len) throw exception_overflow();
00823                 buffer[walk] = 0;
00824         }
00825 
00826 
00827         template<typename t_char> int _strcmp_partial_ex(const t_char * p_string,t_size p_string_length,const t_char * p_substring,t_size p_substring_length) throw() {
00828                 for(t_size walk=0;walk<p_substring_length;walk++) {
00829                         t_char stringchar = (walk>=p_string_length ? 0 : p_string[walk]);
00830                         t_char substringchar = p_substring[walk];
00831                         int result = compare_t(stringchar,substringchar);
00832                         if (result != 0) return result;
00833                 }
00834                 return 0;
00835         }
00836 
00837         template<typename t_char> int strcmp_partial_ex_t(const t_char * p_string,t_size p_string_length,const t_char * p_substring,t_size p_substring_length) throw() {
00838                 p_string_length = strlen_max_t(p_string,p_string_length); p_substring_length = strlen_max_t(p_substring,p_substring_length);
00839                 return _strcmp_partial_ex(p_string,p_string_length,p_substring,p_substring_length);
00840         }
00841 
00842         template<typename t_char>
00843         int strcmp_partial_t(const t_char * p_string,const t_char * p_substring) throw() {return strcmp_partial_ex_t(p_string,infinite,p_substring,infinite);}
00844 
00845         static int strcmp_partial_ex(const char * str, t_size strLen, const char * substr, t_size substrLen) throw() {return strcmp_partial_ex(str, strLen, substr, substrLen); }
00846         static int strcmp_partial(const char * str, const char * substr) throw() {return strcmp_partial_t(str, substr); }
00847 
00848 }
00849 
00850 #endif //_PFC_STRING_H_

Generated on Thu Aug 28 21:15:37 2008 for foobar2000 SDK by  doxygen 1.5.5