cgma
CubitString.cpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines