1 // 2 // Copyright 2016 Pixar 3 // 4 // Licensed under the Apache License, Version 2.0 (the "Apache License") 5 // with the following modification; you may not use this file except in 6 // compliance with the Apache License and the following modification to it: 7 // Section 6. Trademarks. is deleted and replaced with: 8 // 9 // 6. Trademarks. This License does not grant permission to use the trade 10 // names, trademarks, service marks, or product names of the Licensor 11 // and its affiliates, except as required to comply with Section 4(c) of 12 // the License and to reproduce the content of the NOTICE file. 13 // 14 // You may obtain a copy of the Apache License at 15 // 16 // http://www.apache.org/licenses/LICENSE-2.0 17 // 18 // Unless required by applicable law or agreed to in writing, software 19 // distributed under the Apache License with the above modification is 20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 21 // KIND, either express or implied. See the Apache License for the specific 22 // language governing permissions and limitations under the Apache License. 23 // 24 25 #ifndef PXR_BASE_JS_JSON_H 26 #define PXR_BASE_JS_JSON_H 27 28 /// \file js/json.h 29 /// Top-level entrypoints for reading and writing JSON. 30 31 #include "pxr/pxr.h" 32 #include "pxr/base/js/api.h" 33 #include "pxr/base/js/value.h" 34 35 #include <iosfwd> 36 #include <string> 37 38 PXR_NAMESPACE_OPEN_SCOPE 39 40 /// \struct JsParseError 41 /// 42 /// A struct containing information about a JSON parsing error. 43 /// 44 struct JsParseError { JsParseErrorJsParseError45 JsParseError() : line(0), column(0) { } 46 unsigned int line; 47 unsigned int column; 48 std::string reason; 49 }; 50 51 /// Parse the contents of input stream \p istr and return a JsValue. On 52 /// failure, this returns a null JsValue. 53 JS_API 54 JsValue JsParseStream(std::istream& istr, JsParseError* error = 0); 55 56 /// Parse the contents of the JSON string \p data and return it as a JsValue. 57 /// On failure, this returns a null JsValue. 58 JS_API 59 JsValue JsParseString(const std::string& data, JsParseError* error = 0); 60 61 /// Convert the JsValue \p value to JSON and write the result to output stream 62 /// \p ostr. 63 JS_API 64 void JsWriteToStream(const JsValue& value, std::ostream& ostr); 65 66 /// Convert the JsValue \p value to JSON and return it as a string. 67 JS_API 68 std::string JsWriteToString(const JsValue& value); 69 70 /// \class JsWriter 71 /// 72 /// This class provides an interface to writing json values directly to a 73 /// stream. This can be much more efficient than constructing a JsValue instance 74 /// and using JsWriteToStream if the data size is significant. 75 /// 76 class JsWriter { 77 public: 78 enum class Style { 79 Compact, 80 Pretty 81 }; 82 83 /// Constructor. The lifetime of the /p ostr parameter is assumed to be 84 /// longer than the JsWriter instance. 85 JS_API JsWriter(std::ostream& ostr, Style style = Style::Compact); 86 87 /// Destructor. 88 JS_API ~JsWriter(); 89 90 /// Disable copies. 91 JsWriter(const JsWriter&) = delete; 92 JsWriter& operator=(const JsWriter&) = delete; 93 94 /// Write a null value. 95 JS_API bool WriteValue(std::nullptr_t); 96 97 /// Write a boolean value. 98 JS_API bool WriteValue(bool b); 99 100 /// Write an integer value. 101 JS_API bool WriteValue(int i); 102 103 /// Write an unsigned integer value. 104 JS_API bool WriteValue(unsigned u); 105 106 /// Write a 64-bit integer value. 107 JS_API bool WriteValue(int64_t i); 108 109 /// Write a 64-bit unsigned integer value. 110 JS_API bool WriteValue(uint64_t u); 111 112 /// Write a double value. 113 JS_API bool WriteValue(double d); 114 115 /// Write a string value. 116 JS_API bool WriteValue(const std::string& s); 117 118 /// Write a string value. 119 JS_API bool WriteValue(const char* s); 120 121 /// Write a string value. 122 template< size_t N> WriteValue(const char (& s)[N])123 bool WriteValue(const char(&s)[N]) { return _String(s, N-1); } 124 125 /// Write the start of an object. 126 JS_API bool BeginObject(); 127 128 /// Write an object key. 129 JS_API bool WriteKey(const std::string&); 130 131 /// Write an object key. 132 JS_API bool WriteKey(const char*); 133 134 /// Write a string literal object key. 135 template< size_t N> WriteKey(const char (& s)[N])136 bool WriteKey(const char(&s)[N]) { return _Key(s, N-1); } 137 138 /// Convenience function to write an object key and value. 139 template<class K, class V> WriteKeyValue(K && k,V && v)140 void WriteKeyValue(K&& k, V&& v) { 141 _WriteObjectFields(std::forward<K>(k), std::forward<V>(v)); 142 } 143 144 /// Write the end of an object. 145 JS_API bool EndObject(); 146 147 /// Write the start of an array. 148 JS_API bool BeginArray(); 149 150 /// Write the end of an array. 151 JS_API bool EndArray(); 152 153 /// Convenience function to write an array of values. 154 template <class Container> WriteArray(const Container & c)155 void WriteArray(const Container& c) { 156 BeginArray(); 157 for (const auto& i : c) { 158 WriteValue(i); 159 } 160 EndArray(); 161 } 162 163 /// Convenience function to write an array of values by calling the given 164 /// functor for each item in the container. 165 template <class Container, class ItemWriteFn> WriteArray(const Container & c,const ItemWriteFn & f)166 void WriteArray(const Container& c, const ItemWriteFn& f) { 167 BeginArray(); 168 for (const auto& i : c) { 169 f(*this, i); 170 } 171 EndArray(); 172 } 173 174 /// Convenience function to write an array of values given two iterators by 175 /// calling the given functor for each item in the container. 176 template <class Iterator, class ItemWriteFn> WriteArray(const Iterator & begin,const Iterator & end,const ItemWriteFn & f)177 void WriteArray( 178 const Iterator& begin, const Iterator& end, const ItemWriteFn& f) { 179 BeginArray(); 180 for (Iterator i = begin; i != end; ++i) { 181 f(*this, i); 182 } 183 EndArray(); 184 } 185 186 /// Convenience function to write an object given key value pair arguments. 187 /// key arguments must be convertable to strings, value argruments must be 188 /// either a writable type, or a callablable type taking a JsWriter&. 189 template< class ...T> WriteObject(T &&...f)190 void WriteObject(T&&... f) { 191 static_assert(sizeof...(T) %2 == 0, 192 "Arguments must come in key value pairs"); 193 BeginObject(); 194 _WriteObjectFields(std::forward<T>(f)...); 195 EndObject(); 196 } 197 198 private: 199 // Don't want implicit casts to write functions, its better to get an error. 200 template <class T> 201 bool WriteValue(T) = delete; 202 203 JS_API bool _String(const char* s, size_t len); 204 JS_API bool _Key(const char* s, size_t len); 205 206 template <class KeyType, class T> 207 auto _WriteObjectFields(KeyType&& key, T&& v) 208 -> decltype(WriteValue(std::forward<T>(v)), void()) { 209 WriteKey(std::forward<KeyType>(key)); 210 WriteValue(std::forward<T>(v)); 211 } 212 213 template <class KeyType, class T> 214 auto _WriteObjectFields(KeyType&& key, T&& v) 215 -> decltype(v(std::declval<JsWriter&>()), void()) { 216 WriteKey(std::forward<KeyType>(key)); 217 v(*this); 218 } 219 220 template< class Key0, class T0, class ...T> _WriteObjectFields(Key0 && key0,T0 && f0,T &&...f)221 void _WriteObjectFields(Key0&& key0, T0&& f0, T&&...f){ 222 _WriteObjectFields(std::forward<Key0>(key0), std::forward<T0>(f0)); 223 _WriteObjectFields(std::forward<T>(f)...); 224 } 225 226 class _Impl; 227 std::unique_ptr<_Impl> _impl; 228 }; 229 230 /// Write a json value. 231 JS_API void JsWriteValue(JsWriter* writer, const JsValue& value); 232 233 PXR_NAMESPACE_CLOSE_SCOPE 234 235 #endif // PXR_BASE_JS_JSON_H 236