diff options
author | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2016-08-26 18:55:55 +0200 |
---|---|---|
committer | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2016-08-29 17:29:24 +0200 |
commit | c0a7b84748d5e27e6804117b8a57ce71269c3c66 (patch) | |
tree | 40f22e1dd5636673f764bc1f289ab254971ca95d /src/libutil/json.cc | |
parent | 9fa21765e7f267efcc65e1aa6ab21402ea6125ad (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/libutil/json.cc')
-rw-r--r-- | src/libutil/json.cc | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/src/libutil/json.cc b/src/libutil/json.cc new file mode 100644 index 000000000..619b1d631 --- /dev/null +++ b/src/libutil/json.cc @@ -0,0 +1,171 @@ +#include "json.hh" + +#include <iomanip> +#include <cstring> + +namespace nix { + +void toJSON(std::ostream & str, const char * start, const char * end) +{ + str << '"'; + for (auto i = start; i != end; i++) + 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 toJSON(std::ostream & str, const std::string & s) +{ + toJSON(str, s.c_str(), s.c_str() + s.size()); +} + +void toJSON(std::ostream & str, const char * s) +{ + if (!s) str << "null"; else toJSON(str, s, s + strlen(s)); +} + +void toJSON(std::ostream & str, unsigned long n) +{ + str << n; +} + +void toJSON(std::ostream & str, long n) +{ + str << n; +} + +void toJSON(std::ostream & str, double f) +{ + str << f; +} + +void toJSON(std::ostream & str, bool b) +{ + str << (b ? "true" : "false"); +} + +JSONWriter::JSONWriter(std::ostream & str, bool indent) + : state(new JSONState(str, indent)) +{ + state->stack.push_back(this); +} + +JSONWriter::JSONWriter(JSONState * state) + : state(state) +{ + state->stack.push_back(this); +} + +JSONWriter::~JSONWriter() +{ + assertActive(); + state->stack.pop_back(); + if (state->stack.empty()) delete state; +} + +void JSONWriter::comma() +{ + assertActive(); + if (first) { + first = false; + } else { + state->str << ','; + } + if (state->indent) indent(); +} + +void JSONWriter::indent() +{ + state->str << '\n' << std::string(state->depth * 2, ' '); +} + +void JSONList::open() +{ + state->depth++; + state->str << '['; +} + +JSONList::~JSONList() +{ + state->depth--; + if (state->indent && !first) indent(); + state->str << "]"; +} + +JSONList JSONList::list() +{ + comma(); + return JSONList(state); +} + +JSONObject JSONList::object() +{ + comma(); + return JSONObject(state); +} + +JSONPlaceholder JSONList::placeholder() +{ + comma(); + return JSONPlaceholder(state); +} + +void JSONObject::open() +{ + state->depth++; + state->str << '{'; +} + +JSONObject::~JSONObject() +{ + state->depth--; + if (state->indent && !first) indent(); + state->str << "}"; +} + +void JSONObject::attr(const std::string & s) +{ + comma(); + toJSON(state->str, s); + state->str << ':'; + if (state->indent) state->str << ' '; +} + +JSONList JSONObject::list(const std::string & name) +{ + attr(name); + return JSONList(state); +} + +JSONObject JSONObject::object(const std::string & name) +{ + attr(name); + return JSONObject(state); +} + +JSONPlaceholder JSONObject::placeholder(const std::string & name) +{ + attr(name); + return JSONPlaceholder(state); +} + +JSONList JSONPlaceholder::list() +{ + assertValid(); + first = false; + return JSONList(state); +} + +JSONObject JSONPlaceholder::object() +{ + assertValid(); + first = false; + return JSONObject(state); +} + +} |