Add `bt2c::ValReq` class template system
This set of class templates makes it possible to get basic requirement
classes to validate JSON-like value objects, that is, a system of null,
boolean, unsigned/signed integer, real, string, array, and object value
objects.
All the class templates accept a `ValT` parameter which is the base type
of the objects to validate, as well as `ValOpsT`, a structure which
defines specific value operations. See the `bt2c::ValReq` class template
comment to learn the requirements of `ValOpsT`.
Having class templates will make it possible to create both:
• JSON value requirements, to validate a CTF2‑SPEC‑2.0 [1] metadata
stream within the `ctf` plugin.
• libbabeltrace2 value object (`bt2::ConstValue`) requirements, to
validate component initialization parameters, for example.
A value requirement (`bt2c::ValReq` instance; omitting the namespace for
the rest of this message) is an object which offers the validate()
method to validate some value object.
The current concrete requirement class templates are (validating some
value V):
`ValHasTypeReq`:
`AnyIntValReq`:
`UIntValReq`:
Validates the type of V.
`SIntValReq`:
Validates the type of V (unsigned or signed integer) and that the
raw value of V is between -9,223,372,036,854,775,808 and
9,223,372,036,854,775,807.
`IntValInRangeReq`:
Validates the type of V and that the raw value of the integer value
object V is within a given range.
`ScalarValInSetReq`:
Validates the type of V and that the raw value of the scalar value
object V is an element of a given set.
`ArrayValReq`:
Validates the type of V, that the size of V is within a given range,
and, optionally, that all the elements of V satisfy a given value
requirement.
`ObjValReq`:
Validates the type of V and that the properties of V satisfy a given
set of property requirements (no missing mandatory property, no
unknown property if not allowed, valid property value).
ValReq::validate() throws `TextParseError` using the text location
of the value (provided by `ValOpsT`) to validate when it fails.
`ArrayValReq` and `ObjValReq` accept zero or more shared value
requirements: a user of this API may extend `ValReq` to create a custom
value requirement (just implement the virtual _validate() method). A
custom value requirement may reuse existing value requirements
internally.
Each value requirement class C has its static shared() method which
accepts the same parameters as the constructor(s) of C and returns a
`ValReq::SP` instance. Those shared() methods are helpers to make the
usage site clearer, for example (assuming some custom aliases for
specific value object types):
MyUIntValInRangeReq::shared(0, 255)
// vs.
std::make_shared<MyUIntValInRangeReq>(0, 255)
Of course this system is not meant to semantically validate some value.
Even JSON Schema [2], which barectf pushes to its limit for example [3],
cannot do that. But those value requirement classes can certainly remove
a lot of redundant code.
Here are a few examples of value requirement object construction and
corresponding error messages to grasp how to use this API (assume some
custom aliases starting with `Json`):
Simple type check:
Code:
JsonValHasTypeReq {ValType::Str}
Error example:
[1:1] Expecting a string.
Exactly `true`:
Code:
JsonBoolValInSetReq {true}
Error examples:
[1:1] Expecting a boolean.
[1:1] Unexpected value `false`: expecting `true`.
Byte:
Code:
JsonUIntValInRangeReq {0, 255}
Error examples:
[1:1] Expecting an unsigned integer.
[1:1] Integer 256 is too large: expecting at most 255.
Display base:
Code:
JsonUIntValInSetReq {{2, 8, 10, 16}}
Error examples:
[1:1] Expecting an unsigned integer.
[1:1] Unexpected value 5: expecting 2, 8, 10, or 16.
Choice amongst three strings:
Code:
JsonStrValInSetReq {JsonStrValInSetReq::Set {
"Patrick", "Alec", "Annie"
}}
Error examples:
[1:1] Expecting a string.
[1:1] Unexpected value `Yves`: expecting `Alec`, `Annie`, or
`Patrick`.
CTF 2 UUID:
Code:
JsonArrayValReq {
16,
JsonUIntValInRangeReq::shared(0, 255)
}
Error examples:
[1:1] Expecting an array.
[1:1] Size of array (2) is too small: expecting at least 16
elements.
[1:1] Size of array (19) is too large: expecting at most 16
elements.
[1:36] In array element #11:
[1:36] Expecting an unsigned integer.
[1:42] In array element #13:
[1:42] Integer 257 is too large: expecting at most 255.
CTF2-SPECRC-5.0 field location:
Code:
JsonArrayValReq {
2, nonstd::nullopt,
JsonValHasTypeReq::shared(ValType::Str)
}
Error examples:
[1:1] Expecting an array.
[1:1] Size of array (1) is too small: expecting at least 2
elements.
[1:11] In array element #2:
[1:11] Expecting a string.
CTF2-SPECRC-5.0 clock class fragment:
Code:
JsonObjValReq {
{
{"type", {
JsonStrValInSetReq::shared("clock-class"),
true
}},
{"frequency", {
JsonUIntValInRangeReq::shared(1, nonstd::nullopt),
true
}},
{"name", {
JsonValHasTypeReq::shared(ValType::Str)
}},
{"description", {
JsonValHasTypeReq::shared(ValType::Str)
}},
{"uuid", {
JsonArrayValReq::shared(
16,
JsonUIntValInRangeReq::shared(0, 255)
)
}},
{"origin-is-unix-epoch", {
JsonValHasTypeReq::shared(ValType::Bool)
}},
{"offset", {
JsonObjValReq::shared({
{"seconds", {
JsonValHasTypeReq::shared(ValType::UInt)
}},
{"cycles", {
JsonValHasTypeReq::shared(ValType::UInt)
}},
})
}},
{"precision", {
JsonValHasTypeReq::shared(ValType::UInt)
}},
{"user-attributes", {
JsonValHasTypeReq::shared(ValType::Obj)
}},
{"extensions", {
JsonValHasTypeReq::shared(ValType::Obj)
}},
}
}
Error examples:
[1:1] Expecting an object.
[1:1] Missing mandatory object property `type`.
[1:1] Missing mandatory object property `frequency`.
[1:22] Unknown object property `meow`.
[1:10] In object property `type`:
[1:10] Unexpected value `salut`: expecting `clock-class`.
[1:38] In object property `frequency`:
[1:32] Expecting an unsigned integer.
[1:54] In object property `offset`:
[1:63] Unknown object property `meow`.
[1:54] In object property `offset`:
[1:66] In object property `seconds`:
[1:66] Expecting an unsigned integer.
[1:50] In object property `uuid`:
[1:63] In array element #5:
[1:63] Integer 301 is too large: expecting at most 255.
[1]: https://diamon.org/ctf/CTF2-SPEC-2.0.html
[2]: https://json-schema.org/
[3]: https://github.com/efficios/barectf/tree/stable-3.0/barectf/schemas/config
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Change-Id: I71630fc51dafb79dd5ece10efbcf86f3f5933199
Reviewed-on: https://review.lttng.org/c/babeltrace/+/8207
Reviewed-on: https://review.lttng.org/c/babeltrace/+/12696
This page took 0.026238 seconds and 4 git commands to generate.