Skip to content

Commit be77e72

Browse files
committed
new JSON number parsing API
1 parent 2a0fd33 commit be77e72

7 files changed

Lines changed: 427 additions & 551 deletions

File tree

dub.sdl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ dependency "mir-core" version=">=1.1.106"
1313
buildType "unittest" {
1414
buildOptions "unittests" "debugMode" "debugInfo"
1515
versions "mir_bignum_test" "mir_bignum_test_llv"
16-
versions "mir_ndslice_test"
17-
versions "mir_test"
16+
// versions "mir_ndslice_test"
17+
// versions "mir_test"
1818
dflags "-lowmem"
1919
}
2020
buildType "unittest-dip1008" {

source/mir/bignum/decimal.d

Lines changed: 3 additions & 281 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ module mir.bignum.decimal;
99
import mir.serde: serdeProxy, serdeScoped;
1010
import std.traits: isSomeChar;
1111
///
12-
public import mir.bignum.low_level_view: DecimalExponentKey;
12+
public import mir.parse: DecimalExponentKey;
1313
import mir.bignum.low_level_view: ceilLog10Exp2;
1414

1515
private enum expBufferLength = 2 + ceilLog10Exp2(ulong.sizeof * 8);
@@ -180,283 +180,6 @@ struct Decimal(uint size64)
180180
scope @trusted pure @nogc nothrow
181181
if (isSomeChar!C)
182182
{
183-
enum optimize = size_t.sizeof == 8 && size64 == 1;
184-
version(LDC)
185-
{
186-
static if (optimize || (allowSpecialValues && allowDExponent && allowStartingPlus && checkEmpty) == false)
187-
pragma(inline, true);
188-
}
189-
static if (optimize)
190-
{
191-
import mir.utility: _expect;
192-
static if (checkEmpty)
193-
{
194-
if (_expect(str.length == 0, false))
195-
return false;
196-
}
197-
198-
coefficient.sign = str[0] == '-';
199-
if (coefficient.sign)
200-
{
201-
str = str[1 .. $];
202-
if (_expect(str.length == 0, false))
203-
return false;
204-
}
205-
else
206-
static if (allowStartingPlus)
207-
{
208-
if (_expect(str[0] == '+', false))
209-
{
210-
str = str[1 .. $];
211-
if (_expect(str.length == 0, false))
212-
return false;
213-
}
214-
}
215-
216-
ulong d = str[0] - C('0');
217-
str = str[1 .. $];
218-
exponent = 0;
219-
220-
ulong v, multplier = void;
221-
222-
if (_expect(d >= 10, false))
223-
{
224-
static if (allowDotOnBounds)
225-
{
226-
if (d == '.' - '0')
227-
{
228-
if (str.length == 0)
229-
return false;
230-
key = DecimalExponentKey.dot;
231-
d = str[0] - C('0');
232-
str = str[1 .. $];
233-
if (_expect(d < 10, true))
234-
goto FI;
235-
return false;
236-
}
237-
}
238-
static if (allowSpecialValues)
239-
goto NI;
240-
else
241-
return false;
242-
}
243-
244-
static if (!allowLeadingZeros)
245-
{
246-
if (_expect(d == 0, false))
247-
{
248-
if (str.length == 0)
249-
goto R;
250-
d = str[0] - C('0');
251-
str = str[1 .. $];
252-
if (d < 10)
253-
return false;
254-
goto DOT;
255-
}
256-
}
257-
258-
v = d;
259-
260-
S:
261-
if (str.length == 0)
262-
goto R;
263-
d = str[0] - C('0');
264-
str = str[1 .. $];
265-
266-
if (d < 10)
267-
{
268-
F0:
269-
import mir.checkedint: mulu, addu;
270-
bool overflow;
271-
v = mulu(v, 10u, overflow);
272-
if (overflow)
273-
return false;
274-
v = addu(v, d, overflow);
275-
if (overflow)
276-
return false;
277-
goto S;
278-
}
279-
280-
static if (allowUnderscores)
281-
{
282-
if (d == '_' - '0')
283-
{
284-
if (str.length == 0)
285-
return false;
286-
d = str[0] - C('0');
287-
str = str[1 .. $];
288-
if (_expect(d < 10, true))
289-
goto F0;
290-
return false;
291-
}
292-
}
293-
DOT:
294-
if (d == DecimalExponentKey.dot)
295-
{
296-
// The dot modifier CANNOT be preceded by any modifiers.
297-
if (key != DecimalExponentKey.none)
298-
return false;
299-
300-
key = DecimalExponentKey.dot;
301-
302-
if (str.length == 0)
303-
{
304-
static if (allowDotOnBounds)
305-
goto R;
306-
else
307-
return false;
308-
}
309-
310-
IF:
311-
312-
static if (is(C == char))
313-
{
314-
import mir.bignum.internal.parse: isMadeOfEightDigits, parseEightDigits;
315-
if (str.length >= 8 && isMadeOfEightDigits(str[0 .. 8]))
316-
{
317-
multplier = 100000000;
318-
d = parseEightDigits(str[0 .. 8]);
319-
str = str[8 .. $];
320-
exponentShift -= 8;
321-
if (str.length >= 7)
322-
{
323-
if (isMadeOfEightDigits((str.ptr - 1)[0 .. 8]))
324-
{
325-
multplier = 100000000 * 10000000;
326-
d -= str.ptr[-1] - '0';
327-
d *= 10000000;
328-
d += parseEightDigits((str.ptr - 1)[0 .. 8]);
329-
str = str[7 .. $];
330-
exponentShift -= 7;
331-
if (str.length)
332-
{
333-
auto md = str[0] - C('0');
334-
if (md < 10)
335-
{
336-
d *= 10;
337-
multplier = 100000000 * 100000000;
338-
d += md;
339-
str = str[1 .. $];
340-
}
341-
}
342-
}
343-
else
344-
{
345-
TrySix:
346-
if (isMadeOfEightDigits((str.ptr - 2)[0 .. 8]))
347-
{
348-
multplier = 100000000 * 1000000;
349-
d -= str.ptr[-1] - '0';
350-
d -= (str.ptr[-2] - '0') * 10;
351-
d *= 1000000;
352-
d += parseEightDigits((str.ptr - 2)[0 .. 8]);
353-
str = str[6 .. $];
354-
exponentShift -= 6;
355-
}
356-
}
357-
358-
}
359-
else
360-
if (str.length == 6)
361-
goto TrySix;
362-
goto FIL;
363-
}
364-
}
365-
366-
d = str[0] - C('0');
367-
str = str[1 .. $];
368-
if (_expect(d >= 10, false))
369-
goto DOB;
370-
FI:
371-
exponentShift--;
372-
multplier = 10;
373-
FIL:
374-
{
375-
import mir.checkedint: mulu, addu;
376-
bool overflow;
377-
v = mulu(v, multplier, overflow);
378-
if (overflow)
379-
return false;
380-
v = addu(v, d, overflow);
381-
if (overflow)
382-
return false;
383-
}
384-
if (str.length == 0)
385-
goto E;
386-
d = str[0] - C('0');
387-
str = str[1 .. $];
388-
if (d < 10)
389-
goto FI;
390-
391-
static if (allowUnderscores)
392-
{
393-
if (d == '_' - '0')
394-
{
395-
if (str.length == 0)
396-
return false;
397-
d = str[0] - C('0');
398-
str = str[1 .. $];
399-
if (_expect(d < 10, true))
400-
goto FI;
401-
return false;
402-
}
403-
}
404-
DOB:
405-
static if (!allowDotOnBounds)
406-
{
407-
if (exponentShift == 0)
408-
return false;
409-
}
410-
411-
}
412-
413-
static if (allowExponent)
414-
{
415-
if (d == DecimalExponentKey.e
416-
|| d == DecimalExponentKey.E
417-
|| d == DecimalExponentKey.d && allowDExponent
418-
|| d == DecimalExponentKey.D && allowDExponent
419-
)
420-
{
421-
import mir.parse: parse;
422-
key = cast(DecimalExponentKey)d;
423-
if (parse(str, exponent) && str.length == 0)
424-
goto E;
425-
}
426-
}
427-
return false;
428-
429-
E:
430-
exponent += exponentShift;
431-
R:
432-
coefficient.data[0] = v;
433-
coefficient.length = v != 0;
434-
return true;
435-
436-
static if (allowSpecialValues)
437-
{
438-
NI:
439-
exponent = exponent.max;
440-
if (str.length == 2)
441-
{
442-
auto stail = cast(C[2])str[0 .. 2];
443-
if (d == 'i' - '0' && stail == cast(C[2])"nf" || d == 'I' - '0' && (stail == cast(C[2])"nf" || stail == cast(C[2])"NF"))
444-
{
445-
key = DecimalExponentKey.infinity;
446-
goto R;
447-
}
448-
if (d == 'n' - '0' && stail == cast(C[2])"an" || d == 'N' - '0' && (stail == cast(C[2])"aN" || stail == cast(C[2])"AN"))
449-
{
450-
v = 1;
451-
key = DecimalExponentKey.nan;
452-
goto R;
453-
}
454-
}
455-
return false;
456-
}
457-
}
458-
else
459-
{
460183
import mir.bignum.low_level_view: DecimalView, BigUIntView, MaxWordPow10;
461184
auto work = DecimalView!size_t(false, 0, BigUIntView!size_t(coefficient.data));
462185
auto ret = work.fromStringImpl!(C,
@@ -473,7 +196,6 @@ struct Decimal(uint size64)
473196
coefficient.sign = work.sign;
474197
exponent = work.exponent;
475198
return ret;
476-
}
477199
}
478200

479201
private enum coefficientBufferLength = 2 + ceilLog10Exp2(coefficient.data.length * (size_t.sizeof * 8)); // including dot and sign
@@ -723,13 +445,13 @@ struct Decimal(uint size64)
723445
}
724446

725447
///
726-
version(mir_bignum_test)
448+
version(mir_bignum_test)
727449
@safe pure nothrow @nogc
728450
unittest
729451
{
730452
import mir.test: should;
731453
import mir.conv: to;
732-
Decimal!256 decimal = void;
454+
Decimal!128 decimal = void;
733455
DecimalExponentKey key;
734456

735457
assert(decimal.fromStringImpl("3.141592653589793378e-10", key));

source/mir/bignum/internal/dec2float.d

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ private template bigSize(T)
241241
{
242242
static if (T.mant_dig < 64)
243243
{
244-
enum size_t bigSize = 83;
244+
enum size_t bigSize = 128;
245245
}
246246
else
247247
{
@@ -533,6 +533,7 @@ private auto _load(uint size : 128)(long e) @trusted
533533
return Fp!128(false, p10exp, p10coeff);
534534
}
535535

536+
version(mir_test)
536537
unittest
537538
{
538539
import mir.bignum.fp;

0 commit comments

Comments
 (0)