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 {