forked from NASAWorldWind/WorldWindJava
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNumberOutput.java
More file actions
269 lines (244 loc) · 8.69 KB
/
NumberOutput.java
File metadata and controls
269 lines (244 loc) · 8.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
package org.codehaus.jackson.io;
public final class NumberOutput
{
private final static char NULL_CHAR = (char) 0;
private static int MILLION = 1000000;
private static int BILLION = 1000000000;
private static long TEN_BILLION_L = 10000000000L;
private static long THOUSAND_L = 1000L;
private static long MIN_INT_AS_LONG = (long) Integer.MIN_VALUE;
private static long MAX_INT_AS_LONG = (long) Integer.MAX_VALUE;
final static String SMALLEST_LONG = String.valueOf(Long.MIN_VALUE);
final static char[] LEADING_TRIPLETS = new char[4000];
final static char[] FULL_TRIPLETS = new char[4000];
static {
/* Let's fill it with NULLs for ignorable leading digits,
* and digit chars for others
*/
int ix = 0;
for (int i1 = 0; i1 < 10; ++i1) {
char f1 = (char) ('0' + i1);
char l1 = (i1 == 0) ? NULL_CHAR : f1;
for (int i2 = 0; i2 < 10; ++i2) {
char f2 = (char) ('0' + i2);
char l2 = (i1 == 0 && i2 == 0) ? NULL_CHAR : f2;
for (int i3 = 0; i3 < 10; ++i3) {
// Last is never to be empty
char f3 = (char) ('0' + i3);
LEADING_TRIPLETS[ix] = l1;
LEADING_TRIPLETS[ix+1] = l2;
LEADING_TRIPLETS[ix+2] = f3;
FULL_TRIPLETS[ix] = f1;
FULL_TRIPLETS[ix+1] = f2;
FULL_TRIPLETS[ix+2] = f3;
ix += 4;
}
}
}
}
final static String[] sSmallIntStrs = new String[] {
"0","1","2","3","4","5","6","7","8","9","10"
};
final static String[] sSmallIntStrs2 = new String[] {
"-1","-2","-3","-4","-5","-6","-7","-8","-9","-10"
};
/*
////////////////////////////////////////////////////
// Efficient serialization methods using raw buffers
////////////////////////////////////////////////////
*/
/**
* @return Offset within buffer after outputting int
*/
public static int outputInt(int value, char[] buffer, int offset)
{
if (value < 0) {
if (value == Integer.MIN_VALUE) {
/* Special case: no matching positive value within range;
* let's then "upgrade" to long and output as such.
*/
return outputLong((long) value, buffer, offset);
}
buffer[offset++] = '-';
value = -value;
}
if (value < MILLION) { // at most 2 triplets...
if (value < 1000) {
if (value < 10) {
buffer[offset++] = (char) ('0' + value);
} else {
offset = outputLeadingTriplet(value, buffer, offset);
}
} else {
int thousands = value / 1000;
value -= (thousands * 1000); // == value % 1000
offset = outputLeadingTriplet(thousands, buffer, offset);
offset = outputFullTriplet(value, buffer, offset);
}
return offset;
}
// ok, all 3 triplets included
/* Let's first hand possible billions separately before
* handling 3 triplets. This is possible since we know we
* can have at most '2' as billion count.
*/
boolean hasBillions = (value >= BILLION);
if (hasBillions) {
value -= BILLION;
if (value >= BILLION) {
value -= BILLION;
buffer[offset++] = '2';
} else {
buffer[offset++] = '1';
}
}
int newValue = value / 1000;
int ones = (value - (newValue * 1000)); // == value % 1000
value = newValue;
newValue /= 1000;
int thousands = (value - (newValue * 1000));
// value now has millions, which have 1, 2 or 3 digits
if (hasBillions) {
offset = outputFullTriplet(newValue, buffer, offset);
} else {
offset = outputLeadingTriplet(newValue, buffer, offset);
}
offset = outputFullTriplet(thousands, buffer, offset);
offset = outputFullTriplet(ones, buffer, offset);
return offset;
}
/**
* @return Offset within buffer after outputting int
*/
public static int outputLong(long value, char[] buffer, int offset)
{
// First: does it actually fit in an int?
if (value < 0L) {
/* MIN_INT is actually printed as long, just because its
* negation is not an int but long
*/
if (value > MIN_INT_AS_LONG) {
return outputInt((int) value, buffer, offset);
}
if (value == Long.MIN_VALUE) {
// Special case: no matching positive value within range
int len = SMALLEST_LONG.length();
SMALLEST_LONG.getChars(0, len, buffer, offset);
return (offset + len);
}
buffer[offset++] = '-';
value = -value;
} else {
if (value <= MAX_INT_AS_LONG) {
return outputInt((int) value, buffer, offset);
}
}
/* Ok: real long print. Need to first figure out length
* in characters, and then print in from end to beginning
*/
int origOffset = offset;
offset += calcLongStrLength(value);
int ptr = offset;
// First, with long arithmetics:
while (value > MAX_INT_AS_LONG) { // full triplet
ptr -= 3;
long newValue = value / THOUSAND_L;
int triplet = (int) (value - newValue * THOUSAND_L);
outputFullTriplet(triplet, buffer, ptr);
value = newValue;
}
// Then with int arithmetics:
int ivalue = (int) value;
while (ivalue >= 1000) { // still full triplet
ptr -= 3;
int newValue = ivalue / 1000;
int triplet = ivalue - (newValue * 1000);
outputFullTriplet(triplet, buffer, ptr);
ivalue = newValue;
}
// And finally, if anything remains, partial triplet
outputLeadingTriplet(ivalue, buffer, origOffset);
return offset;
}
/*
////////////////////////////////////////////////////
// Secondary convenience serialization methods
////////////////////////////////////////////////////
*/
/* !!! 05-Aug-2008, tatus: Any ways to further optimize
* these? (or need: only called by diagnostics methods?)
*/
public static String toString(int value)
{
// Lookup table for small values
if (value < sSmallIntStrs.length) {
if (value >= 0) {
return sSmallIntStrs[value];
}
int v2 = -value - 1;
if (v2 < sSmallIntStrs2.length) {
return sSmallIntStrs2[v2];
}
}
return Integer.toString(value);
}
public static String toString(long value)
{
if (value <= Integer.MAX_VALUE &&
value >= Integer.MIN_VALUE) {
return toString((int) value);
}
return Long.toString(value);
}
public static String toString(double value)
{
return Double.toString(value);
}
/*
////////////////////////////////////////
// Internal methods
////////////////////////////////////////
*/
private static int outputLeadingTriplet(int triplet, char[] buffer, int offset)
{
int digitOffset = (triplet << 2);
char c = LEADING_TRIPLETS[digitOffset++];
if (c != NULL_CHAR) {
buffer[offset++] = c;
}
c = LEADING_TRIPLETS[digitOffset++];
if (c != NULL_CHAR) {
buffer[offset++] = c;
}
// Last is required to be non-empty
buffer[offset++] = LEADING_TRIPLETS[digitOffset];
return offset;
}
private static int outputFullTriplet(int triplet, char[] buffer, int offset)
{
int digitOffset = (triplet << 2);
buffer[offset++] = FULL_TRIPLETS[digitOffset++];
buffer[offset++] = FULL_TRIPLETS[digitOffset++];
buffer[offset++] = FULL_TRIPLETS[digitOffset];
return offset;
}
/**
*<p>
* Pre-conditions: posValue is positive, and larger than
* Integer.MAX_VALUE (about 2 billions).
*/
private static int calcLongStrLength(long posValue)
{
int len = 10;
long comp = TEN_BILLION_L;
// 19 is longest, need to worry about overflow
while (posValue >= comp) {
if (len == 19) {
break;
}
++len;
comp = (comp << 3) + (comp << 1); // 10x
}
return len;
}
}