Skip to content

Commit af61e1d

Browse files
committed
Version 4.2.0: add missing source files
1 parent d57ebd1 commit af61e1d

File tree

3 files changed

+1005
-0
lines changed

3 files changed

+1005
-0
lines changed
Lines changed: 335 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,335 @@
1+
package com.upokecenter.cbor;
2+
/*
3+
Written by Peter O.
4+
Any copyright is dedicated to the Public Domain.
5+
http://creativecommons.org/publicdomain/zero/1.0/
6+
If you like this, you should donate to Peter O.
7+
at: http://peteroupc.github.io/
8+
*/
9+
10+
import java.util.*;
11+
12+
import com.upokecenter.util.*;
13+
import com.upokecenter.numbers.*;
14+
15+
final class CBORDataUtilitiesByteArrayString {
16+
private CBORDataUtilitiesByteArrayString() {
17+
}
18+
private static final long DoubleNegInfinity = ((long)(0xfffL << 52));
19+
private static final long DoublePosInfinity = ((long)(0x7ffL << 52));
20+
21+
static CBORObject ParseJSONNumber(
22+
byte[] chars,
23+
int offset,
24+
int count,
25+
JSONOptions options,
26+
int[] endOfNumber) {
27+
if (chars == null || chars.length == 0 || count <= 0) {
28+
return null;
29+
}
30+
if (offset < 0 || offset > chars.length) {
31+
return null;
32+
}
33+
if (count > chars.length || chars.length - offset < count) {
34+
return null;
35+
}
36+
JSONOptions opt = (options == null) ? (CBORDataUtilities.DefaultOptions) : options;
37+
boolean preserveNegativeZero = options.getPreserveNegativeZero();
38+
JSONOptions.ConversionMode kind = options.getNumberConversion();
39+
int endPos = offset + count;
40+
int initialOffset = offset;
41+
boolean negative = false;
42+
if (chars[initialOffset] == '-') {
43+
++offset;
44+
negative = true;
45+
}
46+
int numOffset = offset;
47+
boolean haveDecimalPoint = false;
48+
boolean haveDigits = false;
49+
boolean haveDigitsAfterDecimal = false;
50+
boolean haveExponent = false;
51+
int i = offset;
52+
int decimalPointPos = -1;
53+
// Check syntax
54+
int k = i;
55+
if (endPos - 1 > k && chars[k] == '0' && chars[k + 1] >= '0' &&
56+
chars[k + 1] <= '9') {
57+
if (endOfNumber != null) {
58+
endOfNumber[0] = k + 2;
59+
}
60+
return null;
61+
}
62+
for (; k < endPos; ++k) {
63+
byte c = chars[k];
64+
if (c >= '0' && c <= '9') {
65+
haveDigits = true;
66+
haveDigitsAfterDecimal |= haveDecimalPoint;
67+
} else if (c == '.') {
68+
if (!haveDigits || haveDecimalPoint) {
69+
// no digits before the decimal point,
70+
// or decimal point already seen
71+
if (endOfNumber != null) {
72+
endOfNumber[0] = k;
73+
}
74+
return null;
75+
}
76+
haveDecimalPoint = true;
77+
decimalPointPos = k;
78+
} else if (c == 'E' || c == 'e') {
79+
++k;
80+
haveExponent = true;
81+
break;
82+
} else {
83+
if (endOfNumber != null) {
84+
endOfNumber[0] = k;
85+
// Check if character can validly appear after a JSON number
86+
if (c != ',' && c != ']' && c != '}' &&
87+
c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09) {
88+
return null;
89+
} else {
90+
endPos = k;
91+
break;
92+
}
93+
}
94+
return null;
95+
}
96+
}
97+
if (!haveDigits || (haveDecimalPoint && !haveDigitsAfterDecimal)) {
98+
if (endOfNumber != null) {
99+
endOfNumber[0] = k;
100+
}
101+
return null;
102+
}
103+
int exponentPos = -1;
104+
boolean negativeExp = false;
105+
if (haveExponent) {
106+
haveDigits = false;
107+
if (k == endPos) {
108+
if (endOfNumber != null) {
109+
endOfNumber[0] = k;
110+
}
111+
return null;
112+
}
113+
byte c = chars[k];
114+
if (c == '+') {
115+
++k;
116+
} else if (c == '-') {
117+
negativeExp = true;
118+
++k;
119+
}
120+
for (; k < endPos; ++k) {
121+
c = chars[k];
122+
if (c >= '0' && c <= '9') {
123+
if (exponentPos < 0 && c != '0') {
124+
exponentPos = k;
125+
}
126+
haveDigits = true;
127+
} else if (endOfNumber != null) {
128+
endOfNumber[0] = k;
129+
// Check if character can validly appear after a JSON number
130+
if (c != ',' && c != ']' && c != '}' &&
131+
c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09) {
132+
return null;
133+
} else {
134+
endPos = k;
135+
break;
136+
}
137+
} else {
138+
return null;
139+
}
140+
}
141+
if (!haveDigits) {
142+
if (endOfNumber != null) {
143+
endOfNumber[0] = k;
144+
}
145+
return null;
146+
}
147+
}
148+
if (endOfNumber != null) {
149+
endOfNumber[0] = endPos;
150+
}
151+
if (exponentPos >= 0 && endPos - exponentPos > 20) {
152+
// Exponent too high for precision to overcome (which
153+
// has a length no bigger than Integer.MAX_VALUE, which is 10 digits
154+
// long)
155+
if (negativeExp) {
156+
// underflow
157+
if (kind == JSONOptions.ConversionMode.Double ||
158+
kind == JSONOptions.ConversionMode.IntOrFloat) {
159+
if (!negative) {
160+
return CBORObject.FromFloatingPointBits(0, 2);
161+
} else {
162+
return CBORObject.FromFloatingPointBits(0x8000, 2);
163+
}
164+
} else if (kind ==
165+
JSONOptions.ConversionMode.IntOrFloatFromDouble) {
166+
return CBORObject.FromObject(0);
167+
}
168+
} else {
169+
// overflow
170+
if (kind == JSONOptions.ConversionMode.Double ||
171+
kind == JSONOptions.ConversionMode.IntOrFloatFromDouble ||
172+
kind == JSONOptions.ConversionMode.IntOrFloat) {
173+
return CBORObject.FromFloatingPointBits(
174+
negative ? DoubleNegInfinity : DoublePosInfinity,
175+
8);
176+
} else if (kind == JSONOptions.ConversionMode.Decimal128) {
177+
return CBORObject.FromObject(negative ?
178+
EDecimal.NegativeInfinity : EDecimal.PositiveInfinity);
179+
}
180+
}
181+
}
182+
if (!haveExponent && !haveDecimalPoint &&
183+
(endPos - numOffset) <= 16) {
184+
// Very common case of all-digit JSON number strings
185+
// less than 2^53 (with or without number sign)
186+
long v = 0L;
187+
int vi = numOffset;
188+
for (; vi < endPos; ++vi) {
189+
v = (v * 10) + (int)(chars[vi] - '0');
190+
}
191+
if ((v != 0 || !negative) && v < (1L << 53) - 1) {
192+
if (negative) {
193+
v = -v;
194+
}
195+
if (kind == JSONOptions.ConversionMode.Double) {
196+
return CBORObject.FromObject(EFloat.FromInt64(v).ToDoubleBits());
197+
} else if (kind == JSONOptions.ConversionMode.Decimal128) {
198+
return CBORObject.FromObject(EDecimal.FromInt64(v));
199+
} else {
200+
return CBORObject.FromObject(v);
201+
}
202+
}
203+
}
204+
if (kind == JSONOptions.ConversionMode.Full) {
205+
if (!haveDecimalPoint && !haveExponent) {
206+
EInteger ei = EInteger.FromSubstring(chars, initialOffset, endPos);
207+
if (preserveNegativeZero && ei.isZero() && negative) {
208+
// TODO: In next major version, change to EDecimal.NegativeZero
209+
return CBORObject.FromFloatingPointBits(0x8000, 2);
210+
}
211+
return CBORObject.FromObject(ei);
212+
}
213+
if (!haveExponent && haveDecimalPoint) {
214+
// No more than 18 digits plus one decimal point (which
215+
// should fit a long)
216+
long lv = 0L;
217+
int expo = -(endPos - (decimalPointPos + 1));
218+
int vi = numOffset;
219+
int digitCount = 0;
220+
for (; vi < decimalPointPos; ++vi) {
221+
if (digitCount < 0 || digitCount >= 18) {
222+
digitCount = -1;
223+
break;
224+
} else if (digitCount > 0 || chars[vi] != '0') {
225+
++digitCount;
226+
}
227+
lv = ((lv * 10) + (int)(chars[vi] - '0'));
228+
}
229+
for (vi = decimalPointPos + 1; vi < endPos; ++vi) {
230+
if (digitCount < 0 || digitCount >= 18) {
231+
digitCount = -1;
232+
break;
233+
} else if (digitCount > 0 || chars[vi] != '0') {
234+
++digitCount;
235+
}
236+
lv = ((lv * 10) + (int)(chars[vi] - '0'));
237+
}
238+
if (negative) {
239+
lv = -lv;
240+
}
241+
if (digitCount >= 0 && (!negative || lv != 0)) {
242+
if (expo == 0) {
243+
return CBORObject.FromObject(lv);
244+
} else {
245+
CBORObject cbor = CBORObject.FromArrayBackedObject(
246+
new CBORObject[] {
247+
CBORObject.FromObject(expo),
248+
CBORObject.FromObject(lv),
249+
});
250+
return cbor.WithTag(4);
251+
}
252+
}
253+
}
254+
// System.out.println("convfull " + chars.substring(initialOffset,(initialOffset)+(endPos -
255+
// initialOffset)));
256+
EDecimal ed = EDecimal.FromString(
257+
chars,
258+
initialOffset,
259+
endPos - initialOffset);
260+
if (ed.isZero() && negative) {
261+
if (ed.getExponent().isZero()) {
262+
// TODO: In next major version, use EDecimal
263+
// for preserveNegativeZero
264+
return preserveNegativeZero ?
265+
CBORObject.FromFloatingPointBits(0x8000, 2) :
266+
CBORObject.FromObject(0);
267+
} else if (!preserveNegativeZero) {
268+
return CBORObject.FromObject(ed.Negate());
269+
} else {
270+
return CBORObject.FromObject(ed);
271+
}
272+
} else {
273+
return ed.getExponent().isZero() ? CBORObject.FromObject(ed.getMantissa()) :
274+
CBORObject.FromObject(ed);
275+
}
276+
} else if (kind == JSONOptions.ConversionMode.Double) {
277+
EFloat ef = EFloat.FromString(
278+
chars,
279+
initialOffset,
280+
endPos - initialOffset,
281+
EContext.Binary64);
282+
long lb = ef.ToDoubleBits();
283+
if (!preserveNegativeZero && (lb == 1L << 63 || lb == 0L)) {
284+
lb = 0L;
285+
}
286+
return CBORObject.FromFloatingPointBits(lb, 8);
287+
} else if (kind == JSONOptions.ConversionMode.Decimal128) {
288+
EDecimal ed = EDecimal.FromString(
289+
chars,
290+
initialOffset,
291+
endPos - initialOffset,
292+
EContext.Decimal128);
293+
if (!preserveNegativeZero && ed.isNegative() && ed.isZero()) {
294+
ed = ed.Negate();
295+
}
296+
return CBORObject.FromObject(ed);
297+
} else if (kind == JSONOptions.ConversionMode.IntOrFloatFromDouble) {
298+
EFloat ef = EFloat.FromString(
299+
chars,
300+
initialOffset,
301+
endPos - initialOffset,
302+
EContext.Binary64);
303+
long lb = ef.ToDoubleBits();
304+
return (!CBORUtilities.IsBeyondSafeRange(lb) &&
305+
CBORUtilities.IsIntegerValue(lb)) ?
306+
CBORObject.FromObject(CBORUtilities.GetIntegerValue(lb)) :
307+
CBORObject.FromFloatingPointBits(lb, 8);
308+
} else if (kind == JSONOptions.ConversionMode.IntOrFloat) {
309+
EContext ctx = EContext.Binary64.WithBlankFlags();
310+
EFloat ef = EFloat.FromString(
311+
chars,
312+
initialOffset,
313+
endPos - initialOffset,
314+
ctx);
315+
long lb = ef.ToDoubleBits();
316+
if ((ctx.getFlags() & EContext.FlagInexact) != 0) {
317+
// Inexact conversion to double, meaning that the String doesn't
318+
// represent an integer in [-(2^53)+1, 2^53), which is representable
319+
// ((exactly instanceof Double) ? (double)exactly : null), so treat as ConversionMode.Double
320+
if (!preserveNegativeZero && (lb == 1L << 63 || lb == 0L)) {
321+
lb = 0L;
322+
}
323+
return CBORObject.FromFloatingPointBits(lb, 8);
324+
} else {
325+
// Exact conversion; treat as ConversionMode.IntToFloatFromDouble
326+
return (!CBORUtilities.IsBeyondSafeRange(lb) &&
327+
CBORUtilities.IsIntegerValue(lb)) ?
328+
CBORObject.FromObject(CBORUtilities.GetIntegerValue(lb)) :
329+
CBORObject.FromFloatingPointBits(lb, 8);
330+
}
331+
} else {
332+
throw new IllegalArgumentException("Unsupported conversion kind.");
333+
}
334+
}
335+
}

0 commit comments

Comments
 (0)