X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fmisc%2Fstrutils.cxx;h=7a2ffa30dff43a7e6251b603e4a3e7824bc9862d;hb=0d5781aee74071419abccea73fc2fa3f3f5b121b;hp=52a8d619c72e50f794fd7a15721e327eeb08c855;hpb=237752ff621266277b9bdbab7f77861c13ea7787;p=simgear.git diff --git a/simgear/misc/strutils.cxx b/simgear/misc/strutils.cxx index 52a8d619..7a2ffa30 100644 --- a/simgear/misc/strutils.cxx +++ b/simgear/misc/strutils.cxx @@ -23,10 +23,16 @@ #include #include #include +#include +#include // strerror_r() and strerror_s() +#include #include "strutils.hxx" #include +#include +#include // SG_WINDOWS +#include using std::string; using std::vector; @@ -35,6 +41,43 @@ using std::stringstream; namespace simgear { namespace strutils { + /* + * utf8ToLatin1() convert utf8 to latin, useful for accent character (i.e éâàîè...) + */ + template size_t get_length (Iterator p) { + unsigned char c = static_cast (*p); + if (c < 0x80) return 1; + else if (!(c & 0x20)) return 2; + else if (!(c & 0x10)) return 3; + else if (!(c & 0x08)) return 4; + else if (!(c & 0x04)) return 5; + else return 6; + } + + typedef unsigned int value_type; + template value_type get_value (Iterator p) { + size_t len = get_length (p); + if (len == 1) return *p; + value_type res = static_cast ( *p & (0xff >> (len + 1))) << ((len - 1) * 6 ); + for (--len; len; --len) { + value_type next_byte = static_cast (*(++p)) - 0x80; + if (next_byte & 0xC0) return 0x00ffffff; // invalid UTF-8 + res |= next_byte << ((len - 1) * 6); + } + return res; + } + + string utf8ToLatin1( string& s_utf8 ) { + string s_latin1; + for (string::iterator p = s_utf8.begin(); p != s_utf8.end(); ++p) { + value_type value = get_value(p); + if (value > 0x10ffff) return s_utf8; // invalid UTF-8: guess that the input was already Latin-1 + if (value > 0xff) SG_LOG(SG_IO, SG_WARN, "utf8ToLatin1: wrong char value: " << value); + s_latin1 += static_cast(value); + } + return s_latin1; + } + /** * */ @@ -364,8 +407,32 @@ std::string convertWindowsLocal8BitToUtf8(const std::string& a) #endif } +//------------------------------------------------------------------------------ +std::string md5(const unsigned char* data, size_t num) +{ + SG_MD5_CTX md5_ctx; + SG_MD5Init(&md5_ctx); + SG_MD5Update(&md5_ctx, data, num); + unsigned char digest[MD5_DIGEST_LENGTH]; + SG_MD5Final(digest, &md5_ctx); + + return encodeHex(digest, MD5_DIGEST_LENGTH); +} + +//------------------------------------------------------------------------------ +std::string md5(const char* data, size_t num) +{ + return md5(reinterpret_cast(data), num); +} + +//------------------------------------------------------------------------------ +std::string md5(const std::string& str) +{ + return md5(reinterpret_cast(str.c_str()), str.size()); +} +//------------------------------------------------------------------------------ static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" @@ -445,28 +512,24 @@ void decodeBase64(const std::string& encoded_string, std::vector& } } +//------------------------------------------------------------------------------ const char hexChar[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; std::string encodeHex(const std::string& bytes) { - std::string hex; - size_t count = bytes.size(); - for (unsigned int i=0; i> 4]); - hex.push_back(hexChar[c & 0x0f]); - } - - return hex; + return encodeHex( + reinterpret_cast(bytes.c_str()), + bytes.size() + ); } std::string encodeHex(const unsigned char* rawBytes, unsigned int length) { - std::string hex; + std::string hex(length * 2, '\0'); for (unsigned int i=0; i> 4]); - hex.push_back(hexChar[c & 0x0f]); + hex[i * 2] = hexChar[c >> 4]; + hex[i * 2 + 1] = hexChar[c & 0x0f]; } return hex; @@ -538,6 +601,49 @@ string sanitizePrintfFormat(const string& input) return input; } +std::string error_string(int errnum) +{ + char buf[512]; // somewhat arbitrary... + // This could be simplified with C11 (annex K, optional...), which offers: + // + // errno_t strerror_s( char *buf, rsize_t bufsz, errno_t errnum ); + // size_t strerrorlen_s( errno_t errnum ); + +#if defined(SG_WINDOWS) + errno_t retcode; + // Always makes the string in 'buf' null-terminated + retcode = strerror_s(buf, sizeof(buf), errnum); +#elif defined(_GNU_SOURCE) + return std::string(strerror_r(errnum, buf, sizeof(buf))); +#elif _POSIX_C_SOURCE >= 200112L + int retcode; + // POSIX.1-2001 and POSIX.1-2008 + retcode = strerror_r(errnum, buf, sizeof(buf)); +#else +#error "Could not find a thread-safe alternative to strerror()." +#endif + +#if !defined(_GNU_SOURCE) + if (retcode) { + std::string msg = "unable to get error message for a given error number"; + // C++11 would make this shorter with std::to_string() + std::ostringstream ostr; + ostr << errnum; + +#if !defined(SG_WINDOWS) + if (retcode == ERANGE) { // more specific error message in this case + msg = std::string("buffer too small to hold the error message for " + "the specified error number"); + } +#endif + + throw sg_error(msg, ostr.str()); + } + + return std::string(buf); +#endif // !defined(_GNU_SOURCE) +} + } // end namespace strutils } // end namespace simgear