#include #include #include #include #include #include #include #ifdef _WIN32 #include #include #include #else #include #endif std::string QUtil::int_to_string(int num, int fullpad) { // This routine will need to be recompiled if an int can be longer than // 49 digits. char t[50]; // -2 or -1 to leave space for the possible negative sign and for NUL... if (abs(fullpad) > (int)sizeof(t) - ((num < 0)?2:1)) { throw QEXC::Internal("Util::int_to_string has been called with " "a padding value greater than its internal " "limit"); } if (fullpad) { sprintf(t, "%0*d", fullpad, num); } else { sprintf(t, "%d", num); } return std::string(t); } std::string QUtil::double_to_string(double num, int decimal_places) { // This routine will need to be recompiled if a double can be longer than // 99 digits. char t[100]; std::string lhs = int_to_string((int)num); // lhs.length() gives us the length of the part on the right hand // side of the dot + 1 for the dot + decimal_places: total size of // the required string. -1 on the sizeof side to allow for NUL at // the end. // // If decimal_places <= 0, it is as if no precision was provided // so trust the buffer is big enough. The following test will // always pass in those cases. if (decimal_places + 1 + (int)lhs.length() > (int)sizeof(t) - 1) { throw QEXC::Internal("Util::double_to_string has been called with " "a number and a decimal places specification " "that would break an internal limit"); } if (decimal_places) { sprintf(t, "%.*f", decimal_places, num); } else { sprintf(t, "%f", num); } return std::string(t); } int QUtil::os_wrapper(std::string const& description, int status) throw (QEXC::System) { if (status == -1) { throw QEXC::System(description, errno); } return status; } FILE* QUtil::fopen_wrapper(std::string const& description, FILE* f) throw (QEXC::System) { if (f == 0) { throw QEXC::System(description, errno); } return f; } char* QUtil::copy_string(std::string const& str) { char* result = new char[str.length() + 1]; // Use memcpy in case string contains nulls result[str.length()] = '\0'; memcpy(result, str.c_str(), str.length()); return result; } void QUtil::binary_stdout() { #ifdef _WIN32 _setmode(_fileno(stdout), _O_BINARY); #endif } void QUtil::binary_stdin() { #ifdef _WIN32 _setmode(_fileno(stdin), _O_BINARY); #endif } char* QUtil::getWhoami(char* argv0) { #ifdef _WIN32 char pathsep = '\\'; #else char pathsep = '/'; #endif char* whoami = 0; if ((whoami = strrchr(argv0, pathsep)) == NULL) { whoami = argv0; } else { ++whoami; } #ifdef _WIN32 if ((strlen(whoami) > 4) && (strcmp(whoami + strlen(whoami) - 4, ".exe") == 0)) { whoami[strlen(whoami) - 4] = '\0'; } #endif return whoami; } bool QUtil::get_env(std::string const& var, std::string* value) { // This was basically ripped out of wxWindows. #ifdef _WIN32 // first get the size of the buffer DWORD len = ::GetEnvironmentVariable(var.c_str(), NULL, 0); if (len == 0) { // this means that there is no such variable return false; } if (value) { char* t = new char[len + 1]; ::GetEnvironmentVariable(var.c_str(), t, len); *value = t; delete [] t; } return true; #else char* p = getenv(var.c_str()); if (p == 0) { return false; } if (value) { *value = p; } return true; #endif } time_t QUtil::get_current_time() { #ifdef _WIN32 // The procedure to get local time at this resolution comes from // the Microsoft documentation. It says to convert a SYSTEMTIME // to a FILETIME, and to copy the FILETIME to a ULARGE_INTEGER. // The resulting number is the number of 100-nanosecond intervals // between January 1, 1601 and now. POSIX threads wants a time // based on January 1, 1970, so we adjust by subtracting the // number of seconds in that time period from the result we get // here. SYSTEMTIME sysnow; GetSystemTime(&sysnow); FILETIME filenow; SystemTimeToFileTime(&sysnow, &filenow); ULARGE_INTEGER uinow; uinow.LowPart = filenow.dwLowDateTime; uinow.HighPart = filenow.dwHighDateTime; ULONGLONG now = uinow.QuadPart; return ((now / 10000000LL) - 11644473600LL); #else return time(0); #endif } std::string QUtil::toUTF8(unsigned long uval) { std::string result; // A UTF-8 encoding of a Unicode value is a single byte for // Unicode values <= 127. For larger values, the first byte of // the UTF-8 encoding has '1' as each of its n highest bits and // '0' for its (n+1)th highest bit where n is the total number of // bytes required. Subsequent bytes start with '10' and have the // remaining 6 bits free for encoding. For example, an 11-bit // Unicode value can be stored in two bytes where the first is // 110zzzzz, the second is 10zzzzzz, and the z's represent the // remaining bits. if (uval > 0x7fffffff) { throw QEXC::General("bounds error in QUtil::toUTF8"); } else if (uval < 128) { result += (char)(uval); } else { unsigned char bytes[7]; bytes[6] = '\0'; unsigned char* cur_byte = &bytes[5]; // maximum value that will fit in the current number of bytes unsigned char maxval = 0x3f; // six bits while (uval > maxval) { // Assign low six bits plus 10000000 to lowest unused // byte position, then shift *cur_byte = (unsigned char) (0x80 + (uval & 0x3f)); uval >>= 6; // Maximum that will fit in high byte now shrinks by one bit maxval >>= 1; // Slide to the left one byte --cur_byte; if (cur_byte < bytes) { throw QEXC::Internal("QUtil::toUTF8: overflow error"); } } // If maxval is k bits long, the high (7 - k) bits of the // resulting byte must be high. *cur_byte = (unsigned char)((0xff - (1 + (maxval << 1))) + uval); result += (char*)cur_byte; } return result; }