|
@@ -80,78 +80,19 @@ namespace InvercargillJson {
|
|
|
|
|
|
|
|
node = new Json.Node (Json.NodeType.VALUE);
|
|
node = new Json.Node (Json.NodeType.VALUE);
|
|
|
|
|
|
|
|
- // For ValueElement scalars, read the underlying GValue directly instead
|
|
|
|
|
- // of going through element.as<T?>(). The generic extraction path is the
|
|
|
|
|
- // authoritative source of the held type but is unsafe for 64-bit
|
|
|
|
|
- // integers (it returns a corrupt value that crashes Json.Node.set_int)
|
|
|
|
|
- // and the dispatch below has no branches for long/ulong (so they fall
|
|
|
|
|
- // through to the string fallback and serialise as quoted JSON strings).
|
|
|
|
|
- // Reading the raw GValue lets us dispatch on the fundamental type and
|
|
|
|
|
- // use the matching g_value_get_* accessor for every numeric type.
|
|
|
|
|
- // Fixes upstream issues I-1 (int64/uint64 segfault), I-2 (bool) and
|
|
|
|
|
- // I-3 (numeric serialised as string).
|
|
|
|
|
|
|
+ // For ValueElement scalars, read the underlying GValue directly
|
|
|
|
|
+ // through a dedicated helper instead of inlining every branch
|
|
|
|
|
+ // here: the fully inlined version produced a single ~13KB
|
|
|
|
|
+ // function whose optimised stack-slot reuse read a stale cached
|
|
|
|
|
+ // GValue pointer on some layouts (deterministic SIGSEGV in the
|
|
|
|
|
+ // double/int64 paths during Statum slot signing). Keeping the
|
|
|
|
|
+ // scalar dispatch out of line sidesteps that codegen bug.
|
|
|
if (element is Invercargill.ValueElement) {
|
|
if (element is Invercargill.ValueElement) {
|
|
|
- var raw = ((Invercargill.ValueElement) element).get_value();
|
|
|
|
|
- var value_type = raw.type();
|
|
|
|
|
- if (value_type.is_a(Type.STRING)) {
|
|
|
|
|
- node.set_string(raw.get_string());
|
|
|
|
|
|
|
+ if (set_node_from_value(node, ((Invercargill.ValueElement) element).get_value())) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- if (value_type.is_a(Type.BOOLEAN)) {
|
|
|
|
|
- node.set_boolean(raw.get_boolean());
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- if (value_type.is_a(Type.DOUBLE)) {
|
|
|
|
|
- node.set_double(raw.get_double());
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- if (value_type.is_a(Type.FLOAT)) {
|
|
|
|
|
- node.set_double((double)raw.get_float());
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- // Every integer fundamental collapses to JSON's single int node.
|
|
|
|
|
- if (value_type.is_a(Type.INT64)) {
|
|
|
|
|
- node.set_int(raw.get_int64());
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- if (value_type.is_a(Type.UINT64)) {
|
|
|
|
|
- node.set_int((int64)raw.get_uint64());
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- if (value_type.is_a(Type.LONG)) {
|
|
|
|
|
- node.set_int((int64)raw.get_long());
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- if (value_type.is_a(Type.ULONG)) {
|
|
|
|
|
- node.set_int((int64)raw.get_ulong());
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- if (value_type.is_a(Type.INT)) {
|
|
|
|
|
- node.set_int((int64)raw.get_int());
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- if (value_type.is_a(Type.UINT)) {
|
|
|
|
|
- node.set_int((int64)raw.get_uint());
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- if (value_type.is_a(Type.CHAR)) {
|
|
|
|
|
- node.set_int((int64)raw.get_schar());
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- if (value_type.is_a(Type.UCHAR)) {
|
|
|
|
|
- node.set_int((int64)raw.get_uchar());
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- if (value_type.is_a(Type.ENUM)) {
|
|
|
|
|
- node.set_int((int64)raw.get_enum());
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- if (value_type.is_a(Type.FLAGS)) {
|
|
|
|
|
- node.set_int((int64)raw.get_flags());
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- // Non-fundamental held types (DateTime, BinaryData, objects, ...)
|
|
|
|
|
- // fall through to the dispatch below.
|
|
|
|
|
|
|
+ // Non-fundamental held types (DateTime, BinaryData, objects,
|
|
|
|
|
+ // ...) fall through to the dispatch below.
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
var type = element.type();
|
|
var type = element.type();
|
|
@@ -236,6 +177,74 @@ namespace InvercargillJson {
|
|
|
throw new Invercargill.ElementError.INVALID_CONVERSION(@"No way to convert element $(element.get_type ().name()) containing type $(type.name()) to a type suitable for a JsonElement.");
|
|
throw new Invercargill.ElementError.INVALID_CONVERSION(@"No way to convert element $(element.get_type ().name()) containing type $(type.name()) to a type suitable for a JsonElement.");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Fills `node` from a ValueElement's raw GValue when it holds a
|
|
|
|
|
+ * fundamental JSON-representable type, and returns true; false when
|
|
|
|
|
+ * the held type is non-fundamental (DateTime, objects, ...) and the
|
|
|
|
|
+ * caller must fall through to the generic dispatch.
|
|
|
|
|
+ */
|
|
|
|
|
+ private static bool set_node_from_value(Json.Node node, Value raw) {
|
|
|
|
|
+ var value_type = raw.type();
|
|
|
|
|
+ if (value_type.is_a(Type.STRING)) {
|
|
|
|
|
+ node.set_string(raw.get_string());
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (value_type.is_a(Type.BOOLEAN)) {
|
|
|
|
|
+ node.set_boolean(raw.get_boolean());
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (value_type.is_a(Type.DOUBLE)) {
|
|
|
|
|
+ node.set_double(raw.get_double());
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (value_type.is_a(Type.FLOAT)) {
|
|
|
|
|
+ node.set_double((double)raw.get_float());
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ // Every integer fundamental collapses to JSON's single int node.
|
|
|
|
|
+ if (value_type.is_a(Type.INT64)) {
|
|
|
|
|
+ node.set_int(raw.get_int64());
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (value_type.is_a(Type.UINT64)) {
|
|
|
|
|
+ node.set_int((int64)raw.get_uint64());
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (value_type.is_a(Type.LONG)) {
|
|
|
|
|
+ node.set_int((int64)raw.get_long());
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (value_type.is_a(Type.ULONG)) {
|
|
|
|
|
+ node.set_int((int64)raw.get_ulong());
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (value_type.is_a(Type.INT)) {
|
|
|
|
|
+ node.set_int((int64)raw.get_int());
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (value_type.is_a(Type.UINT)) {
|
|
|
|
|
+ node.set_int((int64)raw.get_uint());
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (value_type.is_a(Type.CHAR)) {
|
|
|
|
|
+ node.set_int((int64)raw.get_schar());
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (value_type.is_a(Type.UCHAR)) {
|
|
|
|
|
+ node.set_int((int64)raw.get_uchar());
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (value_type.is_a(Type.ENUM)) {
|
|
|
|
|
+ node.set_int((int64)raw.get_enum());
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (value_type.is_a(Type.FLAGS)) {
|
|
|
|
|
+ node.set_int((int64)raw.get_flags());
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
public bool assignable_to_type (GLib.Type type) {
|
|
public bool assignable_to_type (GLib.Type type) {
|
|
|
if(node.is_null() || type == typeof(Json.Node)) {
|
|
if(node.is_null() || type == typeof(Json.Node)) {
|
|
|
return true;
|
|
return true;
|