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 * Any \c kind can be coerced to a \c string or a \c boolean. A \c boolean, \c integer or \c decimal can be coerced to
33 * an \c integer or a \c decimal. Coercing to a \c null, \c object or \c array requires the source to have that same
34 * \c kind. A \c string going to an \c integer or a \c decimal is the one conversion this overload answers \c false for
35 * which can still succeed: it depends on what the string says, and the \c value overload is the one which looks.
36 *
37 * \returns \c true if the corresponding \c coerce_X function for the specified \a to will successfully return if given
38 * a \c value of the kind \a from; false if there is no such conversion (the \c coerce_X function might
39 * throw).
40**/
41JSONV_NODISCARD JSONV_PUBLIC bool can_coerce(const kind& from, const kind& to);
42
43/** Can the given \c value be converted \a from a kind \a to another?
44 *
45 * \note
46 * This is \e not only a convenience function! There is a special case for converting from a \c string into either a
47 * \c decimal or \c integer where the contents of the string must be considered. This function will look into the given
48 * \a from and see if it can successfully perfrom the coercion.
49 *
50 * \returns \c true if the corresponding \c coerce_X function for the specified \a to will successfully return if given
51 * the \c value \a from; false if there is no such conversion (the \c coerce_X function will throw).
52**/
53JSONV_NODISCARD JSONV_PUBLIC bool can_coerce(const value& from, const kind& to);
54
55/** 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
56 * this beyond completeness.
57 *
58 * \returns \c nullptr if \a from has \c kind::null.
59 * \throws kind_error if \a from is not \c kind::null.
60**/
61JSONV_PUBLIC std::nullptr_t coerce_null(const value& from);
62
63/** Coerce \a from into a \c map.
64 *
65 * \returns a map of the contents of \a from.
66 * \throws kind_error if \a from is not \c kind::object.
67**/
68JSONV_NODISCARD JSONV_PUBLIC std::map<std::string, value> coerce_object(const value& from);
69
70/** Coerce \a from into a \c vector.
71 *
72 * \returns a vector of the contents of \a from.
73 * \throws kind_error if \a from is not \c kind::array.
74**/
75JSONV_NODISCARD JSONV_PUBLIC std::vector<value> coerce_array(const value& from);
76
77/** Coerce \a from into an \c std::string. If \a from is already \c kind::string, the value is simply returned. If
78 * \a from is any other \c kind, the result will be the same as \c to_string.
79**/
81
82/** Coerce \a from into an integer. A \c decimal is truncated toward zero. If \a from is a \c decimal lower than the
83 * minimum of \c std::int64_t or higher than the maximum of \c std::int64_t, it is clamped to the lowest or highest
84 * value, respectively. A NaN \c decimal coerces to \c 0.
85 *
86 * A \c string coerces if it holds a single JSON number (the RFC 8259 grammar), optionally surrounded by JSON whitespace
87 * (space, tab, line feed and carriage return), and nothing else. This is independent of \c parse_options: a comment,
88 * a leading \c +, a hexadecimal number, \c Infinity, \c NaN and \c null are all refused. An integer which fits in an
89 * \c std::int64_t is returned exactly. Any other number is read as its nearest \c double and then truncated and
90 * clamped as a \c decimal is. A number too large for any finite \c double, such as \c 1e400, is refused.
91 *
92 * \returns
93 * \c kind is... | Rules
94 * ------------- | -------------------------------------------------
95 * \c null | throws \c kind_error
96 * \c object | throws \c kind_error
97 * \c array | throws \c kind_error
98 * \c string | the number it holds, as above; otherwise throws \c kind_error
99 * \c integer | \c from.as_integer()
100 * \c decimal | \c from.as_decimal(), truncated and clamped as above
101 * \c boolean | \c from.as_boolean() ? 1 : 0
102**/
104
105/** Coerce \a from into a \c double.
106 *
107 * A \c string is accepted under the same rules as \c coerce_integer and is read as its nearest \c double. A number too
108 * small in magnitude for a \c double becomes zero; one too large for any finite \c double, such as \c 1e400, is
109 * refused.
110 *
111 * \returns
112 * \c kind is... | Rules
113 * ------------- | -------------------------------------------------
114 * \c null | throws \c kind_error
115 * \c object | throws \c kind_error
116 * \c array | throws \c kind_error
117 * \c string | the number it holds, as above; otherwise throws \c kind_error
118 * \c integer | \c from.as_decimal()
119 * \c decimal | \c from.as_decimal()
120 * \c boolean | \c from.as_boolean() ? 1.0 : 0.0
121**/
123
124/** Coerce \a from into a \c bool. This follows the rules of Python's boolean coercion.
125 *
126 * \returns
127 * \c kind is... | Rules
128 * ------------- | --------------------------------------------------
129 * \c null | \c false
130 * \c object | \c !from.empty()
131 * \c array | \c !from.empty()
132 * \c string | \c !from.empty() (even if the value is \c "false")
133 * \c integer | \c from != 0
134 * \c decimal | \c from != 0.0
135 * \c boolean | \c from.as_boolean()
136**/
138
139/** 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
140 * follows what ECMAScript does when you call \c + on two values (sort of). If you are looking for "predictable", this
141 * is not the function for you. If you are looking for convenience, this is it.
142**/
144
145/** \} **/
146
147}
Represents a single JSON value, which can be any one of a potential kind, each behaving slightly diff...
Definition value.hpp:165
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:143
#define JSONV_PUBLIC
This function or class is part of the public API for JSON Voorhees.
Definition config.hpp:124
kind
Describes the kind of data a value holds.
Definition kind.hpp:30
Copyright (c) 2012-2020 by Travis Gockel.