10#include <unordered_map>
18constexpr std::array<vr_info, 31> vr_table = {{
20 {
vr_type::AE,
"Application Entity", 16,
' ',
false, 0},
33 {
vr_type::UC,
"Unlimited Characters", 0xFFFFFFFE,
' ',
false, 0},
34 {
vr_type::UI,
"Unique Identifier", 64,
'\0',
false, 0},
35 {
vr_type::UR,
"Universal Resource Identifier", 0xFFFFFFFE,
' ',
false, 0},
36 {
vr_type::UT,
"Unlimited Text", 0xFFFFFFFE,
' ',
false, 0},
39 {
vr_type::FL,
"Floating Point Single", 4,
'\0',
true, 4},
40 {
vr_type::FD,
"Floating Point Double", 8,
'\0',
true, 8},
43 {
vr_type::SV,
"Signed 64-bit Very Long", 8,
'\0',
true, 8},
46 {
vr_type::UV,
"Unsigned 64-bit Very Long", 8,
'\0',
true, 8},
49 {
vr_type::OB,
"Other Byte", 0xFFFFFFFE,
'\0',
false, 0},
50 {
vr_type::OD,
"Other Double", 0xFFFFFFFE,
'\0',
false, 0},
51 {
vr_type::OF,
"Other Float", 0xFFFFFFFE,
'\0',
false, 0},
52 {
vr_type::OL,
"Other Long", 0xFFFFFFFE,
'\0',
false, 0},
53 {
vr_type::OV,
"Other 64-bit Very Long", 0xFFFFFFFE,
'\0',
false, 0},
54 {
vr_type::OW,
"Other Word", 0xFFFFFFFE,
'\0',
false, 0},
58constexpr vr_info at_info = {
vr_type::AT,
"Attribute Tag", 4,
'\0',
true, 4};
59constexpr vr_info sq_info = {
vr_type::SQ,
"Sequence of Items", 0xFFFFFFFF,
'\0',
false, 0};
60constexpr vr_info un_info = {
vr_type::UN,
"Unknown", 0xFFFFFFFE,
'\0',
false, 0};
63const std::unordered_map<vr_type, const vr_info*>& get_vr_map() {
64 static const auto map = []() {
65 std::unordered_map<vr_type, const vr_info*> m;
66 for (
const auto& info : vr_table) {
78bool is_cs_char(
char c) {
79 return std::isupper(
static_cast<unsigned char>(c)) ||
80 std::isdigit(
static_cast<unsigned char>(c)) ||
84bool is_da_char(
char c) {
85 return std::isdigit(
static_cast<unsigned char>(c));
88bool is_tm_char(
char c) {
89 return std::isdigit(
static_cast<unsigned char>(c)) ||
93bool is_ui_char(
char c) {
94 return std::isdigit(
static_cast<unsigned char>(c)) || c ==
'.';
97bool is_ds_char(
char c) {
98 return std::isdigit(
static_cast<unsigned char>(c)) ||
99 c ==
'+' || c ==
'-' || c ==
'.' ||
100 c ==
'E' || c ==
'e' || c ==
' ';
103bool is_is_char(
char c) {
104 return std::isdigit(
static_cast<unsigned char>(c)) ||
105 c ==
'+' || c ==
'-';
108bool is_as_char(
char c) {
109 return std::isdigit(
static_cast<unsigned char>(c)) ||
110 c ==
'D' || c ==
'W' || c ==
'M' || c ==
'Y';
113bool is_dt_char(
char c) {
114 return std::isdigit(
static_cast<unsigned char>(c)) ||
115 c ==
'.' || c ==
'+' || c ==
'-';
118bool is_printable(
char c) {
119 auto uc =
static_cast<unsigned char>(c);
123 return (uc >= 0x20 && uc <= 0x7E) ||
126 c ==
'\r' || c ==
'\n' || c ==
'\f' || c ==
'\t';
132 const auto& map = get_vr_map();
133 auto it = map.find(
vr);
134 if (it != map.end()) {
145 if (info.is_fixed_length && info.fixed_size > 0) {
146 if (data.size() % info.fixed_size != 0) {
154 if (info.max_length != 0xFFFFFFFE && info.max_length != 0xFFFFFFFF) {
155 if (data.size() > info.max_length) {
162 std::string_view str_value(
reinterpret_cast<const char*
>(data.data()),
179 if (info.max_length != 0xFFFFFFFE) {
180 if (value.size() > info.max_length) {
186 if (info.is_fixed_length && info.fixed_size > 0) {
187 if (value.size() != info.fixed_size) {
197 std::vector<uint8_t> result(data.begin(), data.end());
199 if (result.size() % 2 != 0) {
201 result.push_back(
static_cast<uint8_t
>(info.padding_char));
209 return std::string{};
213 char pad = info.padding_char;
216 auto end = value.find_last_not_of(pad);
217 if (end == std::string_view::npos) {
219 return std::string{};
222 return std::string{value.substr(0, end + 1)};
229 return std::all_of(value.begin(), value.end(), is_cs_char);
233 return value.size() == 8 &&
234 std::all_of(value.begin(), value.end(), is_da_char);
238 return std::all_of(value.begin(), value.end(), is_tm_char);
242 return value.size() <= 64 &&
243 std::all_of(value.begin(), value.end(), is_ui_char);
247 return std::all_of(value.begin(), value.end(), is_ds_char);
251 return std::all_of(value.begin(), value.end(), is_is_char);
255 if (value.size() != 4) {
258 return std::all_of(value.begin(), value.end(), is_as_char) &&
259 (value[3] ==
'D' || value[3] ==
'W' ||
260 value[3] ==
'M' || value[3] ==
'Y');
264 return std::all_of(value.begin(), value.end(), is_dt_char);
272 return std::all_of(value.begin(), value.end(), is_printable);
280 return std::all_of(value.begin(), value.end(), is_printable);
vr_type
DICOM Value Representation (VR) types.
@ OB
Other Byte (variable length)
@ DA
Date (8 chars, format: YYYYMMDD)
@ UN
Unknown (variable length)
@ IS
Integer String (12 chars max)
@ SQ
Sequence of Items (undefined length)
@ UR
Universal Resource Identifier (2^32-2 max)
@ OV
Other 64-bit Very Long (variable length)
@ LO
Long String (64 chars max)
@ DS
Decimal String (16 chars max)
@ DT
Date Time (26 chars max)
@ UL
Unsigned Long (4 bytes)
@ UC
Unlimited Characters (2^32-2 max)
@ UI
Unique Identifier (64 chars max)
@ SL
Signed Long (4 bytes)
@ US
Unsigned Short (2 bytes)
@ OD
Other Double (variable length)
@ PN
Person Name (64 chars max per component group)
@ OF
Other Float (variable length)
@ UT
Unlimited Text (2^32-2 max)
@ CS
Code String (16 chars max, uppercase + digits + space + underscore)
@ OW
Other Word (variable length)
@ AS
Age String (4 chars, format: nnnD/W/M/Y)
@ FD
Floating Point Double (8 bytes)
@ FL
Floating Point Single (4 bytes)
@ TM
Time (14 chars max, format: HHMMSS.FFFFFF)
@ OL
Other Long (variable length)
@ LT
Long Text (10240 chars max)
@ SV
Signed 64-bit Very Long (8 bytes)
@ SS
Signed Short (2 bytes)
@ UV
Unsigned 64-bit Very Long (8 bytes)
@ AE
Application Entity (16 chars max)
@ SH
Short String (16 chars max)
@ ST
Short Text (1024 chars max)
@ AT
Attribute Tag (4 bytes)
constexpr bool is_string_vr(vr_type vr) noexcept
Checks if a VR is a string type.
bool is_valid_charset(vr_type vr, std::string_view value)
Validates that a string uses only allowed characters for its VR.
std::vector< uint8_t > pad_to_even(vr_type vr, std::span< const uint8_t > data)
Pads data to even length as required by DICOM.
bool validate_string(vr_type vr, std::string_view value)
Validates a string value against VR encoding rules.
bool validate_value(vr_type vr, std::span< const uint8_t > data)
Validates binary data against VR encoding rules.
std::string trim_padding(vr_type vr, std::string_view value)
Removes trailing padding characters from a string value.
const vr_info & get_vr_info(vr_type vr)
Retrieves comprehensive metadata for a VR type.
Metadata structure containing comprehensive VR properties.