00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 package com.sleepycat.collections;
00011
00012 import java.util.Comparator;
00013
00014 import com.sleepycat.db.DatabaseEntry;
00015
00019 class KeyRange {
00020
00021 Comparator comparator;
00022 DatabaseEntry beginKey;
00023 DatabaseEntry endKey;
00024 boolean singleKey;
00025 boolean beginInclusive;
00026 boolean endInclusive;
00027
00031 KeyRange(Comparator comparator) {
00032 this.comparator = comparator;
00033 }
00034
00038 KeyRange subRange(DatabaseEntry key)
00039 throws KeyRangeException {
00040
00041 if (!check(key)) {
00042 throw new KeyRangeException("singleKey out of range");
00043 }
00044 KeyRange range = new KeyRange(comparator);
00045 range.beginKey = key;
00046 range.endKey = key;
00047 range.beginInclusive = true;
00048 range.endInclusive = true;
00049 range.singleKey = true;
00050 return range;
00051 }
00052
00057 KeyRange subRange(DatabaseEntry beginKey, boolean beginInclusive,
00058 DatabaseEntry endKey, boolean endInclusive)
00059 throws KeyRangeException {
00060
00061 if (beginKey == null) {
00062 beginKey = this.beginKey;
00063 beginInclusive = this.beginInclusive;
00064 } else if (!check(beginKey, beginInclusive)) {
00065 throw new KeyRangeException("beginKey out of range");
00066 }
00067 if (endKey == null) {
00068 endKey = this.endKey;
00069 endInclusive = this.endInclusive;
00070 } else if (!check(endKey, endInclusive)) {
00071 throw new KeyRangeException("endKey out of range");
00072 }
00073 KeyRange range = new KeyRange(comparator);
00074 range.beginKey = beginKey;
00075 range.endKey = endKey;
00076 range.beginInclusive = beginInclusive;
00077 range.endInclusive = endInclusive;
00078 return range;
00079 }
00080
00085 final DatabaseEntry getSingleKey() {
00086
00087 return singleKey ? beginKey : null;
00088 }
00089
00093 final boolean hasBound() {
00094
00095 return endKey != null || beginKey != null;
00096 }
00097
00101 public String toString() {
00102
00103 return "[KeyRange " + beginKey + ' ' + beginInclusive +
00104 endKey + ' ' + endInclusive +
00105 (singleKey ? " single" : "");
00106 }
00107
00111 boolean check(DatabaseEntry key) {
00112
00113 if (singleKey) {
00114 return (compare(key, beginKey) == 0);
00115 } else {
00116 return checkBegin(key, true) && checkEnd(key, true);
00117 }
00118 }
00119
00123 boolean check(DatabaseEntry key, boolean inclusive) {
00124
00125 if (singleKey) {
00126 return (compare(key, beginKey) == 0);
00127 } else {
00128 return checkBegin(key, inclusive) && checkEnd(key, inclusive);
00129 }
00130 }
00131
00148 boolean checkBegin(DatabaseEntry key, boolean inclusive) {
00149
00150 if (beginKey == null) {
00151 return true;
00152 } else if (!beginInclusive && inclusive) {
00153 return compare(key, beginKey) > 0;
00154 } else {
00155 return compare(key, beginKey) >= 0;
00156 }
00157 }
00158
00163 boolean checkEnd(DatabaseEntry key, boolean inclusive) {
00164
00165 if (endKey == null) {
00166 return true;
00167 } else if (!endInclusive && inclusive) {
00168 return compare(key, endKey) < 0;
00169 } else {
00170 return compare(key, endKey) <= 0;
00171 }
00172 }
00173
00177 int compare(DatabaseEntry key1, DatabaseEntry key2) {
00178
00179 if (comparator != null) {
00180 return comparator.compare(getByteArray(key1), getByteArray(key2));
00181 } else {
00182 return compareBytes
00183 (key1.getData(), key1.getOffset(), key1.getSize(),
00184 key2.getData(), key2.getOffset(), key2.getSize());
00185
00186 }
00187 }
00188
00193 static int compareBytes(byte[] data1, int offset1, int size1,
00194 byte[] data2, int offset2, int size2) {
00195
00196 for (int i = 0; i < size1 && i < size2; i++) {
00197
00198 int b1 = 0xFF & data1[offset1 + i];
00199 int b2 = 0xFF & data2[offset2 + i];
00200 if (b1 < b2)
00201 return -1;
00202 else if (b1 > b2)
00203 return 1;
00204 }
00205
00206 if (size1 < size2)
00207 return -1;
00208 else if (size1 > size2)
00209 return 1;
00210 else
00211 return 0;
00212 }
00213
00217 static DatabaseEntry copy(DatabaseEntry from) {
00218 return new DatabaseEntry(getByteArray(from));
00219 }
00220
00224 static void copy(DatabaseEntry from, DatabaseEntry to) {
00225 to.setData(getByteArray(from));
00226 to.setOffset(0);
00227 }
00228
00233 static byte[] getByteArray(DatabaseEntry entry) {
00234
00235 byte[] bytes = entry.getData();
00236 if (bytes == null) return null;
00237 int size = entry.getSize();
00238 byte[] data = new byte[size];
00239 System.arraycopy(bytes, entry.getOffset(), data, 0, size);
00240 return data;
00241 }
00242
00246 static boolean equalBytes(DatabaseEntry e1, DatabaseEntry e2) {
00247
00248 if (e1 == null && e2 == null) {
00249 return true;
00250 }
00251 if (e1 == null || e2 == null) {
00252 return false;
00253 }
00254
00255 byte[] d1 = e1.getData();
00256 byte[] d2 = e2.getData();
00257 int s1 = e1.getSize();
00258 int s2 = e2.getSize();
00259 int o1 = e1.getOffset();
00260 int o2 = e2.getOffset();
00261
00262 if (d1 == null && d2 == null) {
00263 return true;
00264 }
00265 if (d1 == null || d2 == null) {
00266 return false;
00267 }
00268 if (s1 != s2) {
00269 return false;
00270 }
00271 for (int i = 0; i < s1; i += 1) {
00272 if (d1[o1 + i] != d2[o2 + i]) {
00273 return false;
00274 }
00275 }
00276 return true;
00277 }
00278
00287 static String toString(DatabaseEntry dbt) {
00288
00289 int len = dbt.getOffset() + dbt.getSize();
00290 StringBuffer buf = new StringBuffer(len * 2);
00291 byte[] data = dbt.getData();
00292 for (int i = dbt.getOffset(); i < len; i++) {
00293 String num = Integer.toHexString(data[i]);
00294 if (num.length() < 2) buf.append('0');
00295 buf.append(num);
00296 }
00297 return buf.toString();
00298 }
00299 }