cgma
|
00001 // CubitString.cpp 00002 00003 00004 #include "CubitString.hpp" 00005 #include "CubitDefines.h" 00006 00007 #ifdef _WIN32 00008 #include <windows.h> 00009 #define vsnprintf _vsnprintf 00010 #endif 00011 00012 #ifdef _MSC_VER 00013 #pragma warning ( 4 : 4291 4244 4305 4018 ) 00014 #define va_copy(dest, src) (dest = src) 00015 #endif 00016 00017 00018 #include <iomanip> 00019 #include <cstring> 00020 #include <stdexcept> 00021 #include <algorithm> 00022 #include <stdarg.h> 00023 00024 const size_t CubitString::npos = std::string::npos; 00025 00026 CubitString::CubitString() 00027 { 00028 } 00029 00030 CubitString::CubitString(const CubitString& s) 00031 : rep(s.rep) 00032 { 00033 } 00034 00035 CubitString::~CubitString() 00036 { 00037 } 00038 00039 CubitString::CubitString(const char *s) 00040 { 00041 if(s) 00042 { 00043 rep = s; 00044 } 00045 } 00046 00047 CubitString::CubitString(const std::string& s) 00048 : rep(s) 00049 { 00050 } 00051 00052 CubitString::CubitString(int i, char c) 00053 : rep(i,c) 00054 { 00055 } 00056 00057 CubitString CubitString::number(double f, unsigned int max_length, unsigned int sig_digits) 00058 { 00059 std::stringstream str; 00060 if(max_length) 00061 { 00062 str.width(max_length); 00063 } 00064 if(sig_digits) 00065 { 00066 str.precision(sig_digits); 00067 } 00068 str << f; 00069 std::string ret = str.str(); 00070 size_t i = ret.find_first_not_of(' '); 00071 if(i != std::string::npos) 00072 ret = ret.substr(i); 00073 00074 // change precision to be short enough 00075 if (max_length) 00076 { 00077 if(sig_digits == 0) 00078 sig_digits = max_length; 00079 00080 while(ret.length() > max_length && sig_digits) 00081 { 00082 sig_digits--; 00083 str.precision(sig_digits); 00084 str.str(std::string()); 00085 str << f; 00086 ret = str.str(); 00087 } 00088 } 00089 return ret.c_str(); 00090 } 00091 00092 CubitString CubitString::format(const char* format, ...) 00093 { 00094 va_list args, args2; 00095 va_start(args, format); 00096 // copy because first vsnprintf modifies args 00097 va_copy(args2, args); 00098 00099 // how much room do we need for our string? 00100 int num = vsnprintf(NULL, 0, format, args); 00101 00102 // string plus null terminator 00103 std::vector<char> str; 00104 str.resize(num+1); 00105 00106 // print string 00107 num = vsnprintf(&str[0], num+1, format, args2); 00108 00109 // remove extra null terminator 00110 str.resize(num); 00111 00112 va_end(args); 00113 va_end(args2); 00114 00115 return str.empty() ? CubitString() : CubitString(&str[0]); 00116 } 00117 00118 CubitString& CubitString::operator=(const CubitString& s) 00119 { 00120 rep = s.rep; 00121 return *this; 00122 } 00123 00124 #ifdef _WIN32 00125 # define strcasecmp _stricmp 00126 #endif 00127 00128 bool CubitString::compare(const CubitString& s, CaseSensitivity cs) 00129 { 00130 if(cs == CaseSensitive) 00131 return this->rep == s.rep; 00132 00133 // someday we might need to fix this to be unicode aware 00134 if(strcasecmp(this->rep.c_str(), s.rep.c_str()) == 0) 00135 return true; 00136 return false; 00137 } 00138 00139 char CubitString::get_at(size_t pos) const 00140 { 00141 // some legacy code wants to look for the null terminator 00142 if(pos == rep.size()) 00143 return 0; 00144 00145 return rep.at(pos); 00146 } 00147 00148 bool CubitString::is_empty() const 00149 { 00150 return rep.empty(); 00151 } 00152 00153 size_t CubitString::length() const 00154 { 00155 return rep.length(); 00156 } 00157 00158 const char * CubitString::c_str() const 00159 { 00160 return rep.c_str(); 00161 } 00162 00163 const std::string& CubitString::str() const 00164 { 00165 return rep; 00166 } 00167 00168 void CubitString::clear() 00169 { 00170 rep.clear(); 00171 } 00172 00173 void CubitString::resize(size_t n) 00174 { 00175 rep.resize(n); 00176 } 00177 00178 void CubitString::resize(size_t n, char c) 00179 { 00180 rep.resize(n, c); 00181 } 00182 00183 00184 CubitString operator+(const CubitString& s1, const CubitString& s2) 00185 { 00186 return CubitString(s1) += s2; 00187 } 00188 00189 CubitString operator+(const CubitString& s1, const char *c2) 00190 { 00191 return CubitString(s1) += c2; 00192 } 00193 00194 CubitString operator+(const char *c1, const CubitString& s2) 00195 { 00196 return CubitString(c1) += s2; 00197 } 00198 00199 CubitString& CubitString::operator+=(const CubitString& s) 00200 { 00201 rep += s.rep; 00202 return *this; 00203 } 00204 00205 size_t CubitString::find(const CubitString& s, size_t pos) const 00206 { 00207 if(pos != 0 && pos >= rep.size()) 00208 throw std::out_of_range("find index out of range"); 00209 return rep.find(s.rep, pos); 00210 } 00211 00212 size_t CubitString::find_first_of(const CubitString& s, size_t pos) const 00213 { 00214 return rep.find_first_of(s.rep, pos); 00215 } 00216 00217 size_t CubitString::find_first(char c, size_t pos) const 00218 { 00219 return rep.find(c, pos); 00220 } 00221 00222 size_t CubitString::find_last(char c, size_t pos) const 00223 { 00224 return rep.find_last_of(c, pos); 00225 } 00226 00227 00228 CubitString CubitString::substr(size_t first, size_t count) const 00229 { 00230 if(first >= rep.size()) 00231 return CubitString(); 00232 00233 if(count > rep.size() - first) 00234 count = rep.size() - first; 00235 00236 return rep.substr(first, count).c_str(); 00237 } 00238 00239 void CubitString::erase(size_t pos, size_t len) 00240 { 00241 rep.erase(pos, len); 00242 } 00243 00244 void CubitString::replace(size_t pos, size_t len, const CubitString& str) 00245 { 00246 rep.replace(pos, len, str.rep); 00247 } 00248 00249 void CubitString::replace(const CubitString& to_find, const CubitString& to_replace) 00250 { 00251 size_t len = to_find.length(); 00252 size_t len2 = to_replace.length(); 00253 for(size_t idx = rep.find(to_find.c_str()); idx != npos; idx = rep.find(to_find.c_str(), idx)) 00254 { 00255 rep.replace(idx, len, to_replace.rep); 00256 idx += len2; 00257 } 00258 } 00259 00260 bool CubitString::ends_with(const CubitString& str) const 00261 { 00262 if(rep.size() >= str.rep.size()) 00263 { 00264 size_t offset = rep.size() - str.rep.size(); 00265 return std::equal(str.rep.begin(), str.rep.end(), rep.begin() + offset); 00266 } 00267 return false; 00268 } 00269 00270 bool CubitString::starts_with(const CubitString& str) const 00271 { 00272 if(rep.size() >= str.rep.size()) 00273 { 00274 return std::equal(str.rep.begin(), str.rep.end(), rep.begin()); 00275 } 00276 return false; 00277 } 00278 00279 void CubitString::put_at(size_t pos, char c) 00280 { 00281 rep.at(pos) = c; 00282 } 00283 00284 void CubitString::to_lower() 00285 { 00286 for(size_t i=0; i<rep.size(); i++) 00287 { 00288 rep.at(i) = tolower(rep.at(i)); 00289 } 00290 } 00291 00292 void CubitString::to_upper() 00293 { 00294 for(size_t i=0; i<rep.size(); i++) 00295 { 00296 rep.at(i) = toupper(rep.at(i)); 00297 } 00298 } 00299 00300 void CubitString::to_lower(char *string) 00301 { 00302 // convert this string to lower case 00303 char *p = string; 00304 while (*p != '\0') 00305 { 00306 *p = tolower (*p); 00307 p++; 00308 } 00309 } 00310 00311 void CubitString::to_upper(char *string) 00312 { 00313 // convert this string to upper case 00314 char *p = string; 00315 while (*p != '\0') 00316 { 00317 *p = toupper (*p); 00318 p++; 00319 } 00320 } 00321 00322 void CubitString::trim() 00323 { 00324 std::string::size_type start = rep.find_first_not_of(" \t\n\v\f\r"); 00325 rep.erase(0, start); 00326 std::string::size_type end = rep.find_last_not_of(" \t\n\v\f\r"); 00327 rep.erase(end+1, std::string::npos); 00328 } 00329 00330 void CubitString::simplify() 00331 { 00332 trim(); 00333 for(std::string::size_type i = rep.find_first_of(" \t\n\v\f\r"); i != std::string::npos; 00334 i = rep.find_first_of(" \t\n\v\f\r", i+1)) 00335 { 00336 std::string::size_type next_i = rep.find_first_not_of(" \t\n\v\f\r", i); 00337 if(next_i > i+1) 00338 { 00339 rep.erase(i+1, next_i-i-1); 00340 rep.at(i) = ' '; 00341 } 00342 } 00343 } 00344 00345 void CubitString::tokenize( char delimiter, std::vector<CubitString> &strings ) const 00346 { 00347 std::stringstream ss(rep); 00348 std::string s; 00349 while(std::getline(ss, s, delimiter)) 00350 strings.push_back(CubitString(s.c_str())); 00351 } 00352 00353 bool CubitString::operator==(const CubitString& s2) const 00354 { 00355 return rep == s2.rep; 00356 } 00357 00358 bool CubitString::operator!=(const CubitString& s2) const 00359 { 00360 return rep != s2.rep; 00361 } 00362 00363 bool operator<=(const CubitString& s1, const CubitString& s2) 00364 { 00365 return s1.rep <= s2.rep; 00366 } 00367 00368 bool operator>=(const CubitString& s1, const CubitString& s2) 00369 { 00370 return s1.rep >= s2.rep; 00371 } 00372 00373 bool operator<( const CubitString& s1, const CubitString& s2 ) 00374 { 00375 return s1.rep < s2.rep; 00376 } 00377 00378 bool operator>( const CubitString& s1, const CubitString& s2 ) 00379 { 00380 return s1.rep > s2.rep; 00381 } 00382 00383 #if defined(_WIN32) 00384 00385 std::wstring CubitString::toUtf16(const char* str) 00386 { 00387 // there are other methods (e.g. C++11), but since its Windows specific to support Windows APIs, just use their API. 00388 std::wstring ret; 00389 int sz = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0); 00390 if(sz) 00391 { 00392 std::vector<wchar_t> result(sz); 00393 MultiByteToWideChar(CP_UTF8, 0, str, -1, &result[0], sz); 00394 ret = &result[0]; 00395 } 00396 return ret; 00397 } 00398 00399 std::wstring CubitString::toUtf16(const CubitString& str) 00400 { 00401 return toUtf16(str.c_str()); 00402 } 00403 00404 CubitString CubitString::toUtf8(const wchar_t* str) 00405 { 00406 CubitString ret; 00407 int sz = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL); 00408 if(sz) 00409 { 00410 std::vector<char> result(sz); 00411 WideCharToMultiByte(CP_UTF8, 0, str, -1, &result[0], sz, NULL, NULL); 00412 ret = &result[0]; 00413 } 00414 return ret; 00415 } 00416 00417 #endif 00418 00419 #if defined(_MSC_VER) 00420 00421 std::wstring CubitString::toNative(const char* str) 00422 { 00423 return toUtf16(str); 00424 } 00425 00426 std::wstring CubitString::toNative(const CubitString& str) 00427 { 00428 return toUtf16(str); 00429 } 00430 00431 #else 00432 00433 CubitString CubitString::toNative(const char* str) 00434 { 00435 return str; 00436 } 00437 00438 CubitString CubitString::toNative(const CubitString& str) 00439 { 00440 return str; 00441 } 00442 00443 #endif 00444 00445 std::wstring CubitString::toWide(const CubitString& str) 00446 { 00447 #ifdef _WIN32 00448 return toUtf16(str); 00449 #else 00450 std::wstring wstr; 00451 size_t len = mbstowcs(NULL, str.c_str(), 0) + 1; 00452 if(len > 0) 00453 { 00454 std::vector<wchar_t> wchar(len); 00455 mbstowcs(&wchar[0], str.c_str(), len); 00456 wstr = &wchar[0]; 00457 } 00458 return wstr; 00459 #endif 00460 } 00461 00462 CubitString CubitString::toNarrow(const std::wstring& wstr) 00463 { 00464 #ifdef _WIN32 00465 return toUtf8(wstr.c_str()).c_str(); 00466 #else 00467 CubitString str; 00468 size_t len = wcstombs(NULL, wstr.c_str(), 0) + 1; 00469 if(len > 0) 00470 { 00471 std::vector<char> chars(len); 00472 wcstombs(&chars[0], wstr.c_str(), len); 00473 str = &chars[0]; 00474 } 00475 return str; 00476 #endif 00477 } 00478 00479 00480 00481 #ifdef TEST_STRING 00482 00483 void main() { 00484 CubitString a = "Test "; 00485 CubitString b = "String Class"; 00486 CubitString blank(' '); 00487 00488 CubitString c = a + b; 00489 c+= b; 00490 CubitString e = c; 00491 CubitString f = c; 00492 CubitString g = c; 00493 g.put_at(1, 'Z'); 00494 cout << "G = " << g << endl; 00495 cout << "C = " << c << endl; 00496 00497 c.put_at(1, 'X'); 00498 CubitString d = b; 00499 d.put_at(1, 'Y'); 00500 } 00501 #endif