001/* 002 * Copyright 2013 Alex Kasko (alexkasko.com) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.alexkasko.unsafe.offheapstruct; 018 019import com.alexkasko.unsafe.bytearray.ByteArrayTool; 020 021import java.util.Comparator; 022 023/** 024 * Internal wrapper for user-provided comparator. 025 * NOT thread-safe. 026 * 027 * @author alexkasko 028 * Date: 9/13/13 029 */ 030class OffHeapStructComparator { 031 private final OffHeapStructIndexAccessor ia1; 032 private final OffHeapStructIndexAccessor ia2; 033 private final OffHeapStructByteArrayAccessor baa1; 034 private final OffHeapStructByteArrayAccessor baa2; 035 private final Comparator<OffHeapStructAccessor> comp; 036 037 /** 038 * Constructor 039 * 040 * @param col collection for index access 041 * @param comp comparator 042 */ 043 OffHeapStructComparator(OffHeapStructCollection col, Comparator<OffHeapStructAccessor> comp) { 044 ByteArrayTool bt = ByteArrayTool.get(); 045 this.ia1 = new OffHeapStructIndexAccessor(col); 046 this.ia2 = new OffHeapStructIndexAccessor(col); 047 this.baa1 = new OffHeapStructByteArrayAccessor(bt); 048 this.baa2 = new OffHeapStructByteArrayAccessor(bt); 049 this.comp = comp; 050 } 051 052 /** 053 * Greater-then operation 054 * 055 * @param index1 collection index 056 * @param index2 collection index 057 * @return 'gt' operation result 058 */ 059 boolean gt(long index1, long index2) { 060 ia1.setIndex(index1); 061 ia2.setIndex(index2); 062 return comp.compare(ia1, ia2) > 0; 063 } 064 065 /** 066 * Greater-then operation 067 * 068 * @param index1 collection index 069 * @param struct2 structure 070 * @return 'gt' operation result 071 */ 072 boolean gt(long index1, byte[] struct2) { 073 ia1.setIndex(index1); 074 baa2.setStruct(struct2); 075 return comp.compare(ia1, baa2) > 0; 076 } 077 078 /** 079 * Lesser-then operation 080 * 081 * @param index1 collection index 082 * @param struct2 structure 083 * @return 'lt' operation result 084 */ 085 boolean lt(long index1, byte[] struct2) { 086 ia1.setIndex(index1); 087 baa2.setStruct(struct2); 088 return comp.compare(ia1, baa2) < 0; 089 } 090 091 /** 092 * Lesser-then operation 093 * 094 * @param struct1 structure 095 * @param index2 collection index 096 * @return 'lt' operation result 097 */ 098 boolean lt(byte[] struct1, long index2) { 099 baa1.setStruct(struct1); 100 ia2.setIndex(index2); 101 return comp.compare(baa1, ia2) < 0; 102 } 103 104 /** 105 * Equals operation 106 * 107 * @param index1 collection index 108 * @param struct2 structure 109 * @return 'eq' operation result 110 */ 111 boolean eq(long index1, byte[] struct2) { 112 ia1.setIndex(index1); 113 baa2.setStruct(struct2); 114 return 0 == comp.compare(ia1, baa2); 115 } 116 117 /** 118 * Equals operation 119 * 120 * @param struct1 structure 121 * @param struct2 structure 122 * @return 'eq' operation result 123 */ 124 boolean eq(byte[] struct1, byte[] struct2) { 125 baa1.setStruct(struct1); 126 baa2.setStruct(struct2); 127 return 0 == comp.compare(baa1, baa2); 128 } 129 130 /** 131 * Calls {@code compare} on comparator and return it results 132 * 133 * @param index1 collection index 134 * @param struct2 structure 135 * @return compare result from comparator 136 */ 137 int compare(long index1, byte[] struct2) { 138 ia1.setIndex(index1); 139 baa2.setStruct(struct2); 140 return comp.compare(ia1, baa2); 141 } 142 143 /** 144 * {@inheritDoc} 145 */ 146 @Override 147 public String toString() { 148 final StringBuilder sb = new StringBuilder(); 149 sb.append("OffHeapStructComparator"); 150 sb.append("{comp=").append(comp); 151 sb.append('}'); 152 return sb.toString(); 153 } 154 155 /** 156 * Struct's accessor implementation for byte array structs 157 * 158 * @author alexkasko 159 * Date: 9/13/13 160 */ 161 private static class OffHeapStructByteArrayAccessor implements OffHeapStructAccessor { 162 private final ByteArrayTool bt; 163 private byte[] struct; 164 165 /** 166 * Constructor 167 * 168 * @param bt byte array tool to operate over held byte array 169 */ 170 private OffHeapStructByteArrayAccessor(ByteArrayTool bt) { 171 this.bt = bt; 172 } 173 174 /** 175 * Constructor 176 * 177 * @param bt byte array tool to operate over held byte array 178 * @param struct byte array to hold 179 */ 180 private OffHeapStructByteArrayAccessor(ByteArrayTool bt, byte[] struct) { 181 this.bt = bt; 182 this.struct = struct; 183 } 184 185 /** 186 * {@inheritDoc} 187 */ 188 @Override 189 public int structLength() { 190 return struct.length; 191 } 192 193 /** 194 * {@inheritDoc} 195 */ 196 @Override 197 public void get(byte[] buffer) { 198 bt.copy(struct, 0, buffer, 0, struct.length); 199 } 200 201 /** 202 * {@inheritDoc} 203 */ 204 @Override 205 public void get(int srcPos, byte[] dest, int destPos, int length) { 206 bt.copy(struct, srcPos, dest, destPos, length); 207 } 208 209 /** 210 * Copies specified buffer data into internal buffer 211 * 212 * @param buffer data to copy 213 */ 214 public void set(byte[] buffer) { 215 bt.copy(buffer, 0, struct, 0, struct.length); 216 } 217 218 /** 219 * {@inheritDoc} 220 */ 221 @Override 222 public byte getByte(int offset) { 223 return bt.getByte(struct, offset); 224 } 225 226 /** 227 * {@inheritDoc} 228 */ 229 @Override 230 public short getUnsignedByte(int offset) { 231 return bt.getUnsignedByte(struct, offset); 232 } 233 234 /** 235 * {@inheritDoc} 236 */ 237 @Override 238 public short getShort(int offset) { 239 return bt.getShort(struct, offset); 240 } 241 242 /** 243 * {@inheritDoc} 244 */ 245 @Override 246 public int getUnsignedShort(int offset) { 247 return bt.getUnsignedShort(struct, offset); 248 } 249 250 /** 251 * {@inheritDoc} 252 */ 253 @Override 254 public int getInt(int offset) { 255 return bt.getInt(struct, offset); 256 } 257 258 /** 259 * {@inheritDoc} 260 */ 261 @Override 262 public long getUnsignedInt(int offset) { 263 return bt.getUnsignedInt(struct, offset); 264 } 265 266 /** 267 * {@inheritDoc} 268 */ 269 @Override 270 public long getLong(int offset) { 271 return bt.getLong(struct, offset); 272 } 273 274 /** 275 * Returns previously setted struct 276 * 277 * @return struct 278 */ 279 private byte[] getStruct() { 280 return struct; 281 } 282 283 /** 284 * Sets struct to access it 285 * 286 * @param struct struct 287 */ 288 private void setStruct(byte[] struct) { 289 this.struct = struct; 290 } 291 292 /** 293 * {@inheritDoc} 294 * 295 * @return 296 */ 297 @Override 298 public String toString() { 299 final StringBuilder sb = new StringBuilder(); 300 sb.append("OffHeapStructByteArrayAccessor"); 301 sb.append("{bt=").append(bt); 302 sb.append('}'); 303 return sb.toString(); 304 } 305 } 306 307 /** 308 * Struct's accessor implementation for off-heap stored structs 309 * 310 * @author alexkasko 311 * Date: 9/13/13 312 */ 313 private static class OffHeapStructIndexAccessor implements OffHeapStructAccessor { 314 private final OffHeapStructCollection col; 315 private long index = -1; 316 317 /** 318 * Constructor 319 * 320 * @param col collection to access structs from 321 */ 322 private OffHeapStructIndexAccessor(OffHeapStructCollection col) { 323 this.col = col; 324 } 325 326 /** 327 * {@inheritDoc} 328 */ 329 @Override 330 public int structLength() { 331 return col.structLength(); 332 } 333 334 /** 335 * {@inheritDoc} 336 */ 337 @Override 338 public void get(byte[] buffer) { 339 col.get(index, buffer); 340 } 341 342 /** 343 * {@inheritDoc} 344 */ 345 @Override 346 public void get(int srcPos, byte[] dest, int destPos, int length) { 347 col.get(index, srcPos, dest, destPos, length); 348 } 349 350 /** 351 * {@inheritDoc} 352 */ 353 @Override 354 public byte getByte(int offset) { 355 return col.getByte(index, offset); 356 } 357 358 /** 359 * {@inheritDoc} 360 */ 361 @Override 362 public short getUnsignedByte(int offset) { 363 return col.getUnsignedByte(index, offset); 364 } 365 366 /** 367 * {@inheritDoc} 368 */ 369 @Override 370 public short getShort(int offset) { 371 return col.getShort(index, offset); 372 } 373 374 /** 375 * {@inheritDoc} 376 */ 377 @Override 378 public int getUnsignedShort(int offset) { 379 return col.getUnsignedShort(index, offset); 380 } 381 382 /** 383 * {@inheritDoc} 384 */ 385 @Override 386 public int getInt(int offset) { 387 return col.getInt(index, offset); 388 } 389 390 /** 391 * {@inheritDoc} 392 */ 393 @Override 394 public long getUnsignedInt(int offset) { 395 return col.getUnsignedInt(index, offset); 396 } 397 398 /** 399 * {@inheritDoc} 400 */ 401 @Override 402 public long getLong(int offset) { 403 return col.getLong(index, offset); 404 } 405 406 /** 407 * Sets index value 408 * 409 * @param index index value 410 */ 411 private void setIndex(long index) { 412 this.index = index; 413 } 414 415 /** 416 * {@inheritDoc} 417 */ 418 @Override 419 public String toString() { 420 final StringBuilder sb = new StringBuilder(); 421 sb.append("OffHeapStructIndexAccessor"); 422 sb.append("{col=").append(col); 423 sb.append(", index=").append(index); 424 sb.append('}'); 425 return sb.toString(); 426 } 427 } 428}