1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2000,2008 Oracle. All rights reserved. 5 * 6 * $Id: TupleOutput.java,v 12.7 2008/01/08 20:58:36 bostic Exp $ 7 */ 8 9package com.sleepycat.bind.tuple; 10 11import java.math.BigInteger; 12 13import com.sleepycat.util.FastOutputStream; 14import com.sleepycat.util.PackedInteger; 15import 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 */ 76public 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 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 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 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 < 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 < 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 packed long integer. Note that packed integers are not 499 * appropriate for sorted values (keys) unless a custom comparator is used. 500 * 501 * @see PackedInteger 502 */ 503 public final void writePackedLong(long val) { 504 505 makeSpace(PackedInteger.MAX_LONG_LENGTH); 506 507 int oldLen = getBufferLength(); 508 int newLen = PackedInteger.writeLong(getBufferBytes(), oldLen, val); 509 510 addSize(newLen - oldLen); 511 } 512 513 /** 514 * Writes a {@code BigInteger}. Supported {@code BigInteger} values are 515 * limited to those with a byte array ({@link BigInteger#toByteArray}) 516 * representation with a size of 0x7fff bytes or less. The maximum {@code 517 * BigInteger} value is (2<sup>0x3fff7</sup> - 1) and the minimum value is 518 * (-2<sup>0x3fff7</sup>). 519 * 520 * <p>The byte format for a {@code BigInteger} value is:</p> 521 * <ul> 522 * <li>Byte 0 and 1: The length of the following bytes, negated if the 523 * {@code BigInteger} value is negative, and written as a sorted value as 524 * if {@link #writeShort} were called.</li> 525 * <li>Byte 2: The first byte of the {@link BigInteger#toByteArray} array, 526 * written as a sorted value as if {@link #writeByte} were called.</li> 527 * <li>Byte 3 to N: The second and remaining bytes, if any, of the {@link 528 * BigInteger#toByteArray} array, written without modification.</li> 529 * </ul> 530 * <p>This format provides correct default sorting when the default 531 * byte-by-byte comparison is used.</p> 532 * 533 * @throws NullPointerException if val is null. 534 * 535 * @throws IllegalArgumentException if the byte array representation of val 536 * is larger than 0x7fff bytes. 537 */ 538 public final TupleOutput writeBigInteger(BigInteger val) { 539 byte[] a = val.toByteArray(); 540 if (a.length > Short.MAX_VALUE) { 541 throw new IllegalArgumentException 542 ("BigInteger byte array is larger than 0x7fff bytes"); 543 } 544 int firstByte = a[0]; 545 writeShort((firstByte < 0) ? (- a.length) : a.length); 546 writeByte(firstByte); 547 writeFast(a, 1, a.length - 1); 548 return this; 549 } 550 551 /** 552 * Returns the byte length of a given {@code BigInteger} value. 553 * 554 * @see TupleOutput#writeBigInteger 555 */ 556 public static int getBigIntegerByteLength(BigInteger val) { 557 return 2 /* length bytes */ + 558 (val.bitLength() + 1 /* sign bit */ + 7 /* round up */) / 8; 559 } 560} 561