Files
StorytellersBestFriend/sbf-cpp/Utils.cpp
Tom Hicks dd96f59f2b temp
2025-06-30 13:48:02 -07:00

184 lines
5.3 KiB
C++

#define _XOPEN_SOURCE_EXTENDED
#include "Utils.h"
#include <algorithm>
#include <cstdint>
#include <cstdio>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace SBF;
namespace SBF {
namespace {
using std::ostringstream;
using std::string;
using std::vector;
} // End namespace
vector<string> WordWrap(const string& text, const size_t max_width) {
vector<string> lines;
string output = "";
string thisLine = "";
string nextChunk = "";
int32_t thisLineStartPosition = 0;
int32_t thisLineCurrentPosition = 0;
int32_t nextSpace = -1;
int32_t textLength = text.size();
size_t thisLineLength = 0;
bool done = false;
while (!done) {
nextSpace = GetIndexOf(text, " ", thisLineCurrentPosition);
if (nextSpace < 0) {
nextSpace = textLength;
}
nextChunk = GetSubstring(text, thisLineCurrentPosition, nextSpace - thisLineCurrentPosition);
auto nextChunkLength = nextChunk.size();
if (nextChunkLength > 0) {
auto needsSpace = thisLine.size() > 0;
if (needsSpace) {
thisLine = thisLine + " ";
}
thisLineLength = thisLine.size();
if (nextChunkLength > max_width) {
nextChunk = GetSubstring(text, thisLineCurrentPosition, max_width - thisLineLength);
nextSpace = thisLineStartPosition + max_width;
thisLine = thisLine + nextChunk;
thisLineCurrentPosition = nextSpace;
} else if (thisLineLength + nextChunkLength > max_width) {
thisLine = MakeFitL(thisLine, max_width, L' ');
} else {
thisLine = thisLine + nextChunk;
thisLineCurrentPosition = nextSpace + 1;
}
thisLineLength = thisLine.size();
} else {
thisLineCurrentPosition = nextSpace + 1;
}
if (thisLineLength >= max_width || thisLineCurrentPosition > textLength) {
if (thisLineCurrentPosition > textLength) {
done = true;
}
thisLine = MakeFitL(thisLine, max_width, L'_');
output += thisLine + (done ? "" : "\n");
lines.push_back(thisLine);
thisLine = "";
thisLineLength = thisLine.size();
thisLineStartPosition = thisLineCurrentPosition;
}
}
return lines;
}
string RepeatChar(const size_t length, const char ch) {
if (ch == '\0') {
return RepeatChar(length, ' ');
}
string str = "";
for (size_t i = 0; i < length; i++) {
str += ch;
}
return str;
}
string Left(const string& text, const size_t length) {
return text.substr(0, length);
}
string Right(const string& text, const size_t length) {
size_t text_length = text.size();
size_t starting_position = text_length - length;
if (text_length >= length) {
return text.substr(starting_position);
} else {
return text;
}
}
string MakeFitC(const string& text, const size_t length, const char pad_character) {
size_t text_length = text.size();
size_t left_pad_length = length >= text_length ? (length - text_length) / 2 : 0;
size_t right_pad_length = (length >= text_length + left_pad_length) ? (length - text_length - left_pad_length) : 0;
string left_pad = RepeatChar(left_pad_length, pad_character != '\0' ? pad_character : ' ');
string right_pad = RepeatChar(right_pad_length, pad_character != '\0' ? pad_character : ' ');
size_t total_chop = (text_length >= length) ? text_length - length : 0;
size_t left_chop = total_chop / 2; // + 1
string ret = left_pad + (text == "" ? "" : text.substr(left_chop, length)) + right_pad;
return ret;
}
std::string MakeFitB(const std::string& prefix,
const std::string& suffix,
const size_t length,
const char pad_character) {
return MakeFitL(MakeFitL(prefix, length - suffix.size(), pad_character != '\0' ? pad_character : ' ') + suffix,
length,
pad_character != '\0' ? pad_character : ' ');
}
string MakeFitL(const string& text, const size_t length, const char pad_character) {
return Left(text + RepeatChar(length, pad_character != '\0' ? pad_character : ' '), length);
}
string MakeFitR(const string& text, const size_t length, const char pad_character) {
return Right(RepeatChar(length, pad_character != '\0' ? pad_character : ' ') + text, length);
}
string GetSubstring(const string& text, const size_t start, const size_t length) {
return text.substr(std::min<size_t>(start, text.length()), std::max<size_t>(length, 0));
}
size_t GetIndexOf(const string& text, const string& search, const size_t start) {
return text.find(search, start);
}
bool is_whitespace(char ch) {
return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' || ch == '\f' || ch == '\v';
}
string LeftTrim(const string& text) {
if (text == "") {
return "";
}
size_t index = 0;
size_t length = text.size();
while (index < length) {
if (is_whitespace(text.at(index))) {
index++;
} else {
return text.substr(index);
}
}
return "";
}
string RightTrim(const string& text) {
if (text == "") {
return "";
}
size_t last_index = text.size() - 1;
size_t index = last_index;
while (index != string::npos) {
if (is_whitespace(text.at(index))) {
index--;
} else {
return text.substr(0, index + 1);
}
}
return "";
}
string ToLower(const string& text) {
ostringstream os;
for_each(text.begin(), text.end(), [&os](unsigned char ch) { os << (char)tolower(ch); });
return os.str();
}
} // End namespace SBF