summaryrefslogtreecommitdiff
path: root/zen
diff options
context:
space:
mode:
authorDaniel Wilhelm <shieldwed@outlook.com>2018-05-09 00:09:55 +0200
committerDaniel Wilhelm <shieldwed@outlook.com>2018-05-09 00:09:55 +0200
commit9b623ea3943165fe7efb5e47a0b5b9452c1599e6 (patch)
treedde40e07e907ac6e0ca9ea32524f2cd4810d4be6 /zen
parent9.7 (diff)
downloadFreeFileSync-9b623ea3943165fe7efb5e47a0b5b9452c1599e6.tar.gz
FreeFileSync-9b623ea3943165fe7efb5e47a0b5b9452c1599e6.tar.bz2
FreeFileSync-9b623ea3943165fe7efb5e47a0b5b9452c1599e6.zip
9.8
Diffstat (limited to 'zen')
-rwxr-xr-xzen/basic_math.h18
-rwxr-xr-xzen/build_info.h3
-rwxr-xr-xzen/dir_watcher.cpp22
-rwxr-xr-xzen/dir_watcher.h13
-rwxr-xr-xzen/error_log.h29
-rwxr-xr-xzen/file_access.h1
-rwxr-xr-xzen/file_error.h1
-rwxr-xr-xzen/file_id_def.h2
-rwxr-xr-xzen/file_io.h2
-rwxr-xr-xzen/file_traverser.cpp2
-rwxr-xr-xzen/file_traverser.h6
-rwxr-xr-xzen/fixed_list.h1
-rwxr-xr-xzen/format_unit.cpp7
-rwxr-xr-xzen/format_unit.h4
-rwxr-xr-xzen/globals.h1
-rwxr-xr-xzen/i18n.h7
-rwxr-xr-xzen/optional.h1
-rwxr-xr-xzen/process_priority.h1
-rwxr-xr-xzen/scope_guard.h2
-rwxr-xr-xzen/shell_execute.h8
-rwxr-xr-xzen/shutdown.cpp4
-rwxr-xr-xzen/shutdown.h1
-rwxr-xr-xzen/string_base.h2
-rwxr-xr-xzen/string_tools.h12
-rwxr-xr-xzen/string_traits.h16
-rwxr-xr-xzen/thread.h2
-rwxr-xr-xzen/time.h199
-rwxr-xr-xzen/utf.h13
-rwxr-xr-xzen/xml_io.h2
-rwxr-xr-xzen/zstring.cpp11
30 files changed, 220 insertions, 173 deletions
diff --git a/zen/basic_math.h b/zen/basic_math.h
index 1b6b7e97..16f69bde 100755
--- a/zen/basic_math.h
+++ b/zen/basic_math.h
@@ -31,7 +31,7 @@ template <class T> T clampCpy(T val, T minVal, T maxVal);
template <class T, class InputIterator> //precondition: range must be sorted!
auto nearMatch(const T& val, InputIterator first, InputIterator last);
-int round(double d); //"little rounding function"
+int64_t round(double d); //"little rounding function"
template <class N, class D>
auto integerDivideRoundUp(N numerator, D denominator);
@@ -182,7 +182,7 @@ std::pair<InputIterator, InputIterator> minMaxElement(InputIterator first, Input
}
}
}
- return std::make_pair(lowest, largest);
+ return { lowest, largest };
}
@@ -220,20 +220,20 @@ bool isNull(T value)
inline
-int round(double d)
+int64_t round(double d)
{
- assert(d - 0.5 >= std::numeric_limits<int>::min() && //if double is larger than what int can represent:
- d + 0.5 <= std::numeric_limits<int>::max()); //=> undefined behavior!
- return static_cast<int>(d < 0 ? d - 0.5 : d + 0.5);
+ assert(d - 0.5 >= std::numeric_limits<int64_t>::min() && //if double is larger than what int can represent:
+ d + 0.5 <= std::numeric_limits<int64_t>::max()); //=> undefined behavior!
+ return static_cast<int64_t>(d < 0 ? d - 0.5 : d + 0.5);
}
template <class N, class D> inline
auto integerDivideRoundUp(N numerator, D denominator)
{
- static_assert(std::is_integral<N>::value && std::is_unsigned<N>::value, "");
- static_assert(std::is_integral<D>::value && std::is_unsigned<D>::value, "");
- assert(denominator > 0);
+ static_assert(std::is_integral<N>::value, "");
+ static_assert(std::is_integral<D>::value, "");
+ assert(numerator > 0 && denominator > 0);
return (numerator + denominator - 1) / denominator;
}
diff --git a/zen/build_info.h b/zen/build_info.h
index 7b0aa9cf..9b8b7fc0 100755
--- a/zen/build_info.h
+++ b/zen/build_info.h
@@ -7,8 +7,6 @@
#ifndef BUILD_INFO_H_5928539285603428657
#define BUILD_INFO_H_5928539285603428657
-namespace zen
-{
//determine build info: defines ZEN_BUILD_32BIT or ZEN_BUILD_64BIT
#ifdef __LP64__
@@ -24,6 +22,5 @@ namespace zen
#ifdef ZEN_BUILD_64BIT
static_assert(sizeof(void*) == 8, "");
#endif
-}
#endif //BUILD_INFO_H_5928539285603428657
diff --git a/zen/dir_watcher.cpp b/zen/dir_watcher.cpp
index 17f2244d..0cbde150 100755
--- a/zen/dir_watcher.cpp
+++ b/zen/dir_watcher.cpp
@@ -30,11 +30,11 @@ struct DirWatcher::Impl
DirWatcher::DirWatcher(const Zstring& dirPath) : //throw FileError
- baseDirPath(dirPath),
+ baseDirPath_(dirPath),
pimpl_(std::make_unique<Impl>())
{
//get all subdirectories
- std::vector<Zstring> fullFolderList { baseDirPath };
+ std::vector<Zstring> fullFolderList { baseDirPath_ };
{
std::function<void (const Zstring& path)> traverse;
@@ -46,13 +46,13 @@ DirWatcher::DirWatcher(const Zstring& dirPath) : //throw FileError
[&](const std::wstring& errorMsg) { throw FileError(errorMsg); });
};
- traverse(baseDirPath);
+ traverse(baseDirPath_);
}
//init
pimpl_->notifDescr = ::inotify_init();
if (pimpl_->notifDescr == -1)
- THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot monitor directory %x."), L"%x", fmtPath(baseDirPath)), L"inotify_init");
+ THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot monitor directory %x."), L"%x", fmtPath(baseDirPath_)), L"inotify_init");
ZEN_ON_SCOPE_FAIL( ::close(pimpl_->notifDescr); );
@@ -64,7 +64,7 @@ DirWatcher::DirWatcher(const Zstring& dirPath) : //throw FileError
initSuccess = ::fcntl(pimpl_->notifDescr, F_SETFL, flags | O_NONBLOCK) != -1;
}
if (!initSuccess)
- THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot monitor directory %x."), L"%x", fmtPath(baseDirPath)), L"fcntl");
+ THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot monitor directory %x."), L"%x", fmtPath(baseDirPath_)), L"fcntl");
//add watches
for (const Zstring& subDirPath : fullFolderList)
@@ -101,7 +101,7 @@ DirWatcher::~DirWatcher()
}
-std::vector<DirWatcher::Entry> DirWatcher::getChanges(const std::function<void()>&) //throw FileError
+std::vector<DirWatcher::Entry> DirWatcher::getChanges(const std::function<void()>& requestUiRefresh, std::chrono::milliseconds cbInterval) //throw FileError
{
std::vector<char> buffer(512 * (sizeof(struct ::inotify_event) + NAME_MAX + 1));
@@ -118,7 +118,7 @@ std::vector<DirWatcher::Entry> DirWatcher::getChanges(const std::function<void()
if (errno == EAGAIN) //this error is ignored in all inotify wrappers I found
return std::vector<Entry>();
- THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot monitor directory %x."), L"%x", fmtPath(baseDirPath)), L"read");
+ THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot monitor directory %x."), L"%x", fmtPath(baseDirPath_)), L"read");
}
std::vector<Entry> output;
@@ -135,19 +135,19 @@ std::vector<DirWatcher::Entry> DirWatcher::getChanges(const std::function<void()
{
//Note: evt.len is NOT the size of the evt.name c-string, but the array size including all padding 0 characters!
//It may be even 0 in which case evt.name must not be used!
- const Zstring fullname = it->second + evt.name;
+ const Zstring itemPath = it->second + evt.name;
if ((evt.mask & IN_CREATE) ||
(evt.mask & IN_MOVED_TO))
- output.emplace_back(ACTION_CREATE, fullname);
+ output.push_back({ ACTION_CREATE, itemPath });
else if ((evt.mask & IN_MODIFY) ||
(evt.mask & IN_CLOSE_WRITE))
- output.emplace_back(ACTION_UPDATE, fullname);
+ output.push_back({ ACTION_UPDATE, itemPath });
else if ((evt.mask & IN_DELETE ) ||
(evt.mask & IN_DELETE_SELF) ||
(evt.mask & IN_MOVE_SELF ) ||
(evt.mask & IN_MOVED_FROM))
- output.emplace_back(ACTION_DELETE, fullname);
+ output.push_back({ ACTION_DELETE, itemPath });
}
}
bytePos += sizeof(struct ::inotify_event) + evt.len;
diff --git a/zen/dir_watcher.h b/zen/dir_watcher.h
index 8045d184..b4796618 100755
--- a/zen/dir_watcher.h
+++ b/zen/dir_watcher.h
@@ -9,6 +9,7 @@
#include <vector>
#include <memory>
+#include <chrono>
#include <functional>
#include "file_error.h"
@@ -50,26 +51,22 @@ public:
struct Entry
{
- Entry() {}
- Entry(ActionType action, const Zstring& filepath) : action_(action), filepath_(filepath) {}
-
- ActionType action_ = ACTION_CREATE;
- Zstring filepath_;
+ ActionType action = ACTION_CREATE;
+ Zstring filePath;
};
//extract accumulated changes since last call
- std::vector<Entry> getChanges(const std::function<void()>& processGuiMessages); //throw FileError
+ std::vector<Entry> getChanges(const std::function<void()>& requestUiRefresh, std::chrono::milliseconds cbInterval); //throw FileError
private:
DirWatcher (const DirWatcher&) = delete;
DirWatcher& operator=(const DirWatcher&) = delete;
- const Zstring baseDirPath;
+ const Zstring baseDirPath_;
struct Impl;
const std::unique_ptr<Impl> pimpl_;
};
-
}
#endif
diff --git a/zen/error_log.h b/zen/error_log.h
index 1fcbdefb..b6660850 100755
--- a/zen/error_log.h
+++ b/zen/error_log.h
@@ -20,18 +20,18 @@ namespace zen
{
enum MessageType
{
- TYPE_INFO = 0x1,
- TYPE_WARNING = 0x2,
- TYPE_ERROR = 0x4,
- TYPE_FATAL_ERROR = 0x8,
+ MSG_TYPE_INFO = 0x1,
+ MSG_TYPE_WARNING = 0x2,
+ MSG_TYPE_ERROR = 0x4,
+ MSG_TYPE_FATAL_ERROR = 0x8,
};
using MsgString = Zbase<wchar_t>; //std::wstring may employ small string optimization: we cannot accept bloating the "ErrorLog::entries" memory block below (think 1 million items)
struct LogEntry
{
- time_t time;
- MessageType type;
+ time_t time = 0;
+ MessageType type = MSG_TYPE_FATAL_ERROR;
MsgString message;
};
@@ -45,7 +45,7 @@ public:
template <class String> //a wchar_t-based string!
void logMsg(const String& text, MessageType type);
- int getItemCount(int typeFilter = TYPE_INFO | TYPE_WARNING | TYPE_ERROR | TYPE_FATAL_ERROR) const;
+ int getItemCount(int typeFilter = MSG_TYPE_INFO | MSG_TYPE_WARNING | MSG_TYPE_ERROR | MSG_TYPE_FATAL_ERROR) const;
//subset of std::vector<> interface:
using const_iterator = std::vector<LogEntry>::const_iterator;
@@ -67,10 +67,9 @@ private:
//######################## implementation ##########################
template <class String> inline
-void ErrorLog::logMsg(const String& text, zen::MessageType type)
+void ErrorLog::logMsg(const String& text, MessageType type)
{
- const LogEntry newEntry = { std::time(nullptr), type, copyStringTo<MsgString>(text) };
- entries_.push_back(newEntry);
+ entries_.push_back({ std::time(nullptr), type, copyStringTo<MsgString>(text) });
}
@@ -90,13 +89,13 @@ String formatMessageImpl(const LogEntry& entry) //internal linkage
{
switch (entry.type)
{
- case TYPE_INFO:
+ case MSG_TYPE_INFO:
return _("Info");
- case TYPE_WARNING:
+ case MSG_TYPE_WARNING:
return _("Warning");
- case TYPE_ERROR:
+ case MSG_TYPE_ERROR:
return _("Error");
- case TYPE_FATAL_ERROR:
+ case MSG_TYPE_FATAL_ERROR:
return _("Serious Error");
}
assert(false);
@@ -104,7 +103,7 @@ String formatMessageImpl(const LogEntry& entry) //internal linkage
};
String formattedText = L"[" + formatTime<String>(FORMAT_TIME, getLocalTime(entry.time)) + L"] " + copyStringTo<String>(getTypeName()) + L": ";
- const size_t prefixLen = formattedText.size();
+ const size_t prefixLen = formattedText.size(); //considers UTF-16 only!
for (auto it = entry.message.begin(); it != entry.message.end(); )
if (*it == L'\n')
diff --git a/zen/file_access.h b/zen/file_access.h
index 743ad15d..c62ddc98 100755
--- a/zen/file_access.h
+++ b/zen/file_access.h
@@ -13,6 +13,7 @@
#include "file_id_def.h"
#include "serialize.h"
+
namespace zen
{
//note: certain functions require COM initialization! (vista_file_op.h)
diff --git a/zen/file_error.h b/zen/file_error.h
index decc0f7e..086d0998 100755
--- a/zen/file_error.h
+++ b/zen/file_error.h
@@ -12,6 +12,7 @@
#include "utf.h"
#include "sys_error.h" //we'll need this later anyway!
+
namespace zen
{
class FileError //A high-level exception class giving detailed context information for end users
diff --git a/zen/file_id_def.h b/zen/file_id_def.h
index 7772e3e3..f58cb479 100755
--- a/zen/file_id_def.h
+++ b/zen/file_id_def.h
@@ -7,8 +7,6 @@
#ifndef FILE_ID_DEF_H_013287632486321493
#define FILE_ID_DEF_H_013287632486321493
-#include <utility>
-
#include <sys/stat.h>
diff --git a/zen/file_io.h b/zen/file_io.h
index 369cdc01..5b0b8cb0 100755
--- a/zen/file_io.h
+++ b/zen/file_io.h
@@ -13,7 +13,7 @@
namespace zen
{
- const char LINE_BREAK[] = "\n"; //since OS X apple uses newline, too
+ const char LINE_BREAK[] = "\n"; //since OS X Apple uses newline, too
/*
OS-buffered file IO optimized for
diff --git a/zen/file_traverser.cpp b/zen/file_traverser.cpp
index aa4c439e..bc53f206 100755
--- a/zen/file_traverser.cpp
+++ b/zen/file_traverser.cpp
@@ -55,7 +55,7 @@ void zen::traverseFolder(const Zstring& dirPath,
continue;
const Zstring& itemName = itemNameRaw;
- if (itemName.empty()) //checks result of osx::normalizeUtfForPosix, too!
+ if (itemName.empty()) //checks result of normalizeUtfForPosix, too!
throw FileError(replaceCpy(_("Cannot read directory %x."), L"%x", fmtPath(dirPath)), L"readdir_r: Data corruption; item with empty name.");
const Zstring& itemPath = appendSeparator(dirPath) + itemName;
diff --git a/zen/file_traverser.h b/zen/file_traverser.h
index 19359148..5c1683f8 100755
--- a/zen/file_traverser.h
+++ b/zen/file_traverser.h
@@ -18,8 +18,8 @@ struct FileInfo
{
Zstring itemName;
Zstring fullPath;
- uint64_t fileSize; //[bytes]
- time_t modTime; //number of seconds since Jan. 1st 1970 UTC
+ uint64_t fileSize; //[bytes]
+ time_t modTime = 0; //number of seconds since Jan. 1st 1970 UTC
};
struct FolderInfo
@@ -32,7 +32,7 @@ struct SymlinkInfo
{
Zstring itemName;
Zstring fullPath;
- time_t modTime; //number of seconds since Jan. 1st 1970 UTC
+ time_t modTime = 0; //number of seconds since Jan. 1st 1970 UTC
};
//- non-recursive
diff --git a/zen/fixed_list.h b/zen/fixed_list.h
index 535ffa31..10b66233 100755
--- a/zen/fixed_list.h
+++ b/zen/fixed_list.h
@@ -11,6 +11,7 @@
#include <iterator>
#include "stl_tools.h"
+
namespace zen
{
//std::list(C++11)-like class for inplace element construction supporting non-copyable/non-movable types
diff --git a/zen/format_unit.cpp b/zen/format_unit.cpp
index 0f54a34b..09134c07 100755
--- a/zen/format_unit.cpp
+++ b/zen/format_unit.cpp
@@ -5,7 +5,6 @@
// *****************************************************************************
#include "format_unit.h"
-//#include <cwchar> //swprintf
#include <ctime>
#include <cstdio>
#include "basic_math.h"
@@ -112,7 +111,7 @@ std::wstring roundToBlock(double timeInHigh,
const int blockSizeLow = granularity * timeInHigh < 1 ?
numeric::nearMatch(granularity * timeInLow, std::begin(stepsLow), std::end(stepsLow)):
numeric::nearMatch(granularity * timeInHigh, std::begin(stepsHigh), std::end(stepsHigh)) * unitLowPerHigh;
- const int roundedtimeInLow = numeric::round(timeInLow / blockSizeLow) * blockSizeLow;
+ const int roundedtimeInLow = static_cast<int>(numeric::round(timeInLow / blockSizeLow) * blockSizeLow);
std::wstring output = formatUnitTime(roundedtimeInLow / unitLowPerHigh, unitHigh);
if (unitLowPerHigh > blockSizeLow)
@@ -162,13 +161,13 @@ std::wstring zen::formatFraction(double fraction)
-std::wstring zen::ffs_Impl::includeNumberSeparator(const std::wstring& number)
+std::wstring zen::impl::includeNumberSeparator(const std::wstring& number)
{
//we have to include thousands separator ourselves; this doesn't work for all countries (e.g india), but is better than nothing
//::setlocale (LC_ALL, ""); -> implicitly called by wxLocale
const lconv* localInfo = ::localeconv(); //always bound according to doc
- const std::wstring& thousandSep = utfTo<std::wstring>(localInfo->thousands_sep);
+ const std::wstring& thousandSep = zen::utfTo<std::wstring>(localInfo->thousands_sep);
// THOUSANDS_SEPARATOR = std::use_facet<std::numpunct<wchar_t>>(std::locale("")).thousands_sep(); - why not working?
// DECIMAL_POINT = std::use_facet<std::numpunct<wchar_t>>(std::locale("")).decimal_point();
diff --git a/zen/format_unit.h b/zen/format_unit.h
index 154ec542..9c6a4690 100755
--- a/zen/format_unit.h
+++ b/zen/format_unit.h
@@ -37,7 +37,7 @@ std::wstring formatNumber(NumberType number); //format integer number including
//--------------- inline impelementation -------------------------------------------
-namespace ffs_Impl
+namespace impl
{
std::wstring includeNumberSeparator(const std::wstring& number);
}
@@ -46,7 +46,7 @@ template <class NumberType> inline
std::wstring formatNumber(NumberType number)
{
static_assert(IsInteger<NumberType>::value, "");
- return ffs_Impl::includeNumberSeparator(zen::numberTo<std::wstring>(number));
+ return impl::includeNumberSeparator(zen::numberTo<std::wstring>(number));
}
}
diff --git a/zen/globals.h b/zen/globals.h
index 32781f2a..c57d97ff 100755
--- a/zen/globals.h
+++ b/zen/globals.h
@@ -11,6 +11,7 @@
#include <memory>
#include "scope_guard.h"
+
namespace zen
{
//solve static destruction order fiasco by providing shared ownership and serialized access to global variables
diff --git a/zen/i18n.h b/zen/i18n.h
index bb6dbac5..b67a3bb6 100755
--- a/zen/i18n.h
+++ b/zen/i18n.h
@@ -13,6 +13,7 @@
#include "string_tools.h"
#include "format_unit.h"
+
//minimal layer enabling text translation - without platform/library dependencies!
#define ZEN_TRANS_CONCAT_SUB(X, Y) X ## Y
@@ -55,7 +56,7 @@ std::shared_ptr<const TranslationHandler> getTranslator();
//######################## implementation ##############################
-namespace implementation
+namespace impl
{
inline
Global<const TranslationHandler>& refGlobalTranslationHandler()
@@ -69,14 +70,14 @@ Global<const TranslationHandler>& refGlobalTranslationHandler()
inline
std::shared_ptr<const TranslationHandler> getTranslator()
{
- return implementation::refGlobalTranslationHandler().get();
+ return impl::refGlobalTranslationHandler().get();
}
inline
void setTranslator(std::unique_ptr<const TranslationHandler>&& newHandler)
{
- implementation::refGlobalTranslationHandler().set(std::move(newHandler));
+ impl::refGlobalTranslationHandler().set(std::move(newHandler));
}
diff --git a/zen/optional.h b/zen/optional.h
index a2a1a169..0ef5f1db 100755
--- a/zen/optional.h
+++ b/zen/optional.h
@@ -10,6 +10,7 @@
#include <cassert>
#include <type_traits>
+
namespace zen
{
/*
diff --git a/zen/process_priority.h b/zen/process_priority.h
index bec8f9b5..cfadfff1 100755
--- a/zen/process_priority.h
+++ b/zen/process_priority.h
@@ -10,6 +10,7 @@
#include <memory>
#include "file_error.h"
+
namespace zen
{
//signal a "busy" state to the operating system
diff --git a/zen/scope_guard.h b/zen/scope_guard.h
index 2048af9b..6945b011 100755
--- a/zen/scope_guard.h
+++ b/zen/scope_guard.h
@@ -13,7 +13,7 @@
//std::uncaught_exceptions() currently unsupported on GCC and Clang => clean up ASAP
- static_assert(__GNUC__ < 7 || (__GNUC__ == 7 && (__GNUC_MINOR__ < 2 || (__GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ <= 1))), "check std::uncaught_exceptions support");
+ static_assert(__GNUC__ < 7 || (__GNUC__ == 7 && (__GNUC_MINOR__ < 3 || (__GNUC_MINOR__ == 3 && __GNUC_PATCHLEVEL__ <= 0))), "check std::uncaught_exceptions support");
namespace __cxxabiv1
{
diff --git a/zen/shell_execute.h b/zen/shell_execute.h
index 18e4854b..43bede61 100755
--- a/zen/shell_execute.h
+++ b/zen/shell_execute.h
@@ -17,10 +17,10 @@ namespace zen
{
//launch commandline and report errors via popup dialog
//Windows: COM needs to be initialized before calling this function!
-enum ExecutionType
+enum class ExecutionType
{
- EXEC_TYPE_SYNC,
- EXEC_TYPE_ASYNC
+ SYNC,
+ ASYNC
};
namespace
@@ -36,7 +36,7 @@ void shellExecute(const Zstring& command, ExecutionType type) //throw FileError
- uses a zero-sized dummy window as a hack to keep focus which leaves a useless empty icon in ALT-TAB list in Windows
*/
- if (type == EXEC_TYPE_SYNC)
+ if (type == ExecutionType::SYNC)
{
//Posix ::system() - execute a shell command
const int rv = ::system(command.c_str()); //do NOT use std::system as its documentation says nothing about "WEXITSTATUS(rv)", ect...
diff --git a/zen/shutdown.cpp b/zen/shutdown.cpp
index dd02814f..1794e4a8 100755
--- a/zen/shutdown.cpp
+++ b/zen/shutdown.cpp
@@ -18,7 +18,7 @@ void zen::shutdownSystem() //throw FileError
//https://linux.die.net/man/2/reboot => needs admin rights!
//"systemctl" should work without admin rights:
- shellExecute("sleep 1; systemctl poweroff", EXEC_TYPE_ASYNC); //throw FileError
+ shellExecute("sleep 1; systemctl poweroff", ExecutionType::ASYNC); //throw FileError
//sleep 1: give FFS some time to properly shut down!
}
@@ -27,7 +27,7 @@ void zen::shutdownSystem() //throw FileError
void zen::suspendSystem() //throw FileError
{
//"systemctl" should work without admin rights:
- shellExecute("systemctl suspend", EXEC_TYPE_ASYNC); //throw FileError
+ shellExecute("systemctl suspend", ExecutionType::ASYNC); //throw FileError
}
diff --git a/zen/shutdown.h b/zen/shutdown.h
index b9d47df6..df2314f8 100755
--- a/zen/shutdown.h
+++ b/zen/shutdown.h
@@ -9,6 +9,7 @@
#include "file_error.h"
+
namespace zen
{
void shutdownSystem(); //throw FileError
diff --git a/zen/string_base.h b/zen/string_base.h
index 30699c38..2d043d4f 100755
--- a/zen/string_base.h
+++ b/zen/string_base.h
@@ -13,8 +13,8 @@
#include <atomic>
#include "string_tools.h"
-//Zbase - a policy based string class optimizing performance and flexibility
+//Zbase - a policy based string class optimizing performance and flexibility
namespace zen
{
/*
diff --git a/zen/string_tools.h b/zen/string_tools.h
index 5058f78d..7734b6f0 100755
--- a/zen/string_tools.h
+++ b/zen/string_tools.h
@@ -27,6 +27,7 @@ template <class Char> bool isDigit (Char c); //not exactly the same as "std:
template <class Char> bool isHexDigit (Char c);
template <class Char> bool isAsciiAlpha(Char c);
template <class Char> Char asciiToLower(Char c);
+template <class Char> Char asciiToUpper(Char c);
//case-sensitive comparison (compile-time correctness: use different number of arguments as STL comparison predicates!)
struct CmpBinary { template <class Char> int operator()(const Char* lhs, size_t lhsLen, const Char* rhs, size_t rhsLen) const; };
@@ -159,6 +160,15 @@ Char asciiToLower(Char c)
}
+template <class Char> inline
+Char asciiToUpper(Char c)
+{
+ if (static_cast<Char>('a') <= c && c <= static_cast<Char>('z'))
+ return static_cast<Char>(c - static_cast<Char>('a') + static_cast<Char>('A'));
+ return c;
+}
+
+
template <class S, class T, class Function> inline
bool startsWith(const S& str, const T& prefix, Function cmpStringFun)
{
@@ -740,7 +750,7 @@ std::pair<char, char> hexify(unsigned char c, bool upperCase)
else
return static_cast<char>('a' + (num - 10));
};
- return std::make_pair(hexifyDigit(c / 16), hexifyDigit(c % 16));
+ return { hexifyDigit(c / 16), hexifyDigit(c % 16) };
}
diff --git a/zen/string_traits.h b/zen/string_traits.h
index 502250c2..805db46d 100755
--- a/zen/string_traits.h
+++ b/zen/string_traits.h
@@ -63,7 +63,7 @@ private:
//---------------------- implementation ----------------------
-namespace implementation
+namespace impl
{
template<class S, class Char> //test if result of S::c_str() can convert to const Char*
class HasConversion
@@ -137,13 +137,13 @@ public:
}
template <class T>
-struct IsStringLike : StaticBool<implementation::StringTraits<T>::isStringLike> {};
+struct IsStringLike : StaticBool<impl::StringTraits<T>::isStringLike> {};
template <class T>
-struct GetCharType : ResultType<typename implementation::StringTraits<T>::CharType> {};
+struct GetCharType : ResultType<typename impl::StringTraits<T>::CharType> {};
-namespace implementation
+namespace impl
{
//strlen/wcslen are vectorized since VS14 CTP3
inline size_t cStringLength(const char* str) { return std::strlen(str); }
@@ -162,7 +162,7 @@ size_t cStringLength(const C* str)
}
#endif
-template <class S, typename = typename EnableIf<implementation::StringTraits<S>::isStringClass>::Type> inline
+template <class S, typename = typename EnableIf<StringTraits<S>::isStringClass>::Type> inline
const typename GetCharType<S>::Type* strBegin(const S& str) //SFINAE: T must be a "string"
{
return str.c_str();
@@ -179,7 +179,7 @@ inline const char* strBegin(const StringRef<const char >& ref) { return ref
inline const wchar_t* strBegin(const StringRef<const wchar_t>& ref) { return ref.data(); }
-template <class S, typename = typename EnableIf<implementation::StringTraits<S>::isStringClass>::Type> inline
+template <class S, typename = typename EnableIf<StringTraits<S>::isStringClass>::Type> inline
size_t strLength(const S& str) //SFINAE: T must be a "string"
{
return str.length();
@@ -201,7 +201,7 @@ template <class S> inline
auto strBegin(S&& str) -> const typename GetCharType<S>::Type*
{
static_assert(IsStringLike<S>::value, "");
- return implementation::strBegin(std::forward<S>(str));
+ return impl::strBegin(std::forward<S>(str));
}
@@ -209,7 +209,7 @@ template <class S> inline
size_t strLength(S&& str)
{
static_assert(IsStringLike<S>::value, "");
- return implementation::strLength(std::forward<S>(str));
+ return impl::strLength(std::forward<S>(str));
}
}
diff --git a/zen/thread.h b/zen/thread.h
index 0bff5adc..bfb66c31 100755
--- a/zen/thread.h
+++ b/zen/thread.h
@@ -73,7 +73,7 @@ std::async replacement without crappy semantics:
Example:
Zstring dirpath = ...
- auto ft = zen::runAsync([=](){ return zen::dirExists(dirpath); });
+ auto ft = zen::runAsync([=]{ return zen::dirExists(dirpath); });
if (ft.wait_for(std::chrono::milliseconds(200)) == std::future_status::ready && ft.get())
//dir exising
*/
diff --git a/zen/time.h b/zen/time.h
index 67156b9a..74898c7c 100755
--- a/zen/time.h
+++ b/zen/time.h
@@ -22,19 +22,19 @@ struct TimeComp //replaces std::tm and SYSTEMTIME
int minute = 0; //0-59
int second = 0; //0-60 (including leap second)
};
-
inline bool operator==(const TimeComp& lhs, const TimeComp& rhs)
{
return lhs.year == rhs.year && lhs.month == rhs.month && lhs.day == rhs.day && lhs.hour == rhs.hour && lhs.minute == rhs.minute && lhs.second == rhs.second;
}
+inline bool operator!=(const TimeComp& lhs, const TimeComp& rhs) { return !(lhs == rhs); }
-TimeComp getLocalTime(time_t utc = std::time(nullptr)); //convert time_t (UTC) to local time components
-time_t localToTimeT(const TimeComp& comp); //convert local time components to time_t (UTC), returns -1 on error
+TimeComp getLocalTime(time_t utc = std::time(nullptr)); //convert time_t (UTC) to local time components, returns TimeComp() on error
+time_t localToTimeT(const TimeComp& tc); //convert local time components to time_t (UTC), returns -1 on error
-TimeComp getUtcTime(time_t utc = std::time(nullptr)); //convert time_t (UTC) to UTC time components
-time_t utcToTimeT(const TimeComp& comp); //convert UTC time components to time_t (UTC), returns -1 on error
+TimeComp getUtcTime(time_t utc = std::time(nullptr)); //convert time_t (UTC) to UTC time components, returns TimeComp() on error
+time_t utcToTimeT(const TimeComp& tc); //convert UTC time components to time_t (UTC), returns -1 on error
-TimeComp getCompileTime();
+TimeComp getCompileTime(); //returns TimeComp() on error
//----------------------------------------------------------------------------------------------------------------------------------
@@ -45,7 +45,7 @@ format (current) date and time; example:
formatTime<std::wstring>(FORMAT_TIME); -> "17:55:34"
*/
template <class String, class String2>
-String formatTime(const String2& format, const TimeComp& comp = getLocalTime()); //format as specified by "std::strftime", returns empty string on failure
+String formatTime(const String2& format, const TimeComp& tc = getLocalTime()); //format as specified by "std::strftime", returns empty string on failure
//the "format" parameter of formatTime() is partially specialized with the following type tags:
const struct FormatDateTag {} FORMAT_DATE = {}; //%x - locale dependent date representation: e.g. 08/23/01
@@ -58,8 +58,12 @@ const struct FormatIsoDateTimeTag {} FORMAT_ISO_DATE_TIME = {}; //%Y-%m-%d %H:%M
//----------------------------------------------------------------------------------------------------------------------------------
+/*
+example: parseTime("%Y-%m-%d %H:%M:%S", "2001-08-23 14:55:02");
+ parseTime(FORMAT_ISO_DATE_TIME, "2001-08-23 14:55:02");
+*/
template <class String, class String2>
-bool parseTime(const String& format, const String2& str, TimeComp& comp); //similar to ::strptime(), return true on success
+TimeComp parseTime(const String& format, const String2& str); //similar to ::strptime()
//----------------------------------------------------------------------------------------------------------------------------------
@@ -75,29 +79,26 @@ bool parseTime(const String& format, const String2& str, TimeComp& comp); //simi
-
-
-
//############################ implementation ##############################
-namespace implementation
+namespace impl
{
inline
-std::tm toClibTimeComponents(const TimeComp& comp)
+std::tm toClibTimeComponents(const TimeComp& tc)
{
- assert(1 <= comp.month && comp.month <= 12 &&
- 1 <= comp.day && comp.day <= 31 &&
- 0 <= comp.hour && comp.hour <= 23 &&
- 0 <= comp.minute && comp.minute <= 59 &&
- 0 <= comp.second && comp.second <= 61);
+ assert(1 <= tc.month && tc.month <= 12 &&
+ 1 <= tc.day && tc.day <= 31 &&
+ 0 <= tc.hour && tc.hour <= 23 &&
+ 0 <= tc.minute && tc.minute <= 59 &&
+ 0 <= tc.second && tc.second <= 61);
std::tm ctc = {};
- ctc.tm_year = comp.year - 1900; //years since 1900
- ctc.tm_mon = comp.month - 1; //0-11
- ctc.tm_mday = comp.day; //1-31
- ctc.tm_hour = comp.hour; //0-23
- ctc.tm_min = comp.minute; //0-59
- ctc.tm_sec = comp.second; //0-60 (including leap second)
- ctc.tm_isdst = -1; //> 0 if DST is active, == 0 if DST is not active, < 0 if the information is not available
+ ctc.tm_year = tc.year - 1900; //years since 1900
+ ctc.tm_mon = tc.month - 1; //0-11
+ ctc.tm_mday = tc.day; //1-31
+ ctc.tm_hour = tc.hour; //0-23
+ ctc.tm_min = tc.minute; //0-59
+ ctc.tm_sec = tc.second; //0-60 (including leap second)
+ ctc.tm_isdst = -1; //> 0 if DST is active, == 0 if DST is not active, < 0 if the information is not available
//ctc.tm_wday
//ctc.tm_yday
return ctc;
@@ -106,14 +107,14 @@ std::tm toClibTimeComponents(const TimeComp& comp)
inline
TimeComp toZenTimeComponents(const std::tm& ctc)
{
- TimeComp comp;
- comp.year = ctc.tm_year + 1900;
- comp.month = ctc.tm_mon + 1;
- comp.day = ctc.tm_mday;
- comp.hour = ctc.tm_hour;
- comp.minute = ctc.tm_min;
- comp.second = ctc.tm_sec;
- return comp;
+ TimeComp tc;
+ tc.year = ctc.tm_year + 1900;
+ tc.month = ctc.tm_mon + 1;
+ tc.day = ctc.tm_mday;
+ tc.hour = ctc.tm_hour;
+ tc.minute = ctc.tm_min;
+ tc.second = ctc.tm_sec;
+ return tc;
}
@@ -206,7 +207,6 @@ bool isValid(const std::tm& t)
template <class CharType> inline
size_t strftimeWrap(CharType* buffer, size_t bufferSize, const CharType* format, const std::tm* timeptr)
{
-
return strftimeWrap_impl(buffer, bufferSize, format, timeptr);
}
@@ -215,10 +215,10 @@ struct UserDefinedFormatTag {};
struct PredefinedFormatTag {};
template <class String, class String2> inline
-String formatTime(const String2& format, const TimeComp& comp, UserDefinedFormatTag) //format as specified by "std::strftime", returns empty string on failure
+String formatTime(const String2& format, const TimeComp& tc, UserDefinedFormatTag) //format as specified by "std::strftime", returns empty string on failure
{
using CharType = typename GetCharType<String>::Type;
- std::tm ctc = toClibTimeComponents(comp);
+ std::tm ctc = toClibTimeComponents(tc);
std::mktime(&ctc); // unfortunately std::strftime() needs all elements of "struct tm" filled, e.g. tm_wday, tm_yday
//note: although std::mktime() explicitly expects "local time", calculating weekday and day of year *should* be time-zone and DST independent
@@ -227,11 +227,12 @@ String formatTime(const String2& format, const TimeComp& comp, UserDefinedFormat
return String(buffer, charsWritten);
}
+
template <class String, class FormatType> inline
-String formatTime(FormatType, const TimeComp& comp, PredefinedFormatTag)
+String formatTime(FormatType, const TimeComp& tc, PredefinedFormatTag)
{
using CharType = typename GetCharType<String>::Type;
- return formatTime<String>(GetFormat<FormatType>().format(CharType()), comp, UserDefinedFormatTag());
+ return formatTime<String>(GetFormat<FormatType>().format(CharType()), tc, UserDefinedFormatTag());
}
}
@@ -239,37 +240,49 @@ String formatTime(FormatType, const TimeComp& comp, PredefinedFormatTag)
inline
TimeComp getLocalTime(time_t utc)
{
- std::tm comp = {};
- if (::localtime_r(&utc, &comp) == nullptr)
+ if (utc == -1) //failure code from std::time(nullptr)
+ return TimeComp();
+
+ std::tm ctc = {};
+ if (::localtime_r(&utc, &ctc) == nullptr)
return TimeComp();
- return implementation::toZenTimeComponents(comp);
+ return impl::toZenTimeComponents(ctc);
}
inline
TimeComp getUtcTime(time_t utc)
{
- std::tm comp = {};
- if (::gmtime_r(&utc, &comp) == nullptr)
+ if (utc == -1) //failure code from std::time(nullptr)
return TimeComp();
- return implementation::toZenTimeComponents(comp);
+ std::tm ctc = {};
+ if (::gmtime_r(&utc, &ctc) == nullptr)
+ return TimeComp();
+
+ return impl::toZenTimeComponents(ctc);
}
inline
-time_t localToTimeT(const TimeComp& comp) //returns -1 on error
+time_t localToTimeT(const TimeComp& tc) //returns -1 on error
{
- std::tm ctc = implementation::toClibTimeComponents(comp);
+ if (tc == TimeComp())
+ return -1;
+
+ std::tm ctc = impl::toClibTimeComponents(tc);
return std::mktime(&ctc);
}
inline
-time_t utcToTimeT(const TimeComp& comp) //returns -1 on error
+time_t utcToTimeT(const TimeComp& tc) //returns -1 on error
{
- std::tm ctc = implementation::toClibTimeComponents(comp);
+ if (tc == TimeComp())
+ return -1;
+
+ std::tm ctc = impl::toClibTimeComponents(tc);
ctc.tm_isdst = 0; //"Zero (0) to indicate that standard time is in effect" => unused by _mkgmtime, but take no chances
return ::timegm(&ctc);
}
@@ -283,39 +296,36 @@ TimeComp getCompileTime()
if (compileTime[4] == ' ') //day is space-padded, but %d expects zero-padding
compileTime[4] = '0';
- TimeComp tc = {};
- if (parseTime("%b %d %Y %H:%M:%S", compileTime, tc))
- return tc;
-
- assert(false);
- return TimeComp();
+ return parseTime("%b %d %Y %H:%M:%S", compileTime);
}
template <class String, class String2> inline
-String formatTime(const String2& format, const TimeComp& comp)
+String formatTime(const String2& format, const TimeComp& tc)
{
+ if (tc == TimeComp()) //failure code from getLocalTime()
+ return String();
+
using FormatTag = typename SelectIf<
IsSameType<String2, FormatDateTag >::value ||
IsSameType<String2, FormatTimeTag >::value ||
IsSameType<String2, FormatDateTimeTag >::value ||
IsSameType<String2, FormatIsoDateTag >::value ||
IsSameType<String2, FormatIsoTimeTag >::value ||
- IsSameType<String2, FormatIsoDateTimeTag>::value, implementation::PredefinedFormatTag, implementation::UserDefinedFormatTag>::Type;
+ IsSameType<String2, FormatIsoDateTimeTag>::value, impl::PredefinedFormatTag, impl::UserDefinedFormatTag>::Type;
- return implementation::formatTime<String>(format, comp, FormatTag());
+ return impl::formatTime<String>(format, tc, FormatTag());
}
+namespace impl
+{
template <class String, class String2>
-bool parseTime(const String& format, const String2& str, TimeComp& comp) //return true on success
+TimeComp parseTime(const String& format, const String2& str, UserDefinedFormatTag)
{
using CharType = typename GetCharType<String>::Type;
static_assert(IsSameType<CharType, typename GetCharType<String2>::Type>::value, "");
- const CharType* itFmt = strBegin(format);
- const CharType* const fmtLast = itFmt + strLength(format);
-
const CharType* itStr = strBegin(str);
const CharType* const strLast = itStr + strLength(str);
@@ -332,6 +342,11 @@ bool parseTime(const String& format, const String2& str, TimeComp& comp) //retur
return true;
};
+ TimeComp output;
+
+ const CharType* itFmt = strBegin(format);
+ const CharType* const fmtLast = itFmt + strLength(format);
+
for (; itFmt != fmtLast; ++itFmt)
{
const CharType fmt = *itFmt;
@@ -340,22 +355,22 @@ bool parseTime(const String& format, const String2& str, TimeComp& comp) //retur
{
++itFmt;
if (itFmt == fmtLast)
- return false;
+ return TimeComp();
switch (*itFmt)
{
case 'Y':
- if (!extractNumber(comp.year, 4))
- return false;
+ if (!extractNumber(output.year, 4))
+ return TimeComp();
break;
case 'm':
- if (!extractNumber(comp.month, 2))
- return false;
+ if (!extractNumber(output.month, 2))
+ return TimeComp();
break;
case 'b': //abbreviated month name: Jan-Dec
{
if (strLast - itStr < 3)
- return false;
+ return TimeComp();
const char* months[] = { "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec" };
auto itMonth = std::find_if(std::begin(months), std::end(months), [&](const char* name)
@@ -365,30 +380,30 @@ bool parseTime(const String& format, const String2& str, TimeComp& comp) //retur
asciiToLower(itStr[2]) == name[2];
});
if (itMonth == std::end(months))
- return false;
+ return TimeComp();
- comp.month = 1 + static_cast<int>(itMonth - std::begin(months));
+ output.month = 1 + static_cast<int>(itMonth - std::begin(months));
itStr += 3;
}
break;
case 'd':
- if (!extractNumber(comp.day, 2))
- return false;
+ if (!extractNumber(output.day, 2))
+ return TimeComp();
break;
case 'H':
- if (!extractNumber(comp.hour, 2))
- return false;
+ if (!extractNumber(output.hour, 2))
+ return TimeComp();
break;
case 'M':
- if (!extractNumber(comp.minute, 2))
- return false;
+ if (!extractNumber(output.minute, 2))
+ return TimeComp();
break;
case 'S':
- if (!extractNumber(comp.second, 2))
- return false;
+ if (!extractNumber(output.second, 2))
+ return TimeComp();
break;
default:
- return false;
+ return TimeComp();
}
}
else if (isWhiteSpace(fmt)) //single whitespace in format => skip 0..n whitespace chars
@@ -399,12 +414,36 @@ bool parseTime(const String& format, const String2& str, TimeComp& comp) //retur
else
{
if (itStr == strLast || *itStr != fmt)
- return false;
+ return TimeComp();
++itStr;
}
}
- return itStr == strLast;
+ if (itStr != strLast)
+ return TimeComp();
+
+ return output;
+}
+
+
+template <class FormatType, class String> inline
+TimeComp parseTime(FormatType, const String& str, PredefinedFormatTag)
+{
+ using CharType = typename GetCharType<String>::Type;
+ return parseTime(GetFormat<FormatType>().format(CharType()), str, UserDefinedFormatTag());
+}
+}
+
+
+template <class String, class String2> inline
+TimeComp parseTime(const String& format, const String2& str)
+{
+ using FormatTag = typename SelectIf<
+ IsSameType<String, FormatIsoDateTag >::value ||
+ IsSameType<String, FormatIsoTimeTag >::value ||
+ IsSameType<String, FormatIsoDateTimeTag>::value, impl::PredefinedFormatTag, impl::UserDefinedFormatTag>::Type;
+
+ return impl::parseTime(format, str, FormatTag());
}
}
diff --git a/zen/utf.h b/zen/utf.h
index 820148c6..f8ee91d5 100755
--- a/zen/utf.h
+++ b/zen/utf.h
@@ -12,6 +12,7 @@
#include "string_tools.h" //copyStringTo
#include "optional.h"
+
namespace zen
{
//convert all(!) char- and wchar_t-based "string-like" objects applying a UTF8 conversions (but only if necessary!)
@@ -39,7 +40,7 @@ UtfString getUnicodeSubstring(const UtfString& str, size_t uniPosFirst, size_t u
//----------------------- implementation ----------------------------------
-namespace implementation
+namespace impl
{
using CodePoint = uint32_t;
using Char16 = uint16_t;
@@ -308,7 +309,7 @@ using UtfDecoder = UtfDecoderImpl<CharType, sizeof(CharType)>;
template <class UtfString> inline
bool isValidUtf(const UtfString& str)
{
- using namespace implementation;
+ using namespace impl;
UtfDecoder<typename GetCharType<UtfString>::Type> decoder(strBegin(str), strLength(str));
while (Opt<CodePoint> cp = decoder.getNext())
@@ -323,7 +324,7 @@ template <class UtfString> inline
size_t unicodeLength(const UtfString& str) //return number of code points (+ correctly handle broken UTF encoding)
{
size_t uniLen = 0;
- implementation::UtfDecoder<typename GetCharType<UtfString>::Type> decoder(strBegin(str), strLength(str));
+ impl::UtfDecoder<typename GetCharType<UtfString>::Type> decoder(strBegin(str), strLength(str));
while (decoder.getNext())
++uniLen;
return uniLen;
@@ -334,7 +335,7 @@ template <class UtfString> inline
UtfString getUnicodeSubstring(const UtfString& str, size_t uniPosFirst, size_t uniPosLast) //return position of unicode char in UTF-encoded string
{
assert(uniPosFirst <= uniPosLast && uniPosLast <= unicodeLength(str));
- using namespace implementation;
+ using namespace impl;
using CharType = typename GetCharType<UtfString>::Type;
UtfString output;
if (uniPosFirst >= uniPosLast) //optimize for empty range
@@ -353,7 +354,7 @@ UtfString getUnicodeSubstring(const UtfString& str, size_t uniPosFirst, size_t u
//-------------------------------------------------------------------------------------------
-namespace implementation
+namespace impl
{
template <class TargetString, class SourceString> inline
TargetString utfTo(const SourceString& str, FalseType)
@@ -380,7 +381,7 @@ TargetString utfTo(const SourceString& str, TrueType) { return copyStringTo<Targ
template <class TargetString, class SourceString> inline
TargetString utfTo(const SourceString& str)
{
- return implementation::utfTo<TargetString>(str, StaticBool<sizeof(typename GetCharType<SourceString>::Type) == sizeof(typename GetCharType<TargetString>::Type)>());
+ return impl::utfTo<TargetString>(str, StaticBool<sizeof(typename GetCharType<SourceString>::Type) == sizeof(typename GetCharType<TargetString>::Type)>());
}
}
diff --git a/zen/xml_io.h b/zen/xml_io.h
index 8d3346c6..a53a7edb 100755
--- a/zen/xml_io.h
+++ b/zen/xml_io.h
@@ -10,11 +10,11 @@
#include <zenxml/xml.h>
#include "file_error.h"
+
//combine zen::Xml and zen file i/o
//-> loadXmlDocument vs loadStream:
//1. better error reporting
//2. quick exit if (potentially large) input file is not an XML
-
namespace zen
{
XmlDoc loadXmlDocument(const Zstring& filePath); //throw FileError
diff --git a/zen/zstring.cpp b/zen/zstring.cpp
index 2aa3b3f2..ce94fe56 100755
--- a/zen/zstring.cpp
+++ b/zen/zstring.cpp
@@ -44,18 +44,17 @@ int compareNoCaseUtf8(const char* lhs, size_t lhsLen, const char* rhs, size_t rh
//- strncasecmp implements ASCII CI-comparsion only! => signature is broken for UTF8-input; toupper() similarly doesn't support Unicode
//- wcsncasecmp: https://opensource.apple.com/source/Libc/Libc-763.12/string/wcsncasecmp-fbsd.c
// => re-implement comparison based on towlower() to avoid memory allocations
- using namespace zen::implementation;
- UtfDecoder<char> decL(lhs, lhsLen);
- UtfDecoder<char> decR(rhs, rhsLen);
+ impl::UtfDecoder<char> decL(lhs, lhsLen);
+ impl::UtfDecoder<char> decR(rhs, rhsLen);
for (;;)
{
- const Opt<CodePoint> cpL = decL.getNext();
- const Opt<CodePoint> cpR = decR.getNext();
+ const Opt<impl::CodePoint> cpL = decL.getNext();
+ const Opt<impl::CodePoint> cpR = decR.getNext();
if (!cpL || !cpR)
return static_cast<int>(!cpR) - static_cast<int>(!cpL);
- static_assert(sizeof(wchar_t) == sizeof(CodePoint), "");
+ static_assert(sizeof(wchar_t) == sizeof(impl::CodePoint), "");
const wchar_t charL = ::towlower(static_cast<wchar_t>(*cpL)); //ordering: towlower() converts to higher code points than towupper()
const wchar_t charR = ::towlower(static_cast<wchar_t>(*cpR)); //uses LC_CTYPE category of current locale
if (charL != charR)
bgstack15