| /* 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 <cstdarg> |
| #include <cstdio> |
| #include <iostream> |
| #include <ios> |
| |
| 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<int>(value_)) |
| {} |
| |
| String::String(unsigned int value_) |
| : string(toString<unsigned int>(value_)) |
| {} |
| |
| String::String(long value_) |
| : string(toString<long>(value_)) |
| {} |
| |
| String::String(unsigned long value_) |
| : string(toString<unsigned long>(value_)) |
| {} |
| |
| String::String(float value_) |
| : string(toString<float>(value_)) |
| {} |
| |
| String::String(double value_) |
| : string(toString<double>(value_)) |
| {} |
| |
| String::String(bool value_) |
| : string(toString<bool>(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> String::split(const char* delimiters_) const |
| { |
| vector<String> 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> String::split(const String* delimiters_, unsigned int num_delimiters_) const |
| { |
| vector<String> 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> 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<int>(*this); |
| } |
| |
| unsigned int String::toUInt() const |
| { |
| return fromString<unsigned int>(*this); |
| } |
| |
| long String::toLong() const |
| { |
| return fromString<long>(*this); |
| } |
| |
| unsigned long String::toULong() const |
| { |
| return fromString<unsigned long>(*this); |
| } |
| |
| float String::toFloat() const |
| { |
| return fromString<float>(*this); |
| } |
| |
| double String::toDouble() const |
| { |
| return fromString<double>(*this); |
| } |
| |
| bool String::toBool() const |
| { |
| return fromString<bool>(*this); |
| } |
| |
| String::operator const char*() const |
| { |
| return this->c_str(); |
| } |
| |
| String::operator int() const |
| { |
| return fromString<int>(*this); |
| } |
| |
| String::operator unsigned int() const |
| { |
| return fromString<unsigned int>(*this); |
| } |
| |
| String::operator long() const |
| { |
| return fromString<long>(*this); |
| } |
| |
| String::operator unsigned long() const |
| { |
| return fromString<unsigned long>(*this); |
| } |
| |
| String::operator float() const |
| { |
| return fromString<float>(*this); |
| } |
| |
| String::operator double() const |
| { |
| return fromString<double>(*this); |
| } |
| |
| String::operator bool() const |
| { |
| return fromString<bool>(*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 |
| |