Fixes#56. The generated parseJsonInt64 in schemagen rejected valid JSON numbers whose mathematical value is 0 but which are written with a negative exponent large enough that trailing/leading-zero trimming does not fully offset it (e.g. 0e-2, 0.0e-2, -0e-2, 0e-20).
Root cause
The if (finalExp < 0) return false; guard ran before the zero-detection branch (if (leadingZeros == digits.size()) { out = 0; return true; }). For a zero value, all significant digits get trimmed away, leaving an all-zero digits, but finalExp can still be negative, so the early return false triggered before the out = 0 branch was reached.
Fix
Reorder the two guards so the zero-detection check runs first. When the remaining digits are all zero, the value is 0 regardless of the exponent, so we accept it and set out = 0. The negative-finalExp rejection then only applies to non-zero values, which are correctly rejected as non-integral (e.g. 1e-2).
Testing
Added regression cases to SchemagenIntegerBoundaryTest covering both root and object-field integer schemas for 0e-1, 0e-2, 0.0e-2, -0e-2, 0e-20, 0.000e-5, and {"age":0e-2} / {"age":-0e-20}. Existing rejection cases (1e-2, 1.5, 0.001) remain rejected. Full schemagen test suite and the CMake/CTest suite pass.
## Summary
Fixes #56. The generated `parseJsonInt64` in schemagen rejected valid JSON numbers whose mathematical value is `0` but which are written with a negative exponent large enough that trailing/leading-zero trimming does not fully offset it (e.g. `0e-2`, `0.0e-2`, `-0e-2`, `0e-20`).
## Root cause
The `if (finalExp < 0) return false;` guard ran *before* the zero-detection branch (`if (leadingZeros == digits.size()) { out = 0; return true; }`). For a zero value, all significant digits get trimmed away, leaving an all-zero `digits`, but `finalExp` can still be negative, so the early `return false` triggered before the `out = 0` branch was reached.
## Fix
Reorder the two guards so the zero-detection check runs first. When the remaining digits are all zero, the value is `0` regardless of the exponent, so we accept it and set `out = 0`. The negative-`finalExp` rejection then only applies to non-zero values, which are correctly rejected as non-integral (e.g. `1e-2`).
## Testing
Added regression cases to `SchemagenIntegerBoundaryTest` covering both root and object-field integer schemas for `0e-1`, `0e-2`, `0.0e-2`, `-0e-2`, `0e-20`, `0.000e-5`, and `{"age":0e-2}` / `{"age":-0e-20}`. Existing rejection cases (`1e-2`, `1.5`, `0.001`) remain rejected. Full schemagen test suite and the CMake/CTest suite pass.
Move the zero-detection check in the generated parseJsonInt64 before the
finalExp < 0 guard. Previously, valid JSON numbers whose mathematical
value is 0 but written with a large negative exponent (e.g. 0e-2,
0.0e-2, -0e-2, 0e-20) were rejected because the negative-finalExp early
return ran before the all-zero-digits branch could set out = 0. Non-zero
values with negative exponents are still correctly rejected.
Closes#56
andrew
merged commit 814b24efba into main2026-07-20 18:00:37 +00:00
andrew
deleted branch weaselbot/issue-562026-07-20 18:00:37 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Fixes #56. The generated
parseJsonInt64in schemagen rejected valid JSON numbers whose mathematical value is0but which are written with a negative exponent large enough that trailing/leading-zero trimming does not fully offset it (e.g.0e-2,0.0e-2,-0e-2,0e-20).Root cause
The
if (finalExp < 0) return false;guard ran before the zero-detection branch (if (leadingZeros == digits.size()) { out = 0; return true; }). For a zero value, all significant digits get trimmed away, leaving an all-zerodigits, butfinalExpcan still be negative, so the earlyreturn falsetriggered before theout = 0branch was reached.Fix
Reorder the two guards so the zero-detection check runs first. When the remaining digits are all zero, the value is
0regardless of the exponent, so we accept it and setout = 0. The negative-finalExprejection then only applies to non-zero values, which are correctly rejected as non-integral (e.g.1e-2).Testing
Added regression cases to
SchemagenIntegerBoundaryTestcovering both root and object-field integer schemas for0e-1,0e-2,0.0e-2,-0e-2,0e-20,0.000e-5, and{"age":0e-2}/{"age":-0e-20}. Existing rejection cases (1e-2,1.5,0.001) remain rejected. Full schemagen test suite and the CMake/CTest suite pass.