KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sleepycat > bind > tuple > TupleOutput


1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2000,2006 Oracle. All rights reserved.
5  *
6  * $Id: TupleOutput.java,v 1.28 2006/11/15 14:01:02 mark Exp $
7  */

8
9 package com.sleepycat.bind.tuple;
10
11 import java.math.BigInteger JavaDoc;
12
13 import com.sleepycat.util.FastOutputStream;
14 import com.sleepycat.util.PackedInteger;
15 import com.sleepycat.util.UtfOps;
16
17 /**
18  * An <code>OutputStream</code> with <code>DataOutput</code>-like methods for
19  * writing tuple fields. It is used by <code>TupleBinding</code>.
20  *
21  * <p>This class has many methods that have the same signatures as methods in
22  * the {@link java.io.DataOutput} interface. The reason this class does not
23  * implement {@link java.io.DataOutput} is because it would break the interface
24  * contract for those methods because of data format differences.</p>
25  *
26  * <p>Signed numbers are stored in the buffer in MSB (most significant byte
27  * first) order with their sign bit (high-order bit) inverted to cause negative
28  * numbers to be sorted first when comparing values as unsigned byte arrays,
29  * as done in a database. Unsigned numbers, including characters, are stored
30  * in MSB order with no change to their sign bit. BigInteger values are stored
31  * with a preceding length having the same sign as the value.</p>
32  *
33  * <p>Strings and character arrays are stored either as a fixed length array of
34  * unicode characters, where the length must be known by the application, or as
35  * a null-terminated UTF byte array.</p>
36  * <ul>
37  * <li>Null strings are UTF encoded as { 0xFF }, which is not allowed in a
38  * standard UTF encoding. This allows null strings, as distinct from empty or
39  * zero length strings, to be represented in a tuple. Using the default
40  * comparator, null strings will be ordered last.</li>
41  * <li>Zero (0x0000) character values are UTF encoded as non-zero values, and
42  * therefore embedded zeros in the string are supported. The sequence { 0xC0,
43  * 0x80 } is used to encode a zero character. This UTF encoding is the same
44  * one used by native Java UTF libraries. However, this encoding of zero does
45  * impact the lexicographical ordering, and zeros will not be sorted first (the
46  * natural order) or last. For all character values other than zero, the
47  * default UTF byte ordering is the same as the Unicode lexicographical
48  * character ordering.</li>
49  * </ul>
50  *
51  * <p>Floats and doubles are stored using two different representations: sorted
52  * representation and integer-bit (IEEE 754) representation. If you use
53  * negative floating point numbers in a key, you should use sorted
54  * representation; alternatively you may use integer-bit representation but you
55  * will need to implement and configure a custom comparator to get correct
56  * numeric ordering for negative numbers.</p>
57  *
58  * <p>To use sorted representation use this set of methods:</p>
59  * <ul>
60  * <li>{@link TupleOutput#writeSortedFloat}</li>
61  * <li>{@link TupleInput#readSortedFloat}</li>
62  * <li>{@link TupleOutput#writeSortedDouble}</li>
63  * <li>{@link TupleInput#readSortedDouble}</li>
64  * </ul>
65  *
66  * <p>To use integer-bit representation use this set of methods:</p>
67  * <ul>
68  * <li>{@link TupleOutput#writeFloat}</li>
69  * <li>{@link TupleInput#readFloat}</li>
70  * <li>{@link TupleOutput#writeDouble}</li>
71  * <li>{@link TupleInput#readDouble}</li>
72  * </ul>
73  *
74  * @author Mark Hayes
75  */

