refactor: refactor string helper for UTF8 string
This commit is contained in:
parent
91ba0c22d6
commit
44dbbb1c99
|
@ -1,9 +1,12 @@
|
||||||
#include "StringHelper.hpp"
|
#include "StringHelper.hpp"
|
||||||
|
#include "EncodingHelper.hpp"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
namespace YYCC::StringHelper {
|
namespace YYCC::StringHelper {
|
||||||
|
|
||||||
bool Printf(std::string& strl, const char* format, ...) {
|
#pragma region Printf VPrintf
|
||||||
|
|
||||||
|
bool Printf(yycc_u8string& strl, const yycc_char8_t* format, ...) {
|
||||||
va_list argptr;
|
va_list argptr;
|
||||||
va_start(argptr, format);
|
va_start(argptr, format);
|
||||||
bool ret = VPrintf(strl, format, argptr);
|
bool ret = VPrintf(strl, format, argptr);
|
||||||
|
@ -11,7 +14,7 @@ namespace YYCC::StringHelper {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VPrintf(std::string& strl, const char* format, va_list argptr) {
|
bool VPrintf(yycc_u8string& strl, const yycc_char8_t* format, va_list argptr) {
|
||||||
va_list args1;
|
va_list args1;
|
||||||
va_copy(args1, argptr);
|
va_copy(args1, argptr);
|
||||||
va_list args2;
|
va_list args2;
|
||||||
|
@ -19,7 +22,12 @@ namespace YYCC::StringHelper {
|
||||||
|
|
||||||
// the return value is desired char count without NULL terminal.
|
// the return value is desired char count without NULL terminal.
|
||||||
// minus number means error
|
// minus number means error
|
||||||
int count = std::vsnprintf(nullptr, 0, format, args1);
|
int count = std::vsnprintf(
|
||||||
|
nullptr,
|
||||||
|
0,
|
||||||
|
EncodingHelper::ToNative(format),
|
||||||
|
args1
|
||||||
|
);
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
// invalid length returned by vsnprintf.
|
// invalid length returned by vsnprintf.
|
||||||
return false;
|
return false;
|
||||||
|
@ -31,7 +39,12 @@ namespace YYCC::StringHelper {
|
||||||
// because std::vsnprintf only can write "buf_size - 1" chars with a trailing NULL.
|
// because std::vsnprintf only can write "buf_size - 1" chars with a trailing NULL.
|
||||||
// however std::vsnprintf already have a trailing NULL, so we plus 1 for it.
|
// however std::vsnprintf already have a trailing NULL, so we plus 1 for it.
|
||||||
strl.resize(count);
|
strl.resize(count);
|
||||||
int write_result = std::vsnprintf(strl.data(), strl.size() + 1, format, args2);
|
int write_result = std::vsnprintf(
|
||||||
|
EncodingHelper::ToNative(strl.data()),
|
||||||
|
strl.size() + 1,
|
||||||
|
EncodingHelper::ToNative(format),
|
||||||
|
args2
|
||||||
|
);
|
||||||
va_end(args2);
|
va_end(args2);
|
||||||
|
|
||||||
if (write_result < 0 || write_result > count) {
|
if (write_result < 0 || write_result > count) {
|
||||||
|
@ -42,9 +55,8 @@ namespace YYCC::StringHelper {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
yycc_u8string Printf(const yycc_char8_t* format, ...) {
|
||||||
std::string Printf(const char* format, ...) {
|
yycc_u8string ret;
|
||||||
std::string ret;
|
|
||||||
|
|
||||||
va_list argptr;
|
va_list argptr;
|
||||||
va_start(argptr, format);
|
va_start(argptr, format);
|
||||||
|
@ -54,8 +66,8 @@ namespace YYCC::StringHelper {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string VPrintf(const char* format, va_list argptr) {
|
yycc_u8string VPrintf(const yycc_char8_t* format, va_list argptr) {
|
||||||
std::string ret;
|
yycc_u8string ret;
|
||||||
|
|
||||||
va_list argcpy;
|
va_list argcpy;
|
||||||
va_copy(argcpy, argptr);
|
va_copy(argcpy, argptr);
|
||||||
|
@ -65,28 +77,32 @@ namespace YYCC::StringHelper {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Replace(std::string& strl, const char* _from_strl, const char* _to_strl) {
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Replace
|
||||||
|
|
||||||
|
void Replace(yycc_u8string& strl, const yycc_char8_t* _from_strl, const yycc_char8_t* _to_strl) {
|
||||||
// Reference: https://stackoverflow.com/questions/3418231/replace-part-of-a-string-with-another-string
|
// Reference: https://stackoverflow.com/questions/3418231/replace-part-of-a-string-with-another-string
|
||||||
|
|
||||||
// check requirements
|
// check requirements
|
||||||
// from string and to string should not be nullptr.
|
// from string and to string should not be nullptr.
|
||||||
if (_from_strl == nullptr || _to_strl == nullptr) return;
|
if (_from_strl == nullptr || _to_strl == nullptr) return;
|
||||||
// from string should not be empty
|
// from string should not be empty
|
||||||
std::string from_strl(_from_strl);
|
yycc_u8string from_strl(_from_strl);
|
||||||
std::string to_strl(_to_strl);
|
yycc_u8string to_strl(_to_strl);
|
||||||
if (from_strl.empty()) return;
|
if (from_strl.empty()) return;
|
||||||
|
|
||||||
// start replace one by one
|
// start replace one by one
|
||||||
size_t start_pos = 0;
|
size_t start_pos = 0;
|
||||||
while ((start_pos = strl.find(from_strl, start_pos)) != std::string::npos) {
|
while ((start_pos = strl.find(from_strl, start_pos)) != yycc_u8string::npos) {
|
||||||
strl.replace(start_pos, from_strl.size(), to_strl);
|
strl.replace(start_pos, from_strl.size(), to_strl);
|
||||||
start_pos += to_strl.size(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
|
start_pos += to_strl.size(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Replace(const char* _strl, const char* _from_strl, const char* _to_strl) {
|
yycc_u8string Replace(const yycc_char8_t* _strl, const yycc_char8_t* _from_strl, const yycc_char8_t* _to_strl) {
|
||||||
// prepare result
|
// prepare result
|
||||||
std::string strl;
|
yycc_u8string strl;
|
||||||
// if given string is not nullptr, assign it and process it.
|
// if given string is not nullptr, assign it and process it.
|
||||||
if (_strl != nullptr) {
|
if (_strl != nullptr) {
|
||||||
strl = _strl;
|
strl = _strl;
|
||||||
|
@ -96,13 +112,17 @@ namespace YYCC::StringHelper {
|
||||||
return strl;
|
return strl;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Join(JoinDataProvider fct_data, const char* decilmer) {
|
#pragma endregion
|
||||||
std::string ret;
|
|
||||||
|
#pragma region Join
|
||||||
|
|
||||||
|
yycc_u8string Join(JoinDataProvider fct_data, const yycc_char8_t* decilmer) {
|
||||||
|
yycc_u8string ret;
|
||||||
bool is_first = true;
|
bool is_first = true;
|
||||||
const char* element;
|
yycc_u8string_view element;
|
||||||
|
|
||||||
// fetch element
|
// fetch element
|
||||||
while ((element = fct_data()) != nullptr) {
|
while (fct_data(element)) {
|
||||||
// insert decilmer
|
// insert decilmer
|
||||||
if (is_first) is_first = false;
|
if (is_first) is_first = false;
|
||||||
else {
|
else {
|
||||||
|
@ -111,42 +131,46 @@ namespace YYCC::StringHelper {
|
||||||
ret.append(decilmer);
|
ret.append(decilmer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert element
|
// insert element if it is not empty
|
||||||
ret.append(element);
|
if (!element.empty())
|
||||||
|
ret.append(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Join(const std::vector<std::string>& data, const char* decilmer, bool reversed) {
|
yycc_u8string Join(const std::vector<yycc_u8string>& data, const yycc_char8_t* decilmer, bool reversed) {
|
||||||
if (reversed) {
|
if (reversed) {
|
||||||
auto iter = data.crbegin();
|
auto iter = data.crbegin();
|
||||||
auto stop = data.crend();
|
auto stop = data.crend();
|
||||||
return Join([&iter, &stop]() -> const char* {
|
return Join([&iter, &stop](yycc_u8string_view& view) -> bool {
|
||||||
// if we reach tail, return nullptr
|
// if we reach tail, return false
|
||||||
if (iter == stop) return nullptr;
|
if (iter == stop) return false;
|
||||||
// otherwise fetch data, inc iterator and return.
|
// otherwise fetch data, inc iterator and return.
|
||||||
const char* ret = iter->c_str();
|
view = *iter;
|
||||||
++iter;
|
++iter;
|
||||||
return ret;
|
return true;
|
||||||
}, decilmer);
|
}, decilmer);
|
||||||
} else {
|
} else {
|
||||||
auto iter = data.cbegin();
|
auto iter = data.cbegin();
|
||||||
auto stop = data.cend();
|
auto stop = data.cend();
|
||||||
return Join([&iter, &stop]() -> const char* {
|
return Join([&iter, &stop](yycc_u8string_view& view) -> bool {
|
||||||
// if we reach tail, return nullptr
|
// if we reach tail, return nullptr
|
||||||
if (iter == stop) return nullptr;
|
if (iter == stop) return false;
|
||||||
// otherwise fetch data, inc iterator and return.
|
// otherwise fetch data, inc iterator and return.
|
||||||
const char* ret = iter->c_str();
|
view = *iter;
|
||||||
++iter;
|
++iter;
|
||||||
return ret;
|
return true;
|
||||||
}, decilmer);
|
}, decilmer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Upper Lower
|
||||||
|
|
||||||
template<bool bIsToLower>
|
template<bool bIsToLower>
|
||||||
void GeneralStringLowerUpper(std::string& strl) {
|
void GeneralStringLowerUpper(yycc_u8string& strl) {
|
||||||
// References:
|
// References:
|
||||||
// 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
|
||||||
|
@ -159,43 +183,47 @@ namespace YYCC::StringHelper {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Lower(const char* strl) {
|
yycc_u8string Lower(const yycc_char8_t* strl) {
|
||||||
std::string ret;
|
yycc_u8string ret;
|
||||||
if (strl == nullptr) return ret;
|
if (strl == nullptr) return ret;
|
||||||
else ret = strl;
|
else ret = strl;
|
||||||
Lower(ret);
|
Lower(ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lower(std::string& strl) {
|
void Lower(yycc_u8string& strl) {
|
||||||
GeneralStringLowerUpper<true>(strl);
|
GeneralStringLowerUpper<true>(strl);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Upper(const char* strl) {
|
yycc_u8string Upper(const yycc_char8_t* strl) {
|
||||||
// same as Lower, just replace char transform function.
|
// same as Lower, just replace char transform function.
|
||||||
std::string ret;
|
yycc_u8string ret;
|
||||||
if (strl == nullptr) return ret;
|
if (strl == nullptr) return ret;
|
||||||
else ret = strl;
|
else ret = strl;
|
||||||
Upper(ret);
|
Upper(ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Upper(std::string& strl) {
|
void Upper(yycc_u8string& strl) {
|
||||||
GeneralStringLowerUpper<false>(strl);
|
GeneralStringLowerUpper<false>(strl);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> Split(const char* _strl, const char* _decilmer) {
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Split
|
||||||
|
|
||||||
|
std::vector<yycc_u8string> Split(const yycc_char8_t* _strl, const yycc_char8_t* _decilmer) {
|
||||||
// Reference:
|
// Reference:
|
||||||
// https://stackoverflow.com/questions/14265581/parse-split-a-string-in-c-using-string-delimiter-standard-c
|
// https://stackoverflow.com/questions/14265581/parse-split-a-string-in-c-using-string-delimiter-standard-c
|
||||||
|
|
||||||
// prepare return value
|
// prepare return value
|
||||||
std::vector<std::string> elems;
|
std::vector<yycc_u8string> elems;
|
||||||
|
|
||||||
// if the string need to be splitted is nullptr, return empty result.
|
// if the string need to be splitted is nullptr, return empty result.
|
||||||
if (_strl == nullptr) return elems;
|
if (_strl == nullptr) return elems;
|
||||||
std::string strl(_strl);
|
yycc_u8string strl(_strl);
|
||||||
// if decilmer is nullptr, or decilmer is zero length, return original string
|
// if decilmer is nullptr, or decilmer is zero length, return original string
|
||||||
std::string decilmer;
|
yycc_u8string decilmer;
|
||||||
if (_decilmer == nullptr || (decilmer = _decilmer, decilmer.empty())) {
|
if (_decilmer == nullptr || (decilmer = _decilmer, decilmer.empty())) {
|
||||||
elems.push_back(strl);
|
elems.push_back(strl);
|
||||||
return elems;
|
return elems;
|
||||||
|
@ -203,7 +231,7 @@ namespace YYCC::StringHelper {
|
||||||
|
|
||||||
// start spliting
|
// start spliting
|
||||||
std::size_t previous = 0, current;
|
std::size_t previous = 0, current;
|
||||||
while ((current = strl.find(decilmer.c_str(), previous)) != std::string::npos) {
|
while ((current = strl.find(decilmer.c_str(), previous)) != yycc_u8string::npos) {
|
||||||
elems.push_back(strl.substr(previous, current - previous));
|
elems.push_back(strl.substr(previous, current - previous));
|
||||||
previous = current + decilmer.size();
|
previous = current + decilmer.size();
|
||||||
}
|
}
|
||||||
|
@ -214,4 +242,7 @@ namespace YYCC::StringHelper {
|
||||||
return elems;
|
return elems;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,21 +8,22 @@
|
||||||
|
|
||||||
namespace YYCC::StringHelper {
|
namespace YYCC::StringHelper {
|
||||||
|
|
||||||
bool Printf(std::string& strl, const char* format, ...);
|
bool Printf(yycc_u8string& strl, const yycc_char8_t* format, ...);
|
||||||
bool VPrintf(std::string& strl, const char* format, va_list argptr);
|
bool VPrintf(yycc_u8string& strl, const yycc_char8_t* format, va_list argptr);
|
||||||
|
yycc_u8string Printf(const yycc_char8_t* format, ...);
|
||||||
|
yycc_u8string VPrintf(const yycc_char8_t* format, va_list argptr);
|
||||||
|
|
||||||
std::string Printf(const char* format, ...);
|
void Replace(yycc_u8string& strl, const yycc_char8_t* _from_strl, const yycc_char8_t* _to_strl);
|
||||||
std::string VPrintf(const char* format, va_list argptr);
|
yycc_u8string Replace(const yycc_char8_t* _strl, const yycc_char8_t* _from_strl, const yycc_char8_t* _to_strl);
|
||||||
|
|
||||||
void Replace(std::string& strl, const char* _from_strl, const char* _to_strl);
|
|
||||||
std::string Replace(const char* _strl, const char* _from_strl, const char* _to_strl);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The data provider of general Join function.
|
* @brief The data provider of general Join function.
|
||||||
* This function pointer return non-null string pointer to represent a element of joined series.
|
* For the implementation of this function:
|
||||||
* otherwise return nullptr to terminate the joining process.
|
* Function return true to continue join. otherwise return false to terminate join.
|
||||||
|
* The argument assigned in the calling returning false is not included.
|
||||||
|
* During calling, implementation should assign the string view to the string need to be joined in given argument.
|
||||||
*/
|
*/
|
||||||
using JoinDataProvider = std::function<const char* ()>;
|
using JoinDataProvider = std::function<bool(yycc_u8string_view&)>;
|
||||||
/**
|
/**
|
||||||
* @brief General Join function.
|
* @brief General Join function.
|
||||||
* @details This function use function pointer as a general data provider interface,
|
* @details This function use function pointer as a general data provider interface,
|
||||||
|
@ -31,7 +32,7 @@ namespace YYCC::StringHelper {
|
||||||
* @param decilmer[in] The decilmer.
|
* @param decilmer[in] The decilmer.
|
||||||
* @return A std::string instance which containing the join result.
|
* @return A std::string instance which containing the join result.
|
||||||
*/
|
*/
|
||||||
std::string Join(JoinDataProvider fct_data, const char* decilmer);
|
yycc_u8string Join(JoinDataProvider fct_data, const yycc_char8_t* decilmer);
|
||||||
/**
|
/**
|
||||||
* @brief Specialized Join function for common used container.
|
* @brief Specialized Join function for common used container.
|
||||||
* @param data
|
* @param data
|
||||||
|
@ -39,22 +40,12 @@ namespace YYCC::StringHelper {
|
||||||
* @param reversed
|
* @param reversed
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
std::string Join(const std::vector<std::string>& data, const char* decilmer, bool reversed = false);
|
yycc_u8string Join(const std::vector<yycc_u8string>& data, const yycc_char8_t* decilmer, bool reversed = false);
|
||||||
|
|
||||||
/**
|
yycc_u8string Lower(const yycc_char8_t* strl);
|
||||||
* @brief Transform string to lower.
|
void Lower(yycc_u8string& strl);
|
||||||
* @param strl
|
yycc_u8string Upper(const yycc_char8_t* strl);
|
||||||
* @return
|
void Upper(yycc_u8string& strl);
|
||||||
*/
|
|
||||||
std::string Lower(const char* strl);
|
|
||||||
void Lower(std::string& strl);
|
|
||||||
/**
|
|
||||||
* @brief Transform string to upper.
|
|
||||||
* @param strl
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
std::string Upper(const char* strl);
|
|
||||||
void Upper(std::string& strl);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief General Split function.
|
* @brief General Split function.
|
||||||
|
@ -67,5 +58,5 @@ namespace YYCC::StringHelper {
|
||||||
* 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.
|
||||||
* Also, this function will produce a copy of original string because it is not zero copy.
|
* Also, this function will produce a copy of original string because it is not zero copy.
|
||||||
*/
|
*/
|
||||||
std::vector<std::string> Split(const char* _strl, const char* _decilmer);
|
std::vector<yycc_u8string> Split(const yycc_char8_t* _strl, const yycc_char8_t* _decilmer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
#include "YYCCInternal.hpp"
|
#include "YYCCInternal.hpp"
|
||||||
|
|
||||||
#include "StringHelper.hpp"
|
|
||||||
#include "EncodingHelper.hpp"
|
#include "EncodingHelper.hpp"
|
||||||
|
#include "StringHelper.hpp"
|
||||||
#include "ConsoleHelper.hpp"
|
#include "ConsoleHelper.hpp"
|
||||||
#include "COMHelper.hpp"
|
#include "COMHelper.hpp"
|
||||||
#include "DialogHelper.hpp"
|
#include "DialogHelper.hpp"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user