String.cc revision 10447
1#include "String.h" 2 3#include <cstdarg> 4#include <cstdio> 5#include <iostream> 6#include <ios> 7 8namespace LibUtil 9{ 10 const unsigned int String::msBufferSize = 4096; 11 12 String String::format(const String& format_, ...) 13 { 14 char buffer[msBufferSize]; 15 16 va_list args; 17 va_start(args, format_); 18 vsnprintf(buffer, msBufferSize, format_.c_str(), args); 19 va_end(args); 20 21 return (String)(buffer); 22 } 23 24 String String::format(const String& format_, va_list args_) 25 { 26 char buffer[msBufferSize]; 27 28 vsnprintf(buffer, msBufferSize, format_.c_str(), args_); 29 30 return (String)(buffer); 31 } 32 33 String::String() 34 {} 35 36 String::String(const string& str_) 37 : string(str_) 38 {} 39 40 String::String(const char* str_, size_t n_) 41 : string(str_, n_) 42 {} 43 44 String::String(const char* str_) 45 : string(str_) 46 {} 47 48 String::String(size_t n_, char c_) 49 : string(n_, c_) 50 {} 51 52 String::String(int value_) 53 : string(toString<int>(value_)) 54 {} 55 56 String::String(unsigned int value_) 57 : string(toString<unsigned int>(value_)) 58 {} 59 60 String::String(long value_) 61 : string(toString<long>(value_)) 62 {} 63 64 String::String(unsigned long value_) 65 : string(toString<unsigned long>(value_)) 66 {} 67 68 String::String(float value_) 69 : string(toString<float>(value_)) 70 {} 71 72 String::String(double value_) 73 : string(toString<double>(value_)) 74 {} 75 76 String::String(bool value_) 77 : string(toString<bool>(value_)) 78 {} 79 80 String::~String() 81 {} 82 83 String& String::trim() 84 { 85 // Remove leading and trailing whitespace 86 static const char whitespace[] = " \n\t\v\r\f"; 87 erase(0, find_first_not_of(whitespace)); 88 erase(find_last_not_of(whitespace) + 1U); 89 return (*this); 90 } 91 92 String& String::substitute(const String& str1_, const String& str2_) 93 { 94 size_t str1Size = str1_.size(); 95 size_t str2Size = str2_.size(); 96 97 size_t pos; 98 pos = find(str1_); 99 while(pos != string::npos) 100 { 101 replace(pos, str1Size, str2_); 102 pos += str2Size; 103 pos = find(str1_, pos); 104 } 105 return (*this); 106 } 107 108 vector<String> String::split(const char* delimiters_) const 109 { 110 vector<String> result; 111 112 if(size() == 0) 113 { 114 return result; 115 } 116 117 size_t currPos, nextPos; 118 currPos = 0; 119 nextPos = find_first_of(delimiters_); 120 while(1) 121 { 122 if(nextPos == string::npos) 123 { 124 if(currPos != size()) 125 { 126 result.push_back(substr(currPos)); 127 } 128 break; 129 } 130 131 if(nextPos != currPos) 132 { 133 result.push_back(substr(currPos, nextPos - currPos)); 134 } 135 currPos = nextPos + 1; 136 nextPos = find_first_of(delimiters_, currPos); 137 } 138 139 return result; 140 } 141 142 vector<String> String::split(const String* delimiters_, unsigned int num_delimiters_) const 143 { 144 vector<String> result; 145 146 if(size() == 0) 147 { 148 return result; 149 } 150 151 if(num_delimiters_ == 1) 152 { 153 size_t currPos, nextPos; 154 currPos = 0; 155 nextPos = find(delimiters_[0]); 156 while(1) 157 { 158 if(nextPos == String::npos) 159 { 160 result.push_back(substr(currPos)); 161 break; 162 } 163 164 if(nextPos != currPos) 165 { 166 result.push_back(substr(currPos, nextPos - currPos)); 167 } 168 currPos = nextPos + delimiters_[0].size(); 169 nextPos = find(delimiters_[0], currPos); 170 } 171 } 172 else 173 { 174 // Currently the length of the delimiters are not checked 175 unsigned int delimiterLength = 0; 176 size_t currPos, nextPos; 177 currPos = 0; 178 nextPos = size(); 179 for(unsigned int i = 0; i < num_delimiters_; ++i) 180 { 181 size_t tempPos = find(delimiters_[i], currPos); 182 if((tempPos != String::npos) && (tempPos < nextPos)) 183 { 184 nextPos = tempPos; 185 delimiterLength = delimiters_[i].size(); 186 } 187 } 188 while(1) 189 { 190 if((nextPos == String::npos) || (nextPos == size())) 191 { 192 result.push_back(substr(currPos)); 193 break; 194 } 195 196 if(nextPos != currPos) 197 { 198 result.push_back(substr(currPos, nextPos - currPos)); 199 } 200 currPos = nextPos + delimiterLength; 201 nextPos = size(); 202 delimiterLength = 0; 203 for(unsigned int i = 0; i < num_delimiters_; ++i) 204 { 205 size_t tempPos = find(delimiters_[i], currPos); 206 if((tempPos != String::npos) && (tempPos < nextPos)) 207 { 208 nextPos = tempPos; 209 delimiterLength = delimiters_[i].size(); 210 } 211 } 212 } 213 } 214 return result; 215 } 216 217 vector<String> String::splitByString(const String& delimiter_) const 218 { 219 return split(&delimiter_, 1); 220 } 221 222 bool String::contain(const String& str_) const 223 { 224 return (find(str_) != String::npos); 225 } 226 227 const char* String::toCString() const 228 { 229 return this->c_str(); 230 } 231 232 int String::toInt() const 233 { 234 return fromString<int>(*this); 235 } 236 237 unsigned int String::toUInt() const 238 { 239 return fromString<unsigned int>(*this); 240 } 241 242 long String::toLong() const 243 { 244 return fromString<long>(*this); 245 } 246 247 unsigned long String::toULong() const 248 { 249 return fromString<unsigned long>(*this); 250 } 251 252 float String::toFloat() const 253 { 254 return fromString<float>(*this); 255 } 256 257 double String::toDouble() const 258 { 259 return fromString<double>(*this); 260 } 261 262 bool String::toBool() const 263 { 264 return fromString<bool>(*this); 265 } 266 267 String::operator const char*() const 268 { 269 return this->c_str(); 270 } 271 272 String::operator int() const 273 { 274 return fromString<int>(*this); 275 } 276 277 String::operator unsigned int() const 278 { 279 return fromString<unsigned int>(*this); 280 } 281 282 String::operator long() const 283 { 284 return fromString<long>(*this); 285 } 286 287 String::operator unsigned long() const 288 { 289 return fromString<unsigned long>(*this); 290 } 291 292 String::operator float() const 293 { 294 return fromString<float>(*this); 295 } 296 297 String::operator double() const 298 { 299 return fromString<double>(*this); 300 } 301 302 String::operator bool() const 303 { 304 return fromString<bool>(*this); 305 } 306 307 String& String::operator=(char c_) 308 { 309 this->assign(1, c_); 310 return *this; 311 } 312 313 std::istream& safeGetline(std::istream& is_, String& str_) 314 { 315 str_.clear(); 316 317 // The characters in the stream are read one-by-one using a std::streambuf. 318 // That is faster than reading them one-by-one using the std::istream. 319 // Code that uses streambuf this way must be guarded by a sentry object. 320 // The sentry object performs various tasks, 321 // such as thread synchronization and updating the stream state. 322 323 std::istream::sentry se(is_, true); 324 std::streambuf* sb = is_.rdbuf(); 325 326 while(1) 327 { 328 int c = sb->sbumpc(); 329 switch(c) 330 { 331 case '\r': 332 c = sb->sgetc(); 333 if(c == '\n') 334 sb->sbumpc(); 335 return is_; 336 case '\n': 337 return is_; 338 case EOF: 339 is_.setstate(std::ios_base::failbit|std::ios_base::eofbit); 340 return is_; 341 default: 342 str_ += String(1, (char)c); 343 } 344 } 345 } 346} // namespace LibUtil 347 348