JSON Voorhees
Killer JSON for C++
Loading...
Searching...
No Matches
coerce.hpp
Go to the documentation of this file.
1/** \file jsonv/coerce.hpp
2 * A \c jsonv::value has a number of \c as_X operators, which strictly performs a transformation to a C++ data type.
3 * However, sometimes when working with things like user input, you would like to be more free-form in what you accept
4 * as "valid."
5 *
6 * Copyright (c) 2014-2015 by Travis Gockel. All rights reserved.
7 *
8 * This program is free software: you can redistribute it and/or modify it under the terms of the Apache License
9 * as published by the Apache Software Foundation, either version 2 of the License, or (at your option) any later
10 * version.
11 *
12 * \author Travis Gockel (travis@gockelhut.com)
13**/
14#pragma once
15
16#include <jsonv/config.hpp>
17#include <jsonv/value.hpp>
18
19#include <map>
20#include <vector>
21
22namespace jsonv
23{
24
25/** \addtogroup Coercion
26 * \{
27 * Looser conversion functions to behave more like ECMAScript.
28**/
29
30/** Can the given \c kind be converted \a from a kind \a to another?
31 *
32 * \returns \c true if the corresponding \c coerce_X function for the specified \a to will successfully return if given
33 * a \c value of the kind \a from; false if there is no such conversion (the \c coerce_X function might
34 * throw).
35**/
36JSONV_NODISCARD JSONV_PUBLIC bool can_coerce(const kind& from, const kind& to);
37
38/** Can the given \c value be converted \a from a kind \a to another?
39 *
40 * \note
41 * This is \e not only a convenience function! There is a special case for converting from a \c string into either a
42 * \c decimal or \c integer where the contents of the string must be considered. This function will look into the given
43 * \a from and see if it can successfully perfrom the coercion.
44 *
45 * \returns \c true if the corresponding \c coerce_X function for the specified \a to will successfully return if given
46 * the \c value \a from; false if there is no such conversion (the \c coerce_X function will throw).
47**/
48JSONV_NODISCARD JSONV_PUBLIC bool can_coerce(const value& from, const kind& to);
49
50/** Coerce \a from into a \c null. If \a from is not \c null, this will throw. It is not clear that there is a use for
51 * this beyond completeness.
52 *
53 * \returns \c nullptr if \a from has \c kind::null.
54 * \throws kind_error if \a from is not \c kind::null.
55**/
56JSONV_PUBLIC std::nullptr_t coerce_null(const value& from);
57
58/** Coerce \a from into a \c map.
59 *
60 * \returns a map of the contents of \a from.
61 * \throws kind_error if \a from is not \c kind::object.
62**/
63JSONV_NODISCARD JSONV_PUBLIC std::map<std::string, value> coerce_object(const value& from);
64
65/** Coerce \a from into a \c vector.
66 *
67 * \returns a vector of the contents of \a from.
68 * \throws kind_error if \a from is not \c kind::array.
69**/
70JSONV_NODISCARD JSONV_PUBLIC std::vector<value> coerce_array(const value& from);
71
72/** Coerce \a from into an \c std::string. If \a from is already \c kind::string, the value is simply returned. If
73 * \a from is any other \c kind, the result will be the same as \c to_string.
74**/
76
77/** Coerce \a from into an integer. A \c decimal is truncated toward zero. If \a from is a \c decimal lower than the
78 * minimum of \c std::int64_t or higher than the maximum of \c std::int64_t, it is clamped to the lowest or highest
79 * value, respectively. A NaN \c decimal coerces to \c 0.
80 *
81 * A \c string coerces if it holds a single JSON number (the RFC 8259 grammar), optionally surrounded by JSON whitespace
82 * (space, tab, line feed and carriage return), and nothing else. This is independent of \c parse_options: a comment,
83 * a leading \c +, a hexadecimal number, \c Infinity, \c NaN and \c null are all refused. An integer which fits in an
84 * \c std::int64_t is returned exactly. Any other number is read as its nearest \c double and then truncated and
85 * clamped as a \c decimal is. A number too large for any finite \c double, such as \c 1e400, is refused.
86 *
87 * \returns
88 * \c kind is... | Rules
89 * ------------- | -------------------------------------------------
90 * \c null | throws \c kind_error
91 * \c object | throws \c kind_error
92 * \c array | throws \c kind_error
93 * \c string | the number it holds, as above; otherwise throws \c kind_error
94 * \c integer | \c from.as_integer()
95 * \c decimal | \c from.as_decimal(), truncated and clamped as above
96 * \c boolean | \c from.as_boolean() ? 1 : 0
97**/
99
100/** Coerce \a from into a \c double.
101 *
102 * A \c string is accepted under the same rules as \c coerce_integer and is read as its nearest \c double. A number too
103 * small in magnitude for a \c double becomes zero; one too large for any finite \c double, such as \c 1e400, is
104 * refused.
105 *
106 * \returns
107 * \c kind is... | Rules
108 * ------------- | -------------------------------------------------
109 * \c null | throws \c kind_error
110 * \c object | throws \c kind_error
111 * \c array | throws \c kind_error
112 * \c string | the number it holds, as above; otherwise throws \c kind_error
113 * \c integer | \c from.as_decimal()
114 * \c decimal | \c from.as_decimal()
115 * \c boolean | \c from.as_boolean() ? 1.0 : 0.0
116**/
118
119/** Coerce \a from into a \c bool. This follows the rules of Python's boolean coercion.
120 *
121 * \returns
122 * \c kind is... | Rules
123 * ------------- | --------------------------------------------------
124 * \c null | \c false
125 * \c object | \c !from.empty()
126 * \c array | \c !from.empty()
127 * \c string | \c !from.empty() (even if the value is \c "false")
128 * \c integer | \c from != 0
129 * \c decimal | \c from != 0.0
130 * \c boolean | \c from.as_boolean()
131**/
133
134/** Combines \a a and \a b in any way possible. The result kind is \e usually based on the kind of \a a and loosely
135 * follows what ECMAScript does when you call \c + on two values (sort of). If you are looking for "predictable", this
136 * is not the function for you. If you are looking for convenience, this is it.
137**/
139
140/** \} **/
141
142}
Represents a single JSON value, which can be any one of a potential kind, each behaving slightly diff...
Definition value.hpp:113
Copyright (c) 2014-2020 by Travis Gockel.
JSONV_PUBLIC std::int64_t coerce_integer(const value &from)
Coerce from into an integer.
JSONV_PUBLIC std::string coerce_string(const value &from)
Coerce from into an std::string.
JSONV_PUBLIC bool coerce_boolean(const value &from)
Coerce from into a bool.
JSONV_PUBLIC std::nullptr_t coerce_null(const value &from)
Coerce from into a null.
JSONV_PUBLIC value coerce_merge(value a, value b)
Combines a and b in any way possible.
JSONV_PUBLIC std::vector< value > coerce_array(const value &from)
Coerce from into a vector.
JSONV_PUBLIC std::map< std::string, value > coerce_object(const value &from)
Coerce from into a map.
JSONV_PUBLIC double coerce_decimal(const value &from)
Coerce from into a double.
JSONV_PUBLIC bool can_coerce(const kind &from, const kind &to)
Can the given kind be converted from a kind to another?
#define JSONV_NODISCARD
Warn if the caller discards the result of this function.
Definition config.hpp:132
#define JSONV_PUBLIC
This function or class is part of the public API for JSON Voorhees.
Definition config.hpp:113
kind
Describes the kind of data a value holds.
Definition kind.hpp:30
Copyright (c) 2012-2020 by Travis Gockel.