Skip to content

Commit 684de6b

Browse files
committed
Add support for Decimal64
1 parent 3695c03 commit 684de6b

File tree

1 file changed

+147
-0
lines changed
  • jsoniter-scala-core/jvm/src/main/scala/com/github/plokhotnyuk/jsoniter_scala/core

1 file changed

+147
-0
lines changed

jsoniter-scala-core/jvm/src/main/scala/com/github/plokhotnyuk/jsoniter_scala/core/JsonReader.scala

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,20 @@ final class JsonReader private[jsoniter_scala](
484484
x
485485
}
486486

487+
/**
488+
* Reads a JSON key into a `Long` representation of `Decimal64` value.
489+
*
490+
* @return a Decimal64` value of the parsed JSON key
491+
* @throws JsonReaderException in cases of reaching the end of input or illegal format of JSON key
492+
*/
493+
def readKeyAsDecimal64(): Long = {
494+
nextTokenOrError('"', head)
495+
val x = readDecimal64(isToken = false)
496+
nextByteOrError('"', head)
497+
nextTokenOrError(':', head)
498+
x
499+
}
500+
487501
/**
488502
* Reads a JSON key into a `BigInt` instance with the default limit of allowed digits.
489503
*
@@ -610,6 +624,15 @@ final class JsonReader private[jsoniter_scala](
610624
*/
611625
def readDouble(): Double = readDouble(isToken = true)
612626

627+
/**
628+
* Reads a JSON number value into a `Long` representating of `Decimal64` value.
629+
*
630+
* @return a `Decimal64` value of the parsed JSON value
631+
* @throws JsonReaderException in cases of reaching the end of input or detection of leading zero or
632+
* illegal format of JSON value
633+
*/
634+
def readDecimal64(): Long = readDecimal64(isToken = true)
635+
613636
/**
614637
* Reads a JSON number value into a `Float` value.
615638
*
@@ -1037,6 +1060,19 @@ final class JsonReader private[jsoniter_scala](
10371060
x
10381061
}
10391062

1063+
/**
1064+
* Reads a JSON string value into a `Long` representation of `Decimal64` value.
1065+
*
1066+
* @return a `Decimal` value of the parsed JSON value.
1067+
* @throws JsonReaderException in cases of reaching the end of input or illegal format of JSON value
1068+
*/
1069+
def readStringAsDecimal64(): Long = {
1070+
nextTokenOrError('"', head)
1071+
val x = readDecimal64(isToken = false)
1072+
nextByteOrError('"', head)
1073+
x
1074+
}
1075+
10401076
/**
10411077
* Reads a JSON string value into a `Float` value.
10421078
*
@@ -2333,6 +2369,117 @@ final class JsonReader private[jsoniter_scala](
23332369
java.lang.Double.parseDouble(new String(buf, 0, offset, pos - offset))
23342370
}
23352371

2372+
def readDecimal64(isToken: Boolean): Long = {
2373+
var b =
2374+
if (isToken) nextToken(head)
2375+
else nextByte(head)
2376+
var isNeg = false
2377+
if (b == '-') {
2378+
b = nextByte(head)
2379+
isNeg = true
2380+
}
2381+
if (b < '0' || b > '9') numberError()
2382+
var pos = head
2383+
var buf = this.buf
2384+
val from = pos - 1
2385+
val oldMark = mark
2386+
val newMark =
2387+
if (oldMark < 0) from
2388+
else oldMark
2389+
mark = newMark
2390+
var m10 = (b - '0').toLong
2391+
var e10 = 0
2392+
var digits = 1
2393+
if (isToken && m10 == 0) {
2394+
if ((pos < tail || {
2395+
pos = loadMore(pos)
2396+
buf = this.buf
2397+
pos < tail
2398+
}) && {
2399+
b = buf(pos)
2400+
b >= '0' && b <= '9'
2401+
}) leadingZeroError(pos - 1)
2402+
} else {
2403+
while ((pos < tail || {
2404+
pos = loadMore(pos)
2405+
buf = this.buf
2406+
pos < tail
2407+
}) && {
2408+
b = buf(pos)
2409+
b >= '0' && b <= '9'
2410+
}) {
2411+
if (m10 < 922337203685477580L) {
2412+
m10 = m10 * 10 + (b - '0')
2413+
digits += 1
2414+
} else e10 += 1
2415+
pos += 1
2416+
}
2417+
}
2418+
if (b == '.') {
2419+
pos += 1
2420+
e10 += digits
2421+
var noFracDigits = true
2422+
while ((pos < tail || {
2423+
pos = loadMore(pos)
2424+
buf = this.buf
2425+
pos < tail
2426+
}) && {
2427+
b = buf(pos)
2428+
b >= '0' && b <= '9'
2429+
}) {
2430+
if (m10 < 922337203685477580L) {
2431+
m10 = m10 * 10 + (b - '0')
2432+
digits += 1
2433+
}
2434+
noFracDigits = false
2435+
pos += 1
2436+
}
2437+
e10 -= digits
2438+
if (noFracDigits) numberError(pos)
2439+
}
2440+
if ((b | 0x20) == 'e') {
2441+
b = nextByte(pos + 1)
2442+
var s = 0
2443+
if (b == '-' || b == '+') {
2444+
s = '+' - b >> 31
2445+
b = nextByte(head)
2446+
}
2447+
if (b < '0' || b > '9') numberError()
2448+
var exp = b - '0'
2449+
pos = head
2450+
buf = this.buf
2451+
while ((pos < tail || {
2452+
pos = loadMore(pos)
2453+
buf = this.buf
2454+
pos < tail
2455+
}) && {
2456+
b = buf(pos)
2457+
b >= '0' && b <= '9'
2458+
}) {
2459+
if (exp < 214748364) exp = exp * 10 + (b - '0')
2460+
pos += 1
2461+
}
2462+
exp ^= s
2463+
exp -= s
2464+
e10 += exp
2465+
}
2466+
head = pos
2467+
var x: Double =
2468+
if (e10 == 0 && m10 < 922337203685477580L) m10.toDouble
2469+
else if (m10 < 4503599627370496L && e10 >= -22 && e10 <= 38 - digits) {
2470+
val pow10 = pow10Doubles
2471+
if (e10 < 0) m10 / pow10(-e10)
2472+
else if (e10 <= 22) m10 * pow10(e10)
2473+
else {
2474+
val slop = 16 - digits
2475+
(m10 * pow10(slop)) * pow10(e10 - slop)
2476+
}
2477+
} else toDouble(m10, e10, from, newMark, pos)
2478+
if (isNeg) x = -x
2479+
if (mark > oldMark) mark = oldMark
2480+
x
2481+
}
2482+
23362483
def readFloat(isToken: Boolean): Float = {
23372484
var b =
23382485
if (isToken) nextToken(head)

0 commit comments

Comments
 (0)