27 return !chunk.empty();
32 return !chunks.empty() && std::all_of(chunks.begin(), chunks.end(),
33 [](
const auto& c) { return is_valid_chunk(c); });
37std::vector<std::vector<T>>
safe_copy(
const std::vector<std::vector<T>>& chunks) {
56 const size_t current_depth) {
59 throw std::runtime_error(
"Recursive strategy already processing");
62 std::atomic<bool>& flag;
63 Guard(std::atomic<bool>& f) : flag(f) {}
71 return data.empty() ? std::vector<std::vector<T>>{}
72 : std::vector<std::vector<T>>{data};
75 std::vector<std::vector<T>> result;
77 std::lock_guard<std::mutex> lock(
mutex_);
79 throw std::runtime_error(
"Invalid base strategy");
85 result.reserve(chunks.size() * 2);
87 for (
const auto& chunk : chunks) {
89 result.push_back(chunk);
96 result.insert(result.end(), std::make_move_iterator(sub_chunks.begin()),
97 std::make_move_iterator(sub_chunks.end()));
99 result.push_back(chunk);
102 result.push_back(chunk);
106 return result.empty() ? std::vector<std::vector<T>>{data} : result;
117 throw std::invalid_argument(
"Invalid strategy");
119 throw std::invalid_argument(
"Invalid max depth");
121 throw std::invalid_argument(
"Invalid min size");
124 std::vector<std::vector<T>>
apply(
const std::vector<T>& data)
const override {
142 std::vector<std::vector<T>>
146 throw std::runtime_error(
"Invalid strategy encountered");
154 auto sub_chunks = strategy->apply(chunk);
155 if (sub_chunks.empty()) {
160 for (
const auto& sub : sub_chunks) {
167 }
catch (
const std::exception& e) {
178 if (strategies.empty()) {
179 throw std::invalid_argument(
"Strategies vector cannot be empty");
184 for (
const auto& strategy : strategies) {
186 throw std::invalid_argument(
"Strategy cannot be null");
192 throw std::invalid_argument(
"Minimum size must be positive");
196 std::vector<std::vector<T>>
apply(
const std::vector<T>& data)
const override {
205 std::vector<std::vector<T>> current_chunks{data};
210 throw std::runtime_error(
"Invalid strategy encountered");
213 std::vector<std::vector<T>> next_level;
214 next_level.reserve(current_chunks.size() *
218 for (
const auto& chunk : current_chunks) {
224 next_level.insert(next_level.end(), std::make_move_iterator(sub_chunks.begin()),
225 std::make_move_iterator(sub_chunks.end()));
228 if (next_level.empty()) {
229 return current_chunks;
232 current_chunks = std::move(next_level);
235 return current_chunks;
237 }
catch (
const std::exception& e) {
238 throw std::runtime_error(std::string(
"Error in hierarchical strategy: ") + e.what());
252 std::function<
bool(
const std::vector<T>&)> condition,
257 throw std::invalid_argument(
"Base strategy cannot be null");
260 throw std::invalid_argument(
"Condition function cannot be null");
263 throw std::invalid_argument(
"Minimum size must be positive");
267 std::vector<std::vector<T>>
apply(
const std::vector<T>& data)
const override {
282 }
catch (
const std::exception& e) {
283 throw std::runtime_error(std::string(
"Error in conditional strategy: ") + e.what());
Defines various strategies for chunking data based on different criteria.
std::shared_ptr< ChunkStrategy< T > > base_strategy_
ConditionalSubChunkStrategy(std::shared_ptr< ChunkStrategy< T > > strategy, std::function< bool(const std::vector< T > &)> condition, size_t min_size)
std::vector< std::vector< T > > apply(const std::vector< T > &data) const override
std::function< bool(const std::vector< T > &)> condition_
HierarchicalSubChunkStrategy(std::vector< std::shared_ptr< ChunkStrategy< T > > > strategies, size_t min_size)
std::vector< std::shared_ptr< ChunkStrategy< T > > > strategies_
std::vector< std::vector< T > > process_chunk(const std::vector< T > &chunk, const std::shared_ptr< ChunkStrategy< T > > &strategy) const
std::vector< std::vector< T > > apply(const std::vector< T > &data) const override
RecursiveSubChunkStrategy(std::shared_ptr< ChunkStrategy< T > > strategy, size_t max_depth=5, size_t min_size=2)
std::atomic< bool > is_processing_
const std::shared_ptr< ChunkStrategy< T > > base_strategy_
std::vector< std::vector< T > > apply(const std::vector< T > &data) const override
std::vector< std::vector< T > > safe_recursive_apply(const std::vector< T > &data, const size_t current_depth)
bool is_valid_chunks(const std::vector< std::vector< T > > &chunks)
std::vector< std::vector< T > > safe_copy(const std::vector< std::vector< T > > &chunks)
bool is_valid_chunk(const std::vector< T > &chunk)