Quadcap Embeddable Database

com/quadcap/util/OctetComparator.java

Go to the documentation of this file.
00001 package com.quadcap.util; 00002 00003 /* Copyright 1997 - 2003 Quadcap Software. All rights reserved. 00004 * 00005 * This software is distributed under the Quadcap Free Software License. 00006 * This software may be used or modified for any purpose, personal or 00007 * commercial. Open Source redistributions are permitted. Commercial 00008 * redistribution of larger works derived from, or works which bundle 00009 * this software requires a "Commercial Redistribution License"; see 00010 * http://www.quadcap.com/purchase. 00011 * 00012 * Redistributions qualify as "Open Source" under one of the following terms: 00013 * 00014 * Redistributions are made at no charge beyond the reasonable cost of 00015 * materials and delivery. 00016 * 00017 * Redistributions are accompanied by a copy of the Source Code or by an 00018 * irrevocable offer to provide a copy of the Source Code for up to three 00019 * years at the cost of materials and delivery. Such redistributions 00020 * must allow further use, modification, and redistribution of the Source 00021 * Code under substantially the same terms as this license. 00022 * 00023 * Redistributions of source code must retain the copyright notices as they 00024 * appear in each source code file, these license terms, and the 00025 * disclaimer/limitation of liability set forth as paragraph 6 below. 00026 * 00027 * Redistributions in binary form must reproduce this Copyright Notice, 00028 * these license terms, and the disclaimer/limitation of liability set 00029 * forth as paragraph 6 below, in the documentation and/or other materials 00030 * provided with the distribution. 00031 * 00032 * The Software is provided on an "AS IS" basis. No warranty is 00033 * provided that the Software is free of defects, or fit for a 00034 * particular purpose. 00035 * 00036 * Limitation of Liability. Quadcap Software shall not be liable 00037 * for any damages suffered by the Licensee or any third party resulting 00038 * from use of the Software. 00039 */ 00040 00041 import java.util.Comparator; 00042 00043 /** 00044 * This class implements a comparator for octet strings. 00045 * 00046 * @author Stan Bailes 00047 */ 00048 public class OctetComparator implements Comparator { 00049 boolean reverse = false; 00050 boolean casemap = false; 00051 00052 static OctetComparator cmp = new OctetComparator(); 00053 static OctetComparator casecmp = new OctetComparator(true,false); 00054 /** 00055 * Construct a new octet comparator. 00056 */ 00057 public OctetComparator() {} 00058 00059 public OctetComparator(boolean casemap, boolean reverse) { 00060 this.casemap = casemap; 00061 this.reverse = reverse; 00062 } 00063 00064 /** 00065 * Ordering: is object 'a' <i>less, equal, or greater</i> than object 'b'? 00066 * 00067 * <p>(From the ACAP draft: draft-ietf-acap-spec-06.txt) 00068 * 00069 * <p>Ordering comparators can determine the ordinal precedence of any 00070 * two values. When used for ordering, a comparator's name can be 00071 * prefixed with "+" or "-" to indicate that the ordering should be 00072 * normal order or reversed order respectively. If no prefix is 00073 * included, "+" is assumed. 00074 * 00075 * <p>A comparator may designate certain values as having 00076 * an undefined ordinal precedence. Such values collate with equal 00077 * value after all other values regardless of whether normal or reverse 00078 * ordering is used. 00079 * 00080 * @param a the first object to compare 00081 * @param b the second object 00082 * @return if a < b return -1 else if a > b return 1 else return 0 00083 */ 00084 public int compare(Object a, Object b) { 00085 OctetString oa = (OctetString)a; 00086 OctetString ob = (OctetString)b; 00087 00088 int before = reverse ? 1 : -1; 00089 int after = 0 - before; 00090 00091 byte[] va = getBytes(oa); 00092 byte[] vb = getBytes(ob); 00093 int i = 0; 00094 while (i < va.length && i < vb.length) { 00095 if (va[i] < vb[i]) return before; 00096 if (va[i] > vb[i]) return after; 00097 i++; 00098 } 00099 if (i < vb.length) return before; 00100 if (i < va.length) return after; 00101 return 0; 00102 } 00103 00104 /** 00105 * Determine if the search value is a prefix of the object being 00106 * searched. In the case of a prefix search on a multi-value, 00107 * the match is successful if the value is a prefix of any one of 00108 * the muliple values. 00109 * 00110 * @param obj the "first" object to compare, normally the candidate 00111 * object in a SEARCH operation. 00112 * @param val the "second" object, normally the constant value 00113 * specified in the SEARCH operation. 00114 * @return true if <b>val</b> is a prefix of <b>obj</b>. 00115 */ 00116 public boolean prefixMatch(OctetString obj, OctetString val) { 00117 byte[] va = getBytes(val); 00118 byte[] vb = getBytes(obj); 00119 if (va.length > vb.length) return false; 00120 for (int i = 0; i < va.length; i++) { 00121 if (va[i] != vb[i]) return false; 00122 } 00123 return true; 00124 } 00125 00126 /** 00127 * Determine if the search value is a substring of the object being 00128 * searched. In the case of a substring search on a multi-value, 00129 * the match is successful if the value is a substring of any one of 00130 * the muliple values. 00131 * 00132 * @param obj the "first" object to compare, normally the candidate 00133 * object in a SEARCH operation. 00134 * @param val the "second" object, normally the constant value 00135 * specified in the SEARCH operation. 00136 * @return true if <b>val</b> is a substring of <b>obj</b>. 00137 */ 00138 public boolean substringMatch(OctetString obj, OctetString val) { 00139 byte[] va = getBytes(obj); 00140 byte[] vb = getBytes(val); 00141 int left = va.length - vb.length; 00142 for (int i = 0; i <= left; i++) { 00143 boolean match = true; 00144 for (int j = 0; match && j < vb.length; j++) { 00145 match = va[i+j] == vb[j]; 00146 } 00147 if (match) return true; 00148 } 00149 return false; 00150 } 00151 00152 00153 /** 00154 * Determine if the search value matches a glob-style pattern. 00155 * 00156 * @param obj the object to compare. 00157 * @param pattern the pattern 00158 * @return true if <b>obj</b> matches the pattern specified by 00159 * <b>pattern</b>. 00160 */ 00161 public boolean patternMatch(OctetString obj, OctetString pattern) { 00162 byte[] va = getBytes(obj); 00163 byte[] vb = getBytes(pattern); 00164 return pMatch(va, 0, vb, 0); 00165 } 00166 00167 boolean pMatch(byte[] va, int a, byte[] vb, int b) { 00168 while (b < vb.length) { 00169 byte p = vb[b++]; 00170 switch (p) { 00171 case (byte)'*': 00172 if (a >= va.length || b >= vb.length) return true; 00173 while (a < va.length) { 00174 if (pMatch(va, a++, vb, b)) return true; 00175 } 00176 return false; 00177 case (byte)'?': 00178 if (a++ >= va.length) return false; 00179 break; 00180 case (byte)'\\': 00181 if (b >= vb.length) return false; 00182 p = vb[b++]; 00183 // fall through... 00184 default: 00185 if (a >= va.length) return false; 00186 if (va[a++] != p) return false; 00187 } 00188 } 00189 return a >= va.length; 00190 } 00191 00192 int pMatchOrder(byte[] va, int a, byte[] vb, int b) { 00193 int ret = 0; 00194 while (b < vb.length) { 00195 byte p = vb[b++]; 00196 switch (p) { 00197 case (byte)'*': 00198 while (a < va.length) { 00199 ret = pMatchOrder(va, a++, vb, b); 00200 if (ret == 0) return ret; 00201 } 00202 return ret; 00203 case (byte)'?': 00204 if (a++ >= va.length) return -1; 00205 break; 00206 case (byte)'\\': 00207 if (b >= vb.length) return 1; 00208 p = vb[b++]; 00209 // fall through... 00210 default: 00211 if (a >= va.length) return -1; 00212 byte q = va[a++]; 00213 if (q < p) return -1; 00214 if (q > p) return 1; 00215 } 00216 } 00217 return a >= va.length ? 0 : 1; 00218 } 00219 00220 /** 00221 * The layer above which "i;octet" and "i;ascii-casemap" are the 00222 * same comparator. 00223 * 00224 * @param obj the object whose bytes we want. 00225 */ 00226 byte[] getBytes(OctetString obj) { 00227 byte[] b = obj.getBytes(); 00228 if (casemap) { 00229 byte[] cb = new byte[b.length]; 00230 for (int i = 0; i < b.length; i++) { 00231 byte c = b[i]; 00232 if (c >= 'a' && c <= 'z') 00233 cb[i] = (byte)(c - 32); 00234 else 00235 cb[i] = c; 00236 } 00237 b = cb; 00238 } 00239 return b; 00240 } 00241 }