Add logging for comparison behaviors
[hiphop-php.git] / hphp / compiler / json.h
blob85204dac2275131cc46f7835590dfa4f2e1037d3
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_JSON_H_
18 #define incl_HPHP_JSON_H_
20 #include "hphp/util/hash-map.h"
22 #include <cassert>
23 #include <map>
24 #include <memory>
25 #include <ostream>
26 #include <set>
27 #include <vector>
29 namespace HPHP { namespace JSON {
30 ///////////////////////////////////////////////////////////////////////////////
32 template <typename T> struct _OutputStream;
33 template <typename T> struct _MapStream;
34 template <typename T> struct _ListStream;
35 template <typename T> struct _ISerializable;
37 #define DEFINE_JSON_OUTPUT_TYPE(type) \
38 struct type { \
39 typedef _OutputStream<type> OutputStream; \
40 typedef _MapStream<type> MapStream; \
41 typedef _ListStream<type> ListStream; \
42 typedef _ISerializable<type> ISerializable; \
45 DEFINE_JSON_OUTPUT_TYPE(CodeError);
47 std::string Escape(const char *s);
49 template <typename T>
50 struct _ISerializable {
51 virtual ~_ISerializable() {}
53 /**
54 * Generate JSON output of this data structure.
56 virtual void serialize(_OutputStream<T> &out) const = 0;
59 struct Name {
60 explicit Name(const char *name) {
61 assert(name && *name);
62 m_name = name;
64 explicit Name(const std::string &name) {
65 assert(!name.empty());
66 m_name = name;
68 const std::string &getName() const { return m_name; }
69 private:
70 std::string m_name;
73 // struct _Null {};
74 // _Null Null;
75 enum class Null {};
77 template <typename Type>
78 struct _OutputStream {
79 explicit _OutputStream(std::ostream &out) : m_out(out) {}
81 _OutputStream &operator<< (unsigned int v) { m_out << v; return *this; }
83 _OutputStream &operator<< (int v) { m_out << v; return *this; }
85 _OutputStream &operator<< (bool v) {
86 m_out << (v ? "true" : "false");
87 return *this;
90 _OutputStream &operator<< (const char *v) {
91 m_out << "\"" << Escape(v) << "\"";
92 return *this;
95 _OutputStream &operator<< (const std::string &v) {
96 m_out << "\"" << Escape(v.c_str()) << "\"";
97 return *this;
100 _OutputStream &operator<< (const Name &n) {
101 m_out << "\"" << n.getName() << "\":";
102 return *this;
105 _OutputStream& operator<<(const Null& /*n*/) {
106 m_out << "null";
107 return *this;
110 _OutputStream &operator<< (const _ISerializable<Type> &v) {
111 v.serialize(*this);
112 return *this;
115 template<typename T>
116 _OutputStream &operator<< (const std::shared_ptr<T> &v) {
117 if (v) {
118 *this << *v;
119 } else {
120 *this << Null();
122 return *this;
125 template<typename T>
126 _OutputStream &operator<< (const std::vector<T> &v) {
127 m_out << "[";
128 for (unsigned int i = 0; i < v.size(); i++) {
129 if (i > 0) m_out << ',';
130 *this << v[i];
132 m_out << "]";
133 return *this;
136 template<typename T>
137 _OutputStream &operator<< (const std::set<T> &v) {
138 m_out << "[";
139 bool first = true;
140 for (T el: v) {
141 if (first) {
142 first = false;
143 } else {
144 m_out << ',';
146 *this << el;
148 m_out << "]";
149 return *this;
152 // TODO: std::map and std::unordered_map should share
153 // the same function...
155 template<typename K, typename T, typename C>
156 _OutputStream &operator<< (const std::map<K, T, C> &v) {
157 m_out << "{";
158 for (auto iter = v.begin(); iter != v.end(); ++iter) {
159 if (iter != v.begin()) m_out << ',';
160 *this << Name(iter->first);
161 *this << iter->second;
163 m_out << "}\n";
164 return *this;
167 template<typename K, typename T, typename H, typename E>
168 _OutputStream &operator<< (const hphp_hash_map<K, T, H, E> &v) {
169 m_out << "{";
170 for (auto iter = v.begin(); iter != v.end(); ++iter) {
171 if (iter != v.begin()) m_out << ',';
172 *this << Name(iter->first);
173 *this << iter->second;
175 m_out << "}\n";
176 return *this;
179 private:
180 std::ostream &m_out;
182 std::ostream &raw() { return m_out;}
184 friend struct _MapStream<Type>;
185 friend struct _ListStream<Type>;
188 template <typename Type>
189 struct _MapStream {
190 explicit _MapStream(_OutputStream<Type> &jout)
191 : m_out(jout.raw()), m_jout(jout), m_first(true) {}
193 template<typename T>
194 _MapStream &add(const std::string &n, T v) {
195 init(n);
196 m_jout << v;
197 return *this;
200 _MapStream &add(const std::string &n) {
201 init(n);
202 return *this;
205 void done() {
206 if (m_first) {
207 m_out << "{";
209 m_out << "}\n";
212 private:
213 std::ostream &m_out;
214 _OutputStream<Type> &m_jout;
215 bool m_first;
217 void init(const std::string &n) {
218 if (m_first) {
219 m_out << "{";
220 m_first = false;
221 } else {
222 m_out << ",";
224 m_jout << Name(n);
228 template <typename Type>
229 struct _ListStream {
230 explicit _ListStream(_OutputStream<Type> &jout)
231 : m_out(jout.raw()), m_jout(jout), m_first(true) {}
233 void next() {
234 if (m_first) {
235 m_out << "[";
236 m_first = false;
237 } else {
238 m_out << ",";
242 template<typename T>
243 _ListStream &operator<< (T &v) {
244 next();
245 m_jout << v;
246 return *this;
249 void done() {
250 if (m_first) {
251 m_out << "[";
253 m_out << "]\n";
256 private:
257 std::ostream &m_out;
258 _OutputStream<Type> &m_jout;
259 bool m_first;
262 ///////////////////////////////////////////////////////////////////////////////
265 #endif // incl_HPHP_JSON_H_