changeset 4203:4d42408da117

improving const-correctness in ParsedDicomFile
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 17 Sep 2020 15:01:31 +0200
parents 2007ab69ac16
children 318c16cfccab
files OrthancFramework/Sources/DicomNetworking/DicomControlUserConnection.cpp OrthancFramework/Sources/DicomNetworking/DicomControlUserConnection.h OrthancFramework/Sources/DicomNetworking/Internals/FindScp.cpp OrthancFramework/Sources/DicomParsing/DicomDirWriter.cpp OrthancFramework/Sources/DicomParsing/Internals/DicomImageDecoder.cpp OrthancFramework/Sources/DicomParsing/Internals/DicomImageDecoder.h OrthancFramework/Sources/DicomParsing/ParsedDicomFile.cpp OrthancFramework/Sources/DicomParsing/ParsedDicomFile.h OrthancFramework/Sources/JobsEngine/JobsRegistry.cpp OrthancFramework/Sources/JobsEngine/JobsRegistry.h OrthancFramework/Sources/MetricsRegistry.cpp OrthancFramework/Sources/RestApi/RestApiDeleteCall.h OrthancFramework/Sources/RestApi/RestApiGetCall.h OrthancFramework/Sources/RestApi/RestApiHierarchy.cpp OrthancFramework/Sources/RestApi/RestApiPath.h OrthancFramework/Sources/RestApi/RestApiPostCall.h OrthancFramework/Sources/RestApi/RestApiPutCall.h OrthancFramework/Sources/SerializationToolbox.h OrthancFramework/Sources/SystemToolbox.cpp OrthancFramework/Sources/Toolbox.cpp OrthancFramework/UnitTestsSources/FileStorageTests.cpp OrthancFramework/UnitTestsSources/FromDcmtkTests.cpp OrthancServer/Resources/RunCppCheck.sh OrthancServer/Sources/ServerContext.cpp
diffstat 24 files changed, 152 insertions(+), 132 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancFramework/Sources/DicomNetworking/DicomControlUserConnection.cpp	Thu Sep 17 08:35:11 2020 +0200
+++ b/OrthancFramework/Sources/DicomNetworking/DicomControlUserConnection.cpp	Thu Sep 17 15:01:31 2020 +0200
@@ -654,7 +654,7 @@
 
 
   void DicomControlUserConnection::FindWorklist(DicomFindAnswers& result,
-                                                const ParsedDicomFile& query)
+                                                ParsedDicomFile& query)
   {
     DcmDataset* dataset = query.GetDcmtkObject().getDataset();
     const char* sopClass = UID_FINDModalityWorklistInformationModel;
--- a/OrthancFramework/Sources/DicomNetworking/DicomControlUserConnection.h	Thu Sep 17 08:35:11 2020 +0200
+++ b/OrthancFramework/Sources/DicomNetworking/DicomControlUserConnection.h	Thu Sep 17 15:01:31 2020 +0200
@@ -93,6 +93,6 @@
                       const std::string& instanceUid);
 
     void FindWorklist(DicomFindAnswers& result,
-                      const ParsedDicomFile& query);
+                      ParsedDicomFile& query);
   };
 }
--- a/OrthancFramework/Sources/DicomNetworking/Internals/FindScp.cpp	Thu Sep 17 08:35:11 2020 +0200
+++ b/OrthancFramework/Sources/DicomNetworking/Internals/FindScp.cpp	Thu Sep 17 15:01:31 2020 +0200
@@ -152,7 +152,7 @@
 
 
 
