/ *
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.* ;
import gplx.core.primitives.* ;
public class Btrie_slim_mgr implements Btrie_mgr {
Btrie_slim_mgr ( boolean case_match ) { root = new Btrie_slim_itm ( Byte_ . Zero , null , ! case_match ) ; } private Btrie_slim_itm root ;
public int Count ( ) { return count ; } private int count ;
public int Match_pos ( ) { return match_pos ; } private int match_pos ;
public Object Match_exact ( byte [ ] src ) { return src = = null ? null : Match_exact ( src , 0 , src . length ) ; }
public Object Match_exact ( byte [ ] src , int bgn_pos , int end_pos ) {
Object rv = Match_bgn_w_byte ( src [ bgn_pos ] , src , bgn_pos , end_pos ) ;
return rv = = null ? null : match_pos - bgn_pos = = end_pos - bgn_pos ? rv : null ;
}
public Object Match_bgn ( byte [ ] src , int bgn_pos , int end_pos ) { return bgn_pos < end_pos ? Match_bgn_w_byte ( src [ bgn_pos ] , src , bgn_pos , end_pos ) : null ; } // handle out of bounds gracefully; EX: Match_bgn("abc", 3, 3) should return null not fail
public Object Match_bgn_w_byte ( byte b , byte [ ] src , int bgn_pos , int src_end ) {
Object rv = null ; int cur_pos = match_pos = bgn_pos ;
Btrie_slim_itm cur = root ;
while ( true ) {
Btrie_slim_itm nxt = cur . Ary_find ( b ) ; if ( nxt = = null ) return rv ; // nxt does not hav b; return rv;
+ + cur_pos ;
if ( nxt . Ary_is_empty ( ) ) { match_pos = cur_pos ; return nxt . Val ( ) ; } // nxt is leaf; return nxt.Val() (which should be non-null)
Object nxt_val = nxt . Val ( ) ;
if ( nxt_val ! = null ) { match_pos = cur_pos ; rv = nxt_val ; } // nxt is node; cache rv (in case of false match)
if ( cur_pos = = src_end ) return rv ; // increment cur_pos and exit if src_end
b = src [ cur_pos ] ;
cur = nxt ;
}
}
public byte Match_byte_or ( byte b , byte [ ] src , int bgn , int end , byte or ) {
Object rv_obj = Match_bgn_w_byte ( b , src , bgn , end ) ;
return rv_obj = = null ? or : ( ( Byte_obj_val ) rv_obj ) . Val ( ) ;
}
public byte Match_byte_or ( byte [ ] src , int bgn , int end , byte or ) {
Object rv_obj = Match_bgn ( src , bgn , end ) ;
return rv_obj = = null ? or : ( ( Byte_obj_val ) rv_obj ) . Val ( ) ;
}
public Btrie_slim_mgr Add_bry_tid ( byte [ ] bry , byte tid ) { return ( Btrie_slim_mgr ) Add_obj ( bry , Byte_obj_val . new_ ( tid ) ) ; }
public Btrie_slim_mgr Add_bry_int ( byte [ ] key , int val ) { return ( Btrie_slim_mgr ) Add_obj ( key , Int_obj_val . new_ ( val ) ) ; }
public Btrie_slim_mgr Add_str_byte ( String key , byte val ) { return ( Btrie_slim_mgr ) Add_obj ( Bry_ . new_u8 ( key ) , Byte_obj_val . new_ ( val ) ) ; }
public Btrie_slim_mgr Add_str_int ( String key , int val ) { return ( Btrie_slim_mgr ) Add_obj ( Bry_ . new_u8 ( key ) , Int_obj_val . new_ ( val ) ) ; }
public Btrie_slim_mgr Add_bry ( String key , String val ) { return ( Btrie_slim_mgr ) Add_obj ( Bry_ . new_u8 ( key ) , Bry_ . new_u8 ( val ) ) ; }
public Btrie_slim_mgr Add_bry ( String key , byte [ ] val ) { return ( Btrie_slim_mgr ) Add_obj ( Bry_ . new_u8 ( key ) , val ) ; }
public Btrie_slim_mgr Add_bry ( byte [ ] v ) { return ( Btrie_slim_mgr ) Add_obj ( v , v ) ; }
public Btrie_slim_mgr Add_str_str ( String key , String val ) { return ( Btrie_slim_mgr ) Add_obj ( Bry_ . new_u8 ( key ) , Bry_ . new_u8 ( val ) ) ; }
public Btrie_slim_mgr Add_bry_bry ( byte [ ] key , byte [ ] val ) { return ( Btrie_slim_mgr ) Add_obj ( key , val ) ; }
public Btrie_slim_mgr Add_bry_byte ( byte b , byte val ) { return ( Btrie_slim_mgr ) Add_obj ( new byte [ ] { b } , Byte_obj_val . new_ ( val ) ) ; }
public Btrie_slim_mgr Add_bry_byte ( byte [ ] bry , byte val ) { return ( Btrie_slim_mgr ) Add_obj ( bry , Byte_obj_val . new_ ( val ) ) ; }
public Btrie_slim_mgr Add_str_byte__many ( byte val , String . . . ary ) {
int ary_len = ary . length ;
Byte_obj_val bval = Byte_obj_val . new_ ( val ) ;
for ( int i = 0 ; i < ary_len ; i + + )
Add_obj ( Bry_ . new_u8 ( ary [ i ] ) , bval ) ;
return this ;
}
public Btrie_slim_mgr Add_many_int ( int val , String . . . ary ) { return Add_many_int ( val , Bry_ . Ary ( ary ) ) ; }
public Btrie_slim_mgr Add_many_int ( int val , byte [ ] . . . ary ) {
int len = ary . length ;
Int_obj_val obj = Int_obj_val . new_ ( val ) ;
for ( int i = 0 ; i < len ; i + + )
Add_obj ( ary [ i ] , obj ) ;
return this ;
}
public Btrie_slim_mgr Add_ary_byte ( byte . . . ary ) {
int len = ary . length ;
for ( int i = 0 ; i < len ; + + i ) {
byte b = ary [ i ] ;
Byte_obj_val bval = Byte_obj_val . new_ ( b ) ;
Add_obj ( Bry_ . New_by_byte ( b ) , bval ) ;
}
return this ;
}
public Btrie_slim_mgr Add_replace_many ( String trg_str , String . . . src_ary ) { return Add_replace_many ( Bry_ . new_u8 ( trg_str ) , src_ary ) ; }
public Btrie_slim_mgr Add_replace_many ( byte [ ] trg_bry , String . . . src_ary ) {
int len = src_ary . length ;
for ( int i = 0 ; i < len ; i + + )
Add_obj ( Bry_ . new_u8 ( src_ary [ i ] ) , trg_bry ) ;
return this ;
}
public Btrie_slim_mgr Add_stub ( String key , byte val ) { byte [ ] bry = Bry_ . new_u8 ( key ) ; return ( Btrie_slim_mgr ) Add_obj ( bry , new Btrie_itm_stub ( val , bry ) ) ; }
public Btrie_slim_mgr Add_stubs ( byte [ ] [ ] ary ) { return Add_stubs ( ary , ary . length ) ; }
public Btrie_slim_mgr Add_stubs ( byte [ ] [ ] ary , int ary_len ) {
for ( byte i = 0 ; i < ary_len ; i + + ) {
byte [ ] bry = ary [ i ] ;
Add_obj ( bry , new Btrie_itm_stub ( i , bry ) ) ;
}
return this ;
}
public Btrie_mgr Add_obj ( String key , Object val ) { return Add_obj ( Bry_ . new_u8 ( key ) , val ) ; }
public Btrie_mgr Add_obj ( byte [ ] key , Object val ) {
if ( val = = null ) throw Err_ . new_wo_type ( "null objects cannot be registered" , "key" , String_ . new_u8 ( key ) ) ;
int key_len = key . length ; int key_end = key_len - 1 ;
Btrie_slim_itm cur = root ;
for ( int i = 0 ; i < key_len ; i + + ) {
byte b = key [ i ] ;
if ( root . Case_any ( ) & & ( b > 64 & & b < 91 ) ) b + = 32 ;
Btrie_slim_itm nxt = cur . Ary_find ( b ) ;
if ( nxt = = null )
nxt = cur . Ary_add ( b , null ) ;
if ( i = = key_end )
nxt . Val_set ( val ) ;
cur = nxt ;
}
count + + ; // FUTURE: do not increment if replacing value
return this ;
}
public void Del ( byte [ ] key ) {
int key_len = key . length ;
Btrie_slim_itm cur = root ;
for ( int i = 0 ; i < key_len ; i + + ) {
byte b = key [ i ] ;
Btrie_slim_itm nxt = cur . Ary_find ( b ) ;
if ( nxt = = null ) break ;
Object nxt_val = nxt . Val ( ) ;
if ( nxt_val = = null ) // cur is end of chain; remove entry; EX: Abc and at c
cur . Ary_del ( b ) ;
else // cur is mid of chain; null out entry
nxt . Val_set ( null ) ;
cur = nxt ;
}
count - - ; // FUTURE: do not decrement if not found
}
public byte [ ] Replace ( Bry_bfr tmp_bfr , byte [ ] src , int bgn , int end ) {
int pos = bgn ;
boolean dirty = false ;
while ( pos < end ) {
byte b = src [ pos ] ;
Object o = this . Match_bgn_w_byte ( b , src , pos , end ) ;
if ( o = = null ) {
if ( dirty )
tmp_bfr . Add_byte ( b ) ;
pos + + ;
}
else {
if ( ! dirty ) {
tmp_bfr . Add_mid ( src , bgn , pos ) ;
dirty = true ;
}
tmp_bfr . Add ( ( byte [ ] ) o ) ;
pos = match_pos ;
}
}
return dirty ? tmp_bfr . To_bry_and_clear ( ) : src ;
}
public void Clear ( ) { root . Clear ( ) ; count = 0 ; }
public static Btrie_slim_mgr cs ( ) { return new Btrie_slim_mgr ( Bool_ . Y ) ; }
public static Btrie_slim_mgr ci_a7 ( ) { return new Btrie_slim_mgr ( Bool_ . N ) ; }
public static Btrie_slim_mgr ci_u8 ( ) { return new Btrie_slim_mgr ( Bool_ . N ) ; }
public static Btrie_slim_mgr new_ ( boolean v ) { return new Btrie_slim_mgr ( v ) ; }
}