Skip to content

Instantly share code, notes, and snippets.

@markand
Last active March 23, 2018 16:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save markand/45c9f6a3f9239802850badd8869117e3 to your computer and use it in GitHub Desktop.
Save markand/45c9f6a3f9239802850badd8869117e3 to your computer and use it in GitHub Desktop.
#include <type_traits>
#include <json.hpp>
class parser {
public:
template <typename Type>
class result;
private:
nlohmann::json json_;
public:
inline parser(nlohmann::json json) noexcept
: json_(std::move(json))
{
}
template <typename Type>
result<Type> get(const std::string& key) const noexcept
{
auto it = json_.find(key);
if (it != json_.end())
return result<Type>(json_[key]);
return result<Type>(nullptr);
}
};
template <typename Type>
class parser_traits : public std::false_type {
};
template <>
class parser_traits<std::string> : public std::true_type {
public:
static bool is_valid(const nlohmann::json& value) noexcept
{
return value.is_string();
}
static std::string get(const nlohmann::json& value) noexcept
{
return value.get<std::string>();
}
};
template <typename Type>
class parser::result {
private:
static_assert(parser_traits<Type>::value, "type not supported");
Type result_;
bool valid_{false};
public:
inline result(const nlohmann::json& value) noexcept
{
if (parser_traits<Type>::is_valid(value)) {
result_ = parser_traits<Type>::get(value);
valid_ = true;
}
}
template <typename Exception, typename... Args>
inline result& error(Args&&... args)
{
if (!valid_)
throw Exception(std::forward<Args>(args)...);
return *this;
}
inline result& optional(const Type& def)
{
if (!valid_) {
valid_ = true;
result_ = def;
}
return *this;
}
inline result& optional(Type&& def)
{
if (!valid_) {
valid_ = true;
result_ = std::move(def);
}
return *this;
}
operator Type() const
{
if (!valid_)
throw std::runtime_error("invalid value");
return result_;
}
};
#include <iostream>
class server {
public:
void set_host(std::string) {}
void set_port(std::string) {}
};
int main()
{
const nlohmann::json json{
{ "hostname", "localhost" }
};
const parser ps(json);
server s;
s.set_host(ps.get<std::string>("hostname")
.error<std::invalid_argument>("invalid hostname"));
s.set_port(ps.get<std::string>("port")
.optional("irc")
.error<std::runtime_error>("invalid port number"));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment