Container System 0.1.0
High-performance C++20 type-safe container framework with SIMD-accelerated serialization
Loading...
Searching...
No Matches
container.cpp
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2021, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
5#include "container.h"
6
9
10#include "value_types.h"
11#include "internal/value.h"
18// Legacy value includes removed - using variant-based storage only
19
20#include <fcntl.h>
21#include <wchar.h>
22
23#include <regex>
24#include <sstream>
25#include <fstream>
26#include <unordered_set>
27
29{
30 // Use integer constants instead of string_view to ensure cross-platform compatibility
31 // with fmt library formatting. Linux fmt has issues with string_view arguments.
32 inline constexpr int TARGET_ID = 1;
33 inline constexpr int TARGET_SUB_ID = 2;
34 inline constexpr int SOURCE_ID = 3;
35 inline constexpr int SOURCE_SUB_ID = 4;
36 inline constexpr int MESSAGE_TYPE = 5;
37 inline constexpr int MESSAGE_VERSION = 6;
38
39 using namespace utility_module;
40
41 value_container::value_container()
42 : parsed_data_(true)
43 , changed_data_(false)
44 , data_string_("@data={{}};")
45 , source_id_("")
46 , source_sub_id_("")
47 , target_id_("")
48 , target_sub_id_("")
49 , message_type_("data_container")
50 , version_("1.0.0.0")
51 {
52 }
53
54 value_container::value_container(const std::string& data_str,
55 bool parse_only_header)
56 : value_container()
57 {
58 // Enable zero-copy mode: store shared pointer to original data
59 // This allows lazy parsing and reduces memory copies
60 if (parse_only_header)
61 {
62 raw_data_ptr_ = std::make_shared<const std::string>(data_str);
63 zero_copy_mode_ = true;
64 }
65 deserialize(data_str, parse_only_header);
66 }
67
68 value_container::value_container(const std::vector<uint8_t>& data_array,
69 bool parse_only_header)
70 : value_container()
71 {
72 // Enable zero-copy mode: convert to string and store shared pointer
73 if (parse_only_header)
74 {
75 std::string data_str(data_array.begin(), data_array.end());
76 raw_data_ptr_ = std::make_shared<const std::string>(std::move(data_str));
77 zero_copy_mode_ = true;
78 }
79 deserialize(data_array, parse_only_header);
80 }
81
82 value_container::value_container(const value_container& other,
83 bool parse_only_header)
84 : value_container()
85 {
86 if (metrics_manager::is_enabled())
87 {
88 metrics_manager::get().operations.copies.fetch_add(1, std::memory_order_relaxed);
89 }
90 binary_serializer serializer;
91 deserialize(serializer.serialize_to_string(other), parse_only_header);
92 }
93
94 value_container::value_container(std::shared_ptr<value_container> other,
95 bool parse_only_header)
96 : value_container()
97 {
98 if (other)
99 {
100 binary_serializer serializer;
101 deserialize(serializer.serialize_to_string(*other), parse_only_header);
102 }
103 }
104
105 // Legacy constructors with value vector parameters removed
106
107 value_container::value_container(value_container&& other) noexcept
108 : parsed_data_(other.parsed_data_)
109 , changed_data_(other.changed_data_)
110 , data_string_(std::move(other.data_string_))
111 , source_id_(std::move(other.source_id_))
112 , source_sub_id_(std::move(other.source_sub_id_))
113 , target_id_(std::move(other.target_id_))
114 , target_sub_id_(std::move(other.target_sub_id_))
115 , message_type_(std::move(other.message_type_))
116 , version_(std::move(other.version_))
117 // Legacy units_ and data_type_map_ removed
118 {
119 if (metrics_manager::is_enabled())
120 {
121 metrics_manager::get().operations.moves.fetch_add(1, std::memory_order_relaxed);
122 }
123 // Reset other to a valid state
124 other.parsed_data_ = true;
125 other.changed_data_ = false;
126 }
127
128 value_container& value_container::operator=(value_container&& other) noexcept
129 {
130 if (this != &other)
131 {
132 source_id_ = std::move(other.source_id_);
133 source_sub_id_ = std::move(other.source_sub_id_);
134 target_id_ = std::move(other.target_id_);
135 target_sub_id_ = std::move(other.target_sub_id_);
136 message_type_ = std::move(other.message_type_);
137 version_ = std::move(other.version_);
138 parsed_data_ = other.parsed_data_;
139 changed_data_ = other.changed_data_;
140 data_string_ = std::move(other.data_string_);
141 optimized_units_ = std::move(other.optimized_units_);
142 use_soo_ = other.use_soo_;
143
144 // Reset other to a valid state
145 other.parsed_data_ = true;
146 other.changed_data_ = false;
147 }
148 return *this;
149 }
150
151 value_container::~value_container() {}
152
153 std::shared_ptr<value_container> value_container::get_ptr()
154 {
155 return shared_from_this();
156 }
157
158 void value_container::set_source(std::string_view sid,
159 std::string_view ssubid)
160 {
161 std::unique_lock<std::shared_mutex> lock(mutex_);
162 source_id_ = std::string(sid);
163 source_sub_id_ = std::string(ssubid);
164 }
165
166 void value_container::set_target(std::string_view tid,
167 std::string_view tsubid)
168 {
169 std::unique_lock<std::shared_mutex> lock(mutex_);
170 target_id_ = std::string(tid);
171 target_sub_id_ = std::string(tsubid);
172 }
173
174 void value_container::set_message_type(std::string_view msg_type)
175 {
176 std::unique_lock<std::shared_mutex> lock(mutex_);
177 message_type_ = std::string(msg_type);
178 }
179
180
181 void value_container::swap_header(void)
182 {
183 std::swap(source_id_, target_id_);
184 std::swap(source_sub_id_, target_sub_id_);
185 }
186
187 void value_container::clear_value(void)
188 {
189 parsed_data_ = true;
190 changed_data_ = false;
191 data_string_ = "@data={{}};";
192 optimized_units_.clear();
193 }
194
195 std::shared_ptr<value_container> value_container::copy(
196 bool containing_values)
197 {
198 binary_serializer serializer;
199 auto newC = std::make_shared<value_container>(serializer.serialize_to_string(*this),
200 !containing_values);
201 if (!containing_values && newC)
202 {
203 newC->clear_value();
204 }
205 return newC;
206 }
207
208 std::string value_container::source_id(void) const noexcept {
209 std::shared_lock<std::shared_mutex> lock(mutex_);
210 return source_id_;
211 }
212
213 std::string value_container::source_sub_id(void) const noexcept
214 {
215 std::shared_lock<std::shared_mutex> lock(mutex_);
216 return source_sub_id_;
217 }
218
219 std::string value_container::target_id(void) const noexcept {
220 std::shared_lock<std::shared_mutex> lock(mutex_);
221 return target_id_;
222 }
223
224 std::string value_container::target_sub_id(void) const noexcept
225 {
226 std::shared_lock<std::shared_mutex> lock(mutex_);
227 return target_sub_id_;
228 }
229
230 std::string value_container::message_type(void) const noexcept
231 {
232 std::shared_lock<std::shared_mutex> lock(mutex_);
233 return message_type_;
234 }
235
236 std::string value_container::version(void) const noexcept
237 {
238 std::shared_lock<std::shared_mutex> lock(mutex_);
239 return version_;
240 }
241
242 // =======================================================================
243 // Unified Getter API Implementation (Issue #309)
244 // =======================================================================
245
246 std::optional<optimized_value> value_container::get(std::string_view key) const noexcept
247 {
248 // Record metrics if enabled
249 auto timer = metrics_manager::make_timer(
250 metrics_manager::get().read_latency,
251 &metrics_manager::get().timing.total_read_ns);
252 if (metrics_manager::is_enabled())
253 {
254 metrics_manager::get().operations.reads.fetch_add(1, std::memory_order_relaxed);
255 }
256
257 read_lock_guard lock(this);
258
259 for (const auto& val : optimized_units_) {
260 if (val.name == key) {
261 return val;
262 }
263 }
264 return std::nullopt;
265 }
266
267 std::optional<value_view> value_container::get(std::string_view key, view_tag /*tag*/) const noexcept
268 {
269 read_lock_guard lock(this);
270
271 // Zero-copy mode requires raw_data_ptr_ to be valid
272 if (!zero_copy_mode_ || !raw_data_ptr_) {
273 return std::nullopt;
274 }
275
276 // Build index if not already built
277 if (!index_built_) {
278 build_index();
279 }
280
281 // Search in the index
282 if (value_index_) {
283 for (const auto& entry : *value_index_) {
284 if (entry.name == key) {
285 const char* data_ptr = raw_data_ptr_->data();
286 return value_view(
287 entry.name.data(), entry.name.size(),
288 data_ptr + entry.value_offset, entry.value_length,
289 entry.type
290 );
291 }
292 }
293 }
294
295 return std::nullopt;
296 }
297
298 std::vector<std::optional<optimized_value>> value_container::get(
299 std::span<const std::string_view> keys,
300 batch_options /*opts*/) const noexcept
301 {
302 std::vector<std::optional<optimized_value>> results;
303 results.reserve(keys.size());
304
305 read_lock_guard lock(this);
306
307 for (const auto& key : keys) {
308 std::optional<optimized_value> found = std::nullopt;
309 for (const auto& val : optimized_units_) {
310 if (val.name == key) {
311 found = val;
312 break;
313 }
314 }
315 results.push_back(std::move(found));
316 }
317
318 return results;
319 }
320
321 std::unordered_map<std::string, optimized_value> value_container::get_as_map(
322 std::span<const std::string_view> keys) const
323 {
324 std::unordered_map<std::string, optimized_value> results;
325 results.reserve(keys.size());
326
327 read_lock_guard lock(this);
328
329 for (const auto& key : keys) {
330 for (const auto& val : optimized_units_) {
331 if (val.name == key) {
332 results[std::string(key)] = val;
333 break;
334 }
335 }
336 }
337
338 return results;
339 }
340
341 // =======================================================================
342 // MIGRATE-002: variant_value_v2 Support API Implementation
343 // =======================================================================
344
345 // =======================================================================
346 // Internal implementation method
347 // =======================================================================
348
349 void value_container::set_unit_impl(const optimized_value& val)
350 {
351 // Record metrics if enabled
352 auto timer = metrics_manager::make_timer(
353 metrics_manager::get().write_latency,
354 &metrics_manager::get().timing.total_write_ns);
355 if (metrics_manager::is_enabled())
356 {
357 metrics_manager::get().operations.writes.fetch_add(1, std::memory_order_relaxed);
358 }
359
360 write_lock_guard lock(this);
361
362 // Check if key already exists
363 for (auto& existing : optimized_units_) {
364 if (existing.name == val.name) {
365 existing = val;
366 changed_data_ = true;
367 return;
368 }
369 }
370
371 // Key doesn't exist, add new value
372 optimized_units_.push_back(val);
373 changed_data_ = true;
374
375 if (use_soo_ && val.is_stack_allocated()) {
376 stack_allocations_.fetch_add(1, std::memory_order_relaxed);
377 } else {
378 heap_allocations_.fetch_add(1, std::memory_order_relaxed);
379 }
380 }
381
382 // =======================================================================
383 // Unified Value Setter API (Issue #207)
384 // =======================================================================
385
386 value_container& value_container::set(const optimized_value& val)
387 {
388 set_unit_impl(val);
389 return *this;
390 }
391
392 value_container& value_container::set_all(std::span<const optimized_value> vals)
393 {
394 for (const auto& val : vals) {
395 set_unit_impl(val);
396 }
397 return *this;
398 }
399
400 bool value_container::contains(std::string_view key) const noexcept
401 {
402 read_lock_guard lock(this);
403
404 for (const auto& val : optimized_units_) {
405 if (val.name == key) {
406 return true;
407 }
408 }
409 return false;
410 }
411
412 // =======================================================================
413 // Batch Operation APIs (Issue #229)
414 // =======================================================================
415
416 value_container& value_container::bulk_insert(std::vector<optimized_value>&& values)
417 {
418 if (values.empty()) {
419 return *this;
420 }
421
422 write_lock_guard lock(this);
423
424 // Pre-allocate for efficiency
425 optimized_units_.reserve(optimized_units_.size() + values.size());
426
427 // Move all values
428 for (auto& val : values) {
429 if (use_soo_ && val.is_stack_allocated()) {
430 stack_allocations_.fetch_add(1, std::memory_order_relaxed);
431 } else {
432 heap_allocations_.fetch_add(1, std::memory_order_relaxed);
433 }
434 optimized_units_.push_back(std::move(val));
435 }
436
437 changed_data_ = true;
438 return *this;
439 }
440
441 value_container& value_container::bulk_insert(
442 std::span<const optimized_value> values,
443 size_t reserve_hint)
444 {
445 if (values.empty()) {
446 return *this;
447 }
448
449 write_lock_guard lock(this);
450
451 // Apply reserve hint or use values.size()
452 size_t reserve_size = reserve_hint > 0 ? reserve_hint : values.size();
453 optimized_units_.reserve(optimized_units_.size() + reserve_size);
454
455 // Copy all values
456 for (const auto& val : values) {
457 if (use_soo_ && val.is_stack_allocated()) {
458 stack_allocations_.fetch_add(1, std::memory_order_relaxed);
459 } else {
460 heap_allocations_.fetch_add(1, std::memory_order_relaxed);
461 }
462 optimized_units_.push_back(val);
463 }
464
465 changed_data_ = true;
466 return *this;
467 }
468
469
470 std::vector<bool> value_container::contains_batch(
471 std::span<const std::string_view> keys) const noexcept
472 {
473 std::vector<bool> results;
474 results.reserve(keys.size());
475
476 read_lock_guard lock(this);
477
478 for (const auto& key : keys) {
479 bool found = false;
480 for (const auto& val : optimized_units_) {
481 if (val.name == key) {
482 found = true;
483 break;
484 }
485 }
486 results.push_back(found);
487 }
488
489 return results;
490 }
491
492 size_t value_container::remove_batch(std::span<const std::string_view> keys)
493 {
494 if (keys.empty()) {
495 return 0;
496 }
497
498 write_lock_guard lock(this);
499
500 if (!parsed_data_) {
501 deserialize_values(data_string_, false);
502 }
503
504 // Build a set of keys for O(1) lookup
505 std::unordered_set<std::string_view> key_set(keys.begin(), keys.end());
506
507 // Count and remove matching elements
508 size_t original_size = optimized_units_.size();
509 optimized_units_.erase(
510 std::remove_if(optimized_units_.begin(), optimized_units_.end(),
511 [&key_set](const optimized_value& ov) {
512 return key_set.find(ov.name) != key_set.end();
513 }),
514 optimized_units_.end());
515
516 size_t removed = original_size - optimized_units_.size();
517 if (removed > 0) {
518 changed_data_ = true;
519 }
520
521 return removed;
522 }
523
524 bool value_container::update_if(
525 std::string_view key,
526 const value_variant& expected,
527 value_variant&& new_value)
528 {
529 write_lock_guard lock(this);
530
531 for (auto& val : optimized_units_) {
532 if (val.name == key) {
533 // Compare current value with expected
534 if (val.data == expected) {
535 val.data = std::move(new_value);
536 val.type = static_cast<value_types>(val.data.index());
537 changed_data_ = true;
538 return true;
539 }
540 return false;
541 }
542 }
543
544 return false;
545 }
546
547 std::vector<bool> value_container::update_batch_if(
548 std::span<const update_spec> updates)
549 {
550 std::vector<bool> results;
551 results.reserve(updates.size());
552
553 if (updates.empty()) {
554 return results;
555 }
556
557 write_lock_guard lock(this);
558
559 for (const auto& update : updates) {
560 bool updated = false;
561 for (auto& val : optimized_units_) {
562 if (val.name == update.key) {
563 if (val.data == update.expected) {
564 val.data = update.new_value;
565 val.type = static_cast<value_types>(val.data.index());
566 changed_data_ = true;
567 updated = true;
568 }
569 break;
570 }
571 }
572 results.push_back(updated);
573 }
574
575 return results;
576 }
577
578
579 std::vector<optimized_value> value_container::get_variant_values() const
580 {
581 read_lock_guard lock(this);
582 return optimized_units_;
583 }
584
585 // =======================================================================
586 // Zero-Copy Deserialization Implementation (Issue #226)
587 // =======================================================================
588
589 void value_container::ensure_index_built() const
590 {
591 read_lock_guard lock(this);
592 if (!index_built_) {
593 build_index();
594 }
595 }
596
597 void value_container::build_index() const
598 {
599 if (index_built_ || !raw_data_ptr_) {
600 return;
601 }
602
603 value_index_ = std::vector<value_index_entry>();
604 const std::string& data = *raw_data_ptr_;
605
606 // Find the @data section
607 // Match both single and double braces for @data section
608 std::regex reData("@data=\\s*\\{\\{?\\s*(.*?)\\s*\\}\\}?;");
609 std::smatch dataMatch;
610 if (!std::regex_search(data, dataMatch, reData)) {
611 index_built_ = true;
612 return;
613 }
614
615 // Get the position of the data section in the original string
616 size_t dataStart = static_cast<size_t>(dataMatch.position(1));
617 std::string dataInside = dataMatch[1].str();
618
619 // Parse items: [name,type,data];
620 std::regex reItems("\\[(\\w+),\\s*(\\w+),\\s*(.*?)\\];");
621 auto it = std::sregex_iterator(dataInside.begin(), dataInside.end(), reItems);
622 auto end = std::sregex_iterator();
623
624 for (; it != end; ++it) {
625 value_index_entry entry;
626
627 // Calculate offsets into the original raw data
628 size_t matchPos = static_cast<size_t>(it->position());
629 size_t nameStart = dataStart + matchPos + 1; // +1 for '['
630 size_t nameLen = (*it)[1].length();
631
632 // Store name as string_view into raw data
633 entry.name = std::string_view(data.data() + nameStart, nameLen);
634
635 // Parse type
636 std::string typeStr = (*it)[2].str();
637 entry.type = convert_value_type(typeStr);
638
639 // Calculate value offset and length
640 // Value starts after [name,type,
641 size_t valueStart = dataStart + matchPos + 1 + nameLen + 1 + (*it)[2].length() + 1;
642 // +1 for '[', +1 for first ',', +1 for second ','
643 entry.value_offset = valueStart;
644 entry.value_length = (*it)[3].length();
645
646 value_index_->push_back(entry);
647 }
648
649 index_built_ = true;
650 }
651
652 // =======================================================================
653
654 void value_container::initialize(void)
655 {
656 source_id_.clear();
657 source_sub_id_.clear();
658 target_id_.clear();
659 target_sub_id_.clear();
660 message_type_ = "data_container";
661 version_ = "1.0";
662
663 clear_value();
664 }
665
666 // Note: serialize_impl() removed in Issue #315
667 // Serialization logic moved to binary_serializer strategy class
668 // See: core/serializers/binary_serializer.cpp
669
670 bool value_container::deserialize(const std::string& data_str,
671 bool parse_only_header)
672 {
673 // Record metrics if enabled
674 auto timer = metrics_manager::make_timer(
675 metrics_manager::get().deserialize_latency,
676 &metrics_manager::get().timing.total_deserialize_ns);
677 if (metrics_manager::is_enabled())
678 {
679 metrics_manager::get().operations.deserializations.fetch_add(1, std::memory_order_relaxed);
680 }
681
682 initialize();
683 if (data_str.empty())
684 return false;
685
686 // Remove newlines
687 std::regex newlineRe("\\r\\n?|\\n");
688 std::string clean = std::regex_replace(data_str, newlineRe, "");
689
690 // parse header portion - matches both single and double braces
691 std::regex fullRe("@header=\\s*\\{\\{?\\s*(.*?)\\s*\\}\\}?;");
692 std::smatch match;
693 if (!std::regex_search(clean, match, fullRe))
694 {
695 // No header => parse as data only
696 return deserialize_values(clean, parse_only_header);
697 }
698 // match[1] => inside the header
699 std::string headerInside = match[1].str();
700 std::regex pairRe("\\[(\\w+),(.*?)\\];");
701 auto it = std::sregex_iterator(headerInside.begin(), headerInside.end(),
702 pairRe);
703 auto end = std::sregex_iterator();
704 for (; it != end; ++it)
705 {
706 parsing((*it)[1].str(), std::to_string(TARGET_ID), (*it)[2].str(), target_id_);
707 parsing((*it)[1].str(), std::to_string(TARGET_SUB_ID), (*it)[2].str(), target_sub_id_);
708 parsing((*it)[1].str(), std::to_string(SOURCE_ID), (*it)[2].str(), source_id_);
709 parsing((*it)[1].str(), std::to_string(SOURCE_SUB_ID), (*it)[2].str(), source_sub_id_);
710 parsing((*it)[1].str(), std::to_string(MESSAGE_TYPE), (*it)[2].str(), message_type_);
711 parsing((*it)[1].str(), std::to_string(MESSAGE_VERSION), (*it)[2].str(), version_);
712 }
713
714 return deserialize_values(clean, parse_only_header);
715 }
716
717bool value_container::deserialize(const std::vector<uint8_t>& data_array,
718 bool parse_only_header)
719{
720 auto [strVal, err] = convert_string::to_string(data_array);
721 if (!err.empty())
722 {
723 return false;
724 }
725 return deserialize(strVal, parse_only_header);
726}
727
728// =============================================================================
729// Schema-Validated Deserialization API (Issue #249)
730// =============================================================================
731
732const std::vector<validation_error>& value_container::get_validation_errors() const noexcept
733{
734 return validation_errors_;
735}
736
737void value_container::clear_validation_errors() noexcept
738{
739 validation_errors_.clear();
740}
741
742#if CONTAINER_HAS_RESULT
743 kcenon::common::VoidResult value_container::deserialize_result(
744 const std::string& data_str,
745 bool parse_only_header) noexcept
746 {
747 if (deserialize(data_str, parse_only_header))
748 {
749 return kcenon::common::ok();
750 }
751 return kcenon::common::VoidResult(
752 kcenon::common::error_info{
753 error_codes::deserialization_failed,
754 error_codes::make_message(error_codes::deserialization_failed, "string data"),
755 "container_system"});
756 }
757
758 kcenon::common::VoidResult value_container::deserialize_result(
759 const std::vector<uint8_t>& data_array,
760 bool parse_only_header) noexcept
761 {
762 if (deserialize(data_array, parse_only_header))
763 {
764 return kcenon::common::ok();
765 }
766 return kcenon::common::VoidResult(
767 kcenon::common::error_info{
768 error_codes::deserialization_failed,
769 error_codes::make_message(error_codes::deserialization_failed, "byte array data"),
770 "container_system"});
771 }
772
773 // Schema-validated deserialize_result overloads
774 kcenon::common::VoidResult value_container::deserialize_result(
775 const std::string& data_string,
776 const container_schema& schema,
777 bool parse_only_header) noexcept
778 {
779 // Clear previous validation errors
780 validation_errors_.clear();
781
782 // First, deserialize the data
783 auto deser_result = deserialize_result(data_string, parse_only_header);
784 if (!deser_result.is_ok())
785 {
786 return deser_result;
787 }
788
789 // Then validate against the schema
790 validation_errors_ = schema.validate_all(*this);
791 if (!validation_errors_.empty())
792 {
793 const auto& first_error = validation_errors_.front();
794 return kcenon::common::VoidResult(
795 kcenon::common::error_info{
796 first_error.code,
797 first_error.message,
798 "container_schema"});
799 }
800 return kcenon::common::ok();
801 }
802
803 kcenon::common::VoidResult value_container::deserialize_result(
804 const std::vector<uint8_t>& data_array,
805 const container_schema& schema,
806 bool parse_only_header) noexcept
807 {
808 // Clear previous validation errors
809 validation_errors_.clear();
810
811 // First, deserialize the data
812 auto deser_result = deserialize_result(data_array, parse_only_header);
813 if (!deser_result.is_ok())
814 {
815 return deser_result;
816 }
817
818 // Then validate against the schema
819 validation_errors_ = schema.validate_all(*this);
820 if (!validation_errors_.empty())
821 {
822 const auto& first_error = validation_errors_.front();
823 return kcenon::common::VoidResult(
824 kcenon::common::error_info{
825 first_error.code,
826 first_error.message,
827 "container_schema"});
828 }
829 return kcenon::common::ok();
830 }
831
832 kcenon::common::Result<optimized_value> value_container::get_result(
833 std::string_view key) const noexcept
834 {
835 read_lock_guard lock(this);
836
837 for (const auto& val : optimized_units_)
838 {
839 if (val.name == key)
840 {
841 return kcenon::common::ok(val);
842 }
843 }
844
845 return kcenon::common::Result<optimized_value>(
846 kcenon::common::error_info{
847 error_codes::key_not_found,
848 error_codes::make_message(error_codes::key_not_found, key),
849 "container_system"});
850 }
851
852 kcenon::common::VoidResult value_container::set_result(
853 const optimized_value& val) noexcept
854 {
855 try
856 {
857 if (val.name.empty())
858 {
859 return kcenon::common::VoidResult(
860 kcenon::common::error_info{
861 error_codes::empty_key,
862 error_codes::make_message(error_codes::empty_key),
863 "container_system"});
864 }
865
866 set_unit_impl(val);
867 return kcenon::common::ok();
868 }
869 catch (const std::bad_alloc&)
870 {
871 return kcenon::common::VoidResult(
872 kcenon::common::error_info{
873 error_codes::memory_allocation_failed,
874 error_codes::make_message(error_codes::memory_allocation_failed, val.name),
875 "container_system"});
876 }
877 catch (const std::exception& e)
878 {
879 return kcenon::common::VoidResult(
880 kcenon::common::error_info{
881 error_codes::invalid_value,
882 std::string("Failed to set value: ") + e.what(),
883 "container_system"});
884 }
885 }
886
887 kcenon::common::VoidResult value_container::set_all_result(
888 std::span<const optimized_value> vals) noexcept
889 {
890 try
891 {
892 for (const auto& val : vals)
893 {
894 if (val.name.empty())
895 {
896 return kcenon::common::VoidResult(
897 kcenon::common::error_info{
898 error_codes::empty_key,
899 error_codes::make_message(error_codes::empty_key),
900 "container_system"});
901 }
902 set_unit_impl(val);
903 }
904 return kcenon::common::ok();
905 }
906 catch (const std::bad_alloc&)
907 {
908 return kcenon::common::VoidResult(
909 kcenon::common::error_info{
910 error_codes::memory_allocation_failed,
911 error_codes::make_message(error_codes::memory_allocation_failed),
912 "container_system"});
913 }
914 catch (const std::exception& e)
915 {
916 return kcenon::common::VoidResult(
917 kcenon::common::error_info{
918 error_codes::invalid_value,
919 std::string("Failed to set values: ") + e.what(),
920 "container_system"});
921 }
922 }
923
924 kcenon::common::VoidResult value_container::remove_result(
925 std::string_view target_name) noexcept
926 {
927 try
928 {
929 write_lock_guard lock(this);
930
931 if (!parsed_data_)
932 {
933 deserialize_values(data_string_, false);
934 }
935
936 auto it = std::find_if(optimized_units_.begin(), optimized_units_.end(),
937 [&target_name](const optimized_value& ov)
938 { return (ov.name == target_name); });
939
940 if (it == optimized_units_.end())
941 {
942 return kcenon::common::VoidResult(
943 kcenon::common::error_info{
944 error_codes::key_not_found,
945 error_codes::make_message(error_codes::key_not_found, target_name),
946 "container_system"});
947 }
948
949 // Remove all occurrences
950 optimized_units_.erase(
951 std::remove_if(optimized_units_.begin(), optimized_units_.end(),
952 [&target_name](const optimized_value& ov)
953 { return (ov.name == target_name); }),
954 optimized_units_.end());
955
956 changed_data_ = true;
957 return kcenon::common::ok();
958 }
959 catch (const std::exception& e)
960 {
961 return kcenon::common::VoidResult(
962 kcenon::common::error_info{
963 error_codes::invalid_value,
964 std::string("Failed to remove value: ") + e.what(),
965 "container_system"});
966 }
967 }
968
969 kcenon::common::VoidResult value_container::load_packet_result(
970 const std::string& file_path) noexcept
971 {
972 try
973 {
974 std::ifstream file(file_path, std::ios::binary);
975 if (!file)
976 {
977 return kcenon::common::VoidResult(
978 kcenon::common::error_info{
979 error_codes::file_not_found,
980 error_codes::make_message(error_codes::file_not_found, file_path),
981 "container_system"});
982 }
983
984 std::string content((std::istreambuf_iterator<char>(file)),
985 std::istreambuf_iterator<char>());
986
987 if (file.bad())
988 {
989 return kcenon::common::VoidResult(
990 kcenon::common::error_info{
991 error_codes::file_read_error,
992 error_codes::make_message(error_codes::file_read_error, file_path),
993 "container_system"});
994 }
995
996 return deserialize_result(content, false);
997 }
998 catch (const std::bad_alloc&)
999 {
1000 return kcenon::common::VoidResult(
1001 kcenon::common::error_info{
1002 error_codes::memory_allocation_failed,
1003 error_codes::make_message(error_codes::memory_allocation_failed, file_path),
1004 "container_system"});
1005 }
1006 catch (const std::exception& e)
1007 {
1008 return kcenon::common::VoidResult(
1009 kcenon::common::error_info{
1010 error_codes::file_read_error,
1011 std::string("File read error: ") + e.what(),
1012 "container_system"});
1013 }
1014 }
1015
1016 kcenon::common::VoidResult value_container::save_packet_result(
1017 const std::string& file_path) noexcept
1018 {
1019 try
1020 {
1021 auto serialize_res = serialize_string(serialization_format::binary);
1022 if (!serialize_res.is_ok())
1023 {
1024 return kcenon::common::VoidResult(serialize_res.error());
1025 }
1026
1027 std::ofstream file(file_path, std::ios::binary | std::ios::trunc);
1028 if (!file)
1029 {
1030 return kcenon::common::VoidResult(
1031 kcenon::common::error_info{
1032 error_codes::file_write_error,
1033 error_codes::make_message(error_codes::file_write_error, file_path),
1034 "container_system"});
1035 }
1036
1037 const auto& content = serialize_res.value();
1038 file.write(content.data(), static_cast<std::streamsize>(content.size()));
1039
1040 if (file.bad())
1041 {
1042 return kcenon::common::VoidResult(
1043 kcenon::common::error_info{
1044 error_codes::file_write_error,
1045 error_codes::make_message(error_codes::file_write_error, file_path),
1046 "container_system"});
1047 }
1048
1049 return kcenon::common::ok();
1050 }
1051 catch (const std::bad_alloc&)
1052 {
1053 return kcenon::common::VoidResult(
1054 kcenon::common::error_info{
1055 error_codes::memory_allocation_failed,
1056 error_codes::make_message(error_codes::memory_allocation_failed, file_path),
1057 "container_system"});
1058 }
1059 catch (const std::exception& e)
1060 {
1061 return kcenon::common::VoidResult(
1062 kcenon::common::error_info{
1063 error_codes::file_write_error,
1064 std::string("File write error: ") + e.what(),
1065 "container_system"});
1066 }
1067 }
1068
1069 // =======================================================================
1070 // Batch Operation APIs with Result return type (Issue #229)
1071 // =======================================================================
1072
1073 kcenon::common::VoidResult value_container::bulk_insert_result(
1074 std::vector<optimized_value>&& values) noexcept
1075 {
1076 try
1077 {
1078 bulk_insert(std::move(values));
1079 return kcenon::common::ok();
1080 }
1081 catch (const std::bad_alloc&)
1082 {
1083 return kcenon::common::VoidResult(
1084 kcenon::common::error_info{
1085 error_codes::memory_allocation_failed,
1086 error_codes::make_message(error_codes::memory_allocation_failed),
1087 "container_system"});
1088 }
1089 catch (const std::exception& e)
1090 {
1091 return kcenon::common::VoidResult(
1092 kcenon::common::error_info{
1093 error_codes::invalid_value,
1094 std::string("Bulk insert failed: ") + e.what(),
1095 "container_system"});
1096 }
1097 }
1098
1099 kcenon::common::Result<std::vector<std::optional<optimized_value>>>
1100 value_container::get_batch_result(
1101 std::span<const std::string_view> keys) const noexcept
1102 {
1103 try
1104 {
1105 return kcenon::common::ok(get(keys));
1106 }
1107 catch (const std::bad_alloc&)
1108 {
1109 return kcenon::common::Result<std::vector<std::optional<optimized_value>>>(
1110 kcenon::common::error_info{
1111 error_codes::memory_allocation_failed,
1112 error_codes::make_message(error_codes::memory_allocation_failed),
1113 "container_system"});
1114 }
1115 catch (const std::exception& e)
1116 {
1117 return kcenon::common::Result<std::vector<std::optional<optimized_value>>>(
1118 kcenon::common::error_info{
1119 error_codes::invalid_value,
1120 std::string("Batch get failed: ") + e.what(),
1121 "container_system"});
1122 }
1123 }
1124
1125 kcenon::common::Result<size_t> value_container::remove_batch_result(
1126 std::span<const std::string_view> keys) noexcept
1127 {
1128 try
1129 {
1130 return kcenon::common::ok(remove_batch(keys));
1131 }
1132 catch (const std::bad_alloc&)
1133 {
1134 return kcenon::common::Result<size_t>(
1135 kcenon::common::error_info{
1136 error_codes::memory_allocation_failed,
1137 error_codes::make_message(error_codes::memory_allocation_failed),
1138 "container_system"});
1139 }
1140 catch (const std::exception& e)
1141 {
1142 return kcenon::common::Result<size_t>(
1143 kcenon::common::error_info{
1144 error_codes::invalid_value,
1145 std::string("Batch remove failed: ") + e.what(),
1146 "container_system"});
1147 }
1148 }
1149#endif
1150
1151 // Note: to_xml_impl(), to_json_impl(), to_msgpack_impl() removed in Issue #315
1152 // Serialization logic moved to respective serializer strategy classes:
1153 // - core/serializers/xml_serializer.cpp
1154 // - core/serializers/json_serializer.cpp
1155 // - core/serializers/msgpack_serializer.cpp
1156
1157 // =======================================================================
1158 // MessagePack Internal Deserialization Implementation (Issue #234, #299)
1159 // =======================================================================
1160
1161 bool value_container::from_msgpack_impl(const std::vector<uint8_t>& data)
1162 {
1163 // Record metrics if enabled
1164 auto timer = metrics_manager::make_timer(
1165 metrics_manager::get().deserialize_latency,
1166 &metrics_manager::get().timing.total_deserialize_ns);
1167 if (metrics_manager::is_enabled())
1168 {
1169 metrics_manager::get().operations.deserializations.fetch_add(1, std::memory_order_relaxed);
1170 }
1171
1172 if (data.empty())
1173 {
1174 return false;
1175 }
1176
1177 initialize();
1178
1179 msgpack_decoder decoder(data);
1180
1181 // Expect outer map
1182 auto outer_count = decoder.read_map_header();
1183 if (!outer_count)
1184 {
1185 return false;
1186 }
1187
1188 std::unique_lock<std::shared_mutex> lock(mutex_);
1189
1190 for (size_t i = 0; i < *outer_count; ++i)
1191 {
1192 auto key = decoder.read_string();
1193 if (!key)
1194 {
1195 return false;
1196 }
1197
1198 if (*key == "header")
1199 {
1200 auto header_count = decoder.read_map_header();
1201 if (!header_count)
1202 {
1203 return false;
1204 }
1205
1206 for (size_t j = 0; j < *header_count; ++j)
1207 {
1208 auto hkey = decoder.read_string();
1209 auto hval = decoder.read_string();
1210 if (!hkey || !hval)
1211 {
1212 return false;
1213 }
1214
1215 if (*hkey == "target_id")
1216 {
1217 target_id_ = *hval;
1218 }
1219 else if (*hkey == "target_sub_id")
1220 {
1221 target_sub_id_ = *hval;
1222 }
1223 else if (*hkey == "source_id")
1224 {
1225 source_id_ = *hval;
1226 }
1227 else if (*hkey == "source_sub_id")
1228 {
1229 source_sub_id_ = *hval;
1230 }
1231 else if (*hkey == "message_type")
1232 {
1233 message_type_ = *hval;
1234 }
1235 else if (*hkey == "version")
1236 {
1237 version_ = *hval;
1238 }
1239 }
1240 }
1241 else if (*key == "values")
1242 {
1243 auto values_count = decoder.read_map_header();
1244 if (!values_count)
1245 {
1246 return false;
1247 }
1248
1249 for (size_t j = 0; j < *values_count; ++j)
1250 {
1251 auto vkey = decoder.read_string();
1252 if (!vkey)
1253 {
1254 return false;
1255 }
1256
1257 optimized_value val;
1258 val.name = *vkey;
1259
1260 // Read value based on type
1261 auto type = decoder.peek_type();
1262 switch (type)
1263 {
1264 case msgpack_type::nil:
1265 decoder.read_nil();
1266 val.type = value_types::null_value;
1267 val.data = std::monostate{};
1268 break;
1269
1270 case msgpack_type::boolean:
1271 {
1272 auto b = decoder.read_bool();
1273 if (!b)
1274 {
1275 return false;
1276 }
1277 val.type = value_types::bool_value;
1278 val.data = *b;
1279 }
1280 break;
1281
1282 case msgpack_type::positive_int:
1283 case msgpack_type::negative_int:
1284 {
1285 auto n = decoder.read_int();
1286 if (!n)
1287 {
1288 return false;
1289 }
1290 // Determine best type based on value
1291 if (*n >= 0 && *n <= INT32_MAX)
1292 {
1293 val.type = value_types::int_value;
1294 val.data = static_cast<int>(*n);
1295 }
1296 else if (*n >= INT32_MIN && *n < 0)
1297 {
1298 val.type = value_types::int_value;
1299 val.data = static_cast<int>(*n);
1300 }
1301 else
1302 {
1303 val.type = value_types::llong_value;
1304 val.data = static_cast<long long>(*n);
1305 }
1306 }
1307 break;
1308
1309 case msgpack_type::float32:
1310 {
1311 auto f = decoder.read_float();
1312 if (!f)
1313 {
1314 return false;
1315 }
1316 val.type = value_types::float_value;
1317 val.data = *f;
1318 }
1319 break;
1320
1321 case msgpack_type::float64:
1322 {
1323 auto d = decoder.read_double();
1324 if (!d)
1325 {
1326 return false;
1327 }
1328 val.type = value_types::double_value;
1329 val.data = *d;
1330 }
1331 break;
1332
1333 case msgpack_type::str:
1334 {
1335 auto s = decoder.read_string();
1336 if (!s)
1337 {
1338 return false;
1339 }
1340 val.type = value_types::string_value;
1341 val.data = *s;
1342 }
1343 break;
1344
1345 case msgpack_type::bin:
1346 {
1347 auto b = decoder.read_binary();
1348 if (!b)
1349 {
1350 return false;
1351 }
1352 // Probe: try to decode as a nested container first.
1353 // Nested containers are serialized as msgpack binary
1354 // containing a msgpack-encoded map with "header"/"values" keys.
1355 auto nested = std::make_shared<value_container>();
1356 if (b->size() >= 2 && nested->from_msgpack_impl(*b))
1357 {
1358 val.type = value_types::container_value;
1359 val.data = nested;
1360 }
1361 else
1362 {
1363 val.type = value_types::bytes_value;
1364 val.data = *b;
1365 }
1366 }
1367 break;
1368
1369 case msgpack_type::array:
1370 {
1371 auto arr_size = decoder.read_array_header();
1372 if (!arr_size)
1373 {
1374 return false;
1375 }
1376 auto arr = std::make_shared<array_values>();
1377 arr->items.reserve(*arr_size);
1378 for (size_t ai = 0; ai < *arr_size; ++ai)
1379 {
1380 auto elem_type = decoder.peek_type();
1381 value_variant elem_data = std::monostate{};
1382 switch (elem_type)
1383 {
1384 case msgpack_type::nil:
1385 decoder.read_nil();
1386 break;
1387 case msgpack_type::boolean:
1388 if (auto bv = decoder.read_bool()) elem_data = *bv;
1389 break;
1390 case msgpack_type::positive_int:
1391 case msgpack_type::negative_int:
1392 if (auto nv = decoder.read_int()) elem_data = static_cast<long long>(*nv);
1393 break;
1394 case msgpack_type::float32:
1395 if (auto fv = decoder.read_float()) elem_data = *fv;
1396 break;
1397 case msgpack_type::float64:
1398 if (auto dv = decoder.read_double()) elem_data = *dv;
1399 break;
1400 case msgpack_type::str:
1401 if (auto sv = decoder.read_string()) elem_data = *sv;
1402 break;
1403 case msgpack_type::bin:
1404 if (auto bv = decoder.read_binary()) elem_data = *bv;
1405 break;
1406 default:
1407 break;
1408 }
1409 arr->items.push_back(std::move(elem_data));
1410 }
1411 val.type = value_types::array_value;
1412 val.data = arr;
1413 }
1414 break;
1415
1416 default:
1417 // Skip unknown types
1418 val.type = value_types::null_value;
1419 val.data = std::monostate{};
1420 break;
1421 }
1422
1423 optimized_units_.push_back(std::move(val));
1424 }
1425 }
1426 }
1427
1428 parsed_data_ = true;
1429 changed_data_ = false;
1430
1431 return true;
1432 }
1433
1434 value_container::serialization_format value_container::detect_format(
1435 const std::vector<uint8_t>& data)
1436 {
1437 if (data.empty())
1438 {
1439 return serialization_format::unknown;
1440 }
1441
1442 // Check for MessagePack format
1443 // MessagePack maps start with 0x80-0x8f (fixmap) or 0xde (map16) or 0xdf (map32)
1444 uint8_t first_byte = data[0];
1445 if ((first_byte >= 0x80 && first_byte <= 0x8f) || // fixmap
1446 first_byte == 0xde || // map16
1447 first_byte == 0xdf) // map32
1448 {
1449 return serialization_format::msgpack;
1450 }
1451
1452 // Check for text-based formats (convert to string for analysis)
1453 std::string_view str_view(reinterpret_cast<const char*>(data.data()), data.size());
1454 return detect_format(str_view);
1455 }
1456
1457 value_container::serialization_format value_container::detect_format(
1458 std::string_view data)
1459 {
1460 if (data.empty())
1461 {
1462 return serialization_format::unknown;
1463 }
1464
1465 // Skip leading whitespace
1466 size_t pos = 0;
1467 while (pos < data.size() && std::isspace(static_cast<unsigned char>(data[pos])))
1468 {
1469 ++pos;
1470 }
1471
1472 if (pos >= data.size())
1473 {
1474 return serialization_format::unknown;
1475 }
1476
1477 // Check first non-whitespace character
1478 char first_char = data[pos];
1479
1480 // JSON starts with '{' or '['
1481 if (first_char == '{' || first_char == '[')
1482 {
1483 return serialization_format::json;
1484 }
1485
1486 // XML starts with '<'
1487 if (first_char == '<')
1488 {
1489 return serialization_format::xml;
1490 }
1491
1492 // Binary format starts with "@header"
1493 if (data.substr(pos, 7) == "@header")
1494 {
1495 return serialization_format::binary;
1496 }
1497
1498 // Binary format may also start with "@data"
1499 if (data.substr(pos, 5) == "@data")
1500 {
1501 return serialization_format::binary;
1502 }
1503
1504 return serialization_format::unknown;
1505 }
1506
1507#if CONTAINER_HAS_COMMON_RESULT
1508 // =======================================================================
1509 // Unified Serialization API (Issue #286)
1510 // =======================================================================
1511
1512 kcenon::common::Result<std::vector<uint8_t>> value_container::serialize(
1513 serialization_format fmt) const noexcept
1514 {
1515 // Record metrics if enabled
1516 auto timer = metrics_manager::make_timer(
1517 metrics_manager::get().serialize_latency,
1518 &metrics_manager::get().timing.total_serialize_ns);
1519 if (metrics_manager::is_enabled())
1520 {
1521 metrics_manager::get().operations.serializations.fetch_add(1, std::memory_order_relaxed);
1522 }
1523
1524 // Convert internal format enum to serializer format enum
1525 auto serializer_fmt = static_cast<kcenon::container::serialization_format>(
1526 static_cast<int>(fmt));
1527
1528 // Use serializer factory to create appropriate serializer
1529 auto serializer = serializer_factory::create(serializer_fmt);
1530 if (!serializer)
1531 {
1532 return kcenon::common::Result<std::vector<uint8_t>>(
1533 kcenon::common::error_info{
1534 error_codes::invalid_format,
1535 "Cannot serialize with auto_detect or unknown format",
1536 "container_system"});
1537 }
1538
1539 return serializer->serialize(*this);
1540 }
1541
1542 kcenon::common::Result<std::string> value_container::serialize_string(
1543 serialization_format fmt) const noexcept
1544 {
1545 // Record metrics if enabled
1546 auto timer = metrics_manager::make_timer(
1547 metrics_manager::get().serialize_latency,
1548 &metrics_manager::get().timing.total_serialize_ns);
1549 if (metrics_manager::is_enabled())
1550 {
1551 metrics_manager::get().operations.serializations.fetch_add(1, std::memory_order_relaxed);
1552 }
1553
1554 try
1555 {
1556 // Use format-specific serializers with serialize_to_string
1557 switch (fmt)
1558 {
1559 case serialization_format::binary:
1560 {
1561 binary_serializer serializer;
1562 return kcenon::common::ok(serializer.serialize_to_string(*this));
1563 }
1564 case serialization_format::json:
1565 {
1566 json_serializer serializer;
1567 return kcenon::common::ok(serializer.serialize_to_string(*this));
1568 }
1569 case serialization_format::xml:
1570 {
1571 xml_serializer serializer;
1572 return kcenon::common::ok(serializer.serialize_to_string(*this));
1573 }
1574 case serialization_format::msgpack:
1575 {
1576 // MessagePack is binary format, convert to string
1577 msgpack_serializer serializer;
1578 auto result = serializer.serialize(*this);
1579 if (!result.is_ok())
1580 {
1581 return kcenon::common::Result<std::string>(result.error());
1582 }
1583 const auto& bytes = result.value();
1584 return kcenon::common::ok(std::string(bytes.begin(), bytes.end()));
1585 }
1586 case serialization_format::auto_detect:
1587 case serialization_format::unknown:
1588 default:
1589 return kcenon::common::Result<std::string>(
1590 kcenon::common::error_info{
1591 error_codes::invalid_format,
1592 "Cannot serialize with auto_detect or unknown format",
1593 "container_system"});
1594 }
1595 }
1596 catch (const std::bad_alloc&)
1597 {
1598 return kcenon::common::Result<std::string>(
1599 kcenon::common::error_info{
1600 error_codes::memory_allocation_failed,
1601 error_codes::make_message(error_codes::memory_allocation_failed),
1602 "container_system"});
1603 }
1604 catch (const std::exception& e)
1605 {
1606 return kcenon::common::Result<std::string>(
1607 kcenon::common::error_info{
1608 error_codes::serialization_failed,
1609 std::string("Serialization failed: ") + e.what(),
1610 "container_system"});
1611 }
1612 }
1613
1614 kcenon::common::VoidResult value_container::deserialize(
1615 std::span<const uint8_t> data) noexcept
1616 {
1617 // Auto-detect format
1618 std::vector<uint8_t> data_vec(data.begin(), data.end());
1619 auto fmt = detect_format(data_vec);
1620 return deserialize(data, fmt);
1621 }
1622
1623 kcenon::common::VoidResult value_container::deserialize(
1624 std::span<const uint8_t> data,
1625 serialization_format fmt) noexcept
1626 {
1627 try
1628 {
1629 // Handle auto-detect
1630 if (fmt == serialization_format::auto_detect)
1631 {
1632 std::vector<uint8_t> data_vec(data.begin(), data.end());
1633 fmt = detect_format(data_vec);
1634 }
1635
1636 switch (fmt)
1637 {
1638 case serialization_format::binary:
1639 case serialization_format::json:
1640 case serialization_format::xml:
1641 {
1642 // Convert to string for text-based formats
1643 std::string str_data(data.begin(), data.end());
1644 return deserialize_result(str_data, false);
1645 }
1646 case serialization_format::msgpack:
1647 {
1648 std::vector<uint8_t> data_vec(data.begin(), data.end());
1649 if (from_msgpack_impl(data_vec))
1650 {
1651 return kcenon::common::ok();
1652 }
1653 return kcenon::common::VoidResult(
1654 kcenon::common::error_info{
1655 error_codes::deserialization_failed,
1656 error_codes::make_message(error_codes::deserialization_failed, "Invalid MessagePack data"),
1657 "container_system"});
1658 }
1659 case serialization_format::unknown:
1660 default:
1661 return kcenon::common::VoidResult(
1662 kcenon::common::error_info{
1663 error_codes::invalid_format,
1664 "Unknown or unsupported serialization format",
1665 "container_system"});
1666 }
1667 }
1668 catch (const std::bad_alloc&)
1669 {
1670 return kcenon::common::VoidResult(
1671 kcenon::common::error_info{
1672 error_codes::memory_allocation_failed,
1673 error_codes::make_message(error_codes::memory_allocation_failed),
1674 "container_system"});
1675 }
1676 catch (const std::exception& e)
1677 {
1678 return kcenon::common::VoidResult(
1679 kcenon::common::error_info{
1680 error_codes::deserialization_failed,
1681 std::string("Deserialization failed: ") + e.what(),
1682 "container_system"});
1683 }
1684 }
1685
1686 kcenon::common::VoidResult value_container::deserialize(
1687 std::string_view data) noexcept
1688 {
1689 // Auto-detect format
1690 auto fmt = detect_format(data);
1691 return deserialize(data, fmt);
1692 }
1693
1694 kcenon::common::VoidResult value_container::deserialize(
1695 std::string_view data,
1696 serialization_format fmt) noexcept
1697 {
1698 try
1699 {
1700 // Handle auto-detect
1701 if (fmt == serialization_format::auto_detect)
1702 {
1703 fmt = detect_format(data);
1704 }
1705
1706 switch (fmt)
1707 {
1708 case serialization_format::binary:
1709 case serialization_format::json:
1710 case serialization_format::xml:
1711 {
1712 return deserialize_result(std::string(data), false);
1713 }
1714 case serialization_format::msgpack:
1715 {
1716 std::vector<uint8_t> data_vec(data.begin(), data.end());
1717 if (from_msgpack_impl(data_vec))
1718 {
1719 return kcenon::common::ok();
1720 }
1721 return kcenon::common::VoidResult(
1722 kcenon::common::error_info{
1723 error_codes::deserialization_failed,
1724 error_codes::make_message(error_codes::deserialization_failed, "Invalid MessagePack data"),
1725 "container_system"});
1726 }
1727 case serialization_format::unknown:
1728 default:
1729 return kcenon::common::VoidResult(
1730 kcenon::common::error_info{
1731 error_codes::invalid_format,
1732 "Unknown or unsupported serialization format",
1733 "container_system"});
1734 }
1735 }
1736 catch (const std::bad_alloc&)
1737 {
1738 return kcenon::common::VoidResult(
1739 kcenon::common::error_info{
1740 error_codes::memory_allocation_failed,
1741 error_codes::make_message(error_codes::memory_allocation_failed),
1742 "container_system"});
1743 }
1744 catch (const std::exception& e)
1745 {
1746 return kcenon::common::VoidResult(
1747 kcenon::common::error_info{
1748 error_codes::deserialization_failed,
1749 std::string("Deserialization failed: ") + e.what(),
1750 "container_system"});
1751 }
1752 }
1753#endif
1754
1755 // =======================================================================
1756
1757 std::string value_container::datas(void) const
1758 {
1759 if (!parsed_data_)
1760 {
1761 return data_string_;
1762 }
1763 // Rebuild from top-level units
1764 std::string result;
1765 formatter::format_to(std::back_inserter(result), "@data={{{{");
1766 for (auto& u : optimized_units_)
1767 {
1768 std::string value_str = variant_helpers::to_string(u.data, u.type);
1769 std::string type_str = convert_value_type(u.type);
1770 formatter::format_to(std::back_inserter(result), "[{},{},{}];",
1771 u.name, type_str, value_str);
1772 }
1773 formatter::format_to(std::back_inserter(result), "}}}};");
1774 return result;
1775 }
1776
1777 size_t value_container::memory_footprint() const
1778 {
1779 std::shared_lock<std::shared_mutex> lock(mutex_);
1780
1781 size_t total = sizeof(value_container);
1782
1783 // Add header strings
1784 total += source_id_.capacity();
1785 total += source_sub_id_.capacity();
1786 total += target_id_.capacity();
1787 total += target_sub_id_.capacity();
1788 total += message_type_.capacity();
1789 total += version_.capacity();
1790
1791 // Add data string
1792 total += data_string_.capacity();
1793
1794 // Add traditional value storage (heap-allocated)
1795
1796 // Add optimized value storage (stack-allocated)
1797 total += optimized_units_.capacity() * sizeof(optimized_value);
1798 for (const auto& ov : optimized_units_)
1799 {
1800 total += ov.memory_footprint();
1801 }
1802
1803 // Add parsed values cache
1804
1805 return total;
1806 }
1807
1808 pool_stats value_container::get_pool_stats()
1809 {
1810#if CONTAINER_USE_MEMORY_POOL
1811 auto& allocator = internal::pool_allocator::instance();
1812 auto stats = allocator.get_stats();
1813 auto small_stats = allocator.get_small_pool_stats();
1814 auto medium_stats = allocator.get_medium_pool_stats();
1815
1816 return pool_stats(
1817 stats.pool_hits,
1818 stats.pool_misses,
1819 stats.small_pool_allocs,
1820 stats.medium_pool_allocs,
1821 stats.deallocations,
1822 small_stats.free_blocks + medium_stats.free_blocks
1823 );
1824#else
1825 return pool_stats(0, 0, 0);
1826#endif
1827 }
1828
1829 void value_container::clear_pool()
1830 {
1831#if CONTAINER_USE_MEMORY_POOL
1832 internal::pool_allocator::instance().reset_stats();
1833#endif
1834 }
1835
1836
1837
1838
1839
1840
1841 std::ostream& operator<<(std::ostream& out, value_container& other)
1842 {
1843 binary_serializer serializer;
1844 out << serializer.serialize_to_string(other);
1845 return out;
1846 }
1847
1848 std::ostream& operator<<(std::ostream& out,
1849 std::shared_ptr<value_container> other)
1850 {
1851 if (other)
1852 {
1853 binary_serializer serializer;
1854 out << serializer.serialize_to_string(*other);
1855 }
1856 return out;
1857 }
1858
1859 std::string& operator<<(std::string& out, value_container& other)
1860 {
1861 binary_serializer serializer;
1862 out = serializer.serialize_to_string(other);
1863 return out;
1864 }
1865
1866 std::string& operator<<(std::string& out,
1867 std::shared_ptr<value_container> other)
1868 {
1869 if (other)
1870 {
1871 binary_serializer serializer;
1872 out = serializer.serialize_to_string(*other);
1873 }
1874 else
1875 out.clear();
1876 return out;
1877 }
1878
1879 // =======================================================================
1880 // Metrics Export Implementation (Issue #230)
1881 // =======================================================================
1882
1883 std::string value_container::metrics_to_json() const
1884 {
1885 auto& m = metrics_manager::get();
1886
1887 std::string result;
1888 result.reserve(2048); // Pre-allocate for performance
1889
1890 result += "{\n";
1891 result += " \"operations\": {\n";
1892 result += " \"reads\": " + std::to_string(m.operations.reads.load(std::memory_order_relaxed)) + ",\n";
1893 result += " \"writes\": " + std::to_string(m.operations.writes.load(std::memory_order_relaxed)) + ",\n";
1894 result += " \"serializations\": " + std::to_string(m.operations.serializations.load(std::memory_order_relaxed)) + ",\n";
1895 result += " \"deserializations\": " + std::to_string(m.operations.deserializations.load(std::memory_order_relaxed)) + ",\n";
1896 result += " \"copies\": " + std::to_string(m.operations.copies.load(std::memory_order_relaxed)) + ",\n";
1897 result += " \"moves\": " + std::to_string(m.operations.moves.load(std::memory_order_relaxed)) + "\n";
1898 result += " },\n";
1899
1900 result += " \"timing\": {\n";
1901 result += " \"total_serialize_ns\": " + std::to_string(m.timing.total_serialize_ns.load(std::memory_order_relaxed)) + ",\n";
1902 result += " \"total_deserialize_ns\": " + std::to_string(m.timing.total_deserialize_ns.load(std::memory_order_relaxed)) + ",\n";
1903 result += " \"total_read_ns\": " + std::to_string(m.timing.total_read_ns.load(std::memory_order_relaxed)) + ",\n";
1904 result += " \"total_write_ns\": " + std::to_string(m.timing.total_write_ns.load(std::memory_order_relaxed)) + "\n";
1905 result += " },\n";
1906
1907 result += " \"latency\": {\n";
1908 result += " \"serialize\": {\n";
1909 result += " \"p50_ns\": " + std::to_string(m.serialize_latency.p50()) + ",\n";
1910 result += " \"p95_ns\": " + std::to_string(m.serialize_latency.p95()) + ",\n";
1911 result += " \"p99_ns\": " + std::to_string(m.serialize_latency.p99()) + ",\n";
1912 result += " \"p999_ns\": " + std::to_string(m.serialize_latency.p999()) + ",\n";
1913 result += " \"max_ns\": " + std::to_string(m.serialize_latency.max_ns.load(std::memory_order_relaxed)) + ",\n";
1914 result += " \"avg_ns\": " + std::to_string(m.serialize_latency.avg()) + "\n";
1915 result += " },\n";
1916 result += " \"deserialize\": {\n";
1917 result += " \"p50_ns\": " + std::to_string(m.deserialize_latency.p50()) + ",\n";
1918 result += " \"p95_ns\": " + std::to_string(m.deserialize_latency.p95()) + ",\n";
1919 result += " \"p99_ns\": " + std::to_string(m.deserialize_latency.p99()) + ",\n";
1920 result += " \"p999_ns\": " + std::to_string(m.deserialize_latency.p999()) + ",\n";
1921 result += " \"max_ns\": " + std::to_string(m.deserialize_latency.max_ns.load(std::memory_order_relaxed)) + ",\n";
1922 result += " \"avg_ns\": " + std::to_string(m.deserialize_latency.avg()) + "\n";
1923 result += " },\n";
1924 result += " \"read\": {\n";
1925 result += " \"p50_ns\": " + std::to_string(m.read_latency.p50()) + ",\n";
1926 result += " \"p95_ns\": " + std::to_string(m.read_latency.p95()) + ",\n";
1927 result += " \"p99_ns\": " + std::to_string(m.read_latency.p99()) + ",\n";
1928 result += " \"p999_ns\": " + std::to_string(m.read_latency.p999()) + ",\n";
1929 result += " \"max_ns\": " + std::to_string(m.read_latency.max_ns.load(std::memory_order_relaxed)) + ",\n";
1930 result += " \"avg_ns\": " + std::to_string(m.read_latency.avg()) + "\n";
1931 result += " },\n";
1932 result += " \"write\": {\n";
1933 result += " \"p50_ns\": " + std::to_string(m.write_latency.p50()) + ",\n";
1934 result += " \"p95_ns\": " + std::to_string(m.write_latency.p95()) + ",\n";
1935 result += " \"p99_ns\": " + std::to_string(m.write_latency.p99()) + ",\n";
1936 result += " \"p999_ns\": " + std::to_string(m.write_latency.p999()) + ",\n";
1937 result += " \"max_ns\": " + std::to_string(m.write_latency.max_ns.load(std::memory_order_relaxed)) + ",\n";
1938 result += " \"avg_ns\": " + std::to_string(m.write_latency.avg()) + "\n";
1939 result += " }\n";
1940 result += " },\n";
1941
1942 result += " \"simd\": {\n";
1943 result += " \"simd_operations\": " + std::to_string(m.simd.simd_operations.load(std::memory_order_relaxed)) + ",\n";
1944 result += " \"scalar_fallbacks\": " + std::to_string(m.simd.scalar_fallbacks.load(std::memory_order_relaxed)) + ",\n";
1945 result += " \"bytes_processed_simd\": " + std::to_string(m.simd.bytes_processed_simd.load(std::memory_order_relaxed)) + ",\n";
1946 result += " \"utilization_percent\": " + std::to_string(m.simd.utilization()) + "\n";
1947 result += " },\n";
1948
1949 result += " \"cache\": {\n";
1950 result += " \"key_index_hits\": " + std::to_string(m.cache.key_index_hits.load(std::memory_order_relaxed)) + ",\n";
1951 result += " \"key_index_misses\": " + std::to_string(m.cache.key_index_misses.load(std::memory_order_relaxed)) + ",\n";
1952 result += " \"value_cache_hits\": " + std::to_string(m.cache.value_cache_hits.load(std::memory_order_relaxed)) + ",\n";
1953 result += " \"value_cache_misses\": " + std::to_string(m.cache.value_cache_misses.load(std::memory_order_relaxed)) + ",\n";
1954 result += " \"key_index_hit_rate_percent\": " + std::to_string(m.cache.key_index_hit_rate()) + ",\n";
1955 result += " \"value_cache_hit_rate_percent\": " + std::to_string(m.cache.value_cache_hit_rate()) + "\n";
1956 result += " }\n";
1957
1958 result += "}";
1959
1960 return result;
1961 }
1962
1963 std::string value_container::metrics_to_prometheus() const
1964 {
1965 auto& m = metrics_manager::get();
1966
1967 std::string result;
1968 result.reserve(4096); // Pre-allocate for performance
1969
1970 // Operation counters
1971 result += "# HELP container_operations_total Total number of container operations\n";
1972 result += "# TYPE container_operations_total counter\n";
1973 result += "container_operations_total{operation=\"read\"} " + std::to_string(m.operations.reads.load(std::memory_order_relaxed)) + "\n";
1974 result += "container_operations_total{operation=\"write\"} " + std::to_string(m.operations.writes.load(std::memory_order_relaxed)) + "\n";
1975 result += "container_operations_total{operation=\"serialize\"} " + std::to_string(m.operations.serializations.load(std::memory_order_relaxed)) + "\n";
1976 result += "container_operations_total{operation=\"deserialize\"} " + std::to_string(m.operations.deserializations.load(std::memory_order_relaxed)) + "\n";
1977 result += "container_operations_total{operation=\"copy\"} " + std::to_string(m.operations.copies.load(std::memory_order_relaxed)) + "\n";
1978 result += "container_operations_total{operation=\"move\"} " + std::to_string(m.operations.moves.load(std::memory_order_relaxed)) + "\n";
1979
1980 // Timing totals
1981 result += "# HELP container_operation_duration_nanoseconds_total Total time spent in operations\n";
1982 result += "# TYPE container_operation_duration_nanoseconds_total counter\n";
1983 result += "container_operation_duration_nanoseconds_total{operation=\"serialize\"} " + std::to_string(m.timing.total_serialize_ns.load(std::memory_order_relaxed)) + "\n";
1984 result += "container_operation_duration_nanoseconds_total{operation=\"deserialize\"} " + std::to_string(m.timing.total_deserialize_ns.load(std::memory_order_relaxed)) + "\n";
1985 result += "container_operation_duration_nanoseconds_total{operation=\"read\"} " + std::to_string(m.timing.total_read_ns.load(std::memory_order_relaxed)) + "\n";
1986 result += "container_operation_duration_nanoseconds_total{operation=\"write\"} " + std::to_string(m.timing.total_write_ns.load(std::memory_order_relaxed)) + "\n";
1987
1988 // Latency percentiles - serialize
1989 result += "# HELP container_serialize_latency_nanoseconds Serialize operation latency percentiles\n";
1990 result += "# TYPE container_serialize_latency_nanoseconds summary\n";
1991 result += "container_serialize_latency_nanoseconds{quantile=\"0.5\"} " + std::to_string(m.serialize_latency.p50()) + "\n";
1992 result += "container_serialize_latency_nanoseconds{quantile=\"0.95\"} " + std::to_string(m.serialize_latency.p95()) + "\n";
1993 result += "container_serialize_latency_nanoseconds{quantile=\"0.99\"} " + std::to_string(m.serialize_latency.p99()) + "\n";
1994 result += "container_serialize_latency_nanoseconds{quantile=\"0.999\"} " + std::to_string(m.serialize_latency.p999()) + "\n";
1995 result += "container_serialize_latency_nanoseconds_max " + std::to_string(m.serialize_latency.max_ns.load(std::memory_order_relaxed)) + "\n";
1996 result += "container_serialize_latency_nanoseconds_count " + std::to_string(m.serialize_latency.sample_count.load(std::memory_order_relaxed)) + "\n";
1997
1998 // Latency percentiles - deserialize
1999 result += "# HELP container_deserialize_latency_nanoseconds Deserialize operation latency percentiles\n";
2000 result += "# TYPE container_deserialize_latency_nanoseconds summary\n";
2001 result += "container_deserialize_latency_nanoseconds{quantile=\"0.5\"} " + std::to_string(m.deserialize_latency.p50()) + "\n";
2002 result += "container_deserialize_latency_nanoseconds{quantile=\"0.95\"} " + std::to_string(m.deserialize_latency.p95()) + "\n";
2003 result += "container_deserialize_latency_nanoseconds{quantile=\"0.99\"} " + std::to_string(m.deserialize_latency.p99()) + "\n";
2004 result += "container_deserialize_latency_nanoseconds{quantile=\"0.999\"} " + std::to_string(m.deserialize_latency.p999()) + "\n";
2005 result += "container_deserialize_latency_nanoseconds_max " + std::to_string(m.deserialize_latency.max_ns.load(std::memory_order_relaxed)) + "\n";
2006 result += "container_deserialize_latency_nanoseconds_count " + std::to_string(m.deserialize_latency.sample_count.load(std::memory_order_relaxed)) + "\n";
2007
2008 // Latency percentiles - read
2009 result += "# HELP container_read_latency_nanoseconds Read operation latency percentiles\n";
2010 result += "# TYPE container_read_latency_nanoseconds summary\n";
2011 result += "container_read_latency_nanoseconds{quantile=\"0.5\"} " + std::to_string(m.read_latency.p50()) + "\n";
2012 result += "container_read_latency_nanoseconds{quantile=\"0.95\"} " + std::to_string(m.read_latency.p95()) + "\n";
2013 result += "container_read_latency_nanoseconds{quantile=\"0.99\"} " + std::to_string(m.read_latency.p99()) + "\n";
2014 result += "container_read_latency_nanoseconds{quantile=\"0.999\"} " + std::to_string(m.read_latency.p999()) + "\n";
2015 result += "container_read_latency_nanoseconds_max " + std::to_string(m.read_latency.max_ns.load(std::memory_order_relaxed)) + "\n";
2016 result += "container_read_latency_nanoseconds_count " + std::to_string(m.read_latency.sample_count.load(std::memory_order_relaxed)) + "\n";
2017
2018 // Latency percentiles - write
2019 result += "# HELP container_write_latency_nanoseconds Write operation latency percentiles\n";
2020 result += "# TYPE container_write_latency_nanoseconds summary\n";
2021 result += "container_write_latency_nanoseconds{quantile=\"0.5\"} " + std::to_string(m.write_latency.p50()) + "\n";
2022 result += "container_write_latency_nanoseconds{quantile=\"0.95\"} " + std::to_string(m.write_latency.p95()) + "\n";
2023 result += "container_write_latency_nanoseconds{quantile=\"0.99\"} " + std::to_string(m.write_latency.p99()) + "\n";
2024 result += "container_write_latency_nanoseconds{quantile=\"0.999\"} " + std::to_string(m.write_latency.p999()) + "\n";
2025 result += "container_write_latency_nanoseconds_max " + std::to_string(m.write_latency.max_ns.load(std::memory_order_relaxed)) + "\n";
2026 result += "container_write_latency_nanoseconds_count " + std::to_string(m.write_latency.sample_count.load(std::memory_order_relaxed)) + "\n";
2027
2028 // SIMD metrics
2029 result += "# HELP container_simd_operations_total Total SIMD operations performed\n";
2030 result += "# TYPE container_simd_operations_total counter\n";
2031 result += "container_simd_operations_total " + std::to_string(m.simd.simd_operations.load(std::memory_order_relaxed)) + "\n";
2032 result += "# HELP container_scalar_fallbacks_total Total scalar fallback operations\n";
2033 result += "# TYPE container_scalar_fallbacks_total counter\n";
2034 result += "container_scalar_fallbacks_total " + std::to_string(m.simd.scalar_fallbacks.load(std::memory_order_relaxed)) + "\n";
2035 result += "# HELP container_simd_bytes_processed_total Total bytes processed via SIMD\n";
2036 result += "# TYPE container_simd_bytes_processed_total counter\n";
2037 result += "container_simd_bytes_processed_total " + std::to_string(m.simd.bytes_processed_simd.load(std::memory_order_relaxed)) + "\n";
2038 result += "# HELP container_simd_utilization_ratio SIMD utilization ratio\n";
2039 result += "# TYPE container_simd_utilization_ratio gauge\n";
2040 result += "container_simd_utilization_ratio " + std::to_string(m.simd.utilization() / 100.0) + "\n";
2041
2042 // Cache metrics
2043 result += "# HELP container_cache_hits_total Total cache hits\n";
2044 result += "# TYPE container_cache_hits_total counter\n";
2045 result += "container_cache_hits_total{cache=\"key_index\"} " + std::to_string(m.cache.key_index_hits.load(std::memory_order_relaxed)) + "\n";
2046 result += "container_cache_hits_total{cache=\"value\"} " + std::to_string(m.cache.value_cache_hits.load(std::memory_order_relaxed)) + "\n";
2047 result += "# HELP container_cache_misses_total Total cache misses\n";
2048 result += "# TYPE container_cache_misses_total counter\n";
2049 result += "container_cache_misses_total{cache=\"key_index\"} " + std::to_string(m.cache.key_index_misses.load(std::memory_order_relaxed)) + "\n";
2050 result += "container_cache_misses_total{cache=\"value\"} " + std::to_string(m.cache.value_cache_misses.load(std::memory_order_relaxed)) + "\n";
2051 result += "# HELP container_cache_hit_ratio Cache hit ratio\n";
2052 result += "# TYPE container_cache_hit_ratio gauge\n";
2053 result += "container_cache_hit_ratio{cache=\"key_index\"} " + std::to_string(m.cache.key_index_hit_rate() / 100.0) + "\n";
2054 result += "container_cache_hit_ratio{cache=\"value\"} " + std::to_string(m.cache.value_cache_hit_rate() / 100.0) + "\n";
2055
2056 return result;
2057 }
2058
2059 bool value_container::deserialize_values(const std::string& data,
2060 bool parse_only_header)
2061 {
2062 if (!optimized_units_.empty())
2063 {
2064 optimized_units_.clear();
2065 }
2066 changed_data_ = false;
2067
2068 // Match both single and double braces for @data section
2069 std::regex reData("@data=\\s*\\{\\{?\\s*(.*?)\\s*\\}\\}?;");
2070 std::smatch match;
2071 if (!std::regex_search(data, match, reData))
2072 {
2073 data_string_ = "@data={{}}";
2074 parsed_data_ = true;
2075 return false;
2076 }
2077 data_string_ = match[0];
2078
2079 if (parse_only_header)
2080 {
2081 parsed_data_ = false;
2082 return true;
2083 }
2084 parsed_data_ = true;
2085
2086 // Parse items: [name,type,data];
2087 std::regex reItems("\\[(\\w+),\\s*(\\w+),\\s*(.*?)\\];");
2088 auto it = std::sregex_iterator(data_string_.begin(), data_string_.end(),
2089 reItems);
2090 auto end = std::sregex_iterator();
2091
2092 for (; it != end; ++it)
2093 {
2094 auto nameStr = (*it)[1].str();
2095 auto typeStr = (*it)[2].str();
2096 auto dataStr = (*it)[3].str();
2097
2098 // Convert string -> value_types
2099 auto vt = convert_value_type(typeStr);
2100
2101 // Create optimized_value and populate variant based on type
2102 optimized_value ov;
2103 ov.name = nameStr;
2104 ov.type = vt;
2105
2106 // Parse data string into appropriate variant type
2107 switch (vt)
2108 {
2109 case value_types::null_value:
2110 ov.data = std::monostate{};
2111 break;
2112 case value_types::bool_value:
2113 ov.data = (dataStr == "true" || dataStr == "1");
2114 break;
2115 case value_types::short_value:
2116 ov.data = static_cast<short>(std::stoi(dataStr));
2117 break;
2118 case value_types::ushort_value:
2119 ov.data = static_cast<unsigned short>(std::stoul(dataStr));
2120 break;
2121 case value_types::int_value:
2122 ov.data = std::stoi(dataStr);
2123 break;
2124 case value_types::uint_value:
2125 ov.data = static_cast<unsigned int>(std::stoul(dataStr));
2126 break;
2127 case value_types::long_value:
2128 ov.data = std::stol(dataStr);
2129 break;
2130 case value_types::ulong_value:
2131 ov.data = std::stoul(dataStr);
2132 break;
2133 case value_types::llong_value:
2134 ov.data = std::stoll(dataStr);
2135 break;
2136 case value_types::ullong_value:
2137 ov.data = std::stoull(dataStr);
2138 break;
2139 case value_types::float_value:
2140 ov.data = std::stof(dataStr);
2141 break;
2142 case value_types::double_value:
2143 ov.data = std::stod(dataStr);
2144 break;
2145 case value_types::string_value:
2146 ov.data = dataStr;
2147 break;
2148 case value_types::bytes_value:
2149 {
2150 // For bytes, dataStr should be the string representation
2151 std::vector<uint8_t> bytes(dataStr.begin(), dataStr.end());
2152 ov.data = bytes;
2153 break;
2154 }
2155 case value_types::container_value:
2156 {
2157 // Deserialize nested container from its string representation
2158 auto nested = std::make_shared<value_container>();
2159 if (!dataStr.empty() && nested->deserialize(dataStr, false))
2160 {
2161 ov.data = nested;
2162 }
2163 else
2164 {
2165 ov.data = std::monostate{};
2166 }
2167 break;
2168 }
2169 default:
2170 ov.data = std::monostate{};
2171 break;
2172 }
2173
2174 optimized_units_.push_back(std::move(ov));
2175 }
2176
2177 return true;
2178 }
2179
2180 void value_container::parsing(std::string_view source_name,
2181 std::string_view target_name,
2182 std::string_view target_value,
2183 std::string& target_variable)
2184 {
2185 if (source_name == target_name)
2186 {
2187 // Optimized trim using string_view operations
2188 // This avoids creating intermediate strings and multiple erase operations
2189 if (target_value.empty())
2190 {
2191 target_variable.clear();
2192 return;
2193 }
2194
2195 // Find first non-space character
2196 size_t start = target_value.find_first_not_of(' ');
2197 if (start == std::string_view::npos)
2198 {
2199 // All spaces
2200 target_variable.clear();
2201 return;
2202 }
2203
2204 // Find last non-space character
2205 size_t end = target_value.find_last_not_of(' ');
2206
2207 // Create trimmed string in one operation (reduced memory allocations)
2208 target_variable = std::string(target_value.substr(start, end - start + 1));
2209 }
2210 }
2211} // namespace kcenon::container
value_types convert_value_type(const std::string &target)
std::ostream & operator<<(std::ostream &out, value_container &other)
constexpr int MESSAGE_VERSION
Definition container.cpp:37
constexpr int TARGET_ID
Definition container.cpp:32
constexpr int SOURCE_ID
Definition container.cpp:34
constexpr int MESSAGE_TYPE
Definition container.cpp:36
constexpr int TARGET_SUB_ID
Definition container.cpp:33
constexpr int SOURCE_SUB_ID
Definition container.cpp:35
Thread-local memory pool allocator for value_container.