@@ -35,25 +35,51 @@ class DataAccess {
3535
3636 private static final int NR_TERRITORIES ;
3737 private static final int NR_TERRITORY_RECORDS ;
38- private static final int [] DATA_START ;
39- private static final int [] FILE_DATA ;
38+
39+ private static final int [] INDEX ;
40+ private static final int [] DATA ;
41+
42+ private static final int HEADER_ID_1 = 0 ;
43+ private static final int HEADER_ID_2 = 1 ;
44+ private static final int HEADER_VERSION_LO = 2 ;
45+ private static final int HEADER_VERSION_HI = 3 ;
46+ private static final int HEADER_NR_TERRITORIES_RECS_LO = 4 ;
47+ private static final int HEADER_NR_TERRITORIES_RECS_HI = 5 ;
48+ private static final int HEADER_NR_TERRITORIES_LO = 6 ;
49+ private static final int HEADER_NR_TERRITORIES_HI = 7 ;
50+ private static final int HEADER_SIZE = HEADER_NR_TERRITORIES_HI + 1 ;
51+
52+ private static final int BYTES_PER_INT = 2 ;
53+ private static final int BYTES_PER_LONG = 4 ;
54+
55+ private static final int POS_DATA_LON_MICRO_DEG_MIN = 0 ;
56+ private static final int POS_DATA_LAT_MICRO_DEG_MIN = 1 ;
57+ private static final int POS_DATA_LON_MICRO_DEG_MAX = 2 ;
58+ private static final int POS_DATA_LAT_MICRO_DEG_MAX = 3 ;
59+ private static final int POS_DATA_DATA_FLAGS = 4 ;
60+ private static final int DATA_FIELDS_PER_REC = 5 ;
61+
62+ private static final int MASK_DATA_DATA_FLAGS = 0xffff ;
63+ private static final int SHIFT_POS_DATA_SMART_DIV = 16 ;
64+
65+ private static final int POS_INDEX_FIRST_RECORD = 0 ;
66+ private static final int POS_INDEX_LAST_RECORD = 1 ;
4067
4168 private static final String FILE_NAME = "/com/mapcode/mminfo.dat" ;
42- private static final int HEADER_SIZE = 8 ;
69+ private static final int FILE_BUFFER_SIZE = 50000 ;
4370
4471 // Read data only once in static initializer.
4572 static {
4673 LOG .info ("DataAccess: reading regions from file: {}" , FILE_NAME );
47- final int bufferSize = 131072 ;
48- final byte [] readBuffer = new byte [bufferSize ];
74+ final byte [] readBuffer = new byte [FILE_BUFFER_SIZE ];
4975 int total = 0 ;
5076 try {
5177 final InputStream inputStream = DataAccess .class .getResourceAsStream (FILE_NAME );
5278 try {
5379 final ByteArrayOutputStream outputStream = new ByteArrayOutputStream ();
5480 try {
5581 int nrBytes = inputStream .read (readBuffer );
56- while (nrBytes >= 0 ) {
82+ while (nrBytes > 0 ) {
5783 total += nrBytes ;
5884 outputStream .write (readBuffer , 0 , nrBytes );
5985 nrBytes = inputStream .read (readBuffer );
@@ -65,33 +91,36 @@ class DataAccess {
6591
6692 // Read SIGNATURE "MC", VERSION.
6793 assert total > 12 ;
68- assert (char ) bytes [0 ] == 'M' ;
69- assert (char ) bytes [1 ] == 'C' ;
70- final int dataVersion = (bytes [2 ] & 255 ) + (( bytes [3 ] & 255 ) << 8 );
94+ assert (char ) bytes [HEADER_ID_1 ] == 'M' ;
95+ assert (char ) bytes [HEADER_ID_2 ] == 'C' ;
96+ final int dataVersion = readIntLoHi (bytes [HEADER_VERSION_LO ], bytes [HEADER_VERSION_HI ] );
7197 assert (dataVersion >= 220 );
7298
7399 // Read header: NR TERRITORIES, NR RECTANGLE RECORD.
74- NR_TERRITORY_RECORDS = (bytes [4 ] & 255 ) + ((bytes [5 ] & 255 ) << 8 );
75- NR_TERRITORIES = (bytes [6 ] & 255 ) + ((bytes [7 ] & 255 ) << 8 );
76- LOG .info ("version={} NR_TERRITORIES={} NR_TERRITORY_RECORDS={}" , dataVersion , NR_TERRITORIES , NR_TERRITORY_RECORDS );
77- final int expectedsize = HEADER_SIZE + ((NR_TERRITORIES + 1 ) * 2 ) + (NR_TERRITORY_RECORDS * 20 );
78- assert (expectedsize == total );
100+ NR_TERRITORY_RECORDS = readIntLoHi (bytes [HEADER_NR_TERRITORIES_RECS_LO ], bytes [HEADER_NR_TERRITORIES_RECS_HI ]);
101+ NR_TERRITORIES = readIntLoHi (bytes [HEADER_NR_TERRITORIES_LO ], bytes [HEADER_NR_TERRITORIES_HI ]);
102+ final int expectedSize = HEADER_SIZE +
103+ ((NR_TERRITORIES + 1 ) * BYTES_PER_INT ) +
104+ (NR_TERRITORY_RECORDS * (DATA_FIELDS_PER_REC * BYTES_PER_LONG ));
105+
106+ if (expectedSize != total ) {
107+ LOG .error ("DataAccess: expected {} territories, got {}" , expectedSize , total );
108+ throw new IllegalStateException ("Data file corrupt: " + FILE_NAME );
109+ }
110+ LOG .debug ("DataAccess: version={} territories={} territory records={}" , dataVersion , NR_TERRITORIES , NR_TERRITORY_RECORDS );
79111
80112 // Read DATA+START array (2 bytes per territory, plus closing record).
81- DATA_START = new int [NR_TERRITORIES + 1 ];
113+ INDEX = new int [NR_TERRITORIES + 1 ];
82114 int i = HEADER_SIZE ;
83115 for (int k = 0 ; k <= NR_TERRITORIES ; k ++) {
84- DATA_START [k ] = (bytes [i ] & 255 ) + (( bytes [i + 1 ] & 255 ) << 8 );
116+ INDEX [k ] = readIntLoHi (bytes [i ], bytes [i + 1 ]);
85117 i += 2 ;
86118 }
87119
88- // Read territory rectangle data (5 longs per record).
89- FILE_DATA = new int [NR_TERRITORY_RECORDS * 5 ];
90- for (int k = 0 ; k < (NR_TERRITORY_RECORDS * 5 ); k ++) {
91- FILE_DATA [k ] = ((bytes [i ] & 255 )) +
92- ((bytes [i + 1 ] & 255 ) << 8 ) +
93- ((bytes [i + 2 ] & 255 ) << 16 ) +
94- ((bytes [i + 3 ] & 255 ) << 24 );
120+ // Read territory rectangle data (DATA_FIELDS_PER_REC longs per record).
121+ DATA = new int [NR_TERRITORY_RECORDS * DATA_FIELDS_PER_REC ];
122+ for (int k = 0 ; k < (NR_TERRITORY_RECORDS * DATA_FIELDS_PER_REC ); k ++) {
123+ DATA [k ] = readLongLoHi (bytes [i ], bytes [i + 1 ], bytes [i + 2 ], bytes [i + 3 ]);
95124 i += 4 ;
96125 }
97126 } finally {
@@ -107,40 +136,51 @@ class DataAccess {
107136 LOG .info ("DataAccess: regions initialized, read {} bytes" , total );
108137 }
109138
139+ private static int readIntLoHi (final int lo , final int hi ) {
140+ return (lo & 0xff ) + ((hi & 0xff ) << 8 );
141+ }
142+
143+ private static int readLongLoHi (final int lo , final int mid1 , final int mid2 , final int hi ) {
144+ return ((lo & 0xff )) + ((mid1 & 0xff ) << 8 ) + ((mid2 & 0xff ) << 16 ) + ((hi & 0xff ) << 24 );
145+ }
146+
110147 private DataAccess () {
111148 // Empty.
112149 }
113150
151+ @ SuppressWarnings ("PointlessArithmeticExpression" )
114152 static int getLonMicroDegMin (final int territoryRecord ) {
115- return FILE_DATA [ territoryRecord * 5 ];
153+ return DATA [(( territoryRecord * DATA_FIELDS_PER_REC ) + POS_DATA_LON_MICRO_DEG_MIN ) ];
116154 }
117155
118156 static int getLatMicroDegMin (final int territoryRecord ) {
119- return FILE_DATA [(territoryRecord * 5 ) + 1 ];
157+ return DATA [(territoryRecord * DATA_FIELDS_PER_REC ) + POS_DATA_LAT_MICRO_DEG_MIN ];
120158 }
121159
122160 static int getLonMicroDegMax (final int territoryRecord ) {
123- return FILE_DATA [(territoryRecord * 5 ) + 2 ];
161+ return DATA [(territoryRecord * DATA_FIELDS_PER_REC ) + POS_DATA_LON_MICRO_DEG_MAX ];
124162 }
125163
126164 static int getLatMicroDegMax (final int territoryRecord ) {
127- return FILE_DATA [(territoryRecord * 5 ) + 3 ];
165+ return DATA [(territoryRecord * DATA_FIELDS_PER_REC ) + POS_DATA_LAT_MICRO_DEG_MAX ];
128166 }
129167
130168 static int getDataFlags (final int territoryRecord ) {
131- return FILE_DATA [(territoryRecord * 5 ) + 4 ] & 65535 ;
169+ return DATA [(territoryRecord * DATA_FIELDS_PER_REC ) + POS_DATA_DATA_FLAGS ] & MASK_DATA_DATA_FLAGS ;
132170 }
133171
134172 static int getSmartDiv (final int territoryRecord ) {
135- return FILE_DATA [(territoryRecord * 5 ) + 4 ] >> 16 ;
173+ return DATA [(territoryRecord * DATA_FIELDS_PER_REC ) + POS_DATA_DATA_FLAGS ] >> SHIFT_POS_DATA_SMART_DIV ;
136174 }
137175
138- // / low-level routines for data access
176+ // Low-level routines for data access.
177+ @ SuppressWarnings ("PointlessArithmeticExpression" )
139178 static int getDataFirstRecord (final int territoryNumber ) {
140- return DATA_START [territoryNumber ];
179+ return INDEX [territoryNumber + POS_INDEX_FIRST_RECORD ];
141180 }
142181
143182 static int getDataLastRecord (final int territoryNumber ) {
144- return DATA_START [territoryNumber + 1 ] - 1 ;
183+ return INDEX [territoryNumber + POS_INDEX_LAST_RECORD ] - 1 ;
145184 }
146185}
186+
0 commit comments