/* * Copyright (C) 2015 by Multi-Tech Systems * * This file is part of libmts. * * libmts is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * libmts is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with libmts. If not, see . * */ #include //#include #include #include #include #include using namespace MTS; //strftime //%a Abbreviated weekday name * Thu //%A Full weekday name * Thursday //%b Abbreviated month name * Aug //%B Full month name * August //%c Date and time representation * Thu Aug 23 14:55:02 2001 //%d Day of the month (01-31) 23 //%H Hour in 24h format (00-23) 14 //%I Hour in 12h format (01-12) 02 //%j Day of the year (001-366) 235 //%m Month as a decimal number (01-12) 08 //%M Minute (00-59) 55 //%p AM or PM designation PM //%S Second (00-61) 02 //%U Week number with the first Sunday as the first day of week one (00-53) 33 //%w Weekday as a decimal number with Sunday as 0 (0-6) 4 //%W Week number with the first Monday as the first day of week one (00-53) 34 //%x Date representation * 08/23/01 //%X Time representation * 14:55:02 //%y Year, last two digits (00-99) 01 //%Y Year 2001 //%Z Timezone name or abbreviation CDT //%% A % sign % //Example ///* strftime example */ //#include //#include // //int main () //{ // time_t rawtime; // struct tm * timeinfo; // char buffer [80]; // // time ( &rawtime ); // timeinfo = localtime ( &rawtime ); // // strftime (buffer,80,"Now it's %I:%M%p.",timeinfo); // puts (buffer); // // return 0; //} std::string Text::time(const uint64_t& iTimeMicros, const TIMEFORMAT& eTime) { int64_t now = iTimeMicros / 1000; int64_t millis = now % 1000; int64_t secs = (now / 1000) % 60; int64_t mins = (now / 60000) % 60; int64_t hours = (now / 3600000) % 24; std::stringstream sBuffer; switch (eTime) { case HHcMMcSScmmm: sBuffer << hours << ":" << mins << ":" << secs << ":" << millis; return sBuffer.str(); break; case HHcMMcSS: sBuffer << (hours < 10 ? "0" : "") << hours << ":" << (mins < 10 ? "0" : "") << mins << ":" << (secs < 10 ? "0" : "") << secs; return sBuffer.str(); break; } return std::string("UNKNOWN-TIME-FORMAT"); } std::string Text::date(const tm& stTime, const DATEFORMAT& eDate) { char buffer[80]; switch (eDate) { case MMsDDsYY: strftime(buffer, 80, "%x", &stTime); return std::string(buffer); break; case MMsDDsYY_HHcMMcSS: strftime(buffer, 80, "%m/%d/%Y %H:%M:%S", &stTime); return std::string(buffer); break; case RFC_1123: std::stringstream sBuffer; //Thu, 01 Jan 1970 00:00:01 GMT //Week switch (stTime.tm_wday) { case 0: sBuffer << "Sun, "; break; case 1: sBuffer << "Mon, "; break; case 2: sBuffer << "Tue, "; break; case 3: sBuffer << "Wed, "; break; case 4: sBuffer << "Thu, "; break; case 5: sBuffer << "Fri, "; break; case 6: sBuffer << "Sat, "; break; } //Day of Month sBuffer << (stTime.tm_mday < 10 ? "0" : "") << stTime.tm_mday; //Month switch (stTime.tm_mon) { case 0: sBuffer << " Jan "; break; case 1: sBuffer << " Feb "; break; case 2: sBuffer << " Mar "; break; case 3: sBuffer << " Apr "; break; case 4: sBuffer << " May "; break; case 5: sBuffer << " Jun "; break; case 6: sBuffer << " Jul "; break; case 7: sBuffer << " Aug "; break; case 8: sBuffer << " Sep "; break; case 9: sBuffer << " Oct "; break; case 10: sBuffer << " Nov "; break; case 11: sBuffer << " Dec "; break; } sBuffer << (stTime.tm_year + 1900); sBuffer << (stTime.tm_hour < 10 ? " 0" : " ") << stTime.tm_hour << ":" << (stTime.tm_min < 10 ? "0" : "") << stTime.tm_min << ":" << (stTime.tm_sec < 10 ? "0" : "") << stTime.tm_sec; sBuffer << " GMT"; return sBuffer.str(); break; } return std::string("UNKNOWN-DATE-FORMAT"); } bool Text::datetimeIsBefore(const std::string& time1, const std::string& time2) { struct tm tm1; struct tm tm2; strptime(time1.c_str(), "%x %T", &tm1); strptime(time2.c_str(), "%x %T", &tm2); return difftime(mktime(&tm2), mktime(&tm1)) > 0; } std::vector Text::split(const std::string& str, char delimiter, int limit) { return split(str, std::string(1, delimiter), limit); } std::vector Text::split(const std::string& str, const std::string& delimiter, int limit) { std::vector result; if(str.size() == 0) { return result; } if (limit <= 0) { limit = std::numeric_limits::max(); } size_t start = 0; size_t end = str.find(delimiter, start); for (int i = 1; (i < limit) && (end != std::string::npos); ++i) { result.push_back(str.substr(start, end - start)); start = end + delimiter.length(); end = str.find(delimiter, start); } result.push_back(str.substr(start)); return result; } std::string Text::join(std::vector list, char delimiter) { std::stringstream ss; for (uint32_t i = 0; i < list.size(); i++) { ss << list[i]; if (i < list.size() - 1) ss << delimiter; } return ss.str(); } std::string Text::replace(const std::string& original, const std::string& from, const std::string& to) { size_t start_pos = 0; std::string str(original); while ((start_pos = str.find(from, start_pos)) != std::string::npos) { str.replace(start_pos, from.length(), to); start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx' } return str; } uint32_t Text::count(const std::string& str, const std::string& element) { uint32_t count = 0; size_t start_pos = 0; while ((start_pos = str.find(element, start_pos)) != std::string::npos) { start_pos++; count++; } return count; } uint32_t Text::count(const std::string& str, const uint8_t& element) { uint32_t count = 0; size_t start_pos = 0; while ((start_pos = str.find(element, start_pos)) != std::string::npos) { start_pos++; count++; } return count; } bool Text::endsWith(const std::string& str, const std::string& key) { if (key.size() > str.size()) return false; return std::equal(str.begin() + str.size() - key.size(), str.end(), key.begin()); } std::string Text::getLine(const std::string& source, const size_t& start, size_t& cursor) { char delimiters[2]; delimiters[0] = '\n'; delimiters[1] = '\r'; if(start > source.size()) { cursor = std::string::npos; return ""; } size_t end = source.find_first_of(delimiters, start, 2); std::string line(source.substr(start, end - start)); //printDebug("[TEXT] Start [%d] Cursor[%d] Size[%d] Line: %s", start, end, source.size(), line.c_str()); if (end < source.size()) { if (end < source.size() - 1) if ((source[end] == '\n' && source[end + 1] == '\r') || (source[end] == '\r' && source[end + 1] == '\n')) { //Advance an additional character in scenarios where lines end in \r\n or \n\r end++; } end++; } cursor = end; return line; } std::string Text::trim(const std::string& str) { size_t length = str.length(); size_t start = length; for (size_t i = 0; i < length; ++i) { if (!isspace(static_cast(str[i]))) { start = i; break; } } size_t end = std::string::npos; for (size_t i = length - 1; i != std::string::npos; --i) { if (!isspace(static_cast(str[i]))) { end = i + 1; break; } } return str.substr(start, end - start); } std::string Text::trim(const std::string& str, const uint8_t& element) { size_t length = str.length(); size_t start = length; for (size_t i = 0; i < length; ++i) { if (static_cast(str[i]) != element) { start = i; break; } } size_t end = std::string::npos; for (size_t i = length - 1; i != std::string::npos; --i) { if (static_cast(str[i]) != element) { end = i + 1; break; } } return str.substr(start, end - start); } std::string Text::strip(const std::string& str, const std::vector& elements) { std::string result(str); for (uint32_t i = 0; i < elements.size(); i++) { result.erase (std::remove(result.begin(), result.end(), elements[i]), result.end()); } return result; } std::string Text::strip(const std::string& str, const uint8_t& element) { std::string result(str); result.erase (std::remove(result.begin(), result.end(), element), result.end()); return result; } std::string Text::toLowerCase(const std::string& str) { std::string result(str); size_t length = result.length(); for (size_t i = 0; i < length; ++i) { result[i] = static_cast(tolower(static_cast(result[i]))); } return result; } std::string Text::toUpperCase(const std::string& str) { std::string result(str); size_t length = result.length(); for (size_t i = 0; i < length; ++i) { result[i] = static_cast(toupper(static_cast(result[i]))); } return result; } std::string Text::toCapitalized(const std::string& str) { std::string result; result = str; if (str.size() == 0) return result; else if (str.size() == 1) return toUpperCase(result); else return toUpperCase(result.substr(0, 1)) + toLowerCase(result.substr(1)); } std::string Text::toCamelCase(const std::string& str) { std::string result; if (str.size() == 0) { return result; } std::vector parts = MTS::Text::split(str, ' '); if (parts.size() == 0 || parts[0].size() == 0) { return result; } result.append(MTS::Text::toLowerCase(parts[0])); for (uint32_t i = 1; i < parts.size(); i++) { result.append(MTS::Text::toCapitalized(parts[i])); } return result; } std::string Text::toCommandLineEscaped(const std::string& str) { std::string result(str); result = Text::replace(result, "#", "\\#"); result = Text::replace(result, ".", "\\."); result = Text::replace(result, "&", "\\&"); result = Text::replace(result, "?", "\\?"); return result; } std::wstring Text::widen(const std::string& str) { std::wstringstream wss; size_t length = str.length(); for (size_t i = 0; i < length; ++i) { wss << wss.widen(str[i]); } return wss.str(); } std::string Text::narrow(const std::wstring& str) { std::wstringstream wss; std::stringstream ss; size_t length = str.length(); for (size_t i = 0; i < length; ++i) { ss << wss.narrow(str[i], '?'); } return ss.str(); } std::string Text::format(bool value) { std::stringstream ss; ss.setf(ss.boolalpha); ss << value; return ss.str(); } std::string Text::format(double value, std::streamsize percision) { std::stringstream ss; ss.setf(ss.fixed, ss.floatfield); ss.precision(percision); ss << value; std::string str = ss.str(); // strip trailing zeros size_t pos = str.find_last_not_of('0'); if (pos != std::string::npos) { if (str[pos] == '.') { pos += 2; } else { pos += 1; } } return str.substr(0, pos); } std::string Text::format(int8_t value) { return format(static_cast(value)); } std::string Text::format(int16_t value) { return format(static_cast(value)); } std::string Text::format(int32_t value) { return format(static_cast(value)); } std::string Text::format(int64_t value) { std::stringstream ss; ss.setf(ss.dec, ss.basefield); ss << value; return ss.str(); } std::string Text::format(uint8_t value) { return format(static_cast(value)); } std::string Text::format(uint16_t value) { return format(static_cast(value)); } std::string Text::format(uint32_t value) { return format(static_cast(value)); } std::string Text::format(uint64_t value) { std::stringstream ss; ss.setf(ss.dec, ss.basefield); ss << value; return ss.str(); } static std::string toHexString(uint64_t value, bool pad, std::streamsize padSize) { std::stringstream ss; ss.unsetf(ss.showbase); ss.setf(ss.hex, ss.basefield); ss.setf(ss.uppercase); if (pad) { ss.width(padSize); ss.fill('0'); } ss << value; return ss.str(); } std::string Text::formatHex(int8_t value, bool pad) { return formatHex(static_cast(value), pad); } std::string Text::formatHex(int16_t value, bool pad) { return formatHex(static_cast(value), pad); } std::string Text::formatHex(int32_t value, bool pad) { return formatHex(static_cast(value), pad); } std::string Text::formatHex(int64_t value, bool pad) { return formatHex(static_cast(value), pad); } std::string Text::formatHex(uint8_t value, bool pad) { return toHexString(value, pad, 2); } std::string Text::formatHex(uint16_t value, bool pad) { return toHexString(value, pad, 4); } std::string Text::formatHex(uint32_t value, bool pad) { return toHexString(value, pad, 8); } std::string Text::formatHex(uint64_t value, bool pad) { return toHexString(value, pad, 16); } std::string Text::formatHex(const Buffer& value) { char hex[4]; std::string hexstr; for (uint32_t i = 0; i < value.getSize(); i++) { sprintf(hex, "%X", value.at(i)); hexstr.append(hex); } return hexstr; } bool Text::parse(bool& value, const std::string& str) { if (str.empty()) { return false; } std::istringstream ss(str); ss.setf(ss.boolalpha); ss.unsetf(ss.skipws); ss >> value; return ((uint8_t) ss.rdstate() == RDSTATE_SUCCESS_MASK); } bool Text::parse(double& value, const std::string& str) { if (str.empty()) { return false; } std::istringstream ss(str); ss.setf(ss.fixed, ss.basefield); ss.unsetf(ss.skipws); ss >> value; return ((uint8_t) ss.rdstate() == RDSTATE_SUCCESS_MASK); } bool Text::parse(int8_t& value, const std::string& str) { int64_t i64 = 0; if (!parse(i64, str)) { return false; } if (i64 < INT8_MIN || i64 > INT8_MAX) { return false; } value = static_cast(i64); return true; } bool Text::parse(int16_t& value, const std::string& str) { int64_t i64 = 0; if (!parse(i64, str)) { return false; } if (i64 < INT16_MIN || i64 > INT16_MAX) { return false; } value = static_cast(i64); return true; } bool Text::parse(int32_t& value, const std::string& str) { int64_t i64 = 0; if (!parse(i64, str)) { return false; } if (i64 < INT32_MIN || i64 > INT32_MAX) { return false; } value = static_cast(i64); return true; } bool Text::parse(int64_t& value, const std::string& str) { if (str.empty()) { return false; } std::istringstream ss(str); ss.setf(ss.dec, ss.basefield); ss.unsetf(ss.skipws); ss >> value; return ((uint8_t) ss.rdstate() == RDSTATE_SUCCESS_MASK); } bool Text::parse(uint8_t& value, const std::string& str) { uint64_t u64 = 0; if (!parse(u64, str)) { return false; } if (u64 > UINT8_MAX) { return false; } value = static_cast(u64); return true; } bool Text::parse(uint16_t& value, const std::string& str) { uint64_t u64 = 0; if (!parse(u64, str)) { return false; } if (u64 > UINT16_MAX) { return false; } value = static_cast(u64); return true; } bool Text::parse(uint32_t& value, const std::string& str) { uint64_t u64 = 0; if (!parse(u64, str)) { return false; } if (u64 > UINT32_MAX) { return false; } value = static_cast(u64); return true; } bool Text::parse(uint64_t& value, const std::string& str) { if (str.empty()) { return false; } std::istringstream ss(str); ss.setf(ss.dec, ss.basefield); ss.unsetf(ss.skipws); ss >> value; return ((uint8_t) ss.rdstate() == RDSTATE_SUCCESS_MASK); } bool Text::parseHex(uint8_t& value, const std::string& str) { uint64_t u64 = 0; if (!parseHex(u64, str)) { return false; } if (u64 > UINT8_MAX) { return false; } value = static_cast(u64); return true; } bool Text::parseHex(uint16_t& value, const std::string& str) { uint64_t u64 = 0; if (!parseHex(u64, str)) { return false; } if (u64 > UINT16_MAX) { return false; } value = static_cast(u64); return true; } bool Text::parseHex(uint32_t& value, const std::string& str) { uint64_t u64 = 0; if (!parseHex(u64, str)) { return false; } if (u64 > UINT32_MAX) { return false; } value = static_cast(u64); return true; } bool Text::parseHex(uint64_t& value, const std::string& str) { if (str.empty()) { return false; } std::istringstream ss(str); ss >> std::hex >> value; return ((uint8_t) ss.rdstate() == RDSTATE_SUCCESS_MASK); }