diff --git a/library/zonedetect.c b/library/zonedetect.c index aadd218..33d8daa 100644 --- a/library/zonedetect.c +++ b/library/zonedetect.c @@ -25,16 +25,20 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include -#include #include #include #include #include -#include -#include #include +#if defined(_MSC_VER) + #include +#else + #include + #include + #include + #include +#endif #include "zonedetect.h" @@ -43,14 +47,27 @@ enum ZDInternalError { ZD_E_DB_OPEN, ZD_E_DB_SEEK, ZD_E_DB_MMAP, +#if defined(_MSC_VER) + ZD_E_DB_MMAP_MSVIEW, + ZD_E_DB_MAP_EXCEPTION, + ZD_E_DB_MUNMAP_MSVIEW, +#endif ZD_E_DB_MUNMAP, ZD_E_DB_CLOSE, ZD_E_PARSE_HEADER }; struct ZoneDetectOpaque { +#if defined(_MSC_VER) + HANDLE fd; + HANDLE fdMap; + int32_t length; + int32_t padding; +#else int fd; off_t length; +#endif + uint8_t *mapping; uint8_t tableType; @@ -84,11 +101,15 @@ static unsigned int ZDDecodeVariableLengthUnsigned(const ZoneDetect *library, ui return 0; } + uint32_t value = 0; + unsigned int i = 0; +#if defined(_MSC_VER) + __try { +#endif uint8_t *const buffer = library->mapping + *index; uint8_t *const bufferEnd = library->mapping + library->length - 1; - uint32_t value = 0; - unsigned int i = 0, shift = 0; + unsigned int shift = 0; while(1) { value |= (uint32_t)((buffer[i] & UINT8_C(0x7F)) << shift); shift += 7u; @@ -102,6 +123,14 @@ static unsigned int ZDDecodeVariableLengthUnsigned(const ZoneDetect *library, ui return 0; } } +#if defined(_MSC_VER) + } __except(GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR + ? EXCEPTION_EXECUTE_HANDLER + : EXCEPTION_CONTINUE_SEARCH) { /* file mapping SEH exception occurred */ + zdError(ZD_E_DB_MAP_EXCEPTION, (int)GetLastError()); + return 0; + } +#endif i++; *result = value; @@ -142,9 +171,20 @@ static char *ZDParseString(const ZoneDetect *library, uint32_t *index) char *const str = malloc(strLength + 1); if(str) { +#if defined(_MSC_VER) + __try { +#endif for(size_t i = 0; i < strLength; i++) { str[i] = (char)(library->mapping[strOffset + i] ^ UINT8_C(0x80)); } +#if defined(_MSC_VER) + } __except(GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR + ? EXCEPTION_EXECUTE_HANDLER + : EXCEPTION_CONTINUE_SEARCH) { /* file mapping SEH exception occurred */ + zdError(ZD_E_DB_MAP_EXCEPTION, (int)GetLastError()); + return 0; + } +#endif str[strLength] = 0; } @@ -161,6 +201,9 @@ static int ZDParseHeader(ZoneDetect *library) return -1; } +#if defined(_MSC_VER) + __try { +#endif if(memcmp(library->mapping, "PLB", 3)) { return -1; } @@ -169,6 +212,14 @@ static int ZDParseHeader(ZoneDetect *library) library->version = library->mapping[4]; library->precision = library->mapping[5]; library->numFields = library->mapping[6]; +#if defined(_MSC_VER) + } __except(GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR + ? EXCEPTION_EXECUTE_HANDLER + : EXCEPTION_CONTINUE_SEARCH) { /* file mapping SEH exception occurred */ + zdError(ZD_E_DB_MAP_EXCEPTION, (int)GetLastError()); + return 0; + } +#endif if(library->version != 0) { return -1; @@ -391,8 +442,16 @@ void ZDCloseDatabase(ZoneDetect *library) if(library->notice) { free(library->notice); } + +#if defined(_MSC_VER) + if(!UnmapViewOfFile(library->mapping)) zdError(ZD_E_DB_MUNMAP_MSVIEW, (int)GetLastError()); + if(!CloseHandle(library->fdMap)) zdError(ZD_E_DB_MUNMAP , (int)GetLastError()); + if(!CloseHandle(library->fd)) zdError(ZD_E_DB_CLOSE , (int)GetLastError()); +#else 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); +#endif + free(library); } } @@ -404,6 +463,32 @@ ZoneDetect *ZDOpenDatabase(const char *path) if(library) { memset(library, 0, sizeof(*library)); +#if defined(_MSC_VER) + library->fd = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (library->fd == INVALID_HANDLE_VALUE) { + zdError(ZD_E_DB_OPEN, (int)GetLastError()); + goto fail; + } + + const DWORD fsize = GetFileSize(library->fd, NULL); + if (fsize == INVALID_FILE_SIZE) { + zdError(ZD_E_DB_SEEK, (int)GetLastError()); + goto fail; + } + library->length = (int32_t)fsize; + + library->fdMap = CreateFileMappingA(library->fd, NULL, PAGE_READONLY, 0, 0, NULL); + if (!library->fdMap) { + zdError(ZD_E_DB_MMAP, (int)GetLastError()); + goto fail; + } + + library->mapping = MapViewOfFile(library->fdMap, FILE_MAP_READ, 0, 0, 0); + if (!library->mapping) { + zdError(ZD_E_DB_MMAP_MSVIEW, (int)GetLastError()); + goto fail; + } +#else library->fd = open(path, O_RDONLY | O_CLOEXEC); if(library->fd < 0) { zdError(ZD_E_DB_OPEN, errno); @@ -422,6 +507,7 @@ ZoneDetect *ZDOpenDatabase(const char *path) zdError(ZD_E_DB_MMAP, errno); goto fail; } +#endif /* Parse the header */ if(ZDParseHeader(library)) { @@ -632,6 +718,11 @@ const char *ZDGetErrorString(int errZD) 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"); +#if defined(_MSC_VER) + case ZD_E_DB_MMAP_MSVIEW : return ZD_E_COULD_NOT("open database file view"); + case ZD_E_DB_MAP_EXCEPTION: return "I/O exception occurred while accessing database file view"; + case ZD_E_DB_MUNMAP_MSVIEW: return ZD_E_COULD_NOT("close database file view"); +#endif 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"); diff --git a/library/zonedetect.h b/library/zonedetect.h index 4986e93..d23bbdf 100644 --- a/library/zonedetect.h +++ b/library/zonedetect.h @@ -30,6 +30,14 @@ #ifndef INCL_ZONEDETECT_H_ #define INCL_ZONEDETECT_H_ +#if !defined(ZD_EXPORT) + #if defined(_MSC_VER) + #define ZD_EXPORT __declspec(dllimport) + #else + #define ZD_EXPORT + #endif +#endif + typedef enum { ZD_LOOKUP_IGNORE = -3, ZD_LOOKUP_END = -2, @@ -57,18 +65,18 @@ typedef struct ZoneDetectOpaque ZoneDetect; extern "C" { #endif -ZoneDetect *ZDOpenDatabase(const char *path); -void ZDCloseDatabase(ZoneDetect *library); +ZD_EXPORT ZoneDetect *ZDOpenDatabase(const char *path); +ZD_EXPORT void ZDCloseDatabase(ZoneDetect *library); -ZoneDetectResult *ZDLookup(const ZoneDetect *library, float lat, float lon, float *safezone); -void ZDFreeResults(ZoneDetectResult *results); +ZD_EXPORT ZoneDetectResult *ZDLookup(const ZoneDetect *library, float lat, float lon, float *safezone); +ZD_EXPORT void ZDFreeResults(ZoneDetectResult *results); -const char *ZDGetNotice(const ZoneDetect *library); -uint8_t ZDGetTableType(const ZoneDetect *library); -const char *ZDLookupResultToString(ZDLookupResult result); +ZD_EXPORT const char *ZDGetNotice(const ZoneDetect *library); +ZD_EXPORT uint8_t ZDGetTableType(const ZoneDetect *library); +ZD_EXPORT const char *ZDLookupResultToString(ZDLookupResult result); -int ZDSetErrorHandler(void (*handler)(int, int)); -const char *ZDGetErrorString(int error); +ZD_EXPORT int ZDSetErrorHandler(void (*handler)(int, int)); +ZD_EXPORT const char *ZDGetErrorString(int errZD); #ifdef __cplusplus } diff --git a/vs15/ZoneDetect.sln b/vs15/ZoneDetect.sln new file mode 100644 index 0000000..daf6d71 --- /dev/null +++ b/vs15/ZoneDetect.sln @@ -0,0 +1,44 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.539 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZoneDetect", "ZoneDetect.vcxproj", "{F772ED23-DD9C-445F-813D-DACC5005E93E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo", "demo\demo.vcxproj", "{0129B756-8936-4D9C-8E6E-0A54C66412EE}" + ProjectSection(ProjectDependencies) = postProject + {F772ED23-DD9C-445F-813D-DACC5005E93E} = {F772ED23-DD9C-445F-813D-DACC5005E93E} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F772ED23-DD9C-445F-813D-DACC5005E93E}.Debug|x64.ActiveCfg = Debug|x64 + {F772ED23-DD9C-445F-813D-DACC5005E93E}.Debug|x64.Build.0 = Debug|x64 + {F772ED23-DD9C-445F-813D-DACC5005E93E}.Debug|x86.ActiveCfg = Debug|Win32 + {F772ED23-DD9C-445F-813D-DACC5005E93E}.Debug|x86.Build.0 = Debug|Win32 + {F772ED23-DD9C-445F-813D-DACC5005E93E}.Release|x64.ActiveCfg = Release|x64 + {F772ED23-DD9C-445F-813D-DACC5005E93E}.Release|x64.Build.0 = Release|x64 + {F772ED23-DD9C-445F-813D-DACC5005E93E}.Release|x86.ActiveCfg = Release|Win32 + {F772ED23-DD9C-445F-813D-DACC5005E93E}.Release|x86.Build.0 = Release|Win32 + {0129B756-8936-4D9C-8E6E-0A54C66412EE}.Debug|x64.ActiveCfg = Debug|x64 + {0129B756-8936-4D9C-8E6E-0A54C66412EE}.Debug|x64.Build.0 = Debug|x64 + {0129B756-8936-4D9C-8E6E-0A54C66412EE}.Debug|x86.ActiveCfg = Debug|Win32 + {0129B756-8936-4D9C-8E6E-0A54C66412EE}.Debug|x86.Build.0 = Debug|Win32 + {0129B756-8936-4D9C-8E6E-0A54C66412EE}.Release|x64.ActiveCfg = Release|x64 + {0129B756-8936-4D9C-8E6E-0A54C66412EE}.Release|x64.Build.0 = Release|x64 + {0129B756-8936-4D9C-8E6E-0A54C66412EE}.Release|x86.ActiveCfg = Release|Win32 + {0129B756-8936-4D9C-8E6E-0A54C66412EE}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {2545577E-5875-4173-8F3E-92287C405DD9} + EndGlobalSection +EndGlobal diff --git a/vs15/ZoneDetect.vcxproj b/vs15/ZoneDetect.vcxproj new file mode 100644 index 0000000..6b4c298 --- /dev/null +++ b/vs15/ZoneDetect.vcxproj @@ -0,0 +1,138 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {F772ED23-DD9C-445F-813D-DACC5005E93E} + ZoneDetect + 10.0.17763.0 + + + + DynamicLibrary + true + v141 + MultiByte + + + DynamicLibrary + false + v141 + true + MultiByte + + + DynamicLibrary + true + v141 + MultiByte + + + DynamicLibrary + false + v141 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + true + /Tc %(AdditionalOptions) + S:\ZoneDetect\library;%(AdditionalIncludeDirectories) + ZD_EXPORT=__declspec(dllexport);%(PreprocessorDefinitions) + + + + + Level3 + Disabled + true + true + /Tc %(AdditionalOptions) + S:\ZoneDetect\library;%(AdditionalIncludeDirectories) + ZD_EXPORT=__declspec(dllexport);%(PreprocessorDefinitions) + + + + + Level3 + MaxSpeed + true + true + true + true + /Tc %(AdditionalOptions) + S:\ZoneDetect\library;%(AdditionalIncludeDirectories) + ZD_EXPORT=__declspec(dllexport);%(PreprocessorDefinitions) + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + true + /Tc %(AdditionalOptions) + S:\ZoneDetect\library;%(AdditionalIncludeDirectories) + ZD_EXPORT=__declspec(dllexport);%(PreprocessorDefinitions) + + + true + true + + + + + + + + + + + + \ No newline at end of file diff --git a/vs15/ZoneDetect.vcxproj.filters b/vs15/ZoneDetect.vcxproj.filters new file mode 100644 index 0000000..0119583 --- /dev/null +++ b/vs15/ZoneDetect.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/vs15/ZoneDetect.vcxproj.user b/vs15/ZoneDetect.vcxproj.user new file mode 100644 index 0000000..be25078 --- /dev/null +++ b/vs15/ZoneDetect.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/vs15/demo/demo.vcxproj b/vs15/demo/demo.vcxproj new file mode 100644 index 0000000..891e6ff --- /dev/null +++ b/vs15/demo/demo.vcxproj @@ -0,0 +1,150 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {0129B756-8936-4D9C-8E6E-0A54C66412EE} + demo + 10.0.17763.0 + + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + true + /Tc %(AdditionalOptions) + $(SolutionDir)\..\library;%(AdditionalIncludeDirectories) + + + + ZoneDetect.lib;%(AdditionalDependencies) + $(SolutionDir)$(PlatformShortName)\$(ConfigurationName);%(AdditionalLibraryDirectories) + + + + + Level3 + Disabled + true + true + /Tc %(AdditionalOptions) + $(SolutionDir)\..\library;%(AdditionalIncludeDirectories) + + + + ZoneDetect.lib;%(AdditionalDependencies) + $(SolutionDir)$(PlatformShortName)\$(ConfigurationName);%(AdditionalLibraryDirectories) + + + + + Level3 + MaxSpeed + true + true + true + true + /Tc %(AdditionalOptions) + $(SolutionDir)\..\library;%(AdditionalIncludeDirectories) + + + true + true + ZoneDetect.lib;%(AdditionalDependencies) + $(SolutionDir)$(PlatformShortName)\$(ConfigurationName);%(AdditionalLibraryDirectories) + + + + + + Level3 + MaxSpeed + true + true + true + true + /Tc %(AdditionalOptions) + $(SolutionDir)\..\library;%(AdditionalIncludeDirectories) + + + true + true + ZoneDetect.lib;%(AdditionalDependencies) + $(SolutionDir)$(PlatformShortName)\$(ConfigurationName);%(AdditionalLibraryDirectories) + + + + + + + + + + + + + \ No newline at end of file diff --git a/vs15/demo/demo.vcxproj.filters b/vs15/demo/demo.vcxproj.filters new file mode 100644 index 0000000..31d8982 --- /dev/null +++ b/vs15/demo/demo.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/vs15/demo/demo.vcxproj.user b/vs15/demo/demo.vcxproj.user new file mode 100644 index 0000000..85d5afe --- /dev/null +++ b/vs15/demo/demo.vcxproj.user @@ -0,0 +1,19 @@ + + + + $(SolutionDir)\..\database\out\timezone21.bin -11.695, 166.8 + WindowsLocalDebugger + + + $(SolutionDir)\..\database\out\timezone21.bin -11.695, 166.8 + WindowsLocalDebugger + + + $(SolutionDir)\..\database\out\timezone21.bin -11.695, 166.8 + WindowsLocalDebugger + + + $(SolutionDir)\..\database\out\timezone21.bin -11.695, 166.8 + WindowsLocalDebugger + + \ No newline at end of file