about summary refs log tree commit diff
path: root/src/libexpr
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2016-08-26T16·55+0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2016-08-29T15·29+0200
commitc0a7b84748d5e27e6804117b8a57ce71269c3c66 (patch)
tree40f22e1dd5636673f764bc1f289ab254971ca95d /src/libexpr
parent9fa21765e7f267efcc65e1aa6ab21402ea6125ad (diff)
nix path-info: Add --json flag
Also, factor out JSON generation from value-to-json.{cc,hh}, and
support producing indented JSON.
Diffstat (limited to 'src/libexpr')
-rw-r--r--src/libexpr/value-to-json.cc55
-rw-r--r--src/libexpr/value-to-json.hh71
-rw-r--r--src/libexpr/value.hh3
3 files changed, 30 insertions, 99 deletions
diff --git a/src/libexpr/value-to-json.cc b/src/libexpr/value-to-json.cc
index 47ee324a6e..72e413e449 100644
--- a/src/libexpr/value-to-json.cc
+++ b/src/libexpr/value-to-json.cc
@@ -1,4 +1,5 @@
 #include "value-to-json.hh"
+#include "json.hh"
 #include "eval-inline.hh"
 #include "util.hh"
 
@@ -8,24 +9,8 @@
 
 namespace nix {
 
-
-void escapeJSON(std::ostream & str, const string & s)
-{
-    str << "\"";
-    for (auto & i : s)
-        if (i == '\"' || i == '\\') str << "\\" << i;
-        else if (i == '\n') str << "\\n";
-        else if (i == '\r') str << "\\r";
-        else if (i == '\t') str << "\\t";
-        else if (i >= 0 && i < 32)
-            str << "\\u" << std::setfill('0') << std::setw(4) << std::hex << (uint16_t) i << std::dec;
-        else str << i;
-    str << "\"";
-}
-
-
 void printValueAsJSON(EvalState & state, bool strict,
-    Value & v, std::ostream & str, PathSet & context)
+    Value & v, JSONPlaceholder & out, PathSet & context)
 {
     checkInterrupt();
 
@@ -34,58 +19,58 @@ void printValueAsJSON(EvalState & state, bool strict,
     switch (v.type) {
 
         case tInt:
-            str << v.integer;
+            out.write(v.integer);
             break;
 
         case tBool:
-            str << (v.boolean ? "true" : "false");
+            out.write(v.boolean);
             break;
 
         case tString:
             copyContext(v, context);
-            escapeJSON(str, v.string.s);
+            out.write(v.string.s);
             break;
 
         case tPath:
-            escapeJSON(str, state.copyPathToStore(context, v.path));
+            out.write(state.copyPathToStore(context, v.path));
             break;
 
         case tNull:
-            str << "null";
+            out.write(nullptr);
             break;
 
         case tAttrs: {
             Bindings::iterator i = v.attrs->find(state.sOutPath);
             if (i == v.attrs->end()) {
-                JSONObject json(str);
+                auto obj(out.object());
                 StringSet names;
                 for (auto & j : *v.attrs)
                     names.insert(j.name);
                 for (auto & j : names) {
                     Attr & a(*v.attrs->find(state.symbols.create(j)));
-                    json.attr(j);
-                    printValueAsJSON(state, strict, *a.value, str, context);
+                    auto placeholder(obj.placeholder(j));
+                    printValueAsJSON(state, strict, *a.value, placeholder, context);
                 }
             } else
-                printValueAsJSON(state, strict, *i->value, str, context);
+                printValueAsJSON(state, strict, *i->value, out, context);
             break;
         }
 
         case tList1: case tList2: case tListN: {
-            JSONList json(str);
+            auto list(out.list());
             for (unsigned int n = 0; n < v.listSize(); ++n) {
-                json.elem();
-                printValueAsJSON(state, strict, *v.listElems()[n], str, context);
+                auto placeholder(list.placeholder());
+                printValueAsJSON(state, strict, *v.listElems()[n], placeholder, context);
             }
             break;
         }
 
         case tExternal:
-            v.external->printValueAsJSON(state, strict, str, context);
+            v.external->printValueAsJSON(state, strict, out, context);
             break;
 
         case tFloat:
-            str << v.fpoint;
+            out.write(v.fpoint);
             break;
 
         default:
@@ -93,9 +78,15 @@ void printValueAsJSON(EvalState & state, bool strict,
     }
 }
 
+void printValueAsJSON(EvalState & state, bool strict,
+    Value & v, std::ostream & str, PathSet & context)
+{
+    JSONPlaceholder out(str);
+    printValueAsJSON(state, strict, v, out, context);
+}
 
 void ExternalValueBase::printValueAsJSON(EvalState & state, bool strict,
-      std::ostream & str, PathSet & context) const
+    JSONPlaceholder & out, PathSet & context) const
 {
     throw TypeError(format("cannot convert %1% to JSON") % showType());
 }
diff --git a/src/libexpr/value-to-json.hh b/src/libexpr/value-to-json.hh
index c59caf5641..67fed6487d 100644
--- a/src/libexpr/value-to-json.hh
+++ b/src/libexpr/value-to-json.hh
@@ -8,73 +8,12 @@
 
 namespace nix {
 
-void printValueAsJSON(EvalState & state, bool strict,
-    Value & v, std::ostream & out, PathSet & context);
-
-void escapeJSON(std::ostream & str, const string & s);
+class JSONPlaceholder;
 
-struct JSONObject
-{
-    std::ostream & str;
-    bool first;
-    JSONObject(std::ostream & str) : str(str), first(true)
-    {
-        str << "{";
-    }
-    ~JSONObject()
-    {
-        str << "}";
-    }
-    void attr(const string & s)
-    {
-        if (!first) str << ","; else first = false;
-        escapeJSON(str, s);
-        str << ":";
-    }
-    void attr(const string & s, const string & t)
-    {
-        attr(s);
-        escapeJSON(str, t);
-    }
-    void attr(const string & s, const char * t)
-    {
-        attr(s);
-        escapeJSON(str, t);
-    }
-    void attr(const string & s, bool b)
-    {
-        attr(s);
-        str << (b ? "true" : "false");
-    }
-    template<typename T>
-    void attr(const string & s, const T & n)
-    {
-        attr(s);
-        str << n;
-    }
-};
+void printValueAsJSON(EvalState & state, bool strict,
+    Value & v, JSONPlaceholder & out, PathSet & context);
 
-struct JSONList
-{
-    std::ostream & str;
-    bool first;
-    JSONList(std::ostream & str) : str(str), first(true)
-    {
-        str << "[";
-    }
-    ~JSONList()
-    {
-        str << "]";
-    }
-    void elem()
-    {
-        if (!first) str << ","; else first = false;
-    }
-    void elem(const string & s)
-    {
-        elem();
-        escapeJSON(str, s);
-    }
-};
+void printValueAsJSON(EvalState & state, bool strict,
+    Value & v, std::ostream & str, PathSet & context);
 
 }
diff --git a/src/libexpr/value.hh b/src/libexpr/value.hh
index 62bdd9281f..f5e4857488 100644
--- a/src/libexpr/value.hh
+++ b/src/libexpr/value.hh
@@ -36,6 +36,7 @@ class Symbol;
 struct Pos;
 class EvalState;
 class XMLWriter;
+class JSONPlaceholder;
 
 
 typedef long NixInt;
@@ -73,7 +74,7 @@ class ExternalValueBase
 
     /* Print the value as JSON. Defaults to unconvertable, i.e. throws an error */
     virtual void printValueAsJSON(EvalState & state, bool strict,
-        std::ostream & str, PathSet & context) const;
+        JSONPlaceholder & out, PathSet & context) const;
 
     /* Print the value as XML. Defaults to unevaluated */
     virtual void printValueAsXML(EvalState & state, bool strict, bool location,