169 lines
4.0 KiB
C++
169 lines
4.0 KiB
C++
#include "breeze/Text.hpp"
|
|
|
|
#include <cctype>
|
|
|
|
#include <algorithm>
|
|
|
|
namespace breeze::text
|
|
{
|
|
|
|
std::string trim(std::string_view s)
|
|
{
|
|
std::size_t b = 0;
|
|
std::size_t e = s.size();
|
|
while (b < e && std::isspace(static_cast<unsigned char>(s[b])))
|
|
++b;
|
|
while (e > b && std::isspace(static_cast<unsigned char>(s[e - 1])))
|
|
--e;
|
|
return std::string(s.substr(b, e - b));
|
|
}
|
|
|
|
std::vector<std::string> split(std::string_view s, char delimiter)
|
|
{
|
|
std::vector<std::string> out;
|
|
std::size_t start = 0;
|
|
while (true)
|
|
{
|
|
std::size_t pos = s.find(delimiter, start);
|
|
if (pos == std::string_view::npos)
|
|
{
|
|
out.emplace_back(s.substr(start));
|
|
return out;
|
|
}
|
|
out.emplace_back(s.substr(start, pos - start));
|
|
start = pos + 1;
|
|
}
|
|
}
|
|
|
|
std::vector<std::string> splitLines(std::string_view s)
|
|
{
|
|
std::vector<std::string> lines = split(s, '\n');
|
|
for (std::string& line : lines)
|
|
{
|
|
if (!line.empty() && line.back() == '\r')
|
|
line.pop_back();
|
|
}
|
|
if (!lines.empty() && lines.back().empty())
|
|
lines.pop_back();
|
|
return lines;
|
|
}
|
|
|
|
std::string join(const std::vector<std::string>& parts, std::string_view separator)
|
|
{
|
|
std::string out;
|
|
for (std::size_t i = 0; i < parts.size(); ++i)
|
|
{
|
|
if (i != 0)
|
|
out += separator;
|
|
out += parts[i];
|
|
}
|
|
return out;
|
|
}
|
|
|
|
std::string lower(std::string_view s)
|
|
{
|
|
std::string out(s);
|
|
std::transform(out.begin(), out.end(), out.begin(),
|
|
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
|
|
return out;
|
|
}
|
|
|
|
bool startsWith(std::string_view s, std::string_view prefix)
|
|
{
|
|
return s.size() >= prefix.size() && s.substr(0, prefix.size()) == prefix;
|
|
}
|
|
|
|
bool endsWith(std::string_view s, std::string_view suffix)
|
|
{
|
|
return s.size() >= suffix.size() && s.substr(s.size() - suffix.size()) == suffix;
|
|
}
|
|
|
|
std::string replaceAll(std::string s, std::string_view from, std::string_view to)
|
|
{
|
|
if (from.empty())
|
|
return s;
|
|
std::size_t pos = 0;
|
|
while ((pos = s.find(from, pos)) != std::string::npos)
|
|
{
|
|
s.replace(pos, from.size(), to);
|
|
pos += to.size();
|
|
}
|
|
return s;
|
|
}
|
|
|
|
std::string snakeCase(std::string_view s)
|
|
{
|
|
std::string out;
|
|
for (std::size_t i = 0; i < s.size(); ++i)
|
|
{
|
|
unsigned char c = static_cast<unsigned char>(s[i]);
|
|
if (c == '-' || c == ' ' || c == '.')
|
|
c = '_';
|
|
if (std::isupper(c))
|
|
{
|
|
bool prevLowerOrDigit =
|
|
i > 0 && (std::islower(static_cast<unsigned char>(s[i - 1])) ||
|
|
std::isdigit(static_cast<unsigned char>(s[i - 1])));
|
|
bool acronymEnds = i > 0 && std::isupper(static_cast<unsigned char>(s[i - 1])) &&
|
|
i + 1 < s.size() &&
|
|
std::islower(static_cast<unsigned char>(s[i + 1]));
|
|
if ((prevLowerOrDigit || acronymEnds) && !out.empty() && out.back() != '_')
|
|
out += '_';
|
|
out += static_cast<char>(std::tolower(c));
|
|
}
|
|
else
|
|
{
|
|
if (c == '_' && (out.empty() || out.back() == '_'))
|
|
continue;
|
|
out += static_cast<char>(c);
|
|
}
|
|
}
|
|
while (!out.empty() && out.back() == '_')
|
|
out.pop_back();
|
|
return out;
|
|
}
|
|
|
|
std::string normalized(std::string_view s)
|
|
{
|
|
std::string out;
|
|
for (char c : s)
|
|
{
|
|
unsigned char u = static_cast<unsigned char>(c);
|
|
if (std::isalnum(u))
|
|
out += static_cast<char>(std::tolower(u));
|
|
}
|
|
return out;
|
|
}
|
|
|
|
bool isName(std::string_view s, bool allowDash)
|
|
{
|
|
if (s.empty() || !std::isalpha(static_cast<unsigned char>(s[0])))
|
|
return false;
|
|
return std::all_of(s.begin(), s.end(),
|
|
[allowDash](char c)
|
|
{
|
|
unsigned char u = static_cast<unsigned char>(c);
|
|
return std::isalnum(u) || c == '_' || (allowDash && c == '-');
|
|
});
|
|
}
|
|
|
|
bool isTargetId(std::string_view s)
|
|
{
|
|
if (s.empty() || !(std::isalpha(static_cast<unsigned char>(s[0])) || s[0] == '_'))
|
|
return false;
|
|
return std::all_of(s.begin(), s.end(),
|
|
[](char c)
|
|
{
|
|
unsigned char u = static_cast<unsigned char>(c);
|
|
return std::isalnum(u) || c == '_' || c == '.' || c == '+' ||
|
|
c == '-' || c == ':';
|
|
});
|
|
}
|
|
|
|
std::string orNone(std::string_view s)
|
|
{
|
|
return s.empty() ? std::string("<none>") : std::string(s);
|
|
}
|
|
|
|
}
|