/* * Copyright (c) 2011 LinkedIn, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.flaptor.indextank.index; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.io.UnsupportedEncodingException; public class DocId implements Serializable, Comparable<DocId> { private static final long serialVersionUID = 1L; private byte[] buffer; private int start; private int count; private int hash; public DocId(String string) { try { this.buffer = string.getBytes("UTF-8"); this.start = 0; this.count = this.buffer.length; } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } public DocId(byte[] buffer, int start, int count) { this.buffer = buffer; this.start = start; this.count = count; } @Override public int hashCode() { int h = hash; if (h == 0) { int off = start; byte[] buf = buffer; int len = count; for (int i = 0; i < len; i++) { h = 31*h + buf[off++]; } hash = h; } return h; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof DocId) { DocId oid = (DocId)obj; int n = count; if (n == oid.count) { byte v1[] = buffer; byte v2[] = oid.buffer; int i = start; int j = oid.start; while (n-- != 0) { if (v1[i++] != v2[j++]) return false; } return true; } } return false; } @Override public String toString() { return new String(buffer, start, count); } private void writeObject(ObjectOutputStream oos) throws IOException { oos.writeInt(count); oos.write(buffer, start, count); } private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { this.start = 0; this.count = ois.readInt(); this.buffer = new byte[count]; ois.read(this.buffer); } public void writeData(DataOutputStream dos) throws IOException { dos.writeInt(count); dos.write(buffer, start, count); } public static void writeNull(DataOutputStream dos) throws IOException { dos.writeInt(-1); } public static DocId readData(DataInputStream dis) throws IOException { int count = dis.readInt(); if (count < 0) return null; byte[] buffer = new byte[count]; dis.read(buffer); return new DocId(buffer, 0, count); } @Override public int compareTo(DocId o) { int n = Math.min(count, o.count); int i = start, j = o.start; int end = i + n; if (i == j) { while (i < end) { int c = buffer[i] - o.buffer[i]; if (c != 0) return c; ++i; } } else { while (i < end) { int c = buffer[i++] - o.buffer[j++]; if (c != 0) return c; } } return count - o.count; } public void update(byte[] buffer, int start, int count) { this.buffer = buffer; this.start = start; this.count = count; this.hash = 0; } public void updateFrom(DocId docid) { byte[] buf = this.buffer; byte[] obuf = docid.buffer; int off = docid.start; int len = docid.count; if (buf.length < docid.count) { buf = new byte[docid.count]; this.buffer = buf; } System.arraycopy(obuf, off, buf, 0, len); this.start = 0; this.count = docid.count; this.hash = 0; } public DocId copy() { return this.copy(this.count); } public DocId copy(int targetBufferSize) { byte[] buf = this.buffer; int off = this.start; int len = this.count; targetBufferSize = Math.max(targetBufferSize, len); byte[] clonedBuffer = new byte[targetBufferSize]; System.arraycopy(buf, off, clonedBuffer, 0, len); return new DocId(clonedBuffer, 0, len); } }