Skip to content

Commit

Permalink
Added convenience method for other languages
Browse files Browse the repository at this point in the history
  • Loading branch information
rijnb committed Oct 2, 2017
1 parent 3475b1a commit 6d4dd79
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 6 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,11 @@ The list of support languages may grow over time.

## Release Notes

### 2.5.4

* Added `encodeLatLonToSelectedMapcode` as a convenience for languages that use the
C library, but have difficulties dealing with multi-dimensional arrays (like Swift).

### 2.5.3

* Cleaned up code after running Codacy code reviews.
Expand Down
21 changes: 18 additions & 3 deletions mapcodelib/mapcoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -2037,7 +2037,7 @@ static const int STATE_MACHINE[27][6] = {
STATE_GO |
512, ERR_UNEXPECTED_HYPHEN},

//13 prefix.LLLLL ===
//13 prefix.LLLLL ===
{22 |
128, ERR_UNEXPECTED_DOT, ERR_INVALID_MAPCODE_FORMAT, ERR_INVALID_VOWEL, STATE_GO |
128, 11 |
Expand All @@ -2047,7 +2047,7 @@ static const int STATE_MACHINE[27][6] = {
{ERR_BAD_TERRITORY_FORMAT, ERR_UNEXPECTED_DOT, 15, 15, ERR_BAD_TERRITORY_FORMAT, ERR_UNEXPECTED_HYPHEN},
//15 TC-S === get 2nd state letter
{ERR_BAD_TERRITORY_FORMAT, ERR_UNEXPECTED_DOT, 16, 16, ERR_BAD_TERRITORY_FORMAT, ERR_UNEXPECTED_HYPHEN},
//16 TC-SS === white:waitprefix | det/vow:TC-SSS
//16 TC-SS === white:waitprefix | det/vow:TC-SSS
{18 |
64, ERR_UNEXPECTED_DOT, 17, 17, ERR_DOT_MISSING, ERR_UNEXPECTED_HYPHEN},
//17 TC-SSS === white:waitprefix
Expand Down Expand Up @@ -2159,7 +2159,7 @@ static enum MapcodeError parseMapcodeString(MapcodeElements *mapcodeElements, co
cx = getRomanVersionOf((UWORD) w);
}
c = decodeChar(cx);
if (c < 0) { // vowel or illegal?
if (c < 0) { // vowel or illegal?
if (c == -1) { // illegal?
return ERR_INVALID_CHARACTER;
}
Expand Down Expand Up @@ -3053,6 +3053,21 @@ encodeLatLonToSingleMapcode(char *mapcode, double latDeg, double lonDeg, enum Te
}


// PUBLIC - encode lat,lon for territory to a selected mapcode (from all results) with extraDigits accuracy
int
encodeLatLonToSelectedMapcode(char *mapcode, double latDeg, double lonDeg, enum Territory territory, int extraDigits, int indexOfSelected) {
Mapcodes mapcodes;
int nrOfResults = 0;
nrOfResults = encodeLatLonToMapcodes(&mapcodes, latDeg, lonDeg, territory, extraDigits);
ASSERT(nrOfResults == mapcodes.count);
if ((nrOfResults <= 0) || (indexOfSelected < 0) || (indexOfSelected > nrOfResults)) {
return 0;
}
strcpy(mapcode, mapcodes.mapcode[indexOfSelected]);
return nrOfResults;
}


// PUBLIC - encode lat,lon for (optional) territory to mapcodes with extraDigits accuracy
int
encodeLatLonToMapcodes(Mapcodes *mapcodes, double latDeg, double lonDeg, enum Territory territory, int extraDigits) {
Expand Down
37 changes: 34 additions & 3 deletions mapcodelib/mapcoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ extern "C" {
* International mapcodes never include a territory ISO3166 code, nor a space.
*/
typedef struct {
int count; // The number of mapcode results (length of array).
int count; // The number of mapcode results (length of array).
char mapcode[MAX_NR_OF_MAPCODE_RESULTS][MAX_MAPCODE_RESULT_ASCII_LEN]; // The mapcodes.
} Mapcodes;

Expand Down Expand Up @@ -179,8 +179,7 @@ int encodeLatLonToMapcodes(
*
* Arguments:
* result - Returned Mapcode. The caller must not allocate or de-allocated this string.
* The resulting string MUST be allocated (and de-allocated) by the caller (contrary to
* encodeLatLonToMapcodes!).
* The resulting string MUST be allocated (and de-allocated) by the caller.
* The caller should allocate at least MAX_MAPCODE_RESULT_ASCII_LEN characters for the string.
* lat - Latitude, in degrees. Range: -90..90.
* lon - Longitude, in degrees. Range: -180..180.
Expand All @@ -201,6 +200,38 @@ int encodeLatLonToSingleMapcode(
int extraDigits);


/**
* Encode a latitude, longitude pair (in degrees) to a single Mapcode, selected from all Mapcodes.
* This method is offered for languages which have trouble supporting multi-dimensional arrays from C
* (like Swift).
*
* Arguments:
* result - Returned Mapcode. The caller must not allocate or de-allocated this string.
* The resulting string MUST be allocated (and de-allocated) by the caller.
* The caller should allocate at least MAX_MAPCODE_RESULT_ASCII_LEN characters for the string.
* lat - Latitude, in degrees. Range: -90..90.
* lon - Longitude, in degrees. Range: -180..180.
* territory - Territory (e.g. as obtained from getTerritoryCode), used as encoding context.
* Pass TERRITORY_NONE or TERRITORY_UNKNOWN to get Mapcodes for all territories.
* extraDigits - Number of extra "digits" to add to the generated mapcode. The preferred default is 0.
* Other valid values are 1 to 8, which will add extra letters to the mapcodes to
* make them represent the coordinate more accurately.
* indexOfSelected - Index of selected mapcode. Must be in valid range for number of results.
* The index is base 0. To fetch all Mapcodes, pass 0 in a first call to retrieve the
* first Mapcode and the total number of results and iterate over the rest.
*
* Returns:
* Total number of results available for selection. <=0 if encoding failed, or >0 if it succeeded.
*/
int encodeLatLonToSelectedMapcode(
char *mapcode,
double latDeg,
double lonDeg,
enum Territory territory,
int extraDigits,
int indexOfSelected);


/**
* Decode a utf8 or ascii Mapcode to a latitude, longitude pair (in degrees).
*
Expand Down
51 changes: 51 additions & 0 deletions test/unittest.c
Original file line number Diff line number Diff line change
Expand Up @@ -1711,6 +1711,56 @@ static int testSingleEncodes(void) {
}


static int testSelectedEncodes(void) {
int nrTests = 0;
char mapcode[MAX_MAPCODE_RESULT_ASCII_LEN];
double lat = 52.158993;
double lon = 4.492346;
int i = 0;
int total = 0;
do {
total = encodeLatLonToSelectedMapcode(mapcode, lat, lon, TERRITORY_NONE, 0, i);
if (total != 4) {
foundError();
printf("*** ERROR *** testSelectedEncodes, expected %d alternatives, but got %d", 4, total);
}
switch (i) {
case 0:
if (strcmp(mapcode, "NLD QJM.0G") != 0) {
foundError();
printf("*** ERROR *** testSelectedEncodes, expected '%s', but got '%s', alternative %d\n", "NLD QJM.0G", mapcode, i);
}
break;
case 1:
if (strcmp(mapcode, "NLD CZQ.15C") != 0) {
foundError();
printf("*** ERROR *** testSelectedEncodes, expected '%s', but got '%s', alternative %d\n", "NLD CZQ.15C", mapcode, i);
}
break;
case 2:
if (strcmp(mapcode, "NLD N39J.MZN") != 0) {
foundError();
printf("*** ERROR *** testSelectedEncodes, expected '%s', but got '%s', alternative %d\n", "NLD N39J.MZN", mapcode, i);
}
break;
case 3:
if (strcmp(mapcode, "VHVN4.TZ9S") != 0) {
foundError();
printf("*** ERROR *** testSelectedEncodes, expected '%s', but got '%s', alternative %d\n", "VHVN4.TZ9S", mapcode, i);
}
break;
default:
foundError();
printf("*** ERROR *** testSelectedEncodes, expected %d alternatives, but got %d", 4, i);
break;
}
++i;
} while (i < total);
++nrTests;
return nrTests;
}


static int testGetFullTerritoryNameLocal(const char *expectedName, enum Territory territory, int alternative) {
int nrTests = 0;
int expectedCode = (*expectedName ? 1 : 0);
Expand Down Expand Up @@ -2227,6 +2277,7 @@ int main(const int argc, const char **argv) {

printf("-----------------------------------------------------------\nEncode/decode tests\n");
nrTests += testSingleEncodes();
nrTests += testSelectedEncodes();
nrTests += testEncodeDecode();

printf("-----------------------------------------------------------\nRe-encode tests\n");
Expand Down

0 comments on commit 6d4dd79

Please sign in to comment.