110448Snilay@cs.wisc.edu/* Copyright (c) 2012 Massachusetts Institute of Technology 210448Snilay@cs.wisc.edu * 310448Snilay@cs.wisc.edu * Permission is hereby granted, free of charge, to any person obtaining a copy 410448Snilay@cs.wisc.edu * of this software and associated documentation files (the "Software"), to deal 510448Snilay@cs.wisc.edu * in the Software without restriction, including without limitation the rights 610448Snilay@cs.wisc.edu * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 710448Snilay@cs.wisc.edu * copies of the Software, and to permit persons to whom the Software is 810448Snilay@cs.wisc.edu * furnished to do so, subject to the following conditions: 910448Snilay@cs.wisc.edu * 1010448Snilay@cs.wisc.edu * The above copyright notice and this permission notice shall be included in 1110448Snilay@cs.wisc.edu * all copies or substantial portions of the Software. 1210448Snilay@cs.wisc.edu * 1310448Snilay@cs.wisc.edu * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1410448Snilay@cs.wisc.edu * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1510448Snilay@cs.wisc.edu * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1610448Snilay@cs.wisc.edu * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1710448Snilay@cs.wisc.edu * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 1810448Snilay@cs.wisc.edu * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 1910448Snilay@cs.wisc.edu * THE SOFTWARE. 2010448Snilay@cs.wisc.edu */ 2110448Snilay@cs.wisc.edu 2210447Snilay@cs.wisc.edu#include "String.h" 2310447Snilay@cs.wisc.edu 2410447Snilay@cs.wisc.edu#include <cstdarg> 2510447Snilay@cs.wisc.edu#include <cstdio> 2610447Snilay@cs.wisc.edu#include <iostream> 2710447Snilay@cs.wisc.edu#include <ios> 2810447Snilay@cs.wisc.edu 2910447Snilay@cs.wisc.edunamespace LibUtil 3010447Snilay@cs.wisc.edu{ 3110447Snilay@cs.wisc.edu const unsigned int String::msBufferSize = 4096; 3210447Snilay@cs.wisc.edu 3310447Snilay@cs.wisc.edu String String::format(const String& format_, ...) 3410447Snilay@cs.wisc.edu { 3510447Snilay@cs.wisc.edu char buffer[msBufferSize]; 3610447Snilay@cs.wisc.edu 3710447Snilay@cs.wisc.edu va_list args; 3810447Snilay@cs.wisc.edu va_start(args, format_); 3910447Snilay@cs.wisc.edu vsnprintf(buffer, msBufferSize, format_.c_str(), args); 4010447Snilay@cs.wisc.edu va_end(args); 4110447Snilay@cs.wisc.edu 4210447Snilay@cs.wisc.edu return (String)(buffer); 4310447Snilay@cs.wisc.edu } 4410447Snilay@cs.wisc.edu 4510447Snilay@cs.wisc.edu String String::format(const String& format_, va_list args_) 4610447Snilay@cs.wisc.edu { 4710447Snilay@cs.wisc.edu char buffer[msBufferSize]; 4810447Snilay@cs.wisc.edu 4910447Snilay@cs.wisc.edu vsnprintf(buffer, msBufferSize, format_.c_str(), args_); 5010447Snilay@cs.wisc.edu 5110447Snilay@cs.wisc.edu return (String)(buffer); 5210447Snilay@cs.wisc.edu } 5310447Snilay@cs.wisc.edu 5410447Snilay@cs.wisc.edu String::String() 5510447Snilay@cs.wisc.edu {} 5610447Snilay@cs.wisc.edu 5710447Snilay@cs.wisc.edu String::String(const string& str_) 5810447Snilay@cs.wisc.edu : string(str_) 5910447Snilay@cs.wisc.edu {} 6010447Snilay@cs.wisc.edu 6110447Snilay@cs.wisc.edu String::String(const char* str_, size_t n_) 6210447Snilay@cs.wisc.edu : string(str_, n_) 6310447Snilay@cs.wisc.edu {} 6410447Snilay@cs.wisc.edu 6510447Snilay@cs.wisc.edu String::String(const char* str_) 6610447Snilay@cs.wisc.edu : string(str_) 6710447Snilay@cs.wisc.edu {} 6810447Snilay@cs.wisc.edu 6910447Snilay@cs.wisc.edu String::String(size_t n_, char c_) 7010447Snilay@cs.wisc.edu : string(n_, c_) 7110447Snilay@cs.wisc.edu {} 7210447Snilay@cs.wisc.edu 7310447Snilay@cs.wisc.edu String::String(int value_) 7410447Snilay@cs.wisc.edu : string(toString<int>(value_)) 7510447Snilay@cs.wisc.edu {} 7610447Snilay@cs.wisc.edu 7710447Snilay@cs.wisc.edu String::String(unsigned int value_) 7810447Snilay@cs.wisc.edu : string(toString<unsigned int>(value_)) 7910447Snilay@cs.wisc.edu {} 8010447Snilay@cs.wisc.edu 8110447Snilay@cs.wisc.edu String::String(long value_) 8210447Snilay@cs.wisc.edu : string(toString<long>(value_)) 8310447Snilay@cs.wisc.edu {} 8410447Snilay@cs.wisc.edu 8510447Snilay@cs.wisc.edu String::String(unsigned long value_) 8610447Snilay@cs.wisc.edu : string(toString<unsigned long>(value_)) 8710447Snilay@cs.wisc.edu {} 8810447Snilay@cs.wisc.edu 8910447Snilay@cs.wisc.edu String::String(float value_) 9010447Snilay@cs.wisc.edu : string(toString<float>(value_)) 9110447Snilay@cs.wisc.edu {} 9210447Snilay@cs.wisc.edu 9310447Snilay@cs.wisc.edu String::String(double value_) 9410447Snilay@cs.wisc.edu : string(toString<double>(value_)) 9510447Snilay@cs.wisc.edu {} 9610447Snilay@cs.wisc.edu 9710447Snilay@cs.wisc.edu String::String(bool value_) 9810447Snilay@cs.wisc.edu : string(toString<bool>(value_)) 9910447Snilay@cs.wisc.edu {} 10010447Snilay@cs.wisc.edu 10110447Snilay@cs.wisc.edu String::~String() 10210447Snilay@cs.wisc.edu {} 10310447Snilay@cs.wisc.edu 10410447Snilay@cs.wisc.edu String& String::trim() 10510447Snilay@cs.wisc.edu { 10610447Snilay@cs.wisc.edu // Remove leading and trailing whitespace 10710447Snilay@cs.wisc.edu static const char whitespace[] = " \n\t\v\r\f"; 10810447Snilay@cs.wisc.edu erase(0, find_first_not_of(whitespace)); 10910447Snilay@cs.wisc.edu erase(find_last_not_of(whitespace) + 1U); 11010447Snilay@cs.wisc.edu return (*this); 11110447Snilay@cs.wisc.edu } 11210447Snilay@cs.wisc.edu 11310447Snilay@cs.wisc.edu String& String::substitute(const String& str1_, const String& str2_) 11410447Snilay@cs.wisc.edu { 11510447Snilay@cs.wisc.edu size_t str1Size = str1_.size(); 11610447Snilay@cs.wisc.edu size_t str2Size = str2_.size(); 11710447Snilay@cs.wisc.edu 11810447Snilay@cs.wisc.edu size_t pos; 11910447Snilay@cs.wisc.edu pos = find(str1_); 12010447Snilay@cs.wisc.edu while(pos != string::npos) 12110447Snilay@cs.wisc.edu { 12210447Snilay@cs.wisc.edu replace(pos, str1Size, str2_); 12310447Snilay@cs.wisc.edu pos += str2Size; 12410447Snilay@cs.wisc.edu pos = find(str1_, pos); 12510447Snilay@cs.wisc.edu } 12610447Snilay@cs.wisc.edu return (*this); 12710447Snilay@cs.wisc.edu } 12810447Snilay@cs.wisc.edu 12910447Snilay@cs.wisc.edu vector<String> String::split(const char* delimiters_) const 13010447Snilay@cs.wisc.edu { 13110447Snilay@cs.wisc.edu vector<String> result; 13210447Snilay@cs.wisc.edu 13310447Snilay@cs.wisc.edu if(size() == 0) 13410447Snilay@cs.wisc.edu { 13510447Snilay@cs.wisc.edu return result; 13610447Snilay@cs.wisc.edu } 13710447Snilay@cs.wisc.edu 13810447Snilay@cs.wisc.edu size_t currPos, nextPos; 13910447Snilay@cs.wisc.edu currPos = 0; 14010447Snilay@cs.wisc.edu nextPos = find_first_of(delimiters_); 14110447Snilay@cs.wisc.edu while(1) 14210447Snilay@cs.wisc.edu { 14310447Snilay@cs.wisc.edu if(nextPos == string::npos) 14410447Snilay@cs.wisc.edu { 14510447Snilay@cs.wisc.edu if(currPos != size()) 14610447Snilay@cs.wisc.edu { 14710447Snilay@cs.wisc.edu result.push_back(substr(currPos)); 14810447Snilay@cs.wisc.edu } 14910447Snilay@cs.wisc.edu break; 15010447Snilay@cs.wisc.edu } 15110447Snilay@cs.wisc.edu 15210447Snilay@cs.wisc.edu if(nextPos != currPos) 15310447Snilay@cs.wisc.edu { 15410447Snilay@cs.wisc.edu result.push_back(substr(currPos, nextPos - currPos)); 15510447Snilay@cs.wisc.edu } 15610447Snilay@cs.wisc.edu currPos = nextPos + 1; 15710447Snilay@cs.wisc.edu nextPos = find_first_of(delimiters_, currPos); 15810447Snilay@cs.wisc.edu } 15910447Snilay@cs.wisc.edu 16010447Snilay@cs.wisc.edu return result; 16110447Snilay@cs.wisc.edu } 16210447Snilay@cs.wisc.edu 16310447Snilay@cs.wisc.edu vector<String> String::split(const String* delimiters_, unsigned int num_delimiters_) const 16410447Snilay@cs.wisc.edu { 16510447Snilay@cs.wisc.edu vector<String> result; 16610447Snilay@cs.wisc.edu 16710447Snilay@cs.wisc.edu if(size() == 0) 16810447Snilay@cs.wisc.edu { 16910447Snilay@cs.wisc.edu return result; 17010447Snilay@cs.wisc.edu } 17110447Snilay@cs.wisc.edu 17210447Snilay@cs.wisc.edu if(num_delimiters_ == 1) 17310447Snilay@cs.wisc.edu { 17410447Snilay@cs.wisc.edu size_t currPos, nextPos; 17510447Snilay@cs.wisc.edu currPos = 0; 17610447Snilay@cs.wisc.edu nextPos = find(delimiters_[0]); 17710447Snilay@cs.wisc.edu while(1) 17810447Snilay@cs.wisc.edu { 17910447Snilay@cs.wisc.edu if(nextPos == String::npos) 18010447Snilay@cs.wisc.edu { 18110447Snilay@cs.wisc.edu result.push_back(substr(currPos)); 18210447Snilay@cs.wisc.edu break; 18310447Snilay@cs.wisc.edu } 18410447Snilay@cs.wisc.edu 18510447Snilay@cs.wisc.edu if(nextPos != currPos) 18610447Snilay@cs.wisc.edu { 18710447Snilay@cs.wisc.edu result.push_back(substr(currPos, nextPos - currPos)); 18810447Snilay@cs.wisc.edu } 18910447Snilay@cs.wisc.edu currPos = nextPos + delimiters_[0].size(); 19010447Snilay@cs.wisc.edu nextPos = find(delimiters_[0], currPos); 19110447Snilay@cs.wisc.edu } 19210447Snilay@cs.wisc.edu } 19310447Snilay@cs.wisc.edu else 19410447Snilay@cs.wisc.edu { 19510447Snilay@cs.wisc.edu // Currently the length of the delimiters are not checked 19610447Snilay@cs.wisc.edu unsigned int delimiterLength = 0; 19710447Snilay@cs.wisc.edu size_t currPos, nextPos; 19810447Snilay@cs.wisc.edu currPos = 0; 19910447Snilay@cs.wisc.edu nextPos = size(); 20010447Snilay@cs.wisc.edu for(unsigned int i = 0; i < num_delimiters_; ++i) 20110447Snilay@cs.wisc.edu { 20210447Snilay@cs.wisc.edu size_t tempPos = find(delimiters_[i], currPos); 20310447Snilay@cs.wisc.edu if((tempPos != String::npos) && (tempPos < nextPos)) 20410447Snilay@cs.wisc.edu { 20510447Snilay@cs.wisc.edu nextPos = tempPos; 20610447Snilay@cs.wisc.edu delimiterLength = delimiters_[i].size(); 20710447Snilay@cs.wisc.edu } 20810447Snilay@cs.wisc.edu } 20910447Snilay@cs.wisc.edu while(1) 21010447Snilay@cs.wisc.edu { 21110447Snilay@cs.wisc.edu if((nextPos == String::npos) || (nextPos == size())) 21210447Snilay@cs.wisc.edu { 21310447Snilay@cs.wisc.edu result.push_back(substr(currPos)); 21410447Snilay@cs.wisc.edu break; 21510447Snilay@cs.wisc.edu } 21610447Snilay@cs.wisc.edu 21710447Snilay@cs.wisc.edu if(nextPos != currPos) 21810447Snilay@cs.wisc.edu { 21910447Snilay@cs.wisc.edu result.push_back(substr(currPos, nextPos - currPos)); 22010447Snilay@cs.wisc.edu } 22110447Snilay@cs.wisc.edu currPos = nextPos + delimiterLength; 22210447Snilay@cs.wisc.edu nextPos = size(); 22310447Snilay@cs.wisc.edu delimiterLength = 0; 22410447Snilay@cs.wisc.edu for(unsigned int i = 0; i < num_delimiters_; ++i) 22510447Snilay@cs.wisc.edu { 22610447Snilay@cs.wisc.edu size_t tempPos = find(delimiters_[i], currPos); 22710447Snilay@cs.wisc.edu if((tempPos != String::npos) && (tempPos < nextPos)) 22810447Snilay@cs.wisc.edu { 22910447Snilay@cs.wisc.edu nextPos = tempPos; 23010447Snilay@cs.wisc.edu delimiterLength = delimiters_[i].size(); 23110447Snilay@cs.wisc.edu } 23210447Snilay@cs.wisc.edu } 23310447Snilay@cs.wisc.edu } 23410447Snilay@cs.wisc.edu } 23510447Snilay@cs.wisc.edu return result; 23610447Snilay@cs.wisc.edu } 23710447Snilay@cs.wisc.edu 23810447Snilay@cs.wisc.edu vector<String> String::splitByString(const String& delimiter_) const 23910447Snilay@cs.wisc.edu { 24010447Snilay@cs.wisc.edu return split(&delimiter_, 1); 24110447Snilay@cs.wisc.edu } 24210447Snilay@cs.wisc.edu 24310447Snilay@cs.wisc.edu bool String::contain(const String& str_) const 24410447Snilay@cs.wisc.edu { 24510447Snilay@cs.wisc.edu return (find(str_) != String::npos); 24610447Snilay@cs.wisc.edu } 24710447Snilay@cs.wisc.edu 24810447Snilay@cs.wisc.edu const char* String::toCString() const 24910447Snilay@cs.wisc.edu { 25010447Snilay@cs.wisc.edu return this->c_str(); 25110447Snilay@cs.wisc.edu } 25210447Snilay@cs.wisc.edu 25310447Snilay@cs.wisc.edu int String::toInt() const 25410447Snilay@cs.wisc.edu { 25510447Snilay@cs.wisc.edu return fromString<int>(*this); 25610447Snilay@cs.wisc.edu } 25710447Snilay@cs.wisc.edu 25810447Snilay@cs.wisc.edu unsigned int String::toUInt() const 25910447Snilay@cs.wisc.edu { 26010447Snilay@cs.wisc.edu return fromString<unsigned int>(*this); 26110447Snilay@cs.wisc.edu } 26210447Snilay@cs.wisc.edu 26310447Snilay@cs.wisc.edu long String::toLong() const 26410447Snilay@cs.wisc.edu { 26510447Snilay@cs.wisc.edu return fromString<long>(*this); 26610447Snilay@cs.wisc.edu } 26710447Snilay@cs.wisc.edu 26810447Snilay@cs.wisc.edu unsigned long String::toULong() const 26910447Snilay@cs.wisc.edu { 27010447Snilay@cs.wisc.edu return fromString<unsigned long>(*this); 27110447Snilay@cs.wisc.edu } 27210447Snilay@cs.wisc.edu 27310447Snilay@cs.wisc.edu float String::toFloat() const 27410447Snilay@cs.wisc.edu { 27510447Snilay@cs.wisc.edu return fromString<float>(*this); 27610447Snilay@cs.wisc.edu } 27710447Snilay@cs.wisc.edu 27810447Snilay@cs.wisc.edu double String::toDouble() const 27910447Snilay@cs.wisc.edu { 28010447Snilay@cs.wisc.edu return fromString<double>(*this); 28110447Snilay@cs.wisc.edu } 28210447Snilay@cs.wisc.edu 28310447Snilay@cs.wisc.edu bool String::toBool() const 28410447Snilay@cs.wisc.edu { 28510447Snilay@cs.wisc.edu return fromString<bool>(*this); 28610447Snilay@cs.wisc.edu } 28710447Snilay@cs.wisc.edu 28810447Snilay@cs.wisc.edu String::operator const char*() const 28910447Snilay@cs.wisc.edu { 29010447Snilay@cs.wisc.edu return this->c_str(); 29110447Snilay@cs.wisc.edu } 29210447Snilay@cs.wisc.edu 29310447Snilay@cs.wisc.edu String::operator int() const 29410447Snilay@cs.wisc.edu { 29510447Snilay@cs.wisc.edu return fromString<int>(*this); 29610447Snilay@cs.wisc.edu } 29710447Snilay@cs.wisc.edu 29810447Snilay@cs.wisc.edu String::operator unsigned int() const 29910447Snilay@cs.wisc.edu { 30010447Snilay@cs.wisc.edu return fromString<unsigned int>(*this); 30110447Snilay@cs.wisc.edu } 30210447Snilay@cs.wisc.edu 30310447Snilay@cs.wisc.edu String::operator long() const 30410447Snilay@cs.wisc.edu { 30510447Snilay@cs.wisc.edu return fromString<long>(*this); 30610447Snilay@cs.wisc.edu } 30710447Snilay@cs.wisc.edu 30810447Snilay@cs.wisc.edu String::operator unsigned long() const 30910447Snilay@cs.wisc.edu { 31010447Snilay@cs.wisc.edu return fromString<unsigned long>(*this); 31110447Snilay@cs.wisc.edu } 31210447Snilay@cs.wisc.edu 31310447Snilay@cs.wisc.edu String::operator float() const 31410447Snilay@cs.wisc.edu { 31510447Snilay@cs.wisc.edu return fromString<float>(*this); 31610447Snilay@cs.wisc.edu } 31710447Snilay@cs.wisc.edu 31810447Snilay@cs.wisc.edu String::operator double() const 31910447Snilay@cs.wisc.edu { 32010447Snilay@cs.wisc.edu return fromString<double>(*this); 32110447Snilay@cs.wisc.edu } 32210447Snilay@cs.wisc.edu 32310447Snilay@cs.wisc.edu String::operator bool() const 32410447Snilay@cs.wisc.edu { 32510447Snilay@cs.wisc.edu return fromString<bool>(*this); 32610447Snilay@cs.wisc.edu } 32710447Snilay@cs.wisc.edu 32810447Snilay@cs.wisc.edu String& String::operator=(char c_) 32910447Snilay@cs.wisc.edu { 33010447Snilay@cs.wisc.edu this->assign(1, c_); 33110447Snilay@cs.wisc.edu return *this; 33210447Snilay@cs.wisc.edu } 33310447Snilay@cs.wisc.edu 33410447Snilay@cs.wisc.edu std::istream& safeGetline(std::istream& is_, String& str_) 33510447Snilay@cs.wisc.edu { 33610447Snilay@cs.wisc.edu str_.clear(); 33710447Snilay@cs.wisc.edu 33810447Snilay@cs.wisc.edu // The characters in the stream are read one-by-one using a std::streambuf. 33910447Snilay@cs.wisc.edu // That is faster than reading them one-by-one using the std::istream. 34010447Snilay@cs.wisc.edu // Code that uses streambuf this way must be guarded by a sentry object. 34110447Snilay@cs.wisc.edu // The sentry object performs various tasks, 34210447Snilay@cs.wisc.edu // such as thread synchronization and updating the stream state. 34310447Snilay@cs.wisc.edu 34410447Snilay@cs.wisc.edu std::istream::sentry se(is_, true); 34510447Snilay@cs.wisc.edu std::streambuf* sb = is_.rdbuf(); 34610447Snilay@cs.wisc.edu 34710447Snilay@cs.wisc.edu while(1) 34810447Snilay@cs.wisc.edu { 34910447Snilay@cs.wisc.edu int c = sb->sbumpc(); 35010447Snilay@cs.wisc.edu switch(c) 35110447Snilay@cs.wisc.edu { 35210447Snilay@cs.wisc.edu case '\r': 35310447Snilay@cs.wisc.edu c = sb->sgetc(); 35410447Snilay@cs.wisc.edu if(c == '\n') 35510447Snilay@cs.wisc.edu sb->sbumpc(); 35610447Snilay@cs.wisc.edu return is_; 35710447Snilay@cs.wisc.edu case '\n': 35810447Snilay@cs.wisc.edu return is_; 35910447Snilay@cs.wisc.edu case EOF: 36010447Snilay@cs.wisc.edu is_.setstate(std::ios_base::failbit|std::ios_base::eofbit); 36110447Snilay@cs.wisc.edu return is_; 36210447Snilay@cs.wisc.edu default: 36310447Snilay@cs.wisc.edu str_ += String(1, (char)c); 36410447Snilay@cs.wisc.edu } 36510447Snilay@cs.wisc.edu } 36610447Snilay@cs.wisc.edu } 36710447Snilay@cs.wisc.edu} // namespace LibUtil 36810447Snilay@cs.wisc.edu 369