changeset 1167:ad4e21df4e40 broker

enriching OrthancStone::StoneInitialize()
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 20 Nov 2019 10:55:44 +0100
parents 4d97f532f1e0
children 1644de437a7b
files Framework/StoneInitialization.cpp Framework/Toolbox/LinearAlgebra.cpp UnitTestsSources/UnitTestsMain.cpp
diffstat 3 files changed, 138 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/Framework/StoneInitialization.cpp	Tue Nov 19 21:40:25 2019 +0100
+++ b/Framework/StoneInitialization.cpp	Wed Nov 20 10:55:44 2019 +0100
@@ -21,20 +21,43 @@
 
 #include "StoneInitialization.h"
 
-#include <Core/OrthancException.h>
-
 #if !defined(ORTHANC_ENABLE_SDL)
 #  error Macro ORTHANC_ENABLE_SDL must be defined
 #endif
 
+#if !defined(ORTHANC_ENABLE_SSL)
+#  error Macro ORTHANC_ENABLE_SSL must be defined
+#endif
+
+#if !defined(ORTHANC_ENABLE_CURL)
+#  error Macro ORTHANC_ENABLE_CURL must be defined
+#endif
+
+#if !defined(ORTHANC_ENABLE_DCMTK)
+#  error Macro ORTHANC_ENABLE_DCMTK must be defined
+#  if !defined(DCMTK_VERSION_NUMBER)
+#    error Macro DCMTK_VERSION_NUMBER must be defined
+#  endif
+#endif
+
 #if ORTHANC_ENABLE_SDL == 1
 #  include "Viewport/SdlWindow.h"
 #endif
 
 #if ORTHANC_ENABLE_CURL == 1
-#include <Core/HttpClient.h>
+#  include <Core/HttpClient.h>
+#endif
+
+#if ORTHANC_ENABLE_DCMTK == 1
+#  include <Core/DicomParsing/FromDcmtkBridge.h>
 #endif
 
+#include "Toolbox/LinearAlgebra.h"
+
+#include <Core/OrthancException.h>
+#include <Core/Toolbox.h>
+
+
 namespace OrthancStone
 {
 #if ORTHANC_ENABLE_LOGGING_PLUGIN == 1
@@ -49,14 +72,46 @@
     Orthanc::Logging::Initialize();
 #endif
 
-#if ORTHANC_ENABLE_SDL == 1
-    OrthancStone::SdlWindow::GlobalInitialize();
+#if ORTHANC_ENABLE_SSL == 1
+    // Must be before curl
+    Orthanc::Toolbox::InitializeOpenSsl();
 #endif
 
 #if ORTHANC_ENABLE_CURL == 1
     Orthanc::HttpClient::GlobalInitialize();
+#  if ORTHANC_ENABLE_SSL == 1
+    Orthanc::HttpClient::ConfigureSsl(false, "");
+#  endif
+#endif
+
+#if ORTHANC_ENABLE_DCMTK == 1
+    Orthanc::FromDcmtkBridge::InitializeDictionary(true);
+    Orthanc::FromDcmtkBridge::InitializeCodecs();
+#  if DCMTK_VERSION_NUMBER <= 360
+    OFLog::configure(OFLogger::FATAL_LOG_LEVEL);
+#  else
+    OFLog::configure(OFLogger::OFF_LOG_LEVEL);
+#  endif
+#endif
+
+    {
+      // Run-time check of locale settings after Qt has been initialized
+      OrthancStone::Vector v;
+      if (!OrthancStone::LinearAlgebra::ParseVector(v, "1.3671875\\-1.3671875") ||
+          v.size() != 2 ||
+          !OrthancStone::LinearAlgebra::IsNear(1.3671875f, v[0]) ||
+          !OrthancStone::LinearAlgebra::IsNear(-1.3671875f, v[1]))
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError,
+                                        "Error in the locale settings, giving up");
+      }
+    }
+
+#if ORTHANC_ENABLE_SDL == 1
+    OrthancStone::SdlWindow::GlobalInitialize();
 #endif
   }
+  
 
   void StoneFinalize()
   {
@@ -64,10 +119,18 @@
     OrthancStone::SdlWindow::GlobalFinalize();
 #endif
     
+#if ORTHANC_ENABLE_DCMTK == 1
+    Orthanc::FromDcmtkBridge::FinalizeCodecs();
+#endif
+
 #if ORTHANC_ENABLE_CURL == 1
     Orthanc::HttpClient::GlobalFinalize();
 #endif
 
+#if ORTHANC_ENABLE_SSL == 1
+    Orthanc::Toolbox::FinalizeOpenSsl();
+#endif
+
     Orthanc::Logging::Finalize();
   }
 }
--- a/Framework/Toolbox/LinearAlgebra.cpp	Tue Nov 19 21:40:25 2019 +0100
+++ b/Framework/Toolbox/LinearAlgebra.cpp	Wed Nov 20 10:55:44 2019 +0100
@@ -32,6 +32,7 @@
 
 #include <stdio.h>
 #include <iostream>
