schemagen: accept integral exponent/decimal numbers for integer slots
CI / build (-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++, clang-arm64, ubuntu-latest-arm64, true) (push) Successful in 56s
CI / pre-commit (push) Successful in 59s
CI / build (-DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++, gcc-arm64, ubuntu-latest-arm64, false) (push) Successful in 52s
CI / build (-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++, clang-amd64, ubuntu-latest-amd64, true) (push) Successful in 1m45s
CI / build (-DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++, gcc-amd64, ubuntu-latest-amd64, false) (push) Successful in 1m24s

JSON Schema's 'integer' type matches any number with a zero fractional
part, but the generated builder rejected forms like 1e3 or 2.0 because it
only ran std::from_chars<int64_t>. Keep that exact path for plain integer
literals (so large values near INT64_MAX stay exact), and fall back to
parsing as double for the rest, requiring an integral value within int64
range. Add <cmath> for std::trunc and cover the new cases in test_gen.
This commit is contained in:
2026-06-15 00:57:30 -04:00
parent 4301351042
commit db759a9333
2 changed files with 42 additions and 2 deletions
+16 -2
View File
@@ -487,6 +487,7 @@ class Emitter:
#pragma once
#include <charconv>
#include <cmath>
#include <cstdint>
#include <map>
#include <memory>
@@ -928,8 +929,21 @@ private:
if (si.cat == Cat::Int) {{
int64_t v = 0;
auto r = std::from_chars(b, e, v);
if (r.ec != std::errc() || r.ptr != e) {{ reject(); return; }}
*(int64_t *)p = v;
if (r.ec == std::errc() && r.ptr == e) {{
*(int64_t *)p = v; // plain integer literal: parsed exactly
}} else {{
// JSON Schema "integer" accepts any number with no fractional part,
// including exponent/decimal forms like 1e3 or 2.0. Parse those as a
// double and require an integral value within int64 range.
double d = 0;
auto rd = std::from_chars(b, e, d);
if (rd.ec != std::errc() || rd.ptr != e || d != std::trunc(d) ||
d < -9223372036854775808.0 || d >= 9223372036854775808.0) {{
reject();
return;
}}
*(int64_t *)p = (int64_t)d;
}}
}} else {{
double v = 0;
auto r = std::from_chars(b, e, v);