/******************************************************************************* * Copyright (c) 2000, 2003 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * MetaMatrix, Inc - repackaging and updates for use as a metadata store *******************************************************************************/ package org.teiid.designer.core.index; import java.io.UTFDataFormatException; /** * @since 8.0 */ public class Field { protected byte[] buffer; // contents protected int offset; // offset of the field within the byte array protected int length; // length of the field /** * ByteSegment constructor comment. */ public Field(byte[] bytes) { this.buffer= bytes; this.offset= 0; this.length= bytes.length; } /** * ByteSegment constructor comment. */ public Field(byte[] bytes, int length) { this.buffer= bytes; this.offset= 0; this.length= length; } /** * ByteSegment constructor comment. */ public Field(byte[] bytes, int offset, int length) { this.buffer= bytes; this.offset= offset; this.length= length; } /** * Creates a new field containing an empty buffer of the given length. */ public Field(int length) { this.buffer= new byte[length]; this.offset= 0; this.length= length; } public byte[] buffer() { return buffer; } public Field buffer(byte[] buffer) { this.buffer= buffer; return this; } public Field clear() { clear(buffer, offset, length); return this; } protected static void clear(byte[] buffer, int offset, int length) { int n= offset; for (int i= 0; i < length; i++) { buffer[n]= 0; n++; } } public Field clear(int length) { clear(buffer, offset, length); return this; } public Field clear(int offset, int length) { clear(buffer, this.offset + offset, length); return this; } protected static int compare(byte[] buffer1, int offset1, int length1, byte[] buffer2, int offset2, int length2) { int n= Math.min(length1, length2); for (int i= 0; i < n; i++) { int j1= buffer1[offset1 + i] & 255; int j2= buffer2[offset2 + i] & 255; if (j1 > j2) return 1; if (j1 < j2) return -1; } if (length1 > n) { for (int i= n; i < length1; i++) if (buffer1[offset1 + i] != 0) return 1; return 0; } for (int i= n; i < length2; i++) if (buffer2[offset2 + i] != 0) return -1; return 0; } public static int compare(Field f1, Field f2) { return compare(f1.buffer, f1.offset, f1.length, f2.buffer, f2.offset, f2.length); } // copy bytes from one offset to another within the field public Field copy(int fromOffset, int toOffset, int length) { System.arraycopy(buffer, offset + fromOffset, buffer, offset + toOffset, length); return this; } public Field dec(int n) { offset -= n; return this; } public byte[] get() { byte[] result= new byte[length]; System.arraycopy(buffer, offset, result, 0, length); return result; } public byte[] get(int offset, int length) { byte[] result= new byte[length]; System.arraycopy(buffer, this.offset + offset, result, 0, length); return result; } public Field getField(int offset, int length) { return new Field(buffer, this.offset + offset, length); } public int getInt1() { return buffer[this.offset]; } public int getInt1(int offset) { return buffer[this.offset + offset]; } public int getInt2() { int i= this.offset; int v= buffer[i++]; v= (v << 8) | (buffer[i++] & 255); return v; } public int getInt2(int offset) { int i= this.offset + offset; int v= buffer[i++]; v= (v << 8) | (buffer[i++] & 255); return v; } public int getInt3() { int i= this.offset; int v= buffer[i++]; v= (v << 8) | (buffer[i++] & 255); v= (v << 8) | (buffer[i++] & 255); return v; } public int getInt3(int offset) { int i= this.offset + offset; int v= buffer[i++]; v= (v << 8) | (buffer[i++] & 255); v= (v << 8) | (buffer[i++] & 255); return v; } public int getInt4() { int i= this.offset; int v= buffer[i++]; v= (v << 8) | (buffer[i++] & 255); v= (v << 8) | (buffer[i++] & 255); v= (v << 8) | (buffer[i++] & 255); return v; } public int getInt4(int offset) { int i= this.offset + offset; int v= buffer[i++]; v= (v << 8) | (buffer[i++] & 255); v= (v << 8) | (buffer[i++] & 255); v= (v << 8) | (buffer[i++] & 255); return v; } public int getUInt1() { return buffer[this.offset] & 255; } public int getUInt1(int offset) { return buffer[this.offset + offset] & 255; } public int getUInt2() { int i= this.offset; int v= (buffer[i++] & 255); v= (v << 8) | (buffer[i++] & 255); return v; } public int getUInt2(int offset) { int i= this.offset + offset; int v= (buffer[i++] & 255); v= (v << 8) | (buffer[i++] & 255); return v; } public int getUInt3() { int i= this.offset; int v= (buffer[i++] & 255); v= (v << 8) | (buffer[i++] & 255); v= (v << 8) | (buffer[i++] & 255); return v; } public int getUInt3(int offset) { int i= this.offset + offset; int v= (buffer[i++] & 255); v= (v << 8) | (buffer[i++] & 255); v= (v << 8) | (buffer[i++] & 255); return v; } public char[] getUTF(int offset) throws UTFDataFormatException { int pos= this.offset + offset; int utflen= getUInt2(pos); pos += 2; char str[]= new char[utflen]; int count= 0; int strlen= 0; while (count < utflen) { int c= buffer[pos++] & 0xFF; int char2, char3; switch (c >> 4) { case 0 : case 1 : case 2 : case 3 : case 4 : case 5 : case 6 : case 7 : // 0xxxxxxx count++; str[strlen++]= (char) c; break; case 12 : case 13 : // 110x xxxx 10xx xxxx count += 2; if (count > utflen) throw new UTFDataFormatException(); char2= buffer[pos++] & 0xFF; if ((char2 & 0xC0) != 0x80) throw new UTFDataFormatException(); str[strlen++]= (char) (((c & 0x1F) << 6) | (char2 & 0x3F)); break; case 14 : // 1110 xxxx 10xx xxxx 10xx xxxx count += 3; if (count > utflen) throw new UTFDataFormatException(); char2= buffer[pos++] & 0xFF; char3= buffer[pos++] & 0xFF; if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80)) throw new UTFDataFormatException(); str[strlen++]= (char) (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)); break; default : // 10xx xxxx, 1111 xxxx throw new UTFDataFormatException(); } } if (strlen < utflen) System.arraycopy(str, 0, str= new char[strlen], 0, strlen); return str; } public Field inc(int n) { offset += n; return this; } public int length() { return length; } public Field length(int length) { this.length= length; return this; } /** Returns the offset into the underlying byte array that this field is defined over. */ public int offset() { return offset; } public Field offset(int offset) { this.offset= offset; return this; } public Field pointTo(int offset) { return new Field(buffer, this.offset + offset, 0); } public Field put(byte[] b) { return put(0, b); } public Field put(int offset, byte[] b) { System.arraycopy(b, 0, buffer, this.offset + offset, b.length); return this; } public Field put(int offset, Field f) { System.arraycopy(f.buffer, f.offset, buffer, this.offset + offset, f.length); return this; } public Field put(Field f) { System.arraycopy(f.buffer, f.offset, buffer, offset, f.length); return this; } public Field putInt1(int n) { buffer[offset]= (byte) (n); return this; } public Field putInt1(int offset, int n) { buffer[this.offset + offset]= (byte) (n); return this; } public Field putInt2(int n) { int i= offset; buffer[i++]= (byte) (n >> 8); buffer[i++]= (byte) (n >> 0); return this; } public Field putInt2(int offset, int n) { int i= this.offset + offset; buffer[i++]= (byte) (n >> 8); buffer[i++]= (byte) (n >> 0); return this; } public Field putInt3(int n) { int i= offset; buffer[i++]= (byte) (n >> 16); buffer[i++]= (byte) (n >> 8); buffer[i++]= (byte) (n >> 0); return this; } public Field putInt3(int offset, int n) { int i= this.offset + offset; buffer[i++]= (byte) (n >> 16); buffer[i++]= (byte) (n >> 8); buffer[i++]= (byte) (n >> 0); return this; } public Field putInt4(int n) { int i= offset; buffer[i++]= (byte) (n >> 24); buffer[i++]= (byte) (n >> 16); buffer[i++]= (byte) (n >> 8); buffer[i++]= (byte) (n >> 0); return this; } public Field putInt4(int offset, int n) { int i= this.offset + offset; buffer[i++]= (byte) (n >> 24); buffer[i++]= (byte) (n >> 16); buffer[i++]= (byte) (n >> 8); buffer[i++]= (byte) (n >> 0); return this; } public int putUTF(int offset, char[] str) { int strlen= str.length; int utflen= 0; for (int i= 0; i < strlen; i++) { int c= str[i]; if ((c >= 0x0001) && (c <= 0x007F)) { utflen++; } else if (c > 0x07FF) { utflen += 3; } else { utflen += 2; } } if (utflen > 65535) throw new IllegalArgumentException(); int pos= this.offset + offset; buffer[pos++]= (byte) ((utflen >>> 8) & 0xFF); buffer[pos++]= (byte) ((utflen >>> 0) & 0xFF); for (int i= 0; i < strlen; i++) { int c= str[i]; if ((c >= 0x0001) && (c <= 0x007F)) { buffer[pos++]= ((byte) c); } else if (c > 0x07FF) { buffer[pos++]= ((byte) (0xE0 | ((c >> 12) & 0x0F))); buffer[pos++]= ((byte) (0x80 | ((c >> 6) & 0x3F))); buffer[pos++]= ((byte) (0x80 | ((c >> 0) & 0x3F))); } else { buffer[pos++]= ((byte) (0xC0 | ((c >> 6) & 0x1F))); buffer[pos++]= ((byte) (0x80 | ((c >> 0) & 0x3F))); } } return 2 + utflen; } }