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);
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);
00027 void convert_to_lower_ascii(const char * src,t_size max,char * out,char replace = '?');
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);
00033 t_size string_find_last(const char * p_string,char p_tofind,t_size p_start = ~0);
00034 t_size string_find_first(const char * p_string,const char * p_tofind,t_size p_start = 0);
00035 t_size string_find_last(const char * p_string,const char * p_tofind,t_size p_start = ~0);
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);
00038 t_size string_find_last_ex(const char * p_string,t_size p_string_length,char p_tofind,t_size p_start = ~0);
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);
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);
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();
00070 t_size utf8_char_len(const char * s,t_size max = ~0) throw();
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();
00077 t_size utf8_decode_char(const char * src,unsigned & out) throw();
00078
00079 t_size utf8_encode_char(unsigned c,char * out) throw();
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;
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);
00270 void remove_chars(t_size first,t_size count);
00271 void insert_chars(t_size first,const char * src, t_size count);
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
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
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);
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_