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