/*
* 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);
}
std::string Text::getFileExtension(const std::string& filename) {
size_t pos = filename.rfind('.', filename.length());
if (pos != std::string::npos) {
return (filename.substr(pos + 1));
}
return ("");
}