+#include <cstdlib>
 
 namespace OrthancStone
 {
@@ -75,20 +76,27 @@
       {
         /**
          * SJO - 2019-11-19 - WARNING: I reverted from "std::stod()"
-         * to "boost::lexical_cast", as "std::stod()" is sensitive to
-         * locale settings, making this code non portable and very
-         * dangerous as it fails silently. A string such as
-         * "1.3671875\1.3671875" is interpreted as "1\1", because
-         * "std::stod()" expects a comma (",") instead of a point
-         * (".").
+         * to "boost::lexical_cast", as both "std::stod()" and
+         * "std::strtod()" are sensitive to locale settings, making
+         * this code non portable and very dangerous as it fails
+         * silently. A string such as "1.3671875\1.3671875" is
+         * interpreted as "1\1", because "std::stod()" expects a comma
+         * (",") instead of a point ("."). This problem is notably
+         * seen in Qt-based applications, that somehow set locales
+         * aggressively.
+         *
+         * "boost::lexical_cast<>" is also dependent on the locale
+         * settings, but apparently not in a way that makes this
+         * function fail with Qt. The Orthanc core defines macro
+         * "-DBOOST_LEXICAL_CAST_ASSUME_C_LOCALE" in static builds to
+         * this end.
          **/
         
 #if 0  // __cplusplus >= 201103L  // Is C++11 enabled?
         /**
          * We try and avoid the use of "boost::lexical_cast<>" here,
-         * as it is very slow. As we are parsing many doubles, we
-         * prefer to use the standard "std::stod" function if
-         * available: http://www.cplusplus.com/reference/string/stod/
+         * as it is very slow, and as Stone has to parse many doubles.
+         * https://tinodidriksen.com/2011/05/cpp-convert-string-to-double-speed/
          **/
           
         try
@@ -100,7 +108,26 @@
           target.clear();
           return false;
         }
-#else  // Fallback implementation using Boost
+
+#elif 0
+        /**
+         * "std::strtod()" is the recommended alternative to
+         * "std::stod()". It is apparently as fast as plain-C
+         * "atof()", with more security.
+         **/
+        char* end = NULL;
+        target[i] = std::strtod(items[i].c_str(), &end);
+        if (end == NULL ||
+            end != items[i].c_str() + items[i].size())
+        {
+          return false;
+        }
+
+#else
+        /**
+         * Fallback implementation using Boost (slower, but somewhat
+         * independent to locale).
+         **/
         try
         {
           target[i] = boost::lexical_cast<double>(items[i]);
--- a/UnitTestsSources/UnitTestsMain.cpp	Tue Nov 19 21:40:25 2019 +0100
+++ b/UnitTestsSources/UnitTestsMain.cpp	Wed Nov 20 10:55:44 2019 +0100
@@ -25,6 +25,7 @@
 #include "../Framework/Deprecated/Toolbox/DownloadStack.h"
 #include "../Framework/Deprecated/Toolbox/MessagingToolbox.h"
 #include "../Framework/Deprecated/Toolbox/OrthancSlicesLoader.h"
+#include "../Framework/StoneInitialization.h"
 #include "../Framework/Toolbox/FiniteProjectiveCamera.h"
 #include "../Framework/Toolbox/GeometryToolbox.h"
 #include "../Framework/Volumes/ImageBuffer3D.h"
@@ -696,6 +697,8 @@
   
   for (int p = 0; p < 3; p++)
   {
+    printf("=========== %d\n", p);
+    
     OrthancStone::VolumeProjection projection = (OrthancStone::VolumeProjection) p;
     const OrthancStone::CoordinateSystem3D& s = g.GetProjectionGeometry(projection);
     
@@ -703,6 +706,8 @@
 
     for (unsigned int i = 0; i < g.GetProjectionDepth(projection); i++)
     {
+      printf("------------- %d\n", i);
+    
       OrthancStone::CoordinateSystem3D plane = g.GetProjectionSlice(projection, i);
 
       ASSERT_TRUE(IsEqualVector(plane.GetOrigin(), s.GetOrigin() + static_cast<double>(i) * 
@@ -714,20 +719,44 @@
       OrthancStone::VolumeProjection q;
       ASSERT_TRUE(g.DetectSlice(q, slice, plane));
       ASSERT_EQ(projection, q);
-      ASSERT_EQ(i, slice);     
+      ASSERT_EQ(i, slice);
     }
   }
 }
 
+
+TEST(LinearAlgebra, ParseVectorLocale)
+{
+  OrthancStone::Vector v;
+
+  ASSERT_TRUE(OrthancStone::LinearAlgebra::ParseVector(v, "1.2"));
+  ASSERT_EQ(1u, v.size());
+  ASSERT_FLOAT_EQ(1.2f, v[0]);
+
+  ASSERT_TRUE(OrthancStone::LinearAlgebra::ParseVector(v, "-1.2e+2"));
+  ASSERT_EQ(1u, v.size());
+  ASSERT_FLOAT_EQ(-120.0f, v[0]);
+
+  ASSERT_TRUE(OrthancStone::LinearAlgebra::ParseVector(v, "-1e-2\\2"));
+  ASSERT_EQ(2u, v.size());
+  ASSERT_FLOAT_EQ(-0.01f, v[0]);
+  ASSERT_FLOAT_EQ(2.0f, v[1]);
+
+  ASSERT_TRUE(OrthancStone::LinearAlgebra::ParseVector(v, "1.3671875\\1.3671875"));
+  ASSERT_EQ(2u, v.size());
+  ASSERT_FLOAT_EQ(1.3671875, v[0]);
+  ASSERT_FLOAT_EQ(1.3671875, v[1]); 
+}
+
+
 int main(int argc, char **argv)
 {
-  Orthanc::Logging::Initialize();
-  Orthanc::Logging::EnableInfoLevel(true);
+  OrthancStone::StoneInitialize();
 
   ::testing::InitGoogleTest(&argc, argv);
   int result = RUN_ALL_TESTS();
 
-  Orthanc::Logging::Finalize();
+  OrthancStone::StoneFinalize();
 
   return result;
 }