-    static void FixWorklistQuery(const ParsedDicomFile& query)
+    static void FixWorklistQuery(ParsedDicomFile& query)
     {
       // TODO: Check out
       // WlmDataSourceFileSystem::HandleExistentButEmptyDescriptionAndCodeSequenceAttributes()"
--- a/OrthancFramework/Sources/DicomParsing/DicomDirWriter.cpp	Thu Sep 17 08:35:11 2020 +0200
+++ b/OrthancFramework/Sources/DicomParsing/DicomDirWriter.cpp	Thu Sep 17 15:01:31 2020 +0200
@@ -396,7 +396,7 @@
 
     bool CreateResource(DcmDirectoryRecord*& target,
                         ResourceType level,
-                        const ParsedDicomFile& dicom,
+                        ParsedDicomFile& dicom,
                         const char* filename,
                         const char* path)
     {
--- a/OrthancFramework/Sources/DicomParsing/Internals/DicomImageDecoder.cpp	Thu Sep 17 08:35:11 2020 +0200
+++ b/OrthancFramework/Sources/DicomParsing/Internals/DicomImageDecoder.cpp	Thu Sep 17 15:01:31 2020 +0200
@@ -652,20 +652,6 @@
   }
 
 
-  ImageAccessor* DicomImageDecoder::Decode(const ParsedDicomFile& dicom,
-                                           unsigned int frame)
-  {
-    if (dicom.GetDcmtkObject().getDataset() == NULL)
-    {
-      throw OrthancException(ErrorCode_InternalError);
-    }
-    else
-    {
-      return Decode(*dicom.GetDcmtkObject().getDataset(), frame);
-    }
-  }
-
-
   ImageAccessor* DicomImageDecoder::Decode(DcmDataset& dataset,
                                            unsigned int frame)
   {
--- a/OrthancFramework/Sources/DicomParsing/Internals/DicomImageDecoder.h	Thu Sep 17 08:35:11 2020 +0200
+++ b/OrthancFramework/Sources/DicomParsing/Internals/DicomImageDecoder.h	Thu Sep 17 15:01:31 2020 +0200
@@ -90,9 +90,6 @@
     static bool DecodePsmctRle1(std::string& output,
                                 DcmDataset& dataset);
 
-    static ImageAccessor *Decode(const ParsedDicomFile& dicom,
-                                 unsigned int frame);
-
     static ImageAccessor *Decode(DcmDataset& dataset,
                                  unsigned int frame);
 
--- a/OrthancFramework/Sources/DicomParsing/ParsedDicomFile.cpp	Thu Sep 17 08:35:11 2020 +0200
+++ b/OrthancFramework/Sources/DicomParsing/ParsedDicomFile.cpp	Thu Sep 17 15:01:31 2020 +0200
@@ -72,6 +72,7 @@
 
 #include "FromDcmtkBridge.h"
 #include "Internals/DicomFrameIndex.h"
+#include "Internals/DicomImageDecoder.h"
 #include "ToDcmtkBridge.h"
 
 #include "../Images/PamReader.h"
@@ -442,10 +443,10 @@
 
 #if ORTHANC_ENABLE_CIVETWEB == 1 || ORTHANC_ENABLE_MONGOOSE == 1
   void ParsedDicomFile::SendPathValue(RestApiOutput& output,
-                                      const UriComponents& uri)
+                                      const UriComponents& uri) const
   {
-    DcmItem* dicom = GetDcmtkObject().getDataset();
-    E_TransferSyntax transferSyntax = GetDcmtkObject().getDataset()->getCurrentXfer();
+    DcmItem* dicom = GetDcmtkObjectConst().getDataset();
+    E_TransferSyntax transferSyntax = GetDcmtkObjectConst().getDataset()->getCurrentXfer();
 
     // Special case: Accessing the pixel data
     if (uri.size() == 1 || 
@@ -853,10 +854,10 @@
 
     
 #if ORTHANC_ENABLE_CIVETWEB == 1 || ORTHANC_ENABLE_MONGOOSE == 1
-  void ParsedDicomFile::Answer(RestApiOutput& output)
+  void ParsedDicomFile::Answer(RestApiOutput& output) const
   {
     std::string serialized;
-    if (FromDcmtkBridge::SaveToMemoryBuffer(serialized, *GetDcmtkObject().getDataset()))
+    if (FromDcmtkBridge::SaveToMemoryBuffer(serialized, *GetDcmtkObjectConst().getDataset()))
     {
       output.AnswerBuffer(serialized, MimeType_Dicom);
     }
@@ -865,10 +866,10 @@
 
 
   bool ParsedDicomFile::GetTagValue(std::string& value,
-                                    const DicomTag& tag)
+                                    const DicomTag& tag) const
   {
     DcmTagKey k(tag.GetGroup(), tag.GetElement());
-    DcmDataset& dataset = *GetDcmtkObject().getDataset();
+    DcmDataset& dataset = *GetDcmtkObjectConst().getDataset();
 
     if (tag.IsPrivate() ||
         FromDcmtkBridge::IsUnknownTag(tag) ||
@@ -930,7 +931,7 @@
   }
 
 
-  DicomInstanceHasher ParsedDicomFile::GetHasher()
+  DicomInstanceHasher ParsedDicomFile::GetHasher() const
   {
     std::string patientId, studyUid, seriesUid, instanceUid;
 
@@ -1107,7 +1108,7 @@
                                    bool keepSopInstanceUid) : 
     pimpl_(new PImpl)
   {
-    pimpl_->file_.reset(dynamic_cast<DcmFileFormat*>(other.GetDcmtkObject().clone()));
+    pimpl_->file_.reset(dynamic_cast<DcmFileFormat*>(other.GetDcmtkObjectConst().clone()));
 
     if (!keepSopInstanceUid)
     {
@@ -1135,7 +1136,7 @@
   }
 
 
-  DcmFileFormat& ParsedDicomFile::GetDcmtkObject() const
+  DcmFileFormat& ParsedDicomFile::GetDcmtkObjectConst() const
   {
     if (pimpl_->file_.get() == NULL)
     {
@@ -1164,7 +1165,7 @@
   }
 
 
-  ParsedDicomFile* ParsedDicomFile::Clone(bool keepSopInstanceUid)
+  ParsedDicomFile* ParsedDicomFile::Clone(bool keepSopInstanceUid) const
   {
     return new ParsedDicomFile(*this, keepSopInstanceUid);
   }
@@ -1403,7 +1404,7 @@
   Encoding ParsedDicomFile::DetectEncoding(bool& hasCodeExtensions) const
   {
     return FromDcmtkBridge::DetectEncoding(hasCodeExtensions,
-                                           *GetDcmtkObject().getDataset(),
+                                           *GetDcmtkObjectConst().getDataset(),
                                            GetDefaultDicomEncoding());
   }
 
@@ -1424,10 +1425,10 @@
   void ParsedDicomFile::DatasetToJson(Json::Value& target, 
                                       DicomToJsonFormat format,
                                       DicomToJsonFlags flags,
-                                      unsigned int maxStringLength)
+                                      unsigned int maxStringLength) const
   {
     std::set<DicomTag> ignoreTagLength;
-    FromDcmtkBridge::ExtractDicomAsJson(target, *GetDcmtkObject().getDataset(),
+    FromDcmtkBridge::ExtractDicomAsJson(target, *GetDcmtkObjectConst().getDataset(),
                                         format, flags, maxStringLength, ignoreTagLength);
   }
 
@@ -1436,24 +1437,24 @@
                                       DicomToJsonFormat format,
                                       DicomToJsonFlags flags,
                                       unsigned int maxStringLength,
-                                      const std::set<DicomTag>& ignoreTagLength)
+                                      const std::set<DicomTag>& ignoreTagLength) const
   {
-    FromDcmtkBridge::ExtractDicomAsJson(target, *GetDcmtkObject().getDataset(),
+    FromDcmtkBridge::ExtractDicomAsJson(target, *GetDcmtkObjectConst().getDataset(),
                                         format, flags, maxStringLength, ignoreTagLength);
   }
 
 
   void ParsedDicomFile::HeaderToJson(Json::Value& target, 
-                                     DicomToJsonFormat format)
+                                     DicomToJsonFormat format) const
   {
-    FromDcmtkBridge::ExtractHeaderAsJson(target, *GetDcmtkObject().getMetaInfo(), format, DicomToJsonFlags_None, 0);
+    FromDcmtkBridge::ExtractHeaderAsJson(target, *GetDcmtkObjectConst().getMetaInfo(), format, DicomToJsonFlags_None, 0);
   }
 
 
   bool ParsedDicomFile::HasTag(const DicomTag& tag) const
   {
     DcmTag key(tag.GetGroup(), tag.GetElement());
-    return GetDcmtkObject().getDataset()->tagExists(key);
+    return GetDcmtkObjectConst().getDataset()->tagExists(key);
   }
 
 
@@ -1505,7 +1506,7 @@
   }
 
 
-  bool ParsedDicomFile::ExtractPdf(std::string& pdf)
+  bool ParsedDicomFile::ExtractPdf(std::string& pdf) const
   {
     std::string sop, mime;
     
@@ -1582,18 +1583,18 @@
 
   void ParsedDicomFile::GetRawFrame(std::string& target,
                                     MimeType& mime,
-                                    unsigned int frameId)
+                                    unsigned int frameId) const
   {
     if (pimpl_->frameIndex_.get() == NULL)
     {
       assert(pimpl_->file_ != NULL &&
-             GetDcmtkObject().getDataset() != NULL);
-      pimpl_->frameIndex_.reset(new DicomFrameIndex(*GetDcmtkObject().getDataset()));
+             GetDcmtkObjectConst().getDataset() != NULL);
+      pimpl_->frameIndex_.reset(new DicomFrameIndex(*GetDcmtkObjectConst().getDataset()));
     }
 
     pimpl_->frameIndex_->GetRawFrame(target, frameId);
 
-    E_TransferSyntax transferSyntax = GetDcmtkObject().getDataset()->getCurrentXfer();
+    E_TransferSyntax transferSyntax = GetDcmtkObjectConst().getDataset()->getCurrentXfer();
     switch (transferSyntax)
     {
       case EXS_JPEGProcess1:
@@ -1621,8 +1622,8 @@
   unsigned int ParsedDicomFile::GetFramesCount() const
   {
     assert(pimpl_->file_ != NULL &&
-           GetDcmtkObject().getDataset() != NULL);
-    return DicomFrameIndex::GetFramesCount(*GetDcmtkObject().getDataset());
+           GetDcmtkObjectConst().getDataset() != NULL);
+    return DicomFrameIndex::GetFramesCount(*GetDcmtkObjectConst().getDataset());
   }
 
 
@@ -1643,7 +1644,7 @@
                                             unsigned int maxTagLength) const
   {
     std::set<DicomTag> ignoreTagLength;
-    FromDcmtkBridge::ExtractDicomSummary(target, *GetDcmtkObject().getDataset(),
+    FromDcmtkBridge::ExtractDicomSummary(target, *GetDcmtkObjectConst().getDataset(),
                                          maxTagLength, ignoreTagLength);
   }
 
@@ -1652,12 +1653,12 @@
                                             unsigned int maxTagLength,
                                             const std::set<DicomTag>& ignoreTagLength) const
   {
-    FromDcmtkBridge::ExtractDicomSummary(target, *GetDcmtkObject().getDataset(),
+    FromDcmtkBridge::ExtractDicomSummary(target, *GetDcmtkObjectConst().getDataset(),
                                          maxTagLength, ignoreTagLength);
   }
 
 
-  bool ParsedDicomFile::LookupTransferSyntax(std::string& result)
+  bool ParsedDicomFile::LookupTransferSyntax(std::string& result) const
   {
 #if 0
     // This was the implementation in Orthanc <= 1.6.1
@@ -1666,8 +1667,8 @@
     // using the meta header?
     const char* value = NULL;
 
-    if (GetDcmtkObject().getMetaInfo() != NULL &&
-        GetDcmtkObject().getMetaInfo()->findAndGetString(DCM_TransferSyntaxUID, value).good() &&
+    if (GetDcmtkObjectConst().getMetaInfo() != NULL &&
+        GetDcmtkObjectConst().getMetaInfo()->findAndGetString(DCM_TransferSyntaxUID, value).good() &&
         value != NULL)
     {
       result.assign(value);
@@ -1679,7 +1680,7 @@
     }
 #else
     DicomTransferSyntax s;
-    if (FromDcmtkBridge::LookupOrthancTransferSyntax(s, GetDcmtkObject()))
+    if (FromDcmtkBridge::LookupOrthancTransferSyntax(s, GetDcmtkObjectConst()))
     {
       result.assign(GetTransferSyntaxUid(s));
       return true;
@@ -1697,7 +1698,7 @@
     DcmTagKey k(DICOM_TAG_PHOTOMETRIC_INTERPRETATION.GetGroup(),
                 DICOM_TAG_PHOTOMETRIC_INTERPRETATION.GetElement());
 
-    DcmDataset& dataset = *GetDcmtkObject().getDataset();
+    DcmDataset& dataset = *GetDcmtkObjectConst().getDataset();
 
     const char *c = NULL;
     if (dataset.findAndGetString(k, c).good() &&
@@ -1713,8 +1714,21 @@
   }
 
 
-  void ParsedDicomFile::Apply(ITagVisitor& visitor)
+  void ParsedDicomFile::Apply(ITagVisitor& visitor) const
+  {
+    FromDcmtkBridge::Apply(*GetDcmtkObjectConst().getDataset(), visitor, GetDefaultDicomEncoding());
+  }
+
+
+  ImageAccessor* ParsedDicomFile::DecodeFrame(unsigned int frame) const
   {
-    FromDcmtkBridge::Apply(*GetDcmtkObject().getDataset(), visitor, GetDefaultDicomEncoding());
+    if (GetDcmtkObjectConst().getDataset() == NULL)
+    {
+      throw OrthancException(ErrorCode_InternalError);
+    }
+    else
+    {
+      return DicomImageDecoder::Decode(*GetDcmtkObjectConst().getDataset(), frame);
+    }
   }
 }
--- a/OrthancFramework/Sources/DicomParsing/ParsedDicomFile.h	Thu Sep 17 08:35:11 2020 +0200
+++ b/OrthancFramework/Sources/DicomParsing/ParsedDicomFile.h	Thu Sep 17 15:01:31 2020 +0200
@@ -95,6 +95,10 @@
 
     bool EmbedContentInternal(const std::string& dataUriScheme);
 
+    // For internal use only, in order to provide const-correctness on
+    // the top of DCMTK API
+    DcmFileFormat& GetDcmtkObjectConst() const;
+
     explicit ParsedDicomFile(DcmFileFormat* dicom);  // This takes ownership (no clone)
 
   public:
@@ -124,18 +128,21 @@
       return new ParsedDicomFile(dicom);
     }
 
-    DcmFileFormat& GetDcmtkObject() const;
+    DcmFileFormat& GetDcmtkObject()
+    {
+      return GetDcmtkObjectConst();
+    }
 
     // The "ParsedDicomFile" object cannot be used after calling this method
     DcmFileFormat* ReleaseDcmtkObject();
 
-    ParsedDicomFile* Clone(bool keepSopInstanceUid);
+    ParsedDicomFile* Clone(bool keepSopInstanceUid) const;
 
 #if ORTHANC_ENABLE_CIVETWEB == 1 || ORTHANC_ENABLE_MONGOOSE == 1
     void SendPathValue(RestApiOutput& output,
-                       const UriComponents& uri);
+                       const UriComponents& uri) const;
 
-    void Answer(RestApiOutput& output);
+    void Answer(RestApiOutput& output) const;
 #endif
 
     void Remove(const DicomTag& tag);
@@ -181,10 +188,12 @@
 
     // WARNING: This function handles the decoding of strings to UTF8
     bool GetTagValue(std::string& value,
-                     const DicomTag& tag);
+                     const DicomTag& tag) const;
 
-    DicomInstanceHasher GetHasher();
+    DicomInstanceHasher GetHasher() const;
 
+    // The "Save" methods are not tagged as "const", as the internal
+    // representation might be changed after serialization
     void SaveToMemoryBuffer(std::string& buffer);
 
 #if ORTHANC_SANDBOXED == 0
@@ -207,26 +216,26 @@
     void DatasetToJson(Json::Value& target, 
                        DicomToJsonFormat format,
                        DicomToJsonFlags flags,
-                       unsigned int maxStringLength);
+                       unsigned int maxStringLength) const;
 
     void DatasetToJson(Json::Value& target, 
                        DicomToJsonFormat format,
                        DicomToJsonFlags flags,
                        unsigned int maxStringLength,
-                       const std::set<DicomTag>& ignoreTagLength);
+                       const std::set<DicomTag>& ignoreTagLength) const;
       
     void HeaderToJson(Json::Value& target, 
-                      DicomToJsonFormat format);
+                      DicomToJsonFormat format) const;
 
     bool HasTag(const DicomTag& tag) const;
 
     void EmbedPdf(const std::string& pdf);
 
