about summary refs log tree commit diff
path: root/third_party/nix/src/libutil/json.hh
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/nix/src/libutil/json.hh')
-rw-r--r--third_party/nix/src/libutil/json.hh142
1 files changed, 142 insertions, 0 deletions
diff --git a/third_party/nix/src/libutil/json.hh b/third_party/nix/src/libutil/json.hh
new file mode 100644
index 000000000000..a3843a8a8a7b
--- /dev/null
+++ b/third_party/nix/src/libutil/json.hh
@@ -0,0 +1,142 @@
+#pragma once
+
+#include <cassert>
+#include <iostream>
+#include <vector>
+
+namespace nix {
+
+void toJSON(std::ostream& str, const char* start, const char* end);
+void toJSON(std::ostream& str, const char* s);
+
+template <typename T>
+void toJSON(std::ostream& str, const T& n);
+
+class JSONWriter {
+ protected:
+  struct JSONState {
+    std::ostream& str;
+    bool indent;
+    size_t depth = 0;
+    size_t stack = 0;
+    JSONState(std::ostream& str, bool indent) : str(str), indent(indent) {}
+    ~JSONState() { assert(stack == 0); }
+  };
+
+  JSONState* state;
+
+  bool first = true;
+
+  JSONWriter(std::ostream& str, bool indent);
+
+  JSONWriter(JSONState* state);
+
+  ~JSONWriter();
+
+  void assertActive() { assert(state->stack != 0); }
+
+  void comma();
+
+  void indent();
+};
+
+class JSONObject;
+class JSONPlaceholder;
+
+class JSONList : JSONWriter {
+ private:
+  friend class JSONObject;
+  friend class JSONPlaceholder;
+
+  void open();
+
+  JSONList(JSONState* state) : JSONWriter(state) { open(); }
+
+ public:
+  JSONList(std::ostream& str, bool indent = false) : JSONWriter(str, indent) {
+    open();
+  }
+
+  ~JSONList();
+
+  template <typename T>
+  JSONList& elem(const T& v) {
+    comma();
+    toJSON(state->str, v);
+    return *this;
+  }
+
+  JSONList list();
+
+  JSONObject object();
+
+  JSONPlaceholder placeholder();
+};
+
+class JSONObject : JSONWriter {
+ private:
+  friend class JSONList;
+  friend class JSONPlaceholder;
+
+  void open();
+
+  JSONObject(JSONState* state) : JSONWriter(state) { open(); }
+
+  void attr(const std::string& s);
+
+ public:
+  JSONObject(std::ostream& str, bool indent = false) : JSONWriter(str, indent) {
+    open();
+  }
+
+  JSONObject(const JSONObject& obj) = delete;
+
+  JSONObject(JSONObject&& obj) : JSONWriter(obj.state) { obj.state = 0; }
+
+  ~JSONObject();
+
+  template <typename T>
+  JSONObject& attr(const std::string& name, const T& v) {
+    attr(name);
+    toJSON(state->str, v);
+    return *this;
+  }
+
+  JSONList list(const std::string& name);
+
+  JSONObject object(const std::string& name);
+
+  JSONPlaceholder placeholder(const std::string& name);
+};
+
+class JSONPlaceholder : JSONWriter {
+ private:
+  friend class JSONList;
+  friend class JSONObject;
+
+  JSONPlaceholder(JSONState* state) : JSONWriter(state) {}
+
+  void assertValid() {
+    assertActive();
+    assert(first);
+  }
+
+ public:
+  JSONPlaceholder(std::ostream& str, bool indent = false)
+      : JSONWriter(str, indent) {}
+
+  ~JSONPlaceholder() { assert(!first || std::uncaught_exception()); }
+
+  template <typename T>
+  void write(const T& v) {
+    assertValid();
+    first = false;
+    toJSON(state->str, v);
+  }
+
+  JSONList list();
+
+  JSONObject object();
+};
+
+}  // namespace nix