diff options
Diffstat (limited to 'src/MTS_Text.cpp')
-rw-r--r-- | src/MTS_Text.cpp | 701 |
1 files changed, 701 insertions, 0 deletions
diff --git a/src/MTS_Text.cpp b/src/MTS_Text.cpp new file mode 100644 index 0000000..d823bfe --- /dev/null +++ b/src/MTS_Text.cpp @@ -0,0 +1,701 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + * + */ + +#include <mts/MTS_Text.h> +//#include <mts/MTS_Logger.h> +#include <algorithm> +#include <sstream> +#include <iostream> +#include <limits> + +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 <stdio.h> +//#include <time.h> +// +//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<std::string> Text::split(const std::string& str, char delimiter, int limit) { + return split(str, std::string(1, delimiter), limit); +} + +std::vector<std::string> Text::split(const std::string& str, const std::string& delimiter, int limit) { + std::vector<std::string> result; + if(str.size() == 0) { + return result; + } + if (limit <= 0) { + limit = std::numeric_limits<int>::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<std::string> 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<unsigned char>(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<unsigned char>(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<unsigned char>(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<unsigned char>(str[i]) != element) { + end = i + 1; + break; + } + } + return str.substr(start, end - start); +} + + +std::string Text::strip(const std::string& str, const std::vector<uint8_t>& 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<char>(tolower(static_cast<unsigned char>(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<char>(toupper(static_cast<unsigned char>(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<std::string> 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<int64_t>(value)); +} + +std::string Text::format(int16_t value) { + return format(static_cast<int64_t>(value)); +} + +std::string Text::format(int32_t value) { + return format(static_cast<int64_t>(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<uint64_t>(value)); +} + +std::string Text::format(uint16_t value) { + return format(static_cast<uint64_t>(value)); +} + +std::string Text::format(uint32_t value) { + return format(static_cast<uint64_t>(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<uint8_t>(value), pad); +} + +std::string Text::formatHex(int16_t value, bool pad) { + return formatHex(static_cast<uint16_t>(value), pad); +} + +std::string Text::formatHex(int32_t value, bool pad) { + return formatHex(static_cast<uint32_t>(value), pad); +} + +std::string Text::formatHex(int64_t value, bool pad) { + return formatHex(static_cast<uint64_t>(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<int8_t>(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<int16_t>(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<int32_t>(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<uint8_t>(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<uint16_t>(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<uint32_t>(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<uint8_t>(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<uint16_t>(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<uint32_t>(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); +} + |