blob: 472be802ab8843e944a3e7c52cb184c3d47c6703 [file] [log] [blame] [edit]
/* 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