diff options
author | Thiago Marcos P. Santos <tmpsantos@gmail.com> | 2020-02-26 16:08:23 +0200 |
---|---|---|
committer | Thiago Marcos P. Santos <tmpsantos@gmail.com> | 2020-02-27 18:19:31 +0200 |
commit | 427d785848ba1cbf8df095ebe75c8731f30dfb5e (patch) | |
tree | 317eb2ba3ba7078f13f00cd83a0368d76f6b949f /vendor | |
parent | 242b719f0cbb24b485e439edd0da5aedee87f444 (diff) | |
download | qtlocation-mapboxgl-427d785848ba1cbf8df095ebe75c8731f30dfb5e.tar.gz |
[build] Make csscolorparser and parsedate vendors
They have a different license from the rest of the code
and this will make it explicit. Also the script for generating
the license will dectect them correctly.
Diffstat (limited to 'vendor')
-rw-r--r-- | vendor/csscolorparser.cmake | 27 | ||||
-rw-r--r-- | vendor/csscolorparser/LICENSE | 20 | ||||
-rw-r--r-- | vendor/csscolorparser/csscolorparser.cpp | 288 | ||||
-rw-r--r-- | vendor/csscolorparser/csscolorparser/csscolorparser.hpp | 57 | ||||
-rw-r--r-- | vendor/parsedate.cmake | 27 | ||||
-rw-r--r-- | vendor/parsedate/COPYING | 22 | ||||
-rw-r--r-- | vendor/parsedate/parsedate.cpp | 682 | ||||
-rw-r--r-- | vendor/parsedate/parsedate/parsedate.hpp | 35 |
8 files changed, 1158 insertions, 0 deletions
diff --git a/vendor/csscolorparser.cmake b/vendor/csscolorparser.cmake new file mode 100644 index 0000000000..28038ff988 --- /dev/null +++ b/vendor/csscolorparser.cmake @@ -0,0 +1,27 @@ +if(TARGET mbgl-vendor-csscolorparser) + return() +endif() + +add_library( + mbgl-vendor-csscolorparser STATIC + ${CMAKE_CURRENT_LIST_DIR}/csscolorparser/csscolorparser.cpp +) + +target_link_libraries( + mbgl-vendor-csscolorparser + PRIVATE Mapbox::Base::optional mbgl-compiler-options +) + +target_include_directories( + mbgl-vendor-csscolorparser SYSTEM + PUBLIC ${CMAKE_CURRENT_LIST_DIR}/csscolorparser +) + +set_target_properties( + mbgl-vendor-csscolorparser + PROPERTIES + INTERFACE_MAPBOX_NAME "csscolorparser" + INTERFACE_MAPBOX_URL "https://github.com/mapbox/css-color-parser-cpp" + INTERFACE_MAPBOX_AUTHOR "Dean McNamee and Konstantin Käfer" + INTERFACE_MAPBOX_LICENSE ${CMAKE_CURRENT_LIST_DIR}/csscolorparser/LICENSE +) diff --git a/vendor/csscolorparser/LICENSE b/vendor/csscolorparser/LICENSE new file mode 100644 index 0000000000..2408b4a02e --- /dev/null +++ b/vendor/csscolorparser/LICENSE @@ -0,0 +1,20 @@ +(c) Dean McNamee <dean@gmail.com>, 2012. +(c) Konstantin Käfer <mail@kkaefer.com>, 2014. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. diff --git a/vendor/csscolorparser/csscolorparser.cpp b/vendor/csscolorparser/csscolorparser.cpp new file mode 100644 index 0000000000..b0ff5f84e0 --- /dev/null +++ b/vendor/csscolorparser/csscolorparser.cpp @@ -0,0 +1,288 @@ +// (c) Dean McNamee <dean@gmail.com>, 2012. +// C++ port by Mapbox, Konstantin Käfer <mail@kkaefer.com>, 2014-2017. +// +// https://github.com/deanm/css-color-parser-js +// https://github.com/kkaefer/css-color-parser-cpp +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +#include "csscolorparser/csscolorparser.hpp" + +#include <cstdint> +#include <vector> +#include <sstream> +#include <algorithm> + +namespace CSSColorParser { + +// http://www.w3.org/TR/css3-color/ +struct NamedColor { const char *const name; const Color color; }; +const NamedColor namedColors[] = { + { "transparent", { 0, 0, 0, 0 } }, { "aliceblue", { 240, 248, 255, 1 } }, + { "antiquewhite", { 250, 235, 215, 1 } }, { "aqua", { 0, 255, 255, 1 } }, + { "aquamarine", { 127, 255, 212, 1 } }, { "azure", { 240, 255, 255, 1 } }, + { "beige", { 245, 245, 220, 1 } }, { "bisque", { 255, 228, 196, 1 } }, + { "black", { 0, 0, 0, 1 } }, { "blanchedalmond", { 255, 235, 205, 1 } }, + { "blue", { 0, 0, 255, 1 } }, { "blueviolet", { 138, 43, 226, 1 } }, + { "brown", { 165, 42, 42, 1 } }, { "burlywood", { 222, 184, 135, 1 } }, + { "cadetblue", { 95, 158, 160, 1 } }, { "chartreuse", { 127, 255, 0, 1 } }, + { "chocolate", { 210, 105, 30, 1 } }, { "coral", { 255, 127, 80, 1 } }, + { "cornflowerblue", { 100, 149, 237, 1 } }, { "cornsilk", { 255, 248, 220, 1 } }, + { "crimson", { 220, 20, 60, 1 } }, { "cyan", { 0, 255, 255, 1 } }, + { "darkblue", { 0, 0, 139, 1 } }, { "darkcyan", { 0, 139, 139, 1 } }, + { "darkgoldenrod", { 184, 134, 11, 1 } }, { "darkgray", { 169, 169, 169, 1 } }, + { "darkgreen", { 0, 100, 0, 1 } }, { "darkgrey", { 169, 169, 169, 1 } }, + { "darkkhaki", { 189, 183, 107, 1 } }, { "darkmagenta", { 139, 0, 139, 1 } }, + { "darkolivegreen", { 85, 107, 47, 1 } }, { "darkorange", { 255, 140, 0, 1 } }, + { "darkorchid", { 153, 50, 204, 1 } }, { "darkred", { 139, 0, 0, 1 } }, + { "darksalmon", { 233, 150, 122, 1 } }, { "darkseagreen", { 143, 188, 143, 1 } }, + { "darkslateblue", { 72, 61, 139, 1 } }, { "darkslategray", { 47, 79, 79, 1 } }, + { "darkslategrey", { 47, 79, 79, 1 } }, { "darkturquoise", { 0, 206, 209, 1 } }, + { "darkviolet", { 148, 0, 211, 1 } }, { "deeppink", { 255, 20, 147, 1 } }, + { "deepskyblue", { 0, 191, 255, 1 } }, { "dimgray", { 105, 105, 105, 1 } }, + { "dimgrey", { 105, 105, 105, 1 } }, { "dodgerblue", { 30, 144, 255, 1 } }, + { "firebrick", { 178, 34, 34, 1 } }, { "floralwhite", { 255, 250, 240, 1 } }, + { "forestgreen", { 34, 139, 34, 1 } }, { "fuchsia", { 255, 0, 255, 1 } }, + { "gainsboro", { 220, 220, 220, 1 } }, { "ghostwhite", { 248, 248, 255, 1 } }, + { "gold", { 255, 215, 0, 1 } }, { "goldenrod", { 218, 165, 32, 1 } }, + { "gray", { 128, 128, 128, 1 } }, { "green", { 0, 128, 0, 1 } }, + { "greenyellow", { 173, 255, 47, 1 } }, { "grey", { 128, 128, 128, 1 } }, + { "honeydew", { 240, 255, 240, 1 } }, { "hotpink", { 255, 105, 180, 1 } }, + { "indianred", { 205, 92, 92, 1 } }, { "indigo", { 75, 0, 130, 1 } }, + { "ivory", { 255, 255, 240, 1 } }, { "khaki", { 240, 230, 140, 1 } }, + { "lavender", { 230, 230, 250, 1 } }, { "lavenderblush", { 255, 240, 245, 1 } }, + { "lawngreen", { 124, 252, 0, 1 } }, { "lemonchiffon", { 255, 250, 205, 1 } }, + { "lightblue", { 173, 216, 230, 1 } }, { "lightcoral", { 240, 128, 128, 1 } }, + { "lightcyan", { 224, 255, 255, 1 } }, { "lightgoldenrodyellow", { 250, 250, 210, 1 } }, + { "lightgray", { 211, 211, 211, 1 } }, { "lightgreen", { 144, 238, 144, 1 } }, + { "lightgrey", { 211, 211, 211, 1 } }, { "lightpink", { 255, 182, 193, 1 } }, + { "lightsalmon", { 255, 160, 122, 1 } }, { "lightseagreen", { 32, 178, 170, 1 } }, + { "lightskyblue", { 135, 206, 250, 1 } }, { "lightslategray", { 119, 136, 153, 1 } }, + { "lightslategrey", { 119, 136, 153, 1 } }, { "lightsteelblue", { 176, 196, 222, 1 } }, + { "lightyellow", { 255, 255, 224, 1 } }, { "lime", { 0, 255, 0, 1 } }, + { "limegreen", { 50, 205, 50, 1 } }, { "linen", { 250, 240, 230, 1 } }, + { "magenta", { 255, 0, 255, 1 } }, { "maroon", { 128, 0, 0, 1 } }, + { "mediumaquamarine", { 102, 205, 170, 1 } }, { "mediumblue", { 0, 0, 205, 1 } }, + { "mediumorchid", { 186, 85, 211, 1 } }, { "mediumpurple", { 147, 112, 219, 1 } }, + { "mediumseagreen", { 60, 179, 113, 1 } }, { "mediumslateblue", { 123, 104, 238, 1 } }, + { "mediumspringgreen", { 0, 250, 154, 1 } }, { "mediumturquoise", { 72, 209, 204, 1 } }, + { "mediumvioletred", { 199, 21, 133, 1 } }, { "midnightblue", { 25, 25, 112, 1 } }, + { "mintcream", { 245, 255, 250, 1 } }, { "mistyrose", { 255, 228, 225, 1 } }, + { "moccasin", { 255, 228, 181, 1 } }, { "navajowhite", { 255, 222, 173, 1 } }, + { "navy", { 0, 0, 128, 1 } }, { "oldlace", { 253, 245, 230, 1 } }, + { "olive", { 128, 128, 0, 1 } }, { "olivedrab", { 107, 142, 35, 1 } }, + { "orange", { 255, 165, 0, 1 } }, { "orangered", { 255, 69, 0, 1 } }, + { "orchid", { 218, 112, 214, 1 } }, { "palegoldenrod", { 238, 232, 170, 1 } }, + { "palegreen", { 152, 251, 152, 1 } }, { "paleturquoise", { 175, 238, 238, 1 } }, + { "palevioletred", { 219, 112, 147, 1 } }, { "papayawhip", { 255, 239, 213, 1 } }, + { "peachpuff", { 255, 218, 185, 1 } }, { "peru", { 205, 133, 63, 1 } }, + { "pink", { 255, 192, 203, 1 } }, { "plum", { 221, 160, 221, 1 } }, + { "powderblue", { 176, 224, 230, 1 } }, { "purple", { 128, 0, 128, 1 } }, + { "red", { 255, 0, 0, 1 } }, { "rosybrown", { 188, 143, 143, 1 } }, + { "royalblue", { 65, 105, 225, 1 } }, { "saddlebrown", { 139, 69, 19, 1 } }, + { "salmon", { 250, 128, 114, 1 } }, { "sandybrown", { 244, 164, 96, 1 } }, + { "seagreen", { 46, 139, 87, 1 } }, { "seashell", { 255, 245, 238, 1 } }, + { "sienna", { 160, 82, 45, 1 } }, { "silver", { 192, 192, 192, 1 } }, + { "skyblue", { 135, 206, 235, 1 } }, { "slateblue", { 106, 90, 205, 1 } }, + { "slategray", { 112, 128, 144, 1 } }, { "slategrey", { 112, 128, 144, 1 } }, + { "snow", { 255, 250, 250, 1 } }, { "springgreen", { 0, 255, 127, 1 } }, + { "steelblue", { 70, 130, 180, 1 } }, { "tan", { 210, 180, 140, 1 } }, + { "teal", { 0, 128, 128, 1 } }, { "thistle", { 216, 191, 216, 1 } }, + { "tomato", { 255, 99, 71, 1 } }, { "turquoise", { 64, 224, 208, 1 } }, + { "violet", { 238, 130, 238, 1 } }, { "wheat", { 245, 222, 179, 1 } }, + { "white", { 255, 255, 255, 1 } }, { "whitesmoke", { 245, 245, 245, 1 } }, + { "yellow", { 255, 255, 0, 1 } }, { "yellowgreen", { 154, 205, 50, 1 } } +}; + +template <typename T> +uint8_t clamp_css_byte(T i) { // Clamp to integer 0 .. 255. + i = ::round(i); // Seems to be what Chrome does (vs truncation). + return i < 0 ? 0 : i > 255 ? 255 : uint8_t(i); +} + +template <typename T> +float clamp_css_float(T f) { // Clamp to float 0.0 .. 1.0. + return f < 0 ? 0 : f > 1 ? 1 : float(f); +} + +float parseFloat(const std::string& str) { + return strtof(str.c_str(), nullptr); +} + +int64_t parseInt(const std::string& str, uint8_t base = 10) { + return strtoll(str.c_str(), nullptr, base); +} + +uint8_t parse_css_int(const std::string& str) { // int or percentage. + if (str.length() && str.back() == '%') { + return clamp_css_byte(parseFloat(str) / 100.0f * 255.0f); + } else { + return clamp_css_byte(parseInt(str)); + } +} + +float parse_css_float(const std::string& str) { // float or percentage. + if (str.length() && str.back() == '%') { + return clamp_css_float(parseFloat(str) / 100.0f); + } else { + return clamp_css_float(parseFloat(str)); + } +} + +float css_hue_to_rgb(float m1, float m2, float h) { + if (h < 0.0f) { + h += 1.0f; + } else if (h > 1.0f) { + h -= 1.0f; + } + + if (h * 6.0f < 1.0f) { + return m1 + (m2 - m1) * h * 6.0f; + } + if (h * 2.0f < 1.0f) { + return m2; + } + if (h * 3.0f < 2.0f) { + return m1 + (m2 - m1) * (2.0f / 3.0f - h) * 6.0f; + } + return m1; +} + + + +std::vector<std::string> split(const std::string& s, char delim) { + std::vector<std::string> elems; + std::stringstream ss(s); + std::string item; + while (std::getline(ss, item, delim)) { + elems.push_back(item); + } + return elems; +} + +std::experimental::optional<Color> parse(const std::string& css_str) { + std::string str = css_str; + + // Remove all whitespace, not compliant, but should just be more accepting. + str.erase(std::remove(str.begin(), str.end(), ' '), str.end()); + + // Convert to lowercase. + std::transform(str.begin(), str.end(), str.begin(), ::tolower); + + for (const auto& namedColor : namedColors) { + if (str == namedColor.name) { + return { namedColor.color }; + } + } + + // #abc and #abc123 syntax. + if (str.length() && str.front() == '#') { + if (str.length() == 4) { + int64_t iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing. + if (!(iv >= 0 && iv <= 0xfff)) { + return {}; + } else { + return {{ + static_cast<uint8_t>(((iv & 0xf00) >> 4) | ((iv & 0xf00) >> 8)), + static_cast<uint8_t>((iv & 0xf0) | ((iv & 0xf0) >> 4)), + static_cast<uint8_t>((iv & 0xf) | ((iv & 0xf) << 4)), + 1 + }}; + } + } else if (str.length() == 7) { + int64_t iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing. + if (!(iv >= 0 && iv <= 0xffffff)) { + return {}; // Covers NaN. + } else { + return {{ + static_cast<uint8_t>((iv & 0xff0000) >> 16), + static_cast<uint8_t>((iv & 0xff00) >> 8), + static_cast<uint8_t>(iv & 0xff), + 1 + }}; + } + } + + return {}; + } + + size_t op = str.find_first_of('('), ep = str.find_first_of(')'); + if (op != std::string::npos && ep + 1 == str.length()) { + const std::string fname = str.substr(0, op); + const std::vector<std::string> params = split(str.substr(op + 1, ep - (op + 1)), ','); + + float alpha = 1.0f; + + if (fname == "rgba" || fname == "rgb") { + if (fname == "rgba") { + if (params.size() != 4) { + return {}; + } + alpha = parse_css_float(params.back()); + } else { + if (params.size() != 3) { + return {}; + } + } + + return {{ + parse_css_int(params[0]), + parse_css_int(params[1]), + parse_css_int(params[2]), + alpha + }}; + + } else if (fname == "hsla" || fname == "hsl") { + if (fname == "hsla") { + if (params.size() != 4) { + return {}; + } + alpha = parse_css_float(params.back()); + } else { + if (params.size() != 3) { + return {}; + } + } + + float h = parseFloat(params[0]) / 360.0f; + float i; + // Normalize the hue to [0..1[ + h = std::modf(h, &i); + + // NOTE(deanm): According to the CSS spec s/l should only be + // percentages, but we don't bother and let float or percentage. + float s = parse_css_float(params[1]); + float l = parse_css_float(params[2]); + + float m2 = l <= 0.5f ? l * (s + 1.0f) : l + s - l * s; + float m1 = l * 2.0f - m2; + + return {{ + clamp_css_byte(css_hue_to_rgb(m1, m2, h + 1.0f / 3.0f) * 255.0f), + clamp_css_byte(css_hue_to_rgb(m1, m2, h) * 255.0f), + clamp_css_byte(css_hue_to_rgb(m1, m2, h - 1.0f / 3.0f) * 255.0f), + alpha + }}; + } + } + + return {}; +} + +} // namespace CSSColorParser diff --git a/vendor/csscolorparser/csscolorparser/csscolorparser.hpp b/vendor/csscolorparser/csscolorparser/csscolorparser.hpp new file mode 100644 index 0000000000..30b308022a --- /dev/null +++ b/vendor/csscolorparser/csscolorparser/csscolorparser.hpp @@ -0,0 +1,57 @@ +// (c) Dean McNamee <dean@gmail.com>, 2012. +// C++ port by Mapbox, Konstantin Käfer <mail@kkaefer.com>, 2014-2017. +// +// https://github.com/deanm/css-color-parser-js +// https://github.com/kkaefer/css-color-parser-cpp +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +#ifndef CSS_COLOR_PARSER_CPP +#define CSS_COLOR_PARSER_CPP + +#include <optional.hpp> + +#include <string> +#include <cmath> + +namespace CSSColorParser { + +struct Color { + inline Color() { + } + inline Color(unsigned char r_, unsigned char g_, unsigned char b_, float a_) + : r(r_), g(g_), b(b_), a(a_ > 1 ? 1 : a_ < 0 ? 0 : a_) { + } + unsigned char r = 0, g = 0, b = 0; + float a = 1.0f; +}; + +inline bool operator==(const Color& lhs, const Color& rhs) { + return lhs.r == rhs.r && lhs.g == rhs.g && lhs.b == rhs.b && ::fabs(lhs.a - rhs.a) < 0.0001f; +} + +inline bool operator!=(const Color& lhs, const Color& rhs) { + return !(lhs == rhs); +} + +std::experimental::optional<Color> parse(const std::string& css_str); + +} // namespace CSSColorParser + +#endif diff --git a/vendor/parsedate.cmake b/vendor/parsedate.cmake new file mode 100644 index 0000000000..fe1163ce07 --- /dev/null +++ b/vendor/parsedate.cmake @@ -0,0 +1,27 @@ +if(TARGET mbgl-vendor-parsedate) + return() +endif() + +add_library( + mbgl-vendor-parsedate STATIC + ${CMAKE_CURRENT_LIST_DIR}/parsedate/parsedate.cpp +) + +target_link_libraries( + mbgl-vendor-parsedate + PRIVATE mbgl-compiler-options +) + +target_include_directories( + mbgl-vendor-parsedate SYSTEM + PUBLIC ${CMAKE_CURRENT_LIST_DIR}/parsedate +) + +set_target_properties( + mbgl-vendor-parsedate + PROPERTIES + INTERFACE_MAPBOX_NAME "parsedate" + INTERFACE_MAPBOX_URL "https://curl.haxx.se" + INTERFACE_MAPBOX_AUTHOR "Daniel Stenberg and others" + INTERFACE_MAPBOX_LICENSE ${CMAKE_CURRENT_LIST_DIR}/parsedate/COPYING +) diff --git a/vendor/parsedate/COPYING b/vendor/parsedate/COPYING new file mode 100644 index 0000000000..9d9e4af8d8 --- /dev/null +++ b/vendor/parsedate/COPYING @@ -0,0 +1,22 @@ +COPYRIGHT AND PERMISSION NOTICE + +Copyright (c) 1996 - 2020, Daniel Stenberg, <daniel@haxx.se>, and many +contributors, see the THANKS file. + +All rights reserved. + +Permission to use, copy, modify, and distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright +notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall not +be used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization of the copyright holder. diff --git a/vendor/parsedate/parsedate.cpp b/vendor/parsedate/parsedate.cpp new file mode 100644 index 0000000000..6531cd6dff --- /dev/null +++ b/vendor/parsedate/parsedate.cpp @@ -0,0 +1,682 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +/* + A brief summary of the date string formats this parser groks: + + RFC 2616 3.3.1 + + Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 + Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 + Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format + + we support dates without week day name: + + 06 Nov 1994 08:49:37 GMT + 06-Nov-94 08:49:37 GMT + Nov 6 08:49:37 1994 + + without the time zone: + + 06 Nov 1994 08:49:37 + 06-Nov-94 08:49:37 + + weird order: + + 1994 Nov 6 08:49:37 (GNU date fails) + GMT 08:49:37 06-Nov-94 Sunday + 94 6 Nov 08:49:37 (GNU date fails) + + time left out: + + 1994 Nov 6 + 06-Nov-94 + Sun Nov 6 94 + + unusual separators: + + 1994.Nov.6 + Sun/Nov/6/94/GMT + + commonly used time zone names: + + Sun, 06 Nov 1994 08:49:37 CET + 06 Nov 1994 08:49:37 EST + + time zones specified using RFC822 style: + + Sun, 12 Sep 2004 15:05:58 -0700 + Sat, 11 Sep 2004 21:32:11 +0200 + + compact numerical date strings: + + 20040912 15:05:58 -0700 + 20040911 +0200 + +*/ + +#include "parsedate/parsedate.hpp" + +#ifdef __cplusplus +extern "C" { +#endif + +#include <limits.h> +#include <stdbool.h> +#include <errno.h> +#include <string.h> +#include <ctype.h> +#include <stdlib.h> +#include <stdio.h> + +/* Portable, consistent toupper (remember EBCDIC). Do not use toupper() because + its behavior is altered by the current locale. */ +char raw_toupper(char in) +{ + switch (in) { + case 'a': + return 'A'; + case 'b': + return 'B'; + case 'c': + return 'C'; + case 'd': + return 'D'; + case 'e': + return 'E'; + case 'f': + return 'F'; + case 'g': + return 'G'; + case 'h': + return 'H'; + case 'i': + return 'I'; + case 'j': + return 'J'; + case 'k': + return 'K'; + case 'l': + return 'L'; + case 'm': + return 'M'; + case 'n': + return 'N'; + case 'o': + return 'O'; + case 'p': + return 'P'; + case 'q': + return 'Q'; + case 'r': + return 'R'; + case 's': + return 'S'; + case 't': + return 'T'; + case 'u': + return 'U'; + case 'v': + return 'V'; + case 'w': + return 'W'; + case 'x': + return 'X'; + case 'y': + return 'Y'; + case 'z': + return 'Z'; + } + return in; +} + +/* + * strcasecompare() is for doing "raw" case insensitive strings. This is + * meant to be locale independent and only compare strings we know are safe + * for this. See + * https://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for some + * further explanation to why this function is necessary. + * + * The function is capable of comparing a-z case insensitively even for + * non-ascii. + * + * @unittest: 1301 + */ + +int strcasecompare(const char *first, const char *second) +{ + while(*first && *second) { + if(raw_toupper(*first) != raw_toupper(*second)) + /* get out of the loop as soon as they don't match */ + break; + first++; + second++; + } + /* we do the comparison here (possibly again), just to make sure that if the + loop above is skipped because one of the strings reached zero, we must not + return this as a successful match */ + return (raw_toupper(*first) == raw_toupper(*second)); +} + +#define ISSPACE(x) (isspace((int) ((unsigned char)x))) +#define ISDIGIT(x) (isdigit((int) ((unsigned char)x))) +#define ISALNUM(x) (isalnum((int) ((unsigned char)x))) +#define ISALPHA(x) (isalpha((int) ((unsigned char)x))) + + +/* + * Redefine TRUE and FALSE too, to catch current use. With this + * change, 'bool found = 1' will give a warning on MIPSPro, but + * 'bool found = TRUE' will not. Change tested on IRIX/MIPSPro, + * AIX 5.1/Xlc, Tru64 5.1/cc, w/make test too. + */ + +#ifndef TRUE +#define TRUE true +#endif +#ifndef FALSE +#define FALSE false +#endif + + +#define TIME_T_MIN 0 +#define TIME_T_MAX INT_MAX + +/* +** signed long to signed int +*/ + +int mbgl_curlx_sltosi(long slnum) +{ + return slnum > INT_MAX ? INT_MAX : slnum < INT_MIN ? INT_MIN : (int)slnum; +} + + +const char * const Curl_wkday[] = +{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; +static const char * const weekday[] = +{ "Monday", "Tuesday", "Wednesday", "Thursday", + "Friday", "Saturday", "Sunday" }; +const char * const Curl_month[]= +{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + +struct tzinfo { + char name[5]; + int offset; /* +/- in minutes */ +}; + +/* + * parsedate() + * + * Returns: + * + * PARSEDATE_OK - a fine conversion + * PARSEDATE_FAIL - failed to convert + * PARSEDATE_LATER - time overflow at the far end of time_t + * PARSEDATE_SOONER - time underflow at the low end of time_t + */ + +static int parsedate(const char *date, time_t *output); + +#define PARSEDATE_OK 0 +#define PARSEDATE_FAIL -1 +#define PARSEDATE_LATER 1 +#define PARSEDATE_SOONER 2 + +/* Here's a bunch of frequently used time zone names. These were supported + by the old getdate parser. */ +#define tDAYZONE -60 /* offset for daylight savings time */ +static const struct tzinfo tz[]= { + {"GMT", 0}, /* Greenwich Mean */ + {"UT", 0}, /* Universal Time */ + {"UTC", 0}, /* Universal (Coordinated) */ + {"WET", 0}, /* Western European */ + {"BST", 0 tDAYZONE}, /* British Summer */ + {"WAT", 60}, /* West Africa */ + {"AST", 240}, /* Atlantic Standard */ + {"ADT", 240 tDAYZONE}, /* Atlantic Daylight */ + {"EST", 300}, /* Eastern Standard */ + {"EDT", 300 tDAYZONE}, /* Eastern Daylight */ + {"CST", 360}, /* Central Standard */ + {"CDT", 360 tDAYZONE}, /* Central Daylight */ + {"MST", 420}, /* Mountain Standard */ + {"MDT", 420 tDAYZONE}, /* Mountain Daylight */ + {"PST", 480}, /* Pacific Standard */ + {"PDT", 480 tDAYZONE}, /* Pacific Daylight */ + {"YST", 540}, /* Yukon Standard */ + {"YDT", 540 tDAYZONE}, /* Yukon Daylight */ + {"HST", 600}, /* Hawaii Standard */ + {"HDT", 600 tDAYZONE}, /* Hawaii Daylight */ + {"CAT", 600}, /* Central Alaska */ + {"AHST", 600}, /* Alaska-Hawaii Standard */ + {"NT", 660}, /* Nome */ + {"IDLW", 720}, /* International Date Line West */ + {"CET", -60}, /* Central European */ + {"MET", -60}, /* Middle European */ + {"MEWT", -60}, /* Middle European Winter */ + {"MEST", -60 tDAYZONE}, /* Middle European Summer */ + {"CEST", -60 tDAYZONE}, /* Central European Summer */ + {"MESZ", -60 tDAYZONE}, /* Middle European Summer */ + {"FWT", -60}, /* French Winter */ + {"FST", -60 tDAYZONE}, /* French Summer */ + {"EET", -120}, /* Eastern Europe, USSR Zone 1 */ + {"WAST", -420}, /* West Australian Standard */ + {"WADT", -420 tDAYZONE}, /* West Australian Daylight */ + {"CCT", -480}, /* China Coast, USSR Zone 7 */ + {"JST", -540}, /* Japan Standard, USSR Zone 8 */ + {"EAST", -600}, /* Eastern Australian Standard */ + {"EADT", -600 tDAYZONE}, /* Eastern Australian Daylight */ + {"GST", -600}, /* Guam Standard, USSR Zone 9 */ + {"NZT", -720}, /* New Zealand */ + {"NZST", -720}, /* New Zealand Standard */ + {"NZDT", -720 tDAYZONE}, /* New Zealand Daylight */ + {"IDLE", -720}, /* International Date Line East */ + /* Next up: Military timezone names. RFC822 allowed these, but (as noted in + RFC 1123) had their signs wrong. Here we use the correct signs to match + actual military usage. + */ + {"A", 1 * 60}, /* Alpha */ + {"B", 2 * 60}, /* Bravo */ + {"C", 3 * 60}, /* Charlie */ + {"D", 4 * 60}, /* Delta */ + {"E", 5 * 60}, /* Echo */ + {"F", 6 * 60}, /* Foxtrot */ + {"G", 7 * 60}, /* Golf */ + {"H", 8 * 60}, /* Hotel */ + {"I", 9 * 60}, /* India */ + /* "J", Juliet is not used as a timezone, to indicate the observer's local + time */ + {"K", 10 * 60}, /* Kilo */ + {"L", 11 * 60}, /* Lima */ + {"M", 12 * 60}, /* Mike */ + {"N", -1 * 60}, /* November */ + {"O", -2 * 60}, /* Oscar */ + {"P", -3 * 60}, /* Papa */ + {"Q", -4 * 60}, /* Quebec */ + {"R", -5 * 60}, /* Romeo */ + {"S", -6 * 60}, /* Sierra */ + {"T", -7 * 60}, /* Tango */ + {"U", -8 * 60}, /* Uniform */ + {"V", -9 * 60}, /* Victor */ + {"W", -10 * 60}, /* Whiskey */ + {"X", -11 * 60}, /* X-ray */ + {"Y", -12 * 60}, /* Yankee */ + {"Z", 0}, /* Zulu, zero meridian, a.k.a. UTC */ +}; + +/* returns: + -1 no day + 0 monday - 6 sunday +*/ + +static int checkday(const char *check, size_t len) +{ + int i; + const char * const *what; + bool found = FALSE; + if(len > 3) + what = &weekday[0]; + else + what = &Curl_wkday[0]; + for(i = 0; i<7; i++) { + if(strcasecompare(check, what[0])) { + found = TRUE; + break; + } + what++; + } + return found?i:-1; +} + +static int checkmonth(const char *check) +{ + int i; + const char * const *what; + bool found = FALSE; + + what = &Curl_month[0]; + for(i = 0; i<12; i++) { + if(strcasecompare(check, what[0])) { + found = TRUE; + break; + } + what++; + } + return found?i:-1; /* return the offset or -1, no real offset is -1 */ +} + +/* return the time zone offset between GMT and the input one, in number + of seconds or -1 if the timezone wasn't found/legal */ + +static int checktz(const char *check) +{ + unsigned int i; + const struct tzinfo *what; + bool found = FALSE; + + what = tz; + for(i = 0; i< sizeof(tz)/sizeof(tz[0]); i++) { + if(strcasecompare(check, what->name)) { + found = TRUE; + break; + } + what++; + } + return found?what->offset*60:-1; +} + +static void skip(const char **date) +{ + /* skip everything that aren't letters or digits */ + while(**date && !ISALNUM(**date)) + (*date)++; +} + +enum assume { + DATE_MDAY, + DATE_YEAR, + DATE_TIME +}; + +/* this is a clone of 'struct tm' but with all fields we don't need or use + cut out */ +struct my_tm { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; /* full year */ +}; + +/* struct tm to time since epoch in GMT time zone. + * This is similar to the standard mktime function but for GMT only, and + * doesn't suffer from the various bugs and portability problems that + * some systems' implementations have. + * + * Returns 0 on success, otherwise non-zero. + */ +static void my_timegm(struct my_tm *tm, time_t *t) +{ + static const int month_days_cumulative [12] = + { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; + int month_, year, leap_days; + + year = tm->tm_year; + month_ = tm->tm_mon; + if(month_ < 0) { + year += (11 - month_) / 12; + month_ = 11 - (11 - month_) % 12; + } + else if(month_ >= 12) { + year -= month_ / 12; + month_ = month_ % 12; + } + + leap_days = year - (tm->tm_mon <= 1); + leap_days = ((leap_days / 4) - (leap_days / 100) + (leap_days / 400) + - (1969 / 4) + (1969 / 100) - (1969 / 400)); + + *t = ((((time_t) (year - 1970) * 365 + + leap_days + month_days_cumulative[month_] + tm->tm_mday - 1) * 24 + + tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec; +} + +/* + * parsedate() + * + * Returns: + * + * PARSEDATE_OK - a fine conversion + * PARSEDATE_FAIL - failed to convert + * PARSEDATE_LATER - time overflow at the far end of time_t + * PARSEDATE_SOONER - time underflow at the low end of time_t + */ + +static int parsedate(const char *date, time_t *output) +{ + time_t t = 0; + int wdaynum = -1; /* day of the week number, 0-6 (mon-sun) */ + int monnum = -1; /* month of the year number, 0-11 */ + int mdaynum = -1; /* day of month, 1 - 31 */ + int hournum = -1; + int minnum = -1; + int secnum = -1; + int yearnum = -1; + int tzoff = -1; + struct my_tm tm; + enum assume dignext = DATE_MDAY; + const char *indate = date; /* save the original pointer */ + int part = 0; /* max 6 parts */ + + while(*date && (part < 6)) { + bool found = FALSE; + + skip(&date); + + if(ISALPHA(*date)) { + /* a name coming up */ + char buf[32]=""; + size_t len; + if(sscanf(date, "%31[ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz]", buf)) + len = strlen(buf); + else + len = 0; + + if(wdaynum == -1) { + wdaynum = checkday(buf, len); + if(wdaynum != -1) + found = TRUE; + } + if(!found && (monnum == -1)) { + monnum = checkmonth(buf); + if(monnum != -1) + found = TRUE; + } + + if(!found && (tzoff == -1)) { + /* this just must be a time zone string */ + tzoff = checktz(buf); + if(tzoff != -1) + found = TRUE; + } + + if(!found) + return PARSEDATE_FAIL; /* bad string */ + + date += len; + } + else if(ISDIGIT(*date)) { + /* a digit */ + int val; + char *end; + int len = 0; + if((secnum == -1) && + (3 == sscanf(date, "%02d:%02d:%02d%n", + &hournum, &minnum, &secnum, &len))) { + /* time stamp! */ + date += len; + } + else if((secnum == -1) && + (2 == sscanf(date, "%02d:%02d%n", &hournum, &minnum, &len))) { + /* time stamp without seconds */ + date += len; + secnum = 0; + } + else { + long lval; + int error; + int old_errno; + + old_errno = errno; + errno = 0; + lval = strtol(date, &end, 10); + error = errno; + if(errno != old_errno) + errno = old_errno; + + if(error) + return PARSEDATE_FAIL; + +#if LONG_MAX != INT_MAX + if((lval > (long)INT_MAX) || (lval < (long)INT_MIN)) + return PARSEDATE_FAIL; +#endif + + val = mbgl_curlx_sltosi(lval); + + if((tzoff == -1) && + ((end - date) == 4) && + (val <= 1400) && + (indate< date) && + ((date[-1] == '+' || date[-1] == '-'))) { + /* four digits and a value less than or equal to 1400 (to take into + account all sorts of funny time zone diffs) and it is preceded + with a plus or minus. This is a time zone indication. 1400 is + picked since +1300 is frequently used and +1400 is mentioned as + an edge number in the document "ISO C 200X Proposal: Timezone + Functions" at http://david.tribble.com/text/c0xtimezone.html If + anyone has a more authoritative source for the exact maximum time + zone offsets, please speak up! */ + found = TRUE; + tzoff = (val/100 * 60 + val%100)*60; + + /* the + and - prefix indicates the local time compared to GMT, + this we need their reversed math to get what we want */ + tzoff = date[-1]=='+'?-tzoff:tzoff; + } + + if(((end - date) == 8) && + (yearnum == -1) && + (monnum == -1) && + (mdaynum == -1)) { + /* 8 digits, no year, month or day yet. This is YYYYMMDD */ + found = TRUE; + yearnum = val/10000; + monnum = (val%10000)/100-1; /* month is 0 - 11 */ + mdaynum = val%100; + } + + if(!found && (dignext == DATE_MDAY) && (mdaynum == -1)) { + if((val > 0) && (val<32)) { + mdaynum = val; + found = TRUE; + } + dignext = DATE_YEAR; + } + + if(!found && (dignext == DATE_YEAR) && (yearnum == -1)) { + yearnum = val; + found = TRUE; + if(yearnum < 100) { + if(yearnum > 70) + yearnum += 1900; + else + yearnum += 2000; + } + if(mdaynum == -1) + dignext = DATE_MDAY; + } + + if(!found) + return PARSEDATE_FAIL; + + date = end; + } + } + + part++; + } + + if(-1 == secnum) + secnum = minnum = hournum = 0; /* no time, make it zero */ + + if((-1 == mdaynum) || + (-1 == monnum) || + (-1 == yearnum)) + /* lacks vital info, fail */ + return PARSEDATE_FAIL; + + if(yearnum < 1970) { + /* only positive numbers cannot return earlier */ + *output = TIME_T_MIN; + return PARSEDATE_SOONER; + } + + /* a signed 32 bit time_t can only hold dates to the beginning of 2038 */ + if(yearnum > 2037) { + *output = TIME_T_MAX; + return PARSEDATE_LATER; + } + + if((mdaynum > 31) || (monnum > 11) || + (hournum > 23) || (minnum > 59) || (secnum > 60)) + return PARSEDATE_FAIL; /* clearly an illegal date */ + + tm.tm_sec = secnum; + tm.tm_min = minnum; + tm.tm_hour = hournum; + tm.tm_mday = mdaynum; + tm.tm_mon = monnum; + tm.tm_year = yearnum; + + /* my_timegm() returns a time_t. time_t is often 32 bits, sometimes even on + architectures that feature 64 bit 'long' but ultimately time_t is the + correct data type to use. + */ + my_timegm(&tm, &t); + + /* Add the time zone diff between local time zone and GMT. */ + if(tzoff == -1) + tzoff = 0; + + if((tzoff > 0) && (t > TIME_T_MAX - tzoff)) { + *output = TIME_T_MAX; + return PARSEDATE_LATER; /* time_t overflow */ + } + + t += tzoff; + + *output = t; + + return PARSEDATE_OK; +} + +time_t parse_date(const char *p) +{ + time_t parsed = -1; + int rc = parsedate(p, &parsed); + + if(rc == PARSEDATE_OK) { + if(parsed == -1) + /* avoid returning -1 for a working scenario */ + parsed++; + return parsed; + } + /* everything else is fail */ + return -1; +} + +#ifdef __cplusplus +} +#endif diff --git a/vendor/parsedate/parsedate/parsedate.hpp b/vendor/parsedate/parsedate/parsedate.hpp new file mode 100644 index 0000000000..40bfccb7a0 --- /dev/null +++ b/vendor/parsedate/parsedate/parsedate.hpp @@ -0,0 +1,35 @@ +#pragma once +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + + +#ifdef __cplusplus +extern "C" { +#endif + +#include <time.h> + +time_t parse_date(const char *p); + +#ifdef __cplusplus +} +#endif |