1
0

feat: change join data provider.

- use Rust iterator style for join data provider for better understanding.
This commit is contained in:
2025-09-28 17:01:18 +08:00
parent cc1ce5bb04
commit bd5032cee7
2 changed files with 16 additions and 22 deletions

View File

@ -1,7 +1,6 @@
#include "op.hpp" #include "op.hpp"
#include <map> #include <map>
#include <memory> #include <memory>
#include <iterator>
#include <type_traits> #include <type_traits>
#include <algorithm> #include <algorithm>
#include <stdexcept> #include <stdexcept>
@ -113,19 +112,15 @@ namespace yycc::string::op {
std::u8string join(JoinDataProvider fct_data, const std::u8string_view& delimiter) { std::u8string join(JoinDataProvider fct_data, const std::u8string_view& delimiter) {
std::u8string ret; std::u8string ret;
bool is_first = true; bool is_first = true;
std::u8string_view element;
// fetch element // fetch element
while (fct_data(element)) { while (auto item = fct_data()) {
// insert delimiter // append delimiter if it is not first
if (is_first) is_first = false; if (is_first) is_first = false;
else { else ret.append(delimiter);
// append delimiter.
ret.append(delimiter);
}
// insert element if it is not empty // append element
if (!element.empty()) ret.append(element); ret.append(item.value());
} }
return ret; return ret;

View File

@ -6,6 +6,7 @@
#include <functional> #include <functional>
#include <vector> #include <vector>
#include <optional> #include <optional>
#include <iterator>
namespace yycc::string::op { namespace yycc::string::op {
@ -67,13 +68,12 @@ namespace yycc::string::op {
/** /**
* @brief The data provider of general join function. * @brief The data provider of general join function.
* @details * @details
* This data provider is more like Rust iterator.
* For programmer using lambda to implement this function pointer: * For programmer using lambda to implement this function pointer:
* \li During calling, implementation should assign the reference of string view passed in argument * \li Return \c std::nullopt if there is no more data for join.
* to the string which need to be joined. * \li Return \c std::u8string_view for the data of join.
* \li Function return true to continue joining. otherwise return false to stop joining.
* The argument content assigned in the calling returning false is not included in join process.
*/ */
using JoinDataProvider = std::function<bool(std::u8string_view&)>; using JoinDataProvider = std::function<std::optional<std::u8string_view>()>;
/** /**
* @brief Universal join function. * @brief Universal join function.
* @details * @details
@ -96,16 +96,15 @@ namespace yycc::string::op {
* @param[in] delimiter The delimiter used for joining. * @param[in] delimiter The delimiter used for joining.
* @return The result string of joining. * @return The result string of joining.
*/ */
template<class InputIt> template<std::input_iterator InputIt>
requires std::is_constructible_v<std::u8string_view, std::iter_value_t<InputIt>>
std::u8string join(InputIt first, InputIt last, const std::u8string_view& delimiter) { std::u8string join(InputIt first, InputIt last, const std::u8string_view& delimiter) {
return join( return join(
[&first, &last](std::u8string_view& view) -> bool { [&first, &last]() -> std::optional<std::u8string_view> {
// if we reach tail, return false to stop join process // if we reach tail, return std::nullopt to stop join process
if (first == last) return false; if (first == last) return std::nullopt;
// otherwise fetch data, inc iterator and return. // otherwise fetch data, inc iterator and return.
view = *first; return std::u8string_view(*(first++));
++first;
return true;
}, },
delimiter); delimiter);
} }