PACS System 0.1.0
PACS DICOM system library
Loading...
Searching...
No Matches
dicom_dictionary.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
12
13#include <algorithm>
14
15namespace kcenon::pacs::core {
16
17// Forward declaration - defined in standard_tags_data.cpp
18extern auto get_standard_tags() -> std::span<const tag_info>;
19
21 static dicom_dictionary instance;
22 return instance;
23}
24
28
30 const auto tags = get_standard_tags();
31
32 tag_map_.reserve(tags.size());
33 keyword_map_.reserve(tags.size());
34
35 for (const auto& info : tags) {
36 tag_map_.emplace(info.tag, info);
37 if (!info.keyword.empty()) {
38 keyword_map_.emplace(info.keyword, info.tag);
39 }
40 }
41
42 standard_count_ = tags.size();
43}
44
45auto dicom_dictionary::find(dicom_tag tag) const -> std::optional<tag_info> {
46 std::shared_lock lock(mutex_);
47
48 const auto it = tag_map_.find(tag);
49 if (it != tag_map_.end()) {
50 return it->second;
51 }
52 return std::nullopt;
53}
54
55auto dicom_dictionary::find_by_keyword(std::string_view keyword) const
56 -> std::optional<tag_info> {
57 std::shared_lock lock(mutex_);
58
59 const auto it = keyword_map_.find(keyword);
60 if (it != keyword_map_.end()) {
61 const auto tag_it = tag_map_.find(it->second);
62 if (tag_it != tag_map_.end()) {
63 return tag_it->second;
64 }
65 }
66 return std::nullopt;
67}
68
69auto dicom_dictionary::contains(dicom_tag tag) const -> bool {
70 std::shared_lock lock(mutex_);
71 return tag_map_.contains(tag);
72}
73
74auto dicom_dictionary::contains_keyword(std::string_view keyword) const -> bool {
75 std::shared_lock lock(mutex_);
76 return keyword_map_.contains(keyword);
77}
78
79auto dicom_dictionary::validate_vm(dicom_tag tag, uint32_t count) const -> bool {
80 const auto info = find(tag);
81 if (!info) {
82 return false;
83 }
84 return info->vm.is_valid(count);
85}
86
87auto dicom_dictionary::get_vr(dicom_tag tag) const -> uint16_t {
88 const auto info = find(tag);
89 if (!info) {
90 return 0;
91 }
92 return info->vr;
93}
94
96 // Only allow private tags
97 if (!info.tag.is_private()) {
98 return false;
99 }
100
101 std::unique_lock lock(mutex_);
102
103 // Check if already exists
104 if (tag_map_.contains(info.tag)) {
105 return false;
106 }
107
108 tag_map_.emplace(info.tag, info);
109 if (!info.keyword.empty()) {
110 keyword_map_.emplace(info.keyword, info.tag);
111 }
112
113 return true;
114}
115
116auto dicom_dictionary::size() const -> size_t {
117 std::shared_lock lock(mutex_);
118 return tag_map_.size();
119}
120
122 return standard_count_;
123}
124
126 std::shared_lock lock(mutex_);
127 return tag_map_.size() - standard_count_;
128}
129
130auto dicom_dictionary::get_tags_in_group(uint16_t group) const
131 -> std::vector<tag_info> {
132 std::shared_lock lock(mutex_);
133
134 std::vector<tag_info> result;
135 for (const auto& [tag, info] : tag_map_) {
136 if (tag.group() == group) {
137 result.push_back(info);
138 }
139 }
140
141 std::sort(result.begin(), result.end(),
142 [](const auto& a, const auto& b) {
143 return a.tag < b.tag;
144 });
145
146 return result;
147}
148
149} // namespace kcenon::pacs::core
std::unordered_map< std::string_view, dicom_tag > keyword_map_
Hash map for O(1) lookup by keyword.
auto find_by_keyword(std::string_view keyword) const -> std::optional< tag_info >
Find tag metadata by keyword.
std::shared_mutex mutex_
Mutex for thread-safe private tag registration.
auto get_tags_in_group(uint16_t group) const -> std::vector< tag_info >
Get all tags in a specific group.
auto contains(dicom_tag tag) const -> bool
Check if a tag exists in the dictionary.
auto find(dicom_tag tag) const -> std::optional< tag_info >
Find tag metadata by DICOM tag.
void initialize_standard_tags()
Initialize the dictionary with standard PS3.6 tags.
auto size() const -> size_t
Get the total number of tags in the dictionary.
static auto instance() -> dicom_dictionary &
Get the singleton instance.
auto get_vr(dicom_tag tag) const -> uint16_t
Get the VR type for a tag.
auto validate_vm(dicom_tag tag, uint32_t count) const -> bool
Validate that a value count is valid for a tag's VM.
size_t standard_count_
Count of standard tags (vs private)
std::unordered_map< dicom_tag, tag_info > tag_map_
Hash map for O(1) lookup by tag.
auto register_private_tag(const tag_info &info) -> bool
Register a private tag at runtime.
auto private_tag_count() const -> size_t
Get the number of registered private tags.
auto contains_keyword(std::string_view keyword) const -> bool
Check if a keyword exists in the dictionary.
dicom_dictionary()
Private constructor - initializes with standard tags.
auto standard_tag_count() const -> size_t
Get the number of standard (non-private) tags.
DICOM Data Dictionary for tag metadata lookup.
auto get_standard_tags() -> std::span< const tag_info >