Act nowcan affect a running systemThe raw payload contains no superseded_by markers. The avoid range is based on the embedded consecutive diffs and commit subjects, which explicitly repair and then rewrite the same numeric parser routines. Upstream head is build 2.4.16844 at the end of the review window.
Tiny decimals are repaired and TimeSpan text becomes bidirectional
The numeric parser work from the previous edition needed two correctness follow-ups: GetExtended and GetNumericVariantFromJson could lose significant digits after a long run of fractional zeros. Their implementations were then simplified, optimized and covered with boundary tests, including Delphi 7 and Delphi Win32 paths. Microsoft TimeSpan support now parses text back to signed 64-bit ticks and accepts safe CSV or JSON delimiters.
TL;DR
- Land on 2.4.16844; builds 2.4.16828 through 2.4.16839 contain incomplete or still-changing numeric parser work.
- GetExtended and GetNumericVariantFromJson now preserve significant digits in values such as 0.00000000000000000123 instead of silently losing them.
- GetNumericVariantFromJson now uses a negative Int64 accumulator, restoring Delphi 7 compatibility while retaining Int64, Currency and double bounds.
- TextToTimeSpan and TextToTimeSpanBuffer parse Microsoft TimeSpan text into signed 100 ns ticks at millisecond resolution.
- TSynSystemTime.FromTimeSpan has a pointer-based overload and the final parser accepts NUL, whitespace, comma, semicolon, apostrophe or quote delimiters.
- Delphi Win32 receives shift-and-add paths for slow 64-bit multiplication; other targets retain ordinary multiplication.
Upgrade advice
Take build 2.4.16844 as a complete unit. Do not stop between 2.4.16828 and 2.4.16839: builds 16836 and 16837 repair tiny fractional values, then builds 16838 and 16839 rewrite the same parser paths before build 16840 completes their regression coverage. Applications that parse small scientific or financial values should rerun boundary tests after upgrading.
14 of 14 entries · 14 commits upstream
1
High
JSON variants keep significant digits after long fractional zeros
GetNumericVariantFromJson now skips leading zero digits after the decimal point without consuming its significant-digit budget. The fractional exponent is still decremented for every skipped zero.
Fixes
mormot.core.variants
ca07dda2+12-8
core: fixed GetNumericVariantFromJson() long-standing issue
Impact
Backends parsing tiny JSON numbers such as 0.00000000000000000123 no longer silently lose the non-zero digits or return the wrong numeric variant. This is a data-correctness fix for Delphi and FPC.
Upgrade recommended
Upgrade through build 2.4.16840 or later and retest JSON fields with many leading fractional zeros, including signed and exponent forms.
Public API
GetNumericVariantFromJsonbehaviour-changed — Leading fractional zeros no longer consume significant-digit capacity.
Units
2
High
GetExtended preserves tiny non-zero fractional values
mormot.core.text changes GetExtended so zero digits immediately after a decimal point adjust the scale without consuming the 19-digit accumulator budget until the first significant digit appears.
Fixes
mormot.core.text
9e649966+8-2
core: fixed GetExtended() long-standing issue
Impact
Delphi and FPC code parsing small scientific or financial decimal strings no longer gets a silently truncated value after many fractional zeros.
Upgrade recommended
Upgrade through the completed numeric series at build 2.4.16840 or later and add a regression case around the smallest non-zero decimal your application accepts.
Public API
GetExtendedbehaviour-changed — Long runs of fractional zeros no longer discard following significant digits.
Units
3
Medium
TSynSystemTime gains a parser for textual TimeSpan values
mormot.core.datetime adds MAX_TIMESPAN and an overloaded TSynSystemTime.FromTimeSpan that parses day, time and optional fractional fields from PUtf8Char. It returns the ending pointer and exposes day count and sign separately.
New features
mormot.core.datetime
9b3f2566+107-4
core: new TSynSystemTime.FromTimeSpan() overload
Impact
Low-level Delphi and FPC parsers can decode the same compact format emitted by TimeSpanToText. Invalid day or clock ranges return nil and clear the record.
Worth a look
Public API
MAX_TIMESPANadded — Maximum whole-day count representable by a signed 64-bit TimeSpan.TSynSystemTime.FromTimeSpan(PUtf8Char, PtrInt, PtrInt)added — Parses compact TimeSpan text and returns its end pointer, days and sign.
Units
4
Medium
Microsoft TimeSpan text can be converted back to ticks
mormot.core.datetime adds TextToTimeSpanBuffer and TextToTimeSpan. They combine parsed days, hours, minutes, seconds and milliseconds into a signed Int64 count of Microsoft 100 ns ticks.
New features
mormot.core.datetime
b6bef042+29-2
core: new TextToTimeSpan/TextToTimeSpanBuffer() functions
Impact
Delphi and FPC backends can round-trip directory or .NET duration text without custom parsing. Digits below millisecond precision are accepted but deliberately discarded.
Worth a look
Public API
TextToTimeSpanBufferadded — Returns the first byte after a parsed TimeSpan or nil on error.TextToTimeSpanadded — Converts RawUtf8 TimeSpan text into signed 100 ns ticks.
Units
5
Medium
TimeSpan parsing stops cleanly at common data delimiters
mormot.core.datetime refines TSynSystemTime.FromTimeSpan(PUtf8Char, days, neg) so a parsed value may end at NUL, whitespace, comma, semicolon, apostrophe or double quote. Fractional seconds still require at least three digits.
New features
mormot.core.datetime
a2908ede+7-6
core: refined TextToTimeSpanBuffer() function
Impact
Delphi and FPC parsers can consume a TimeSpan directly from CSV, JSON-like or tokenized buffers and continue at the returned delimiter. This broadens accepted input for APIs introduced in the same batch.
Worth a look
Public API
TSynSystemTime.FromTimeSpan(PUtf8Char, PtrInt, PtrInt)behaviour-changed — Accepts NUL, whitespace and common CSV or JSON delimiters after a valid value.
Units
6
Medium
GetInteger streamlines signed bounds on 32-bit and 64-bit targets
mormot.core.base replaces pointer-distance digit counting with a countdown, represents the sign as PtrUInt and separates explicit 32-bit overflow checks from the 64-bit nineteenth-digit bound. Leading spaces, signs and zero trimming remain supported.
Performance
mormot.core.base
b1187b83+27-30
core: refactored/optimized GetInteger() after PR #579
Impact
Delphi and FPC callers keep the same GetInteger contract and signed limits. The change is an implementation optimization following the previous overflow fix.
Units
7
Medium
Slow 64-bit multiplication paths are limited to Delphi Win32
Core integer, YAML, Currency and HTTP range parsers now use shift-and-add multiplication by ten only under HASSLOWMUL64. Other targets use native multiplication, and numeric output assertions are normalized.
Performance
mormot.core.base+3
33638087+16-27
core: optimize Delphi Win32 HASSLOWMUL64 path
Impact
Delphi Win32 keeps the multiplication workaround while current Delphi and FPC targets avoid unnecessary shift-and-add sequences. Parsed values and public APIs are unchanged.
8
Medium
JSON numeric variants regain Delphi 7 compatibility
mormot.core.variants rewrites GetNumericVariantFromJson around a negative Int64 accumulator instead of UInt64. Integer, Currency and double output paths are simplified while preserving grammar and range checks introduced by PR #579.
Compiler & platform
mormot.core.variants
41f703b6+92-114
core: rewritten GetNumericVariantFromJson()
Impact
Delphi 7 can compile the hardened parser again. Current Delphi and FPC backends keep the same variant selection and boundary behavior with a shorter common path.
Upgrade recommended
Delphi 7 users should take this rewrite together with the following GetExtended refactor and completed numeric tests through build 2.4.16840.
Public API
GetNumericVariantFromJsonbehaviour-changed — Internal accumulation changes to signed negative Int64, restoring Delphi 7 support.
Units
9
Medium
GetExtended finalizes bounded scaling without changing its API
mormot.core.text reorganizes GetExtended scaling into fast -31..31, very small and very large paths. It preserves explicit underflow and overflow checks and applies the sign after the bounded multiplication.
Under the hood
mormot.core.text
30e95e50+30-33
core: refactored GetExtended() after #579
Impact
Delphi and FPC callers keep the same API. The final implementation reduces common-case work while retaining the corrected tiny-decimal and extreme-value behavior.
Units
10
Low
GetExtended reduces per-digit and sign overhead
mormot.core.text caches each decimal digit as an integer for its bounds check and accumulation, then applies a direct unary minus instead of multiplying by a negative power-of-ten constant.
Performance
mormot.core.text
5bca2b43+6-5
core: optimized GetExtended() after last PR
Impact
No application code changes. GetExtended does slightly less work on Delphi and FPC while preserving the parser behavior from the preceding fix.
Units
11
Low
GetExtended simplifies limits and special-value handling
mormot.core.text consolidates NaN, Infinity and error exits, replaces literal Int64 bounds with a compact comparison, uses HASSLOWMUL64 for accumulation and caps parsed exponents before PtrInt arithmetic can overflow.
Under the hood
mormot.core.text
19d03c62+26-39
core: another pass on GetExtended() after #579
Impact
No public API change. Delphi and FPC retain the parser bounds added previously with a shorter implementation and an architecture-friendly exponent guard.
Units
12
Low
Int64 bounds are centralized across parsers and storage
mormot.core.base publishes MAX_INT64 and MAX_INT64_DIV10. GetExtended, HTTP byte-range parsing, OpenSSL constants and ORM database-ID limits reuse them, with GetNextRange retaining its High(Int64) clamp.
Under the hood
mormot.core.base+4
a5b75dde+13-11
core: refactored GetNextRange() and other Int64 clamp code
Impact
No application behavior changes are visible in the diff. Delphi and FPC code may reuse the new public constants instead of repeating signed 64-bit limit expressions.
Public API
MAX_INT64added — Public alias for High(Int64).MAX_INT64_DIV10added — Public precomputed High(Int64) div 10 limit.
13
Low
TimeSpan round trips and malformed inputs gain boundary tests
test.core.base checks TimeSpanToText against TextToTimeSpanBuffer for zero, signed values, day boundaries, millisecond truncation and Int64 extremes. It also rejects incomplete fields, out-of-range hours, minutes and seconds, unsupported plus signs and malformed fractions.
Tests
77e2295f+89-25
tests: enhanced TimeSpan validation coverage
Impact
No application code changes. Delphi and FPC builds gain regression coverage for the new parser and its millisecond-resolution contract.
14
Low
Numeric limits and tiny fractions gain cross-backend tests
test.core.base expands Int64, Currency, double, malformed-number and tiny-fraction assertions. It checks textual double output across TSynExtended layouts and adjusts overflow tests for supported Delphi and FPC backends.
Tests
1cff873b+56-32
tests: fixed and completed numerical conversion coverage
Impact
No application code changes. The stabilized parser behavior is now exercised across compiler-specific floating-point representations.