mirror of
https://github.com/Telecominfraproject/wlan-cloud-lib-valijson.git
synced 2026-01-27 02:22:38 +00:00
This patch adds support for a new Cmake option, VALIJSON_USE_EXCEPTIONS. If specified and set to `0`, Valijson will disable all exception throwing, add the `-fno-exceptions` compiler flag, and print to std::err and abort where exceptions would have been thrown. NOTE: to set the value of a CMake option, the easiest way is to modify the appropriate source line in the <build folder>/CMakeCache.txt file. Bug: #106
225 lines
6.0 KiB
C++
225 lines
6.0 KiB
C++
#pragma once
|
|
|
|
#include <cstdio>
|
|
#include <set>
|
|
|
|
#include <valijson/subschema.hpp>
|
|
#include <valijson/exceptions.hpp>
|
|
|
|
namespace valijson {
|
|
|
|
/**
|
|
* Represents the root of a JSON Schema
|
|
*
|
|
* The root is distinct from other sub-schemas because it is the canonical
|
|
* starting point for validation of a document against a given a JSON Schema.
|
|
*/
|
|
class Schema: public Subschema
|
|
{
|
|
public:
|
|
/**
|
|
* @brief Construct a new Schema instance with no constraints
|
|
*/
|
|
Schema()
|
|
: sharedEmptySubschema(newSubschema()) { }
|
|
|
|
/**
|
|
* @brief Construct a new Schema using custom memory management
|
|
* functions
|
|
*
|
|
* @param allocFn malloc- or new-like function to allocate memory
|
|
* within Schema, such as for Subschema instances
|
|
* @param freeFn free-like function to free memory allocated with
|
|
* the `customAlloc` function
|
|
*/
|
|
Schema(CustomAlloc allocFn, CustomFree freeFn)
|
|
: Subschema(allocFn, freeFn),
|
|
sharedEmptySubschema(newSubschema()) { }
|
|
|
|
// Disable copy construction
|
|
Schema(const Schema &) = delete;
|
|
|
|
// Disable copy assignment
|
|
Schema & operator=(const Schema &) = delete;
|
|
|
|
/**
|
|
* @brief Clean up and free all memory managed by the Schema
|
|
*
|
|
* Note that any Subschema pointers created and returned by this Schema
|
|
* should be considered invalid.
|
|
*/
|
|
~Schema() override
|
|
{
|
|
sharedEmptySubschema->~Subschema();
|
|
m_freeFn(const_cast<Subschema *>(sharedEmptySubschema));
|
|
sharedEmptySubschema = nullptr;
|
|
|
|
#if VALIJSON_USE_EXCEPTIONS
|
|
try {
|
|
#endif
|
|
for (auto subschema : subschemaSet) {
|
|
subschema->~Subschema();
|
|
m_freeFn(subschema);
|
|
}
|
|
#if VALIJSON_USE_EXCEPTIONS
|
|
} catch (const std::exception &e) {
|
|
fprintf(stderr, "Caught an exception while destroying Schema: %s",
|
|
e.what());
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Copy a constraint to a specific sub-schema
|
|
*
|
|
* @param constraint reference to a constraint that will be copied into
|
|
* the sub-schema
|
|
* @param subschema pointer to the sub-schema that will own the copied
|
|
* constraint
|
|
*
|
|
* @throws std::runtime_error if the sub-schema is not owned by this Schema
|
|
* instance
|
|
*/
|
|
void addConstraintToSubschema(const Constraint &constraint,
|
|
const Subschema *subschema)
|
|
{
|
|
// TODO: Check heirarchy for subschemas that do not belong...
|
|
|
|
mutableSubschema(subschema)->addConstraint(constraint);
|
|
}
|
|
|
|
/**
|
|
* @brief Create a new Subschema instance that is owned by this Schema
|
|
*
|
|
* @returns const pointer to the new Subschema instance
|
|
*/
|
|
const Subschema * createSubschema()
|
|
{
|
|
Subschema *subschema = newSubschema();
|
|
|
|
#if VALIJSON_USE_EXCEPTIONS
|
|
try {
|
|
#endif
|
|
if (!subschemaSet.insert(subschema).second) {
|
|
throwRuntimeError(
|
|
"Failed to store pointer for new sub-schema");
|
|
}
|
|
#if VALIJSON_USE_EXCEPTIONS
|
|
} catch (...) {
|
|
subschema->~Subschema();
|
|
m_freeFn(subschema);
|
|
throw;
|
|
}
|
|
#endif
|
|
return subschema;
|
|
}
|
|
|
|
/**
|
|
* @brief Return a pointer to the shared empty schema
|
|
*/
|
|
const Subschema * emptySubschema() const
|
|
{
|
|
return sharedEmptySubschema;
|
|
}
|
|
|
|
/**
|
|
* @brief Get a pointer to the root sub-schema of this Schema instance
|
|
*/
|
|
const Subschema * root() const
|
|
{
|
|
return this;
|
|
}
|
|
|
|
void setAlwaysInvalid(const Subschema *subschema, bool value)
|
|
{
|
|
mutableSubschema(subschema)->setAlwaysInvalid(value);
|
|
}
|
|
|
|
/**
|
|
* @brief Update the description for one of the sub-schemas owned by this
|
|
* Schema instance
|
|
*
|
|
* @param subschema sub-schema to update
|
|
* @param description new description
|
|
*/
|
|
void setSubschemaDescription(const Subschema *subschema,
|
|
const std::string &description)
|
|
{
|
|
mutableSubschema(subschema)->setDescription(description);
|
|
}
|
|
|
|
/**
|
|
* @brief Update the ID for one of the sub-schemas owned by this Schema
|
|
* instance
|
|
*
|
|
* @param subschema sub-schema to update
|
|
* @param id new ID
|
|
*/
|
|
void setSubschemaId(const Subschema *subschema, const std::string &id)
|
|
{
|
|
mutableSubschema(subschema)->setId(id);
|
|
}
|
|
|
|
/**
|
|
* @brief Update the title for one of the sub-schemas owned by this Schema
|
|
* instance
|
|
*
|
|
* @param subschema sub-schema to update
|
|
* @param title new title
|
|
*/
|
|
void setSubschemaTitle(const Subschema *subschema, const std::string &title)
|
|
{
|
|
mutableSubschema(subschema)->setTitle(title);
|
|
}
|
|
|
|
private:
|
|
|
|
Subschema *newSubschema()
|
|
{
|
|
void *ptr = m_allocFn(sizeof(Subschema));
|
|
if (!ptr) {
|
|
throwRuntimeError(
|
|
"Failed to allocate memory for shared empty sub-schema");
|
|
}
|
|
|
|
#if VALIJSON_USE_EXCEPTIONS
|
|
try {
|
|
#endif
|
|
return new (ptr) Subschema();
|
|
#if VALIJSON_USE_EXCEPTIONS
|
|
} catch (...) {
|
|
m_freeFn(ptr);
|
|
throw;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
Subschema * mutableSubschema(const Subschema *subschema)
|
|
{
|
|
if (subschema == this) {
|
|
return this;
|
|
}
|
|
|
|
if (subschema == sharedEmptySubschema) {
|
|
throwRuntimeError(
|
|
"Cannot modify the shared empty sub-schema");
|
|
}
|
|
|
|
auto *noConst = const_cast<Subschema*>(subschema);
|
|
if (subschemaSet.find(noConst) == subschemaSet.end()) {
|
|
throwRuntimeError(
|
|
"Subschema pointer is not owned by this Schema instance");
|
|
}
|
|
|
|
return noConst;
|
|
}
|
|
|
|
/// Set of Subschema instances owned by this schema
|
|
std::set<Subschema*> subschemaSet;
|
|
|
|
/// Empty schema that can be reused by multiple constraints
|
|
const Subschema *sharedEmptySubschema;
|
|
};
|
|
|
|
} // namespace valijson
|