2023-10-16 09:18:09 +00:00
|
|
|
///
|
|
|
|
/// \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>
|
2023-10-15 00:56:26 +00:00
|
|
|
#include <iostream>
|
|
|
|
#include <sstream>
|
|
|
|
|
|
|
|
#include "StringUtil.h"
|
|
|
|
|
|
|
|
|
2023-10-15 01:38:01 +00:00
|
|
|
namespace scsl {
|
2023-10-15 00:56:26 +00:00
|
|
|
/// 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)
|
|
|
|
{
|
2023-10-16 09:18:09 +00:00
|
|
|
auto pair = SplitN(line, delimiter, 2);
|
|
|
|
|
|
|
|
if (pair.size() == 0) {
|
|
|
|
return {"", ""};
|
|
|
|
} else if (pair.size() == 1) {
|
|
|
|
return {pair[0], ""};
|
2023-10-15 00:56:26 +00:00
|
|
|
}
|
|
|
|
|
2023-10-16 09:18:09 +00:00
|
|
|
assert(pair.size() == 2);
|
|
|
|
auto key = pair[0];
|
|
|
|
auto val = pair[1];
|
|
|
|
|
2023-10-15 00:56:26 +00:00
|
|
|
TrimWhitespace(key);
|
|
|
|
TrimWhitespace(val);
|
|
|
|
return {key, val};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<std::string>
|
|
|
|
SplitKeyValuePair(std::string line, char delimiter)
|
|
|
|
{
|
2023-10-16 09:18:09 +00:00
|
|
|
std::string sDelim;
|
2023-10-15 00:56:26 +00:00
|
|
|
|
2023-10-16 09:18:09 +00:00
|
|
|
sDelim.push_back(delimiter);
|
|
|
|
return SplitKeyValuePair(line, sDelim);
|
2023-10-15 00:56:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-10-16 09:18:09 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-10-15 00:56:26 +00:00
|
|
|
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++) {
|
2023-10-16 09:18:09 +00:00
|
|
|
if (i > 0) { os << ", "; }
|
2023-10-15 00:56:26 +00:00
|
|
|
os << svec[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
os << "}";
|
|
|
|
return os;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::string
|
|
|
|
VectorToString(const std::vector<std::string> &svec)
|
|
|
|
{
|
2023-10-16 09:18:09 +00:00
|
|
|
std::stringstream ss;
|
2023-10-15 00:56:26 +00:00
|
|
|
|
|
|
|
VectorToString(ss, svec);
|
|
|
|
return ss.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace S
|
|
|
|
} // namespace U
|
2023-10-15 01:38:01 +00:00
|
|
|
} // namespace scsl
|