diff --git a/demo.c b/demo.c index b860ff8..a7c13f4 100644 --- a/demo.c +++ b/demo.c @@ -53,31 +53,33 @@ void printResults(ZoneDetectResult *results, float safezone) if(index) { printf("Safezone: %f\n", safezone); } - printf("\n\n"); +} + +void onError(int errZD, int errNative) +{ + fprintf(stderr, "ZD error: %s (0x%08X)\n", ZDGetErrorString(errZD), (unsigned)errNative); } int main(int argc, char *argv[]) { - ZoneDetect *cd; if(argc != 4) { printf("Usage: %s dbname lat lon\n", argv[0]); - exit(0); + return 1; } - cd = ZDOpenDatabase(argv[1]); - if(!cd) { - printf("Init failed\n"); - exit(0); - } + ZDSetErrorHandler(onError); - float lat = atof(argv[2]); - float lon = atof(argv[3]); + ZoneDetect *const cd = ZDOpenDatabase(argv[1]); + if(!cd) return 2; + + const float lat = (float)atof(argv[2]); + const float lon = (float)atof(argv[3]); float safezone = 0; ZoneDetectResult *results = ZDLookup(cd, lat, lon, &safezone); printResults(results, safezone); ZDCloseDatabase(cd); + return 0; } - diff --git a/library/zonedetect.c b/library/zonedetect.c index f766306..aadd218 100644 --- a/library/zonedetect.c +++ b/library/zonedetect.c @@ -26,6 +26,8 @@ */ #include +#include +#include #include #include #include @@ -36,6 +38,16 @@ #include "zonedetect.h" +enum ZDInternalError { + ZD_OK, + ZD_E_DB_OPEN, + ZD_E_DB_SEEK, + ZD_E_DB_MMAP, + ZD_E_DB_MUNMAP, + ZD_E_DB_CLOSE, + ZD_E_PARSE_HEADER +}; + struct ZoneDetectOpaque { int fd; off_t length; @@ -54,6 +66,12 @@ struct ZoneDetectOpaque { uint32_t dataOffset; }; +static void (*zdErrorHandler)(int, int); +static void zdError(enum ZDInternalError errZD, int errNative) +{ + if (zdErrorHandler) zdErrorHandler((int)errZD, errNative); +} + static int32_t ZDFloatToFixedPoint(float input, float scale, unsigned int precision) { const float inputScaled = input / scale; @@ -373,12 +391,8 @@ void ZDCloseDatabase(ZoneDetect *library) if(library->notice) { free(library->notice); } - if(library->mapping) { - munmap(library->mapping, (size_t)(library->length)); - } - if(library->fd >= 0) { - close(library->fd); - } + if(library->mapping && munmap(library->mapping, (size_t)(library->length))) zdError(ZD_E_DB_MUNMAP, errno); + if(library->fd >= 0 && close(library->fd)) zdError(ZD_E_DB_CLOSE , errno); free(library); } } @@ -392,22 +406,26 @@ ZoneDetect *ZDOpenDatabase(const char *path) library->fd = open(path, O_RDONLY | O_CLOEXEC); if(library->fd < 0) { + zdError(ZD_E_DB_OPEN, errno); goto fail; } library->length = lseek(library->fd, 0, SEEK_END); if(library->length <= 0) { + zdError(ZD_E_DB_SEEK, errno); goto fail; } lseek(library->fd, 0, SEEK_SET); library->mapping = mmap(NULL, (size_t)library->length, PROT_READ, MAP_PRIVATE | MAP_FILE, library->fd, 0); if(!library->mapping) { + zdError(ZD_E_DB_MMAP, errno); goto fail; } /* Parse the header */ if(ZDParseHeader(library)) { + zdError(ZD_E_PARSE_HEADER, 0); goto fail; } } @@ -604,3 +622,26 @@ const char *ZDLookupResultToString(ZDLookupResult result) return "Unknown"; } +#define ZD_E_COULD_NOT(msg) "could not " msg + +const char *ZDGetErrorString(int errZD) +{ + switch ((enum ZDInternalError)errZD) { + default: assert(0); + case ZD_OK : return ""; + case ZD_E_DB_OPEN : return ZD_E_COULD_NOT("open database file"); + case ZD_E_DB_SEEK : return ZD_E_COULD_NOT("retrieve database file size"); + case ZD_E_DB_MMAP : return ZD_E_COULD_NOT("map database file to system memory"); + case ZD_E_DB_MUNMAP : return ZD_E_COULD_NOT("unmap database"); + case ZD_E_DB_CLOSE : return ZD_E_COULD_NOT("close database file"); + case ZD_E_PARSE_HEADER : return ZD_E_COULD_NOT("parse database header"); + } +} + +#undef ZD_E_COULD_NOT + +int ZDSetErrorHandler(void (*handler)(int, int)) +{ + zdErrorHandler = handler; + return 0; +} diff --git a/library/zonedetect.h b/library/zonedetect.h index 79417de..4986e93 100644 --- a/library/zonedetect.h +++ b/library/zonedetect.h @@ -67,6 +67,9 @@ const char *ZDGetNotice(const ZoneDetect *library); uint8_t ZDGetTableType(const ZoneDetect *library); const char *ZDLookupResultToString(ZDLookupResult result); +int ZDSetErrorHandler(void (*handler)(int, int)); +const char *ZDGetErrorString(int error); + #ifdef __cplusplus } #endif