# HG changeset patch # User Sebastien Jodogne # Date 1574243744 -3600 # Node ID ad4e21df4e40f14a601c93c1469932b197670c42 # Parent 4d97f532f1e0f487c15e7ccd604d6f0fcd4cf547 enriching OrthancStone::StoneInitialize() diff -r 4d97f532f1e0 -r ad4e21df4e40 Framework/StoneInitialization.cpp --- 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 - #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 +# include +#endif + +#if ORTHANC_ENABLE_DCMTK == 1 +# include #endif +#include "Toolbox/LinearAlgebra.h" + +#include +#include + + 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(); } } diff -r 4d97f532f1e0 -r ad4e21df4e40 Framework/Toolbox/LinearAlgebra.cpp --- 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 #include +#include 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(items[i]); diff -r 4d97f532f1e0 -r ad4e21df4e40 UnitTestsSources/UnitTestsMain.cpp --- 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(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; }