forked from HowardHinnant/date
Remove support for using system() now other means proven.
* Other miscellaneous improvements.
This commit is contained in:
@@ -90,9 +90,9 @@ tzmain()
|
|||||||
auto& db = get_tzdb();
|
auto& db = get_tzdb();
|
||||||
std::vector<std::string> names;
|
std::vector<std::string> names;
|
||||||
names.reserve(db.zones.size() + db.links.size());
|
names.reserve(db.zones.size() + db.links.size());
|
||||||
for (auto& zone : db.zones)
|
for (const auto& zone : db.zones)
|
||||||
names.push_back(zone.name());
|
names.push_back(zone.name());
|
||||||
for (auto& link : db.links)
|
for (const auto& link : db.links)
|
||||||
names.push_back(link.name());
|
names.push_back(link.name());
|
||||||
std::sort(names.begin(), names.end());
|
std::sort(names.begin(), names.end());
|
||||||
std::cout << db.version << "\n\n";
|
std::cout << db.version << "\n\n";
|
||||||
|
127
tz.cpp
127
tz.cpp
@@ -85,6 +85,7 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <array>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -106,14 +107,12 @@
|
|||||||
#else // !WIN32
|
#else // !WIN32
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
# include <wordexp.h>
|
# include <wordexp.h>
|
||||||
# if !USE_SHELL_API
|
|
||||||
# include <sys/stat.h>
|
# include <sys/stat.h>
|
||||||
# include <sys/fcntl.h>
|
# include <sys/fcntl.h>
|
||||||
# include <dirent.h>
|
# include <dirent.h>
|
||||||
# include <cstring>
|
# include <cstring>
|
||||||
# include <sys/wait.h>
|
# include <sys/wait.h>
|
||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
# endif //!USE_SHELL_API
|
|
||||||
#endif // !WIN32
|
#endif // !WIN32
|
||||||
|
|
||||||
#if HAS_REMOTE_API
|
#if HAS_REMOTE_API
|
||||||
@@ -155,14 +154,6 @@ get_known_folder(const GUID& folderid)
|
|||||||
return folder;
|
return folder;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Usually something like "c:\Program Files".
|
|
||||||
static
|
|
||||||
std::string
|
|
||||||
get_program_folder()
|
|
||||||
{
|
|
||||||
return get_known_folder(FOLDERID_ProgramFiles);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Usually something like "c:\Users\username\Downloads".
|
// Usually something like "c:\Users\username\Downloads".
|
||||||
static
|
static
|
||||||
std::string
|
std::string
|
||||||
@@ -217,7 +208,7 @@ get_download_gz_file(const std::string& version)
|
|||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const std::vector<std::string> files =
|
static const std::array<const std::string, 12> files
|
||||||
{
|
{
|
||||||
"africa", "antarctica", "asia", "australasia", "backward", "etcetera", "europe",
|
"africa", "antarctica", "asia", "australasia", "backward", "etcetera", "europe",
|
||||||
"pacificnew", "northamerica", "southamerica", "systemv", "leapseconds"
|
"pacificnew", "northamerica", "southamerica", "systemv", "leapseconds"
|
||||||
@@ -434,8 +425,6 @@ load_timezone_mappings_from_xml_file(const std::string& input_path)
|
|||||||
// Quick but not overly forgiving XML mapping file processing.
|
// Quick but not overly forgiving XML mapping file processing.
|
||||||
bool mapTimezonesOpenTagFound = false;
|
bool mapTimezonesOpenTagFound = false;
|
||||||
bool mapTimezonesCloseTagFound = false;
|
bool mapTimezonesCloseTagFound = false;
|
||||||
bool mapZoneOpenTagFound = false;
|
|
||||||
bool mapTZoneCloseTagFound = false;
|
|
||||||
std::size_t mapZonePos = std::string::npos;
|
std::size_t mapZonePos = std::string::npos;
|
||||||
std::size_t mapTimezonesPos = std::string::npos;
|
std::size_t mapTimezonesPos = std::string::npos;
|
||||||
CONSTDATA char mapTimeZonesOpeningTag[] = { "<mapTimezones " };
|
CONSTDATA char mapTimeZonesOpeningTag[] = { "<mapTimezones " };
|
||||||
@@ -1719,7 +1708,7 @@ find_rule_for_zone(const std::pair<const Rule*, const Rule*>& eqr,
|
|||||||
const Rule* prev_rule = nullptr;
|
const Rule* prev_rule = nullptr;
|
||||||
while (r != nullptr)
|
while (r != nullptr)
|
||||||
{
|
{
|
||||||
bool found;
|
bool found = false;
|
||||||
switch (r->mdt().zone())
|
switch (r->mdt().zone())
|
||||||
{
|
{
|
||||||
case tz::utc:
|
case tz::utc:
|
||||||
@@ -1820,6 +1809,7 @@ time_zone::adjust_infos(const std::vector<Rule>& rules)
|
|||||||
{
|
{
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
using string = std::string;
|
using string = std::string;
|
||||||
|
in.clear();
|
||||||
in.str(z.u.rule_);
|
in.str(z.u.rule_);
|
||||||
auto tmp = duration_cast<minutes>(parse_signed_time(in));
|
auto tmp = duration_cast<minutes>(parse_signed_time(in));
|
||||||
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
|
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
|
||||||
@@ -2289,35 +2279,21 @@ remote_download(const std::string& version)
|
|||||||
auto mapping_file = get_download_mapping_file(version);
|
auto mapping_file = get_download_mapping_file(version);
|
||||||
result = download_to_file("http://unicode.org/repos/cldr/trunk/common/"
|
result = download_to_file("http://unicode.org/repos/cldr/trunk/common/"
|
||||||
"supplemental/windowsZones.xml",
|
"supplemental/windowsZones.xml",
|
||||||
mapping_file, download_file_options::text);
|
mapping_file, download_file_options::text);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO! Using system() create a process and a console window.
|
|
||||||
// This is useful to see what errors may occur but is slow and distracting.
|
|
||||||
// Consider implementing this functionality more directly, such as
|
|
||||||
// using _mkdir and CreateProcess etc.
|
|
||||||
// But use the current means now as matches Unix implementations and while
|
|
||||||
// in proof of concept / testing phase.
|
|
||||||
// TODO! Use <filesystem> eventually.
|
// TODO! Use <filesystem> eventually.
|
||||||
static
|
static
|
||||||
bool
|
bool
|
||||||
remove_folder_and_subfolders(const std::string& folder)
|
remove_folder_and_subfolders(const std::string& folder)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# if USE_SHELL_API
|
|
||||||
// Delete the folder contents by deleting the folder.
|
|
||||||
std::string cmd = "rd /s /q \"";
|
|
||||||
cmd += folder;
|
|
||||||
cmd += '\"';
|
|
||||||
return std::system(cmd.c_str()) == EXIT_SUCCESS;
|
|
||||||
# else // !USE_SHELL_API
|
|
||||||
// Create a buffer containing the path to delete. It must be terminated
|
// Create a buffer containing the path to delete. It must be terminated
|
||||||
// by two nuls. Who designs these API's...
|
// by two nuls. Who designs these API's...
|
||||||
std::vector<char> from;
|
std::vector<char> from(folder.begin(), folder.end());
|
||||||
from.assign(folder.begin(), folder.end());
|
|
||||||
from.push_back('\0');
|
from.push_back('\0');
|
||||||
from.push_back('\0');
|
from.push_back('\0');
|
||||||
SHFILEOPSTRUCT fo{}; // Zero initialize.
|
SHFILEOPSTRUCT fo{}; // Zero initialize.
|
||||||
@@ -2328,11 +2304,7 @@ remove_folder_and_subfolders(const std::string& folder)
|
|||||||
if (ret == 0 && !fo.fAnyOperationsAborted)
|
if (ret == 0 && !fo.fAnyOperationsAborted)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
# endif // !USE_SHELL_API
|
|
||||||
#else // !WIN32
|
#else // !WIN32
|
||||||
# if USE_SHELL_API
|
|
||||||
return std::system(("rm -R " + folder).c_str()) == EXIT_SUCCESS;
|
|
||||||
# else // !USE_SHELL_API
|
|
||||||
struct dir_deleter {
|
struct dir_deleter {
|
||||||
dir_deleter() {}
|
dir_deleter() {}
|
||||||
void operator()(DIR* d) const
|
void operator()(DIR* d) const
|
||||||
@@ -2377,7 +2349,6 @@ remove_folder_and_subfolders(const std::string& folder)
|
|||||||
r = rmdir(folder.c_str()) == 0;
|
r = rmdir(folder.c_str()) == 0;
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
# endif // !USE_SHELL_API
|
|
||||||
#endif // !WIN32
|
#endif // !WIN32
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2386,21 +2357,9 @@ bool
|
|||||||
make_directory(const std::string& folder)
|
make_directory(const std::string& folder)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# if USE_SHELL_API
|
|
||||||
// Re-create the folder.
|
|
||||||
std::string cmd = "mkdir \"";
|
|
||||||
cmd += folder;
|
|
||||||
cmd += '\"';
|
|
||||||
return std::system(cmd.c_str()) == EXIT_SUCCESS;
|
|
||||||
# else // !USE_SHELL_API
|
|
||||||
return _mkdir(folder.c_str()) == 0;
|
return _mkdir(folder.c_str()) == 0;
|
||||||
# endif // !USE_SHELL_API
|
|
||||||
#else // !WIN32
|
#else // !WIN32
|
||||||
# if USE_SHELL_API
|
|
||||||
return std::system(("mkdir " + folder).c_str()) == EXIT_SUCCESS;
|
|
||||||
# else // !USE_SHELL_API
|
|
||||||
return mkdir(folder.c_str(), 0777) == 0;
|
return mkdir(folder.c_str(), 0777) == 0;
|
||||||
# endif // !USE_SHELL_API
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2409,20 +2368,9 @@ bool
|
|||||||
delete_file(const std::string& file)
|
delete_file(const std::string& file)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# if USE_SHELL_API
|
|
||||||
std::string cmd = "del \"";
|
|
||||||
cmd += file;
|
|
||||||
cmd += '\"';
|
|
||||||
return std::system(cmd.c_str()) == 0;
|
|
||||||
# else // !USE_SHELL_API
|
|
||||||
return _unlink(file.c_str()) == 0;
|
return _unlink(file.c_str()) == 0;
|
||||||
# endif // !USE_SHELL_API
|
|
||||||
#else // !WIN32
|
#else // !WIN32
|
||||||
# if USE_SHELL_API
|
|
||||||
return std::system(("rm " + file).c_str()) == EXIT_SUCCESS;
|
|
||||||
# else // !USE_SHELL_API
|
|
||||||
return unlink(file.c_str()) == 0;
|
return unlink(file.c_str()) == 0;
|
||||||
# endif // !USE_SHELL_API
|
|
||||||
#endif // !WIN32
|
#endif // !WIN32
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2433,22 +2381,9 @@ bool
|
|||||||
move_file(const std::string& from, const std::string& to)
|
move_file(const std::string& from, const std::string& to)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# if USE_SHELL_API
|
|
||||||
std::string cmd = "move \"";
|
|
||||||
cmd += from;
|
|
||||||
cmd += "\" \"";
|
|
||||||
cmd += to;
|
|
||||||
cmd += '\"';
|
|
||||||
return std::system(cmd.c_str()) == EXIT_SUCCESS;
|
|
||||||
# else // !USE_SHELL_API
|
|
||||||
return !!::MoveFile(from.c_str(), to.c_str());
|
return !!::MoveFile(from.c_str(), to.c_str());
|
||||||
# endif // !USE_SHELL_API
|
|
||||||
#else // !WIN32
|
#else // !WIN32
|
||||||
# if USE_SHELL_API
|
|
||||||
return std::system(("mv " + from + " " + to).c_str()) == EXIT_SUCCESS;
|
|
||||||
# else
|
|
||||||
return rename(from, to) == 0);
|
return rename(from, to) == 0);
|
||||||
# endif
|
|
||||||
#endif // !WIN32
|
#endif // !WIN32
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2456,6 +2391,14 @@ move_file(const std::string& from, const std::string& to)
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
// Usually something like "c:\Program Files".
|
||||||
|
static
|
||||||
|
std::string
|
||||||
|
get_program_folder()
|
||||||
|
{
|
||||||
|
return get_known_folder(FOLDERID_ProgramFiles);
|
||||||
|
}
|
||||||
|
|
||||||
// Note folder can and usually does contain spaces.
|
// Note folder can and usually does contain spaces.
|
||||||
static
|
static
|
||||||
std::string
|
std::string
|
||||||
@@ -2488,13 +2431,12 @@ get_unzip_program()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
path += get_program_folder();
|
path = get_program_folder();
|
||||||
path += folder_delimiter;
|
path += folder_delimiter;
|
||||||
path += "7-Zip\\7z.exe";
|
path += "7-Zip\\7z.exe";
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !USE_SHELL_API
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
run_program(const std::string& command)
|
run_program(const std::string& command)
|
||||||
@@ -2522,7 +2464,6 @@ run_program(const std::string& command)
|
|||||||
}
|
}
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
#endif // !USE_SHELL_API
|
|
||||||
|
|
||||||
static
|
static
|
||||||
std::string
|
std::string
|
||||||
@@ -2557,18 +2498,8 @@ extract_gz_file(const std::string& version, const std::string& gz_file,
|
|||||||
cmd += dest_folder;
|
cmd += dest_folder;
|
||||||
cmd += '\"';
|
cmd += '\"';
|
||||||
|
|
||||||
#if USE_SHELL_API
|
|
||||||
// When using shelling out with std::system() extra quotes are required around the
|
|
||||||
// whole command. It's weird but neccessary it seems, see:
|
|
||||||
// http://stackoverflow.com/q/27975969/576911
|
|
||||||
|
|
||||||
cmd = "\"" + cmd + "\"";
|
|
||||||
if (std::system(cmd.c_str()) == EXIT_SUCCESS)
|
|
||||||
unzip_result = true;
|
|
||||||
#else // !USE_SHELL_API
|
|
||||||
if (run_program(cmd) == EXIT_SUCCESS)
|
if (run_program(cmd) == EXIT_SUCCESS)
|
||||||
unzip_result = true;
|
unzip_result = true;
|
||||||
#endif // !USE_SHELL_API
|
|
||||||
if (unzip_result)
|
if (unzip_result)
|
||||||
delete_file(gz_file);
|
delete_file(gz_file);
|
||||||
|
|
||||||
@@ -2582,15 +2513,8 @@ extract_gz_file(const std::string& version, const std::string& gz_file,
|
|||||||
cmd += "\" -o\"";
|
cmd += "\" -o\"";
|
||||||
cmd += install;
|
cmd += install;
|
||||||
cmd += '\"';
|
cmd += '\"';
|
||||||
#if USE_SHELL_API
|
|
||||||
cmd = "\"" + cmd + "\"";
|
|
||||||
if (std::system(cmd.c_str()) == EXIT_SUCCESS)
|
|
||||||
unzip_result = true;
|
|
||||||
#else // !USE_SHELL_API
|
|
||||||
if (run_program(cmd) == EXIT_SUCCESS)
|
if (run_program(cmd) == EXIT_SUCCESS)
|
||||||
unzip_result = true;
|
unzip_result = true;
|
||||||
#endif // !USE_SHELL_API
|
|
||||||
|
|
||||||
if (unzip_result)
|
if (unzip_result)
|
||||||
delete_file(tar_file);
|
delete_file(tar_file);
|
||||||
|
|
||||||
@@ -2599,7 +2523,6 @@ extract_gz_file(const std::string& version, const std::string& gz_file,
|
|||||||
|
|
||||||
#else // !_WIN32
|
#else // !_WIN32
|
||||||
|
|
||||||
#if !USE_SHELL_API
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
run_program(const char* prog, const char*const args[])
|
run_program(const char* prog, const char*const args[])
|
||||||
@@ -2629,7 +2552,6 @@ run_program(const char* prog, const char*const args[])
|
|||||||
}
|
}
|
||||||
else // We are in the child process. Start the program the parent wants to run.
|
else // We are in the child process. Start the program the parent wants to run.
|
||||||
{
|
{
|
||||||
|
|
||||||
if (execv(prog, const_cast<char**>(args)) == -1) // Does not return.
|
if (execv(prog, const_cast<char**>(args)) == -1) // Does not return.
|
||||||
{
|
{
|
||||||
perror("unreachable 0\n");
|
perror("unreachable 0\n");
|
||||||
@@ -2643,22 +2565,17 @@ run_program(const char* prog, const char*const args[])
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
#endif // !USE_SHELL_API
|
|
||||||
|
|
||||||
static
|
static
|
||||||
bool
|
bool
|
||||||
extract_gz_file(const std::string&, const std::string& gz_file, const std::string&)
|
extract_gz_file(const std::string&, const std::string& gz_file, const std::string&)
|
||||||
{
|
{
|
||||||
#if USE_SHELL_API
|
|
||||||
bool unzipped = std::system(("tar -xzf " + gz_file + " -C " + install).c_str()) == EXIT_SUCCESS;
|
|
||||||
#else // !USE_SHELL_API
|
|
||||||
const char prog[] = {"/usr/bin/tar"};
|
const char prog[] = {"/usr/bin/tar"};
|
||||||
const char*const args[] =
|
const char*const args[] =
|
||||||
{
|
{
|
||||||
prog, "-xzf", gz_file.c_str(), "-C", install.c_str(), nullptr
|
prog, "-xzf", gz_file.c_str(), "-C", install.c_str(), nullptr
|
||||||
};
|
};
|
||||||
bool unzipped = (run_program(prog, args) == EXIT_SUCCESS);
|
bool unzipped = (run_program(prog, args) == EXIT_SUCCESS);
|
||||||
#endif // !USE_SHELL_API
|
|
||||||
if (unzipped)
|
if (unzipped)
|
||||||
{
|
{
|
||||||
delete_file(gz_file);
|
delete_file(gz_file);
|
||||||
@@ -2722,8 +2639,6 @@ init_tzdb()
|
|||||||
{
|
{
|
||||||
using namespace date;
|
using namespace date;
|
||||||
const std::string path = install + folder_delimiter;
|
const std::string path = install + folder_delimiter;
|
||||||
std::string line;
|
|
||||||
bool continue_zone = false;
|
|
||||||
TZ_DB db;
|
TZ_DB db;
|
||||||
|
|
||||||
#if AUTO_DOWNLOAD
|
#if AUTO_DOWNLOAD
|
||||||
@@ -2775,9 +2690,19 @@ init_tzdb()
|
|||||||
db.version = get_version(path);
|
db.version = get_version(path);
|
||||||
#endif // !AUTO_DOWNLOAD
|
#endif // !AUTO_DOWNLOAD
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
bool continue_zone = false;
|
||||||
for (const auto& filename : files)
|
for (const auto& filename : files)
|
||||||
{
|
{
|
||||||
std::ifstream infile(path + filename);
|
std::string infile_name{path + filename};
|
||||||
|
std::ifstream infile(infile_name);
|
||||||
|
if (!infile)
|
||||||
|
{
|
||||||
|
std::string msg = "Error opening time zone data file \"";
|
||||||
|
msg += infile_name;
|
||||||
|
msg += "\".";
|
||||||
|
throw std::runtime_error(msg);
|
||||||
|
}
|
||||||
while (infile)
|
while (infile)
|
||||||
{
|
{
|
||||||
std::getline(infile, line);
|
std::getline(infile, line);
|
||||||
|
Reference in New Issue
Block a user