@ -1,6 +1,6 @@
/ *
XOWA: the XOWA Offline Wiki Application
Copyright ( C ) 2012 - 20 17 gnosygnu @gmail.com
Copyright ( C ) 2012 - 20 20 gnosygnu @gmail.com
XOWA is licensed under the terms of the General Public License ( GPL ) Version 3 ,
or alternatively under the terms of the Apache License Version 2.0 .
@ -13,293 +13,306 @@ The terms of each license can be found in the source code repository:
GPLv3 License : https : //github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License : https : //github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
* /
package gplx.xowa.xtns.mapSources ; import gplx.* ; import gplx.xowa.* ; import gplx.xowa.xtns.* ;
import gplx.core.primitives.* ; import gplx.core.btries.* ;
import gplx.xowa.parsers.* ; import gplx.xowa.parsers.tmpls.* ;
class Map_math { // REF.MW:MapSources_math.php
private int word_idx_nsew ;
private double [ ] rv = new double [ 4 ] ;
private byte dir_id ;
private int prec ;
private int step ;
public double Dec ( ) { return dec ; } private double dec ;
public int Error ( ) { return error ; } private int error ;
public double Coord_dec ( ) { return coord_dec ; } private double coord_dec ;
public double Coord_deg ( ) { return coord_deg ; } private double coord_deg ;
public double Coord_min ( ) { return coord_min ; } private double coord_min ;
public double Coord_sec ( ) { return coord_sec ; } private double coord_sec ;
public byte [ ] Coord_dir_ns ( ) { return coord_dir_ns ; } private byte [ ] coord_dir_ns ;
public byte [ ] Coord_dir_ew ( ) { return coord_dir_ew ; } private byte [ ] coord_dir_ew ;
public boolean Ctor ( byte [ ] input , int prec , byte [ ] dir , int until_step ) {
try {
New_coord ( input , dir , prec ) ;
if ( until_step > 1 & & error = = 0 )
Set_coord ( ) ;
} catch ( Exception e ) {
Err_ . Noop ( e ) ;
error = - 128 ;
}
return error = = 0 ;
}
public void Fail ( Xop_ctx ctx , byte [ ] src , Xot_invk self , Bry_bfr bfr , byte [ ] pfunc_name ) {
String page_str = ctx . Page ( ) . Url ( ) . To_str ( ) ;
String pfunc_name_str = String_ . new_u8 ( pfunc_name ) ;
String self_str = String_ . new_u8 ( src , self . Src_bgn ( ) , self . Src_end ( ) ) ;
switch ( error ) {
case - 1 : // empty coord; EX: {{#deg2dd:|precision=6}}}} PAGE:it.v:Sami; DATE:2014-03-02
case - 2 : // words > 4; EX:{{#geoLink: $1 $2 $3 $4 $5 $6|lat=51°20′ 00″19°55′ 50″}}; PAGE:pl.v:Rezerwat_przyrody_Jaksonek DATE:2014-08-14
case - 3 : // invalid delim; EX:{{#geoLink: $1 $2 $3 $4 $5 $6|lat=51°31′ 37″|long=20°13′ 17'}}; PAGE:pl.v:Rezerwat_przyrody_Ciosny DATE:2014-08-14
ctx . App ( ) . Usr_dlg ( ) . Log_many ( "" , "" , "mapSources failed: page=~{0} pfunc=~{1} err=~{2} src=~{3}" , page_str , pfunc_name_str , error , self_str ) ; // don't warn b/c there are many
break ;
default :
ctx . App ( ) . Usr_dlg ( ) . Warn_many ( "" , "" , "mapSources failed: page=~{0} pfunc=~{1} err=~{2} src=~{3}" , page_str , pfunc_name_str , error , self_str ) ;
break ;
}
}
private void New_coord ( byte [ ] input , byte [ ] dir , int prec ) { // REF.MW:newCoord
this . error = 0 ; this . word_idx_nsew = - 1 ;
coord_dec = coord_deg = coord_min = coord_sec = 0 ;
rv [ 0 ] = rv [ 1 ] = rv [ 2 ] = 0 ; rv [ 3 ] = 1 ;
this . dir_id = Parse_dir ( dir ) ;
this . prec = Parse_precision ( prec ) ;
this . dec = 0 ;
this . step = 0 ;
Parse_input ( input ) ;
}
private void Set_coord ( ) { // REF.MW:setCoord
if ( step > 1 ) return ;
if ( prec < 9 )
dec = Math_ . Round ( dec , prec ) ;
int sign = dec < 0 ? - 1 : 1 ;
double angle = Math_ . Abs_double ( dec ) ;
double deg = Math_ . Floor ( angle ) ;
double min = ( angle - deg ) * 60 ;
double sec = prec > 0
? Math_ . Round ( ( min - Math_ . Floor ( min ) ) * 60 , prec - 4 )
: Math_ . Round ( ( min - Math_ . Floor ( min ) ) * 60 , 0 )
;
min = Math_ . Floor ( min ) ;
if ( sec > = 60 ) {
sec - = 60 ;
min + + ;
}
if ( prec < 3 & & sec > = 30 )
min + + ;
if ( prec < 3 )
sec = 0 ;
if ( min > = 60 ) {
min - = 60 ;
deg + + ;
}
if ( prec < 1 & & min > = 30 ) {
deg + + ;
}
if ( prec < 1 )
min = 0 ;
coord_dec = Math_ . Round ( dec , prec ) ;
coord_deg = deg * sign ;
coord_min = min ;
coord_sec = sec ;
if ( sign > 0 ) {
coord_dir_ns = Compass_N ;
coord_dir_ew = Compass_E ;
}
else {
coord_dir_ns = Compass_S ;
coord_dir_ew = Compass_W ;
}
step = 2 ;
}
public byte [ ] Get_dms ( boolean wikibase , byte [ ] plus , byte [ ] minus ) { // REF.MW: getDMSString
if ( step < 2 ) Set_coord ( ) ;
double deg = coord_deg ;
if ( dec < 0
& & ( ( Bry_ . Len_gt_0 ( plus ) | | Bry_ . Len_gt_0 ( minus ) )
| | wikibase // NOTE: wikibase will always pass in empty plus / minus; still need to suppress "-" sign because letter has already been reversed; EX:"-2 E" -> "2 W" x> "-2 W" DATE:2017-04-02
)
) {
deg = Math_ . Abs_double ( deg ) ;
}
tmp_bfr . Add_double ( deg ) . Add ( Bry_deg ) ;
if ( prec > 0 ) {
if ( ! wikibase ) // NOTE: do not add space if wikibase, else will fail in Module:en.w:WikidataCoord; PAGE:en.w:Hulme_Arch_Bridge DATE:2017-04-02
tmp_bfr . Add_byte_space ( ) ;
tmp_bfr . Add_double ( coord_min ) . Add ( wikibase ? Bry_apos_wb : Bry_apos_mw ) ;
}
if ( prec > 2 ) {
if ( ! wikibase ) // NOTE: do not add space if wikibase, else will fail in Module:en.w:WikidataCoord; PAGE:en.w:Hulme_Arch_Bridge DATE:2017-04-02
tmp_bfr . Add_byte_space ( ) ;
tmp_bfr . Add_double ( coord_sec ) . Add ( wikibase ? Bry_quot_wb : Bry_quot_mw ) ;
}
byte [ ] letter = null ;
if ( dir_id = = Dir_lat_id )
letter = coord_dir_ns ;
if ( dir_id = = Dir_long_id )
letter = coord_dir_ew ;
if ( dec > 0 & & Bry_ . Len_gt_0 ( plus ) )
letter = plus ;
if ( dec < 0 & & Bry_ . Len_gt_0 ( minus ) )
letter = minus ;
if ( letter ! = null ) {
tmp_bfr . Add_byte_space ( ) ;
tmp_bfr . Add ( letter ) ;
}
return tmp_bfr . To_bry_and_clear ( ) ;
}
private void Parse_input ( byte [ ] src ) { // REF.MW: toDec
src = Parse_input_normalize ( tmp_bfr , src ) ;
if ( src = = null ) { error = - 1 ; return ; }
int src_len = src . length ;
int word_idx = - 1 , word_bgn = 0 , words_len = 0 ;
int i = 0 ;
while ( true ) {
boolean is_last = i = = src_len ;
byte b = is_last ? Byte_ascii . Space : src [ i ] ;
switch ( b ) {
case Byte_ascii . Space :
Parse_input_word ( rv , src , + + word_idx , word_bgn , i ) ;
+ + words_len ;
i = Bry_find_ . Find_fwd_while_space_or_tab ( src , i , src_len ) ;
word_bgn = i ;
break ;
}
if ( is_last ) break ;
i + + ;
}
if ( words_len < 1 | | words_len > 4 ) { error = - 2 ; return ; }
if ( word_idx_nsew ! = - 1 & & word_idx_nsew ! = words_len - 1 ) { error = - 10 ; return ; }
if ( rv [ 0 ] > = 0 )
dec = ( rv [ 0 ] + rv [ 1 ] / 60 + rv [ 2 ] / 3600 ) * rv [ 3 ] ;
else
dec = ( rv [ 0 ] - rv [ 1 ] / 60 - rv [ 2 ] / 3600 ) * rv [ 3 ] ;
this . step = 1 ;
}
private boolean Parse_input_word_is_compass ( byte v ) {
switch ( v ) {
case Byte_ascii . Ltr_N :
case Byte_ascii . Ltr_E :
case Byte_ascii . Ltr_S :
case Byte_ascii . Ltr_W :
return true ;
default :
return false ;
}
}
private void Parse_input_word ( double [ ] rv , byte [ ] input , int word_idx , int word_bgn , int word_end ) {
if ( word_idx > = Input_units_len ) return ;
byte unit_dlm = Input_units [ word_idx ] ;
int pos = Bry_find_ . Find_fwd ( input , unit_dlm , word_bgn , word_end ) ;
if ( pos ! = Bry_find_ . Not_found ) // remove dlms from end of bry; EX: "123'" -> "123"
word_end = pos ;
if ( ! Parse_input_word_is_compass ( input [ word_bgn ] ) ) { // if ( is_numeric( $v ) ) {
double word_val = Bry_ . To_double_or ( input , word_bgn , word_end , Double_ . NaN ) ;
if ( ! Double_ . IsNaN ( word_val ) ) {
if ( word_idx > 2 ) { error = - 4 ; return ; }
switch ( word_idx ) {
case 0 :
if ( word_val < = - 180 | | word_val > 180 ) { error = - 5 ; return ; }
rv [ 0 ] = word_val ;
break ;
case 1 :
if ( word_val < 0 | | word_val > = 60 ) { error = - 6 ; return ; }
if ( rv [ 0 ] ! = ( int ) ( rv [ 0 ] ) ) { error = - 7 ; return ; }
rv [ 1 ] = word_val ;
break ;
case 2 :
if ( word_val < 0 | | word_val > = 60 ) { error = - 8 ; return ; }
if ( rv [ 1 ] ! = ( int ) ( rv [ 1 ] ) ) { error = - 9 ; return ; }
rv [ 2 ] = word_val ;
break ;
}
}
else {
error = - 3 ;
return ;
}
}
else { // 'NSEW'
word_idx_nsew = word_idx ;
byte word_byte = input [ word_bgn ] ;
if ( rv [ 0 ] < 0 ) { error = - 11 ; return ; }
if ( word_end - word_bgn ! = 1 ) { error = - 3 ; return ; }
switch ( dir_id ) {
case Dir_long_id :
if ( word_byte = = Byte_ascii . Ltr_N | | word_byte = = Byte_ascii . Ltr_S ) { error = - 12 ; return ; }
break ;
case Dir_lat_id :
if ( word_byte = = Byte_ascii . Ltr_E | | word_byte = = Byte_ascii . Ltr_W ) { error = - 12 ; return ; }
break ;
case Dir_unknown_id :
if ( word_byte = = Byte_ascii . Ltr_N | | word_byte = = Byte_ascii . Ltr_S ) this . dir_id = Dir_lat_id ;
else this . dir_id = Dir_long_id ;
break ;
}
if ( this . dir_id = = Dir_lat_id ) {
double rv_0 = rv [ 0 ] ;
if ( rv_0 < - 90 | | rv_0 > 90 ) { error = - 13 ; return ; }
}
if ( word_byte = = Byte_ascii . Ltr_S | | word_byte = = Byte_ascii . Ltr_W )
rv [ 3 ] = - 1 ;
}
}
private static byte Parse_dir ( byte [ ] dir ) {
if ( Bry_ . Len_eq_0 ( dir ) ) return Dir_unknown_id ;
Object dir_obj = Dir_trie . Match_bgn ( dir , 0 , dir . length ) ;
return dir_obj = = null ? Dir_unknown_id : ( ( Byte_obj_val ) dir_obj ) . Val ( ) ;
}
private static int Parse_precision ( int val ) { // REF.MW: MapSourcesMath.php|newCoord
if ( val > - 1 & & val < 10 ) return val ;
else if ( val = = - 1 ) return 9 ;
else return 4 ;
}
private Bry_bfr tmp_bfr = Bry_bfr_ . Reset ( 32 ) ;
public static byte [ ] Parse_input_normalize ( Bry_bfr bfr , byte [ ] src ) {
/ *
$w = str_replace ( array ( '‘ ' , '’ ' , '′ ' ) , "'" , $input ) ;
$w = str_replace ( array ( "''" , '“' , '”' , '″' ) , '"' , $w ) ;
$w = str_replace ( '− ' , '-' , $w ) ;
$w = strtoupper ( str_replace ( array ( '_' , '/' , "\t" , "\n" , "\r" ) , ' ' , $w ) ) ;
$w = str_replace ( array ( '°' , "'" , '"' ) , array ( ' ° ' , "' " , ' " ' ) , $w ) ;
$w = trim ( str_replace ( array ( 'N' , 'S' , 'E' , 'W' ) , array ( ' N ' , ' S ' , ' E ' , ' W ' ) , $w ) ) ;
* /
int src_end = src . length ; if ( src_end = = 0 ) return null ;
src = Trie__normalize__apos . Replace ( bfr , src , 0 , src_end ) ; // normalize apos separately, since 2 apos can go to quotes; EX: ‘ ’ -> "; PAGE:it.v:Morro_d'Oro DATE:2015-12-06
src = Trie__normalize__rest . Replace ( bfr , src , 0 , src . length ) ; // normalize rest;
return Bry_ . Trim ( src ) ;
}
private static final byte [ ]
Bry_deg = Bry_ . new_u8 ( "°" )
, Bry_quot_mw = Bry_ . new_a7 ( """ )
, Bry_quot_wb = Bry_ . new_a7 ( """ ) // REF:en.w:Module:WikidataCoord
, Bry_apos_mw = Bry_ . new_a7 ( "'" )
, Bry_apos_wb = Bry_ . new_a7 ( "'" ) // REF:en.w:Module:WikidataCoord
;
private static final byte Dir_unknown_id = 0 , Dir_lat_id = 1 , Dir_long_id = 2 ;
public static final byte [ ] Dir_lat_bry = Bry_ . new_a7 ( "lat" ) , Dir_long_bry = Bry_ . new_a7 ( "long" ) ;
private static final Btrie_slim_mgr Dir_trie = Btrie_slim_mgr . ci_a7 ( ) // NOTE:ci.ascii:MW_const.en
. Add_bry_byte ( Dir_lat_bry , Dir_lat_id )
. Add_bry_byte ( Dir_long_bry , Dir_long_id )
;
private static final byte [ ]
Compass_N = new byte [ ] { Byte_ascii . Ltr_N }
, Compass_E = new byte [ ] { Byte_ascii . Ltr_E }
, Compass_S = new byte [ ] { Byte_ascii . Ltr_S }
, Compass_W = new byte [ ] { Byte_ascii . Ltr_W }
;
private static final byte Input_byte_degree = Byte_ascii . Slash ; // NOTE: ugly cheat to avoid using multi-byte char; note that all "/" are swapped out to " ", so any remaining "/" was added by the normalizer; EX: "123° 4/5" -> "123/ 4 5"
private static final byte [ ] Input_units = new byte [ ] { Input_byte_degree , Byte_ascii . Apos , Byte_ascii . Quote , Byte_ascii . Space } ;
private static final int Input_units_len = Input_units . length ;
private static final Btrie_slim_mgr Trie__normalize__apos = Btrie_slim_mgr . cs ( )
. Add_replace_many ( Byte_ascii . Apos_bry , "‘ " , "’ " , "′ " ) ;
private static final Btrie_slim_mgr Trie__normalize__rest = Btrie_slim_mgr . cs ( )
. Add_replace_many ( "' " , "'" )
. Add_replace_many ( "\" " , "\"" , "''" , "“" , "”" , "″" )
. Add_replace_many ( Byte_ascii . Dash_bry , "-" , "− " ) // NOTE: emdash and endash
. Add_replace_many ( Byte_ascii . Space_bry , " " , "_" , "/" , "\t" , "\n" , "\r" ) // NOTE: " " =
. Add_replace_many ( "/ " , "°" )
. Add_replace_many ( " N" , "N" , "n" )
. Add_replace_many ( " S" , "S" , "s" )
. Add_replace_many ( " E" , "E" , "e" )
. Add_replace_many ( " W" , "W" , "w" ) ;
public static final Map_math Instance = new Map_math ( ) ;
}
package gplx.xowa.xtns.mapSources ;
import gplx.Bry_ ;
import gplx.Bry_bfr ;
import gplx.Bry_bfr_ ;
import gplx.Bry_find_ ;
import gplx.Byte_ascii ;
import gplx.Double_ ;
import gplx.Err_ ;
import gplx.Math_ ;
import gplx.String_ ;
import gplx.core.btries.Btrie_slim_mgr ;
import gplx.core.primitives.Byte_obj_val ;
import gplx.xowa.parsers.Xop_ctx ;
import gplx.xowa.parsers.tmpls.Xot_invk ;
class Map_math { // REF.MW:MapSources_math.php
private int word_idx_nsew ;
private double [ ] rv = new double [ 4 ] ;
private byte dir_id ;
private int prec ;
private int step ;
public double Dec ( ) { return dec ; } private double dec ;
public int Error ( ) { return error ; } private int error ;
public double Coord_dec ( ) { return coord_dec ; } private double coord_dec ;
public double Coord_deg ( ) { return coord_deg ; } private double coord_deg ;
public double Coord_min ( ) { return coord_min ; } private double coord_min ;
public double Coord_sec ( ) { return coord_sec ; } private double coord_sec ;
public byte [ ] Coord_dir_ns ( ) { return coord_dir_ns ; } private byte [ ] coord_dir_ns ;
public byte [ ] Coord_dir_ew ( ) { return coord_dir_ew ; } private byte [ ] coord_dir_ew ;
public boolean Ctor ( byte [ ] input , int prec , byte [ ] dir , int until_step ) {
try {
New_coord ( input , dir , prec ) ;
if ( until_step > 1 & & error = = 0 )
Set_coord ( ) ;
} catch ( Exception e ) {
Err_ . Noop ( e ) ;
error = - 128 ;
}
return error = = 0 ;
}
public void Fail ( Xop_ctx ctx , byte [ ] src , Xot_invk self , Bry_bfr bfr , byte [ ] pfunc_name ) {
String page_str = ctx . Page ( ) . Url ( ) . To_str ( ) ;
String pfunc_name_str = String_ . new_u8 ( pfunc_name ) ;
String self_str = String_ . new_u8 ( src , self . Src_bgn ( ) , self . Src_end ( ) ) ;
switch ( error ) {
case - 1 : // empty coord; EX: {{#deg2dd:|precision=6}}}} PAGE:it.v:Sami; DATE:2014-03-02
case - 2 : // words > 4; EX:{{#geoLink: $1 $2 $3 $4 $5 $6|lat=51°20′ 00″19°55′ 50″}}; PAGE:pl.v:Rezerwat_przyrody_Jaksonek DATE:2014-08-14
case - 3 : // invalid delim; EX:{{#geoLink: $1 $2 $3 $4 $5 $6|lat=51°31′ 37″|long=20°13′ 17'}}; PAGE:pl.v:Rezerwat_przyrody_Ciosny DATE:2014-08-14
ctx . App ( ) . Usr_dlg ( ) . Log_many ( "" , "" , "mapSources failed: page=~{0} pfunc=~{1} err=~{2} src=~{3}" , page_str , pfunc_name_str , error , self_str ) ; // don't warn b/c there are many
break ;
default :
ctx . App ( ) . Usr_dlg ( ) . Warn_many ( "" , "" , "mapSources failed: page=~{0} pfunc=~{1} err=~{2} src=~{3}" , page_str , pfunc_name_str , error , self_str ) ;
break ;
}
}
private void New_coord ( byte [ ] input , byte [ ] dir , int prec ) { // REF.MW:newCoord
this . error = 0 ; this . word_idx_nsew = - 1 ;
coord_dec = coord_deg = coord_min = coord_sec = 0 ;
rv [ 0 ] = rv [ 1 ] = rv [ 2 ] = 0 ; rv [ 3 ] = 1 ;
this . dir_id = Parse_dir ( dir ) ;
this . prec = Parse_precision ( prec ) ;
this . dec = 0 ;
this . step = 0 ;
Parse_input ( input ) ;
}
private void Set_coord ( ) { // REF.MW:setCoord
if ( step > 1 ) return ;
if ( prec < 9 )
dec = Math_ . Round ( dec , prec ) ;
int sign = dec < 0 ? - 1 : 1 ;
double angle = Math_ . Abs_double ( dec ) ;
double deg = Math_ . Floor ( angle ) ;
double min = ( angle - deg ) * 60 ;
double sec = prec > 4 // 2020-09-03|ISSUE#:792|precision check should be > 4 not > 0;PAGE:en.w:Huntington_Plaza
? Math_ . Round ( ( min - Math_ . Floor ( min ) ) * 60 , prec - 4 )
: Math_ . Round ( ( min - Math_ . Floor ( min ) ) * 60 , 0 )
;
min = Math_ . Floor ( min ) ;
if ( sec > = 60 ) {
sec - = 60 ;
min + + ;
}
if ( prec < 3 & & sec > = 30 )
min + + ;
if ( prec < 3 )
sec = 0 ;
if ( min > = 60 ) {
min - = 60 ;
deg + + ;
}
if ( prec < 1 & & min > = 30 ) {
deg + + ;
}
if ( prec < 1 )
min = 0 ;
coord_dec = Math_ . Round ( dec , prec ) ;
coord_deg = deg * sign ;
coord_min = min ;
coord_sec = sec ;
if ( sign > 0 ) {
coord_dir_ns = Compass_N ;
coord_dir_ew = Compass_E ;
}
else {
coord_dir_ns = Compass_S ;
coord_dir_ew = Compass_W ;
}
step = 2 ;
}
public byte [ ] Get_dms ( boolean wikibase , byte [ ] plus , byte [ ] minus ) { // REF.MW: getDMSString
if ( step < 2 ) Set_coord ( ) ;
double deg = coord_deg ;
if ( dec < 0
& & ( ( Bry_ . Len_gt_0 ( plus ) | | Bry_ . Len_gt_0 ( minus ) )
| | wikibase // NOTE: wikibase will always pass in empty plus / minus; still need to suppress "-" sign because letter has already been reversed; EX:"-2 E" -> "2 W" x> "-2 W" DATE:2017-04-02
)
) {
deg = Math_ . Abs_double ( deg ) ;
}
tmp_bfr . Add_double ( deg ) . Add ( Bry_deg ) ;
if ( prec > 0 ) {
if ( ! wikibase ) // NOTE: do not add space if wikibase, else will fail in Module:en.w:WikidataCoord; PAGE:en.w:Hulme_Arch_Bridge DATE:2017-04-02
tmp_bfr . Add_byte_space ( ) ;
tmp_bfr . Add_double ( coord_min ) . Add ( wikibase ? Bry_apos_wb : Bry_apos_mw ) ;
}
if ( prec > 2 ) {
if ( ! wikibase ) // NOTE: do not add space if wikibase, else will fail in Module:en.w:WikidataCoord; PAGE:en.w:Hulme_Arch_Bridge DATE:2017-04-02
tmp_bfr . Add_byte_space ( ) ;
tmp_bfr . Add_double ( coord_sec ) . Add ( wikibase ? Bry_quot_wb : Bry_quot_mw ) ;
}
byte [ ] letter = null ;
if ( dir_id = = Dir_lat_id )
letter = coord_dir_ns ;
if ( dir_id = = Dir_long_id )
letter = coord_dir_ew ;
if ( dec > 0 & & Bry_ . Len_gt_0 ( plus ) )
letter = plus ;
if ( dec < 0 & & Bry_ . Len_gt_0 ( minus ) )
letter = minus ;
if ( letter ! = null ) {
tmp_bfr . Add_byte_space ( ) ;
tmp_bfr . Add ( letter ) ;
}
return tmp_bfr . To_bry_and_clear ( ) ;
}
private void Parse_input ( byte [ ] src ) { // REF.MW: toDec
src = Parse_input_normalize ( tmp_bfr , src ) ;
if ( src = = null ) { error = - 1 ; return ; }
int src_len = src . length ;
int word_idx = - 1 , word_bgn = 0 , words_len = 0 ;
int i = 0 ;
while ( true ) {
boolean is_last = i = = src_len ;
byte b = is_last ? Byte_ascii . Space : src [ i ] ;
switch ( b ) {
case Byte_ascii . Space :
Parse_input_word ( rv , src , + + word_idx , word_bgn , i ) ;
+ + words_len ;
i = Bry_find_ . Find_fwd_while_space_or_tab ( src , i , src_len ) ;
word_bgn = i ;
break ;
}
if ( is_last ) break ;
i + + ;
}
if ( words_len < 1 | | words_len > 4 ) { error = - 2 ; return ; }
if ( word_idx_nsew ! = - 1 & & word_idx_nsew ! = words_len - 1 ) { error = - 10 ; return ; }
if ( rv [ 0 ] > = 0 )
dec = ( rv [ 0 ] + rv [ 1 ] / 60 + rv [ 2 ] / 3600 ) * rv [ 3 ] ;
else
dec = ( rv [ 0 ] - rv [ 1 ] / 60 - rv [ 2 ] / 3600 ) * rv [ 3 ] ;
this . step = 1 ;
}
private boolean Parse_input_word_is_compass ( byte v ) {
switch ( v ) {
case Byte_ascii . Ltr_N :
case Byte_ascii . Ltr_E :
case Byte_ascii . Ltr_S :
case Byte_ascii . Ltr_W :
return true ;
default :
return false ;
}
}
private void Parse_input_word ( double [ ] rv , byte [ ] input , int word_idx , int word_bgn , int word_end ) {
if ( word_idx > = Input_units_len ) return ;
byte unit_dlm = Input_units [ word_idx ] ;
int pos = Bry_find_ . Find_fwd ( input , unit_dlm , word_bgn , word_end ) ;
if ( pos ! = Bry_find_ . Not_found ) // remove dlms from end of bry; EX: "123'" -> "123"
word_end = pos ;
if ( ! Parse_input_word_is_compass ( input [ word_bgn ] ) ) { // if ( is_numeric( $v ) ) {
double word_val = Bry_ . To_double_or ( input , word_bgn , word_end , Double_ . NaN ) ;
if ( ! Double_ . IsNaN ( word_val ) ) {
if ( word_idx > 2 ) { error = - 4 ; return ; }
switch ( word_idx ) {
case 0 :
if ( word_val < = - 180 | | word_val > 180 ) { error = - 5 ; return ; }
rv [ 0 ] = word_val ;
break ;
case 1 :
if ( word_val < 0 | | word_val > = 60 ) { error = - 6 ; return ; }
if ( rv [ 0 ] ! = ( int ) ( rv [ 0 ] ) ) { error = - 7 ; return ; }
rv [ 1 ] = word_val ;
break ;
case 2 :
if ( word_val < 0 | | word_val > = 60 ) { error = - 8 ; return ; }
if ( rv [ 1 ] ! = ( int ) ( rv [ 1 ] ) ) { error = - 9 ; return ; }
rv [ 2 ] = word_val ;
break ;
}
}
else {
error = - 3 ;
return ;
}
}
else { // 'NSEW'
word_idx_nsew = word_idx ;
byte word_byte = input [ word_bgn ] ;
if ( rv [ 0 ] < 0 ) { error = - 11 ; return ; }
if ( word_end - word_bgn ! = 1 ) { error = - 3 ; return ; }
switch ( dir_id ) {
case Dir_long_id :
if ( word_byte = = Byte_ascii . Ltr_N | | word_byte = = Byte_ascii . Ltr_S ) { error = - 12 ; return ; }
break ;
case Dir_lat_id :
if ( word_byte = = Byte_ascii . Ltr_E | | word_byte = = Byte_ascii . Ltr_W ) { error = - 12 ; return ; }
break ;
case Dir_unknown_id :
if ( word_byte = = Byte_ascii . Ltr_N | | word_byte = = Byte_ascii . Ltr_S ) this . dir_id = Dir_lat_id ;
else this . dir_id = Dir_long_id ;
break ;
}
if ( this . dir_id = = Dir_lat_id ) {
double rv_0 = rv [ 0 ] ;
if ( rv_0 < - 90 | | rv_0 > 90 ) { error = - 13 ; return ; }
}
if ( word_byte = = Byte_ascii . Ltr_S | | word_byte = = Byte_ascii . Ltr_W )
rv [ 3 ] = - 1 ;
}
}
private static byte Parse_dir ( byte [ ] dir ) {
if ( Bry_ . Len_eq_0 ( dir ) ) return Dir_unknown_id ;
Object dir_obj = Dir_trie . Match_bgn ( dir , 0 , dir . length ) ;
return dir_obj = = null ? Dir_unknown_id : ( ( Byte_obj_val ) dir_obj ) . Val ( ) ;
}
private static int Parse_precision ( int val ) { // REF.MW: MapSourcesMath.php|newCoord
if ( val > - 1 & & val < 10 ) return val ;
else if ( val = = - 1 ) return 9 ;
else return 4 ;
}
private Bry_bfr tmp_bfr = Bry_bfr_ . Reset ( 32 ) ;
public static byte [ ] Parse_input_normalize ( Bry_bfr bfr , byte [ ] src ) {
/ *
$w = str_replace ( array ( '‘ ' , '’ ' , '′ ' ) , "'" , $input ) ;
$w = str_replace ( array ( "''" , '“' , '”' , '″' ) , '"' , $w ) ;
$w = str_replace ( '− ' , '-' , $w ) ;
$w = strtoupper ( str_replace ( array ( '_' , '/' , "\t" , "\n" , "\r" ) , ' ' , $w ) ) ;
$w = str_replace ( array ( '°' , "'" , '"' ) , array ( ' ° ' , "' " , ' " ' ) , $w ) ;
$w = trim ( str_replace ( array ( 'N' , 'S' , 'E' , 'W' ) , array ( ' N ' , ' S ' , ' E ' , ' W ' ) , $w ) ) ;
* /
int src_end = src . length ; if ( src_end = = 0 ) return null ;
src = Trie__normalize__apos . Replace ( bfr , src , 0 , src_end ) ; // normalize apos separately, since 2 apos can go to quotes; EX: ‘ ’ -> "; PAGE:it.v:Morro_d'Oro DATE:2015-12-06
src = Trie__normalize__rest . Replace ( bfr , src , 0 , src . length ) ; // normalize rest;
return Bry_ . Trim ( src ) ;
}
private static final byte [ ]
Bry_deg = Bry_ . new_u8 ( "°" )
, Bry_quot_mw = Bry_ . new_a7 ( """ )
, Bry_quot_wb = Bry_ . new_a7 ( """ ) // REF:en.w:Module:WikidataCoord
, Bry_apos_mw = Bry_ . new_a7 ( "'" )
, Bry_apos_wb = Bry_ . new_a7 ( "'" ) // REF:en.w:Module:WikidataCoord
;
private static final byte Dir_unknown_id = 0 , Dir_lat_id = 1 , Dir_long_id = 2 ;
public static final byte [ ] Dir_lat_bry = Bry_ . new_a7 ( "lat" ) , Dir_long_bry = Bry_ . new_a7 ( "long" ) ;
private static final Btrie_slim_mgr Dir_trie = Btrie_slim_mgr . ci_a7 ( ) // NOTE:ci.ascii:MW_const.en
. Add_bry_byte ( Dir_lat_bry , Dir_lat_id )
. Add_bry_byte ( Dir_long_bry , Dir_long_id )
;
private static final byte [ ]
Compass_N = new byte [ ] { Byte_ascii . Ltr_N }
, Compass_E = new byte [ ] { Byte_ascii . Ltr_E }
, Compass_S = new byte [ ] { Byte_ascii . Ltr_S }
, Compass_W = new byte [ ] { Byte_ascii . Ltr_W }
;
private static final byte Input_byte_degree = Byte_ascii . Slash ; // NOTE: ugly cheat to avoid using multi-byte char; note that all "/" are swapped out to " ", so any remaining "/" was added by the normalizer; EX: "123° 4/5" -> "123/ 4 5"
private static final byte [ ] Input_units = new byte [ ] { Input_byte_degree , Byte_ascii . Apos , Byte_ascii . Quote , Byte_ascii . Space } ;
private static final int Input_units_len = Input_units . length ;
private static final Btrie_slim_mgr Trie__normalize__apos = Btrie_slim_mgr . cs ( )
. Add_replace_many ( Byte_ascii . Apos_bry , "‘ " , "’ " , "′ " ) ;
private static final Btrie_slim_mgr Trie__normalize__rest = Btrie_slim_mgr . cs ( )
. Add_replace_many ( "' " , "'" )
. Add_replace_many ( "\" " , "\"" , "''" , "“" , "”" , "″" )
. Add_replace_many ( Byte_ascii . Dash_bry , "-" , "− " ) // NOTE: emdash and endash
. Add_replace_many ( Byte_ascii . Space_bry , " " , "_" , "/" , "\t" , "\n" , "\r" ) // NOTE: " " =
. Add_replace_many ( "/ " , "°" )
. Add_replace_many ( " N" , "N" , "n" )
. Add_replace_many ( " S" , "S" , "s" )
. Add_replace_many ( " E" , "E" , "e" )
. Add_replace_many ( " W" , "W" , "w" ) ;
public static final Map_math Instance = new Map_math ( ) ;
}