| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // SPDX-FileCopyrightText: 2023 Carl Zeiss Microscopy GmbH | ||
| 2 | // | ||
| 3 | // SPDX-License-Identifier: MIT | ||
| 4 | |||
| 5 | #include "ClassFactory.h" | ||
| 6 | |||
| 7 | #include <charconv> | ||
| 8 | #include <cstdlib> | ||
| 9 | #include "../doc/document.h" | ||
| 10 | #include "../src/db/DbFactory.h" | ||
| 11 | #include "../src/db/database_creator.h" | ||
| 12 | #include "../src/db/database_discovery.h" | ||
| 13 | |||
| 14 | #include <libimgdoc2_config.h> | ||
| 15 | |||
| 16 | using namespace std; | ||
| 17 | using namespace imgdoc2; | ||
| 18 | |||
| 19 | class StandardHostingEnvironment : public IHostingEnvironment | ||
| 20 | { | ||
| 21 | public: | ||
| 22 | ✗ | void Log(int level, const char* message) override | |
| 23 | { | ||
| 24 | // TODO(JBL): on Windows, let's use DebugOutputString, | ||
| 25 | // on Linux - I am not sure what to do | ||
| 26 | ✗ | } | |
| 27 | |||
| 28 | ✗ | bool IsLogLevelActive(int level) override | |
| 29 | { | ||
| 30 | ✗ | return true; | |
| 31 | } | ||
| 32 | |||
| 33 | ✗ | void ReportFatalErrorAndExit(const char* message) override | |
| 34 | { | ||
| 35 | ✗ | abort(); | |
| 36 | } | ||
| 37 | }; | ||
| 38 | |||
| 39 | class NullHostingEnvironment : public IHostingEnvironment | ||
| 40 | { | ||
| 41 | public: | ||
| 42 | ✗ | void Log(int level, const char* message) override | |
| 43 | { | ||
| 44 | ✗ | } | |
| 45 | |||
| 46 | 202620 | bool IsLogLevelActive(int level) override | |
| 47 | { | ||
| 48 | 202620 | return false; | |
| 49 | } | ||
| 50 | |||
| 51 | ✗ | void ReportFatalErrorAndExit(const char* message) override | |
| 52 | { | ||
| 53 | ✗ | abort(); | |
| 54 | } | ||
| 55 | }; | ||
| 56 | |||
| 57 | class HostingEnvironmentOnFunctionPointers : public IHostingEnvironment | ||
| 58 | { | ||
| 59 | private: | ||
| 60 | std::intptr_t userparam_; | ||
| 61 | void (*pfnLog_)(std::intptr_t userparam, int level, const char* szMessage); | ||
| 62 | bool (*pfnIsLevelActive_)(std::intptr_t userparam, int level); | ||
| 63 | void (*pfnReportFatalErrorAndExit_)(std::intptr_t userparam, const char* szMessage); | ||
| 64 | public: | ||
| 65 | 2 | explicit HostingEnvironmentOnFunctionPointers(std::intptr_t userparam, | |
| 66 | void (*pfnLog)(std::intptr_t userparam, int level, const char* szMessage), | ||
| 67 | bool (*pfnIsLevelActive)(std::intptr_t userparam, int level), | ||
| 68 | void (*pfnReportFatalErrorAndExit)(std::intptr_t userparam, const char* szMessage)) | ||
| 69 | 4 | : userparam_(userparam), | |
| 70 | 2 | pfnLog_(pfnLog), | |
| 71 | 2 | pfnIsLevelActive_(pfnIsLevelActive), | |
| 72 | 2 | pfnReportFatalErrorAndExit_(pfnReportFatalErrorAndExit) | |
| 73 | 2 | {} | |
| 74 | |||
| 75 | 18 | void Log(int level, const char* message) override | |
| 76 | { | ||
| 77 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | if (this->pfnLog_ != nullptr) |
| 78 | { | ||
| 79 | 18 | this->pfnLog_(this->userparam_, level, message); | |
| 80 | } | ||
| 81 | 18 | } | |
| 82 | |||
| 83 | 22 | bool IsLogLevelActive(int level) override | |
| 84 | { | ||
| 85 |
1/2✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
|
22 | if (this->pfnIsLevelActive_ != nullptr) |
| 86 | { | ||
| 87 | 22 | return this->pfnIsLevelActive_(this->userparam_, level); | |
| 88 | } | ||
| 89 | |||
| 90 | ✗ | return false; | |
| 91 | } | ||
| 92 | |||
| 93 | ✗ | void ReportFatalErrorAndExit(const char* message) override | |
| 94 | { | ||
| 95 | ✗ | if (this->pfnReportFatalErrorAndExit_ != nullptr) | |
| 96 | { | ||
| 97 | ✗ | this->pfnReportFatalErrorAndExit_(this->userparam_, message); | |
| 98 | } | ||
| 99 | |||
| 100 | ✗ | abort(); | |
| 101 | } | ||
| 102 | }; | ||
| 103 | |||
| 104 | //------------------------------------------------------------------------ | ||
| 105 | |||
| 106 | 6 | static std::uint32_t convert_to_uint32(const char* str) | |
| 107 | { | ||
| 108 | 6 | std::uint32_t result = 0; | |
| 109 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | auto [ptr, ec] = std::from_chars(str, str + strlen(str), result); |
| 110 |
3/6✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
|
6 | if (ec == std::errc::invalid_argument || ec == std::errc::result_out_of_range || *ptr != '\0') |
| 111 | { | ||
| 112 | ✗ | return (numeric_limits<uint32_t>::max)(); | |
| 113 | } | ||
| 114 | |||
| 115 | 6 | return result; | |
| 116 | } | ||
| 117 | |||
| 118 | 2 | /*static*/VersionInfo imgdoc2::ClassFactory::GetVersionInfo() | |
| 119 | { | ||
| 120 | 2 | VersionInfo version_info; | |
| 121 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | version_info.major = convert_to_uint32(LIBIMGDOC2_VERSION_MAJOR); |
| 122 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | version_info.minor = convert_to_uint32(LIBIMGDOC2_VERSION_MINOR); |
| 123 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | version_info.patch = convert_to_uint32(LIBIMGDOC2_VERSION_PATCH); |
| 124 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | version_info.compiler_identification = LIBIMGDOC2_CXX_COMPILER_IDENTIFICATION; |
| 125 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | version_info.build_type = LIBIMGDOC2_BUILD_TYPE; |
| 126 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | version_info.repository_url = LIBIMGDOC2_REPOSITORYREMOTEURL; |
| 127 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | version_info.repository_branch = LIBIMGDOC2_REPOSITORYBRANCH; |
| 128 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | version_info.repository_tag = LIBIMGDOC2_REPOSITORYHASH; |
| 129 | |||
| 130 | 2 | return version_info; | |
| 131 | ✗ | } | |
| 132 | |||
| 133 | 248 | /*static*/std::shared_ptr<imgdoc2::IDoc> imgdoc2::ClassFactory::CreateNew(imgdoc2::ICreateOptions* create_options, std::shared_ptr<IHostingEnvironment> environment) | |
| 134 | { | ||
| 135 | // TODO(JBL): here would be the place where we'd allow for "other databases than Sqlite", for the time being, | ||
| 136 | // we just deal with Sqlite here | ||
| 137 |
2/4✓ Branch 2 taken 248 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 248 times.
✗ Branch 7 not taken.
|
248 | auto db_connection = DbFactory::SqliteCreateNewDatabase(create_options->GetFilename().c_str(), environment); |
| 138 | |||
| 139 | // check pre-conditions | ||
| 140 | // TODO(JBL) | ||
| 141 | |||
| 142 | // tweak settings | ||
| 143 |
3/6✓ Branch 1 taken 248 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 178 times.
✓ Branch 4 taken 70 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
248 | switch (create_options->GetDocumentType()) // NOLINT(clang-diagnostic-switch) |
| 144 | { | ||
| 145 | 178 | case DocumentType::kImage2d: | |
| 146 | { | ||
| 147 | 178 | DbCreator db_creator(db_connection); | |
| 148 |
1/2✓ Branch 1 taken 178 times.
✗ Branch 2 not taken.
|
178 | const auto database_configuration_2d = db_creator.CreateTables2d(create_options); |
| 149 | |||
| 150 |
1/2✓ Branch 1 taken 178 times.
✗ Branch 2 not taken.
|
178 | if (database_configuration_2d) |
| 151 | { | ||
| 152 |
1/2✓ Branch 1 taken 178 times.
✗ Branch 2 not taken.
|
178 | return make_shared<Document>(db_connection, database_configuration_2d); |
| 153 | } | ||
| 154 | |||
| 155 | ✗ | break; | |
| 156 |
2/4✓ Branch 1 taken 178 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 178 times.
✗ Branch 5 not taken.
|
356 | } |
| 157 | 70 | case DocumentType::kImage3d: | |
| 158 | { | ||
| 159 | 70 | DbCreator db_creator(db_connection); | |
| 160 |
1/2✓ Branch 1 taken 70 times.
✗ Branch 2 not taken.
|
70 | const auto database_configuration_3d = db_creator.CreateTables3d(create_options); |
| 161 | |||
| 162 |
1/2✓ Branch 1 taken 70 times.
✗ Branch 2 not taken.
|
70 | if (database_configuration_3d) |
| 163 | { | ||
| 164 |
1/2✓ Branch 1 taken 70 times.
✗ Branch 2 not taken.
|
70 | return make_shared<Document>(db_connection, database_configuration_3d); |
| 165 | } | ||
| 166 | |||
| 167 | ✗ | break; | |
| 168 |
2/4✓ Branch 1 taken 70 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 70 times.
✗ Branch 5 not taken.
|
140 | } |
| 169 | ✗ | case DocumentType::kInvalid: | |
| 170 | ✗ | break; | |
| 171 | } | ||
| 172 | |||
| 173 | ✗ | return {}; | |
| 174 | 248 | } | |
| 175 | |||
| 176 | 4 | /*static*/std::shared_ptr<imgdoc2::IDoc> imgdoc2::ClassFactory::OpenExisting(imgdoc2::IOpenExistingOptions* open_existing_options, std::shared_ptr<IHostingEnvironment> environment) | |
| 177 | { | ||
| 178 | // TODO(JBL): here would be the place where we'd allow for "other databases than Sqlite", for the time being, | ||
| 179 | // we just deal with Sqlite here | ||
| 180 |
3/6✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
|
4 | auto db_connection = DbFactory::SqliteOpenExistingDatabase(open_existing_options->GetFilename().c_str(), open_existing_options->GetOpenReadonly(), environment); |
| 181 | |||
| 182 | 4 | DbDiscovery database_discovery{ db_connection }; | |
| 183 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | database_discovery.DoDiscovery(); |
| 184 | |||
| 185 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | const auto database_configuration_2d = database_discovery.GetDatabaseConfiguration2DOrNull(); |
| 186 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
|
4 | if (database_configuration_2d) |
| 187 | { | ||
| 188 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | return make_shared<Document>(db_connection, database_configuration_2d); |
| 189 | } | ||
| 190 | |||
| 191 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | const auto database_configuration_3d = database_discovery.GetDatabaseConfiguration3DOrNull(); |
| 192 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | if (database_configuration_3d) |
| 193 | { | ||
| 194 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | return make_shared<Document>(db_connection, database_configuration_3d); |
| 195 | } | ||
| 196 | |||
| 197 | ✗ | return {}; | |
| 198 | 4 | } | |
| 199 | |||
| 200 | ✗ | /*static*/std::shared_ptr<IHostingEnvironment> imgdoc2::ClassFactory::CreateStandardHostingEnvironment() | |
| 201 | { | ||
| 202 | ✗ | return make_shared<StandardHostingEnvironment>(); | |
| 203 | } | ||
| 204 | |||
| 205 | 270 | /*static*/std::shared_ptr<IHostingEnvironment> imgdoc2::ClassFactory::CreateNullHostingEnvironment() | |
| 206 | { | ||
| 207 |
1/2✓ Branch 1 taken 270 times.
✗ Branch 2 not taken.
|
270 | return make_shared<NullHostingEnvironment>(); |
| 208 | } | ||
| 209 | |||
| 210 | 2 | /*static*/std::shared_ptr<IHostingEnvironment> imgdoc2::ClassFactory::CreateHostingEnvironmentForFunctionPointers( | |
| 211 | std::intptr_t userparam, | ||
| 212 | void (*pfnLog)(std::intptr_t userparam, int level, const char* szMessage), | ||
| 213 | bool (*pfnIsLevelActive)(std::intptr_t userparam, int level), | ||
| 214 | void (*pfnReportFatalErrorAndExit)(std::intptr_t userparam, const char* szMessage)) | ||
| 215 | { | ||
| 216 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
4 | return make_shared<HostingEnvironmentOnFunctionPointers>( |
| 217 | userparam, | ||
| 218 | pfnLog, | ||
| 219 | pfnIsLevelActive, | ||
| 220 | 4 | pfnReportFatalErrorAndExit); | |
| 221 | } | ||
| 222 |