001: /*
002:
003: Derby - Class org.apache.derby.iapi.services.io.CompressedNumber
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.iapi.services.io;
023:
024: import org.apache.derby.iapi.services.sanity.SanityManager;
025:
026: import java.io.*;
027:
028: /**
029: Static methods to write and read compressed forms of numbers
030: to DataOut and DataIn interfaces. Format written is platform
031: independent like the Data* interfaces and must remain fixed
032: once a product is shipped. If a different format is required
033: then write a new set of methods, e.g. writeInt2. The formats
034: defined by stored format identifiers are implicitly dependent
035: on these formats not changing.
036: */
037:
038: public abstract class CompressedNumber {
039:
040: // the maximum number of bytes written out for an int
041: public static final int MAX_INT_STORED_SIZE = 4;
042:
043: // the maximum number of bytes written out for a long
044: public static final int MAX_LONG_STORED_SIZE = 8;
045:
046: // largest int stored compressed in 1 byte
047: public static final int MAX_COMPRESSED_INT_ONE_BYTE = 0x3f;
048:
049: // largest int stored compressed in 2 bytes
050: public static final int MAX_COMPRESSED_INT_TWO_BYTES = 0x3fff;
051:
052: /**
053: Write a compressed integer only supporting signed values.
054: Formats are (with x representing value bits):
055: <PRE>
056: 1 Byte - 00xxxxxx Represents the value <= 63 (0x3f)
057: 2 Byte - 01xxxxxx xxxxxxxx Represents the value > 63 && <= 16383 (0x3fff)
058: 4 byte - 1xxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx Represents the value > 16383 && <= MAX_INT
059: </PRE>
060:
061:
062: @exception IOException value is negative or an exception was thrown by a method on out.
063: */
064: public static final int writeInt(DataOutput out, int value)
065: throws IOException {
066:
067: if (value < 0)
068: throw new IOException();
069:
070: if (value <= 0x3f) {
071:
072: out.writeByte(value);
073: return 1;
074: }
075:
076: if (value <= 0x3fff) {
077:
078: out.writeByte(0x40 | (value >>> 8));
079: out.writeByte(value & 0xff);
080: return 2;
081: }
082:
083: out.writeByte(((value >>> 24) | 0x80) & 0xff);
084: out.writeByte((value >>> 16) & 0xff);
085: out.writeByte((value >>> 8) & 0xff);
086: out.writeByte((value) & 0xff);
087: return 4;
088: }
089:
090: /**
091: Write a compressed integer directly to an OutputStream.
092: @exception IOException an exception was thrown by a method on in.
093: */
094: public static final int writeInt(OutputStream out, int value)
095: throws IOException {
096:
097: if (value < 0)
098: throw new IOException();
099:
100: if (value <= 0x3f) {
101:
102: out.write(value);
103: return 1;
104: }
105:
106: if (value <= 0x3fff) {
107:
108: out.write(0x40 | (value >>> 8));
109: out.write(value & 0xff);
110: return 2;
111: }
112:
113: out.write(((value >>> 24) | 0x80) & 0xff);
114: out.write((value >>> 16) & 0xff);
115: out.write((value >>> 8) & 0xff);
116: out.write((value) & 0xff);
117: return 4;
118: }
119:
120: /**
121: Read an integer previously written by writeInt().
122:
123: @exception IOException an exception was thrown by a method on in.
124: */
125: public static final int readInt(DataInput in) throws IOException {
126:
127: int value = in.readUnsignedByte();
128:
129: if ((value & ~0x3f) == 0) {
130: // length is stored in this byte, we also know that the 0x80 bit
131: // was not set, so no need to mask off the sign extension from
132: // the byte to int conversion.
133:
134: // account for 1 byte stored length of field + 1 for all returns
135: return (value);
136: } else if ((value & 0x80) == 0) {
137: // length is stored in 2 bytes. only use low 6 bits from 1st byte.
138:
139: if (SanityManager.DEBUG) {
140: SanityManager.ASSERT((value & 0x40) == 0x40);
141: }
142:
143: // top 8 bits of 2 byte length is stored in this byte, we also
144: // know that the 0x80 bit was not set, so no need to mask off the
145: // sign extension from the 1st byte to int conversion. Need to
146: // mask the byte in data[offset + 1] to account for possible sign
147: // extension.
148:
149: return (((value & 0x3f) << 8) | in.readUnsignedByte());
150: } else {
151: // length is stored in 4 bytes. only use low 7 bits from 1st byte.
152:
153: if (SanityManager.DEBUG) {
154: SanityManager.ASSERT((value & 0x80) == 0x80);
155: }
156:
157: // top 8 bits of 4 byte length is stored in this byte, we also
158: // know that the 0x80 bit was set, so need to mask off the
159: // sign extension from the 1st byte to int conversion. Need to
160: // mask the bytes from the next 3 bytes data[offset + 1,2,3] to
161: // account for possible sign extension.
162: //
163: return (((value & 0x7f) << 24)
164: | (in.readUnsignedByte() << 16)
165: | (in.readUnsignedByte() << 8) | (in
166: .readUnsignedByte()));
167: }
168: }
169:
170: /**
171: Read an integer previously written by writeInt().
172:
173: @exception IOException an exception was thrown by a method on in.
174: */
175: public static final int readInt(InputStream in) throws IOException {
176:
177: int value = InputStreamUtil.readUnsignedByte(in);
178:
179: if ((value & ~0x3f) == 0) {
180: return (value);
181: } else if ((value & 0x80) == 0) {
182: return (((value & 0x3f) << 8) | InputStreamUtil
183: .readUnsignedByte(in));
184: } else {
185: return (((value & 0x7f) << 24)
186: | (InputStreamUtil.readUnsignedByte(in) << 16)
187: | (InputStreamUtil.readUnsignedByte(in) << 8) | (InputStreamUtil
188: .readUnsignedByte(in)));
189: }
190: }
191:
192: public static final int readInt(byte[] data, int offset) {
193: int value = data[offset++];
194:
195: if ((value & ~0x3f) == 0) {
196: // length is stored in this byte, we also know that the 0x80 bit
197: // was not set, so no need to mask off the sign extension from
198: // the byte to int conversion.
199:
200: return (value);
201: } else if ((value & 0x80) == 0) {
202: // length is stored in 2 bytes. only use low 6 bits from 1st byte.
203:
204: if (SanityManager.DEBUG) {
205: SanityManager.ASSERT((value & 0x40) == 0x40);
206: }
207:
208: // top 8 bits of 2 byte length is stored in this byte, we also
209: // know that the 0x80 bit was not set, so no need to mask off the
210: // sign extension from the 1st byte to int conversion. Need to
211: // mask the byte in data[offset + 1] to account for possible sign
212: // extension.
213:
214: return (((value & 0x3f) << 8) | (data[offset] & 0xff));
215: } else {
216: // length is stored in 4 bytes. only use low 7 bits from 1st byte.
217:
218: if (SanityManager.DEBUG) {
219: SanityManager.ASSERT((value & 0x80) == 0x80);
220: }
221:
222: // top 8 bits of 4 byte length is stored in this byte, we also
223: // know that the 0x80 bit was set, so need to mask off the
224: // sign extension from the 1st byte to int conversion. Need to
225: // mask the bytes from the next 3 bytes data[offset + 1,2,3] to
226: // account for possible sign extension.
227: //
228: return (((value & 0x7f) << 24)
229: | ((data[offset++] & 0xff) << 16)
230: | ((data[offset++] & 0xff) << 8) | ((data[offset] & 0xff)));
231: }
232: }
233:
234: /**
235: * Return the compressed Int value + stored size of the length + 1
236: * <p>
237: * Given offset in array to beginning of compressed int, return the
238: * value of the compressed int + the number of bytes used to store the
239: * length.
240: * <p>
241: * So 1 byte lengths will return: length + 1 + 1
242: * So 2 byte lengths will return: length + 2 + 1
243: * So 4 byte lengths will return: length + 4 + 1
244: * <p>
245: * Note that this routine will not work for lengths MAX_INT - (MAX_INT - 5).
246: * <p>
247: * This routine is currently used by the StorePage code to skip fields
248: * as efficiently as possible. Since the page size is less than
249: * (MAX_INT - 5) it is all right to use this routine.
250: *
251: * @return compressed int value + length used to store the length.
252: *
253: * @param data byte array containing the field.
254: * @param offset offset to beginning of field, ie. data[offset] contains
255: * 1st byte of the compressed int.
256: **/
257: public static final int readIntAndReturnIntPlusOverhead(
258: byte[] data, int offset) {
259: int value = data[offset];
260:
261: if ((value & ~0x3f) == 0) {
262: // length is stored in this byte, we also know that the 0x80 bit
263: // was not set, so no need to mask off the sign extension from
264: // the byte to int conversion.
265:
266: // account for 1 byte stored length of field + 1 for all returns
267: return (value + 2);
268: } else if ((value & 0x80) == 0) {
269: // length is stored in 2 bytes. only use low 6 bits from 1st byte.
270:
271: if (SanityManager.DEBUG) {
272: SanityManager.ASSERT((value & 0x40) == 0x40);
273: }
274:
275: // top 8 bits of 2 byte length is stored in this byte, we also
276: // know that the 0x80 bit was not set, so no need to mask off the
277: // sign extension from the 1st byte to int conversion. Need to
278: // mask the byte in data[offset + 1] to account for possible sign
279: // extension.
280:
281: // add 3 to account for 2 byte length + 1 added to all returns
282:
283: return ((((value & 0x3f) << 8) | (data[offset + 1] & 0xff)) + 3);
284: } else {
285: // length is stored in 4 bytes. only use low 7 bits from 1st byte.
286:
287: if (SanityManager.DEBUG) {
288: SanityManager.ASSERT((value & 0x80) == 0x80);
289: }
290:
291: // top 8 bits of 4 byte length is stored in this byte, we also
292: // know that the 0x80 bit was set, so need to mask off the
293: // sign extension from the 1st byte to int conversion. Need to
294: // mask the bytes from the next 3 bytes data[offset + 1,2,3] to
295: // account for possible sign extension.
296:
297: // add 5 to account for 4 byte length + 1 added to all returns
298: return ((((value & 0x7f) << 24)
299: | ((data[offset + 1] & 0xff) << 16)
300: | ((data[offset + 2] & 0xff) << 8) | (data[offset + 3] & 0xff)) + 5);
301: }
302: }
303:
304: /**
305: Skip an integer previously written by writeInt().
306:
307: @exception IOException an exception was thrown by a method on in.
308: */
309: public static final int skipInt(DataInput in) throws IOException {
310:
311: int value = in.readUnsignedByte();
312:
313: if ((value & 0x80) == 0x80) {
314: in.skipBytes(3);
315: return 4;
316: }
317:
318: if ((value & 0x40) == 0x40) {
319: in.skipBytes(1);
320: return 2;
321: }
322:
323: return 1;
324: }
325:
326: /**
327: Skip an integer previously written by writeInt().
328:
329: @exception IOException an exception was thrown by a method on in.
330: */
331: public static final int skipInt(InputStream in) throws IOException {
332:
333: int value = InputStreamUtil.readUnsignedByte(in);
334:
335: int skipBytes = 0;
336:
337: if ((value & 0x80) == 0x80) {
338: skipBytes = 3;
339: } else if ((value & 0x40) == 0x40) {
340: skipBytes = 1;
341: }
342:
343: if (skipBytes != 0) {
344: if (in.skip(skipBytes) != skipBytes)
345: throw new EOFException();
346: }
347:
348: return skipBytes + 1;
349: }
350:
351: /**
352: Return the number of bytes that would be written by a writeInt call
353: */
354: public static final int sizeInt(int value) {
355: if (value <= 0x3f) {
356: return 1;
357: }
358: if (value <= 0x3fff) {
359: return 2;
360: }
361: return 4;
362: }
363:
364: /**
365: Write a compressed long only supporting signed values.
366:
367: Formats are (with x representing value bits):
368: <PRE>
369: 2 byte - 00xxxxxx xxxxxxxx Represents the value <= 16383 (0x3fff)
370: 4 byte - 01xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx Represents the value > 16383 && <= 0x3fffffff
371: 8 byte - 1xxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx Represents the value > 0x3fffffff && <= MAX_LONG
372: </PRE>
373:
374:
375: @exception IOException value is negative or an exception was thrown by a method on out.
376: */
377: public static final int writeLong(DataOutput out, long value)
378: throws IOException {
379:
380: if (value < 0)
381: throw new IOException();
382:
383: if (value <= 0x3fff) {
384:
385: out.writeByte((int) ((value >>> 8) & 0xff));
386: out.writeByte((int) ((value) & 0xff));
387: return 2;
388: }
389:
390: if (value <= 0x3fffffff) {
391:
392: out.writeByte((int) (((value >>> 24) | 0x40) & 0xff));
393: out.writeByte((int) ((value >>> 16) & 0xff));
394: out.writeByte((int) ((value >>> 8) & 0xff));
395: out.writeByte((int) ((value) & 0xff));
396: return 4;
397: }
398:
399: out.writeByte((int) (((value >>> 56) | 0x80) & 0xff));
400: out.writeByte((int) ((value >>> 48) & 0xff));
401: out.writeByte((int) ((value >>> 40) & 0xff));
402: out.writeByte((int) ((value >>> 32) & 0xff));
403: out.writeByte((int) ((value >>> 24) & 0xff));
404: out.writeByte((int) ((value >>> 16) & 0xff));
405: out.writeByte((int) ((value >>> 8) & 0xff));
406: out.writeByte((int) ((value) & 0xff));
407: return 8;
408: }
409:
410: /**
411: Write a compressed integer only supporting signed values.
412:
413: @exception IOException value is negative or an exception was thrown by a method on out.
414: */
415: public static final int writeLong(OutputStream out, long value)
416: throws IOException {
417:
418: if (value < 0)
419: throw new IOException();
420:
421: if (value <= 0x3fff) {
422:
423: out.write((int) ((value >>> 8) & 0xff));
424: out.write((int) ((value) & 0xff));
425: return 2;
426: }
427:
428: if (value <= 0x3fffffff) {
429:
430: out.write((int) (((value >>> 24) | 0x40) & 0xff));
431: out.write((int) ((value >>> 16) & 0xff));
432: out.write((int) ((value >>> 8) & 0xff));
433: out.write((int) ((value) & 0xff));
434: return 4;
435: }
436:
437: out.write((int) (((value >>> 56) | 0x80) & 0xff));
438: out.write((int) ((value >>> 48) & 0xff));
439: out.write((int) ((value >>> 40) & 0xff));
440: out.write((int) ((value >>> 32) & 0xff));
441: out.write((int) ((value >>> 24) & 0xff));
442: out.write((int) ((value >>> 16) & 0xff));
443: out.write((int) ((value >>> 8) & 0xff));
444: out.write((int) ((value) & 0xff));
445: return 8;
446: }
447:
448: /**
449: Read a long previously written by writeLong().
450:
451: @exception IOException an exception was thrown by a method on in.
452: */
453: public static final long readLong(DataInput in) throws IOException {
454:
455: int int_value = in.readUnsignedByte();
456:
457: if ((int_value & ~0x3f) == 0) {
458: // test for small case first - assuming this is usual case.
459: // this is stored in 2 bytes.
460:
461: return ((int_value << 8) | in.readUnsignedByte());
462: } else if ((int_value & 0x80) == 0) {
463: // value is stored in 4 bytes. only use low 6 bits from 1st byte.
464:
465: return (((int_value & 0x3f) << 24)
466: | (in.readUnsignedByte() << 16)
467: | (in.readUnsignedByte() << 8) | (in
468: .readUnsignedByte()));
469: } else {
470: // value is stored in 8 bytes. only use low 7 bits from 1st byte.
471: return ((((long) (int_value & 0x7f)) << 56)
472: | (((long) in.readUnsignedByte()) << 48)
473: | (((long) in.readUnsignedByte()) << 40)
474: | (((long) in.readUnsignedByte()) << 32)
475: | (((long) in.readUnsignedByte()) << 24)
476: | (((long) in.readUnsignedByte()) << 16)
477: | (((long) in.readUnsignedByte()) << 8) | (((long) in
478: .readUnsignedByte())));
479: }
480: }
481:
482: /**
483: Read a long previously written by writeLong().
484:
485: @exception IOException an exception was thrown by a method on in.
486: */
487: public static final long readLong(InputStream in)
488: throws IOException {
489:
490: int int_value = InputStreamUtil.readUnsignedByte(in);
491:
492: if ((int_value & ~0x3f) == 0) {
493: // test for small case first - assuming this is usual case.
494: // this is stored in 2 bytes.
495:
496: return ((int_value << 8) | InputStreamUtil
497: .readUnsignedByte(in));
498: } else if ((int_value & 0x80) == 0) {
499: // value is stored in 4 bytes. only use low 6 bits from 1st byte.
500:
501: return (((int_value & 0x3f) << 24)
502: | (InputStreamUtil.readUnsignedByte(in) << 16)
503: | (InputStreamUtil.readUnsignedByte(in) << 8) | (InputStreamUtil
504: .readUnsignedByte(in)));
505:
506: } else {
507: // value is stored in 8 bytes. only use low 7 bits from 1st byte.
508: long value = int_value;
509:
510: return ((((long) (value & 0x7f)) << 56)
511: | (((long) InputStreamUtil.readUnsignedByte(in)) << 48)
512: | (((long) InputStreamUtil.readUnsignedByte(in)) << 40)
513: | (((long) InputStreamUtil.readUnsignedByte(in)) << 32)
514: | (((long) InputStreamUtil.readUnsignedByte(in)) << 24)
515: | (((long) InputStreamUtil.readUnsignedByte(in)) << 16)
516: | (((long) InputStreamUtil.readUnsignedByte(in)) << 8) | (((long) InputStreamUtil
517: .readUnsignedByte(in))));
518: }
519: }
520:
521: public static final long readLong(byte[] data, int offset) {
522: int int_value = data[offset++];
523:
524: if ((int_value & ~0x3f) == 0) {
525: // test for small case first - assuming this is usual case.
526: // this is stored in 2 bytes.
527:
528: return ((int_value << 8) | (data[offset] & 0xff));
529: } else if ((int_value & 0x80) == 0) {
530: // value is stored in 4 bytes. only use low 6 bits from 1st byte.
531:
532: return (((int_value & 0x3f) << 24)
533: | ((data[offset++] & 0xff) << 16)
534: | ((data[offset++] & 0xff) << 8) | ((data[offset] & 0xff)));
535:
536: } else {
537: // value is stored in 8 bytes. only use low 6 bits from 1st byte.
538: return ((((long) (int_value & 0x7f)) << 56)
539: | (((long) (data[offset++] & 0xff)) << 48)
540: | (((long) (data[offset++] & 0xff)) << 40)
541: | (((long) (data[offset++] & 0xff)) << 32)
542: | (((long) (data[offset++] & 0xff)) << 24)
543: | (((long) (data[offset++] & 0xff)) << 16)
544: | (((long) (data[offset++] & 0xff)) << 8) | (((long) (data[offset] & 0xff))));
545:
546: }
547: }
548:
549: /**
550: Skip a long previously written by writeLong().
551:
552: @exception IOException an exception was thrown by a method on in.
553: */
554: public static final int skipLong(DataInput in) throws IOException {
555:
556: long value = in.readUnsignedByte();
557:
558: if ((value & 0x80) == 0x80) {
559: in.skipBytes(7);
560: return 8;
561: }
562:
563: if ((value & 0x40) == 0x40) {
564: in.skipBytes(3);
565: return 4;
566:
567: }
568:
569: in.skipBytes(1);
570: return 2;
571: }
572:
573: /**
574: Skip a long previously written by writeLong().
575:
576: @exception IOException an exception was thrown by a method on in.
577: */
578: public static final int skipLong(InputStream in) throws IOException {
579:
580: int value = InputStreamUtil.readUnsignedByte(in);
581:
582: int skipBytes;
583:
584: if ((value & 0x80) == 0x80) {
585: skipBytes = 7;
586: } else if ((value & 0x40) == 0x40) {
587: skipBytes = 3;
588: } else
589: skipBytes = 1;
590:
591: if (in.skip(skipBytes) != skipBytes)
592: throw new EOFException();
593:
594: return skipBytes + 1;
595: }
596:
597: public static final int sizeLong(long value) {
598:
599: if (value <= 0x3fff) {
600:
601: return 2;
602: }
603:
604: if (value <= 0x3fffffff) {
605: return 4;
606: }
607:
608: return 8;
609: }
610:
611: // /* FOR TESTING
612: // *****************************************************
613:
614: private static byte[] holder = new byte[8];
615: private static ArrayOutputStream aos = new ArrayOutputStream(holder);
616: private static DataOutput out = new DataOutputStream(aos);
617:
618: private static ArrayInputStream ais = new ArrayInputStream(holder);
619: private static DataInput in = new DataInputStream(ais);
620: private static InputStream in_stream = ais;
621:
622: private static short checkInt(int i, short oldLength)
623: throws IOException {
624:
625: aos.setPosition(0);
626: int length = CompressedNumber.writeInt(out, i);
627: if (length != oldLength) {
628: System.out
629: .println("changing length to " + length
630: + " at value " + i + " 0x"
631: + Integer.toHexString(i));
632:
633: oldLength = (short) length;
634: }
635:
636: int writtenBytes = aos.getPosition();
637: if (writtenBytes != length) {
638: System.out.println("MISMATCH written bytes expected "
639: + length + " got " + writtenBytes);
640: System.exit(1);
641: }
642:
643: if (length != CompressedNumber.sizeInt(i)) {
644: System.out.println("MISMATCH sizeInt() bytes expected "
645: + length + " got " + CompressedNumber.sizeInt(i));
646: System.exit(1);
647: }
648:
649: ais.setPosition(0);
650: int value = CompressedNumber.readInt(in);
651: if (value != i) {
652: System.out
653: .println("MISMATCH value readInt(DataInput) expected "
654: + i + " got " + value);
655: System.exit(1);
656: }
657:
658: ais.setPosition(0);
659: value = ais.readCompressedInt();
660: if (value != i) {
661: System.out
662: .println("MISMATCH value readInt(DataInput) expected "
663: + i + " got " + value);
664: System.exit(1);
665: }
666:
667: ais.setPosition(0);
668: value = CompressedNumber.readInt(in_stream);
669: if (value != i) {
670: System.out
671: .println("MISMATCH value in readInt(InputStream) expected "
672: + i + " got " + value);
673: System.exit(1);
674: }
675:
676: value = CompressedNumber.readInt(holder, 0);
677: if (value != i) {
678: System.out
679: .println("MISMATCH frome readInt(byte[], offset) value expected "
680: + i + " got " + value);
681: System.exit(1);
682: }
683:
684: ais.setPosition(0);
685: int skipLength = CompressedNumber.skipInt(in);
686: if (skipLength != length) {
687: System.out.println("MISMATCH skip length expected "
688: + length + " got " + skipLength);
689: System.exit(1);
690: }
691:
692: int value_plus_int_length = readIntAndReturnIntPlusOverhead(
693: holder, 0);
694: if (value_plus_int_length != (length + i + 1)) {
695: System.out
696: .println("MISMATCH readIntAndReturnIntPlusOverhead() return expected "
697: + (length + i)
698: + " got "
699: + value_plus_int_length);
700: System.exit(1);
701: }
702:
703: int skipPosition = ais.getPosition();
704: if (skipPosition != length) {
705: System.out.println("MISMATCH skip position expected "
706: + length + " got " + skipPosition);
707: System.exit(1);
708: }
709:
710: return oldLength;
711: }
712:
713: private static short checkLong(long i, short oldLength)
714: throws IOException {
715:
716: aos.setPosition(0);
717: int length = CompressedNumber.writeLong(out, i);
718: if (length != oldLength) {
719: System.out.println("changing length to " + length
720: + " at value " + i + " 0x" + Long.toHexString(i));
721: oldLength = (short) length;
722: }
723:
724: int writtenBytes = aos.getPosition();
725: if (writtenBytes != length) {
726: System.out.println("MISMATCH written bytes expected "
727: + length + " got " + writtenBytes);
728: System.exit(1);
729: }
730:
731: if (length != CompressedNumber.sizeLong(i)) {
732: System.out.println("MISMATCH sizeLong() bytes expected "
733: + length + " got " + CompressedNumber.sizeLong(i));
734: System.exit(1);
735: }
736:
737: long value = CompressedNumber.readLong(holder, 0);
738: if (value != i) {
739: for (int j = 0; j < 8; j++) {
740:
741: System.out
742: .println(Integer.toHexString((int) holder[j]));
743: }
744:
745: System.out
746: .println("MISMATCH in readLong(byte[], offset) value expected "
747: + Long.toHexString(i) + " got " + value);
748: System.exit(1);
749: }
750:
751: ais.setPosition(0);
752: value = CompressedNumber.readLong(in_stream);
753: if (value != i) {
754: for (int j = 0; j < 8; j++) {
755:
756: System.out
757: .println(Integer.toHexString((int) holder[j]));
758: }
759: System.out
760: .println("MISMATCH value in readLong(InputStream) expected "
761: + Long.toHexString(i) + " got " + value);
762: System.exit(1);
763: }
764:
765: ais.setPosition(0);
766: value = ais.readCompressedLong();
767: if (value != i) {
768: for (int j = 0; j < 8; j++) {
769:
770: System.out
771: .println(Integer.toHexString((int) holder[j]));
772: }
773: System.out
774: .println("MISMATCH value in readLong(InputStream) expected "
775: + Long.toHexString(i) + " got " + value);
776: System.exit(1);
777: }
778:
779: ais.setPosition(0);
780: value = CompressedNumber.readLong(in);
781: if (value != i) {
782: for (int j = 0; j < 8; j++) {
783:
784: System.out
785: .println(Integer.toHexString((int) holder[j]));
786: }
787: System.out
788: .println("MISMATCH value in readLong(DataInput) expected "
789: + Long.toHexString(i) + " got " + value);
790: System.exit(1);
791: }
792:
793: ais.setPosition(0);
794: int skipLength = CompressedNumber.skipLong(in);
795: if (skipLength != length) {
796: System.out.println("MISMATCH skip length expected "
797: + length + " got " + skipLength);
798: System.exit(1);
799: }
800:
801: int skipPosition = ais.getPosition();
802: if (skipPosition != length) {
803: System.out.println("MISMATCH skip position expected "
804: + length + " got " + skipPosition);
805: System.exit(1);
806: }
807:
808: return oldLength;
809: }
810:
811: public static void main(String[] args) throws IOException {
812:
813: short oldLength = -1;
814:
815: System.out.println("** Testing Int");
816:
817: oldLength = checkInt(0, oldLength);
818: oldLength = checkInt(1, oldLength);
819: oldLength = checkInt(2, oldLength);
820:
821: oldLength = checkInt(0x3f - 4, oldLength);
822: oldLength = checkInt(0x3f - 3, oldLength);
823: oldLength = checkInt(0x3f - 2, oldLength);
824: oldLength = checkInt(0x3f - 1, oldLength);
825: oldLength = checkInt(0x3f, oldLength);
826: oldLength = checkInt(0x3f + 1, oldLength);
827: oldLength = checkInt(0x3f + 2, oldLength);
828: oldLength = checkInt(0x3f + 3, oldLength);
829: oldLength = checkInt(0x3f + 4, oldLength);
830:
831: oldLength = checkInt(0x3f80 - 4, oldLength);
832: oldLength = checkInt(0x3f80 - 3, oldLength);
833: oldLength = checkInt(0x3f80 - 2, oldLength);
834: oldLength = checkInt(0x3f80 - 1, oldLength);
835: oldLength = checkInt(0x3f80, oldLength);
836: oldLength = checkInt(0x3f80 + 1, oldLength);
837: oldLength = checkInt(0x3f80 + 2, oldLength);
838: oldLength = checkInt(0x3f80 + 3, oldLength);
839: oldLength = checkInt(0x3f80 + 4, oldLength);
840:
841: oldLength = checkInt(0x3fff - 4, oldLength);
842: oldLength = checkInt(0x3fff - 3, oldLength);
843: oldLength = checkInt(0x3fff - 2, oldLength);
844: oldLength = checkInt(0x3fff - 1, oldLength);
845: oldLength = checkInt(0x3fff, oldLength);
846: oldLength = checkInt(0x3fff + 1, oldLength);
847: oldLength = checkInt(0x3fff + 2, oldLength);
848: oldLength = checkInt(0x3fff + 3, oldLength);
849: oldLength = checkInt(0x3fff + 4, oldLength);
850:
851: oldLength = checkInt(Integer.MAX_VALUE - 4, oldLength);
852: oldLength = checkInt(Integer.MAX_VALUE - 3, oldLength);
853: oldLength = checkInt(Integer.MAX_VALUE - 2, oldLength);
854: oldLength = checkInt(Integer.MAX_VALUE - 1, oldLength);
855: oldLength = checkInt(Integer.MAX_VALUE, oldLength);
856:
857: oldLength = -1;
858: for (int i = 0; i < 0xf0000; i++) {
859: oldLength = checkInt(i, oldLength);
860: }
861:
862: // takes 30 minutes to run.
863: //
864: // for (int i = 0; i < Integer.MAX_VALUE; i++)
865: // {
866: // if (i % 0x00800000 == 0)
867: // System.out.println("checking: " + i);
868: //
869: // oldLength = checkInt(i, oldLength);
870: // }
871:
872: System.out.println("** Testing Long");
873:
874: oldLength = -1;
875: for (int i = 0; i < 0xf0000; i++) {
876: oldLength = checkLong(i, oldLength);
877: }
878:
879: oldLength = -1;
880:
881: oldLength = checkLong(0, oldLength);
882: oldLength = checkLong(1, oldLength);
883: oldLength = checkLong(2, oldLength);
884:
885: oldLength = checkLong(0x3fff - 2, oldLength);
886: oldLength = checkLong(0x3fff - 1, oldLength);
887: oldLength = checkLong(0x3fff, oldLength);
888: oldLength = checkLong(0x3fff + 1, oldLength);
889: oldLength = checkLong(0x3fff + 2, oldLength);
890:
891: oldLength = checkLong(0x3fffffff - 4, oldLength);
892: oldLength = checkLong(0x3fffffff - 3, oldLength);
893: oldLength = checkLong(0x3fffffff - 2, oldLength);
894: oldLength = checkLong(0x3fffffff - 1, oldLength);
895: oldLength = checkLong(0x3fffffff, oldLength);
896: oldLength = checkLong(0x3fffffff + 1, oldLength);
897: oldLength = checkLong(0x3fffffff + 2, oldLength);
898: oldLength = checkLong(0x3fffffff + 3, oldLength);
899: oldLength = checkLong(0x3fffffff + 4, oldLength);
900:
901: oldLength = checkLong(0x70000000 - 2, oldLength);
902: oldLength = checkLong(0x70000000 - 1, oldLength);
903: oldLength = checkLong(0x70000000, oldLength);
904: oldLength = checkLong(0x70000000 + 1, oldLength);
905: oldLength = checkLong(0x70000000 + 2, oldLength);
906:
907: oldLength = checkLong(Long.MAX_VALUE - 2, oldLength);
908: oldLength = checkLong(Long.MAX_VALUE - 1, oldLength);
909: oldLength = checkLong(Long.MAX_VALUE, oldLength);
910:
911: }
912: // ********************************************************/
913: }
|