blob: 9b4cfa2911e6a76f6987d9e3210f9694d9ea69ab [file] [log] [blame]
/*******************************************************************************
* 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
*******************************************************************************/
package org.eclipse.cdt.internal.core.index.impl;
import java.io.UTFDataFormatException;
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;
}
}