1 /**
2  * Orthanc - A Lightweight, RESTful DICOM Store
3  * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4  * Department, University Hospital of Liege, Belgium
5  * Copyright (C) 2017-2021 Osimis S.A., Belgium
6  *
7  * This program is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * as published by the Free Software Foundation, either version 3 of
10  * the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this program. If not, see
19  * <http://www.gnu.org/licenses/>.
20  **/
21 
22 
23 #include "../PrecompiledHeaders.h"
24 #include "DicomValue.h"
25 
26 #include "../OrthancException.h"
27 #include "../SerializationToolbox.h"
28 #include "../Toolbox.h"
29 
30 #include <boost/lexical_cast.hpp>
31 
32 namespace Orthanc
33 {
DicomValue()34   DicomValue::DicomValue() :
35     type_(Type_Null)
36   {
37   }
38 
39 
DicomValue(const DicomValue & other)40   DicomValue::DicomValue(const DicomValue& other) :
41     type_(other.type_),
42     content_(other.content_)
43   {
44   }
45 
46 
DicomValue(const std::string & content,bool isBinary)47   DicomValue::DicomValue(const std::string& content,
48                          bool isBinary) :
49     type_(isBinary ? Type_Binary : Type_String),
50     content_(content)
51   {
52   }
53 
54 
DicomValue(const char * data,size_t size,bool isBinary)55   DicomValue::DicomValue(const char* data,
56                          size_t size,
57                          bool isBinary) :
58     type_(isBinary ? Type_Binary : Type_String)
59   {
60     content_.assign(data, size);
61   }
62 
63 
GetContent() const64   const std::string& DicomValue::GetContent() const
65   {
66     if (type_ == Type_Null)
67     {
68       throw OrthancException(ErrorCode_BadParameterType);
69     }
70     else
71     {
72       return content_;
73     }
74   }
75 
IsNull() const76   bool DicomValue::IsNull() const
77   {
78     return type_ == Type_Null;
79   }
80 
IsBinary() const81   bool DicomValue::IsBinary() const
82   {
83     return type_ == Type_Binary;
84   }
85 
86 
Clone() const87   DicomValue* DicomValue::Clone() const
88   {
89     return new DicomValue(*this);
90   }
91 
92 
93 #if ORTHANC_ENABLE_BASE64 == 1
FormatDataUriScheme(std::string & target,const std::string & mime) const94   void DicomValue::FormatDataUriScheme(std::string& target,
95                                        const std::string& mime) const
96   {
97     Toolbox::EncodeBase64(target, GetContent());
98     target.insert(0, "data:" + mime + ";base64,");
99   }
100 
FormatDataUriScheme(std::string & target) const101   void DicomValue::FormatDataUriScheme(std::string& target) const
102   {
103     FormatDataUriScheme(target, MIME_BINARY);
104   }
105 #endif
106 
ParseInteger32(int32_t & result) const107   bool DicomValue::ParseInteger32(int32_t& result) const
108   {
109     if (IsBinary() ||
110         IsNull())
111     {
112       return false;
113     }
114     else
115     {
116       return SerializationToolbox::ParseInteger32(result, GetContent());
117     }
118   }
119 
ParseInteger64(int64_t & result) const120   bool DicomValue::ParseInteger64(int64_t& result) const
121   {
122     if (IsBinary() ||
123         IsNull())
124     {
125       return false;
126     }
127     else
128     {
129       return SerializationToolbox::ParseInteger64(result, GetContent());
130     }
131   }
132 
ParseUnsignedInteger32(uint32_t & result) const133   bool DicomValue::ParseUnsignedInteger32(uint32_t& result) const
134   {
135     if (IsBinary() ||
136         IsNull())
137     {
138       return false;
139     }
140     else
141     {
142       return SerializationToolbox::ParseUnsignedInteger32(result, GetContent());
143     }
144   }
145 
ParseUnsignedInteger64(uint64_t & result) const146   bool DicomValue::ParseUnsignedInteger64(uint64_t& result) const
147   {
148     if (IsBinary() ||
149         IsNull())
150     {
151       return false;
152     }
153     else
154     {
155       return SerializationToolbox::ParseUnsignedInteger64(result, GetContent());
156     }
157   }
158 
ParseFloat(float & result) const159   bool DicomValue::ParseFloat(float& result) const
160   {
161     if (IsBinary() ||
162         IsNull())
163     {
164       return false;
165     }
166     else
167     {
168       return SerializationToolbox::ParseFloat(result, GetContent());
169     }
170   }
171 
ParseDouble(double & result) const172   bool DicomValue::ParseDouble(double& result) const
173   {
174     if (IsBinary() ||
175         IsNull())
176     {
177       return false;
178     }
179     else
180     {
181       return SerializationToolbox::ParseDouble(result, GetContent());
182     }
183   }
184 
ParseFirstFloat(float & result) const185   bool DicomValue::ParseFirstFloat(float& result) const
186   {
187     if (IsBinary() ||
188         IsNull())
189     {
190       return false;
191     }
192     else
193     {
194       return SerializationToolbox::ParseFirstFloat(result, GetContent());
195     }
196   }
197 
ParseFirstUnsignedInteger(unsigned int & result) const198   bool DicomValue::ParseFirstUnsignedInteger(unsigned int& result) const
199   {
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     }
216   }
217 
CopyToString(std::string & result,bool allowBinary) const218   bool DicomValue::CopyToString(std::string& result,
219                                 bool allowBinary) const
220   {
221     if (IsNull())
222     {
223       return false;
224     }
225     else if (IsBinary() && !allowBinary)
226     {
227       return false;
228     }
229     else
230     {
231       result.assign(content_);
232       return true;
233     }
234   }
235 
236 
237   static const char* KEY_TYPE = "Type";
238   static const char* KEY_CONTENT = "Content";
239 
Serialize(Json::Value & target) const240   void DicomValue::Serialize(Json::Value& target) const
241   {
242     target = Json::objectValue;
243 
244     switch (type_)
245     {
246       case Type_Null:
247         target[KEY_TYPE] = "Null";
248         break;
249 
250       case Type_String:
251         target[KEY_TYPE] = "String";
252         target[KEY_CONTENT] = content_;
253         break;
254 
255       case Type_Binary:
256       {
257         target[KEY_TYPE] = "Binary";
258 
259         std::string base64;
260         Toolbox::EncodeBase64(base64, content_);
261         target[KEY_CONTENT] = base64;
262         break;
263       }
264 
265       default:
266         throw OrthancException(ErrorCode_InternalError);
267     }
268   }
269 
Unserialize(const Json::Value & source)270   void DicomValue::Unserialize(const Json::Value& source)
271   {
272     std::string type = SerializationToolbox::ReadString(source, KEY_TYPE);
273 
274     if (type == "Null")
275     {
276       type_ = Type_Null;
277       content_.clear();
278     }
279     else if (type == "String")
280     {
281       type_ = Type_String;
282       content_ = SerializationToolbox::ReadString(source, KEY_CONTENT);
283     }
284     else if (type == "Binary")
285     {
286       type_ = Type_Binary;
287 
288       const std::string base64 =SerializationToolbox::ReadString(source, KEY_CONTENT);
289       Toolbox::DecodeBase64(content_, base64);
290     }
291     else
292     {
293       throw OrthancException(ErrorCode_BadFileFormat);
294     }
295   }
296 }
297