-    bool ExtractPdf(std::string& pdf);
+    bool ExtractPdf(std::string& pdf) const;
 
     void GetRawFrame(std::string& target, // OUT
                      MimeType& mime,   // OUT
-                     unsigned int frameId);  // IN
+                     unsigned int frameId) const;  // IN
 
     unsigned int GetFramesCount() const;
 
@@ -253,10 +262,13 @@
                              unsigned int maxTagLength,
                              const std::set<DicomTag>& ignoreTagLength) const;
 
-    bool LookupTransferSyntax(std::string& result);
+    bool LookupTransferSyntax(std::string& result) const;
 
     bool LookupPhotometricInterpretation(PhotometricInterpretation& result) const;
 
-    void Apply(ITagVisitor& visitor);
+    void Apply(ITagVisitor& visitor) const;
+
+    // Decode the given frame, using the built-in DICOM decoder of Orthanc
+    ImageAccessor* DecodeFrame(unsigned int frame) const;
   };
 }
--- a/OrthancFramework/Sources/JobsEngine/JobsRegistry.cpp	Thu Sep 17 08:35:11 2020 +0200
+++ b/OrthancFramework/Sources/JobsEngine/JobsRegistry.cpp	Thu Sep 17 15:01:31 2020 +0200
@@ -312,8 +312,8 @@
   };
 
 
