@@ -185,6 +185,7 @@ static int disambiguate_str(const char *s, int len) // returns disambiguation 1-
185185}
186186
187187
188+ #ifndef FAST_ALPHA
188189// returns coode, or negative if invalid
189190static int ccode_of_iso3 (const char * in_iso , int parentcode ) {
190191 const char * aliases = ALIASES ;
@@ -196,12 +197,14 @@ static int ccode_of_iso3(const char *in_iso, int parentcode) {
196197 if (in_iso [2 ]) {
197198 if (in_iso [2 ] == '-' ) {
198199 parentcode = disambiguate_str (in_iso , 2 );
199- hyphenated = (parentcode > 0 );
200+ if (parentcode < 0 ) { return parentcode ; }
201+ hyphenated = 1 ;
200202 in_iso += 3 ;
201203 }
202204 else if (in_iso [3 ] == '-' ) {
203205 parentcode = disambiguate_str (in_iso , 3 );
204- hyphenated = (parentcode > 0 );
206+ if (parentcode < 0 ) { return parentcode ; }
207+ hyphenated = 1 ;
205208 in_iso += 4 ;
206209 }
207210 }
@@ -211,11 +214,12 @@ static int ccode_of_iso3(const char *in_iso, int parentcode) {
211214 iso [0 ] = (char ) toupper (in_iso [0 ]);
212215 if (iso [0 ]) { iso [1 ] = (char ) toupper (in_iso [1 ]); }
213216 if (iso [1 ]) { iso [2 ] = (char ) toupper (in_iso [2 ]); }
217+ if (iso [2 ] && in_iso [3 ]!= 0 && in_iso [3 ]!= '-' ) { return -41 ; }
214218 iso [3 ] = 0 ;
215219
216220 if (iso [2 ] == 0 || iso [2 ] == ' ' ) // 2-letter iso code?
217221 {
218- static char disambiguate_iso3 [4 ] = {'1 ' , '?' , '?' , 0 }; // cache for disambiguation
222+ static char disambiguate_iso3 [4 ] = {'0 ' , '?' , '?' , 0 }; // cache for disambiguation
219223 if (parentcode > 0 ) {
220224 disambiguate_iso3 [0 ] = (char ) ('0' + parentcode );
221225 }
@@ -227,7 +231,7 @@ static int ccode_of_iso3(const char *in_iso, int parentcode) {
227231 s = strstr (aliases , disambiguate_iso3 ); // search in aliases
228232 if (s == NULL || s [3 ] != '=' ) {
229233 s = NULL ;
230- if (disambiguate_iso3 [0 ] <= '9' ) {
234+ if (disambiguate_iso3 [0 ] <= '9' && ! hyphenated ) {
231235 disambiguate_iso3 [0 ] = '0' ;
232236 s = strstr (aliases , disambiguate_iso3 ); // search in aliases
233237 }
@@ -237,7 +241,7 @@ static int ccode_of_iso3(const char *in_iso, int parentcode) {
237241 s = strstr (entity_iso , iso ); // search disambiguated 2-letter iso
238242 }
239243 }
240- if (s == NULL ) {
244+ if (s == NULL && ! hyphenated ) {
241245 // find the FIRST disambiguation option, if any
242246 for (s = entity_iso - 1 ; ;) {
243247 s = strstr (s + 1 , disambiguate_iso3 + 1 );
@@ -293,7 +297,7 @@ static int ccode_of_iso3(const char *in_iso, int parentcode) {
293297 // return result
294298 return (int ) ((s - entity_iso ) / 4 );
295299}
296-
300+ #endif
297301
298302////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
299303//
@@ -357,6 +361,9 @@ static int decodeExtension(decodeRec *dec, int dividerx4, int dividery0, int lon
357361 int lat32 = 0 ;
358362 int processor = 1 ;
359363 int odd = 0 ;
364+ if (strlen (extrapostfix )> MAX_PRECISION_DIGITS ) {
365+ return -79 ; // too many digits
366+ }
360367 while (* extrapostfix ) {
361368 int column1 , row1 , column2 , row2 ;
362369 int c1 = * extrapostfix ++ ;
@@ -978,8 +985,8 @@ static void repack_if_alldigits(char *input, int aonly) {
978985 }
979986}
980987
981- static int unpack_if_alldigits (
982- char * input ) // returns 1 if unpacked, 0 if left unchanged, negative if unchanged and an error was detected
988+ // returns 1 if unpacked, 0 if left unchanged, negative if unchanged and an error was detected
989+ static int unpack_if_alldigits ( char * input )
983990{ // rewrite all-digit codes
984991 char * s = input ;
985992 char * dotpos = NULL ;
@@ -1029,6 +1036,8 @@ static int unpack_if_alldigits(
10291036 if (v < 100 ) {
10301037 * s = encode_chars [(unsigned int ) v / 10 ];
10311038 * e = encode_chars [(unsigned int ) v % 10 ];
1039+ } else {
1040+ return -31 ; // overflow (ending in UE or UU)
10321041 }
10331042 return 1 ;
10341043 }
@@ -1397,22 +1406,22 @@ static int decoderEngine(decodeRec *dec) {
13971406 if (s ) {
13981407 * s ++ = 0 ;
13991408 while (* s > 0 && * s <= 32 ) { s ++ ; }
1400- ccode = ccode_of_iso3 (w , dec -> context ) ;
1409+ ccode = convertTerritoryIsoNameToCode (w , dec -> context - 1 ) - 1 ;
14011410 }
14021411 else {
14031412 ccode = dec -> context - 1 ;
14041413 s = w ;
14051414 }
14061415 if (ccode == ccode_mex && len < 8 ) {
1407- ccode = ccode_of_iso3 ("5MX" , -1 );
1416+ ccode = convertTerritoryIsoNameToCode ("5MX" , -1 ) - 1 ;
14081417 } // special case for mexico country vs state
14091418 if (* s == 'u' || * s == 'U' ) {
14101419 strcpy (s ,s + 1 );
14111420 repack_if_alldigits (s , 1 );
14121421 }
14131422 dec -> context = ccode ;
14141423 dec -> mapcode = s ;
1415- dec -> extension = "" ;
1424+ dec -> extension = NULL ;
14161425 // make upper, handle i and o, split off high precision characters if any
14171426 for (w = s ; * w != 0 ; w ++ ) {
14181427 // uppercase
@@ -1427,7 +1436,7 @@ static int decoderEngine(decodeRec *dec) {
14271436 * w = '1' ;
14281437 } else if (* w == 'A' || * w == 'E' || * w == 'U' ) {
14291438 hasvowels = 1 ;
1430- } else {
1439+ } else if ( dec -> extension == NULL ) {
14311440 hasletters = 1 ;
14321441 }
14331442 }
@@ -1438,9 +1447,9 @@ static int decoderEngine(decodeRec *dec) {
14381447 prelen = (int ) ((dot = w ) - s );
14391448 }
14401449 else if (* w == '-' ) {
1441- if (* dec -> extension ) {
1442- return -17 ;
1443- } // already had a hyphen
1450+ if (dec -> extension != NULL ) {
1451+ return -17 ; // already had a hyphen
1452+ }
14441453 dec -> extension = w + 1 ;
14451454 * w = 0 ;
14461455 }
@@ -1451,6 +1460,9 @@ static int decoderEngine(decodeRec *dec) {
14511460 if (!dot ) {
14521461 return -27 ;
14531462 }
1463+ if (dec -> extension == NULL ) {
1464+ dec -> extension = "" ;
1465+ }
14541466
14551467 codex = prelen * 10 + strlen (dot ) - 1 ;
14561468
@@ -1642,7 +1654,7 @@ static int decoderEngine(decodeRec *dec) {
16421654#ifdef SUPPORT_FOREIGN_ALPHABETS
16431655
16441656// WARNING - these alphabets have NOT yet been released as standard! use at your own risk! check www.mapcode.com for details.
1645- static UWORD asc2lan [MAX_LANGUAGES ][36 ] = // A-Z equivalents for ascii characters A to Z, 0-9
1657+ static UWORD asc2lan [MAPCODE_ALPHABETS_TOTAL ][36 ] = // A-Z equivalents for ascii characters A to Z, 0-9
16461658 {
16471659 {0x0041 , 0x0042 , 0x0043 , 0x0044 , 0x0045 , 0x0046 , 0x0047 , 0x0048 , 0x0049 , 0x004a , 0x004b , 0x004c , 0x004d , 0x004e , 0x004f , 0x0050 , 0x0051 , 0x0052 , 0x0053 , 0x0054 , 0x0055 , 0x0056 , 0x0057 , 0x0058 , 0x0059 , 0x005a , 0x0030 , 0x0031 , 0x0032 , 0x0033 , 0x0034 , 0x0035 , 0x0036 , 0x0037 , 0x0038 , 0x0039 }, // roman
16481660 {0x0391 , 0x0392 , 0x039e , 0x0394 , 0x003f , 0x0395 , 0x0393 , 0x0397 , 0x0399 , 0x03a0 , 0x039a , 0x039b , 0x039c , 0x039d , 0x039f , 0x03a1 , 0x0398 , 0x03a8 , 0x03a3 , 0x03a4 , 0x003f , 0x03a6 , 0x03a9 , 0x03a7 , 0x03a5 , 0x0396 , 0x0030 , 0x0031 , 0x0032 , 0x0033 , 0x0034 , 0x0035 , 0x0036 , 0x0037 , 0x0038 , 0x0039 }, // greek
@@ -2118,38 +2130,53 @@ int decodeMapcodeToLatLon(double *lat, double *lon, const char *input,
21182130
21192131#ifdef SUPPORT_FOREIGN_ALPHABETS
21202132
2133+ // convert as much as will fit of mapcode into unibuf
21212134UWORD * convertToAlphabet (UWORD * unibuf , int maxlength , const char * mapcode , int alphabet ) // 0=roman, 2=cyrillic
21222135{
21232136 UWORD * startbuf = unibuf ;
2137+ UWORD * lastspot = & unibuf [maxlength - 1 ];
2138+ if (maxlength > 0 ) {
2139+ char u [MAX_MAPCODE_RESULT_LEN ];
2140+
2141+ // skip leading spaces
2142+ while (* mapcode > 0 && * mapcode <= 32 ) { mapcode ++ ; }
2143+
2144+ // straight-copy everything up to and including first space
2145+ {
2146+ char * e = strchr (mapcode , ' ' );
2147+ if (e ) {
2148+ while (mapcode <= e ) {
2149+ if (unibuf == lastspot ) { // buffer fully filled?
2150+ // zero-terminate and return
2151+ * unibuf = 0 ;
2152+ return startbuf ;
2153+ }
2154+ * unibuf ++ = * mapcode ++ ;
2155+ }
2156+ }
2157+ }
21242158
2125- while (* mapcode > 0 && * mapcode < 32 ) { mapcode ++ ; }
2126- { // skip lead
2127- char * e = strrchr (mapcode , ' ' );
2128- if (e ) {
2129- while (mapcode <= e ) {
2130- * unibuf ++ = * mapcode ++ ;
2131- }
2132- }
2133- }
2134-
2135- if (asc2lan [alphabet ][4 ] == 0x003f ) { // alphabet has no letter E
2136- if (strchr (mapcode , 'E' ) || strchr (mapcode , 'U' ) || strchr (mapcode , 'e' ) ||
2137- strchr (mapcode , 'u' )) // v1.50 get rid of E and U
2138- {
2139- // safely copy mapcode into temporary buffer u
2140- char u [MAX_MAPCODE_RESULT_LEN ];
2141- int len = (int ) strlen (mapcode );
2142- if (len >= MAX_MAPCODE_RESULT_LEN ) {
2143- len = MAX_MAPCODE_RESULT_LEN - 1 ;
2159+ // re-pack E/U-voweled mapcodes when necessary:
2160+ if (asc2lan [alphabet ][4 ] == 0x003f ) { // alphabet has no letter E
2161+ if (strchr (mapcode , 'E' ) || strchr (mapcode , 'U' ) ||
2162+ strchr (mapcode , 'e' ) || strchr (mapcode , 'u' ))
2163+ {
2164+ // copy trimmed mapcode into temporary buffer u
2165+ int len = (int ) strlen (mapcode );
2166+ if (len > MAX_MAPCODE_RESULT_LEN - 1 ) {
2167+ len = MAX_MAPCODE_RESULT_LEN - 1 ;
2168+ }
2169+ while (len > 0 && mapcode [len - 1 ]> 0 && mapcode [len - 1 ]<=32 ) { len -- ; }
2170+ memcpy (u , mapcode , len );
2171+ u [len ] = 0 ;
2172+ // re-pack into A-voweled mapcode
2173+ unpack_if_alldigits (u );
2174+ repack_if_alldigits (u , 1 );
2175+ mapcode = u ;
21442176 }
2145- memcpy (u , mapcode , len );
2146- u [len ] = 0 ;
2147- unpack_if_alldigits (u );
2148- repack_if_alldigits (u , 1 );
2149- mapcode = u ;
21502177 }
2178+ encode_utf16 (unibuf , 1 + (int )(lastspot - unibuf ), mapcode , alphabet );
21512179 }
2152- encode_utf16 (unibuf , maxlength , mapcode , alphabet );
21532180 return startbuf ;
21542181}
21552182
0 commit comments