/* * Copyright (C) 2014-2017 Stichting Mapcode Foundation (http://www.mapcode.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __MAPCODER_H__ #define __MAPCODER_H__ #ifdef __cplusplus extern "C" { #endif #include "mapcode_territories.h" #include "mapcode_alphabets.h" // English is always defined - this is the fallback language for any unknown language. #define MAPCODE_SUPPORT_LANGUAGE_EN #define DEFAULT_TERRITORY_FULL_NAME TERRITORY_FULL_NAME_EN #ifndef MAPCODE_NO_SUPPORT_ALL_LANGUAGES #define MAPCODE_SUPPORT_LANGUAGE_AF #define MAPCODE_SUPPORT_LANGUAGE_AR #define MAPCODE_SUPPORT_LANGUAGE_BE #define MAPCODE_SUPPORT_LANGUAGE_CN #define MAPCODE_SUPPORT_LANGUAGE_CS #define MAPCODE_SUPPORT_LANGUAGE_DA #define MAPCODE_SUPPORT_LANGUAGE_DE #define MAPCODE_SUPPORT_LANGUAGE_EN #define MAPCODE_SUPPORT_LANGUAGE_ES #define MAPCODE_SUPPORT_LANGUAGE_FI #define MAPCODE_SUPPORT_LANGUAGE_FR #define MAPCODE_SUPPORT_LANGUAGE_HE #define MAPCODE_SUPPORT_LANGUAGE_HI #define MAPCODE_SUPPORT_LANGUAGE_HR #define MAPCODE_SUPPORT_LANGUAGE_ID #define MAPCODE_SUPPORT_LANGUAGE_IT #define MAPCODE_SUPPORT_LANGUAGE_JA #define MAPCODE_SUPPORT_LANGUAGE_KO #define MAPCODE_SUPPORT_LANGUAGE_NL #define MAPCODE_SUPPORT_LANGUAGE_NO #define MAPCODE_SUPPORT_LANGUAGE_PL #define MAPCODE_SUPPORT_LANGUAGE_PT #define MAPCODE_SUPPORT_LANGUAGE_RU #define MAPCODE_SUPPORT_LANGUAGE_SV #define MAPCODE_SUPPORT_LANGUAGE_SW #define MAPCODE_SUPPORT_LANGUAGE_TR #define MAPCODE_SUPPORT_LANGUAGE_UK #endif #define MAPCODE_C_VERSION "2.5.5" #define UWORD unsigned short int // 2-byte unsigned integer. #define MAX_NR_OF_MAPCODE_RESULTS 22 // Max. number of results ever returned by encoder (e.g. for 26.904899, 95.138515). #define MAX_PRECISION_DIGITS 8 // Max. number of extension characters (excluding the hyphen). Must be even. #define MAX_PROPER_MAPCODE_ASCII_LEN 11 // Max. chars in a proper mapcode (including the dot, excl. precision extension). #define MAX_ISOCODE_ASCII_LEN 7 // Max. chars in a valid ISO3166 territory code. #define MAX_CLEAN_MAPCODE_ASCII_LEN (MAX_PROPER_MAPCODE_ASCII_LEN + 1 + MAX_PRECISION_DIGITS) // Max. chars in a clean mapcode (excluding zero-terminator). #define MAX_MAPCODE_RESULT_ASCII_LEN (MAX_ISOCODE_ASCII_LEN + 1 + MAX_CLEAN_MAPCODE_ASCII_LEN + 1) // Max. chars to store a single result (including zero-terminator). #define MAX_TERRITORY_FULLNAME_UTF8_LEN 111 // Max. number of characters to store the longest possible territory name (in UTF8) #define MAX_MAPCODE_RESULT_UTF8_LEN (MAX_MAPCODE_RESULT_ASCII_LEN * 3) // One mapcode character can become at most 3 UTF8characters. #define MAX_MAPCODE_RESULT_UTF16_LEN (MAX_MAPCODE_RESULT_ASCII_LEN) // Each mapcode character can become one UTF16 word. // The constants are also exported as variables, to allow other languages to use them. extern char* _MAPCODE_C_VERSION; extern int _MAX_NR_OF_MAPCODE_RESULTS; extern int _MAX_PRECISION_DIGITS; extern int _MAX_PROPER_MAPCODE_ASCII_LEN; extern int _MAX_ISOCODE_ASCII_LEN; extern int _MAX_CLEAN_MAPCODE_ASCII_LEN; extern int _MAX_MAPCODE_RESULT_ASCII_LEN; extern int _MAX_TERRITORY_FULLNAME_UTF8_LEN; extern int _MAX_MAPCODE_RESULT_UTF8_LEN; extern int _MAX_MAPCODE_RESULT_UTF16_LEN; extern int _MAX_ALPHABETS_PER_TERRITORY; /** * The type Mapcodes hold a number of mapcodes, for example from an encoding call. * If a result contains a space, that space seperates the territory ISO3166 code from the mapcode. * International mapcodes never include a territory ISO3166 code, nor a space. */ typedef struct { 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; /** * The MapcodeElement structure is returned by decodeXXX and can be used to inspect or clean up the * mapcode input. The field territoryISO contains the cleaned up territory code from the input, but * the code may be abbreviated, or even missing (if it wasn't available in the input). * * If you want to get a full territory code, use: * char isoName[MAX_ISOCODE_ASCII_LEN + 1]; * getTerritoryIsoName(isoName, mapcodeElement.territoryCode, 0) */ typedef struct { char territoryISO[MAX_ISOCODE_ASCII_LEN + 1]; // The (trimmed and uppercased) territory code, from the input. enum Territory territoryCode; // The territory, as recognized and disambiguated from territoryISO. char properMapcode[MAX_PROPER_MAPCODE_ASCII_LEN + 1]; // The (romanised) mapcode excl. territory or extension. int indexOfDot; // Position of dot in properMapcode (a value between 2 and 5). char precisionExtension[MAX_PRECISION_DIGITS + 1]; // The (romanised) extension (excluding the hyphen). } MapcodeElements; /** * List of error return codes (negative except for ERR_OK = 0) */ enum MapcodeError { // note: an incomplete mapcode could "become" complete by adding letters. ERR_MAPCODE_INCOMPLETE = -999, // not enough letters (yet) after dot // format errors. ERR_ALL_DIGIT_CODE = -299, // mapcode consists only of digits ERR_INVALID_MAPCODE_FORMAT, // string not recognized as mapcode format ERR_INVALID_CHARACTER, // mapcode contains an invalid character ERR_BAD_ARGUMENTS, // an argument is invalid (e.g. NULL) ERR_INVALID_ENDVOWELS, // mapcodes ends in UE or UU ERR_EXTENSION_INVALID_LENGTH, // precision extension too long, or empty ERR_EXTENSION_INVALID_CHARACTER, // bad precision extension character (e.g. Z) ERR_UNEXPECTED_DOT, // mapcode dot can not be in this position ERR_DOT_MISSING, // mapcode dot not found ERR_UNEXPECTED_HYPHEN, // hyphen can not be in this position ERR_INVALID_VOWEL, // vowel in invalid location, or missing ERR_BAD_TERRITORY_FORMAT, // mapcode territory badly formatted ERR_TRAILING_CHARACTERS, // characters found trailing the mapcode // parse errors. ERR_UNKNOWN_TERRITORY = -199, // mapcode territory not recognized // other errors. ERR_BAD_MAPCODE_LENGTH = -99, // proper mapcode too short or too long ERR_MISSING_TERRITORY, // mapcode can not be decoded without territory ERR_EXTENSION_UNDECODABLE, // extension does not decode to valid coordinate ERR_MAPCODE_UNDECODABLE, // mapcode does not decode inside territory ERR_BAD_COORDINATE, // latitude or longitude is NAN or infinite // all OK. ERR_OK = 0 }; /** * Encode a latitude, longitude pair (in degrees) to a set of Mapcodes. * * Arguments: * mapcodes - A pointer to a buffer to hold the mapcodes, allocated by the caller. * lat - Latitude, in degrees. Range: -90..90. * lon - Longitude, in degrees. Range: -180..180. * territory - Territory (e.g. as 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. * * Returns: * Number of results stored in parameter results. Always >= 0 (0 if no encoding was possible or an error occurred). * The results are stored as pairs (Mapcode, territory name) in: * (results[0], results[1])...(results[(2 * N) - 2], results[(2 * N) - 1]) */ int encodeLatLonToMapcodes( Mapcodes *mapcodes, double latDeg, double lonDeg, enum Territory territory, int extraDigits); /** * Encode a latitude, longitude pair (in degrees) to a single Mapcode: the shortest possible for the given territory * (which can be 0 for all territories). * * 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. * * Returns: * Number of results. <=0 if encoding failed, or 1 if it succeeded. */ int encodeLatLonToSingleMapcode( char *mapcode, double latDeg, double lonDeg, enum Territory territory, 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). * * Arguments: * lat - Decoded latitude, in degrees. Range: -90..90. * lon - Decoded longitude, in degrees. Range: -180..180. * utf8string - Mapcode to decode (ascii or utf8 string). * territory - Territory (e.g. as obtained from getTerritoryCode), used as decoding context. * Pass TERRITORY_NONE if not available. * mapcodeElements - If not NULL, filled with analysis of the string (unless an error was encountered). * * Returns: * ERR_OK if encoding succeeded. */ enum MapcodeError decodeMapcodeToLatLonUtf8( double *latDeg, double *lonDeg, const char *utf8string, enum Territory territory, MapcodeElements *mapcodeElements); /** * Decode a utf16 Mapcode to a latitude, longitude pair (in degrees). * * Arguments: * lat - Decoded latitude, in degrees. Range: -90..90. * lon - Decoded longitude, in degrees. Range: -180..180. * mapcodeElements - If not NULL, filled with analysis of the string (unless an error was encountered) * utf8string - Mapcode to decode (ascii or utf8 string). * territory - Territory (e.g. as obtained from getTerritoryCode), used as decoding context. * Pass TERRITORY_NONE if not available. * * Returns: * ERR_OK if encoding succeeded. */ enum MapcodeError decodeMapcodeToLatLonUtf16( double *latDeg, double *lonDeg, const UWORD *utf16string, enum Territory territory, MapcodeElements *mapcodeElements); /** * Checks if a string has the format of a Mapcode. (Note: The method is called compareXXX rather than hasXXX because * the return value ERR_OK indicates the string has the Mapcode format, much like string comparison strcmp returns.) * * Arguments: * utf8String/utf16String - Mapcode string to check, in UTF8 or UTF16 format. * * Returns: * ERR_OK if the string has a correct Mapcode format, another ERR_XXX value if the string does * not have a Mapcode format. * Special value ERR_MAPCODE_INCOMPLETE indicates the string could be a Mapcode, but it seems * to lack some characters. * NOTE: a correct Mapcode format does not in itself guarantee the mapcode will decode to * a valid coordinate! */ enum MapcodeError compareWithMapcodeFormatUtf8(const char *utf8String); enum MapcodeError compareWithMapcodeFormatUtf16(const UWORD *utf16String); /** * Convert an ISO3166 territory code to a territory. * * Arguments: * territoryISO - String starting with ISO3166 code of territory (e.g. "USA" or "US-CA"). * parentTerritoryCode - Parent territory, or TERRITORY_NONE if not available. * * Returns: * Territory (> _TERRITORY_MIN) if succeeded, or TERRITORY_NONE if failed. */ enum Territory getTerritoryCode( const char *territoryISO, enum Territory optionalTerritoryContext); /** * Convert a territory to a territory name. * * Arguments: * territoryISO - String to territory ISO code name result. * territory - Territory to get the name of. * userShortName - Pass 0 for full name, 1 for short name (state codes may be ambiguous). * * Returns: * Pointer to result. String will be empty if territory illegal. */ char *getTerritoryIsoName( char *territoryISO, enum Territory territory, int useShortName); /** * Given a territory, return the territory itself it it was a country, or return its parent * territory if it was a subdivision (e.g. a state). * * Arguments: * territory - territory (either a country or a subdivision, e.g. a state). * * Returns: * Territory of the parent country (if the territory has one), or the territory itself. * TERRITORY_NONE if the territory was invalid. */ enum Territory getCountryOrParentCountry(enum Territory territory); /** * Given a territory, return its parent country. * * Arguments: * territory - territory to get the parent of. * * Returns: * Territory of the parent country. * TERRITORY_NONE if the territory was not a subdivision, or invalid. */ enum Territory getParentCountryOf(enum Territory territory); /** * Returns the distance in meters between two coordinates (latitude/longitude pairs). * Important: only accurate for coordinates within a few kilometers from each other. */ double distanceInMeters(double latDeg1, double lonDeg1, double latDeg2, double lonDeg2); /** * Returns how far, at worst, a decoded mapcode can be from the original encoded coordinate. * * Arguments: * extraDigits - Number of extra "digits" in the mapcode. Extra letters added to mapcodes * make them represent coordinates more accurately. Must be >= 0. * * Returns: * The worst-case distance in meters between a decoded mapcode and the encoded coordinate. */ double maxErrorInMeters(int extraDigits); /** * Returns whether a coordinate is near more than one territory border. * * Arguments: * lat - Latitude, in degrees. Range: -90..90. * lon - Longitude, in degrees. Range: -180..180. * territory - Territory * * Return value: * 0 if coordinate is NOT near more than one territory border, non-0 otherwise. * * Note that for the mapcode system, the following should hold: IF a point p has a * mapcode M, THEN decode(M) delivers a point q within maxErrorInMeters() of p. * Furthermore, encode(q) must yield back M *unless* point q is near multiple borders. */ int multipleBordersNearby( double latDeg, double lonDeg, enum Territory territory); /** * Returns territory names in English. There's always at least 1 alternative (with index 0). * * Arguments: * territoryName - Target string, allocated by caller to be at least MAX_TERRITORY_FULLNAME_ASCII_LEN + 1 bytes. * territory - Territory to get name for. * alternative - Which name to get, must be >= 0 (0 = default, 1 = first alternative, 2 = second etc.). * * Return value: * 0 if the alternative does not exist (territoryName will be empty). * non-0 if the alternative exists (territoryName contains name). */ int getFullTerritoryNameEnglish( char *territoryName, enum Territory territory, int alternative); /** * Returns territory names in the local language. There are two variants of this call. One returns local * territory names in a specified alphabet only. The other simply returns the local names, regardless * of its alphabet. There is always at least 1 alternative, with index 0. * * Arguments: * territoryName - Target string, allocated by caller to be at least MAX_TERRITORY_FULLNAME_UTF8_LEN + 1 bytes. * territory - Territory to get name for. * alternative - Which name to get, must be >= 0 (0 = default, 1 = first alternative, 2 = second etc.). * alphabet - Alphabet to use for territoryName. Must be a valid alphabet value. * * Return value: * 0 if the alternative does not exist (territoryName will be empty). * non-0 if the alternative exists (territoryName contains name). */ int getFullTerritoryNameLocalUtf8( char *territoryName, enum Territory territory, int alternative); int getFullTerritoryNameLocalInAlphabetUtf8( char *territoryName, enum Territory territory, int alternative, enum Alphabet alphabet); /** * Returns territory names in a specific locale. There are two variants of this call. One returns * territory names in a specified alphabet only. The other simply returns the local names, regardless * of its alphabet. There is always at least 1 alternative, with index 0. * * Arguments: * territoryName - Target string, allocated by caller to be at least MAX_TERRITORY_FULLNAME_UTF8_LEN + 1 bytes. * territory - Territory to get name for. * alternative - Which name to get, must be >= 0 (0 = default, 1 = first alternative, 2 = second etc.). * locale - A locale (e.g. "en_US" for U.S. English); use NULL for local territory names. * alphabet - Alphabet to use for territoryName. Must be a valid alphabet value. * * Return value: * 0 if the alternative does not exist (territoryName will be empty). * non-0 if the alternative exists (territoryName contains name). */ int getFullTerritoryNameInLocaleUtf8( char *territoryName, enum Territory territory, int alternative, const char *locale); int getFullTerritoryNameInLocaleInAlphabetUtf8( char *territoryName, enum Territory territory, int alternative, const char *locale, enum Alphabet alphabet); /** * This struct contains the returned alphabest for getAlphabetsForTerritory. The 'count' specifies * how many alphabets are listed in 'alphabet', range [1, MAX_ALPHABETS_PER_TERRITORY]. */ #define MAX_ALPHABETS_PER_TERRITORY 3 typedef struct { int count; enum Alphabet alphabet[MAX_ALPHABETS_PER_TERRITORY]; } TerritoryAlphabets; /** * Given a territory, returns a structure defining which alphabets (in order of importance) * are in common use in the territory. * * Arguments: * territory - Territory to get the common alphabets for. * * Returns: * A pointer to a TerritoryAlphabets structure, or NULL if the territory is invalid. * (The pointer is owned by the library and should not be dealloacted by the caller.) */ const TerritoryAlphabets *getAlphabetsForTerritory(enum Territory territory); /** * Encode a string to Alphabet characters for a language. * * Arguments: * utf8String - Buffer to be filled with the Unicode string result. * Must have capacity for MAX_MAPCODE_RESULT_UTF8_LEN + 1 characters. * asciiString - ASCII string to encode (must be < MAX_MAPCODE_RESULT_ASCII_LEN characters). * alphabet - Alphabet to use. * * Returns: * Encode UTF8 string (pointer to utf8String buffer), allocated and deallocated by the caller. */ char *convertMapcodeToAlphabetUtf8(char *utf8String, const char *asciiString, enum Alphabet alphabet); /** * Encode a string to Alphabet characters for a language. * * Arguments: * utf16String - Buffer to be filled with the Unicode string result. * Must have capacity for MAX_MAPCODE_RESULT_UTF16_LEN 16-bit characters. * asciiString - ASCII string to encode (must be < MAX_MAPCODE_RESULT_ASCII_LEN characters). * alphabet - Alphabet to use. * * Returns: * Encode UTF16 string (pointer to utf16String buffer), allocated and deallocated by the caller. */ UWORD *convertMapcodeToAlphabetUtf16(UWORD *utf16String, const char *asciiString, enum Alphabet alphabet); #ifdef __cplusplus } #endif #endif