-  bool JobsRegistry::PriorityComparator::operator() (JobHandler*& a,
-                                                     JobHandler*& b) const
+  bool JobsRegistry::PriorityComparator::operator() (JobHandler* const& a,
+                                                     JobHandler* const& b) const
   {
     return a->GetPriority() < b->GetPriority();
   }
--- a/OrthancFramework/Sources/JobsEngine/JobsRegistry.h	Thu Sep 17 08:35:11 2020 +0200
+++ b/OrthancFramework/Sources/JobsEngine/JobsRegistry.h	Thu Sep 17 15:01:31 2020 +0200
@@ -71,8 +71,8 @@
 
     struct PriorityComparator
     {
-      bool operator() (JobHandler*& a,
-                       JobHandler*& b) const;
+      bool operator() (JobHandler* const& a,
+                       JobHandler* const& b) const;
     };
 
     typedef std::map<std::string, JobHandler*>              JobsIndex;
--- a/OrthancFramework/Sources/MetricsRegistry.cpp	Thu Sep 17 08:35:11 2020 +0200
+++ b/OrthancFramework/Sources/MetricsRegistry.cpp	Thu Sep 17 15:01:31 2020 +0200
@@ -94,7 +94,7 @@
     }
 
   public:
-    Item(MetricsType type) :
+    explicit Item(MetricsType type) :
       type_(type),
       hasValue_(false),
       value_(0)
