5353
5454#define USIZE 256
5555
56+ #define MATH_PI 3.14159265358979323846
57+
5658// Radius of Earth.
5759#define EARTH_RADIUS_X_METERS 6378137
5860#define EARTH_RADIUS_Y_METERS 6356752
5961
6062// Circumference of Earth.
61- #define EARTH_CIRCUMFERENCE_X (EARTH_RADIUS_X_METERS * 2 * _PI )
62- #define EARTH_CIRCUMFERENCE_Y (EARTH_RADIUS_Y_METERS * 2 * _PI )
63+ #define EARTH_CIRCUMFERENCE_X (EARTH_RADIUS_X_METERS * 2 * MATH_PI )
64+ #define EARTH_CIRCUMFERENCE_Y (EARTH_RADIUS_Y_METERS * 2 * MATH_PI )
6365
6466// Meters per degree latitude is fixed. For longitude: use factor * cos(midpoint of two degree latitudes).
6567#define METERS_PER_DEGREE_LAT (EARTH_CIRCUMFERENCE_Y / 360.0)
6668#define METERS_PER_DEGREE_LON (EARTH_CIRCUMFERENCE_X / 360.0)
6769
68- #define _PI 3.14159265358979323846
70+ #define PARENT_LETTER ( ccode ) ((int) parentletter[ccode])
6971
7072// Legacy buffers: NOT threadsafe!
7173static char legacy_asciiBuffer [MAX_MAPCODE_RESULT_LEN ];
@@ -95,7 +97,7 @@ double distanceInMeters(double latDeg1, double lonDeg1, double latDeg2, double l
9597 }
9698 {
9799 const double dy = (latDeg2 - latDeg1 ) * METERS_PER_DEGREE_LAT ;
98- const double dx = (lonDeg2 - lonDeg1 ) * METERS_PER_DEGREE_LON * cos ((latDeg1 + latDeg2 ) * _PI / 360.0 );
100+ const double dx = (lonDeg2 - lonDeg1 ) * METERS_PER_DEGREE_LON * cos ((latDeg1 + latDeg2 ) * MATH_PI / 360.0 );
99101 return sqrt (dx * dx + dy * dy );
100102 }
101103}
@@ -338,14 +340,12 @@ static int lastrec(const int ccode) {
338340 return data_start [ccode + 1 ] - 1 ;
339341}
340342
341- #define ParentLetter (ccode ) ((int)parentletter[ccode])
342-
343343// returns parent of ccode, or -1
344344static int parentTerritoryOf (const int ccode ) {
345345 if (ccode < 0 || ccode > ccode_earth ) {
346346 return -1 ;
347347 }
348- return parentnr [ParentLetter (ccode )];
348+ return parentnr [PARENT_LETTER (ccode )];
349349}
350350
351351static int coDex (const int m ) {
@@ -1090,7 +1090,7 @@ static int encodeLatLonToMapcodes_internal(char **v, Mapcodes *mapcodes,
10901090
10911091typedef struct {
10921092 // input
1093- MapcodeElements mapcodeFormat ;
1093+ MapcodeElements mapcodeElements ;
10941094 const char * orginput ; // original full input string
10951095 const char * mapcode ; // input mapcode (first character of proper mapcode excluding territory code)
10961096 const char * extension ; // input extension (or empty)
@@ -1543,19 +1543,22 @@ static int decoderEngine(decodeRec *dec) {
15431543 int ccode ;
15441544 int err ;
15451545 int codex ;
1546+ int from ;
1547+ int upto ;
1548+ int i ;
15461549 char * s ;
15471550
1548- err = parseMapcodeString (& dec -> mapcodeFormat , dec -> orginput , 1 , dec -> context );
1551+ err = parseMapcodeString (& dec -> mapcodeElements , dec -> orginput , 1 , dec -> context );
15491552 if (err ) {
15501553 return err ;
15511554 }
15521555
1553- ccode = dec -> mapcodeFormat .territoryCode - 1 ;
1556+ ccode = dec -> mapcodeElements .territoryCode - 1 ;
15541557 dec -> context = ccode ;
1555- dec -> mapcode = dec -> mapcodeFormat .properMapcode ;
1556- dec -> extension = dec -> mapcodeFormat .precisionExtension ;
1557- codex = dec -> mapcodeFormat .indexOfDot * 9 + (int ) strlen (dec -> mapcodeFormat .properMapcode ) - 1 ;
1558- s = dec -> mapcodeFormat .properMapcode ;
1558+ dec -> mapcode = dec -> mapcodeElements .properMapcode ;
1559+ dec -> extension = dec -> mapcodeElements .precisionExtension ;
1560+ codex = dec -> mapcodeElements .indexOfDot * 9 + (int ) strlen (dec -> mapcodeElements .properMapcode ) - 1 ;
1561+ s = dec -> mapcodeElements .properMapcode ;
15591562
15601563 if (strchr (s , 'A' ) || strchr (s , 'E' ) || strchr (s , 'U' )) {
15611564 if (unpack_if_alldigits (s ) <= 0 ) {
@@ -1574,95 +1577,94 @@ static int decoderEngine(decodeRec *dec) {
15741577 }
15751578 }
15761579
1580+ if (ccode < 0 ) {
1581+ return -1 ;
1582+ }
1583+ from = firstrec (ccode );
1584+ upto = lastrec (ccode );
15771585
1578- {
1579- const int from = firstrec (ccode );
1580- const int upto = lastrec (ccode );
1581- int i ;
1582-
1583- // try all ccode rectangles to decode s (pointing to first character of proper mapcode)
1584- for (i = from ; i <= upto ; i ++ ) {
1585- const int codexi = coDex (i );
1586- const int r = recType (i );
1587- if (r == 0 ) {
1588- if (isNameless (i )) {
1589- if (((codexi == 21 ) && (codex == 22 )) ||
1590- ((codexi == 22 ) && (codex == 32 )) ||
1591- ((codexi == 13 ) && (codex == 23 ))) {
1592- err = decodeNameless (dec , i );
1593- break ;
1594- }
1595- } else {
1596- if ((codexi == codex ) || ((codex == 22 ) && (codexi == 21 ))) {
1597- err = decodeGrid (dec , i , 0 );
1598-
1599- // first of all, make sure the zone fits the country
1600- restrictZoneTo (& dec -> zone , & dec -> zone , boundaries (upto ));
1601-
1602- if ((err == 0 ) && isRestricted (i )) {
1603- int nrZoneOverlaps = 0 ;
1604- int j ;
1605-
1606- // *** make sure decode fits somewhere ***
1607- dec -> result = getMidPointFractions (& dec -> zone );
1608- dec -> coord32 = convertFractionsToCoord32 (& dec -> result );
1609- for (j = i - 1 ; j >= from ; j -- ) { // look in previous rects
1610- if (!isRestricted (j )) {
1611- if (fitsInsideBoundaries (& dec -> coord32 , boundaries (j ))) {
1612- nrZoneOverlaps = 1 ;
1613- break ;
1614- }
1586+ // try all ccode rectangles to decode s (pointing to first character of proper mapcode)
1587+ for (i = from ; i <= upto ; i ++ ) {
1588+ const int codexi = coDex (i );
1589+ const int r = recType (i );
1590+ if (r == 0 ) {
1591+ if (isNameless (i )) {
1592+ if (((codexi == 21 ) && (codex == 22 )) ||
1593+ ((codexi == 22 ) && (codex == 32 )) ||
1594+ ((codexi == 13 ) && (codex == 23 ))) {
1595+ err = decodeNameless (dec , i );
1596+ break ;
1597+ }
1598+ } else {
1599+ if ((codexi == codex ) || ((codex == 22 ) && (codexi == 21 ))) {
1600+ err = decodeGrid (dec , i , 0 );
1601+
1602+ // first of all, make sure the zone fits the country
1603+ restrictZoneTo (& dec -> zone , & dec -> zone , boundaries (upto ));
1604+
1605+ if ((err == 0 ) && isRestricted (i )) {
1606+ int nrZoneOverlaps = 0 ;
1607+ int j ;
1608+
1609+ // *** make sure decode fits somewhere ***
1610+ dec -> result = getMidPointFractions (& dec -> zone );
1611+ dec -> coord32 = convertFractionsToCoord32 (& dec -> result );
1612+ for (j = i - 1 ; j >= from ; j -- ) { // look in previous rects
1613+ if (!isRestricted (j )) {
1614+ if (fitsInsideBoundaries (& dec -> coord32 , boundaries (j ))) {
1615+ nrZoneOverlaps = 1 ;
1616+ break ;
16151617 }
16161618 }
1619+ }
16171620
1618- if (!nrZoneOverlaps ) {
1619- MapcodeZone zfound ;
1620- Boundaries prevu ;
1621- for (j = from ; j < i ; j ++ ) { // try all smaller rectangles j
1622- if (!isRestricted (j )) {
1623- MapcodeZone z ;
1624- if (restrictZoneTo (& z , & dec -> zone , boundaries (j ))) {
1625- nrZoneOverlaps ++ ;
1626- if (nrZoneOverlaps == 1 ) {
1627- // first fit! remember...
1628- zoneCopyFrom (& zfound , & z );
1629- memcpy (& prevu , boundaries (j ), sizeof (Boundaries ));
1630- } else { // nrZoneOverlaps >= 2
1631- // more than one hit
1632- break ; // give up
1633- }
1621+ if (!nrZoneOverlaps ) {
1622+ MapcodeZone zfound ;
1623+ Boundaries prevu ;
1624+ for (j = from ; j < i ; j ++ ) { // try all smaller rectangles j
1625+ if (!isRestricted (j )) {
1626+ MapcodeZone z ;
1627+ if (restrictZoneTo (& z , & dec -> zone , boundaries (j ))) {
1628+ nrZoneOverlaps ++ ;
1629+ if (nrZoneOverlaps == 1 ) {
1630+ // first fit! remember...
1631+ zoneCopyFrom (& zfound , & z );
1632+ memcpy (& prevu , boundaries (j ), sizeof (Boundaries ));
1633+ } else { // nrZoneOverlaps >= 2
1634+ // more than one hit
1635+ break ; // give up
16341636 }
1635- } // isRestricted
1636- } // for j
1637+ }
1638+ } // isRestricted
1639+ } // for j
16371640
1638- // if several sub-areas intersect, just return the whole zone
1639- // (the center of which may NOT re-encode to the same mapcode!)
1640- if (nrZoneOverlaps == 1 ) { // found exactly ONE intersection?
1641- zoneCopyFrom (& dec -> zone , & zfound );
1642- }
1641+ // if several sub-areas intersect, just return the whole zone
1642+ // (the center of which may NOT re-encode to the same mapcode!)
1643+ if (nrZoneOverlaps == 1 ) { // found exactly ONE intersection?
1644+ zoneCopyFrom (& dec -> zone , & zfound );
16431645 }
1646+ }
16441647
1645- if (!nrZoneOverlaps ) {
1646- err = -1234 ;
1647- }
1648- } // *** make sure decode fits somewhere ***
1649- break ;
1650- }
1651- }
1652- } else if (r == 1 ) {
1653- if (codex == codexi + 10 && headerLetter (i ) == * s ) {
1654- err = decodeGrid (dec , i , 1 );
1655- break ;
1656- }
1657- } else { //r>1
1658- if (((codex == 23 ) && (codexi == 22 )) ||
1659- ((codex == 33 ) && (codexi == 23 ))) {
1660- err = decodeAutoHeader (dec , i );
1648+ if (!nrZoneOverlaps ) {
1649+ err = -1234 ;
1650+ }
1651+ } // *** make sure decode fits somewhere ***
16611652 break ;
16621653 }
16631654 }
1664- } // for
1665- }
1655+ } else if (r == 1 ) {
1656+ if (codex == codexi + 10 && headerLetter (i ) == * s ) {
1657+ err = decodeGrid (dec , i , 1 );
1658+ break ;
1659+ }
1660+ } else { //r>1
1661+ if (((codex == 23 ) && (codexi == 22 )) ||
1662+ ((codex == 33 ) && (codexi == 23 ))) {
1663+ err = decodeAutoHeader (dec , i );
1664+ break ;
1665+ }
1666+ }
1667+ } // for
16661668
16671669 restrictZoneTo (& dec -> zone , & dec -> zone , boundaries (lastrec (ccode )));
16681670
@@ -2249,14 +2251,26 @@ int getTerritoryCode(const char *territoryISO, int optionalTerritoryContext) {
22492251 } else if (territoryISO [2 ] && territoryISO [3 ] == '-' ) {
22502252 return binfindmatch (getParentNumber (territoryISO , 3 ), territoryISO + 4 );
22512253 } else {
2252- const int parentNumber =
2253- ccode < 0 ? 0 : ((parentnumber [ccode ] > 0 ) ? parentnumber [ccode ] : parentnumber [parentTerritoryOf (
2254- ccode )]);
2255- const int b = binfindmatch (parentNumber , territoryISO );
2254+ int b ;
2255+ int parentNumber = 0 ;
2256+ if (ccode >= 0 ) {
2257+ if (parentnumber [ccode ] > 0 ) {
2258+ parentNumber = parentnumber [ccode ];
2259+ } else {
2260+ int parentTerritory = parentTerritoryOf (ccode );
2261+ if (parentTerritory >= 0 ) {
2262+ parentNumber = parentnumber [parentTerritory ];
2263+ } else {
2264+ parentNumber = -1 ;
2265+ }
2266+
2267+ }
2268+ }
2269+ b = binfindmatch (parentNumber , territoryISO );
22562270 if (b > 0 ) {
22572271 return b ;
2258- } //
2259- } //
2272+ }
2273+ }
22602274 return binfindmatch (0 , territoryISO );
22612275 } // else, fail:
22622276 return -1 ;
0 commit comments