/* Copyright (c) 2012 Massachusetts Institute of Technology * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "String.h" #include #include #include #include namespace LibUtil { const unsigned int String::msBufferSize = 4096; String String::format(const String& format_, ...) { char buffer[msBufferSize]; va_list args; va_start(args, format_); vsnprintf(buffer, msBufferSize, format_.c_str(), args); va_end(args); return (String)(buffer); } String String::format(const String& format_, va_list args_) { char buffer[msBufferSize]; vsnprintf(buffer, msBufferSize, format_.c_str(), args_); return (String)(buffer); } String::String() {} String::String(const string& str_) : string(str_) {} String::String(const char* str_, size_t n_) : string(str_, n_) {} String::String(const char* str_) : string(str_) {} String::String(size_t n_, char c_) : string(n_, c_) {} String::String(int value_) : string(toString(value_)) {} String::String(unsigned int value_) : string(toString(value_)) {} String::String(long value_) : string(toString(value_)) {} String::String(unsigned long value_) : string(toString(value_)) {} String::String(float value_) : string(toString(value_)) {} String::String(double value_) : string(toString(value_)) {} String::String(bool value_) : string(toString(value_)) {} String::~String() {} String& String::trim() { // Remove leading and trailing whitespace static const char whitespace[] = " \n\t\v\r\f"; erase(0, find_first_not_of(whitespace)); erase(find_last_not_of(whitespace) + 1U); return (*this); } String& String::substitute(const String& str1_, const String& str2_) { size_t str1Size = str1_.size(); size_t str2Size = str2_.size(); size_t pos; pos = find(str1_); while(pos != string::npos) { replace(pos, str1Size, str2_); pos += str2Size; pos = find(str1_, pos); } return (*this); } vector String::split(const char* delimiters_) const { vector result; if(size() == 0) { return result; } size_t currPos, nextPos; currPos = 0; nextPos = find_first_of(delimiters_); while(1) { if(nextPos == string::npos) { if(currPos != size()) { result.push_back(substr(currPos)); } break; } if(nextPos != currPos) { result.push_back(substr(currPos, nextPos - currPos)); } currPos = nextPos + 1; nextPos = find_first_of(delimiters_, currPos); } return result; } vector String::split(const String* delimiters_, unsigned int num_delimiters_) const { vector result; if(size() == 0) { return result; } if(num_delimiters_ == 1) { size_t currPos, nextPos; currPos = 0; nextPos = find(delimiters_[0]); while(1) { if(nextPos == String::npos) { result.push_back(substr(currPos)); break; } if(nextPos != currPos) { result.push_back(substr(currPos, nextPos - currPos)); } currPos = nextPos + delimiters_[0].size(); nextPos = find(delimiters_[0], currPos); } } else { // Currently the length of the delimiters are not checked unsigned int delimiterLength = 0; size_t currPos, nextPos; currPos = 0; nextPos = size(); for(unsigned int i = 0; i < num_delimiters_; ++i) { size_t tempPos = find(delimiters_[i], currPos); if((tempPos != String::npos) && (tempPos < nextPos)) { nextPos = tempPos; delimiterLength = delimiters_[i].size(); } } while(1) { if((nextPos == String::npos) || (nextPos == size())) { result.push_back(substr(currPos)); break; } if(nextPos != currPos) { result.push_back(substr(currPos, nextPos - currPos)); } currPos = nextPos + delimiterLength; nextPos = size(); delimiterLength = 0; for(unsigned int i = 0; i < num_delimiters_; ++i) { size_t tempPos = find(delimiters_[i], currPos); if((tempPos != String::npos) && (tempPos < nextPos)) { nextPos = tempPos; delimiterLength = delimiters_[i].size(); } } } } return result; } vector String::splitByString(const String& delimiter_) const { return split(&delimiter_, 1); } bool String::contain(const String& str_) const { return (find(str_) != String::npos); } const char* String::toCString() const { return this->c_str(); } int String::toInt() const { return fromString(*this); } unsigned int String::toUInt() const { return fromString(*this); } long String::toLong() const { return fromString(*this); } unsigned long String::toULong() const { return fromString(*this); } float String::toFloat() const { return fromString(*this); } double String::toDouble() const { return fromString(*this); } bool String::toBool() const { return fromString(*this); } String::operator const char*() const { return this->c_str(); } String::operator int() const { return fromString(*this); } String::operator unsigned int() const { return fromString(*this); } String::operator long() const { return fromString(*this); } String::operator unsigned long() const { return fromString(*this); } String::operator float() const { return fromString(*this); } String::operator double() const { return fromString(*this); } String::operator bool() const { return fromString(*this); } String& String::operator=(char c_) { this->assign(1, c_); return *this; } std::istream& safeGetline(std::istream& is_, String& str_) { str_.clear(); // The characters in the stream are read one-by-one using a std::streambuf. // That is faster than reading them one-by-one using the std::istream. // Code that uses streambuf this way must be guarded by a sentry object. // The sentry object performs various tasks, // such as thread synchronization and updating the stream state. std::istream::sentry se(is_, true); std::streambuf* sb = is_.rdbuf(); while(1) { int c = sb->sbumpc(); switch(c) { case '\r': c = sb->sgetc(); if(c == '\n') sb->sbumpc(); return is_; case '\n': return is_; case EOF: is_.setstate(std::ios_base::failbit|std::ios_base::eofbit); return is_; default: str_ += String(1, (char)c); } } } } // namespace LibUtil