--- a/OrthancFramework/Sources/RestApi/RestApiDeleteCall.h	Thu Sep 17 08:35:11 2020 +0200
+++ b/OrthancFramework/Sources/RestApi/RestApiDeleteCall.h	Thu Sep 17 15:01:31 2020 +0200
@@ -45,7 +45,7 @@
     {
     }
 
-    virtual bool ParseJsonRequest(Json::Value& result) const
+    virtual bool ParseJsonRequest(Json::Value& result) const ORTHANC_OVERRIDE
     {
       result.clear();
       return true;
--- a/OrthancFramework/Sources/RestApi/RestApiGetCall.h	Thu Sep 17 08:35:11 2020 +0200
+++ b/OrthancFramework/Sources/RestApi/RestApiGetCall.h	Thu Sep 17 15:01:31 2020 +0200
@@ -61,6 +61,6 @@
       return getArguments_.find(name) != getArguments_.end();
     }
 
-    virtual bool ParseJsonRequest(Json::Value& result) const;
+    virtual bool ParseJsonRequest(Json::Value& result) const ORTHANC_OVERRIDE;
   };
 }
--- a/OrthancFramework/Sources/RestApi/RestApiHierarchy.cpp	Thu Sep 17 08:35:11 2020 +0200
+++ b/OrthancFramework/Sources/RestApi/RestApiHierarchy.cpp	Thu Sep 17 15:01:31 2020 +0200
@@ -411,7 +411,8 @@
       std::set<HttpMethod>& methods_;
 
     public:
-      AcceptedMethodsVisitor(std::set<HttpMethod>& methods) : methods_(methods)
+      explicit AcceptedMethodsVisitor(std::set<HttpMethod>& methods) :
+        methods_(methods)
       {
       }
 
--- a/OrthancFramework/Sources/RestApi/RestApiPath.h	Thu Sep 17 08:35:11 2020 +0200
+++ b/OrthancFramework/Sources/RestApi/RestApiPath.h	Thu Sep 17 15:01:31 2020 +0200
@@ -37,7 +37,7 @@
     std::vector<std::string> components_;
 
   public:
-    RestApiPath(const std::string& uri);
+    explicit RestApiPath(const std::string& uri);
 
     // This version is slower
     bool Match(IHttpHandler::Arguments& components,
--- a/OrthancFramework/Sources/RestApi/RestApiPostCall.h	Thu Sep 17 08:35:11 2020 +0200
+++ b/OrthancFramework/Sources/RestApi/RestApiPostCall.h	Thu Sep 17 15:01:31 2020 +0200
@@ -68,7 +68,7 @@
       result.assign(reinterpret_cast<const char*>(bodyData_), bodySize_);
     }
 
-    virtual bool ParseJsonRequest(Json::Value& result) const
+    virtual bool ParseJsonRequest(Json::Value& result) const ORTHANC_OVERRIDE
     {
       return ParseJsonRequestInternal(result, reinterpret_cast<const char*>(bodyData_), bodySize_);
     }
