package divconq.db.rocks.keyquery; import divconq.db.Constants; import divconq.db.util.ByteUtil; import divconq.lang.Memory; public class MatchKeyLevel extends KeyLevel { protected byte[] match = null; protected boolean hasMatch = false; public MatchKeyLevel(Object match) { this.match = ByteUtil.buildKey(match); } public MatchKeyLevel(byte[] match) { this.match = match; } // return -1 if key is less than match, 0 for equal and 1 for key is greater than match @Override public int compare(byte[] key, int offset, boolean browseMode, Memory browseKey) { int mlen = this.match.length; // compare the arrays, as far as they both have bytes for (int i = 0; i < Math.min(mlen, key.length - offset); i++) { if (this.match[i] < key[offset + i]) { this.resetLast(); return 1; } if (this.match[i] > key[offset + i]) { this.resetLast(); return -1; } } // Presumably they are an exact match up to the lowest shared slot // thus is key is shorter it comes before us if (offset + mlen > key.length) { this.resetLast(); return -1; } /* if (this.next == null) { // can be nothing past me, if there is it is bigger than me if (key.length > offset + mlen) return 1; return 0; } */ // can be nothing past me if there is no `next` if ((this.next == null) && (key.length > offset + mlen)) { if (!browseMode) return 1; if (this.hasMatch) return 1; // treat as match - need special handling browseKey.setLength(offset + mlen); this.hasMatch = true; return 0; } if (this.next == null) { if (browseMode) this.hasMatch = true; return 0; } // look for field separator - check length if (offset + mlen + 1 > key.length) { this.next.resetLast(); return -1; } // look for field separator - check byte if (Constants.DB_TYPE_MARKER_ALPHA != key[offset + this.match.length]) { this.next.resetLast(); return 1; } return this.next.compare(key, offset + mlen + 1, browseMode, browseKey); } @Override public void resetLast() { if (this.hasMatch) this.hasMatch = false; if (this.next != null) this.next.resetLast(); } @Override public void buildSeek(Memory mem) { mem.write(this.match); if (this.next != null) { mem.writeByte(Constants.DB_TYPE_MARKER_ALPHA); this.next.buildSeek(mem); } else if (this.hasMatch) { mem.writeByte((byte)0x01); } } }