Restructure project, start importing sc3 code.
This commit is contained in:
235
src/sl/StringUtil.cc
Normal file
235
src/sl/StringUtil.cc
Normal file
@@ -0,0 +1,235 @@
|
||||
///
|
||||
/// \file StringUtil.cc
|
||||
/// \author K. Isom <kyle@imap.cc>
|
||||
/// \date 2023-10-12
|
||||
/// \brief Utilities for working with strings.
|
||||
///
|
||||
/// Copyright 2023 K. Isom <kyle@imap.cc>
|
||||
///
|
||||
/// Permission to use, copy, modify, and/or distribute this software for
|
||||
/// any purpose with or without fee is hereby granted, provided that
|
||||
/// the above copyright notice and this permission notice appear in all /// copies.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
/// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
/// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
/// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
/// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
|
||||
/// OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
/// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
/// PERFORMANCE OF THIS SOFTWARE.
|
||||
///
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include <scsl/StringUtil.h>
|
||||
|
||||
|
||||
namespace scsl {
|
||||
/// namespace U contains utilities.
|
||||
namespace U {
|
||||
|
||||
/// namespace S contains string-related functions.
|
||||
namespace S {
|
||||
|
||||
|
||||
std::vector<std::string>
|
||||
SplitKeyValuePair(std::string line, std::string delimiter)
|
||||
{
|
||||
auto pair = SplitN(line, delimiter, 2);
|
||||
|
||||
if (pair.size() == 0) {
|
||||
return {"", ""};
|
||||
} else if (pair.size() == 1) {
|
||||
return {pair[0], ""};
|
||||
}
|
||||
|
||||
assert(pair.size() == 2);
|
||||
auto key = pair[0];
|
||||
auto val = pair[1];
|
||||
|
||||
TrimWhitespace(key);
|
||||
TrimWhitespace(val);
|
||||
return {key, val};
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::string>
|
||||
SplitKeyValuePair(std::string line, char delimiter)
|
||||
{
|
||||
std::string sDelim;
|
||||
|
||||
sDelim.push_back(delimiter);
|
||||
return SplitKeyValuePair(line, sDelim);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TrimLeadingWhitespace(std::string &s)
|
||||
{
|
||||
s.erase(s.begin(),
|
||||
std::find_if(s.begin(), s.end(),
|
||||
[](unsigned char ch) {
|
||||
return !std::isspace(ch);
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TrimTrailingWhitespace(std::string &s)
|
||||
{
|
||||
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
|
||||
return !std::isspace(ch);
|
||||
}).base(), s.end());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TrimWhitespace(std::string &s)
|
||||
{
|
||||
TrimLeadingWhitespace(s);
|
||||
TrimTrailingWhitespace(s);
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
TrimLeadingWhitespaceDup(std::string s)
|
||||
{
|
||||
TrimLeadingWhitespace(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
TrimTrailingWhitespaceDup(std::string s)
|
||||
{
|
||||
TrimTrailingWhitespace(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
TrimWhitespaceDup(std::string s)
|
||||
{
|
||||
TrimWhitespace(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::string>
|
||||
SplitN(std::string s, std::string delim, size_t maxCount)
|
||||
{
|
||||
std::vector<std::string> parts;
|
||||
size_t ss = 0;
|
||||
size_t se = 0;
|
||||
|
||||
for (ss = 0; s.size() != 0 && ss < s.size(); ss++) {
|
||||
se = s.find(delim, ss);
|
||||
if ((maxCount > 0) && (parts.size() == maxCount - 1)) {
|
||||
se = s.size();
|
||||
} else if (se == std::string::npos) {
|
||||
se = s.size();
|
||||
}
|
||||
|
||||
auto length = se - ss;
|
||||
parts.push_back(s.substr(ss, length));
|
||||
ss = se;
|
||||
}
|
||||
|
||||
return parts;
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::string>
|
||||
WrapText(std::string line, size_t lineLength)
|
||||
{
|
||||
std::vector<std::string> wrapped;
|
||||
auto parts = SplitN(line, " ", 0);
|
||||
|
||||
for (auto &part: parts) {
|
||||
TrimWhitespace(part);
|
||||
|
||||
}
|
||||
|
||||
std::string wLine;
|
||||
for (auto word: parts) {
|
||||
if (word.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((wLine.size() + word.size() + 1) > lineLength) {
|
||||
wrapped.push_back(wLine);
|
||||
wLine.clear();
|
||||
}
|
||||
|
||||
if (wLine.size() > 0) {
|
||||
wLine += " ";
|
||||
}
|
||||
wLine += word;
|
||||
}
|
||||
|
||||
if (wLine.size() > 0) {
|
||||
wrapped.push_back(wLine);
|
||||
}
|
||||
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WriteTabIndented(std::ostream &os, std::vector<std::string> lines,
|
||||
int tabStop, bool indentFirst)
|
||||
{
|
||||
std::string indent(tabStop, '\t');
|
||||
|
||||
for (size_t i = 0; i < lines.size(); i++) {
|
||||
if (i > 0 || indentFirst) {
|
||||
os << indent;
|
||||
}
|
||||
os << lines[i] << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WriteTabIndented(std::ostream &os, std::string line, size_t maxLength,
|
||||
int tabStop, bool indentFirst)
|
||||
{
|
||||
auto lines = WrapText(line, maxLength);
|
||||
WriteTabIndented(os, lines, tabStop, indentFirst);
|
||||
}
|
||||
|
||||
|
||||
std::ostream &
|
||||
VectorToString(std::ostream &os, const std::vector<std::string> &svec)
|
||||
{
|
||||
os << "(";
|
||||
os << svec.size();
|
||||
os << ")";
|
||||
os << "{";
|
||||
|
||||
for (size_t i = 0; i < svec.size(); i++) {
|
||||
if (i > 0) { os << ", "; }
|
||||
os << svec[i];
|
||||
}
|
||||
|
||||
os << "}";
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
VectorToString(const std::vector<std::string> &svec)
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
VectorToString(ss, svec);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
||||
} // namespace S
|
||||
} // namespace U
|
||||
} // namespace scsl
|
||||
Reference in New Issue
Block a user