annotate ext/json11/json11.hpp @ 186:52322dde68ea

Fix erroneous logic for handling step and block size in prior commit The earlier change had a logical misconception. If PluginStub is receiving the correct step and block size back from the configure call, the plugin on the server side must have already been successfully initialised, as the step and block size are only returned in a successful configure response. This means the test for a failed initialise and redo with the correct parameters must be done on the server side (in LoaderRequests) not the client. The client has a more complicated job, which is to notice that a *successful* configure had returned different framing parameters from those passed to the initialise call, and to pretend that it had actually failed until the host called again with the correct parameters. We definitely need tests for this!
author Chris Cannam <cannam@all-day-breakfast.com>
date Mon, 06 Feb 2017 16:44:33 +0000
parents bf8e3e7dd7de
children d607ae858682
rev   line source
cannam@150 1 /* json11
cannam@150 2 *
cannam@150 3 * json11 is a tiny JSON library for C++11, providing JSON parsing and serialization.
cannam@150 4 *
cannam@150 5 * The core object provided by the library is json11::Json. A Json object represents any JSON
cannam@150 6 * value: null, bool, number (int or double), string (std::string), array (std::vector), or
cannam@150 7 * object (std::map).
cannam@150 8 *
cannam@150 9 * Json objects act like values: they can be assigned, copied, moved, compared for equality or
cannam@150 10 * order, etc. There are also helper methods Json::dump, to serialize a Json to a string, and
cannam@150 11 * Json::parse (static) to parse a std::string as a Json object.
cannam@150 12 *
cannam@150 13 * Internally, the various types of Json object are represented by the JsonValue class
cannam@150 14 * hierarchy.
cannam@150 15 *
cannam@150 16 * A note on numbers - JSON specifies the syntax of number formatting but not its semantics,
cannam@150 17 * so some JSON implementations distinguish between integers and floating-point numbers, while
cannam@150 18 * some don't. In json11, we choose the latter. Because some JSON implementations (namely
cannam@150 19 * Javascript itself) treat all numbers as the same type, distinguishing the two leads
cannam@150 20 * to JSON that will be *silently* changed by a round-trip through those implementations.
cannam@150 21 * Dangerous! To avoid that risk, json11 stores all numbers as double internally, but also
cannam@150 22 * provides integer helpers.
cannam@150 23 *
cannam@150 24 * Fortunately, double-precision IEEE754 ('double') can precisely store any integer in the
cannam@150 25 * range +/-2^53, which includes every 'int' on most systems. (Timestamps often use int64
cannam@150 26 * or long long to avoid the Y2038K problem; a double storing microseconds since some epoch
cannam@150 27 * will be exact for +/- 275 years.)
cannam@150 28 */
cannam@150 29
cannam@150 30 /* Copyright (c) 2013 Dropbox, Inc.
cannam@150 31 *
cannam@150 32 * Permission is hereby granted, free of charge, to any person obtaining a copy
cannam@150 33 * of this software and associated documentation files (the "Software"), to deal
cannam@150 34 * in the Software without restriction, including without limitation the rights
cannam@150 35 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
cannam@150 36 * copies of the Software, and to permit persons to whom the Software is
cannam@150 37 * furnished to do so, subject to the following conditions:
cannam@150 38 *
cannam@150 39 * The above copyright notice and this permission notice shall be included in
cannam@150 40 * all copies or substantial portions of the Software.
cannam@150 41 *
cannam@150 42 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
cannam@150 43 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
cannam@150 44 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
cannam@150 45 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
cannam@150 46 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
cannam@150 47 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
cannam@150 48 * THE SOFTWARE.
cannam@150 49 */
cannam@150 50
cannam@150 51 #pragma once
cannam@150 52
cannam@150 53 #include <string>
cannam@150 54 #include <vector>
cannam@150 55 #include <map>
cannam@150 56 #include <memory>
cannam@150 57 #include <initializer_list>
cannam@150 58
cannam@150 59 namespace json11 {
cannam@150 60
cannam@150 61 enum JsonParse {
cannam@150 62 STANDARD, COMMENTS
cannam@150 63 };
cannam@150 64
cannam@150 65 class JsonValue;
cannam@150 66
cannam@150 67 class Json final {
cannam@150 68 public:
cannam@150 69 // Types
cannam@150 70 enum Type {
cannam@150 71 NUL, NUMBER, BOOL, STRING, ARRAY, OBJECT
cannam@150 72 };
cannam@150 73
cannam@150 74 // Array and object typedefs
cannam@150 75 typedef std::vector<Json> array;
cannam@150 76 typedef std::map<std::string, Json> object;
cannam@150 77
cannam@150 78 // Constructors for the various types of JSON value.
cannam@150 79 Json() noexcept; // NUL
cannam@150 80 Json(std::nullptr_t) noexcept; // NUL
cannam@150 81 Json(double value); // NUMBER
cannam@150 82 Json(int value); // NUMBER
cannam@150 83 Json(bool value); // BOOL
cannam@150 84 Json(const std::string &value); // STRING
cannam@150 85 Json(std::string &&value); // STRING
cannam@150 86 Json(const char * value); // STRING
cannam@150 87 Json(const array &values); // ARRAY
cannam@150 88 Json(array &&values); // ARRAY
cannam@150 89 Json(const object &values); // OBJECT
cannam@150 90 Json(object &&values); // OBJECT
cannam@150 91
cannam@150 92 // Implicit constructor: anything with a to_json() function.
cannam@150 93 template <class T, class = decltype(&T::to_json)>
cannam@150 94 Json(const T & t) : Json(t.to_json()) {}
cannam@150 95
cannam@150 96 // Implicit constructor: map-like objects (std::map, std::unordered_map, etc)
cannam@150 97 template <class M, typename std::enable_if<
cannam@150 98 std::is_constructible<std::string, typename M::key_type>::value
cannam@150 99 && std::is_constructible<Json, typename M::mapped_type>::value,
cannam@150 100 int>::type = 0>
cannam@150 101 Json(const M & m) : Json(object(m.begin(), m.end())) {}
cannam@150 102
cannam@150 103 // Implicit constructor: vector-like objects (std::list, std::vector, std::set, etc)
cannam@150 104 template <class V, typename std::enable_if<
cannam@150 105 std::is_constructible<Json, typename V::value_type>::value,
cannam@150 106 int>::type = 0>
cannam@150 107 Json(const V & v) : Json(array(v.begin(), v.end())) {}
cannam@150 108
cannam@150 109 // This prevents Json(some_pointer) from accidentally producing a bool. Use
cannam@150 110 // Json(bool(some_pointer)) if that behavior is desired.
cannam@150 111 Json(void *) = delete;
cannam@150 112
cannam@150 113 // Accessors
cannam@150 114 Type type() const;
cannam@150 115
cannam@150 116 bool is_null() const { return type() == NUL; }
cannam@150 117 bool is_number() const { return type() == NUMBER; }
cannam@150 118 bool is_bool() const { return type() == BOOL; }
cannam@150 119 bool is_string() const { return type() == STRING; }
cannam@150 120 bool is_array() const { return type() == ARRAY; }
cannam@150 121 bool is_object() const { return type() == OBJECT; }
cannam@150 122
cannam@150 123 // Return the enclosed value if this is a number, 0 otherwise. Note that json11 does not
cannam@150 124 // distinguish between integer and non-integer numbers - number_value() and int_value()
cannam@150 125 // can both be applied to a NUMBER-typed object.
cannam@150 126 double number_value() const;
cannam@150 127 int int_value() const;
cannam@150 128
cannam@150 129 // Return the enclosed value if this is a boolean, false otherwise.
cannam@150 130 bool bool_value() const;
cannam@150 131 // Return the enclosed string if this is a string, "" otherwise.
cannam@150 132 const std::string &string_value() const;
cannam@150 133 // Return the enclosed std::vector if this is an array, or an empty vector otherwise.
cannam@150 134 const array &array_items() const;
cannam@150 135 // Return the enclosed std::map if this is an object, or an empty map otherwise.
cannam@150 136 const object &object_items() const;
cannam@150 137
cannam@150 138 // Return a reference to arr[i] if this is an array, Json() otherwise.
cannam@150 139 const Json & operator[](size_t i) const;
cannam@150 140 // Return a reference to obj[key] if this is an object, Json() otherwise.
cannam@150 141 const Json & operator[](const std::string &key) const;
cannam@150 142
cannam@150 143 // Serialize.
cannam@150 144 void dump(std::string &out) const;
cannam@150 145 std::string dump() const {
cannam@150 146 std::string out;
cannam@150 147 dump(out);
cannam@150 148 return out;
cannam@150 149 }
cannam@150 150
cannam@150 151 // Parse. If parse fails, return Json() and assign an error message to err.
cannam@150 152 static Json parse(const std::string & in,
cannam@150 153 std::string & err,
cannam@150 154 JsonParse strategy = JsonParse::STANDARD);
cannam@150 155 static Json parse(const char * in,
cannam@150 156 std::string & err,
cannam@150 157 JsonParse strategy = JsonParse::STANDARD) {
cannam@150 158 if (in) {
cannam@150 159 return parse(std::string(in), err, strategy);
cannam@150 160 } else {
cannam@150 161 err = "null input";
cannam@150 162 return nullptr;
cannam@150 163 }
cannam@150 164 }
cannam@150 165 // Parse multiple objects, concatenated or separated by whitespace
cannam@150 166 static std::vector<Json> parse_multi(
cannam@150 167 const std::string & in,
cannam@150 168 std::string & err,
cannam@150 169 JsonParse strategy = JsonParse::STANDARD);
cannam@150 170
cannam@150 171 bool operator== (const Json &rhs) const;
cannam@150 172 bool operator< (const Json &rhs) const;
cannam@150 173 bool operator!= (const Json &rhs) const { return !(*this == rhs); }
cannam@150 174 bool operator<= (const Json &rhs) const { return !(rhs < *this); }
cannam@150 175 bool operator> (const Json &rhs) const { return (rhs < *this); }
cannam@150 176 bool operator>= (const Json &rhs) const { return !(*this < rhs); }
cannam@150 177
cannam@150 178 /* has_shape(types, err)
cannam@150 179 *
cannam@150 180 * Return true if this is a JSON object and, for each item in types, has a field of
cannam@150 181 * the given type. If not, return false and set err to a descriptive message.
cannam@150 182 */
cannam@150 183 typedef std::initializer_list<std::pair<std::string, Type>> shape;
cannam@150 184 bool has_shape(const shape & types, std::string & err) const;
cannam@150 185
cannam@150 186 private:
cannam@150 187 std::shared_ptr<JsonValue> m_ptr;
cannam@150 188 };
cannam@150 189
cannam@150 190 // Internal class hierarchy - JsonValue objects are not exposed to users of this API.
cannam@150 191 class JsonValue {
cannam@150 192 protected:
cannam@150 193 friend class Json;
cannam@150 194 friend class JsonInt;
cannam@150 195 friend class JsonDouble;
cannam@150 196 virtual Json::Type type() const = 0;
cannam@150 197 virtual bool equals(const JsonValue * other) const = 0;
cannam@150 198 virtual bool less(const JsonValue * other) const = 0;
cannam@150 199 virtual void dump(std::string &out) const = 0;
cannam@150 200 virtual double number_value() const;
cannam@150 201 virtual int int_value() const;
cannam@150 202 virtual bool bool_value() const;
cannam@150 203 virtual const std::string &string_value() const;
cannam@150 204 virtual const Json::array &array_items() const;
cannam@150 205 virtual const Json &operator[](size_t i) const;
cannam@150 206 virtual const Json::object &object_items() const;
cannam@150 207 virtual const Json &operator[](const std::string &key) const;
cannam@150 208 virtual ~JsonValue() {}
cannam@150 209 };
cannam@150 210
cannam@150 211 } // namespace json11