uox3/source/StringUtility.cpp
2022-03-05 13:25:29 -05:00

431 lines
11 KiB
C++

//
// StringUtility.cpp
// Infinity
//
//
#include "StringUtility.hpp"
#include <cctype>
#include <regex>
#include <locale>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <stdexcept>
#include <filesystem>
#include <codecvt>
using namespace std::string_literals;
namespace oldstrutil {
//=====================================================================
// Lowercase the string
std::string lower(const std::string &value){
auto rvalue = value ;
std::transform(rvalue.begin(), rvalue.end(),rvalue.begin(),
[](unsigned char c){ return std::tolower(c);});
return rvalue;
}
//=====================================================================
// Uppercase the string
std::string upper(const std::string &value){
auto rvalue = value ;
std::transform(rvalue.begin(), rvalue.end(),rvalue.begin(),
[](unsigned char c){ return std::toupper(c);});
return rvalue;
}
//=====================================================================
// Remove leading whitespace
std::string ltrim(const std::string &value){
auto count = 0 ;
for (auto it = value.begin(); it != value.end();it++) {
if (!isspace(*it)){
return value.substr(count) ;
}
else {
count++;
}
}
return std::string();
}
//=====================================================================
// Remove trailing whitespace
std::string rtrim(const std::string &value){
auto count = 0 ;
for (auto it = value.rbegin(); it != value.rend();it++) {
if (!isspace(*it)){
return value.substr(0,value.size()-count);
}
else {
count++;
}
}
return std::string();
}
//=====================================================================
// Remove leading/trailing whitespace
std::string trim(const std::string &value) {
return rtrim(ltrim(value));
}
//=====================================================================
// Remove leading/trailing whitepace, and reduce all other whitespace to one " "
std::string simplify(const std::string &value){
auto tvalue = trim(value) ;
auto rvalue = ""s ;
auto toggle = false ;
for (auto &c :tvalue){
if (isspace(c)) {
if (!toggle){
rvalue = rvalue + c ;
toggle = true ;
}
}
else {
toggle = false ;
rvalue = rvalue + c ;
}
}
return rvalue ;
}
//=====================================================================
// Removing everything after a delimiter. Normally "//" for comments
std::string removeTrailing(const std::string& value,const std::string& delim){
auto loc = value.find(delim) ;
if (loc == std::string::npos){
return value ;
}
return value.substr(0,loc) ;
}
//=====================================================================
// Return the values between two delimitors.
std::string contents(const std::string &value,const std::string& startdelim, const std::string &enddelim,std::string::size_type location){
auto loc = value.find_first_of(startdelim,location);
if (loc == std::string::npos){
return std::string();
}
auto start_search = loc + startdelim.size() ;
if (start_search >= value.size()){
return std::string();
}
auto end = value.find_first_of(enddelim,start_search);
if (end == std::string::npos){
return std::string();
}
return value.substr(start_search,end-start_search);
}
//=====================================================================
// Split a string based on a separator
std::tuple<std::string,std::string> split(const std::string &value, const std::string &sep){
auto loc = value.find(sep) ;
auto next = loc + sep.size();
if ((loc == std::string::npos) || (next >= value.size())){
return std::make_tuple(trim(value),""s);
}
else {
return std::make_tuple(trim(value.substr(0,loc)),trim(value.substr(next)));
}
}
//+++++++++++++++++++++++++++++++++++++
std::string format(std::size_t maxsize, const std::string fmtstring,...) {
std::va_list argptr ;
va_start(argptr, fmtstring);
auto test = oldstrutil::format(fmtstring,argptr) ;
if (maxsize>0){
if (test.size() > maxsize) {
test = test.substr(0,maxsize);
}
}
return test ;
}
//++++++++++++++++++++++++++++++++++++++
std::string format(std::size_t maxsize,const std::string fmtstring,va_list& list){
auto temp = oldstrutil::format(fmtstring,list);
if (maxsize>0){
if (temp.size() > maxsize) {
temp = temp.substr(0,maxsize);
}
}
return temp ;
}
//+++++++++++++++++++++++++++++++++++++
std::string format(const std::string fmtstring,...) {
std::va_list argptr ;
va_start(argptr, fmtstring);
return oldstrutil::format(fmtstring,argptr) ;
}
//++++++++++++++++++++++++++++++++++++++
std::string format(const std::string fmtstring,va_list& list){
constexpr std::uintmax_t buffersize = 4096 ;
char msg[buffersize];
std::memset(msg, 0,buffersize);
std::vsnprintf(msg, buffersize, fmtstring.c_str(), list);
va_end(list);
return std::string(msg) ;
}
//++++++++++++++++++++++++++++++++++++++++
std::string formatMessage(const std::string& uformat,const std::string& data){
auto values = oldstrutil::sections(data,",");
auto format = uformat ;
auto pos = format.find_first_of("%") ;
if (pos == std::string::npos) {
return format ;
}
auto index = 0 ;
while ( pos != std::string::npos) {
if (index >= values.size() ){
break;
}
auto temp = values[index];
index++;
// now, we assume the formatting was done before the string, so basically we
// replace the format specifier, with the string
format.replace(pos, 2, temp);
pos = format.find_first_of("%") ;
}
return format ;
}
//++++++++++++++++++++++++++++++++++++++++++
std::vector<std::string> sections(const std::string& value, const std::string& sep, std::string::size_type start, std::string::size_type end ) {
std::vector<std::string> rvalue ;
auto pos = value.find(sep,start) ;
while (pos < end) {
if ((pos - start) > 0) {
auto potential = value.substr(start,pos - start) ;
rvalue.push_back(potential);
start = pos+sep.size() ;
}
else if (pos == start) {
rvalue.push_back("");
start += sep.size() ;
}
pos = value.find(sep,start) ;
}
rvalue.push_back(value.substr(start,pos - start)) ;
return rvalue ;
}
//++++++++++++++++++++++++++++++++++++++++++
std::uintmax_t sectionCount(const std::string& value, const std::string& sep, std::string::size_type start , std::string::size_type end ){
return oldstrutil::sections(value,sep,start,end).size() ;
}
//++++++++++++++++++++++++++++++++++++++++++
std::string indexSection(const std::string& value, std::uintmax_t sectionindex,const std::string& sep, std::string::size_type start , std::string::size_type end ){
auto sec = oldstrutil::sections(value,sep,start,end) ;
if (sec.size() <= sectionindex) {
return sec[sectionindex];
}
throw std::runtime_error(oldstrutil::format("Section index %ul exceeded size %ul from sections %s",sectionindex,sec.size(),value.c_str()));
}
//+++++++++++++++++++++++++++++++++++++++++
std::string extractSection( const std::string& value, const std::string& sep, std::string::size_type start, std::string::size_type stop )
{
std::string data ;
int count = -1 ;
size_t startoffset = 0 ;
size_t stopoffset = 0 ;
bool match = false ;
stopoffset = value.find(sep,startoffset);
while ( startoffset != std::string::npos )
{
count++ ;
if( count == start )
{
match = true ;
// We dont return the seperator, so jump over it
size_t tempoffset = startoffset ;
while ( stopoffset != std::string::npos )
{
if( count == stop )
{
break ;
}
else
{
tempoffset = stopoffset + sep.length() ;
stopoffset = value.find(sep,tempoffset) ;
count++ ;
}
}
break ;
}
else
{
if( stopoffset != std::string::npos )
startoffset = stopoffset+ sep.length();
else
startoffset = static_cast<size_t>(std::string::npos) ;
stopoffset = value.find(sep,startoffset) ;
}
}
if( match )
{
size_t length = stopoffset - startoffset ;
if( stopoffset == std::string::npos ){
length = value.length() - startoffset ;
}
data = value.substr(startoffset,length) ;
}
return data ;
}
//++++++++++++++++++++++++++++++++++++++++++
std::vector<std::string> breakSize(std::size_t maxsize, const std::string& input){
auto working = input ;
std::vector<std::string> total ;
while (working.size() > maxsize) {
auto portion = working.substr(0,maxsize);
working.replace(0, maxsize, "");
total.push_back(portion);
}
if (!working.empty()){
total.push_back(working);
}
return total ;
}
//++++++++++++++++++++++++++++++++++++++++++
std::string fixDirectory(const std::string& base){
std::string value = "\\" ;
std::string::size_type index = 0 ;
auto data = trim(base) ;
while ( (index = data.find( value, index ) ) != std::string::npos )
{
data = data.replace(index,1,"/") ;
}
if( data.find_last_of("/") != data.size()-1 )
{
data = data+"/" ;
}
return data ;
}
//+++++++++++++++++++++++++++++++++++++++++++
std::string replaceSlash( std::string& data )
{
std::string value = "\\" ;
std::string::size_type index = 0 ;
while ( (index = data.find( value, index ) ) != std::string::npos )
{
data = data.replace(index,1,"/") ;
}
return data ;
}
std::string number(char n, int base){
std::stringstream conversion ;
auto value = static_cast<std::int16_t>(n);
switch (base) {
case 10:
conversion << std::dec << value ;
break;
case 16:
conversion <<std::hex << value <<std::dec;
break;
case 8:
conversion << std::oct << value <<std::dec;
break;
default:
conversion << std::dec << value ;
break;
}
return conversion.str() ;
}
std::string number(unsigned char n, int base){
std::stringstream conversion ;
auto value = static_cast<std::uint16_t>(n);
switch (base) {
case 10:
conversion << std::dec << value ;
break;
case 16:
conversion <<std::hex << value <<std::dec;
break;
case 8:
conversion << std::oct << value <<std::dec;
break;
default:
conversion << std::dec << value ;
break;
}
return conversion.str() ;
}
#if defined( _MSC_VER )
#pragma warning(push)
#pragma warning(disable : 4996)
#endif
// Decode a UTF8 string into a wstring
std::wstring stringToWstring( const std::string& t_str )
{
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> converter;
// use converter (.to_bytes: wstr->str, .from_bytes: str->wstr)
try {
auto rvalue = converter.from_bytes(t_str);
return rvalue;
}
catch( ... ) {
return L"";
}
}
#if defined( _MSC_VER )
#pragma warning(pop)
#endif
// "Encode" a wstring into UTF8, while retaining any special wide characters
std::string wStringToString( const std::wstring& t_str )
{
const size_t stringLen = t_str.size();
std::string resultString;
for( size_t i = 0; i < stringLen; ++i )
resultString.push_back(static_cast<char>(t_str[i]));
return resultString;
}
// Convert from string to wstring and back to string
std::string stringToWstringToString( const std::string& t_str )
{
return wStringToString( stringToWstring( t_str ));
}
}