#ifndef LH_HTML_H #define LH_HTML_H #include #include #include #include #include #include "types.h" #include "media_query.h" namespace litehtml { const string whitespace = " \n\r\t\f"; string& trim(string& s, const string& chars_to_trim = whitespace); string trim(const string& s, const string& chars_to_trim = whitespace); string& lcase(string& s); int value_index(const string& val, const string& strings, int defValue = -1, char delim = ';'); string index_value(int index, const string& strings, char delim = ';'); bool value_in_list(const string& val, const string& strings, char delim = ';'); string::size_type find_close_bracket(const string& s, string::size_type off, char open_b = '(', char close_b = ')'); void split_string(const string& str, string_vector& tokens, const string& delims = whitespace, const string& delims_preserve = "", const string& quote = "\""); string_vector split_string(const string& str, const string& delims = whitespace, const string& delims_preserve = "", const string& quote = "\""); void join_string(string& str, const string_vector& tokens, const string& delims); double t_strtod(const char* string, char** endPtr = nullptr); string get_escaped_string(const string& in_str); template bool is_one_of(T val, Opts ...opts) { return (... || (val == opts)); } template const T& at(const vector& vec, int index /*may be negative*/) { static T invalid_item; // T's default constructor must create invalid item if (index < 0) index += (int)vec.size(); return index >= 0 && index < (int)vec.size() ? vec[index] : invalid_item; } template auto at(const Map& map, Key key) { static typename Map::mapped_type invalid_value; // mapped_type's default constructor must create invalid item auto it = map.find(key); return it != map.end() ? it->second : invalid_value; } template vector slice(const vector& vec, int index, int count = -1) { if (count == -1) count = (int)vec.size() - index; return {vec.begin() + index, vec.begin() + index + count}; } template // C == vector or string void remove(C& vec, int index /*may be negative*/, int count = 1) { if (index < 0) index += (int)vec.size(); if (!(index >= 0 && index < (int)vec.size())) return; count = min(count, (int)vec.size() - index); if (count <= 0) return; vec.erase(vec.begin() + index, vec.begin() + index + count); } template void insert(vector& vec, int index, const vector& x) { vec.insert(vec.begin() + index, x.begin(), x.end()); } template vector& operator+=(vector& vec, const vector& x) { vec.insert(vec.end(), x.begin(), x.end()); return vec; } template bool contains(const C& coll, const T& item) { return std::find(coll.begin(), coll.end(), item) != coll.end(); } inline bool contains(const string& str, const string& substr) { return str.find(substr) != string::npos; } template void sort(C& coll) { std::sort(coll.begin(), coll.end()); } int t_strcasecmp(const char *s1, const char *s2); int t_strncasecmp(const char *s1, const char *s2, size_t n); inline bool equal_i(const string& s1, const string& s2) { if (s1.size() != s2.size()) return false; return t_strncasecmp(s1.c_str(), s2.c_str(), s1.size()) == 0; } inline bool match(const string& str, int index /*may be negative*/, const string& substr) { if (index < 0) index += (int)str.size(); if (index < 0) return false; return str.substr(index, substr.size()) == substr; } inline bool match_i(const string& str, int index /*may be negative*/, const string& substr) { if (index < 0) index += (int)str.size(); if (index < 0) return false; return equal_i(str.substr(index, substr.size()), substr); } bool is_number(const string& string, bool allow_dot = true); // https://infra.spec.whatwg.org/#ascii-whitespace inline bool is_whitespace(int c) { return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f'; } inline int t_isalpha(int c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); } const auto is_letter = t_isalpha; inline int t_tolower(int c) { return (c >= 'A' && c <= 'Z' ? c + 'a' - 'A' : c); } // https://infra.spec.whatwg.org/#ascii-lowercase inline int lowcase(int c) { return t_tolower(c); } inline string lowcase(string str) { for (char& c : str) c = (char)t_tolower(c); return str; } inline int t_isdigit(int c) { return (c >= '0' && c <= '9'); } const auto is_digit = t_isdigit; inline bool is_hex_digit(int ch) { return is_digit(ch) || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'); } inline int digit_value(int ch) { return is_digit(ch) ? ch - '0' : lowcase(ch) - 'a' + 10; } inline bool is_surrogate(int ch) { return ch >= 0xD800 && ch < 0xE000; } inline int round_f(float val) { int int_val = (int) val; if(val - int_val >= 0.5) { int_val++; } return int_val; } inline int round_d(double val) { int int_val = (int) val; if(val - int_val >= 0.5) { int_val++; } return int_val; } inline float t_strtof(const string& str, char** endPtr = nullptr) { return (float)t_strtod(str.c_str(), endPtr); } inline int baseline_align(int line_height, int line_base_line, int height, int baseline) { return (line_height - line_base_line) - (height - baseline); } } #endif // LH_HTML_H