--- a/OrthancFramework/Sources/RestApi/RestApiPutCall.h	Thu Sep 17 08:35:11 2020 +0200
+++ b/OrthancFramework/Sources/RestApi/RestApiPutCall.h	Thu Sep 17 15:01:31 2020 +0200
@@ -68,7 +68,7 @@
       result.assign(reinterpret_cast<const char*>(bodyData_), bodySize_);
     }
 
-    virtual bool ParseJsonRequest(Json::Value& result) const
+    virtual bool ParseJsonRequest(Json::Value& result) const ORTHANC_OVERRIDE
     {
       return ParseJsonRequestInternal(result, reinterpret_cast<const char*>(bodyData_), bodySize_);
     }      
--- a/OrthancFramework/Sources/SerializationToolbox.h	Thu Sep 17 08:35:11 2020 +0200
+++ b/OrthancFramework/Sources/SerializationToolbox.h	Thu Sep 17 15:01:31 2020 +0200
@@ -66,12 +66,12 @@
                               const Json::Value& value,
                               const std::string& field);
 
-    static void ReadMapOfStrings(std::map<std::string, std::string>& values,
-                                 const Json::Value& target,
+    static void ReadMapOfStrings(std::map<std::string, std::string>& target,
+                                 const Json::Value& value,
                                  const std::string& field);
 
-    static void ReadMapOfTags(std::map<DicomTag, std::string>& values,
-                              const Json::Value& target,
+    static void ReadMapOfTags(std::map<DicomTag, std::string>& target,
+                              const Json::Value& value,
                               const std::string& field);
 
     static void WriteArrayOfStrings(Json::Value& target,
--- a/OrthancFramework/Sources/SystemToolbox.cpp	Thu Sep 17 08:35:11 2020 +0200
+++ b/OrthancFramework/Sources/SystemToolbox.cpp	Thu Sep 17 15:01:31 2020 +0200
@@ -637,7 +637,7 @@
     // CPUs or cores or hyperthreading units)
     unsigned int threads = boost::thread::hardware_concurrency();
     
-    if (threads <= 0)
+    if (threads == 0)
     {
       return 1;
     }
--- a/OrthancFramework/Sources/Toolbox.cpp	Thu Sep 17 08:35:11 2020 +0200
+++ b/OrthancFramework/Sources/Toolbox.cpp	Thu Sep 17 15:01:31 2020 +0200
@@ -913,7 +913,7 @@
   {
     // http://sourceforge.net/p/predef/wiki/Endianness/
 
-    uint32_t bufferView;
+    uint32_t bufferView = 0;
 
     uint8_t* buffer = reinterpret_cast<uint8_t*>(&bufferView);
 
@@ -1569,27 +1569,27 @@
     }
 #endif
 
-    // Make Orthanc use English, United States locale
-    // Linux: use "en_US.UTF-8"
-    // Windows: use ""
-    // Wine: use NULL
-    
-#if defined(__MINGW32__)
-    // Visibly, there is no support of locales in MinGW yet
-    // http://mingw.5.n7.nabble.com/How-to-use-std-locale-global-with-MinGW-correct-td33048.html
-    static const char* DEFAULT_LOCALE = NULL;
-#elif defined(_WIN32)
-    // For Windows: use default locale (using "en_US" does not work)
-    static const char* DEFAULT_LOCALE = "";
-#else
-    // For Linux & cie
-    static const char* DEFAULT_LOCALE = "en_US.UTF-8";
-#endif
-
     bool ok;
     
     if (locale == NULL)
     {
+      // Make Orthanc use English, United States locale
+      // Linux: use "en_US.UTF-8"
+      // Windows: use ""
+      // Wine: use NULL
+    
+#if defined(__MINGW32__)
+      // Visibly, there is no support of locales in MinGW yet
+      // http://mingw.5.n7.nabble.com/How-to-use-std-locale-global-with-MinGW-correct-td33048.html
+      static const char* DEFAULT_LOCALE = NULL;
+#elif defined(_WIN32)
+      // For Windows: use default locale (using "en_US" does not work)
+      static const char* DEFAULT_LOCALE = "";
+#else
+      // For Linux & cie
+      static const char* DEFAULT_LOCALE = "en_US.UTF-8";
+#endif
+
       ok = SetGlobalLocale(DEFAULT_LOCALE);
 
 #if defined(__MINGW32__)
@@ -1773,7 +1773,7 @@
       const Dictionary& dictionary_;
 
     public:
-      VariableFormatter(const Dictionary& dictionary) :
+      explicit VariableFormatter(const Dictionary& dictionary) :
         dictionary_(dictionary)
       {
       }
@@ -2253,10 +2253,10 @@
         assert(array.isArray());
 
         Json::Value children = Json::arrayValue;
-        for (Json::Value::ArrayIndex i = 0; i < array.size(); i++)
+        for (Json::Value::ArrayIndex j = 0; j < array.size(); j++)
         {
           Json::Value c;
-          SimplifyDicomAsJson(c, array[i], format);
+          SimplifyDicomAsJson(c, array[j], format);
           children.append(c);
         }
 
--- a/OrthancFramework/UnitTestsSources/FileStorageTests.cpp	Thu Sep 17 08:35:11 2020 +0200
+++ b/OrthancFramework/UnitTestsSources/FileStorageTests.cpp	Thu Sep 17 15:01:31 2020 +0200
@@ -98,8 +98,8 @@
   ASSERT_EQ(10u, ss.size());
   
   unsigned int c = 0;
-  for (std::list<std::string>::iterator
-         i = u.begin(); i != u.end(); i++, c++)
+  for (std::list<std::string>::const_iterator
+         i = u.begin(); i != u.end(); ++i, c++)
   {
     ASSERT_TRUE(ss.find(*i) != ss.end());
     if (c < 5)
--- a/OrthancFramework/UnitTestsSources/FromDcmtkTests.cpp	Thu Sep 17 08:35:11 2020 +0200
+++ b/OrthancFramework/UnitTestsSources/FromDcmtkTests.cpp	Thu Sep 17 15:01:31 2020 +0200
@@ -40,7 +40,6 @@
 #include "../Sources/DicomParsing/DicomModification.h"
 #include "../Sources/DicomParsing/DicomWebJsonVisitor.h"
 #include "../Sources/DicomParsing/FromDcmtkBridge.h"
-#include "../Sources/DicomParsing/Internals/DicomImageDecoder.h"
 #include "../Sources/DicomParsing/ToDcmtkBridge.h"
 #include "../Sources/Endianness.h"
 #include "../Sources/Images/Image.h"
@@ -781,7 +780,7 @@
     Orthanc::SystemToolbox::ReadFile(s, PATH);
     Orthanc::ParsedDicomFile f(s);
     
-    std::unique_ptr<Orthanc::ImageAccessor> decoded(Orthanc::DicomImageDecoder::Decode(f, 0));
+    std::unique_ptr<Orthanc::ImageAccessor> decoded(f.DecodeFrame(0));
     ASSERT_EQ(256u, decoded->GetWidth());
     ASSERT_EQ(256u, decoded->GetHeight());
     ASSERT_EQ(Orthanc::PixelFormat_Grayscale8, decoded->GetFormat());
@@ -843,7 +842,7 @@
     Orthanc::SystemToolbox::ReadFile(s, PATH);
     Orthanc::ParsedDicomFile f(s);
     
-    std::unique_ptr<Orthanc::ImageAccessor> decoded(Orthanc::DicomImageDecoder::Decode(f, 0));
+    std::unique_ptr<Orthanc::ImageAccessor> decoded(f.DecodeFrame(0));
     ASSERT_EQ(384u, decoded->GetWidth());
     ASSERT_EQ(256u, decoded->GetHeight());
     ASSERT_EQ(Orthanc::PixelFormat_RGB24, decoded->GetFormat());
@@ -900,7 +899,7 @@
     Orthanc::SystemToolbox::ReadFile(s, PATH);
     Orthanc::ParsedDicomFile f(s);
     
-    std::unique_ptr<Orthanc::ImageAccessor> decoded(Orthanc::DicomImageDecoder::Decode(f, 0));
+    std::unique_ptr<Orthanc::ImageAccessor> decoded(f.DecodeFrame(0));
     ASSERT_EQ(256u, decoded->GetWidth());
     ASSERT_EQ(256u, decoded->GetHeight());
     ASSERT_EQ(Orthanc::PixelFormat_Grayscale16, decoded->GetFormat());
@@ -956,7 +955,7 @@
     Orthanc::SystemToolbox::ReadFile(s, PATH);
     Orthanc::ParsedDicomFile f(s);
     
-    std::unique_ptr<Orthanc::ImageAccessor> decoded(Orthanc::DicomImageDecoder::Decode(f, 0));
+    std::unique_ptr<Orthanc::ImageAccessor> decoded(f.DecodeFrame(0));
     ASSERT_EQ(256u, decoded->GetWidth());
     ASSERT_EQ(256u, decoded->GetHeight());
     ASSERT_EQ(Orthanc::PixelFormat_SignedGrayscale16, decoded->GetFormat());
@@ -972,7 +971,7 @@
 
 
 
-static void CheckEncoding(const ParsedDicomFile& dicom,
+static void CheckEncoding(ParsedDicomFile& dicom,
                           Encoding expected)
 {
   const char* value = NULL;
@@ -1052,8 +1051,9 @@
           // A specific source string is used in "EncodingTests.py" to
           // test against Chinese, it is normal that it does not correspond to UTF8
 
-          std::string encoded = Toolbox::ConvertToUtf8(Toolbox::ConvertFromUtf8(utf8, testEncodings[i]), testEncodings[i], false);
-          ASSERT_STREQ(testEncodingsExpected[i], encoded.c_str());
+          const std::string tmp = Toolbox::ConvertToUtf8(
+            Toolbox::ConvertFromUtf8(utf8, testEncodings[i]), testEncodings[i], false);
+          ASSERT_STREQ(testEncodingsExpected[i], tmp.c_str());
         }
       }
 
@@ -1969,8 +1969,7 @@
     DicomMap m;
     m.FromDicomWeb(visitor.GetResult());
     ASSERT_EQ(31u, m.GetSize());
-
-    std::string s;
+    
     ASSERT_TRUE(m.LookupStringValue(s, DicomTag(0x0002, 0x0002), false));  ASSERT_EQ("UI", s);
     ASSERT_TRUE(m.LookupStringValue(s, DicomTag(0x0040, 0x0241), false));  ASSERT_EQ("AE", s);
     ASSERT_TRUE(m.LookupStringValue(s, DicomTag(0x0010, 0x1010), false));  ASSERT_EQ("AS", s);
@@ -2019,8 +2018,7 @@
     ASSERT_TRUE(m.LookupStringValue(s, DicomTag(0x0008, 0x0119), true));  ASSERT_EQ("UC", s);
     ASSERT_TRUE(m.LookupStringValue(s, DicomTag(0x0008, 0x0120), true));  ASSERT_EQ("UR", s);
     ASSERT_TRUE(m.LookupStringValue(s, DicomTag(0x0008, 0x0301), true));  ASSERT_EQ("17", s);  // US (but tag unknown to DCMTK 3.6.0)
-#endif
-    
+#endif    
   }
 }
 
@@ -2107,10 +2105,10 @@
         std::string source;
         Orthanc::SystemToolbox::ReadFile(source, path);
 
-        std::string c, i;
+        std::string c, k;
         try
         {
-          scu.Transcode(c, i, transcoder, source.c_str(), source.size(), false, "", 0);
+          scu.Transcode(c, k, transcoder, source.c_str(), source.size(), false, "", 0);
         }
         catch (OrthancException& e)
         {
@@ -2120,7 +2118,7 @@
           }
           else
           {
-            throw e;
+            throw;
           }
         }
       }
@@ -2130,10 +2128,14 @@
 
 TEST(Toto, DISABLED_Transcode4)
 {
-  std::string source;
-  Orthanc::SystemToolbox::ReadFile(source, "/home/jodogne/Subversion/orthanc-tests/Database/KarstenHilbertRF.dcm");
+  std::unique_ptr<DcmFileFormat> toto;
 
-  std::unique_ptr<DcmFileFormat> toto(FromDcmtkBridge::LoadFromMemoryBuffer(source.c_str(), source.size()));
+  {
+    std::string source;
+    Orthanc::SystemToolbox::ReadFile(source, "/home/jodogne/Subversion/orthanc-tests/Database/KarstenHilbertRF.dcm");
+    toto.reset(FromDcmtkBridge::LoadFromMemoryBuffer(source.c_str(), source.size()));
+  }
+  
   const std::string sourceUid = IDicomTranscoder::GetSopInstanceUid(*toto);
   
   DicomTransferSyntax sourceSyntax;
--- a/OrthancServer/Resources/RunCppCheck.sh	Thu Sep 17 08:35:11 2020 +0200
+++ b/OrthancServer/Resources/RunCppCheck.sh	Thu Sep 17 15:01:31 2020 +0200
@@ -8,7 +8,17 @@
     CPPCHECK=$1
 fi
 
+cat <<EOF > /tmp/cppcheck-suppressions.txt
+constParameter:../../OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.cpp
+nullPointerRedundantCheck:../../OrthancFramework/UnitTestsSources/DicomMapTests.cpp
+stlFindInsert:../../OrthancFramework/Sources/DicomFormat/DicomMap.cpp
+unreadVariable:../../OrthancFramework/Sources/FileStorage/StorageAccessor.cpp
+useInitializationList:../../OrthancFramework/Sources/Images/PngReader.cpp
+syntaxError:../../OrthancFramework/Sources/SQLite/FunctionContext.h
+EOF
+
 ${CPPCHECK} --enable=all --quiet --std=c++11 \
+            --suppressions-list=/tmp/cppcheck-suppressions.txt \
             -DBOOST_HAS_DATE_TIME=1 \
             -DBOOST_HAS_FILESYSTEM_V3=1 \
             -DBOOST_HAS_REGEX=1 \
--- a/OrthancServer/Sources/ServerContext.cpp	Thu Sep 17 08:35:11 2020 +0200
+++ b/OrthancServer/Sources/ServerContext.cpp	Thu Sep 17 15:01:31 2020 +0200
@@ -1440,8 +1440,7 @@
       // Use Orthanc's built-in decoder, using the cache to speed-up
       // things on multi-frame images
       ServerContext::DicomCacheLocker locker(*this, publicId);        
-      std::unique_ptr<ImageAccessor> decoded(
-        DicomImageDecoder::Decode(locker.GetDicom(), frameIndex));
+      std::unique_ptr<ImageAccessor> decoded(locker.GetDicom().DecodeFrame(frameIndex));
       if (decoded.get() != NULL)
       {
         return decoded.release();
@@ -1472,7 +1471,7 @@
     if (builtinDecoderTranscoderOrder_ == BuiltinDecoderTranscoderOrder_After)
     {
       ServerContext::DicomCacheLocker locker(*this, publicId);        
-      return DicomImageDecoder::Decode(locker.GetDicom(), frameIndex);
+      return locker.GetDicom().DecodeFrame(frameIndex);
     }
     else
     {
@@ -1486,8 +1485,7 @@
   {
     if (builtinDecoderTranscoderOrder_ == BuiltinDecoderTranscoderOrder_Before)
     {
-      std::unique_ptr<ImageAccessor> decoded(
-        DicomImageDecoder::Decode(dicom.GetParsedDicomFile(), frameIndex));
+      std::unique_ptr<ImageAccessor> decoded(dicom.GetParsedDicomFile().DecodeFrame(frameIndex));
       if (decoded.get() != NULL)
       {
         return decoded.release();
@@ -1514,7 +1512,7 @@
 
     if (builtinDecoderTranscoderOrder_ == BuiltinDecoderTranscoderOrder_After)
     {
-      return DicomImageDecoder::Decode(dicom.GetParsedDicomFile(), frameIndex);
+      return dicom.GetParsedDicomFile().DecodeFrame(frameIndex);
     }
     else
     {