From 8053187731ae8e3eb368d8360989cf5fd6eed9f7 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 05:32:49 +0200 Subject: Adding upstream version 0.17.0. Signed-off-by: Daniel Baumann --- src/common/CMakeLists.txt | 64 +++++++++ src/common/file-utils.cpp | 359 ++++++++++++++++++++++++++++++++++++++++++++++ src/common/file-utils.h | 89 ++++++++++++ src/common/getoptwin.h | 34 +++++ src/common/str-utils.cpp | 217 ++++++++++++++++++++++++++++ src/common/str-utils.h | 63 ++++++++ src/common/time-utils.cpp | 96 +++++++++++++ src/common/time-utils.h | 38 +++++ src/common/uniwin.h | 60 ++++++++ 9 files changed, 1020 insertions(+) create mode 100644 src/common/CMakeLists.txt create mode 100644 src/common/file-utils.cpp create mode 100644 src/common/file-utils.h create mode 100644 src/common/getoptwin.h create mode 100644 src/common/str-utils.cpp create mode 100644 src/common/str-utils.h create mode 100644 src/common/time-utils.cpp create mode 100644 src/common/time-utils.h create mode 100644 src/common/uniwin.h (limited to 'src/common') diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt new file mode 100644 index 0000000..1ea3445 --- /dev/null +++ b/src/common/CMakeLists.txt @@ -0,0 +1,64 @@ +# Copyright (c) 2020 Ribose Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +add_library(rnp-common OBJECT + str-utils.cpp + file-utils.cpp + time-utils.cpp +) + +if(MSVC) + find_path(GETOPT_INCLUDE_DIR + NAMES getopt.h + ) + find_library(GETOPT_LIBRARY + NAMES getopt + ) + find_path(DIRENT_INCLUDE_DIR + NAMES dirent.h + ) +endif() + +target_include_directories(rnp-common + PUBLIC + "$" + "$" + "$" + PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}" + "${PROJECT_SOURCE_DIR}/src" +) +if(MSVC) + target_include_directories(rnp-common + PRIVATE + "${GETOPT_INCLUDE_DIR}" + "${DIRENT_INCLUDE_DIR}" + ) +endif() + +set_target_properties(rnp-common PROPERTIES + POSITION_INDEPENDENT_CODE ON + CXX_VISIBILITY_PRESET hidden +) + diff --git a/src/common/file-utils.cpp b/src/common/file-utils.cpp new file mode 100644 index 0000000..d9cdb40 --- /dev/null +++ b/src/common/file-utils.cpp @@ -0,0 +1,359 @@ +/* + * Copyright (c) 2017-2020 [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** File utilities + * @file + */ + +#include "file-utils.h" +#include "config.h" +#ifdef _MSC_VER +#include +#include +#include "uniwin.h" +#include +#else +#include +#include +#include +#endif // !_MSC_VER +#include "str-utils.h" +#include +#ifdef _WIN32 +#include // for rnp_mkstemp +#define CATCH_AND_RETURN(v) \ + catch (...) \ + { \ + errno = ENOMEM; \ + return v; \ + } +#else +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#include + +int +rnp_unlink(const char *filename) +{ +#ifdef _WIN32 + try { + return _wunlink(wstr_from_utf8(filename).c_str()); + } + CATCH_AND_RETURN(-1) +#else + return unlink(filename); +#endif +} + +bool +rnp_file_exists(const char *path) +{ + struct stat st; + return rnp_stat(path, &st) == 0 && S_ISREG(st.st_mode); +} + +bool +rnp_dir_exists(const char *path) +{ + struct stat st; + return rnp_stat(path, &st) == 0 && S_ISDIR(st.st_mode); +} + +int +rnp_open(const char *filename, int oflag, int pmode) +{ +#ifdef _WIN32 + try { + return _wopen(wstr_from_utf8(filename).c_str(), oflag, pmode); + } + CATCH_AND_RETURN(-1) +#else + return open(filename, oflag, pmode); +#endif +} + +FILE * +rnp_fopen(const char *filename, const char *mode) +{ +#ifdef _WIN32 + try { + return _wfopen(wstr_from_utf8(filename).c_str(), wstr_from_utf8(mode).c_str()); + } + CATCH_AND_RETURN(NULL) +#else + return fopen(filename, mode); +#endif +} + +FILE * +rnp_fdopen(int fildes, const char *mode) +{ +#ifdef _WIN32 + return _fdopen(fildes, mode); +#else + return fdopen(fildes, mode); +#endif +} + +int +rnp_access(const char *path, int mode) +{ +#ifdef _WIN32 + try { + return _waccess(wstr_from_utf8(path).c_str(), mode); + } + CATCH_AND_RETURN(-1) +#else + return access(path, mode); +#endif +} + +int +rnp_stat(const char *filename, struct stat *statbuf) +{ +#ifdef _WIN32 + static_assert(sizeof(struct stat) == sizeof(struct _stat64i32), + "stat is expected to match _stat64i32"); + try { + return _wstat64i32(wstr_from_utf8(filename).c_str(), (struct _stat64i32 *) statbuf); + } + CATCH_AND_RETURN(-1) +#else + return stat(filename, statbuf); +#endif +} + +#ifdef _WIN32 +int +rnp_mkdir(const char *path) +{ + try { + return _wmkdir(wstr_from_utf8(path).c_str()); + } + CATCH_AND_RETURN(-1) +} +#endif + +int +rnp_rename(const char *oldpath, const char *newpath) +{ +#ifdef _WIN32 + try { + return _wrename(wstr_from_utf8(oldpath).c_str(), wstr_from_utf8(newpath).c_str()); + } + CATCH_AND_RETURN(-1) +#else + return rename(oldpath, newpath); +#endif +} + +#ifdef _WIN32 +_WDIR * +#else +DIR * +#endif +rnp_opendir(const char *path) +{ +#ifdef _WIN32 + try { + return _wopendir(wstr_from_utf8(path).c_str()); + } + CATCH_AND_RETURN(NULL) +#else + return opendir(path); +#endif +} + +std::string +#ifdef _WIN32 +rnp_readdir_name(_WDIR *dir) +{ + _wdirent *ent; + for (;;) { + if ((ent = _wreaddir(dir)) == NULL) { + return std::string(); + } + if (wcscmp(ent->d_name, L".") && wcscmp(ent->d_name, L"..")) { + break; + } + } + try { + return wstr_to_utf8(ent->d_name); + } + CATCH_AND_RETURN(std::string()) +#else +rnp_readdir_name(DIR *dir) +{ + dirent *ent; + for (;;) { + if ((ent = readdir(dir)) == NULL) { + return std::string(); + } + if (strcmp(ent->d_name, ".") && strcmp(ent->d_name, "..")) { + break; + } + } + return std::string(ent->d_name); +#endif +} + +/* return the file modification time */ +int64_t +rnp_filemtime(const char *path) +{ + struct stat st; + + if (rnp_stat(path, &st) != 0) { + return 0; + } else { + return st.st_mtime; + } +} + +#ifdef _WIN32 +static const char letters[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + +/** @private + * generate a temporary file name based on TMPL. + * + * @param tmpl filename template in UTF-8 ending in XXXXXX + * @return file descriptor of newly created and opened file, or -1 on error + **/ +int +rnp_mkstemp(char *tmpl) +{ + try { + int save_errno = errno; + const int mask_length = 6; + int len = strlen(tmpl); + if (len < mask_length || strcmp(&tmpl[len - mask_length], "XXXXXX")) { + errno = EINVAL; + return -1; + } + std::wstring tmpl_w = wstr_from_utf8(tmpl, tmpl + len - mask_length); + + /* This is where the Xs start. */ + char *XXXXXX = &tmpl[len - mask_length]; + + std::random_device rd; + std::mt19937_64 rng(rd()); + + for (unsigned int countdown = TMP_MAX; --countdown;) { + unsigned long long v = rng(); + + XXXXXX[0] = letters[v % 36]; + v /= 36; + XXXXXX[1] = letters[v % 36]; + v /= 36; + XXXXXX[2] = letters[v % 36]; + v /= 36; + XXXXXX[3] = letters[v % 36]; + v /= 36; + XXXXXX[4] = letters[v % 36]; + v /= 36; + XXXXXX[5] = letters[v % 36]; + + int flags = O_WRONLY | O_CREAT | O_EXCL | O_BINARY; + int fd = + _wopen((tmpl_w + wstr_from_utf8(XXXXXX)).c_str(), flags, _S_IREAD | _S_IWRITE); + if (fd != -1) { + errno = save_errno; + return fd; + } else if (errno != EEXIST) + return -1; + } + + // We got out of the loop because we ran out of combinations to try. + errno = EEXIST; + return -1; + } + CATCH_AND_RETURN(-1) +} +#endif // _WIN32 + +namespace rnp { +namespace path { +inline char +separator() +{ +#ifdef _WIN32 + return '\\'; +#else + return '/'; +#endif +} + +bool +exists(const std::string &path, bool is_dir) +{ + return is_dir ? rnp_dir_exists(path.c_str()) : rnp_file_exists(path.c_str()); +} + +bool +empty(const std::string &path) +{ + auto dir = rnp_opendir(path.c_str()); + if (!dir) { + return true; + } + bool empty = rnp_readdir_name(dir).empty(); + rnp_closedir(dir); + return empty; +} + +std::string +HOME(const std::string &sdir) +{ + const char *home = getenv("HOME"); + if (!home) { + return ""; + } + return sdir.empty() ? home : append(home, sdir); +} + +static bool +has_forward_slash(const std::string &path) +{ + return std::find(path.begin(), path.end(), '/') != path.end(); +} + +std::string +append(const std::string &path, const std::string &name) +{ + bool no_sep = path.empty() || name.empty() || (rnp::is_slash(path.back())) || + (rnp::is_slash(name.front())); + if (no_sep) { + return path + name; + } + /* Use forward slash if there is at least one in the path/name. */ + char sep = has_forward_slash(path) || has_forward_slash(name) ? '/' : separator(); + return path + sep + name; +} + +} // namespace path +} // namespace rnp diff --git a/src/common/file-utils.h b/src/common/file-utils.h new file mode 100644 index 0000000..1993d17 --- /dev/null +++ b/src/common/file-utils.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2019-2020, [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RNP_FILE_UTILS_H_ +#define RNP_FILE_UTILS_H_ + +#include +#include +#include +#include + +bool rnp_file_exists(const char *path); +bool rnp_dir_exists(const char *path); +int64_t rnp_filemtime(const char *path); +int rnp_open(const char *filename, int oflag, int pmode); +FILE * rnp_fopen(const char *filename, const char *mode); +FILE * rnp_fdopen(int fildes, const char *mode); +int rnp_access(const char *path, int mode); +int rnp_stat(const char *filename, struct stat *statbuf); +int rnp_rename(const char *oldpath, const char *newpath); +int rnp_unlink(const char *path); + +#ifdef _WIN32 +#define rnp_closedir _wclosedir +int rnp_mkdir(const char *path); +_WDIR * rnp_opendir(const char *path); +std::string rnp_readdir_name(_WDIR *dir); +#else +#define rnp_closedir closedir +DIR * rnp_opendir(const char *path); +std::string rnp_readdir_name(DIR *dir); +#endif +#ifdef _WIN32 +#define RNP_MKDIR(pathname, mode) rnp_mkdir(pathname) +#else +#define RNP_MKDIR(pathname, mode) mkdir(pathname, mode) +#endif + +#ifdef _MSC_VER +#define R_OK 4 /* Test for read permission. */ +#define W_OK 2 /* Test for write permission. */ +#define F_OK 0 /* Test for existence. */ +#endif + +/** @private + * generate a temporary file name based on TMPL. TMPL must match the + * rules for mk[s]temp (i.e. end in "XXXXXX"). The name constructed + * does not exist at the time of the call to mkstemp. TMPL is + * overwritten with the result.get the list item at specified index + * + * @param tmpl filename template + * @return file descriptor of newly created and opened file, or -1 on error + **/ +int rnp_mkstemp(char *tmpl); + +namespace rnp { +namespace path { +inline char separator(); +bool exists(const std::string &path, bool is_dir = false); +bool empty(const std::string &path); +std::string HOME(const std::string &sdir = ""); +std::string append(const std::string &path, const std::string &name); +} // namespace path +} // namespace rnp + +#endif diff --git a/src/common/getoptwin.h b/src/common/getoptwin.h new file mode 100644 index 0000000..84a9583 --- /dev/null +++ b/src/common/getoptwin.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020 [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _GETOPTWIN_H +#define _GETOPTWIN_H 1 + +#include + +#define _BEGIN_EXTERN_C extern "C" { +#define _END_EXTERN_C } + +#endif /* getoptwin.h */ \ No newline at end of file diff --git a/src/common/str-utils.cpp b/src/common/str-utils.cpp new file mode 100644 index 0000000..245e31e --- /dev/null +++ b/src/common/str-utils.cpp @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2017 [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** String utilities + * @file + */ + +#include +#include +#include +#include +#include "str-utils.h" +#ifdef _WIN32 +#include +#include +#endif + +using std::size_t; +using std::strlen; + +namespace rnp { +char * +strip_eol(char *s) +{ + size_t len = strlen(s); + + while ((len > 0) && ((s[len - 1] == '\n') || (s[len - 1] == '\r'))) { + s[--len] = '\0'; + } + + return s; +} + +bool +strip_eol(std::string &s) +{ + size_t len = s.size(); + while (len && ((s[len - 1] == '\n') || (s[len - 1] == '\r'))) { + len--; + } + if (len == s.size()) { + return false; + } + s.resize(len); + return true; +} + +bool +is_blank_line(const char *line, size_t len) +{ + for (size_t i = 0; i < len && line[i]; i++) { + if (line[i] != ' ' && line[i] != '\t' && line[i] != '\r') { + return false; + } + } + return true; +} + +bool +str_case_eq(const char *s1, const char *s2) +{ + while (*s1 && *s2) { + if (std::tolower(*s1) != std::tolower(*s2)) { + return false; + } + s1++; + s2++; + } + return !*s1 && !*s2; +} + +bool +str_case_eq(const std::string &s1, const std::string &s2) +{ + if (s1.size() != s2.size()) { + return false; + } + return str_case_eq(s1.c_str(), s2.c_str()); +} + +static size_t +hex_prefix_len(const std::string &str) +{ + if ((str.length() >= 2) && (str[0] == '0') && ((str[1] == 'x') || (str[1] == 'X'))) { + return 2; + } + return 0; +} + +bool +is_hex(const std::string &s) +{ + for (size_t i = hex_prefix_len(s); i < s.length(); i++) { + auto &ch = s[i]; + if ((ch >= '0') && (ch <= '9')) { + continue; + } + if ((ch >= 'a') && (ch <= 'f')) { + continue; + } + if ((ch >= 'A') && (ch <= 'F')) { + continue; + } + if ((ch == ' ') || (ch == '\t')) { + continue; + } + return false; + } + return true; +} + +std::string +strip_hex(const std::string &s) +{ + std::string res = ""; + for (size_t idx = hex_prefix_len(s); idx < s.length(); idx++) { + auto ch = s[idx]; + if ((ch == ' ') || (ch == '\t')) { + continue; + } + res.push_back(ch); + } + return res; +} + +char * +lowercase(char *s) +{ + if (!s) { + return s; + } + for (char *ptr = s; *ptr; ++ptr) { + *ptr = tolower(*ptr); + } + return s; +} + +bool +str_to_int(const std::string &s, int &val) +{ + for (const char &ch : s) { + if ((ch < '0') || (ch > '9')) { + return false; + } + } + try { + val = std::stoi(s); + } catch (std::out_of_range const &ex) { + return false; + } + return true; +} + +bool +is_slash(char c) +{ + return (c == '/') || (c == '\\'); +} + +} // namespace rnp + +#ifdef _WIN32 +std::wstring +wstr_from_utf8(const char *s) +{ + std::wstring_convert> utf8conv; + return utf8conv.from_bytes(s); +} + +std::wstring +wstr_from_utf8(const char *first, const char *last) +{ + std::wstring_convert> utf8conv; + return utf8conv.from_bytes(first, last); +} + +std::wstring +wstr_from_utf8(const std::string &s) +{ + return wstr_from_utf8(s.c_str()); +} + +std::string +wstr_to_utf8(const wchar_t *ws) +{ + std::wstring_convert> utf8conv; + return utf8conv.to_bytes(ws); +} + +std::string +wstr_to_utf8(const std::wstring &ws) +{ + return wstr_to_utf8(ws.c_str()); +} +#endif diff --git a/src/common/str-utils.h b/src/common/str-utils.h new file mode 100644 index 0000000..9a4eb73 --- /dev/null +++ b/src/common/str-utils.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2019-2020 [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RNP_STR_UTILS_H_ +#define RNP_STR_UTILS_H_ + +#include + +namespace rnp { +char *strip_eol(char *s); +/** + * @brief Strip EOL characters from the string's end. + * + * @param s string to check + * @return true if EOL was found and stripped, or false otherwise. + */ +bool strip_eol(std::string &s); +bool is_blank_line(const char *line, size_t len); +bool str_case_eq(const char *s1, const char *s2); +bool str_case_eq(const std::string &s1, const std::string &s2); + +bool is_hex(const std::string &s); +std::string strip_hex(const std::string &s); + +/** + * @brief Convert string to lowercase and return it. + */ +char *lowercase(char *s); +bool str_to_int(const std::string &s, int &val); +bool is_slash(char c); +} // namespace rnp +#ifdef _WIN32 +#include +std::wstring wstr_from_utf8(const char *s); +std::wstring wstr_from_utf8(const char *first, const char *last); +std::wstring wstr_from_utf8(const std::string &s); +std::string wstr_to_utf8(const wchar_t *ws); +std::string wstr_to_utf8(const std::wstring &ws); +#endif // _WIN32 +#endif diff --git a/src/common/time-utils.cpp b/src/common/time-utils.cpp new file mode 100644 index 0000000..83d934a --- /dev/null +++ b/src/common/time-utils.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2021 [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** Time utilities + * @file + */ + +#include +#include "time-utils.h" + +static inline time_t +adjust_time32(time_t t) +{ + return (sizeof(t) == 4 && t < 0) ? INT32_MAX : t; +} + +bool +rnp_y2k38_warning(time_t t) +{ + return (sizeof(t) == 4 && (t < 0 || t == INT32_MAX)); +} + +time_t +rnp_mktime(struct tm *tm) +{ + return adjust_time32(mktime(tm)); +} + +void +rnp_gmtime(time_t t, struct tm &tm) +{ + time_t adjusted = adjust_time32(t); +#ifndef _WIN32 + gmtime_r(&adjusted, &tm); +#else + (void) gmtime_s(&tm, &adjusted); +#endif +} + +void +rnp_localtime(time_t t, struct tm &tm) +{ + time_t adjusted = adjust_time32(t); +#ifndef _WIN32 + localtime_r(&adjusted, &tm); +#else + (void) localtime_s(&tm, &adjusted); +#endif +} + +std::string +rnp_ctime(time_t t) +{ + char time_buf[26]; + time_t adjusted = adjust_time32(t); +#ifndef _WIN32 + (void) ctime_r(&adjusted, time_buf); +#else + (void) ctime_s(time_buf, sizeof(time_buf), &adjusted); +#endif + return std::string(time_buf); +} + +time_t +rnp_timeadd(time_t t1, time_t t2) +{ + if (sizeof(time_t) == 4) { + if (t1 < 0 || t2 < 0) { + return INT32_MAX; + } + return adjust_time32(t1 + t2); + } + return t1 + t2; +} diff --git a/src/common/time-utils.h b/src/common/time-utils.h new file mode 100644 index 0000000..525309e --- /dev/null +++ b/src/common/time-utils.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RNP_TIME_UTILS_H_ +#define RNP_TIME_UTILS_H_ + +#include +#include +time_t rnp_mktime(struct tm *tm); +void rnp_gmtime(time_t t, struct tm &tm); +void rnp_localtime(time_t t, struct tm &tm); +bool rnp_y2k38_warning(time_t t); +std::string rnp_ctime(time_t t); +time_t rnp_timeadd(time_t t1, time_t t2); +#endif diff --git a/src/common/uniwin.h b/src/common/uniwin.h new file mode 100644 index 0000000..095c325 --- /dev/null +++ b/src/common/uniwin.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020 [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#if !defined(_UNISTD_H) && defined(_MSC_VER) +#define _UNISTD_H 1 + +/* Taken partially from + * https://stackoverflow.com/a/826027/1202830 + */ + +#include +#include "getoptwin.h" +#include /* for _getcwd() and _chdir() */ + +#ifdef _WIN64 +#define ssize_t __int64 +#else +#define ssize_t long +#endif + +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 + +#define NOMINMAX 1 /* to retain std::min and std::max */ +#include +#include /* for S_ISREG and S_ISDIR */ + +#define strncasecmp strnicmp +#define strcasecmp stricmp + +#ifndef MAXPATHLEN +#define MAXPATHLEN _MAX_PATH +#endif + +typedef unsigned short mode_t; + +#endif \ No newline at end of file -- cgit v1.2.3