#include <ctype.h>
#include <cstring>
#include <sstream>
+#include <algorithm>
+#include <string.h> // strerror_r() and strerror_s()
+#include <errno.h>
#include "strutils.hxx"
#include <simgear/debug/logstream.hxx>
+#include <simgear/package/md5.h>
+#include <simgear/compiler.h> // SG_WINDOWS
+#include <simgear/structure/exception.hxx>
using std::string;
using std::vector;
size_t len = get_length (p);
if (len == 1) return *p;
value_type res = static_cast<unsigned char> ( *p & (0xff >> (len + 1))) << ((len - 1) * 6 );
- for (--len; len; --len)
- res |= (static_cast<unsigned char> (*(++p)) - 0x80) << ((len - 1) * 6);
+ for (--len; len; --len) {
+ value_type next_byte = static_cast<unsigned char> (*(++p)) - 0x80;
+ if (next_byte & 0xC0) return 0x00ffffff; // invalid UTF-8
+ res |= next_byte << ((len - 1) * 6);
+ }
return res;
}
string s_latin1;
for (string::iterator p = s_utf8.begin(); p != s_utf8.end(); ++p) {
value_type value = get_value<string::iterator&>(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<char>(value);
}
#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<const unsigned char*>(data), num);
+}
+//------------------------------------------------------------------------------
+std::string md5(const std::string& str)
+{
+ return md5(reinterpret_cast<const unsigned char*>(str.c_str()), str.size());
+}
+
+//------------------------------------------------------------------------------
static const std::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
}
}
+//------------------------------------------------------------------------------
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<count;++i) {
- unsigned char c = bytes[i];
- hex.push_back(hexChar[c >> 4]);
- hex.push_back(hexChar[c & 0x0f]);
- }
-
- return hex;
+ return encodeHex(
+ reinterpret_cast<const unsigned char*>(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<length;++i) {
unsigned char c = *rawBytes++;
- hex.push_back(hexChar[c >> 4]);
- hex.push_back(hexChar[c & 0x0f]);
+ hex[i * 2] = hexChar[c >> 4];
+ hex[i * 2 + 1] = hexChar[c & 0x0f];
}
return hex;
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