76 public class TupleOutput extends FastOutputStream {
77
78     /**
79      * We represent a null string as a single FF UTF character, which cannot
80      * occur in a UTF encoded string.
81      */

82     static final int NULL_STRING_UTF_VALUE = ((byte) 0xFF);
83
84     /**
85      * Creates a tuple output object for writing a byte array of tuple data.
86      */

87     public TupleOutput() {
88
89         super();
90     }
91
92     /**
93      * Creates a tuple output object for writing a byte array of tuple data,
94      * using a given buffer. A new buffer will be allocated only if the number
95      * of bytes needed is greater than the length of this buffer. A reference
96      * to the byte array will be kept by this object and therefore the byte
97      * array should not be modified while this object is in use.
98      *
99      * @param buffer is the byte array to use as the buffer.
100      */

101     public TupleOutput(byte[] buffer) {
102
103         super(buffer);
104     }
105
106     // --- begin DataOutput compatible methods ---
107

108     /**
109      * Writes the specified bytes to the buffer, converting each character to
110      * an unsigned byte value.
111      * Writes values that can be read using {@link TupleInput#readBytes}.
112      * Only characters with values below 0x100 may be written using this
113      * method, since the high-order 8 bits of all characters are discarded.
114      *
115      * @param val is the string containing the values to be written.
116      *
117      * @return this tuple output object.
118      *
119      * @throws NullPointerException if the val parameter is null.
120      */

121     public final TupleOutput writeBytes(String JavaDoc val) {
122
123         writeBytes(val.toCharArray());
124         return this;
125     }
126
127     /**
128      * Writes the specified characters to the buffer, converting each character
129      * to a two byte unsigned value.
130      * Writes values that can be read using {@link TupleInput#readChars}.
131      *
132      * @param val is the string containing the characters to be written.
133      *
134      * @return this tuple output object.
135      *
136      * @throws NullPointerException if the val parameter is null.
137      */

138     public final TupleOutput writeChars(String JavaDoc val) {
139
140         writeChars(val.toCharArray());
141         return this;
142     }
143
144     /**
145      * Writes the specified characters to the buffer, converting each character
146      * to UTF format, and adding a null terminator byte.
147      * Note that zero (0x0000) character values are encoded as non-zero values
148      * and a null String parameter is encoded as 0xFF.
149      * Writes values that can be read using {@link TupleInput#readString()}.
150      *
151      * @param val is the string containing the characters to be written.
152      *
153      * @return this tuple output object.
154      */

155     public final TupleOutput writeString(String JavaDoc val) {
156
157         if (val != null) {
158             writeString(val.toCharArray());
159         } else {
160             writeFast(NULL_STRING_UTF_VALUE);
161         }
162         writeFast(0);
163         return this;
164     }
165
166     /**
167      * Writes a char (two byte) unsigned value to the buffer.
168      * Writes values that can be read using {@link TupleInput#readChar}.
169      *
170      * @param val is the value to write to the buffer.
171      *
172      * @return this tuple output object.
173      */

174     public final TupleOutput writeChar(int val) {
175
176         writeFast((byte) (val >>> 8));
177         writeFast((byte) val);
178         return this;
179     }
180
181     /**
182      * Writes a boolean (one byte) unsigned value to the buffer, writing one
183      * if the value is true and zero if it is false.
184      * Writes values that can be read using {@link TupleInput#readBoolean}.
185      *
186      * @param val is the value to write to the buffer.
187      *
188      * @return this tuple output object.
189      */

190     public final TupleOutput writeBoolean(boolean val) {
191
192         writeFast(val ? (byte)1 : (byte)0);
193         return this;
194     }
195
196     /**
197      * Writes an signed byte (one byte) value to the buffer.
198      * Writes values that can be read using {@link TupleInput#readByte}.
199      *
200      * @param val is the value to write to the buffer.
201      *
202      * @return this tuple output object.
203      */

204     public final TupleOutput writeByte(int val) {
205
206         writeUnsignedByte(val ^ 0x80);
207         return this;
208     }
209
210     /**
211      * Writes an signed short (two byte) value to the buffer.
212      * Writes values that can be read using {@link TupleInput#readShort}.
213      *
214      * @param val is the value to write to the buffer.
215      *
216      * @return this tuple output object.
217      */

218     public final TupleOutput writeShort(int val) {
219
220         writeUnsignedShort(val ^ 0x8000);
221         return this;
222     }
223
224     /**
225      * Writes an signed int (four byte) value to the buffer.
226      * Writes values that can be read using {@link TupleInput#readInt}.
227      *
228      * @param val is the value to write to the buffer.
229      *
230      * @return this tuple output object.
231      */

232     public final TupleOutput writeInt(int val) {
233
234         writeUnsignedInt(val ^ 0x80000000);
235         return this;
236     }
237
238     /**
239      * Writes an signed long (eight byte) value to the buffer.
240      * Writes values that can be read using {@link TupleInput#readLong}.
241      *
242      * @param val is the value to write to the buffer.
243      *
244      * @return this tuple output object.
245      */

246     public final TupleOutput writeLong(long val) {
247
248         writeUnsignedLong(val ^ 0x8000000000000000L);
249         return this;
250     }
251
252     /**
253      * Writes an signed float (four byte) value to the buffer.
254      * Writes values that can be read using {@link TupleInput#readFloat}.
255      * <code>Float.floatToIntBits</code> is used to convert the signed float
256      * value.
257      *
258      * <p><em>Note:</em> This method produces byte array values that by default
259      * (without a custom comparator) do <em>not</em> sort correctly for
260      * negative values. Only non-negative values are sorted correctly by
261      * default. To sort all values correctly by default, use {@link
262      * #writeSortedFloat}.</p>
263      *
264      * @param val is the value to write to the buffer.
265      *
266      * @return this tuple output object.
267      */

268     public final TupleOutput writeFloat(float val) {
269
270         writeUnsignedInt(Float.floatToIntBits(val));
271         return this;
272     }
273
274     /**
275      * Writes an signed double (eight byte) value to the buffer.
276      * Writes values that can be read using {@link TupleInput#readDouble}.
277      * <code>Double.doubleToLongBits</code> is used to convert the signed
278      * double value.
279      *
280      * <p><em>Note:</em> This method produces byte array values that by default
281      * (without a custom comparator) do <em>not</em> sort correctly for
282      * negative values. Only non-negative values are sorted correctly by
283      * default. To sort all values correctly by default, use {@link
284      * #writeSortedDouble}.</p>
285      *
286      * @param val is the value to write to the buffer.
287      *
288      * @return this tuple output object.
289      */

290     public final TupleOutput writeDouble(double val) {
291
292         writeUnsignedLong(Double.doubleToLongBits(val));
293         return this;
294     }
295
296     /**
297      * Writes a signed float (four byte) value to the buffer, with support for
298      * correct default sorting of all values.
299      * Writes values that can be read using {@link TupleInput#readSortedFloat}.
300      *
301      * <p><code>Float.floatToIntBits</code> and the following bit manipulations
302      * are used to convert the signed float value to a representation that is
303      * sorted correctly by default.</p>
304      * <pre>
305      * int intVal = Float.floatToIntBits(val);
306      * intVal ^= (intVal &lt; 0) ? 0xffffffff : 0x80000000;
307      * </pre>
308      *
309      * @param val is the value to write to the buffer.
310      *
311      * @return this tuple output object.
312      */

313     public final TupleOutput writeSortedFloat(float val) {
314
315         int intVal = Float.floatToIntBits(val);
316         intVal ^= (intVal < 0) ? 0xffffffff : 0x80000000;
317         writeUnsignedInt(intVal);
318         return this;
319     }
320
321     /**
322      * Writes a signed double (eight byte) value to the buffer, with support
323      * for correct default sorting of all values.
324      * Writes values that can be read using {@link TupleInput#readSortedDouble}.
325      *
326      * <p><code>Float.doubleToLongBits</code> and the following bit
327      * manipulations are used to convert the signed double value to a
328      * representation that is sorted correctly by default.</p>
329      * <pre>
330      * long longVal = Double.doubleToLongBits(val);
331      * longVal ^= (longVal &lt; 0) ? 0xffffffffffffffffL : 0x8000000000000000L;
332      * </pre>
333      *
334      * @param val is the value to write to the buffer.
335      *
336      * @return this tuple output object.
337      */

338     public final TupleOutput writeSortedDouble(double val) {
339
340         long longVal = Double.doubleToLongBits(val);
341         longVal ^= (longVal < 0) ? 0xffffffffffffffffL : 0x8000000000000000L;
342         writeUnsignedLong(longVal);
343         return this;
344     }
345
346     // --- end DataOutput compatible methods ---
347

348     /**
349      * Writes the specified bytes to the buffer, converting each character to
350      * an unsigned byte value.
351      * Writes values that can be read using {@link TupleInput#readBytes}.
352      * Only characters with values below 0x100 may be written using this
353      * method, since the high-order 8 bits of all characters are discarded.
354      *
355      * @param chars is the array of values to be written.
356      *
357      * @return this tuple output object.
358      *
359      * @throws NullPointerException if the chars parameter is null.
360      */

361     public final TupleOutput writeBytes(char[] chars) {
362
363         for (int i = 0; i < chars.length; i++) {
364             writeFast((byte) chars[i]);
365         }
366         return this;
367     }
368
369     /**
370      * Writes the specified characters to the buffer, converting each character
371      * to a two byte unsigned value.
372      * Writes values that can be read using {@link TupleInput#readChars}.
373      *
374      * @param chars is the array of characters to be written.
375      *
376      * @return this tuple output object.
377      *
378      * @throws NullPointerException if the chars parameter is null.
379      */

380     public final TupleOutput writeChars(char[] chars) {
381
382         for (int i = 0; i < chars.length; i++) {
383             writeFast((byte) (chars[i] >>> 8));
384             writeFast((byte) chars[i]);
385         }
386         return this;
387     }
388
389     /**
390      * Writes the specified characters to the buffer, converting each character
391      * to UTF format.
392      * Note that zero (0x0000) character values are encoded as non-zero values.
393      * Writes values that can be read using {@link TupleInput#readString(int)}
394      * or {@link TupleInput#readString(char[])}.
395      *
396      * @param chars is the array of characters to be written.
397      *
398      * @return this tuple output object.
399      *
400      * @throws NullPointerException if the chars parameter is null.
401      */

402     public final TupleOutput writeString(char[] chars) {
403
404         if (chars.length == 0) return this;
405
406         int utfLength = UtfOps.getByteLength(chars);
407
408         makeSpace(utfLength);
409         UtfOps.charsToBytes(chars, 0, getBufferBytes(), getBufferLength(),
410                             chars.length);
411         addSize(utfLength);
412         return this;
413     }
414
415     /**
416      * Writes an unsigned byte (one byte) value to the buffer.
417      * Writes values that can be read using {@link
418      * TupleInput#readUnsignedByte}.
419      *
420      * @param val is the value to write to the buffer.
421      *
422      * @return this tuple output object.
423      */

424     public final TupleOutput writeUnsignedByte(int val) {
425
426         writeFast(val);
427         return this;
428     }
429
430     /**
431      * Writes an unsigned short (two byte) value to the buffer.
432      * Writes values that can be read using {@link
433      * TupleInput#readUnsignedShort}.
434      *
435      * @param val is the value to write to the buffer.
436      *
437      * @return this tuple output object.
438      */

439     public final TupleOutput writeUnsignedShort(int val) {
440
441         writeFast((byte) (val >>> 8));
442         writeFast((byte) val);
443         return this;
444     }
445
446     /**
447      * Writes an unsigned int (four byte) value to the buffer.
448      * Writes values that can be read using {@link
449      * TupleInput#readUnsignedInt}.
450      *
451      * @param val is the value to write to the buffer.
452      *
453      * @return this tuple output object.
454      */

455     public final TupleOutput writeUnsignedInt(long val) {
456
457         writeFast((byte) (val >>> 24));
458         writeFast((byte) (val >>> 16));
459         writeFast((byte) (val >>> 8));
460         writeFast((byte) val);
461         return this;
462     }
463
464     /**
465      * This method is private since an unsigned long cannot be treated as
466      * such in Java, nor converted to a BigInteger of the same value.
467      */

468     private final TupleOutput writeUnsignedLong(long val) {
469
470         writeFast((byte) (val >>> 56));
471         writeFast((byte) (val >>> 48));
472         writeFast((byte) (val >>> 40));
473         writeFast((byte) (val >>> 32));
474         writeFast((byte) (val >>> 24));
475         writeFast((byte) (val >>> 16));
476         writeFast((byte) (val >>> 8));
477         writeFast((byte) val);
478         return this;
479     }
480
481     /**
482      * Writes a packed integer. Note that packed integers are not appropriate
483      * for sorted values (keys) unless a custom comparator is used.
484      *
485      * @see PackedInteger
486      */

487     public final void writePackedInt(int val) {
488
489         makeSpace(PackedInteger.MAX_LENGTH);
490
491         int oldLen = getBufferLength();
492         int newLen = PackedInteger.writeInt(getBufferBytes(), oldLen, val);
493
494         addSize(newLen - oldLen);
495     }
496
497     /**
498      * Writes a {@code BigInteger}. Supported {@code BigInteger} values are
499      * limited to those with a byte array ({@link BigInteger#toByteArray})
500      * representation with a size of 0x7fff bytes or less. The maximum {@code
501      * BigInteger} value is (2<sup>0x3fff7</sup> - 1) and the minimum value is
502      * (-2<sup>0x3fff7</sup>).
503      *
504      * <p>The byte format for a {@code BigInteger} value is:</p>
505      * <ul>
506      * <li>Byte 0 and 1: The length of the following bytes, negated if the
507      * {@code BigInteger} value is negative, and written as a sorted value as
508      * if {@link #writeShort} were called.</li>
509      * <li>Byte 2: The first byte of the {@link BigInteger#toByteArray} array,
510      * written as a sorted value as if {@link #writeByte} were called.</li>
511      * <li>Byte 3 to N: The second and remaining bytes, if any, of the {@link
512      * BigInteger#toByteArray} array, written without modification.</li>
513      * </ul>
514      * <p>This format provides correct default sorting when the default
515      * byte-by-byte comparison is used.</p>
516      *
517      * @throws NullPointerException if val is null.
518      *
519      * @throws IllegalArgumentException if the byte array representation of val
520      * is larger than 0x7fff bytes.
521      */

522     public final TupleOutput writeBigInteger(BigInteger JavaDoc val) {
523         byte[] a = val.toByteArray();
524         if (a.length > Short.MAX_VALUE) {
525             throw new IllegalArgumentException JavaDoc
526                 ("BigInteger byte array is larger than 0x7fff bytes");
527         }
528         int firstByte = a[0];
529         writeShort((firstByte < 0) ? (- a.length) : a.length);
530         writeByte(firstByte);
531         writeFast(a, 1, a.length - 1);
532         return this;
533     }
534
535     /**
536      * Returns the byte length of a given {@code BigInteger} value.
537      *
538      * @see TupleOutput#writeBigInteger
539      */

540     public static int getBigIntegerByteLength(BigInteger JavaDoc val) {
541         return 2 /* length bytes */ +
542                (val.bitLength() + 1 /* sign bit */ + 7 /* round up */) / 8;
543     }
544 }
545
Popular Tags