about summary refs log tree commit diff
path: root/src/libexpr/value-to-json.cc
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2013-11-18T23·03+0100
committerEelco Dolstra <eelco.dolstra@logicblox.com>2013-11-18T23·04+0100
commit77c13cdf566ffedc70d8860571afae8a6d43b552 (patch)
tree80d2c35c450911d0401e8a95d28ff9d8904b53fc /src/libexpr/value-to-json.cc
parent285df765b91588e39d6f35a32e30b84c3cb5be75 (diff)
Add a toJSON primop
Diffstat (limited to 'src/libexpr/value-to-json.cc')
-rw-r--r--src/libexpr/value-to-json.cc93
1 files changed, 93 insertions, 0 deletions
diff --git a/src/libexpr/value-to-json.cc b/src/libexpr/value-to-json.cc
new file mode 100644
index 0000000000..671a3c1197
--- /dev/null
+++ b/src/libexpr/value-to-json.cc
@@ -0,0 +1,93 @@
+#include "value-to-xml.hh"
+#include "xml-writer.hh"
+#include "eval-inline.hh"
+#include "util.hh"
+
+#include <cstdlib>
+
+
+namespace nix {
+
+
+static void escapeJSON(std::ostream & str, const string & s)
+{
+    str << "\"";
+    foreach (string::const_iterator, 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 str << *i;
+    str << "\"";
+}
+
+
+void printValueAsJSON(EvalState & state, bool strict,
+    Value & v, std::ostream & str, PathSet & context)
+{
+    checkInterrupt();
+
+    if (strict) state.forceValue(v);
+
+    switch (v.type) {
+
+        case tInt:
+            str << v.integer;
+            break;
+
+        case tBool:
+            str << (v.boolean ? "true" : "false");
+            break;
+
+        case tString:
+            copyContext(v, context);
+            escapeJSON(str, v.string.s);
+            break;
+
+        case tPath:
+            escapeJSON(str, state.copyPathToStore(context, v.path));
+            break;
+
+        case tNull:
+            str << "null";
+            break;
+
+        case tAttrs: {
+            Bindings::iterator i = v.attrs->find(state.sOutPath);
+            if (i == v.attrs->end()) {
+                str << "{";
+                StringSet names;
+                foreach (Bindings::iterator, i, *v.attrs)
+                    names.insert(i->name);
+                bool first = true;
+                foreach (StringSet::iterator, i, names) {
+                    if (!first) str << ","; else first = false;
+                    Attr & a(*v.attrs->find(state.symbols.create(*i)));
+                    escapeJSON(str, *i);
+                    str << ":";
+                    printValueAsJSON(state, strict, *a.value, str, context);
+                }
+                str << "}";
+            } else
+                printValueAsJSON(state, strict, *i->value, str, context);
+            break;
+        }
+
+        case tList: {
+            str << "[";
+            bool first = true;
+            for (unsigned int n = 0; n < v.list.length; ++n) {
+                if (!first) str << ","; else first = false;
+                printValueAsJSON(state, strict, *v.list.elems[n], str, context);
+            }
+            str << "]";
+            break;
+        }
+
+        default:
+            throw TypeError(format("cannot convert %1% to JSON") % showType(v));
+    }
+}
+
+
+}