You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gnosygnu_xowa/100_core/src/gplx/core/btries/Btrie_slim_itm.java

131 lines
4.7 KiB

/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.core.btries; import gplx.*; import gplx.core.*;
public class Btrie_slim_itm {
private Btrie_slim_itm[] ary = Btrie_slim_itm.Ary_empty;
public Btrie_slim_itm(byte key_byte, Object val, boolean case_any) {this.key_byte = key_byte; this.val = val; this.case_any = case_any;}
public byte Key_byte() {return key_byte;} private byte key_byte;
public Object Val() {return val;} public void Val_set(Object val) {this.val = val;} private Object val;
public boolean Case_any() {return case_any;} private boolean case_any;
public boolean Ary_is_empty() {return ary == Btrie_slim_itm.Ary_empty;}
public void Clear() {
val = null;
for (int i = 0; i < ary_len; i++)
ary[i].Clear();
ary = Btrie_slim_itm.Ary_empty;
ary_len = ary_max = 0;
}
public Btrie_slim_itm Ary_find(byte b) {
int find_val = (case_any && (b > 64 && b < 91) ? b + 32 : b) & 0xff;// PATCH.JAVA:need to convert to unsigned byte
int key_val = 0;
switch (ary_len) {
case 0: return null;
case 1:
Btrie_slim_itm rv = ary[0];
key_val = rv.Key_byte() & 0xff;// PATCH.JAVA:need to convert to unsigned byte;
key_val = (case_any && (key_val > 64 && key_val < 91) ? key_val + 32 : key_val);
return key_val == find_val ? rv : null;
default:
int adj = 1;
int prv_pos = 0;
int prv_len = ary_len;
int cur_len = 0;
int cur_idx = 0;
Btrie_slim_itm itm = null;
while (true) {
cur_len = prv_len / 2;
if (prv_len % 2 == 1) ++cur_len;
cur_idx = prv_pos + (cur_len * adj);
if (cur_idx < 0) cur_idx = 0;
else if (cur_idx >= ary_len) cur_idx = ary_len - 1;
itm = ary[cur_idx];
key_val = itm.Key_byte() & 0xff; // PATCH.JAVA:need to convert to unsigned byte;
key_val = (case_any && (key_val > 64 && key_val < 91) ? key_val + 32 : key_val);
if (find_val < key_val) adj = -1;
else if (find_val > key_val) adj = 1;
else /*(find_val == cur_val)*/ return itm;
if (cur_len == 1) {
cur_idx += adj;
if (cur_idx < 0 || cur_idx >= ary_len) return null;
itm = ary[cur_idx];
return (itm.Key_byte() & 0xff) == find_val ? itm : null; // PATCH.JAVA:need to convert to unsigned byte;
}
prv_len = cur_len;
prv_pos = cur_idx;
}
}
}
public Btrie_slim_itm Ary_add(byte b, Object val) {
int new_len = ary_len + 1;
if (new_len > ary_max) {
ary_max += 4;
ary = (Btrie_slim_itm[])Array_.Resize(ary, ary_max);
}
Btrie_slim_itm rv = new Btrie_slim_itm(b, val, case_any);
ary[ary_len] = rv;
ary_len = new_len;
ByteHashItm_sorter.Instance.Sort(ary, ary_len);
return rv;
}
public void Ary_del(byte b) {
boolean found = false;
for (int i = 0; i < ary_len; i++) {
if (found) {
if (i < ary_len - 1)
ary[i] = ary[i + 1];
}
else {
if (b == ary[i].Key_byte()) found = true;
}
}
if (found) --ary_len;
}
public static final Btrie_slim_itm[] Ary_empty = new Btrie_slim_itm[0]; int ary_len = 0, ary_max = 0;
}
class ByteHashItm_sorter {// quicksort
Btrie_slim_itm[] ary; int ary_len;
public void Sort(Btrie_slim_itm[] ary, int ary_len) {
if (ary == null || ary_len < 2) return;
this.ary = ary;
this.ary_len = ary_len;
Sort_recurse(0, ary_len - 1);
}
private void Sort_recurse(int lo, int hi) {
int i = lo, j = hi;
int mid = ary[lo + (hi-lo)/2].Key_byte()& 0xFF; // get mid itm
while (i <= j) { // divide into two lists
while ((ary[i].Key_byte() & 0xFF) < mid) // if lhs.cur < mid, then get next from lhs
i++;
while ((ary[j].Key_byte() & 0xFF) > mid) // if rhs.cur > mid, then get next from rhs
j--;
// lhs.cur > mid && rhs.cur < mid; switch lhs.cur and rhs.cur; increase i and j
if (i <= j) {
Btrie_slim_itm tmp = ary[i];
ary[i] = ary[j];
ary[j] = tmp;
i++;
j--;
}
}
if (lo < j) Sort_recurse(lo, j);
if (i < hi) Sort_recurse(i, hi);
}
public static final ByteHashItm_sorter Instance = new ByteHashItm_sorter(); ByteHashItm_sorter() {}
}