Updated jwt-cpp library.
This commit is contained in:
@@ -113,6 +113,11 @@ file(GLOB lib_files ${lib_files} ${PROJECT_LIB_DIR}/picojson/*.h)
|
||||
include_directories(${PROJECT_LIB_DIR}/jwt-cpp)
|
||||
file(GLOB lib_files ${lib_files} ${PROJECT_LIB_DIR}/jwt-cpp/*.h)
|
||||
|
||||
set(JWT_JSON_TRAITS_OPTIONS boost-json danielaparker-jsoncons kazuho-picojson nlohmann-json)
|
||||
foreach(traits ${JWT_JSON_TRAITS_OPTIONS})
|
||||
list(APPEND lib_files ${PROJECT_LIB_DIR}/jwt-cpp/traits/${traits}/defaults.h ${PROJECT_LIB_DIR}/jwt-cpp/traits/${traits}/traits.h)
|
||||
endforeach()
|
||||
|
||||
# Find boost
|
||||
#------------------------------------------------------------------------------
|
||||
find_package(Boost 1.62.0 REQUIRED COMPONENTS)
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#ifndef JWT_CPP_BASE_H
|
||||
#define JWT_CPP_BASE_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#ifdef __has_cpp_attribute
|
||||
#if __has_cpp_attribute(fallthrough)
|
||||
@@ -13,67 +18,128 @@
|
||||
#endif
|
||||
|
||||
namespace jwt {
|
||||
/**
|
||||
* \brief character maps when encoding and decoding
|
||||
*/
|
||||
namespace alphabet {
|
||||
/**
|
||||
* \brief valid list of character when working with [Base64](https://datatracker.ietf.org/doc/html/rfc4648#section-4)
|
||||
*
|
||||
* As directed in [X.509 Parameter](https://datatracker.ietf.org/doc/html/rfc7517#section-4.7) certificate chains are
|
||||
* base64-encoded as per [Section 4 of RFC4648](https://datatracker.ietf.org/doc/html/rfc4648#section-4)
|
||||
*/
|
||||
struct base64 {
|
||||
static const std::array<char, 64>& data() {
|
||||
static std::array<char, 64> data = {
|
||||
static constexpr std::array<char, 64> data{
|
||||
{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||||
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
|
||||
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
||||
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'}};
|
||||
return data;
|
||||
};
|
||||
}
|
||||
static const std::string& fill() {
|
||||
static std::string fill = "=";
|
||||
static std::string fill{"="};
|
||||
return fill;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* \brief valid list of character when working with [Base64URL](https://tools.ietf.org/html/rfc4648#section-5)
|
||||
*
|
||||
* As directed by [RFC 7519 Terminology](https://datatracker.ietf.org/doc/html/rfc7519#section-2) set the definition of Base64URL
|
||||
* encoding as that in [RFC 7515](https://datatracker.ietf.org/doc/html/rfc7515#section-2) that states:
|
||||
*
|
||||
* > Base64 encoding using the URL- and filename-safe character set defined in
|
||||
* > [Section 5 of RFC 4648 RFC4648](https://tools.ietf.org/html/rfc4648#section-5), with all trailing '=' characters omitted
|
||||
*/
|
||||
struct base64url {
|
||||
static const std::array<char, 64>& data() {
|
||||
static std::array<char, 64> data = {
|
||||
static constexpr std::array<char, 64> data{
|
||||
{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||||
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
|
||||
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
||||
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'}};
|
||||
return data;
|
||||
};
|
||||
}
|
||||
static const std::string& fill() {
|
||||
static std::string fill = "%3d";
|
||||
static std::string fill{"%3d"};
|
||||
return fill;
|
||||
}
|
||||
};
|
||||
namespace helper {
|
||||
/**
|
||||
* @brief A General purpose base64url alphabet respecting the
|
||||
* [URI Case Normalization](https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2.1)
|
||||
*
|
||||
* This is useful in situations outside of JWT encoding/decoding and is provided as a helper
|
||||
*/
|
||||
struct base64url_percent_encoding {
|
||||
static const std::array<char, 64>& data() {
|
||||
static constexpr std::array<char, 64> data{
|
||||
{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||||
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
|
||||
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
||||
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'}};
|
||||
return data;
|
||||
}
|
||||
static const std::initializer_list<std::string>& fill() {
|
||||
static std::initializer_list<std::string> fill{"%3D", "%3d"};
|
||||
return fill;
|
||||
}
|
||||
};
|
||||
} // namespace helper
|
||||
|
||||
inline uint32_t index(const std::array<char, 64>& alphabet, char symbol) {
|
||||
auto itr = std::find_if(alphabet.cbegin(), alphabet.cend(), [symbol](char c) { return c == symbol; });
|
||||
if (itr == alphabet.cend()) { throw std::runtime_error("Invalid input: not within alphabet"); }
|
||||
|
||||
return std::distance(alphabet.cbegin(), itr);
|
||||
}
|
||||
} // namespace alphabet
|
||||
|
||||
/**
|
||||
* \brief A collection of fellable functions for working with base64 and base64url
|
||||
*/
|
||||
namespace base {
|
||||
|
||||
namespace details {
|
||||
struct padding {
|
||||
size_t count = 0;
|
||||
size_t length = 0;
|
||||
|
||||
padding() = default;
|
||||
padding(size_t count, size_t length) : count(count), length(length) {}
|
||||
|
||||
padding operator+(const padding& p) { return padding(count + p.count, length + p.length); }
|
||||
|
||||
friend bool operator==(const padding& lhs, const padding& rhs) {
|
||||
return lhs.count == rhs.count && lhs.length == rhs.length;
|
||||
}
|
||||
};
|
||||
|
||||
inline padding count_padding(const std::string& base, const std::vector<std::string>& fills) {
|
||||
for (const auto& fill : fills) {
|
||||
if (base.size() < fill.size()) continue;
|
||||
// Does the end of the input exactly match the fill pattern?
|
||||
if (base.substr(base.size() - fill.size()) == fill) {
|
||||
return padding{1, fill.length()} +
|
||||
count_padding(base.substr(0, base.size() - fill.size()), fills);
|
||||
}
|
||||
}
|
||||
|
||||
class base {
|
||||
public:
|
||||
template<typename T>
|
||||
static std::string encode(const std::string& bin) {
|
||||
return encode(bin, T::data(), T::fill());
|
||||
}
|
||||
template<typename T>
|
||||
static std::string decode(const std::string& base) {
|
||||
return decode(base, T::data(), T::fill());
|
||||
}
|
||||
template<typename T>
|
||||
static std::string pad(const std::string& base) {
|
||||
return pad(base, T::fill());
|
||||
}
|
||||
template<typename T>
|
||||
static std::string trim(const std::string& base) {
|
||||
return trim(base, T::fill());
|
||||
return {};
|
||||
}
|
||||
|
||||
private:
|
||||
static std::string encode(const std::string& bin, const std::array<char, 64>& alphabet, const std::string& fill) {
|
||||
inline std::string encode(const std::string& bin, const std::array<char, 64>& alphabet,
|
||||
const std::string& fill) {
|
||||
size_t size = bin.size();
|
||||
std::string res;
|
||||
|
||||
// clear incomplete bytes
|
||||
size_t fast_size = size - size % 3;
|
||||
for (size_t i = 0; i < fast_size;) {
|
||||
uint32_t octet_a = (unsigned char)bin[i++];
|
||||
uint32_t octet_b = (unsigned char)bin[i++];
|
||||
uint32_t octet_c = (unsigned char)bin[i++];
|
||||
uint32_t octet_a = static_cast<unsigned char>(bin[i++]);
|
||||
uint32_t octet_b = static_cast<unsigned char>(bin[i++]);
|
||||
uint32_t octet_c = static_cast<unsigned char>(bin[i++]);
|
||||
|
||||
uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
|
||||
|
||||
@@ -83,14 +149,13 @@ namespace jwt {
|
||||
res += alphabet[(triple >> 0 * 6) & 0x3F];
|
||||
}
|
||||
|
||||
if (fast_size == size)
|
||||
return res;
|
||||
if (fast_size == size) return res;
|
||||
|
||||
size_t mod = size % 3;
|
||||
|
||||
uint32_t octet_a = fast_size < size ? (unsigned char)bin[fast_size++] : 0;
|
||||
uint32_t octet_b = fast_size < size ? (unsigned char)bin[fast_size++] : 0;
|
||||
uint32_t octet_c = fast_size < size ? (unsigned char)bin[fast_size++] : 0;
|
||||
uint32_t octet_a = fast_size < size ? static_cast<unsigned char>(bin[fast_size++]) : 0;
|
||||
uint32_t octet_b = fast_size < size ? static_cast<unsigned char>(bin[fast_size++]) : 0;
|
||||
uint32_t octet_c = fast_size < size ? static_cast<unsigned char>(bin[fast_size++]) : 0;
|
||||
|
||||
uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
|
||||
|
||||
@@ -107,42 +172,25 @@ namespace jwt {
|
||||
res += alphabet[(triple >> 1 * 6) & 0x3F];
|
||||
res += fill;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static std::string decode(const std::string& base, const std::array<char, 64>& alphabet, const std::string& fill) {
|
||||
size_t size = base.size();
|
||||
inline std::string decode(const std::string& base, const std::array<char, 64>& alphabet,
|
||||
const std::vector<std::string>& fill) {
|
||||
const auto pad = count_padding(base, fill);
|
||||
if (pad.count > 2) throw std::runtime_error("Invalid input: too much fill");
|
||||
|
||||
size_t fill_cnt = 0;
|
||||
while (size > fill.size()) {
|
||||
if (base.substr(size - fill.size(), fill.size()) == fill) {
|
||||
fill_cnt++;
|
||||
size -= fill.size();
|
||||
if(fill_cnt > 2)
|
||||
throw std::runtime_error("Invalid input");
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
if ((size + fill_cnt) % 4 != 0)
|
||||
throw std::runtime_error("Invalid input");
|
||||
const size_t size = base.size() - pad.length;
|
||||
if ((size + pad.count) % 4 != 0) throw std::runtime_error("Invalid input: incorrect total size");
|
||||
|
||||
size_t out_size = size / 4 * 3;
|
||||
std::string res;
|
||||
res.reserve(out_size);
|
||||
|
||||
auto get_sextet = [&](size_t offset) {
|
||||
for (size_t i = 0; i < alphabet.size(); i++) {
|
||||
if (alphabet[i] == base[offset])
|
||||
return static_cast<uint32_t>(i);
|
||||
}
|
||||
throw std::runtime_error("Invalid input");
|
||||
};
|
||||
|
||||
auto get_sextet = [&](size_t offset) { return alphabet::index(alphabet, base[offset]); };
|
||||
|
||||
size_t fast_size = size - size % 4;
|
||||
for (size_t i = 0; i < fast_size;) {
|
||||
@@ -151,60 +199,71 @@ namespace jwt {
|
||||
uint32_t sextet_c = get_sextet(i++);
|
||||
uint32_t sextet_d = get_sextet(i++);
|
||||
|
||||
uint32_t triple = (sextet_a << 3 * 6)
|
||||
+ (sextet_b << 2 * 6)
|
||||
+ (sextet_c << 1 * 6)
|
||||
+ (sextet_d << 0 * 6);
|
||||
uint32_t triple =
|
||||
(sextet_a << 3 * 6) + (sextet_b << 2 * 6) + (sextet_c << 1 * 6) + (sextet_d << 0 * 6);
|
||||
|
||||
res += (triple >> 2 * 8) & 0xFF;
|
||||
res += (triple >> 1 * 8) & 0xFF;
|
||||
res += (triple >> 0 * 8) & 0xFF;
|
||||
res += static_cast<char>((triple >> 2 * 8) & 0xFFU);
|
||||
res += static_cast<char>((triple >> 1 * 8) & 0xFFU);
|
||||
res += static_cast<char>((triple >> 0 * 8) & 0xFFU);
|
||||
}
|
||||
|
||||
if (fill_cnt == 0)
|
||||
return res;
|
||||
if (pad.count == 0) return res;
|
||||
|
||||
uint32_t triple = (get_sextet(fast_size) << 3 * 6)
|
||||
+ (get_sextet(fast_size + 1) << 2 * 6);
|
||||
uint32_t triple = (get_sextet(fast_size) << 3 * 6) + (get_sextet(fast_size + 1) << 2 * 6);
|
||||
|
||||
switch (fill_cnt) {
|
||||
switch (pad.count) {
|
||||
case 1:
|
||||
triple |= (get_sextet(fast_size + 2) << 1 * 6);
|
||||
res += (triple >> 2 * 8) & 0xFF;
|
||||
res += (triple >> 1 * 8) & 0xFF;
|
||||
break;
|
||||
case 2:
|
||||
res += (triple >> 2 * 8) & 0xFF;
|
||||
break;
|
||||
default:
|
||||
res += static_cast<char>((triple >> 2 * 8) & 0xFFU);
|
||||
res += static_cast<char>((triple >> 1 * 8) & 0xFFU);
|
||||
break;
|
||||
case 2: res += static_cast<char>((triple >> 2 * 8) & 0xFFU); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static std::string pad(const std::string& base, const std::string& fill) {
|
||||
inline std::string decode(const std::string& base, const std::array<char, 64>& alphabet,
|
||||
const std::string& fill) {
|
||||
return decode(base, alphabet, std::vector<std::string>{fill});
|
||||
}
|
||||
|
||||
inline std::string pad(const std::string& base, const std::string& fill) {
|
||||
std::string padding;
|
||||
switch (base.size() % 4) {
|
||||
case 1:
|
||||
padding += fill;
|
||||
JWT_FALLTHROUGH;
|
||||
case 2:
|
||||
padding += fill;
|
||||
JWT_FALLTHROUGH;
|
||||
case 3:
|
||||
padding += fill;
|
||||
JWT_FALLTHROUGH;
|
||||
default:
|
||||
break;
|
||||
case 1: padding += fill; JWT_FALLTHROUGH;
|
||||
case 2: padding += fill; JWT_FALLTHROUGH;
|
||||
case 3: padding += fill; JWT_FALLTHROUGH;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return base + padding;
|
||||
}
|
||||
|
||||
static std::string trim(const std::string& base, const std::string& fill) {
|
||||
inline std::string trim(const std::string& base, const std::string& fill) {
|
||||
auto pos = base.find(fill);
|
||||
return base.substr(0, pos);
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace details
|
||||
|
||||
template<typename T>
|
||||
std::string encode(const std::string& bin) {
|
||||
return details::encode(bin, T::data(), T::fill());
|
||||
}
|
||||
template<typename T>
|
||||
std::string decode(const std::string& base) {
|
||||
return details::decode(base, T::data(), T::fill());
|
||||
}
|
||||
template<typename T>
|
||||
std::string pad(const std::string& base) {
|
||||
return details::pad(base, T::fill());
|
||||
}
|
||||
template<typename T>
|
||||
std::string trim(const std::string& base) {
|
||||
return details::trim(base, T::fill());
|
||||
}
|
||||
} // namespace base
|
||||
} // namespace jwt
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
88
src/lib/jwt-cpp/traits/boost-json/defaults.h
Normal file
88
src/lib/jwt-cpp/traits/boost-json/defaults.h
Normal file
@@ -0,0 +1,88 @@
|
||||
#ifndef JWT_CPP_BOOST_JSON_DEFAULTS_H
|
||||
#define JWT_CPP_BOOST_JSON_DEFAULTS_H
|
||||
|
||||
#ifndef JWT_DISABLE_PICOJSON
|
||||
#define JWT_DISABLE_PICOJSON
|
||||
#endif
|
||||
|
||||
#include "traits.h"
|
||||
|
||||
namespace jwt {
|
||||
/**
|
||||
* \brief a class to store a generic [Boost.JSON](https://github.com/boostorg/json) value as claim
|
||||
*
|
||||
* This type is the specialization of the \ref basic_claim class which
|
||||
* uses the standard template types.
|
||||
*/
|
||||
using claim = basic_claim<traits::boost_json>;
|
||||
|
||||
/**
|
||||
* Create a verifier using the default clock
|
||||
* \return verifier instance
|
||||
*/
|
||||
inline verifier<default_clock, traits::boost_json> verify() {
|
||||
return verify<default_clock, traits::boost_json>(default_clock{});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a builder instance to create a new token
|
||||
*/
|
||||
inline builder<traits::boost_json> create() { return builder<traits::boost_json>(); }
|
||||
|
||||
#ifndef JWT_DISABLE_BASE64
|
||||
/**
|
||||
* Decode a token
|
||||
* \param token Token to decode
|
||||
* \return Decoded token
|
||||
* \throw std::invalid_argument Token is not in correct format
|
||||
* \throw std::runtime_error Base64 decoding failed or invalid json
|
||||
*/
|
||||
inline decoded_jwt<traits::boost_json> decode(const std::string& token) {
|
||||
return decoded_jwt<traits::boost_json>(token);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Decode a token
|
||||
* \tparam Decode is callabled, taking a string_type and returns a string_type.
|
||||
* It should ensure the padding of the input and then base64url decode and
|
||||
* return the results.
|
||||
* \param token Token to decode
|
||||
* \param decode The token to parse
|
||||
* \return Decoded token
|
||||
* \throw std::invalid_argument Token is not in correct format
|
||||
* \throw std::runtime_error Base64 decoding failed or invalid json
|
||||
*/
|
||||
template<typename Decode>
|
||||
decoded_jwt<traits::boost_json> decode(const std::string& token, Decode decode) {
|
||||
return decoded_jwt<traits::boost_json>(token, decode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a jwk
|
||||
* \param token JWK Token to parse
|
||||
* \return Parsed JWK
|
||||
* \throw std::runtime_error Token is not in correct format
|
||||
*/
|
||||
inline jwk<traits::boost_json> parse_jwk(const traits::boost_json::string_type& token) {
|
||||
return jwk<traits::boost_json>(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a jwks
|
||||
* \param token JWKs Token to parse
|
||||
* \return Parsed JWKs
|
||||
* \throw std::runtime_error Token is not in correct format
|
||||
*/
|
||||
inline jwks<traits::boost_json> parse_jwks(const traits::boost_json::string_type& token) {
|
||||
return jwks<traits::boost_json>(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* This type is the specialization of the \ref verify_ops::verify_context class which
|
||||
* uses the standard template types.
|
||||
*/
|
||||
using verify_context = verify_ops::verify_context<traits::boost_json>;
|
||||
} // namespace jwt
|
||||
|
||||
#endif // JWT_CPP_BOOST_JSON_DEFAULTS_H
|
||||
80
src/lib/jwt-cpp/traits/boost-json/traits.h
Normal file
80
src/lib/jwt-cpp/traits/boost-json/traits.h
Normal file
@@ -0,0 +1,80 @@
|
||||
#ifndef JWT_CPP_BOOSTJSON_TRAITS_H
|
||||
#define JWT_CPP_BOOSTJSON_TRAITS_H
|
||||
|
||||
#define JWT_DISABLE_PICOJSON
|
||||
#include "jwt-cpp/jwt.h"
|
||||
|
||||
#include <boost/json.hpp>
|
||||
// if not boost JSON standalone then error...
|
||||
|
||||
namespace jwt {
|
||||
namespace traits {
|
||||
namespace json = boost::json;
|
||||
struct boost_json {
|
||||
using value_type = json::value;
|
||||
using object_type = json::object;
|
||||
using array_type = json::array;
|
||||
using string_type = std::string;
|
||||
using number_type = double;
|
||||
using integer_type = std::int64_t;
|
||||
using boolean_type = bool;
|
||||
|
||||
static jwt::json::type get_type(const value_type& val) {
|
||||
using jwt::json::type;
|
||||
|
||||
if (val.kind() == json::kind::bool_) return type::boolean;
|
||||
if (val.kind() == json::kind::int64) return type::integer;
|
||||
if (val.kind() == json::kind::uint64) // boost internally tracks two types of integers
|
||||
return type::integer;
|
||||
if (val.kind() == json::kind::double_) return type::number;
|
||||
if (val.kind() == json::kind::string) return type::string;
|
||||
if (val.kind() == json::kind::array) return type::array;
|
||||
if (val.kind() == json::kind::object) return type::object;
|
||||
|
||||
throw std::logic_error("invalid type");
|
||||
}
|
||||
|
||||
static object_type as_object(const value_type& val) {
|
||||
if (val.kind() != json::kind::object) throw std::bad_cast();
|
||||
return val.get_object();
|
||||
}
|
||||
|
||||
static array_type as_array(const value_type& val) {
|
||||
if (val.kind() != json::kind::array) throw std::bad_cast();
|
||||
return val.get_array();
|
||||
}
|
||||
|
||||
static string_type as_string(const value_type& val) {
|
||||
if (val.kind() != json::kind::string) throw std::bad_cast();
|
||||
return string_type{val.get_string()};
|
||||
}
|
||||
|
||||
static integer_type as_integer(const value_type& val) {
|
||||
switch (val.kind()) {
|
||||
case json::kind::int64: return val.get_int64();
|
||||
case json::kind::uint64: return static_cast<int64_t>(val.get_uint64());
|
||||
default: throw std::bad_cast();
|
||||
}
|
||||
}
|
||||
|
||||
static boolean_type as_boolean(const value_type& val) {
|
||||
if (val.kind() != json::kind::bool_) throw std::bad_cast();
|
||||
return val.get_bool();
|
||||
}
|
||||
|
||||
static number_type as_number(const value_type& val) {
|
||||
if (val.kind() != json::kind::double_) throw std::bad_cast();
|
||||
return val.get_double();
|
||||
}
|
||||
|
||||
static bool parse(value_type& val, string_type str) {
|
||||
val = json::parse(str);
|
||||
return true;
|
||||
}
|
||||
|
||||
static std::string serialize(const value_type& val) { return json::serialize(val); }
|
||||
};
|
||||
} // namespace traits
|
||||
} // namespace jwt
|
||||
|
||||
#endif // JWT_CPP_BOOSTJSON_TRAITS_H
|
||||
88
src/lib/jwt-cpp/traits/danielaparker-jsoncons/defaults.h
Normal file
88
src/lib/jwt-cpp/traits/danielaparker-jsoncons/defaults.h
Normal file
@@ -0,0 +1,88 @@
|
||||
#ifndef JWT_CPP_DANIELAPARKER_JSONCONS_DEFAULTS_H
|
||||
#define JWT_CPP_DANIELAPARKER_JSONCONS_DEFAULTS_H
|
||||
|
||||
#ifndef JWT_DISABLE_PICOJSON
|
||||
#define JWT_DISABLE_PICOJSON
|
||||
#endif
|
||||
|
||||
#include "traits.h"
|
||||
|
||||
namespace jwt {
|
||||
/**
|
||||
* \brief a class to store a generic [jsoncons](https://github.com/danielaparker/jsoncons) value as claim
|
||||
*
|
||||
* This type is the specialization of the \ref basic_claim class which
|
||||
* uses the standard template types.
|
||||
*/
|
||||
using claim = basic_claim<traits::danielaparker_jsoncons>;
|
||||
|
||||
/**
|
||||
* Create a verifier using the default clock
|
||||
* \return verifier instance
|
||||
*/
|
||||
inline verifier<default_clock, traits::danielaparker_jsoncons> verify() {
|
||||
return verify<default_clock, traits::danielaparker_jsoncons>(default_clock{});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a builder instance to create a new token
|
||||
*/
|
||||
inline builder<traits::danielaparker_jsoncons> create() { return builder<traits::danielaparker_jsoncons>(); }
|
||||
|
||||
#ifndef JWT_DISABLE_BASE64
|
||||
/**
|
||||
* Decode a token
|
||||
* \param token Token to decode
|
||||
* \return Decoded token
|
||||
* \throw std::invalid_argument Token is not in correct format
|
||||
* \throw std::runtime_error Base64 decoding failed or invalid json
|
||||
*/
|
||||
inline decoded_jwt<traits::danielaparker_jsoncons> decode(const std::string& token) {
|
||||
return decoded_jwt<traits::danielaparker_jsoncons>(token);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Decode a token
|
||||
* \tparam Decode is callabled, taking a string_type and returns a string_type.
|
||||
* It should ensure the padding of the input and then base64url decode and
|
||||
* return the results.
|
||||
* \param token Token to decode
|
||||
* \param decode The token to parse
|
||||
* \return Decoded token
|
||||
* \throw std::invalid_argument Token is not in correct format
|
||||
* \throw std::runtime_error Base64 decoding failed or invalid json
|
||||
*/
|
||||
template<typename Decode>
|
||||
decoded_jwt<traits::danielaparker_jsoncons> decode(const std::string& token, Decode decode) {
|
||||
return decoded_jwt<traits::danielaparker_jsoncons>(token, decode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a jwk
|
||||
* \param token JWK Token to parse
|
||||
* \return Parsed JWK
|
||||
* \throw std::runtime_error Token is not in correct format
|
||||
*/
|
||||
inline jwk<traits::danielaparker_jsoncons> parse_jwk(const traits::danielaparker_jsoncons::string_type& token) {
|
||||
return jwk<traits::danielaparker_jsoncons>(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a jwks
|
||||
* \param token JWKs Token to parse
|
||||
* \return Parsed JWKs
|
||||
* \throw std::runtime_error Token is not in correct format
|
||||
*/
|
||||
inline jwks<traits::danielaparker_jsoncons> parse_jwks(const traits::danielaparker_jsoncons::string_type& token) {
|
||||
return jwks<traits::danielaparker_jsoncons>(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* This type is the specialization of the \ref verify_ops::verify_context class which
|
||||
* uses the standard template types.
|
||||
*/
|
||||
using verify_context = verify_ops::verify_context<traits::danielaparker_jsoncons>;
|
||||
} // namespace jwt
|
||||
|
||||
#endif // JWT_CPP_DANIELAPARKER_JSONCONS_DEFAULTS_H
|
||||
123
src/lib/jwt-cpp/traits/danielaparker-jsoncons/traits.h
Normal file
123
src/lib/jwt-cpp/traits/danielaparker-jsoncons/traits.h
Normal file
@@ -0,0 +1,123 @@
|
||||
#define JWT_DISABLE_PICOJSON
|
||||
#define JSONCONS_NO_DEPRECATED
|
||||
|
||||
#include "jwt-cpp/jwt.h"
|
||||
|
||||
#include "jsoncons/json.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace jwt {
|
||||
namespace traits {
|
||||
struct danielaparker_jsoncons {
|
||||
// Needs at least https://github.com/danielaparker/jsoncons/commit/28c56b90ec7337f98a5b8942574590111a5e5831
|
||||
static_assert(jsoncons::version().minor >= 167, "A higher version of jsoncons is required!");
|
||||
|
||||
using json = jsoncons::json;
|
||||
using value_type = json;
|
||||
struct object_type : json::object {
|
||||
// Add missing C++11 member types
|
||||
// https://github.com/danielaparker/jsoncons/commit/1b1ceeb572f9a2db6d37cff47ac78a4f14e072e2#commitcomment-45391411
|
||||
using value_type = key_value_type; // Enable optional jwt-cpp methods
|
||||
using mapped_type = key_value_type::value_type;
|
||||
using size_type = size_t; // for implementing count
|
||||
|
||||
object_type() = default;
|
||||
object_type(const object_type&) = default;
|
||||
explicit object_type(const json::object& o) : json::object(o) {}
|
||||
object_type(object_type&&) = default;
|
||||
explicit object_type(json::object&& o) : json::object(o) {}
|
||||
~object_type() = default;
|
||||
object_type& operator=(const object_type& o) = default;
|
||||
object_type& operator=(object_type&& o) noexcept = default;
|
||||
|
||||
// Add missing C++11 subscription operator
|
||||
mapped_type& operator[](const key_type& key) {
|
||||
// https://github.com/microsoft/STL/blob/2914b4301c59dc7ffc09d16ac6f7979fde2b7f2c/stl/inc/map#L325
|
||||
return try_emplace(key).first->value();
|
||||
}
|
||||
|
||||
// Add missing C++11 element access
|
||||
const mapped_type& at(const key_type& key) const {
|
||||
auto target = find(key);
|
||||
if (target != end()) return target->value();
|
||||
|
||||
throw std::out_of_range("invalid key");
|
||||
}
|
||||
|
||||
// Add missing C++11 lookup method
|
||||
size_type count(const key_type& key) const {
|
||||
struct compare {
|
||||
bool operator()(const value_type& val, const key_type& key) const { return val.key() < key; }
|
||||
bool operator()(const key_type& key, const value_type& val) const { return key < val.key(); }
|
||||
};
|
||||
|
||||
// https://en.cppreference.com/w/cpp/algorithm/binary_search#Complexity
|
||||
if (std::binary_search(this->begin(), this->end(), key, compare{})) return 1;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
using array_type = json::array;
|
||||
using string_type = std::string; // current limitation of traits implementation
|
||||
using number_type = double;
|
||||
using integer_type = int64_t;
|
||||
using boolean_type = bool;
|
||||
|
||||
static jwt::json::type get_type(const json& val) {
|
||||
using jwt::json::type;
|
||||
|
||||
if (val.type() == jsoncons::json_type::bool_value) return type::boolean;
|
||||
if (val.type() == jsoncons::json_type::int64_value) return type::integer;
|
||||
if (val.type() == jsoncons::json_type::uint64_value) return type::integer;
|
||||
if (val.type() == jsoncons::json_type::half_value) return type::number;
|
||||
if (val.type() == jsoncons::json_type::double_value) return type::number;
|
||||
if (val.type() == jsoncons::json_type::string_value) return type::string;
|
||||
if (val.type() == jsoncons::json_type::array_value) return type::array;
|
||||
if (val.type() == jsoncons::json_type::object_value) return type::object;
|
||||
|
||||
throw std::logic_error("invalid type");
|
||||
}
|
||||
|
||||
static object_type as_object(const json& val) {
|
||||
if (val.type() != jsoncons::json_type::object_value) throw std::bad_cast();
|
||||
return object_type(val.object_value());
|
||||
}
|
||||
|
||||
static array_type as_array(const json& val) {
|
||||
if (val.type() != jsoncons::json_type::array_value) throw std::bad_cast();
|
||||
return val.array_value();
|
||||
}
|
||||
|
||||
static string_type as_string(const json& val) {
|
||||
if (val.type() != jsoncons::json_type::string_value) throw std::bad_cast();
|
||||
return val.as_string();
|
||||
}
|
||||
|
||||
static number_type as_number(const json& val) {
|
||||
if (get_type(val) != jwt::json::type::number) throw std::bad_cast();
|
||||
return val.as_double();
|
||||
}
|
||||
|
||||
static integer_type as_integer(const json& val) {
|
||||
if (get_type(val) != jwt::json::type::integer) throw std::bad_cast();
|
||||
return val.as<integer_type>();
|
||||
}
|
||||
|
||||
static boolean_type as_boolean(const json& val) {
|
||||
if (val.type() != jsoncons::json_type::bool_value) throw std::bad_cast();
|
||||
return val.as_bool();
|
||||
}
|
||||
|
||||
static bool parse(json& val, const std::string& str) {
|
||||
val = json::parse(str);
|
||||
return true;
|
||||
}
|
||||
|
||||
static std::string serialize(const json& val) {
|
||||
std::ostringstream os;
|
||||
os << jsoncons::print(val);
|
||||
return os.str();
|
||||
}
|
||||
};
|
||||
} // namespace traits
|
||||
} // namespace jwt
|
||||
90
src/lib/jwt-cpp/traits/defaults.h.mustache
Normal file
90
src/lib/jwt-cpp/traits/defaults.h.mustache
Normal file
@@ -0,0 +1,90 @@
|
||||
#ifndef JWT_CPP_{{traits_name_upper}}_DEFAULTS_H
|
||||
#define JWT_CPP_{{traits_name_upper}}_DEFAULTS_H
|
||||
{{#disable_default_traits}}
|
||||
|
||||
#ifndef JWT_DISABLE_PICOJSON
|
||||
#define JWT_DISABLE_PICOJSON
|
||||
#endif
|
||||
{{/disable_default_traits}}
|
||||
|
||||
#include "traits.h"
|
||||
|
||||
namespace jwt {
|
||||
/**
|
||||
* \brief a class to store a generic [{{library_name}}]({{{library_url}}}) value as claim
|
||||
*
|
||||
* This type is the specialization of the \ref basic_claim class which
|
||||
* uses the standard template types.
|
||||
*/
|
||||
using claim = basic_claim<traits::{{traits_name}}>;
|
||||
|
||||
/**
|
||||
* Create a verifier using the default clock
|
||||
* \return verifier instance
|
||||
*/
|
||||
inline verifier<default_clock, traits::{{traits_name}}> verify() {
|
||||
return verify<default_clock, traits::{{traits_name}}>(default_clock{});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a builder instance to create a new token
|
||||
*/
|
||||
inline builder<traits::{{traits_name}}> create() { return builder<traits::{{traits_name}}>(); }
|
||||
|
||||
#ifndef JWT_DISABLE_BASE64
|
||||
/**
|
||||
* Decode a token
|
||||
* \param token Token to decode
|
||||
* \return Decoded token
|
||||
* \throw std::invalid_argument Token is not in correct format
|
||||
* \throw std::runtime_error Base64 decoding failed or invalid json
|
||||
*/
|
||||
inline decoded_jwt<traits::{{traits_name}}> decode(const std::string& token) {
|
||||
return decoded_jwt<traits::{{traits_name}}>(token);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Decode a token
|
||||
* \tparam Decode is callabled, taking a string_type and returns a string_type.
|
||||
* It should ensure the padding of the input and then base64url decode and
|
||||
* return the results.
|
||||
* \param token Token to decode
|
||||
* \param decode The token to parse
|
||||
* \return Decoded token
|
||||
* \throw std::invalid_argument Token is not in correct format
|
||||
* \throw std::runtime_error Base64 decoding failed or invalid json
|
||||
*/
|
||||
template<typename Decode>
|
||||
decoded_jwt<traits::{{traits_name}}> decode(const std::string& token, Decode decode) {
|
||||
return decoded_jwt<traits::{{traits_name}}>(token, decode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a jwk
|
||||
* \param token JWK Token to parse
|
||||
* \return Parsed JWK
|
||||
* \throw std::runtime_error Token is not in correct format
|
||||
*/
|
||||
inline jwk<traits::{{traits_name}}> parse_jwk(const traits::{{traits_name}}::string_type& token) {
|
||||
return jwk<traits::{{traits_name}}>(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a jwks
|
||||
* \param token JWKs Token to parse
|
||||
* \return Parsed JWKs
|
||||
* \throw std::runtime_error Token is not in correct format
|
||||
*/
|
||||
inline jwks<traits::{{traits_name}}> parse_jwks(const traits::{{traits_name}}::string_type& token) {
|
||||
return jwks<traits::{{traits_name}}>(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* This type is the specialization of the \ref verify_ops::verify_context class which
|
||||
* uses the standard template types.
|
||||
*/
|
||||
using verify_context = verify_ops::verify_context<traits::{{traits_name}}>;
|
||||
} // namespace jwt
|
||||
|
||||
#endif // JWT_CPP_{{traits_name_upper}}_DEFAULTS_H
|
||||
84
src/lib/jwt-cpp/traits/kazuho-picojson/defaults.h
Normal file
84
src/lib/jwt-cpp/traits/kazuho-picojson/defaults.h
Normal file
@@ -0,0 +1,84 @@
|
||||
#ifndef JWT_CPP_KAZUHO_PICOJSON_DEFAULTS_H
|
||||
#define JWT_CPP_KAZUHO_PICOJSON_DEFAULTS_H
|
||||
|
||||
#include "traits.h"
|
||||
|
||||
namespace jwt {
|
||||
/**
|
||||
* \brief a class to store a generic [picojson](https://github.com/kazuho/picojson) value as claim
|
||||
*
|
||||
* This type is the specialization of the \ref basic_claim class which
|
||||
* uses the standard template types.
|
||||
*/
|
||||
using claim = basic_claim<traits::kazuho_picojson>;
|
||||
|
||||
/**
|
||||
* Create a verifier using the default clock
|
||||
* \return verifier instance
|
||||
*/
|
||||
inline verifier<default_clock, traits::kazuho_picojson> verify() {
|
||||
return verify<default_clock, traits::kazuho_picojson>(default_clock{});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a builder instance to create a new token
|
||||
*/
|
||||
inline builder<traits::kazuho_picojson> create() { return builder<traits::kazuho_picojson>(); }
|
||||
|
||||
#ifndef JWT_DISABLE_BASE64
|
||||
/**
|
||||
* Decode a token
|
||||
* \param token Token to decode
|
||||
* \return Decoded token
|
||||
* \throw std::invalid_argument Token is not in correct format
|
||||
* \throw std::runtime_error Base64 decoding failed or invalid json
|
||||
*/
|
||||
inline decoded_jwt<traits::kazuho_picojson> decode(const std::string& token) {
|
||||
return decoded_jwt<traits::kazuho_picojson>(token);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Decode a token
|
||||
* \tparam Decode is callabled, taking a string_type and returns a string_type.
|
||||
* It should ensure the padding of the input and then base64url decode and
|
||||
* return the results.
|
||||
* \param token Token to decode
|
||||
* \param decode The token to parse
|
||||
* \return Decoded token
|
||||
* \throw std::invalid_argument Token is not in correct format
|
||||
* \throw std::runtime_error Base64 decoding failed or invalid json
|
||||
*/
|
||||
template<typename Decode>
|
||||
decoded_jwt<traits::kazuho_picojson> decode(const std::string& token, Decode decode) {
|
||||
return decoded_jwt<traits::kazuho_picojson>(token, decode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a jwk
|
||||
* \param token JWK Token to parse
|
||||
* \return Parsed JWK
|
||||
* \throw std::runtime_error Token is not in correct format
|
||||
*/
|
||||
inline jwk<traits::kazuho_picojson> parse_jwk(const traits::kazuho_picojson::string_type& token) {
|
||||
return jwk<traits::kazuho_picojson>(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a jwks
|
||||
* \param token JWKs Token to parse
|
||||
* \return Parsed JWKs
|
||||
* \throw std::runtime_error Token is not in correct format
|
||||
*/
|
||||
inline jwks<traits::kazuho_picojson> parse_jwks(const traits::kazuho_picojson::string_type& token) {
|
||||
return jwks<traits::kazuho_picojson>(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* This type is the specialization of the \ref verify_ops::verify_context class which
|
||||
* uses the standard template types.
|
||||
*/
|
||||
using verify_context = verify_ops::verify_context<traits::kazuho_picojson>;
|
||||
} // namespace jwt
|
||||
|
||||
#endif // JWT_CPP_KAZUHO_PICOJSON_DEFAULTS_H
|
||||
76
src/lib/jwt-cpp/traits/kazuho-picojson/traits.h
Normal file
76
src/lib/jwt-cpp/traits/kazuho-picojson/traits.h
Normal file
@@ -0,0 +1,76 @@
|
||||
#ifndef JWT_CPP_PICOJSON_TRAITS_H
|
||||
#define JWT_CPP_PICOJSON_TRAITS_H
|
||||
|
||||
#ifndef PICOJSON_USE_INT64
|
||||
#define PICOJSON_USE_INT64
|
||||
#endif
|
||||
#include "picojson.h"
|
||||
|
||||
#ifndef JWT_DISABLE_PICOJSON
|
||||
#define JWT_DISABLE_PICOJSON
|
||||
#endif
|
||||
#include "jwt.h"
|
||||
|
||||
namespace jwt {
|
||||
namespace traits {
|
||||
struct kazuho_picojson {
|
||||
using value_type = picojson::value;
|
||||
using object_type = picojson::object;
|
||||
using array_type = picojson::array;
|
||||
using string_type = std::string;
|
||||
using number_type = double;
|
||||
using integer_type = int64_t;
|
||||
using boolean_type = bool;
|
||||
|
||||
static json::type get_type(const picojson::value& val) {
|
||||
using json::type;
|
||||
if (val.is<bool>()) return type::boolean;
|
||||
if (val.is<int64_t>()) return type::integer;
|
||||
if (val.is<double>()) return type::number;
|
||||
if (val.is<std::string>()) return type::string;
|
||||
if (val.is<picojson::array>()) return type::array;
|
||||
if (val.is<picojson::object>()) return type::object;
|
||||
|
||||
throw std::logic_error("invalid type");
|
||||
}
|
||||
|
||||
static picojson::object as_object(const picojson::value& val) {
|
||||
if (!val.is<picojson::object>()) throw std::bad_cast();
|
||||
return val.get<picojson::object>();
|
||||
}
|
||||
|
||||
static std::string as_string(const picojson::value& val) {
|
||||
if (!val.is<std::string>()) throw std::bad_cast();
|
||||
return val.get<std::string>();
|
||||
}
|
||||
|
||||
static picojson::array as_array(const picojson::value& val) {
|
||||
if (!val.is<picojson::array>()) throw std::bad_cast();
|
||||
return val.get<picojson::array>();
|
||||
}
|
||||
|
||||
static int64_t as_integer(const picojson::value& val) {
|
||||
if (!val.is<int64_t>()) throw std::bad_cast();
|
||||
return val.get<int64_t>();
|
||||
}
|
||||
|
||||
static bool as_boolean(const picojson::value& val) {
|
||||
if (!val.is<bool>()) throw std::bad_cast();
|
||||
return val.get<bool>();
|
||||
}
|
||||
|
||||
static double as_number(const picojson::value& val) {
|
||||
if (!val.is<double>()) throw std::bad_cast();
|
||||
return val.get<double>();
|
||||
}
|
||||
|
||||
static bool parse(picojson::value& val, const std::string& str) {
|
||||
return picojson::parse(val, str).empty();
|
||||
}
|
||||
|
||||
static std::string serialize(const picojson::value& val) { return val.serialize(); }
|
||||
};
|
||||
} // namespace traits
|
||||
} // namespace jwt
|
||||
|
||||
#endif
|
||||
88
src/lib/jwt-cpp/traits/nlohmann-json/defaults.h
Normal file
88
src/lib/jwt-cpp/traits/nlohmann-json/defaults.h
Normal file
@@ -0,0 +1,88 @@
|
||||
#ifndef JWT_CPP_NLOHMANN_JSON_DEFAULTS_H
|
||||
#define JWT_CPP_NLOHMANN_JSON_DEFAULTS_H
|
||||
|
||||
#ifndef JWT_DISABLE_PICOJSON
|
||||
#define JWT_DISABLE_PICOJSON
|
||||
#endif
|
||||
|
||||
#include "traits.h"
|
||||
|
||||
namespace jwt {
|
||||
/**
|
||||
* \brief a class to store a generic [JSON for Modern C++](https://github.com/nlohmann/json) value as claim
|
||||
*
|
||||
* This type is the specialization of the \ref basic_claim class which
|
||||
* uses the standard template types.
|
||||
*/
|
||||
using claim = basic_claim<traits::nlohmann_json>;
|
||||
|
||||
/**
|
||||
* Create a verifier using the default clock
|
||||
* \return verifier instance
|
||||
*/
|
||||
inline verifier<default_clock, traits::nlohmann_json> verify() {
|
||||
return verify<default_clock, traits::nlohmann_json>(default_clock{});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a builder instance to create a new token
|
||||
*/
|
||||
inline builder<traits::nlohmann_json> create() { return builder<traits::nlohmann_json>(); }
|
||||
|
||||
#ifndef JWT_DISABLE_BASE64
|
||||
/**
|
||||
* Decode a token
|
||||
* \param token Token to decode
|
||||
* \return Decoded token
|
||||
* \throw std::invalid_argument Token is not in correct format
|
||||
* \throw std::runtime_error Base64 decoding failed or invalid json
|
||||
*/
|
||||
inline decoded_jwt<traits::nlohmann_json> decode(const std::string& token) {
|
||||
return decoded_jwt<traits::nlohmann_json>(token);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Decode a token
|
||||
* \tparam Decode is callabled, taking a string_type and returns a string_type.
|
||||
* It should ensure the padding of the input and then base64url decode and
|
||||
* return the results.
|
||||
* \param token Token to decode
|
||||
* \param decode The token to parse
|
||||
* \return Decoded token
|
||||
* \throw std::invalid_argument Token is not in correct format
|
||||
* \throw std::runtime_error Base64 decoding failed or invalid json
|
||||
*/
|
||||
template<typename Decode>
|
||||
decoded_jwt<traits::nlohmann_json> decode(const std::string& token, Decode decode) {
|
||||
return decoded_jwt<traits::nlohmann_json>(token, decode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a jwk
|
||||
* \param token JWK Token to parse
|
||||
* \return Parsed JWK
|
||||
* \throw std::runtime_error Token is not in correct format
|
||||
*/
|
||||
inline jwk<traits::nlohmann_json> parse_jwk(const traits::nlohmann_json::string_type& token) {
|
||||
return jwk<traits::nlohmann_json>(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a jwks
|
||||
* \param token JWKs Token to parse
|
||||
* \return Parsed JWKs
|
||||
* \throw std::runtime_error Token is not in correct format
|
||||
*/
|
||||
inline jwks<traits::nlohmann_json> parse_jwks(const traits::nlohmann_json::string_type& token) {
|
||||
return jwks<traits::nlohmann_json>(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* This type is the specialization of the \ref verify_ops::verify_context class which
|
||||
* uses the standard template types.
|
||||
*/
|
||||
using verify_context = verify_ops::verify_context<traits::nlohmann_json>;
|
||||
} // namespace jwt
|
||||
|
||||
#endif // JWT_CPP_NLOHMANN_JSON_DEFAULTS_H
|
||||
77
src/lib/jwt-cpp/traits/nlohmann-json/traits.h
Normal file
77
src/lib/jwt-cpp/traits/nlohmann-json/traits.h
Normal file
@@ -0,0 +1,77 @@
|
||||
#ifndef JWT_CPP_NLOHMANN_JSON_TRAITS_H
|
||||
#define JWT_CPP_NLOHMANN_JSON_TRAITS_H
|
||||
|
||||
#include "jwt-cpp/jwt.h"
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
namespace jwt {
|
||||
namespace traits {
|
||||
struct nlohmann_json {
|
||||
using json = nlohmann::json;
|
||||
using value_type = json;
|
||||
using object_type = json::object_t;
|
||||
using array_type = json::array_t;
|
||||
using string_type = std::string; // current limitation of traits implementation
|
||||
using number_type = json::number_float_t;
|
||||
using integer_type = json::number_integer_t;
|
||||
using boolean_type = json::boolean_t;
|
||||
|
||||
static jwt::json::type get_type(const json& val) {
|
||||
using jwt::json::type;
|
||||
|
||||
if (val.type() == json::value_t::boolean) return type::boolean;
|
||||
// nlohmann internally tracks two types of integers
|
||||
if (val.type() == json::value_t::number_integer) return type::integer;
|
||||
if (val.type() == json::value_t::number_unsigned) return type::integer;
|
||||
if (val.type() == json::value_t::number_float) return type::number;
|
||||
if (val.type() == json::value_t::string) return type::string;
|
||||
if (val.type() == json::value_t::array) return type::array;
|
||||
if (val.type() == json::value_t::object) return type::object;
|
||||
|
||||
throw std::logic_error("invalid type");
|
||||
}
|
||||
|
||||
static json::object_t as_object(const json& val) {
|
||||
if (val.type() != json::value_t::object) throw std::bad_cast();
|
||||
return val.get<json::object_t>();
|
||||
}
|
||||
|
||||
static std::string as_string(const json& val) {
|
||||
if (val.type() != json::value_t::string) throw std::bad_cast();
|
||||
return val.get<std::string>();
|
||||
}
|
||||
|
||||
static json::array_t as_array(const json& val) {
|
||||
if (val.type() != json::value_t::array) throw std::bad_cast();
|
||||
return val.get<json::array_t>();
|
||||
}
|
||||
|
||||
static int64_t as_integer(const json& val) {
|
||||
switch (val.type()) {
|
||||
case json::value_t::number_integer:
|
||||
case json::value_t::number_unsigned: return val.get<int64_t>();
|
||||
default: throw std::bad_cast();
|
||||
}
|
||||
}
|
||||
|
||||
static bool as_boolean(const json& val) {
|
||||
if (val.type() != json::value_t::boolean) throw std::bad_cast();
|
||||
return val.get<bool>();
|
||||
}
|
||||
|
||||
static double as_number(const json& val) {
|
||||
if (val.type() != json::value_t::number_float) throw std::bad_cast();
|
||||
return val.get<double>();
|
||||
}
|
||||
|
||||
static bool parse(json& val, std::string str) {
|
||||
val = json::parse(str.begin(), str.end());
|
||||
return true;
|
||||
}
|
||||
|
||||
static std::string serialize(const json& val) { return val.dump(); }
|
||||
};
|
||||
} // namespace traits
|
||||
} // namespace jwt
|
||||
|
||||
#endif
|
||||
@@ -110,13 +110,14 @@ extern "C" {
|
||||
#pragma warning(disable : 4244) // conversion from int to char
|
||||
#pragma warning(disable : 4127) // conditional expression is constant
|
||||
#pragma warning(disable : 4702) // unreachable code
|
||||
#pragma warning(disable : 4706) // assignment within conditional expression
|
||||
#else
|
||||
#define SNPRINTF snprintf
|
||||
#endif
|
||||
|
||||
namespace picojson {
|
||||
|
||||
enum {
|
||||
enum {
|
||||
null_type,
|
||||
boolean_type,
|
||||
number_type,
|
||||
@@ -127,14 +128,14 @@ enum {
|
||||
,
|
||||
int64_type
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
enum { INDENT_WIDTH = 2 };
|
||||
enum { INDENT_WIDTH = 2, DEFAULT_MAX_DEPTHS = 100 };
|
||||
|
||||
struct null {};
|
||||
struct null {};
|
||||
|
||||
class value {
|
||||
public:
|
||||
class value {
|
||||
public:
|
||||
typedef std::vector<value> array;
|
||||
typedef std::map<std::string, value> object;
|
||||
union _storage {
|
||||
@@ -148,11 +149,11 @@ public:
|
||||
object *object_;
|
||||
};
|
||||
|
||||
protected:
|
||||
protected:
|
||||
int type_;
|
||||
_storage u_;
|
||||
|
||||
public:
|
||||
public:
|
||||
value();
|
||||
value(int type, bool);
|
||||
explicit value(bool b);
|
||||
@@ -197,21 +198,21 @@ public:
|
||||
template <typename Iter> void serialize(Iter os, bool prettify = false) const;
|
||||
std::string serialize(bool prettify = false) const;
|
||||
|
||||
private:
|
||||
private:
|
||||
template <typename T> value(const T *); // intentionally defined to block implicit conversion of pointer to bool
|
||||
template <typename Iter> static void _indent(Iter os, int indent);
|
||||
template <typename Iter> void _serialize(Iter os, int indent) const;
|
||||
std::string _serialize(int indent) const;
|
||||
void clear();
|
||||
};
|
||||
};
|
||||
|
||||
typedef value::array array;
|
||||
typedef value::object object;
|
||||
typedef value::array array;
|
||||
typedef value::object object;
|
||||
|
||||
inline value::value() : type_(null_type), u_() {
|
||||
}
|
||||
inline value::value() : type_(null_type), u_() {
|
||||
}
|
||||
|
||||
inline value::value(int type, bool) : type_(type), u_() {
|
||||
inline value::value(int type, bool) : type_(type), u_() {
|
||||
switch (type) {
|
||||
#define INIT(p, v) \
|
||||
case p##type: \
|
||||
@@ -229,24 +230,24 @@ inline value::value(int type, bool) : type_(type), u_() {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline value::value(bool b) : type_(boolean_type), u_() {
|
||||
inline value::value(bool b) : type_(boolean_type), u_() {
|
||||
u_.boolean_ = b;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PICOJSON_USE_INT64
|
||||
inline value::value(int64_t i) : type_(int64_type), u_() {
|
||||
inline value::value(int64_t i) : type_(int64_type), u_() {
|
||||
u_.int64_ = i;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
inline value::value(double n) : type_(number_type), u_() {
|
||||
inline value::value(double n) : type_(number_type), u_() {
|
||||
if (
|
||||
#ifdef _MSC_VER
|
||||
!_finite(n)
|
||||
!_finite(n)
|
||||
#elif __cplusplus >= 201103L
|
||||
std::isnan(n) || std::isinf(n)
|
||||
std::isnan(n) || std::isinf(n)
|
||||
#else
|
||||
isnan(n) || isinf(n)
|
||||
#endif
|
||||
@@ -254,43 +255,43 @@ inline value::value(double n) : type_(number_type), u_() {
|
||||
throw std::overflow_error("");
|
||||
}
|
||||
u_.number_ = n;
|
||||
}
|
||||
}
|
||||
|
||||
inline value::value(const std::string &s) : type_(string_type), u_() {
|
||||
inline value::value(const std::string &s) : type_(string_type), u_() {
|
||||
u_.string_ = new std::string(s);
|
||||
}
|
||||
}
|
||||
|
||||
inline value::value(const array &a) : type_(array_type), u_() {
|
||||
inline value::value(const array &a) : type_(array_type), u_() {
|
||||
u_.array_ = new array(a);
|
||||
}
|
||||
}
|
||||
|
||||
inline value::value(const object &o) : type_(object_type), u_() {
|
||||
inline value::value(const object &o) : type_(object_type), u_() {
|
||||
u_.object_ = new object(o);
|
||||
}
|
||||
}
|
||||
|
||||
#if PICOJSON_USE_RVALUE_REFERENCE
|
||||
inline value::value(std::string &&s) : type_(string_type), u_() {
|
||||
inline value::value(std::string &&s) : type_(string_type), u_() {
|
||||
u_.string_ = new std::string(std::move(s));
|
||||
}
|
||||
}
|
||||
|
||||
inline value::value(array &&a) : type_(array_type), u_() {
|
||||
inline value::value(array &&a) : type_(array_type), u_() {
|
||||
u_.array_ = new array(std::move(a));
|
||||
}
|
||||
}
|
||||
|
||||
inline value::value(object &&o) : type_(object_type), u_() {
|
||||
inline value::value(object &&o) : type_(object_type), u_() {
|
||||
u_.object_ = new object(std::move(o));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
inline value::value(const char *s) : type_(string_type), u_() {
|
||||
inline value::value(const char *s) : type_(string_type), u_() {
|
||||
u_.string_ = new std::string(s);
|
||||
}
|
||||
}
|
||||
|
||||
inline value::value(const char *s, size_t len) : type_(string_type), u_() {
|
||||
inline value::value(const char *s, size_t len) : type_(string_type), u_() {
|
||||
u_.string_ = new std::string(s, len);
|
||||
}
|
||||
}
|
||||
|
||||
inline void value::clear() {
|
||||
inline void value::clear() {
|
||||
switch (type_) {
|
||||
#define DEINIT(p) \
|
||||
case p##type: \
|
||||
@@ -303,13 +304,13 @@ inline void value::clear() {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline value::~value() {
|
||||
inline value::~value() {
|
||||
clear();
|
||||
}
|
||||
}
|
||||
|
||||
inline value::value(const value &x) : type_(x.type_), u_() {
|
||||
inline value::value(const value &x) : type_(x.type_), u_() {
|
||||
switch (type_) {
|
||||
#define INIT(p, v) \
|
||||
case p##type: \
|
||||
@@ -323,50 +324,50 @@ inline value::value(const value &x) : type_(x.type_), u_() {
|
||||
u_ = x.u_;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline value &value::operator=(const value &x) {
|
||||
inline value &value::operator=(const value &x) {
|
||||
if (this != &x) {
|
||||
value t(x);
|
||||
swap(t);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
#if PICOJSON_USE_RVALUE_REFERENCE
|
||||
inline value::value(value &&x) PICOJSON_NOEXCEPT : type_(null_type), u_() {
|
||||
inline value::value(value &&x) PICOJSON_NOEXCEPT : type_(null_type), u_() {
|
||||
swap(x);
|
||||
}
|
||||
inline value &value::operator=(value &&x) PICOJSON_NOEXCEPT {
|
||||
}
|
||||
inline value &value::operator=(value &&x) PICOJSON_NOEXCEPT {
|
||||
swap(x);
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
inline void value::swap(value &x) PICOJSON_NOEXCEPT {
|
||||
inline void value::swap(value &x) PICOJSON_NOEXCEPT {
|
||||
std::swap(type_, x.type_);
|
||||
std::swap(u_, x.u_);
|
||||
}
|
||||
}
|
||||
|
||||
#define IS(ctype, jtype) \
|
||||
template <> inline bool value::is<ctype>() const { \
|
||||
return type_ == jtype##_type; \
|
||||
}
|
||||
IS(null, null)
|
||||
IS(bool, boolean)
|
||||
IS(null, null)
|
||||
IS(bool, boolean)
|
||||
#ifdef PICOJSON_USE_INT64
|
||||
IS(int64_t, int64)
|
||||
IS(int64_t, int64)
|
||||
#endif
|
||||
IS(std::string, string)
|
||||
IS(array, array)
|
||||
IS(object, object)
|
||||
IS(std::string, string)
|
||||
IS(array, array)
|
||||
IS(object, object)
|
||||
#undef IS
|
||||
template <> inline bool value::is<double>() const {
|
||||
template <> inline bool value::is<double>() const {
|
||||
return type_ == number_type
|
||||
#ifdef PICOJSON_USE_INT64
|
||||
#ifdef PICOJSON_USE_INT64
|
||||
|| type_ == int64_type
|
||||
#endif
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
#define GET(ctype, var) \
|
||||
template <> inline const ctype &value::get<ctype>() const { \
|
||||
@@ -377,17 +378,17 @@ template <> inline bool value::is<double>() const {
|
||||
PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" && is<ctype>()); \
|
||||
return var; \
|
||||
}
|
||||
GET(bool, u_.boolean_)
|
||||
GET(std::string, *u_.string_)
|
||||
GET(array, *u_.array_)
|
||||
GET(object, *u_.object_)
|
||||
GET(bool, u_.boolean_)
|
||||
GET(std::string, *u_.string_)
|
||||
GET(array, *u_.array_)
|
||||
GET(object, *u_.object_)
|
||||
#ifdef PICOJSON_USE_INT64
|
||||
GET(double,
|
||||
(type_ == int64_type && (const_cast<value *>(this)->type_ = number_type, const_cast<value *>(this)->u_.number_ = u_.int64_),
|
||||
GET(double,
|
||||
(type_ == int64_type && (const_cast<value *>(this)->type_ = number_type, (const_cast<value *>(this)->u_.number_ = u_.int64_)),
|
||||
u_.number_))
|
||||
GET(int64_t, u_.int64_)
|
||||
GET(int64_t, u_.int64_)
|
||||
#else
|
||||
GET(double, u_.number_)
|
||||
GET(double, u_.number_)
|
||||
#endif
|
||||
#undef GET
|
||||
|
||||
@@ -397,13 +398,13 @@ GET(double, u_.number_)
|
||||
type_ = jtype##_type; \
|
||||
setter \
|
||||
}
|
||||
SET(bool, boolean, u_.boolean_ = _val;)
|
||||
SET(std::string, string, u_.string_ = new std::string(_val);)
|
||||
SET(array, array, u_.array_ = new array(_val);)
|
||||
SET(object, object, u_.object_ = new object(_val);)
|
||||
SET(double, number, u_.number_ = _val;)
|
||||
SET(bool, boolean, u_.boolean_ = _val;)
|
||||
SET(std::string, string, u_.string_ = new std::string(_val);)
|
||||
SET(array, array, u_.array_ = new array(_val);)
|
||||
SET(object, object, u_.object_ = new object(_val);)
|
||||
SET(double, number, u_.number_ = _val;)
|
||||
#ifdef PICOJSON_USE_INT64
|
||||
SET(int64_t, int64, u_.int64_ = _val;)
|
||||
SET(int64_t, int64, u_.int64_ = _val;)
|
||||
#endif
|
||||
#undef SET
|
||||
|
||||
@@ -414,13 +415,13 @@ SET(int64_t, int64, u_.int64_ = _val;)
|
||||
type_ = jtype##_type; \
|
||||
setter \
|
||||
}
|
||||
MOVESET(std::string, string, u_.string_ = new std::string(std::move(_val));)
|
||||
MOVESET(array, array, u_.array_ = new array(std::move(_val));)
|
||||
MOVESET(object, object, u_.object_ = new object(std::move(_val));)
|
||||
MOVESET(std::string, string, u_.string_ = new std::string(std::move(_val));)
|
||||
MOVESET(array, array, u_.array_ = new array(std::move(_val));)
|
||||
MOVESET(object, object, u_.object_ = new object(std::move(_val));)
|
||||
#undef MOVESET
|
||||
#endif
|
||||
|
||||
inline bool value::evaluate_as_boolean() const {
|
||||
inline bool value::evaluate_as_boolean() const {
|
||||
switch (type_) {
|
||||
case null_type:
|
||||
return false;
|
||||
@@ -437,46 +438,46 @@ inline bool value::evaluate_as_boolean() const {
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline const value &value::get(const size_t idx) const {
|
||||
inline const value &value::get(const size_t idx) const {
|
||||
static value s_null;
|
||||
PICOJSON_ASSERT(is<array>());
|
||||
return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;
|
||||
}
|
||||
}
|
||||
|
||||
inline value &value::get(const size_t idx) {
|
||||
inline value &value::get(const size_t idx) {
|
||||
static value s_null;
|
||||
PICOJSON_ASSERT(is<array>());
|
||||
return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;
|
||||
}
|
||||
}
|
||||
|
||||
inline const value &value::get(const std::string &key) const {
|
||||
inline const value &value::get(const std::string &key) const {
|
||||
static value s_null;
|
||||
PICOJSON_ASSERT(is<object>());
|
||||
object::const_iterator i = u_.object_->find(key);
|
||||
return i != u_.object_->end() ? i->second : s_null;
|
||||
}
|
||||
}
|
||||
|
||||
inline value &value::get(const std::string &key) {
|
||||
inline value &value::get(const std::string &key) {
|
||||
static value s_null;
|
||||
PICOJSON_ASSERT(is<object>());
|
||||
object::iterator i = u_.object_->find(key);
|
||||
return i != u_.object_->end() ? i->second : s_null;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool value::contains(const size_t idx) const {
|
||||
inline bool value::contains(const size_t idx) const {
|
||||
PICOJSON_ASSERT(is<array>());
|
||||
return idx < u_.array_->size();
|
||||
}
|
||||
}
|
||||
|
||||
inline bool value::contains(const std::string &key) const {
|
||||
inline bool value::contains(const std::string &key) const {
|
||||
PICOJSON_ASSERT(is<object>());
|
||||
object::const_iterator i = u_.object_->find(key);
|
||||
return i != u_.object_->end();
|
||||
}
|
||||
}
|
||||
|
||||
inline std::string value::to_str() const {
|
||||
inline std::string value::to_str() const {
|
||||
switch (type_) {
|
||||
case null_type:
|
||||
return "null";
|
||||
@@ -519,13 +520,13 @@ inline std::string value::to_str() const {
|
||||
#endif
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Iter> void copy(const std::string &s, Iter oi) {
|
||||
template <typename Iter> void copy(const std::string &s, Iter oi) {
|
||||
std::copy(s.begin(), s.end(), oi);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Iter> struct serialize_str_char {
|
||||
template <typename Iter> struct serialize_str_char {
|
||||
Iter oi;
|
||||
void operator()(char c) {
|
||||
switch (c) {
|
||||
@@ -553,31 +554,31 @@ template <typename Iter> struct serialize_str_char {
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template <typename Iter> void serialize_str(const std::string &s, Iter oi) {
|
||||
template <typename Iter> void serialize_str(const std::string &s, Iter oi) {
|
||||
*oi++ = '"';
|
||||
serialize_str_char<Iter> process_char = {oi};
|
||||
std::for_each(s.begin(), s.end(), process_char);
|
||||
*oi++ = '"';
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Iter> void value::serialize(Iter oi, bool prettify) const {
|
||||
template <typename Iter> void value::serialize(Iter oi, bool prettify) const {
|
||||
return _serialize(oi, prettify ? 0 : -1);
|
||||
}
|
||||
}
|
||||
|
||||
inline std::string value::serialize(bool prettify) const {
|
||||
inline std::string value::serialize(bool prettify) const {
|
||||
return _serialize(prettify ? 0 : -1);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Iter> void value::_indent(Iter oi, int indent) {
|
||||
template <typename Iter> void value::_indent(Iter oi, int indent) {
|
||||
*oi++ = '\n';
|
||||
for (int i = 0; i < indent * INDENT_WIDTH; ++i) {
|
||||
*oi++ = ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Iter> void value::_serialize(Iter oi, int indent) const {
|
||||
template <typename Iter> void value::_serialize(Iter oi, int indent) const {
|
||||
switch (type_) {
|
||||
case string_type:
|
||||
serialize_str(*u_.string_, oi);
|
||||
@@ -640,21 +641,21 @@ template <typename Iter> void value::_serialize(Iter oi, int indent) const {
|
||||
if (indent == 0) {
|
||||
*oi++ = '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline std::string value::_serialize(int indent) const {
|
||||
inline std::string value::_serialize(int indent) const {
|
||||
std::string s;
|
||||
_serialize(std::back_inserter(s), indent);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Iter> class input {
|
||||
protected:
|
||||
template <typename Iter> class input {
|
||||
protected:
|
||||
Iter cur_, end_;
|
||||
bool consumed_;
|
||||
int line_;
|
||||
|
||||
public:
|
||||
public:
|
||||
input(const Iter &first, const Iter &last) : cur_(first), end_(last), consumed_(false), line_(1) {
|
||||
}
|
||||
int getc() {
|
||||
@@ -711,9 +712,9 @@ public:
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template <typename Iter> inline int _parse_quadhex(input<Iter> &in) {
|
||||
template <typename Iter> inline int _parse_quadhex(input<Iter> &in) {
|
||||
int uni_ch = 0, hex;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((hex = in.getc()) == -1) {
|
||||
@@ -732,9 +733,9 @@ template <typename Iter> inline int _parse_quadhex(input<Iter> &in) {
|
||||
uni_ch = uni_ch * 16 + hex;
|
||||
}
|
||||
return uni_ch;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename String, typename Iter> inline bool _parse_codepoint(String &out, input<Iter> &in) {
|
||||
template <typename String, typename Iter> inline bool _parse_codepoint(String &out, input<Iter> &in) {
|
||||
int uni_ch;
|
||||
if ((uni_ch = _parse_quadhex(in)) == -1) {
|
||||
return false;
|
||||
@@ -773,9 +774,9 @@ template <typename String, typename Iter> inline bool _parse_codepoint(String &o
|
||||
out.push_back(static_cast<char>(0x80 | (uni_ch & 0x3f)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename String, typename Iter> inline bool _parse_string(String &out, input<Iter> &in) {
|
||||
template <typename String, typename Iter> inline bool _parse_string(String &out, input<Iter> &in) {
|
||||
while (1) {
|
||||
int ch = in.getc();
|
||||
if (ch < ' ') {
|
||||
@@ -814,9 +815,9 @@ template <typename String, typename Iter> inline bool _parse_string(String &out,
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Context, typename Iter> inline bool _parse_array(Context &ctx, input<Iter> &in) {
|
||||
template <typename Context, typename Iter> inline bool _parse_array(Context &ctx, input<Iter> &in) {
|
||||
if (!ctx.parse_array_start()) {
|
||||
return false;
|
||||
}
|
||||
@@ -831,14 +832,14 @@ template <typename Context, typename Iter> inline bool _parse_array(Context &ctx
|
||||
idx++;
|
||||
} while (in.expect(','));
|
||||
return in.expect(']') && ctx.parse_array_stop(idx);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Context, typename Iter> inline bool _parse_object(Context &ctx, input<Iter> &in) {
|
||||
template <typename Context, typename Iter> inline bool _parse_object(Context &ctx, input<Iter> &in) {
|
||||
if (!ctx.parse_object_start()) {
|
||||
return false;
|
||||
}
|
||||
if (in.expect('}')) {
|
||||
return true;
|
||||
return ctx.parse_object_stop();
|
||||
}
|
||||
do {
|
||||
std::string key;
|
||||
@@ -849,10 +850,10 @@ template <typename Context, typename Iter> inline bool _parse_object(Context &ct
|
||||
return false;
|
||||
}
|
||||
} while (in.expect(','));
|
||||
return in.expect('}');
|
||||
}
|
||||
return in.expect('}') && ctx.parse_object_stop();
|
||||
}
|
||||
|
||||
template <typename Iter> inline std::string _parse_number(input<Iter> &in) {
|
||||
template <typename Iter> inline std::string _parse_number(input<Iter> &in) {
|
||||
std::string num_str;
|
||||
while (1) {
|
||||
int ch = in.getc();
|
||||
@@ -870,9 +871,9 @@ template <typename Iter> inline std::string _parse_number(input<Iter> &in) {
|
||||
}
|
||||
}
|
||||
return num_str;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Context, typename Iter> inline bool _parse(Context &ctx, input<Iter> &in) {
|
||||
template <typename Context, typename Iter> inline bool _parse(Context &ctx, input<Iter> &in) {
|
||||
in.skip_ws();
|
||||
int ch = in.getc();
|
||||
switch (ch) {
|
||||
@@ -924,10 +925,10 @@ template <typename Context, typename Iter> inline bool _parse(Context &ctx, inpu
|
||||
}
|
||||
in.ungetc();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class deny_parse_context {
|
||||
public:
|
||||
class deny_parse_context {
|
||||
public:
|
||||
bool set_null() {
|
||||
return false;
|
||||
}
|
||||
@@ -960,14 +961,15 @@ public:
|
||||
template <typename Iter> bool parse_object_item(input<Iter> &, const std::string &) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class default_parse_context {
|
||||
protected:
|
||||
class default_parse_context {
|
||||
protected:
|
||||
value *out_;
|
||||
size_t depths_;
|
||||
|
||||
public:
|
||||
default_parse_context(value *out) : out_(out) {
|
||||
public:
|
||||
default_parse_context(value *out, size_t depths = DEFAULT_MAX_DEPTHS) : out_(out), depths_(depths) {
|
||||
}
|
||||
bool set_null() {
|
||||
*out_ = value();
|
||||
@@ -992,42 +994,55 @@ public:
|
||||
return _parse_string(out_->get<std::string>(), in);
|
||||
}
|
||||
bool parse_array_start() {
|
||||
if (depths_ == 0)
|
||||
return false;
|
||||
--depths_;
|
||||
*out_ = value(array_type, false);
|
||||
return true;
|
||||
}
|
||||
template <typename Iter> bool parse_array_item(input<Iter> &in, size_t) {
|
||||
array &a = out_->get<array>();
|
||||
a.push_back(value());
|
||||
default_parse_context ctx(&a.back());
|
||||
default_parse_context ctx(&a.back(), depths_);
|
||||
return _parse(ctx, in);
|
||||
}
|
||||
bool parse_array_stop(size_t) {
|
||||
++depths_;
|
||||
return true;
|
||||
}
|
||||
bool parse_object_start() {
|
||||
if (depths_ == 0)
|
||||
return false;
|
||||
*out_ = value(object_type, false);
|
||||
return true;
|
||||
}
|
||||
template <typename Iter> bool parse_object_item(input<Iter> &in, const std::string &key) {
|
||||
object &o = out_->get<object>();
|
||||
default_parse_context ctx(&o[key]);
|
||||
default_parse_context ctx(&o[key], depths_);
|
||||
return _parse(ctx, in);
|
||||
}
|
||||
bool parse_object_stop() {
|
||||
++depths_;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
default_parse_context(const default_parse_context &);
|
||||
default_parse_context &operator=(const default_parse_context &);
|
||||
};
|
||||
};
|
||||
|
||||
class null_parse_context {
|
||||
public:
|
||||
class null_parse_context {
|
||||
protected:
|
||||
size_t depths_;
|
||||
|
||||
public:
|
||||
struct dummy_str {
|
||||
void push_back(int) {
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
null_parse_context() {
|
||||
public:
|
||||
null_parse_context(size_t depths = DEFAULT_MAX_DEPTHS) : depths_(depths) {
|
||||
}
|
||||
bool set_null() {
|
||||
return true;
|
||||
@@ -1048,34 +1063,45 @@ public:
|
||||
return _parse_string(s, in);
|
||||
}
|
||||
bool parse_array_start() {
|
||||
if (depths_ == 0)
|
||||
return false;
|
||||
--depths_;
|
||||
return true;
|
||||
}
|
||||
template <typename Iter> bool parse_array_item(input<Iter> &in, size_t) {
|
||||
return _parse(*this, in);
|
||||
}
|
||||
bool parse_array_stop(size_t) {
|
||||
++depths_;
|
||||
return true;
|
||||
}
|
||||
bool parse_object_start() {
|
||||
if (depths_ == 0)
|
||||
return false;
|
||||
--depths_;
|
||||
return true;
|
||||
}
|
||||
template <typename Iter> bool parse_object_item(input<Iter> &in, const std::string &) {
|
||||
++depths_;
|
||||
return _parse(*this, in);
|
||||
}
|
||||
bool parse_object_stop() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
null_parse_context(const null_parse_context &);
|
||||
null_parse_context &operator=(const null_parse_context &);
|
||||
};
|
||||
};
|
||||
|
||||
// obsolete, use the version below
|
||||
template <typename Iter> inline std::string parse(value &out, Iter &pos, const Iter &last) {
|
||||
template <typename Iter> inline std::string parse(value &out, Iter &pos, const Iter &last) {
|
||||
std::string err;
|
||||
pos = parse(out, pos, last, &err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Context, typename Iter> inline Iter _parse(Context &ctx, const Iter &first, const Iter &last, std::string *err) {
|
||||
template <typename Context, typename Iter> inline Iter _parse(Context &ctx, const Iter &first, const Iter &last, std::string *err) {
|
||||
input<Iter> in(first, last);
|
||||
if (!_parse(ctx, in) && err != NULL) {
|
||||
char buf[64];
|
||||
@@ -1091,37 +1117,37 @@ template <typename Context, typename Iter> inline Iter _parse(Context &ctx, cons
|
||||
}
|
||||
}
|
||||
return in.cur();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Iter> inline Iter parse(value &out, const Iter &first, const Iter &last, std::string *err) {
|
||||
template <typename Iter> inline Iter parse(value &out, const Iter &first, const Iter &last, std::string *err) {
|
||||
default_parse_context ctx(&out);
|
||||
return _parse(ctx, first, last, err);
|
||||
}
|
||||
}
|
||||
|
||||
inline std::string parse(value &out, const std::string &s) {
|
||||
inline std::string parse(value &out, const std::string &s) {
|
||||
std::string err;
|
||||
parse(out, s.begin(), s.end(), &err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
inline std::string parse(value &out, std::istream &is) {
|
||||
inline std::string parse(value &out, std::istream &is) {
|
||||
std::string err;
|
||||
parse(out, std::istreambuf_iterator<char>(is.rdbuf()), std::istreambuf_iterator<char>(), &err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> struct last_error_t { static std::string s; };
|
||||
template <typename T> std::string last_error_t<T>::s;
|
||||
template <typename T> struct last_error_t { static std::string s; };
|
||||
template <typename T> std::string last_error_t<T>::s;
|
||||
|
||||
inline void set_last_error(const std::string &s) {
|
||||
inline void set_last_error(const std::string &s) {
|
||||
last_error_t<bool>::s = s;
|
||||
}
|
||||
}
|
||||
|
||||
inline const std::string &get_last_error() {
|
||||
inline const std::string &get_last_error() {
|
||||
return last_error_t<bool>::s;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool operator==(const value &x, const value &y) {
|
||||
inline bool operator==(const value &x, const value &y) {
|
||||
if (x.is<null>())
|
||||
return y.is<null>();
|
||||
#define PICOJSON_CMP(type) \
|
||||
@@ -1138,11 +1164,11 @@ inline bool operator==(const value &x, const value &y) {
|
||||
__assume(0);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool operator!=(const value &x, const value &y) {
|
||||
inline bool operator!=(const value &x, const value &y) {
|
||||
return !(x == y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !PICOJSON_USE_RVALUE_REFERENCE
|
||||
|
||||
Reference in New Issue
Block a user