audio_trans/lib/inc/drogon/utils/Utilities.h

430 lines
12 KiB
C++

/**
*
* @file Utilities.h
* @author An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
* Use of this source code is governed by a MIT license
* that can be found in the License file.
*
* Drogon
*
*/
#pragma once
#include <drogon/exports.h>
#include <trantor/utils/Date.h>
#include <trantor/utils/Funcs.h>
#include <trantor/utils/Utilities.h>
#include <drogon/utils/string_view.h>
#include <memory>
#include <string>
#include <vector>
#include <set>
#include <limits>
#include <sstream>
#include <algorithm>
#ifdef _WIN32
#include <time.h>
DROGON_EXPORT char *strptime(const char *s, const char *f, struct tm *tm);
DROGON_EXPORT time_t timegm(struct tm *tm);
#endif
namespace drogon
{
namespace internal
{
template <typename T>
struct CanConvertFromStringStream
{
private:
using yes = std::true_type;
using no = std::false_type;
template <typename U>
static auto test(U *p, std::stringstream &&ss)
-> decltype((ss >> *p), yes());
template <typename>
static no test(...);
public:
static constexpr bool value =
std::is_same<decltype(test<T>(nullptr, std::stringstream())),
yes>::value;
};
} // namespace internal
namespace utils
{
/// Determine if the string is an integer
DROGON_EXPORT bool isInteger(const std::string &str);
/// Generate random a string
/**
* @param length The string length
* The returned string consists of uppercase and lowercase letters and numbers
*/
DROGON_EXPORT std::string genRandomString(int length);
/// Convert a binary string to hex format
DROGON_EXPORT std::string binaryStringToHex(const unsigned char *ptr,
size_t length);
/// Get a binary string from hexadecimal format
DROGON_EXPORT std::string hexToBinaryString(const char *ptr, size_t length);
/// Get a binary vector from hexadecimal format
DROGON_EXPORT std::vector<char> hexToBinaryVector(const char *ptr,
size_t length);
/// Split the string into multiple separated strings.
/**
* @param acceptEmptyString if true, empty strings are accepted in the
* result, for example, splitting the ",1,2,,3," by "," produces
* ["","1","2","","3",""]
*/
inline std::vector<std::string> splitString(const std::string &str,
const std::string &separator,
bool acceptEmptyString = false)
{
return trantor::splitString(str, separator, acceptEmptyString);
}
DROGON_EXPORT std::set<std::string> splitStringToSet(
const std::string &str,
const std::string &separator);
/// Get UUID string.
DROGON_EXPORT std::string getUuid();
/// Encode the string to base64 format.
DROGON_EXPORT std::string base64Encode(const unsigned char *bytes_to_encode,
unsigned int in_len,
bool url_safe = false);
/// Decode the base64 format string.
DROGON_EXPORT std::string base64Decode(const std::string &encoded_string);
DROGON_EXPORT std::vector<char> base64DecodeToVector(
const std::string &encoded_string);
/// Check if the string need decoding
DROGON_EXPORT bool needUrlDecoding(const char *begin, const char *end);
/// Decode from or encode to the URL format string
DROGON_EXPORT std::string urlDecode(const char *begin, const char *end);
inline std::string urlDecode(const std::string &szToDecode)
{
auto begin = szToDecode.data();
return urlDecode(begin, begin + szToDecode.length());
}
inline std::string urlDecode(const string_view &szToDecode)
{
auto begin = szToDecode.data();
return urlDecode(begin, begin + szToDecode.length());
}
DROGON_EXPORT std::string urlEncode(const std::string &);
DROGON_EXPORT std::string urlEncodeComponent(const std::string &);
/// Get the MD5 digest of a string.
DROGON_EXPORT std::string getMd5(const char *data, const size_t dataLen);
inline std::string getMd5(const std::string &originalString)
{
return getMd5(originalString.data(), originalString.length());
}
/// Commpress or decompress data using gzip lib.
/**
* @param data the input data
* @param ndata the input data length
*/
DROGON_EXPORT std::string gzipCompress(const char *data, const size_t ndata);
DROGON_EXPORT std::string gzipDecompress(const char *data, const size_t ndata);
/// Commpress or decompress data using brotli lib.
/**
* @param data the input data
* @param ndata the input data length
*/
DROGON_EXPORT std::string brotliCompress(const char *data, const size_t ndata);
DROGON_EXPORT std::string brotliDecompress(const char *data,
const size_t ndata);
/// Get the http full date string
/**
* rfc2616-3.3.1
* Full Date format(RFC 822)
* like this:
* @code
Sun, 06 Nov 1994 08:49:37 GMT
Wed, 12 Sep 2018 09:22:40 GMT
@endcode
*/
DROGON_EXPORT char *getHttpFullDate(
const trantor::Date &date = trantor::Date::now());
/// Get the trantor::Date object according to the http full date string
/**
* Returns trantor::Date(std::numeric_limits<int64_t>::max()) upon failure.
*/
DROGON_EXPORT trantor::Date getHttpDate(const std::string &httpFullDateString);
/// Get a formatted string
DROGON_EXPORT std::string formattedString(const char *format, ...);
/// Recursively create a file system path
/**
* Return 0 or -1 on success or failure.
*/
DROGON_EXPORT int createPath(const std::string &path);
/**
* @details Convert a wide string path with arbitrary directory separators
* to a UTF-8 portable path for use with trantor.
*
* This is a helper, mainly for Windows and multi-platform projects.
*
* @note On Windows, backslash directory separators are converted to slash to
* keep portable paths.
*
* @remarks On other OSes, backslashes are not converted to slash, since they
* are valid characters for directory/file names.
*
* @param strPath Wide string path.
*
* @return std::string UTF-8 path, with slash directory separator.
*/
inline std::string fromWidePath(const std::wstring &strPath)
{
return trantor::utils::fromWidePath(strPath);
}
/**
* @details Convert a UTF-8 path with arbitrary directory separator to a wide
* string path.
*
* This is a helper, mainly for Windows and multi-platform projects.
*
* @note On Windows, slash directory separators are converted to backslash.
* Although it accepts both slash and backslash as directory separator in its
* API, it is better to stick to its standard.
* @remarks On other OSes, slashes are not converted to backslashes, since they
* are not interpreted as directory separators and are valid characters for
* directory/file names.
*
* @param strUtf8Path Ascii path considered as being UTF-8.
*
* @return std::wstring path with, on windows, standard backslash directory
* separator to stick to its standard.
*/
inline std::wstring toWidePath(const std::string &strUtf8Path)
{
return trantor::utils::toWidePath(strUtf8Path);
}
/**
* @brief Convert a generic (UTF-8) path with to an OS native path.
* @details This is a helper, mainly for Windows and multi-platform projects.
*
* On Windows, slash directory separators are converted to backslash, and a
* wide string is returned.
*
* On other OSes, returns an UTF-8 string _without_ altering the directory
* separators.
*
* @param strPath Wide string or UTF-8 path.
*
* @return An OS path, suitable for use with the OS API.
*/
#if defined(_WIN32) && !defined(__MINGW32__)
inline std::wstring toNativePath(const std::string &strPath)
{
return trantor::utils::toNativePath(strPath);
}
inline const std::wstring &toNativePath(const std::wstring &strPath)
{
return trantor::utils::toNativePath(strPath);
}
#else // __WIN32
inline const std::string &toNativePath(const std::string &strPath)
{
return trantor::utils::toNativePath(strPath);
}
inline std::string toNativePath(const std::wstring &strPath)
{
return trantor::utils::toNativePath(strPath);
}
#endif // _WIN32
/**
* @brief Convert a OS native path (wide string on Windows) to a generic UTF-8
* path.
* @details This is a helper, mainly for Windows and multi-platform projects.
*
* On Windows, backslash directory separators are converted to slash, and a
* a UTF-8 string is returned, suitable for libraries that supports UTF-8 paths
* like OpenSSL or drogon.
*
* On other OSes, returns an UTF-8 string without altering the directory
* separators (backslashes are *NOT* replaced with slashes, since they
* are valid characters for directory/file names).
*
* @param strPath Wide string or UTF-8 path.
*
* @return A generic path.
*/
inline const std::string &fromNativePath(const std::string &strPath)
{
return trantor::utils::fromNativePath(strPath);
}
// Convert on all systems
inline std::string fromNativePath(const std::wstring &strPath)
{
return trantor::utils::fromNativePath(strPath);
}
/// Replace all occurances of from to to inplace
/**
* @param from string to replace
* @param to string to replace with
*/
DROGON_EXPORT void replaceAll(std::string &s,
const std::string &from,
const std::string &to);
/**
* @brief Generates cryptographically secure random bytes.
*
* @param ptr the pointer which the random bytes are stored to
* @param size number of bytes to generate
*
* @return true if generation is successfull. False otherwise
*
* @note DO NOT abuse this function. Especially if Drogon is built without
* OpenSSL. Entropy running low is a real issue.
*/
DROGON_EXPORT bool secureRandomBytes(void *ptr, size_t size);
template <typename T>
typename std::enable_if<internal::CanConvertFromStringStream<T>::value, T>::type
fromString(const std::string &p) noexcept(false)
{
T value{};
if (!p.empty())
{
std::stringstream ss(p);
ss >> value;
}
return value;
}
template <typename T>
typename std::enable_if<!(internal::CanConvertFromStringStream<T>::value),
T>::type
fromString(const std::string &) noexcept(false)
{
throw std::runtime_error("Bad type conversion");
}
template <>
inline std::string fromString<std::string>(const std::string &p) noexcept(false)
{
return p;
}
template <>
inline int fromString<int>(const std::string &p) noexcept(false)
{
return std::stoi(p);
}
template <>
inline long fromString<long>(const std::string &p) noexcept(false)
{
return std::stol(p);
}
template <>
inline long long fromString<long long>(const std::string &p) noexcept(false)
{
return std::stoll(p);
}
template <>
inline unsigned long fromString<unsigned long>(const std::string &p) noexcept(
false)
{
return std::stoul(p);
}
template <>
inline unsigned long long fromString<unsigned long long>(
const std::string &p) noexcept(false)
{
return std::stoull(p);
}
template <>
inline float fromString<float>(const std::string &p) noexcept(false)
{
return std::stof(p);
}
template <>
inline double fromString<double>(const std::string &p) noexcept(false)
{
return std::stod(p);
}
template <>
inline long double fromString<long double>(const std::string &p) noexcept(false)
{
return std::stold(p);
}
template <>
inline bool fromString<bool>(const std::string &p) noexcept(false)
{
if (p == "1")
{
return true;
}
if (p == "0")
{
return false;
}
std::string l{p};
std::transform(p.begin(), p.end(), l.begin(), [](unsigned char c) {
return (char)tolower(c);
});
if (l == "true")
{
return true;
}
else if (l == "false")
{
return false;
}
throw std::runtime_error("Can't convert from string '" + p + "' to bool");
}
namespace internal
{
DROGON_EXPORT extern const size_t fixedRandomNumber;
struct SafeStringHash
{
size_t operator()(const std::string &str) const
{
const size_t A = 6665339;
const size_t B = 2534641;
size_t h = fixedRandomNumber;
for (char ch : str)
h = (h * A) ^ (ch * B);
return h;
}
};
} // namespace internal
} // namespace utils
} // namespace drogon