feat: finish string helper.
- finish Split() in string helper. - make complement to testbench test code.
This commit is contained in:
parent
9c943705de
commit
b8a56efd7c
|
@ -4,6 +4,7 @@
|
||||||
#include "EncodingHelper.hpp"
|
#include "EncodingHelper.hpp"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace YYCC::IOHelper {
|
namespace YYCC::IOHelper {
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#include "YYCCInternal.hpp"
|
#include "YYCCInternal.hpp"
|
||||||
#if YYCC_OS == YYCC_OS_WINDOWS
|
#if YYCC_OS == YYCC_OS_WINDOWS
|
||||||
|
|
||||||
#include <string>
|
#include <cstdio>
|
||||||
|
|
||||||
namespace YYCC::IOHelper {
|
namespace YYCC::IOHelper {
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,5 @@ namespace YYCC::ParserHelper {
|
||||||
|
|
||||||
bool Parse(const std::string& strl, int& ret, int base = 10);
|
bool Parse(const std::string& strl, int& ret, int base = 10);
|
||||||
int Parse(const std::string& strl, int base = 10);
|
int Parse(const std::string& strl, int base = 10);
|
||||||
bool ToString(int val, std::string& ret, int base = 10);
|
|
||||||
std::string ToString(int val, int base = 10);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,7 +98,7 @@ namespace YYCC::StringHelper {
|
||||||
const char* ret = iter->c_str();
|
const char* ret = iter->c_str();
|
||||||
++iter;
|
++iter;
|
||||||
return ret;
|
return ret;
|
||||||
}, decilmer);
|
}, decilmer);
|
||||||
} else {
|
} else {
|
||||||
auto iter = data.cbegin();
|
auto iter = data.cbegin();
|
||||||
auto stop = data.cend();
|
auto stop = data.cend();
|
||||||
|
@ -109,7 +109,7 @@ namespace YYCC::StringHelper {
|
||||||
const char* ret = iter->c_str();
|
const char* ret = iter->c_str();
|
||||||
++iter;
|
++iter;
|
||||||
return ret;
|
return ret;
|
||||||
}, decilmer);
|
}, decilmer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ namespace YYCC::StringHelper {
|
||||||
// https://en.cppreference.com/w/cpp/algorithm/transform
|
// https://en.cppreference.com/w/cpp/algorithm/transform
|
||||||
// https://en.cppreference.com/w/cpp/string/byte/tolower
|
// https://en.cppreference.com/w/cpp/string/byte/tolower
|
||||||
std::transform(
|
std::transform(
|
||||||
strl.cbegin(), strl.cend(), strl.begin(),
|
strl.cbegin(), strl.cend(), strl.begin(),
|
||||||
[](unsigned char c) -> char {
|
[](unsigned char c) -> char {
|
||||||
if constexpr (bIsToLower) return std::tolower(c);
|
if constexpr (bIsToLower) return std::tolower(c);
|
||||||
else return std::toupper(c);
|
else return std::toupper(c);
|
||||||
|
@ -153,33 +153,30 @@ namespace YYCC::StringHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> Split(const char* _strl, const char* _decilmer) {
|
std::vector<std::string> Split(const char* _strl, const char* _decilmer) {
|
||||||
std::vector<std::string> elems;
|
// Reference:
|
||||||
|
// https://stackoverflow.com/questions/14265581/parse-split-a-string-in-c-using-string-delimiter-standard-c
|
||||||
|
|
||||||
// check whether string and decilmer are nullptr
|
// prepare return value
|
||||||
std::string strl, decilmer;
|
std::vector<std::string> elems;
|
||||||
if (_strl == nullptr || _decilmer == nullptr)
|
|
||||||
return elems;
|
// if the string need to be splitted is nullptr, return empty result.
|
||||||
else {
|
if (_strl == nullptr) return elems;
|
||||||
strl = _strl;
|
std::string strl(_strl);
|
||||||
decilmer = _decilmer;
|
// if decilmer is nullptr, or decilmer is zero length, return original string
|
||||||
}
|
std::string decilmer;
|
||||||
// if no decilmer, return the whole string as the only one element of result.
|
if (_decilmer == nullptr || (decilmer = _decilmer, decilmer.empty())) {
|
||||||
if (decilmer.empty()) {
|
|
||||||
elems.push_back(strl);
|
elems.push_back(strl);
|
||||||
return elems;
|
return elems;
|
||||||
}
|
}
|
||||||
|
|
||||||
// start spliting
|
// start spliting
|
||||||
std::size_t previous = 0;
|
std::size_t previous = 0, current;
|
||||||
std::size_t current = strl.find(decilmer.c_str());
|
while ((current = strl.find(decilmer.c_str(), previous)) != std::string::npos) {
|
||||||
while (current != std::string::npos) {
|
elems.push_back(strl.substr(previous, current - previous));
|
||||||
if (current >= previous) {
|
|
||||||
elems.push_back(strl.substr(previous, current - previous));
|
|
||||||
}
|
|
||||||
previous = current + decilmer.size();
|
previous = current + decilmer.size();
|
||||||
current = strl.find(decilmer, previous);
|
|
||||||
}
|
}
|
||||||
if (previous != strl.size()) {
|
// try insert last part but prevent possible out of range exception
|
||||||
|
if (previous <= strl.size()) {
|
||||||
elems.push_back(strl.substr(previous));
|
elems.push_back(strl.substr(previous));
|
||||||
}
|
}
|
||||||
return elems;
|
return elems;
|
||||||
|
|
|
@ -53,8 +53,10 @@ namespace YYCC::StringHelper {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief General Split function.
|
* @brief General Split function.
|
||||||
* @param _strl
|
* @param _strl[in] The string need to be splitting.
|
||||||
* @param _decilmer
|
* If this is nullptr, the result will be empty.
|
||||||
|
* @param _decilmer[in] The decilmer for splitting.
|
||||||
|
* If decilmer is nullptr or zero length, the result will only have 1 element which is original string.
|
||||||
* @return
|
* @return
|
||||||
* @remarks This function may be low performance because it just a homebrew Split functon.
|
* @remarks This function may be low performance because it just a homebrew Split functon.
|
||||||
* It can works in most toy cases but not suit for high performance scenario.
|
* It can works in most toy cases but not suit for high performance scenario.
|
||||||
|
|
|
@ -3,6 +3,15 @@
|
||||||
|
|
||||||
namespace Testbench {
|
namespace Testbench {
|
||||||
|
|
||||||
|
static void Assert(bool condition, const char* description) {
|
||||||
|
if (condition) {
|
||||||
|
YYCC::TerminalHelper::FPrintf(stdout, YYCC_TERMCOL_LIGHT_GREEN(u8"OK: %s\n"), description);
|
||||||
|
} else {
|
||||||
|
YYCC::TerminalHelper::FPrintf(stdout, YYCC_TERMCOL_LIGHT_RED(u8"Failed: %s\n"), description);
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void TerminalTestbench() {
|
static void TerminalTestbench() {
|
||||||
YYCC::TerminalHelper::EnsureTerminalUTF8(stdout);
|
YYCC::TerminalHelper::EnsureTerminalUTF8(stdout);
|
||||||
YYCC::TerminalHelper::FPuts(u8"你好世界\n", stdout);
|
YYCC::TerminalHelper::FPuts(u8"你好世界\n", stdout);
|
||||||
|
@ -11,22 +20,36 @@ namespace Testbench {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void StringTestbench() {
|
static void StringTestbench() {
|
||||||
YYCC::TerminalHelper::FPuts(
|
auto test_printf = YYCC::StringHelper::Printf(u8"%s == %s", u8"Hello World", u8"你好世界");
|
||||||
YYCC::StringHelper::Printf(u8"Translation: %s == %s\n", u8"Hello World", u8"你好世界").c_str(),
|
Assert(test_printf == u8"Hello World == 你好世界", "YYCC::StringHelper::Printf");
|
||||||
stdout
|
|
||||||
);
|
auto test_lower = YYCC::StringHelper::Lower("LOWER");
|
||||||
|
Assert(test_lower == "lower", "YYCC::StringHelper::Lower");
|
||||||
|
auto test_upper = YYCC::StringHelper::Upper("upper");
|
||||||
|
Assert(test_upper == "UPPER", "YYCC::StringHelper::Upper");
|
||||||
|
|
||||||
std::string test_string(u8"UPPER -> lower\n");
|
|
||||||
YYCC::TerminalHelper::FPuts(test_string.c_str(), stdout);
|
std::vector<std::string> test_join_container {
|
||||||
YYCC::TerminalHelper::FPuts(YYCC::StringHelper::Lower(test_string.c_str()).c_str(), stdout);
|
"", "1", "2", ""
|
||||||
YYCC::TerminalHelper::FPuts(YYCC::StringHelper::Upper(test_string.c_str()).c_str(), stdout);
|
|
||||||
|
|
||||||
std::vector<std::string> test_container {
|
|
||||||
"test1", "test2", "test3", "test4"
|
|
||||||
};
|
};
|
||||||
YYCC::TerminalHelper::FPuts(YYCC::StringHelper::Join(test_container, ", ").c_str(), stdout);
|
auto test_join = YYCC::StringHelper::Join(test_join_container, ", ");
|
||||||
std::string test_split(", 1, 3, 5, 7, 9, ");
|
Assert(test_join == ", 1, 2, ", "YYCC::StringHelper::Join");
|
||||||
YYCC::TerminalHelper::FPuts(YYCC::StringHelper::Join(YYCC::StringHelper::Split(test_split.c_str(), ", "), " -> ").c_str(), stdout);
|
test_join = YYCC::StringHelper::Join(test_join_container, ", ", true);
|
||||||
|
Assert(test_join == ", 2, 1, ", "YYCC::StringHelper::Join");
|
||||||
|
|
||||||
|
auto test_split = YYCC::StringHelper::Split(", 1, 2, ", ", ");
|
||||||
|
Assert(test_split.size() == 4u, "YYCC::StringHelper::Split");
|
||||||
|
Assert(test_split[0] == "", "YYCC::StringHelper::Split");
|
||||||
|
Assert(test_split[1] == "1", "YYCC::StringHelper::Split");
|
||||||
|
Assert(test_split[2] == "2", "YYCC::StringHelper::Split");
|
||||||
|
Assert(test_split[3] == "", "YYCC::StringHelper::Split");
|
||||||
|
test_split = YYCC::StringHelper::Split("test", "-");
|
||||||
|
Assert(test_split.size() == 1u, "YYCC::StringHelper::Split");
|
||||||
|
Assert(test_split[0] == "test", "YYCC::StringHelper::Split");
|
||||||
|
test_split = YYCC::StringHelper::Split("test", "");
|
||||||
|
Assert(test_split.size() == 1u, "YYCC::StringHelper::Split");
|
||||||
|
Assert(test_split[0] == "test", "YYCC::StringHelper::Split");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user