Mercurial > hg > orthanc
comparison OrthancFramework/Sources/DicomFormat/DicomValue.cpp @ 4775:add0337b928a
refactoring parsing of numbers
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 30 Aug 2021 10:24:36 +0200 |
parents | d9473bd5ed43 |
children | 7053502fbf97 |
comparison
equal
deleted
inserted
replaced
4771:9f207131c7f4 | 4775:add0337b928a |
---|---|
102 { | 102 { |
103 FormatDataUriScheme(target, MIME_BINARY); | 103 FormatDataUriScheme(target, MIME_BINARY); |
104 } | 104 } |
105 #endif | 105 #endif |
106 | 106 |
107 // same as ParseValue but in case the value actually contains a sequence, | |
108 // it will return the first value | |
109 // this has been introduced to support invalid "width/height" DICOM tags in some US | |
110 // images where the width is stored as "800\0" ! | |
111 template <typename T, | |
112 bool allowSigned> | |
113 static bool ParseFirstValue(T& result, | |
114 const DicomValue& source) | |
115 { | |
116 if (source.IsBinary() || | |
117 source.IsNull()) | |
118 { | |
119 return false; | |
120 } | |
121 | |
122 try | |
123 { | |
124 std::string value = Toolbox::StripSpaces(source.GetContent()); | |
125 if (value.empty()) | |
126 { | |
127 return false; | |
128 } | |
129 | |
130 if (!allowSigned && | |
131 value[0] == '-') | |
132 { | |
133 return false; | |
134 } | |
135 | |
136 if (value.find("\\") == std::string::npos) | |
137 { | |
138 result = boost::lexical_cast<T>(value); | |
139 return true; | |
140 } | |
141 else | |
142 { | |
143 std::vector<std::string> tokens; | |
144 Toolbox::TokenizeString(tokens, value, '\\'); | |
145 | |
146 if (tokens.size() >= 1) | |
147 { | |
148 result = boost::lexical_cast<T>(tokens[0]); | |
149 return true; | |
150 } | |
151 | |
152 return false; | |
153 } | |
154 } | |
155 catch (boost::bad_lexical_cast&) | |
156 { | |
157 return false; | |
158 } | |
159 } | |
160 | |
161 | |
162 template <typename T, | |
163 bool allowSigned> | |
164 static bool ParseValue(T& result, | |
165 const DicomValue& source) | |
166 { | |
167 if (source.IsBinary() || | |
168 source.IsNull()) | |
169 { | |
170 return false; | |
171 } | |
172 | |
173 try | |
174 { | |
175 std::string value = Toolbox::StripSpaces(source.GetContent()); | |
176 if (value.empty()) | |
177 { | |
178 return false; | |
179 } | |
180 | |
181 if (!allowSigned && | |
182 value[0] == '-') | |
183 { | |
184 return false; | |
185 } | |
186 | |
187 result = boost::lexical_cast<T>(value); | |
188 return true; | |
189 } | |
190 catch (boost::bad_lexical_cast&) | |
191 { | |
192 return false; | |
193 } | |
194 } | |
195 | |
196 bool DicomValue::ParseInteger32(int32_t& result) const | 107 bool DicomValue::ParseInteger32(int32_t& result) const |
197 { | 108 { |
198 int64_t tmp; | 109 if (IsBinary() || |
199 if (ParseValue<int64_t, true>(tmp, *this)) | 110 IsNull()) |
200 { | 111 { |
201 result = static_cast<int32_t>(tmp); | 112 return false; |
202 return (tmp == static_cast<int64_t>(result)); // Check no overflow occurs | 113 } |
203 } | 114 else |
204 else | 115 { |
205 { | 116 return SerializationToolbox::ParseInteger32(result, GetContent()); |
206 return false; | |
207 } | 117 } |
208 } | 118 } |
209 | 119 |
210 bool DicomValue::ParseInteger64(int64_t& result) const | 120 bool DicomValue::ParseInteger64(int64_t& result) const |
211 { | 121 { |
212 return ParseValue<int64_t, true>(result, *this); | 122 if (IsBinary() || |
123 IsNull()) | |
124 { | |
125 return false; | |
126 } | |
127 else | |
128 { | |
129 return SerializationToolbox::ParseInteger64(result, GetContent()); | |
130 } | |
213 } | 131 } |
214 | 132 |
215 bool DicomValue::ParseUnsignedInteger32(uint32_t& result) const | 133 bool DicomValue::ParseUnsignedInteger32(uint32_t& result) const |
216 { | 134 { |
217 uint64_t tmp; | 135 if (IsBinary() || |
218 if (ParseValue<uint64_t, false>(tmp, *this)) | 136 IsNull()) |
219 { | 137 { |
220 result = static_cast<uint32_t>(tmp); | 138 return false; |
221 return (tmp == static_cast<uint64_t>(result)); // Check no overflow occurs | 139 } |
222 } | 140 else |
223 else | 141 { |
224 { | 142 return SerializationToolbox::ParseUnsignedInteger32(result, GetContent()); |
225 return false; | |
226 } | 143 } |
227 } | 144 } |
228 | 145 |
229 bool DicomValue::ParseUnsignedInteger64(uint64_t& result) const | 146 bool DicomValue::ParseUnsignedInteger64(uint64_t& result) const |
230 { | 147 { |
231 return ParseValue<uint64_t, false>(result, *this); | 148 if (IsBinary() || |
149 IsNull()) | |
150 { | |
151 return false; | |
152 } | |
153 else | |
154 { | |
155 return SerializationToolbox::ParseUnsignedInteger64(result, GetContent()); | |
156 } | |
232 } | 157 } |
233 | 158 |
234 bool DicomValue::ParseFloat(float& result) const | 159 bool DicomValue::ParseFloat(float& result) const |
235 { | 160 { |
236 return ParseValue<float, true>(result, *this); | 161 if (IsBinary() || |
162 IsNull()) | |
163 { | |
164 return false; | |
165 } | |
166 else | |
167 { | |
168 return SerializationToolbox::ParseFloat(result, GetContent()); | |
169 } | |
237 } | 170 } |
238 | 171 |
239 bool DicomValue::ParseDouble(double& result) const | 172 bool DicomValue::ParseDouble(double& result) const |
240 { | 173 { |
241 return ParseValue<double, true>(result, *this); | 174 if (IsBinary() || |
175 IsNull()) | |
176 { | |
177 return false; | |
178 } | |
179 else | |
180 { | |
181 return SerializationToolbox::ParseDouble(result, GetContent()); | |
182 } | |
242 } | 183 } |
243 | 184 |
244 bool DicomValue::ParseFirstFloat(float& result) const | 185 bool DicomValue::ParseFirstFloat(float& result) const |
245 { | 186 { |
246 return ParseFirstValue<float, true>(result, *this); | 187 if (IsBinary() || |
188 IsNull()) | |
189 { | |
190 return false; | |
191 } | |
192 else | |
193 { | |
194 return SerializationToolbox::ParseFirstFloat(result, GetContent()); | |
195 } | |
247 } | 196 } |
248 | 197 |
249 bool DicomValue::ParseFirstUnsignedInteger(unsigned int& result) const | 198 bool DicomValue::ParseFirstUnsignedInteger(unsigned int& result) const |
250 { | 199 { |
251 return ParseFirstValue<unsigned int, true>(result, *this); | 200 uint64_t value; |
201 | |
202 if (IsBinary() || | |
203 IsNull()) | |
204 { | |
205 return false; | |
206 } | |
207 else if (SerializationToolbox::ParseFirstUnsignedInteger64(value, GetContent())) | |
208 { | |
209 result = static_cast<unsigned int>(value); | |
210 return (static_cast<uint64_t>(result) == value); // Check no overflow | |
211 } | |
212 else | |
213 { | |
214 return false; | |
215 } | |
252 } | 216 } |
253 | 217 |
254 bool DicomValue::CopyToString(std::string& result, | 218 bool DicomValue::CopyToString(std::string& result, |
255 bool allowBinary) const | 219 bool allowBinary) const |
256 { | 220 { |