45namespace Steinberg::ModuleInfoLib {
51 errorOut <<
"error : "
52 << JSON::errorToString (
static_cast<json_parse_error_e
> (parseResult.error)) <<
'\n';
53 errorOut <<
"offset : " << parseResult.error_offset <<
'\n';
54 errorOut <<
"line no: " << parseResult.error_line_no <<
'\n';
55 errorOut <<
"row no : " << parseResult.error_row_no <<
'\n';
62 : str (str), location (value.getSourceLocation ())
64 addLocation (location);
67 : str (str), location (value.getSourceLocation ())
69 addLocation (location);
71 const char* what () const noexcept
override {
return str.data (); }
93struct ModuleInfoJsonParser
95 ModuleInfoJsonParser () =
default;
99 if (
auto str = value.asString ())
101 throw parse_error (
"Expect a String here", value);
104 template <
typename T>
107 if (
auto number = value.asNumber ())
109 if (
auto result = number->getInteger ())
113 throw parse_error (
"Value is out of range here", value);
114 return static_cast<T
> (*result);
116 throw parse_error (
"Expect an Integer here", value);
118 throw parse_error (
"Expect a Number here", value);
123 if (
auto number = value.asNumber ())
125 if (
auto result = number->getDouble ())
127 throw parse_error (
"Expect a Double here", value);
129 throw parse_error (
"Expect a Number here", value);
142 if (
auto obj = value.asObject ())
144 for (
const auto& el : *obj)
146 auto elementName = el.name ().text ();
147 if (elementName ==
"Vendor")
149 if (parsed & ParsedBits::Vendor)
150 throw parse_error (
"Only one 'Vendor' key allowed", el.name ());
151 parsed |= ParsedBits::Vendor;
152 info.factoryInfo.vendor = getText (el.value ());
154 else if (elementName ==
"URL")
156 if (parsed & ParsedBits::URL)
157 throw parse_error (
"Only one 'URL' key allowed", el.name ());
158 parsed |= ParsedBits::URL;
159 info.factoryInfo.url = getText (el.value ());
161 else if (elementName ==
"E-Mail")
163 if (parsed & ParsedBits::EMail)
164 throw parse_error (
"Only one 'E-Mail' key allowed", el.name ());
165 parsed |= ParsedBits::EMail;
166 info.factoryInfo.email = getText (el.value ());
168 else if (elementName ==
"Flags")
170 if (parsed & ParsedBits::Flags)
171 throw parse_error (
"Only one 'Flags' key allowed", el.name ());
172 auto flags = el.value ().asObject ();
174 throw parse_error (
"Expect 'Flags' to be a JSON Object", el.name ());
175 for (
const auto& flag : *flags)
177 auto flagName = flag.name ().text ();
178 auto flagValue = flag.value ().asBoolean ();
180 throw parse_error (
"Flag must be a boolean", flag.value ());
181 if (flagName ==
"Classes Discardable")
186 else if (flagName ==
"Component Non Discardable")
191 else if (flagName ==
"Unicode")
197 throw parse_error (
"Unknown flag", flag.name ());
199 parsed |= ParsedBits::Flags;
203 if (!(parsed & ParsedBits::Vendor))
205 if (!(parsed & ParsedBits::URL))
207 if (!(parsed & ParsedBits::EMail))
209 if (!(parsed & ParsedBits::Flags))
223 SubCategories = 1 << 6,
226 Cardinality = 1 << 9,
229 auto array = value.asArray ();
231 throw parse_error (
"Expect Classes Array", value);
232 for (
const auto& classInfoEl : *array)
234 auto classInfo = classInfoEl.value ().asObject ();
236 throw parse_error (
"Expect Class Object", classInfoEl.value ());
238 ModuleInfo::ClassInfo ci {};
242 for (
const auto& el : *classInfo)
244 auto elementName = el.name ().text ();
245 if (elementName ==
"CID")
247 if (parsed & ParsedBits::CID)
248 throw parse_error (
"Only one 'CID' key allowed", el.name ());
249 ci.cid = getText (el.value ());
250 parsed |= ParsedBits::CID;
252 else if (elementName ==
"Category")
254 if (parsed & ParsedBits::Category)
255 throw parse_error (
"Only one 'Category' key allowed", el.name ());
256 ci.category = getText (el.value ());
257 parsed |= ParsedBits::Category;
259 else if (elementName ==
"Name")
261 if (parsed & ParsedBits::Name)
262 throw parse_error (
"Only one 'Name' key allowed", el.name ());
263 ci.name = getText (el.value ());
264 parsed |= ParsedBits::Name;
266 else if (elementName ==
"Vendor")
268 if (parsed & ParsedBits::Vendor)
269 throw parse_error (
"Only one 'Vendor' key allowed", el.name ());
270 ci.vendor = getText (el.value ());
271 parsed |= ParsedBits::Vendor;
273 else if (elementName ==
"Version")
275 if (parsed & ParsedBits::Version)
276 throw parse_error (
"Only one 'Version' key allowed", el.name ());
277 ci.version = getText (el.value ());
278 parsed |= ParsedBits::Version;
280 else if (elementName ==
"SDKVersion")
282 if (parsed & ParsedBits::SDKVersion)
283 throw parse_error (
"Only one 'SDKVersion' key allowed", el.name ());
284 ci.sdkVersion = getText (el.value ());
285 parsed |= ParsedBits::SDKVersion;
287 else if (elementName ==
"Sub Categories")
289 if (parsed & ParsedBits::SubCategories)
290 throw parse_error (
"Only one 'Sub Categories' key allowed", el.name ());
291 auto subCatArr = el.value ().asArray ();
293 throw parse_error (
"Expect Array here", el.value ());
294 for (
const auto& catEl : *subCatArr)
296 auto cat = getText (catEl.value ());
297 ci.subCategories.emplace_back (cat);
299 parsed |= ParsedBits::SubCategories;
301 else if (elementName ==
"Class Flags")
303 if (parsed & ParsedBits::ClassFlags)
304 throw parse_error (
"Only one 'Class Flags' key allowed", el.name ());
305 ci.flags = getInteger<uint32_t> (el.value ());
306 parsed |= ParsedBits::ClassFlags;
308 else if (elementName ==
"Cardinality")
310 if (parsed & ParsedBits::Cardinality)
311 throw parse_error (
"Only one 'Cardinality' key allowed", el.name ());
312 ci.cardinality = getInteger<int32_t> (el.value ());
313 parsed |= ParsedBits::Cardinality;
315 else if (elementName ==
"Snapshots")
317 if (parsed & ParsedBits::Snapshots)
318 throw parse_error (
"Only one 'Snapshots' key allowed", el.name ());
319 auto snapArr = el.value ().asArray ();
321 throw parse_error (
"Expect Array here", el.value ());
322 for (
const auto& snapEl : *snapArr)
324 auto snap = snapEl.value ().asObject ();
326 throw parse_error (
"Expect Object here", snapEl.value ());
327 ModuleInfo::Snapshot snapshot;
328 for (
const auto& spEl : *snap)
330 auto spElName = spEl.name ().text ();
331 if (spElName ==
"Path")
332 snapshot.path = getText (spEl.value ());
333 else if (spElName ==
"Scale Factor")
334 snapshot.scaleFactor = getDouble (spEl.value ());
336 throw parse_error (
"Unexpected key", spEl.name ());
338 if (snapshot.scaleFactor == 0. || snapshot.path.empty ())
339 throw parse_error (
"Missing Snapshot keys", snapEl.value ());
340 ci.snapshots.emplace_back (std::move (snapshot));
342 parsed |= ParsedBits::Snapshots;
345 throw parse_error (
"Unexpected key", el.name ());
347 if (!(parsed & ParsedBits::CID))
348 throw parse_error (
"'CID' key missing", classInfoEl.value ());
349 if (!(parsed & ParsedBits::Category))
350 throw parse_error (
"'Category' key missing", classInfoEl.value ());
351 if (!(parsed & ParsedBits::Name))
352 throw parse_error (
"'Name' key missing", classInfoEl.value ());
353 if (!(parsed & ParsedBits::Vendor))
354 throw parse_error (
"'Vendor' key missing", classInfoEl.value ());
355 if (!(parsed & ParsedBits::Version))
356 throw parse_error (
"'Version' key missing", classInfoEl.value ());
357 if (!(parsed & ParsedBits::SDKVersion))
358 throw parse_error (
"'SDK Version' key missing", classInfoEl.value ());
359 if (!(parsed & ParsedBits::ClassFlags))
360 throw parse_error (
"'Class Flags' key missing", classInfoEl.value ());
361 if (!(parsed & ParsedBits::Cardinality))
362 throw parse_error (
"'Cardinality' key missing", classInfoEl.value ());
363 info.classes.emplace_back (std::move (ci));
369 auto arr = value.asArray ();
371 throw parse_error (
"Expect Array here", value);
372 for (
const auto& el : *arr)
374 auto obj = el.value ().asObject ();
376 throw parse_error (
"Expect Object here", el.value ());
378 ModuleInfo::Compatibility compat;
379 for (
const auto& objEl : *obj)
381 auto elementName = objEl.name ().text ();
382 if (elementName ==
"New")
383 compat.newCID = getText (objEl.value ());
384 else if (elementName ==
"Old")
386 auto oldElArr = objEl.value ().asArray ();
388 throw parse_error (
"Expect Array here", objEl.value ());
389 for (
const auto& old : *oldElArr)
391 compat.oldCID.emplace_back (getText (old.value ()));
395 if (compat.newCID.empty ())
396 throw parse_error (
"Expect New CID here", el.value ());
397 if (compat.oldCID.empty ())
398 throw parse_error (
"Expect Old CID here", el.value ());
399 info.compatibility.emplace_back (std::move (compat));
405 auto docObj = doc.asObject ();
407 throw parse_error (
"Unexpected", doc);
413 FactoryInfo = 1 << 2,
414 Compatibility = 1 << 3,
419 for (
const auto& el : *docObj)
421 auto elementName = el.name ().text ();
422 if (elementName ==
"Name")
424 if (parsed & ParsedBits::Name)
425 throw parse_error (
"Only one 'Name' key allowed", el.name ());
426 parsed |= ParsedBits::Name;
427 info.name = getText (el.value ());
429 else if (elementName ==
"Version")
431 if (parsed & ParsedBits::Version)
432 throw parse_error (
"Only one 'Version' key allowed", el.name ());
433 parsed |= ParsedBits::Version;
434 info.version = getText (el.value ());
436 else if (elementName ==
"Factory Info")
438 if (parsed & ParsedBits::FactoryInfo)
439 throw parse_error (
"Only one 'Factory Info' key allowed", el.name ());
440 parseFactoryInfo (el.value ());
441 parsed |= ParsedBits::FactoryInfo;
443 else if (elementName ==
"Compatibility")
445 if (parsed & ParsedBits::Compatibility)
446 throw parse_error (
"Only one 'Compatibility' key allowed", el.name ());
447 parseCompatibility (el.value ());
448 parsed |= ParsedBits::Compatibility;
450 else if (elementName ==
"Classes")
452 if (parsed & ParsedBits::Classes)
453 throw parse_error (
"Only one 'Classes' key allowed", el.name ());
454 parseClasses (el.value ());
455 parsed |= ParsedBits::Classes;
459 throw parse_error (
"Unexpected JSON Token", el.name ());
462 if (!(parsed & ParsedBits::Name))
464 if (!(parsed & ParsedBits::Version))
466 if (!(parsed & ParsedBits::FactoryInfo))
468 if (!(parsed & ParsedBits::Classes))
472 ModuleInfo&& takeInfo () {
return std::move (info); }
484 auto docVar = JSON::Document::parse (jsonData);
485 if (
auto res = std::get_if<json_parse_result_s> (&docVar))
488 printJsonParseError (*res, *optErrorOutput);
491 auto doc = std::get_if<JSON::Document> (&docVar);
495 ModuleInfoJsonParser parser;
497 return parser.takeInfo ();
502 *optErrorOutput << error.
what () <<
'\n';
512 auto docVar = JSON::Document::parse (jsonData);
513 if (
auto res = std::get_if<json_parse_result_s> (&docVar))
516 printJsonParseError (*res, *optErrorOutput);
519 auto doc = std::get_if<JSON::Document> (&docVar);
523 ModuleInfoJsonParser parser;
524 parser.parseCompatibility (*doc);
525 return parser.takeInfo ().compatibility;
530 *optErrorOutput << error.
what () <<
'\n';
std::optional< ModuleInfo::CompatibilityList > parseCompatibilityJson(std::string_view jsonData, std::ostream *optErrorOutput)
parse a json formatted string to a ModuleInfo::CompatibilityList
std::optional< ModuleInfo > parseJson(std::string_view jsonData, std::ostream *optErrorOutput)
parse a json formatted string to a ModuleInfo struct
@ kUnicode
Components have entirely unicode encoded strings (True for VST 3 plug-ins so far).
@ kComponentNonDiscardable
Component will not be unloaded until process exit.
@ kClassesDiscardable
The number of exported classes can change each time the Module is loaded.