Cogs.Core
Config.cpp
1#include "Foundation/Logging/Logger.h"
2
3#include "Context.h"
4#include "Serialization/JsonParser.h"
5
6#include "Image360System.h"
7
8namespace {
9 using namespace Cogs::Core;
10 using namespace Cogs::Core::Image360;
11
13
14 bool parseJsonChannel(Config& config, const Value& channelJson)
15 {
16 if (!channelJson.IsObject()) {
17 LOG_ERROR(logger, "json: channel item not an object");
18 return false;
19 }
20
21 Config::Channel channel;
22
23 for (const auto& channelMemberJson : channelJson.GetObject()) {
24 Cogs::StringView channelMemberName = toView(channelMemberJson.name);
25 switch (channelMemberName.hash()) {
26
27
28 case Cogs::hash("dataType"):
29 if (channelMemberJson.value.IsString()) {
30 Cogs::StringView dataTypeJson = toView(channelMemberJson.value);
31 switch (dataTypeJson.hash()) {
32 case Cogs::hash("SRGB8_JPEG"):
33 channel.dataType = Config::Channel::DataType::SRGB8_JPEG;
34 break;
35 case Cogs::hash("SRGB8_PNG"):
36 channel.dataType = Config::Channel::DataType::SRGB8_PNG;
37 break;
38 case Cogs::hash("SRGBA8_PNG"):
39 channel.dataType = Config::Channel::DataType::SRGBA8_PNG;
40 break;
41 case Cogs::hash("U16"):
42 channel.dataType = Config::Channel::DataType::U16;
43 break;
44 case Cogs::hash("U16_ZST"):
45 channel.dataType = Config::Channel::DataType::U16_ZST;
46 break;
47 default:
48 LOG_ERROR(logger, "json: unrecognized channel item member 'dataType' value '%.*s'", StringViewFormat(dataTypeJson));
49 return false;
50 }
51 }
52 else {
53 LOG_ERROR(logger, "json: channel item member 'dataType' is not a string");
54 return false;
55 }
56 break;
57
58 case Cogs::hash("prefix"):
59 if (channelMemberJson.value.IsString() && channelMemberJson.value.GetStringLength() != 0) {
60 channel.prefix = channelMemberJson.value.GetString();
61 if (Cogs::IO::isRelative(channel.prefix)) {
62 channel.prefix = Cogs::IO::combine(config.rootPath, channel.prefix);
63 }
64 }
65 else {
66 LOG_ERROR(logger, "json: channel item member 'prefix' is not a nonempty string");
67 return false;
68 }
69 break;
70
71 case Cogs::hash("scale"):
72 if (channelMemberJson.value.IsFloat()) {
73 channel.scale = channelMemberJson.value.GetFloat();
74 }
75 else {
76 LOG_ERROR(logger, "json: channel item member 'scale' is not a float");
77 return false;
78 }
79 break;
80
81 case Cogs::hash("bias"):
82 if (channelMemberJson.value.IsFloat()) {
83 channel.bias = channelMemberJson.value.GetFloat();
84 }
85 else {
86 LOG_ERROR(logger, "json: channel item member 'bias' is not a float");
87 return false;
88 }
89 break;
90
91 default:
92 LOG_ERROR(logger, "json: unexpected channel member %.*s", StringViewFormat(channelMemberName));
93 return false;
94 }
95 }
96
97 if (channel.dataType == Config::Channel::DataType::None) {
98 LOG_ERROR(logger, "json: channel missing compulsory member 'dataType");
99 return false;
100 }
101 if (channel.prefix.empty()) {
102 LOG_ERROR(logger, "json: channel missing compulsory member 'prefix");
103 return false;
104 }
105
106 config.channels.emplace_back(std::move(channel));
107 return true;
108 }
109
110}
111
112bool Cogs::Core::Image360::Config::parseConfigJson(Cogs::FileContents* contents)
113{
114
115 Document doc = parseJson(Cogs::StringView((const char*)contents->ptr, contents->size), JsonParseFlags::None);
116 if (doc.HasParseError()) {
117 LOG_ERROR(logger, "json: malformed document");
118 return false;
119 }
120
121 if (!doc.IsObject()) {
122 LOG_ERROR(logger, "json: document root is not an object");
123 return false;
124 }
125
126 rootPath = IO::parentPath(contents->origin());
127
128 for (const auto& rootMemberJson : doc.GetObject()) {
129 const Cogs::StringView rootMemberName = toView(rootMemberJson.name);
130 switch (rootMemberName.hash()) {
131 case Cogs::hash("baseSize"):
132 if (rootMemberJson.value.IsUint() && rootMemberJson.value.GetUint() != 0) {
133 baseSize = rootMemberJson.value.GetUint();
134 }
135 else {
136 LOG_ERROR(logger, "json: root member 'baseSize' not a nonzero uint");
137 return false;
138 }
139 break;
140 case Cogs::hash("treeDepth"):
141 if (rootMemberJson.value.IsUint() && rootMemberJson.value.GetUint() != 0) {
142 treeDepth = rootMemberJson.value.GetUint();
143 }
144 else {
145 LOG_ERROR(logger, "json: root member 'treeDepth' not a nonzero uint");
146 return false;
147 }
148 break;
149 case Cogs::hash("extent"):
150 if (rootMemberJson.value.IsFloat() && 0.f < rootMemberJson.value.GetFloat()) {
151 extent = rootMemberJson.value.GetFloat();
152 }
153 else {
154 LOG_ERROR(logger, "json: root member 'extent' not a positive float");
155 return false;
156 }
157 break;
158 case Cogs::hash("depthChannel"):
159 if (rootMemberJson.value.IsUint() && rootMemberJson.value.GetUint() < 256) {
160 depthChannel = uint8_t(rootMemberJson.value.GetUint());
161 }
162 else {
163 LOG_ERROR(logger, "json: root member 'depthChannel' not a byte-valued uint");
164 return false;
165 }
166 break;
167 case Cogs::hash("noDataDepth"):
168 if (rootMemberJson.value.IsUint()) {
169 noDataDepth = rootMemberJson.value.GetUint();
170 }
171 else {
172 LOG_ERROR(logger, "json: root member 'noDataDepth' not an uint");
173 return false;
174 }
175 break;
176 case Cogs::hash("discardNoDepth"):
177 if (rootMemberJson.value.IsBool()) {
178 discardNoDepth = rootMemberJson.value.GetBool();
179 }
180 else {
181 LOG_ERROR(logger, "json: root member 'discardNoDepth' not a bool");
182 return false;
183 }
184 break;
185 case Cogs::hash("channels"):
186 if (rootMemberJson.value.IsArray()) {
187 for (const auto& channelJson : rootMemberJson.value.GetArray()) {
188 if (!parseJsonChannel(*this, channelJson)) return false;
189 }
190 }
191 else {
192 LOG_ERROR(logger, "json: root member 'channels' not an array");
193 return false;
194 }
195 break;
196 default:
197 LOG_ERROR(logger, "json: unexpected root member %.*s", StringViewFormat(rootMemberName));
198 return false;
199 }
200 }
201
202 if (baseSize == 0) {
203 LOG_ERROR(logger, "json: root missing compulsory member 'baseSize");
204 return false;
205 }
206 if (treeDepth == 0) {
207 LOG_ERROR(logger, "json: root missing compulsory member 'treeDepth");
208 return false;
209 }
210 if (channels.empty()) {
211 LOG_ERROR(logger, "json: root missing compulsory member 'channels");
212 return false;
213 }
214
215 return true;
216}
Log implementation class.
Definition: LogManager.h:139
Provides a weakly referenced view over the contents of a string.
Definition: StringView.h:24
constexpr size_t hash() const noexcept
Get the hash code of the string.
Definition: StringView.h:200
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:180
constexpr size_t hash() noexcept
Simple getter function that returns the initial value for fnv1a hashing.
Definition: HashFunctions.h:62
std::vector< Channel > channels
Data channels to use. From json.
Definition: Image360.h:51
Abstract base class storing data read from a file.
Definition: FileContents.h:20
size_t size
Number of data bytes.
Definition: FileContents.h:29
const uint8_t * ptr
Start of buffer storing file data. Use.
Definition: FileContents.h:27