summaryrefslogtreecommitdiff
path: root/vendor
diff options
context:
space:
mode:
authorThiago Marcos P. Santos <tmpsantos@gmail.com>2020-02-26 16:08:23 +0200
committerThiago Marcos P. Santos <tmpsantos@gmail.com>2020-02-27 18:19:31 +0200
commit427d785848ba1cbf8df095ebe75c8731f30dfb5e (patch)
tree317eb2ba3ba7078f13f00cd83a0368d76f6b949f /vendor
parent242b719f0cbb24b485e439edd0da5aedee87f444 (diff)
downloadqtlocation-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.cmake27
-rw-r--r--vendor/csscolorparser/LICENSE20
-rw-r--r--vendor/csscolorparser/csscolorparser.cpp288
-rw-r--r--vendor/csscolorparser/csscolorparser/csscolorparser.hpp57
-rw-r--r--vendor/parsedate.cmake27
-rw-r--r--vendor/parsedate/COPYING22
-rw-r--r--vendor/parsedate/parsedate.cpp682
-rw-r--r--vendor/parsedate/parsedate/parsedate.hpp35
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