From d3e496e29030a0ebe980dcd0326a1c3262d2db1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20P=C3=B6sel?= Date: Tue, 20 Oct 2015 09:37:23 +0000 Subject: Add std_string_utils into /utils directory to easily share between more plugins git-svn-id: http://svn.miranda-ng.org/main/trunk@15574 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- utils/std_string_utils.cpp | 510 +++++++++++++++++++++++++++++++++++++++++++++ utils/std_string_utils.h | 92 ++++++++ 2 files changed, 602 insertions(+) create mode 100644 utils/std_string_utils.cpp create mode 100644 utils/std_string_utils.h (limited to 'utils') diff --git a/utils/std_string_utils.cpp b/utils/std_string_utils.cpp new file mode 100644 index 0000000000..71068013fb --- /dev/null +++ b/utils/std_string_utils.cpp @@ -0,0 +1,510 @@ +/* + +Copyright © 2009-11 Michal Zelinka, 2011-15 Robert Pösel + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +*/ + +#include "std_string_utils.h" + +std::string utils::url::encode(const std::string &s) +{ + return (char*)ptrA(mir_urlEncode(s.c_str())); +} + +std::string utils::url::decode(std::string data) +{ + // TODO: Better and universal method? + utils::text::replace_all(&data, "%2F", "/"); + utils::text::replace_all(&data, "%3F", "?"); + utils::text::replace_all(&data, "%3D", "="); + utils::text::replace_all(&data, "%26", "&"); + utils::text::replace_all(&data, "%3A", ":"); + + return data; +} + +std::string utils::time::unix_timestamp() +{ + time_t in = ::time(NULL); + return utils::conversion::to_string((void*)&in, UTILS_CONV_TIME_T); +} + +std::string utils::time::mili_timestamp() +{ + SYSTEMTIME st; + std::string timestamp = utils::time::unix_timestamp(); + GetSystemTime(&st); + timestamp.append(utils::conversion::to_string((void*)&st.wMilliseconds, UTILS_CONV_UNSIGNED_NUMBER)); + return timestamp.substr(0, 13); +} + +time_t utils::time::from_string(const std::string &data) +{ + long long timestamp = _strtoi64(data.c_str(), NULL, 10); + + // If it is milli timestamp + if (timestamp > 100000000000) + timestamp /= 1000; + + // If conversion fails, use local time? + //if (!timestamp) + // timestamp = ::time(NULL); + + return (time_t)timestamp; +} + +std::string utils::conversion::to_string(void* data, WORD type) +{ + std::stringstream out; + + switch (type) + { + case UTILS_CONV_BOOLEAN: + out << (data ? "true" : "false"); + break; + + case UTILS_CONV_TIME_T: + out << (*(time_t*)data); + break; + + case UTILS_CONV_SIGNED_NUMBER: + out << (*(signed int*)data); + break; + + case UTILS_CONV_UNSIGNED_NUMBER: + out << (*(unsigned int*)data); + break; + } + + return out.str(); +} + +void utils::text::replace_first(std::string* data, const std::string &from, const std::string &to) +{ + std::string::size_type position = data->find(from); + if (position != std::string::npos) + { + data->replace(position, from.size(), to); + } +} + +void utils::text::replace_all(std::string* data, const std::string &from, const std::string &to) +{ + std::string::size_type position = 0; + + while ((position = data->find(from, position)) != std::string::npos) + { + data->replace(position, from.size(), to); + position += to.size(); + } +} + +void utils::text::treplace_all(std::tstring* data, const std::tstring &from, const std::tstring &to) +{ + std::tstring::size_type position = 0; + + while ((position = data->find(from, position)) != std::tstring::npos) + { + data->replace(position, from.size(), to); + position++; + } +} + +unsigned int utils::text::count_all(std::string* data, const std::string &term) +{ + unsigned int count = 0; + std::string::size_type position = 0; + + while ((position = data->find(term, position)) != std::string::npos) + { + count++; + position++; + } + + return count; +} + +void utils::text::append_ordinal(unsigned long value, std::string* data) +{ + if (value <= 127) + { // U+0000 .. U+007F + *data += (char)value; + } + else if (value >= 128 && value <= 2047) + { // U+0080 .. U+07FF + *data += (char)(192 + (value / 64)); + *data += (char)(128 + (value % 64)); + } + else if (value >= 2048 && value <= 65535) + { // U+0800 .. U+FFFF + *data += (char)(224 + (value / 4096)); + *data += (char)(128 + ((value / 64) % 64)); + *data += (char)(128 + (value % 64)); + } + else + { + *data += (char)((value >> 24) & 0xFF); + *data += (char)((value >> 16) & 0xFF); + *data += (char)((value >> 8) & 0xFF); + *data += (char)((value)& 0xFF); + } +} + +std::string utils::text::html_entities_decode(std::string data) +{ + utils::text::replace_all(&data, "&", "&"); + utils::text::replace_all(&data, """, "\""); + utils::text::replace_all(&data, "<", "<"); + utils::text::replace_all(&data, ">", ">"); + + utils::text::replace_all(&data, "♥", "\xE2\x99\xA5"); // direct byte replacement + // utils::text::replace_all(&data, "♥", "\\u2665"); // indirect slashu replacement + + utils::text::replace_all(&data, "\\r", "\r"); + utils::text::replace_all(&data, "\\n", "\n"); + utils::text::replace_all(&data, "\\\"", "\""); + utils::text::replace_all(&data, "\\/", "/"); + utils::text::replace_all(&data, "\\\\", "\\"); + + // TODO: Add more to comply general usage + // http://www.utexas.edu/learn/html/spchar.html + // http://www.webmonkey.com/reference/Special_Characters + // http://www.degraeve.com/reference/specialcharacters.php + // http://www.chami.com/tips/internet/050798i.html + // http://www.w3schools.com/tags/ref_entities.asp + // http://www.natural-innovations.com/wa/doc-charset.html + // http://webdesign.about.com/library/bl_htmlcodes.htm + + std::string new_string; + for (std::string::size_type i = 0; i < data.length(); i++) + { + if (data.at(i) == '&' && (i + 1) < data.length() && data.at(i + 1) == '#') + { + std::string::size_type comma = data.find(";", i); + if (comma != std::string::npos) { + bool hexa = false; + if ((i + 2) < data.length() && data.at(i + 2) == 'x') { + hexa = true; + i += 3; + } + else { + i += 2; + } + + std::string num = data.substr(i, comma - i); + if (!num.empty()) { + unsigned long udn = strtoul(num.c_str(), NULL, hexa ? 16 : 10); + utils::text::append_ordinal(udn, &new_string); + } + + i = comma; + continue; + } + } + + new_string += data.at(i); + } + + return new_string; +} + +std::string utils::text::edit_html(std::string data) +{ + std::string::size_type end = 0; + std::string::size_type start = 0; + std::string new_string; + + while (end != std::string::npos) + { + end = data.find("", start); + if (end != std::string::npos) + { + new_string += data.substr(start, end - start); + start = data.find("<\\/a", end); + } + else { + new_string += data.substr(start, data.length() - start); + } + } + + // Append newline after attachement title + start = new_string.find("class=\\\"uiAttachmentTitle", 0); + if (start != std::string::npos) + { + data = new_string.substr(0, start); + data = utils::text::trim(data); + + start = new_string.find(">", start); + if (start != std::string::npos) + new_string.insert(start + 1, "\n\n"); + + start = new_string.find("<\\/div>", start); + if (start != std::string::npos) + new_string.insert(start, "\n"); + } + + // Append newline between attachement link and description + start = new_string.find("uiAttachmentDesc", 0); + if (start != std::string::npos) + { + start = new_string.find(">", start); + if (start != std::string::npos) + new_string.insert(start + 1, "\n"); + + start = new_string.find("<\\/div>", start); + if (start != std::string::npos) + new_string.insert(start, "\n"); + } + + utils::text::replace_all(&new_string, "
", "\n"); + utils::text::replace_all(&new_string, "\n\n\n", "\n\n"); + //utils::text::replace_all(&new_string, "\\t", ""); + //utils::text::replace_all(&new_string, "\\n", ""); + return new_string; +} + + +std::string utils::text::remove_html(const std::string &data) +{ + std::string new_string; + + for (std::string::size_type i = 0; i < data.length(); i++) + { + if (data.at(i) == '<' && (i + 1) < data.length() && data.at(i + 1) != ' ') + { + i = data.find(">", i); + if (i == std::string::npos) + break; + + continue; + } + + new_string += data.at(i); + } + + return new_string; +} + +std::string utils::text::slashu_to_utf8(const std::string &data) +{ + std::string new_string; + + for (std::string::size_type i = 0; i < data.length(); i++) + { + if (data.at(i) == '\\' && (i + 1) < data.length() && data.at(i + 1) == 'u') + { + unsigned long udn = strtoul(data.substr(i + 2, 4).c_str(), NULL, 16); + append_ordinal(udn, &new_string); + i += 5; + continue; + } + + new_string += data.at(i); + } + + return new_string; +} + +std::string utils::text::trim(const std::string &data, bool rtrim) +{ + std::string spaces = " \t\r\n"; + std::string::size_type begin = rtrim ? 0 : data.find_first_not_of(spaces); + std::string::size_type end = data.find_last_not_of(spaces); + + return (end != std::string::npos) ? data.substr(begin, end + 1 - begin) : ""; +} + +void utils::text::explode(std::string str, const std::string &separator, std::vector* results) +{ + std::string::size_type pos; + pos = str.find_first_of(separator); + while (pos != std::string::npos) { + if (pos > 0) { + results->push_back(str.substr(0, pos)); + } + str = str.substr(pos + 1); + pos = str.find_first_of(separator); + } + if (str.length() > 0) { + results->push_back(str); + } +} + +std::string utils::text::source_get_value(std::string* data, unsigned int argument_count, ...) +{ + va_list arg; + std::string ret; + std::string::size_type start = 0, end = 0; + + va_start(arg, argument_count); + + for (unsigned int i = argument_count; i > 0; i--) + { + if (i == 1) + { + end = data->find(va_arg(arg, char*), start); + if (start == std::string::npos || end == std::string::npos) + break; + ret = data->substr(start, end - start); + } + else { + std::string term = va_arg(arg, char*); + start = data->find(term, start); + if (start == std::string::npos) + break; + start += term.length(); + } + } + + va_end(arg); + return ret; +} + +std::string utils::text::source_get_value2(std::string* data, const char *term, const char *endings, bool wholeString) +{ + std::string::size_type start = 0, end = 0; + std::string ret; + + start = data->find(term); + if (start != std::string::npos) { + start += mir_strlen(term); + + end = data->find_first_of(endings, start); + if (end != std::string::npos) { + ret = data->substr(start, end - start); + } + else if (wholeString) { + ret = data->substr(start); + } + } + + return ret; +} + +std::string utils::text::source_get_form_data(std::string* data) +{ + std::string values; + + std::string::size_type start = 0; + start = data->find("find("name=\"", start); + if (pos != std::string::npos) { + pos += 6; + std::string::size_type end = data->find("\"", pos); + if (end != std::string::npos) + attr = data->substr(pos, end - pos); + + + end = data->find(">", pos); + pos = data->find("value=\"", pos); + if (pos != std::string::npos && end != std::string::npos && pos < end) { + pos += 7; + end = data->find("\"", pos); + if (end != std::string::npos) + value = data->substr(pos, end - pos); + } + } + + if (!attr.empty()) { + if (!values.empty()) + values += "&"; + values += attr + "=" + value; + } + start = data->find(". + +*/ + +#pragma once + +#define _CRT_RAND_S + +#include +#include +#include + +#include +#include + +#include + +// C++ bool type +#define UTILS_CONV_BOOLEAN 0x0001 // true | false +// signed regular numbers +#define UTILS_CONV_SIGNED_NUMBER 0x0010 // 1234 | -1234 +// unsigned regular numbers +#define UTILS_CONV_UNSIGNED_NUMBER 0x0020 // 1234 +// miscellaneous +#define UTILS_CONV_TIME_T 0x0040 // 1234567890 + +namespace utils +{ + namespace url + { + std::string encode(const std::string &s); + std::string decode(std::string data); + }; + + namespace time + { + std::string unix_timestamp(); + std::string mili_timestamp(); + time_t from_string(const std::string &data); + }; + + namespace number + { + int random(int min, int max, unsigned int *value = NULL); + }; + + namespace text + { + void replace_first(std::string* data, const std::string &from, const std::string &to); + void replace_all(std::string* data, const std::string &from, const std::string &to); + void treplace_all(std::tstring* data, const std::tstring &from, const std::tstring &to); + unsigned int count_all(std::string* data, const std::string &term); + std::string html_entities_decode(std::string data); + std::string edit_html(std::string data); + std::string remove_html(const std::string &data); + std::string slashu_to_utf8(const std::string &data); + std::string trim(const std::string &data, bool rtrim = false); + std::string source_get_value(std::string* data, unsigned int argument_count, ...); + std::string source_get_value2(std::string* data, const char *term, const char *endings, bool wholeString = false); + std::string source_get_form_data(std::string* data); + std::string rand_string(int len, const char *chars = "0123456789" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz", unsigned int *number = NULL); + void explode(std::string str, const std::string &separator, std::vector* results); + void append_ordinal(unsigned long value, std::string* data); + std::tstring prepare_name(const std::tstring &name, bool withSurnameLetter); + }; + + namespace conversion + { + std::string to_string(void*, WORD type); + + template + bool from_string(T& t, const std::string& s, std::ios_base& (*f)(std::ios_base&)) { + std::istringstream iss(s); + return !(iss >> f >> t).fail(); + } + }; +}; -- cgit v1.2.3