This commit is contained in:
LOSEARDES77 2025-05-11 11:08:55 +02:00 committed by GitHub
commit 9bdfa71017
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 67 additions and 16 deletions

View file

@ -8,12 +8,22 @@ namespace Hyprutils {
class CVarList {
public:
/** Split string into arg list
@param lastArgNo stop splitting after argv reaches maximum size, last arg will contain rest of unsplit args
@param delim if delimiter is 's', use std::isspace
@param removeEmpty remove empty args from argv
* @param in The string to split
* @param lastArgNo The number of arguments to split into
* @param delim The delimiter to use for splitting
* @param removeEmpty Whether to remove empty arguments
*/
CVarList(const std::string& in, const size_t lastArgNo = 0, const char delim = ',', const bool removeEmpty = false);
/** Split string into arg list with escape handling
* @param in The string to split
* @param lastArgNo The number of arguments to split into
* @param delim The delimiter to use for splitting
* @param removeEmpty Whether to remove empty arguments
* @param handleEscape Whether to handle escape characters
*/
CVarList(const std::string& in, const size_t lastArgNo, const char delim, const bool removeEmpty, const bool handleEscape);
~CVarList() = default;
size_t size() const {

View file

@ -5,24 +5,56 @@
using namespace Hyprutils::String;
Hyprutils::String::CVarList::CVarList(const std::string& in, const size_t lastArgNo, const char delim, const bool removeEmpty) {
if (!removeEmpty && in.empty())
// Original constructor calls the extended one with handleEscape = false
Hyprutils::String::CVarList::CVarList(const std::string& in, const size_t lastArgNo, const char delim, const bool removeEmpty) :
CVarList(in, lastArgNo, delim, removeEmpty, false) {}
// Extended constructor with escape handling parameter
Hyprutils::String::CVarList::CVarList(const std::string& in, const size_t lastArgNo, const char delim, const bool removeEmpty, const bool handleEscape) {
if (!removeEmpty && in.empty()) {
m_vArgs.emplace_back("");
return;
}
std::string args{in};
size_t idx = 0;
size_t pos = 0;
std::ranges::replace_if(args, [&](const char& c) { return delim == 's' ? std::isspace(c) : c == delim; }, 0);
std::vector<std::pair<size_t, size_t>> argIndices;
size_t currentStart = 0;
size_t idx = 0;
for (const auto& s : args | std::views::split(0)) {
if (removeEmpty && s.empty())
for (size_t i = 0; i < in.length(); ++i) {
if (handleEscape && in[i] == '\\' && i + 1 < in.length()) {
i++;
continue;
if (++idx == lastArgNo) {
m_vArgs.emplace_back(trim(in.substr(pos)));
break;
}
pos += s.size() + 1;
m_vArgs.emplace_back(trim(s.data()));
const char c = in[i];
const bool isDelim = (delim == 's' ? std::isspace(c) : c == delim);
if (isDelim) {
if (!removeEmpty || i > currentStart) {
argIndices.emplace_back(currentStart, i);
idx++;
}
currentStart = i + 1;
if (idx == lastArgNo - 1) {
argIndices.emplace_back(i + 1, in.length());
break;
}
}
}
if (currentStart < in.length() && (!removeEmpty || currentStart < in.length()))
argIndices.emplace_back(currentStart, in.length());
m_vArgs.reserve(argIndices.size());
for (const auto& [start, end] : argIndices) {
if (handleEscape) {
std::string segment = in.substr(start, end - start);
replaceInString(segment, "\\", "");
m_vArgs.emplace_back(trim(segment));
} else
m_vArgs.emplace_back(trim(in.substr(start, end - start)));
}
}

View file

@ -39,6 +39,15 @@ int main(int argc, char** argv, char** envp) {
EXPECT(list[0], "hello");
EXPECT(list[1], "world!");
CVarList list2("test:test\\:test", 0, ':', true, true);
EXPECT(list2[0], "test");
EXPECT(list2[1], "test:test");
CVarList list3("test:test\\:test", 0, ':', true);
EXPECT(list3[0], "test");
EXPECT(list3[1], "test\\");
EXPECT(list3[2], "test");
CConstVarList listConst("hello world!", 0, 's', true);
EXPECT(listConst[0], "hello");
EXPECT(listConst[1], "world!");