PACS System 0.1.0
PACS DICOM system library
Loading...
Searching...
No Matches
tag_info.cpp
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2021-2025, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
11
12#include <charconv>
13#include <sstream>
14
15namespace kcenon::pacs::core {
16
17auto value_multiplicity::from_string(std::string_view str)
18 -> std::optional<value_multiplicity> {
19 if (str.empty()) {
20 return std::nullopt;
21 }
22
23 value_multiplicity result;
24
25 // Find the hyphen separator
26 const auto hyphen_pos = str.find('-');
27
28 if (hyphen_pos == std::string_view::npos) {
29 // Single value case: "1", "2", etc.
30 uint32_t val{0};
31 auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), val);
32 if (ec != std::errc{} || ptr != str.data() + str.size()) {
33 return std::nullopt;
34 }
35 result.min = val;
36 result.max = val;
37 return result;
38 }
39
40 // Range case: "min-max" or "min-n" or "min-2n"
41 const auto min_str = str.substr(0, hyphen_pos);
42 const auto max_str = str.substr(hyphen_pos + 1);
43
44 if (min_str.empty() || max_str.empty()) {
45 return std::nullopt;
46 }
47
48 // Parse minimum
49 uint32_t min_val{0};
50 auto [min_ptr, min_ec] = std::from_chars(
51 min_str.data(), min_str.data() + min_str.size(), min_val);
52 if (min_ec != std::errc{} || min_ptr != min_str.data() + min_str.size()) {
53 return std::nullopt;
54 }
55 result.min = min_val;
56
57 // Parse maximum
58 if (max_str == "n") {
59 // Unbounded: "1-n"
60 result.max = std::nullopt;
61 result.multiplier = 1;
62 } else if (max_str.back() == 'n') {
63 // Multiplier pattern: "1-2n", "2-3n"
64 const auto mult_str = max_str.substr(0, max_str.size() - 1);
65 uint32_t mult_val{1};
66 auto [mult_ptr, mult_ec] = std::from_chars(
67 mult_str.data(), mult_str.data() + mult_str.size(), mult_val);
68 if (mult_ec != std::errc{} || mult_ptr != mult_str.data() + mult_str.size()) {
69 return std::nullopt;
70 }
71 result.max = std::nullopt;
72 result.multiplier = mult_val;
73 } else {
74 // Fixed range: "1-2", "1-3"
75 uint32_t max_val{0};
76 auto [max_ptr, max_ec] = std::from_chars(
77 max_str.data(), max_str.data() + max_str.size(), max_val);
78 if (max_ec != std::errc{} || max_ptr != max_str.data() + max_str.size()) {
79 return std::nullopt;
80 }
81 result.max = max_val;
82 }
83
84 return result;
85}
86
87auto value_multiplicity::to_string() const -> std::string {
88 std::ostringstream oss;
89 oss << min;
90
91 if (!max.has_value()) {
92 // Unbounded
93 oss << '-';
94 if (multiplier > 1) {
95 oss << multiplier;
96 }
97 oss << 'n';
98 } else if (max.value() != min) {
99 // Range
100 oss << '-' << max.value();
101 }
102 // If max == min, just output the single value
103
104 return oss.str();
105}
106
107} // namespace kcenon::pacs::core
Value Multiplicity (VM) specification.
Definition tag_info.h:41
static auto from_string(std::string_view str) -> std::optional< value_multiplicity >
Parse VM from string representation.
Definition tag_info.cpp:17
uint32_t multiplier
For "n", "2n", "3n" patterns.
Definition tag_info.h:44
uint32_t min
Minimum number of values.
Definition tag_info.h:42
std::optional< uint32_t > max
Maximum number of values (nullopt = unbounded)
Definition tag_info.h:43
auto to_string() const -> std::string
Convert to string representation.
Definition tag_info.cpp:87
DICOM tag metadata information structure.