Throw a runtime error if the install folder does not exist.

Replace my accidental use of NULL with nullptr.
Improve some comments.
This commit is contained in:
gm
2015-09-27 20:55:55 +13:00
parent 0791828329
commit 635ec55065
2 changed files with 30 additions and 19 deletions

36
tz.cpp
View File

@@ -62,6 +62,7 @@
#ifdef _WIN32 #ifdef _WIN32
#include <Windows.h> #include <Windows.h>
#include <io.h>
#else #else
#include <unistd.h> #include <unistd.h>
#endif #endif
@@ -74,6 +75,15 @@ static const char folder_delimiter =
'/'; '/';
#endif #endif
static bool file_exists(const std::string& filename)
{
#ifdef _WIN32
return ::_access(filename.c_str(), 0) == 0;
#else
return ::access(filename.c_str(), F_OK) == 0;
#endif
}
#ifdef _WIN32 #ifdef _WIN32
// Win32 support requires calling OS functions. // Win32 support requires calling OS functions.
// This routine maps OS error codes to readable text strngs. // This routine maps OS error codes to readable text strngs.
@@ -92,8 +102,8 @@ static std::string get_win32_message(DWORD error_code)
auto result = FormatMessageA( auto result = FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS, | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), nullptr, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<char*>(&msg), 0, NULL ); reinterpret_cast<char*>(&msg), 0, nullptr );
std::unique_ptr<char[], free_message> message_buffer(msg); std::unique_ptr<char[], free_message> message_buffer(msg);
if (result == 0) // If there is no error message, still give the code. if (result == 0) // If there is no error message, still give the code.
{ {
@@ -159,7 +169,7 @@ namespace // Put types in an anonymous name space.
private: private:
// Note there is no value documented to be an invalid handle value. // Note there is no value documented to be an invalid handle value.
// Not NULL nor INVALID_HANDLE_VALUE. We must rely on is_open. // Not NULL nor INVALID_HANDLE_VALUE. We must rely on is_open.
HKEY m_key = NULL; HKEY m_key = nullptr;
bool m_is_open = false; bool m_is_open = false;
public: public:
HKEY handle() HKEY handle()
@@ -187,7 +197,7 @@ namespace // Put types in an anonymous name space.
if (result == ERROR_SUCCESS) if (result == ERROR_SUCCESS)
{ {
m_is_open = false; m_is_open = false;
m_key = NULL; m_key = nullptr;
} }
return result; return result;
} }
@@ -245,13 +255,8 @@ static inline size_t countof(T(&arr)[N])
// This function returns an exhaustive list of time zone information // This function returns an exhaustive list of time zone information
// from the Windows registry. // from the Windows registry.
// The routine tries to to obtain as much information as possible despite errors. // The routine tries to load as many time zone entries as possible despite errors.
// If there is an error with any key, it is silently ignored to move on to the next. // We don't want to fail to load the whole database just because one record can't be read.
// We don't have a logger to log such errors and it might be disruptive to log anyway.
// We don't want the whole database of information disrupted just because
// one record in it can't be read.
// The expectation is that the errors will eventually manifest to the
// caller as a missing time zone which they will need to investigate.
static void get_windows_timezone_info(std::vector<timezone_info>& tz_list) static void get_windows_timezone_info(std::vector<timezone_info>& tz_list)
{ {
@@ -1858,6 +1863,15 @@ init_tzdb()
std::string line; std::string line;
bool continue_zone = false; bool continue_zone = false;
TZ_DB db; TZ_DB db;
if (!file_exists(install))
{
std::string msg = "Timezone database not found at \"";
msg += install;
msg += "\"";
throw std::runtime_error(msg);
}
for (const auto& filename : files) for (const auto& filename : files)
{ {
std::ifstream infile(path + filename); std::ifstream infile(path + filename);

13
tz.h
View File

@@ -33,18 +33,15 @@
The notion of "current timezone" is something the operating system is expected The notion of "current timezone" is something the operating system is expected
to "just know". How it knows this is system specific. It's often a value to "just know". How it knows this is system specific. It's often a value
set by the user at OS intallation time and recorded by the OS somewhere. set by the user at OS intallation time and recorded by the OS somewhere.
On Linux and Mac systems. the current timezone name is obtained by looking at On Linux and Mac systems the current timezone name is obtained by looking at
the name or contents of a particular file on disk. the name or contents of a particular file on disk.
On Windows the current timzeone name comes from the registry. On Windows the current timzeone name comes from the registry.
But however the name is obtained there is no guarante In either method, there is no guarantee that the "native" current timezone name obtained
that the "native" current timezone name obtained in this way
will match any of the "Standard" names in this library's "database". will match any of the "Standard" names in this library's "database".
On Linux, the names usually do seem to match so mapping functions to map from On Linux, the names usually do seem to match so mapping functions to map from
native to "Standard" are typically NOT required. native to "Standard" are typically not required.
On Windows, the names are never Standard mapping is always required. On Windows, the names are never "Standard" so mapping is always required.
One should not equate the mapping process with Windows. Technically any OS may use the mapping process but currently only Windows does use it.
Windows is just currently the only client of them.
Technically any OS may required mapping.
*/ */
#ifdef _WIN32 #ifdef _WIN32