@@ -33,6 +33,7 @@ public class OrderedCodeWriter {
33
33
public static final byte SEPARATOR = 0x01 ; // Combined with ESCAPE1
34
34
35
35
public static final byte ESCAPE2 = (byte ) 0xff ;
36
+ public static final byte INFINITY = (byte ) 0xff ; // Combined with ESCAPE2
36
37
public static final byte FF_BYTE = 0x00 ; // Combined with ESCAPE2
37
38
38
39
/** These constants are taken from the backend. */
@@ -79,6 +80,13 @@ public void writeBytesAscending(ByteString value) {
79
80
writeSeparatorAscending ();
80
81
}
81
82
83
+ public void writeBytesDescending (ByteString value ) {
84
+ for (int i = 0 ; i < value .size (); ++i ) {
85
+ writeByteDescending (value .byteAt (i ));
86
+ }
87
+ writeSeparatorDescending ();
88
+ }
89
+
82
90
/**
83
91
* Writes utf8 bytes into this byte sequence, ascending.
84
92
*
@@ -109,6 +117,36 @@ public void writeUtf8Ascending(CharSequence sequence) {
109
117
writeSeparatorAscending ();
110
118
}
111
119
120
+ /**
121
+ * Writes utf8 bytes into this byte sequence, descending.
122
+ *
123
+ * <p>This is a more efficent version of writeBytesDescending(str.getBytes(UTF_8));
124
+ */
125
+ public void writeUtf8Descending (CharSequence sequence ) {
126
+ int utf16Length = sequence .length ();
127
+ for (int i = 0 ; i < utf16Length ; i ++) {
128
+ char c = sequence .charAt (i );
129
+ if (c < 0x80 ) {
130
+ writeByteDescending ((byte ) c );
131
+ } else if (c < 0x800 ) {
132
+ writeByteDescending ((byte ) ((0xF << 6 ) | (c >>> 6 )));
133
+ writeByteDescending ((byte ) (0x80 | (0x3F & c )));
134
+ } else if ((c < MIN_SURROGATE || MAX_SURROGATE < c )) {
135
+ writeByteDescending ((byte ) ((0xF << 5 ) | (c >>> 12 )));
136
+ writeByteDescending ((byte ) (0x80 | (0x3F & (c >>> 6 ))));
137
+ writeByteDescending ((byte ) (0x80 | (0x3F & c )));
138
+ } else {
139
+ final int codePoint = Character .codePointAt (sequence , i );
140
+ ++i ; // Skip the low surrogate.
141
+ writeByteDescending ((byte ) ((0xF << 4 ) | (codePoint >>> 18 )));
142
+ writeByteDescending ((byte ) (0x80 | (0x3F & (codePoint >>> 12 ))));
143
+ writeByteDescending ((byte ) (0x80 | (0x3F & (codePoint >>> 6 ))));
144
+ writeByteDescending ((byte ) (0x80 | (0x3F & codePoint )));
145
+ }
146
+ }
147
+ writeSeparatorDescending ();
148
+ }
149
+
112
150
/** Writes an unsigned long in the ordered code format, ascending. */
113
151
public void writeUnsignedLongAscending (long value ) {
114
152
// Values are encoded with a single byte length prefix, followed
@@ -124,6 +162,21 @@ public void writeUnsignedLongAscending(long value) {
124
162
position += len ;
125
163
}
126
164
165
+ /** Writes an unsigned long in the ordered code format, descending. */
166
+ public void writeUnsignedLongDescending (long value ) {
167
+ // Values are encoded with a complemented single byte length prefix,
168
+ // followed by the complement of the actual value in big-endian format with
169
+ // leading 0xff bytes dropped.
170
+ int len = unsignedNumLength (value );
171
+ ensureAvailable (1 + len );
172
+ buffer [position ++] = (byte ) ~len ; // Write the length
173
+ for (int i = position + len - 1 ; i >= position ; --i ) {
174
+ buffer [i ] = (byte ) ~(value & 0xff );
175
+ value >>>= 8 ;
176
+ }
177
+ position += len ;
178
+ }
179
+
127
180
/** Writes a signed long in the ordered code format, ascending. */
128
181
public void writeSignedLongAscending (long value ) {
129
182
long val = value < 0 ? ~value : value ;
@@ -162,6 +215,11 @@ public void writeSignedLongAscending(long value) {
162
215
position += len ;
163
216
}
164
217
218
+ /** Writes a signed long in the ordered code format, descending. */
219
+ public void writeSignedLongDescending (long value ) {
220
+ writeSignedLongAscending (~value );
221
+ }
222
+
165
223
public void writeDoubleAscending (double val ) {
166
224
// This particular encoding has the following properties:
167
225
// The order matches the IEEE 754 floating-point comparison results with the
@@ -174,6 +232,13 @@ public void writeDoubleAscending(double val) {
174
232
writeUnsignedLongAscending (v );
175
233
}
176
234
235
+ public void writeDoubleDescending (double val ) {
236
+ // See note in #writeDoubleAscending
237
+ long v = Double .doubleToLongBits (val );
238
+ v ^= (v < 0 ) ? DOUBLE_ALL_BITS : DOUBLE_SIGN_MASK ;
239
+ writeUnsignedLongDescending (v );
240
+ }
241
+
177
242
/** Resets the buffer such that it is the same as when it was newly constructed. */
178
243
public void reset () {
179
244
position = 0 ;
@@ -200,16 +265,42 @@ private void writeByteAscending(byte b) {
200
265
}
201
266
}
202
267
268
+ /**
269
+ * Writes a single byte descending to the buffer, doing proper escaping as described in {@link
270
+ * OrderedCodeConstants}.
271
+ */
272
+ private void writeByteDescending (byte b ) {
273
+ if (b == ESCAPE1 ) {
274
+ writeEscapedByteDescending (ESCAPE1 );
275
+ writeEscapedByteDescending (NULL_BYTE );
276
+ } else if (b == ESCAPE2 ) {
277
+ writeEscapedByteDescending (ESCAPE2 );
278
+ writeEscapedByteDescending (FF_BYTE );
279
+ } else {
280
+ writeEscapedByteDescending (b );
281
+ }
282
+ }
283
+
203
284
private void writeSeparatorAscending () {
204
285
writeEscapedByteAscending (ESCAPE1 );
205
286
writeEscapedByteAscending (SEPARATOR );
206
287
}
207
288
289
+ private void writeSeparatorDescending () {
290
+ writeEscapedByteDescending (ESCAPE1 );
291
+ writeEscapedByteDescending (SEPARATOR );
292
+ }
293
+
208
294
private void writeEscapedByteAscending (byte b ) {
209
295
ensureAvailable (1 );
210
296
buffer [position ++] = b ;
211
297
}
212
298
299
+ private void writeEscapedByteDescending (byte b ) {
300
+ ensureAvailable (1 );
301
+ buffer [position ++] = (byte ) ~b ;
302
+ }
303
+
213
304
private void ensureAvailable (int bytes ) {
214
305
int minCapacity = bytes + position ;
215
306
if (minCapacity <= buffer .length ) {
0 commit comments