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 |