CernVM-FS  2.12.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
json_document.cc
Go to the documentation of this file.
1 
5 #include "json_document.h"
6 
7 #include <cassert>
8 #include <cstdlib>
9 #include <cstring>
10 
11 #include "util/exception.h"
12 #include "util/logging.h"
13 #include "util/pointer.h"
14 #include "util/string.h"
15 
16 using namespace std; // NOLINT
17 
18 JsonDocument *JsonDocument::Create(const string &text) {
20  bool retval = json->Parse(text);
21  if (!retval) return NULL;
22  return json.Release();
23 }
24 
25 string JsonDocument::EscapeString(const string &input) {
26  string escaped;
27  escaped.reserve(input.length());
28 
29  for (unsigned i = 0, s = input.length(); i < s; ++i) {
30  if (input[i] == '\\') {
31  escaped.push_back('\\');
32  escaped.push_back('\\');
33  } else if (input[i] == '"') {
34  escaped.push_back('\\');
35  escaped.push_back('"');
36  } else {
37  escaped.push_back(input[i]);
38  }
39  }
40  return escaped;
41 }
42 
44  : allocator_(kDefaultBlockSize), root_(NULL), raw_text_(NULL) {}
45 
47  if (raw_text_) free(raw_text_);
48 }
49 
55 bool JsonDocument::Parse(const string &text) {
56  assert(root_ == NULL);
57 
58  // The used JSON library 'vjson' is a destructive parser and therefore
59  // alters the content of the provided buffer. The buffer must persist as
60  // name and string values from JSON nodes just point into it.
61  raw_text_ = strdup(text.c_str());
62 
63  char *error_pos = 0;
64  char *error_desc = 0;
65  int error_line = 0;
66  JSON *root =
67  json_parse(raw_text_, &error_pos, &error_desc, &error_line, &allocator_);
68 
69  // check if the json string was parsed successfully
70  if (!root) {
72  "Failed to parse json string. Error at line %d: %s (%s)",
73  error_line, error_desc, error_pos);
74  return false;
75  }
76 
77  root_ = root;
78  return true;
79 }
80 
81 string JsonDocument::PrintArray(JSON *first_child, PrintOptions print_options) {
82  string result = "[";
83  if (print_options.with_whitespace) {
84  result += "\n";
85  print_options.num_indent += 2;
86  }
87  JSON *value = first_child;
88  if (value != NULL) {
89  result += PrintValue(value, print_options);
90  value = value->next_sibling;
91  }
92  while (value != NULL) {
93  result += print_options.with_whitespace ? ",\n" : ",";
94  result += PrintValue(value, print_options);
95  value = value->next_sibling;
96  }
97  if (print_options.with_whitespace) {
98  result += "\n";
99  for (unsigned i = 2; i < print_options.num_indent; ++i)
100  result.push_back(' ');
101  }
102  return result + "]";
103 }
104 
113  if (!root_) return "";
114  PrintOptions print_options;
115  return PrintObject(root_->first_child, print_options);
116 }
117 
118 string JsonDocument::PrintObject(JSON *first_child,
119  PrintOptions print_options) {
120  string result = "{";
121  if (print_options.with_whitespace) {
122  result += "\n";
123  print_options.num_indent += 2;
124  }
125  JSON *value = first_child;
126  if (value != NULL) {
127  result += PrintValue(value, print_options);
128  value = value->next_sibling;
129  }
130  while (value != NULL) {
131  result += print_options.with_whitespace ? ",\n" : ",";
132  result += PrintValue(value, print_options);
133  value = value->next_sibling;
134  }
135  if (print_options.with_whitespace) {
136  result += "\n";
137  for (unsigned i = 2; i < print_options.num_indent; ++i)
138  result.push_back(' ');
139  }
140  return result + "}";
141 }
142 
147  if (!root_) return "";
148  PrintOptions print_options;
149  print_options.with_whitespace = true;
150  return PrintObject(root_->first_child, print_options);
151 }
152 
153 std::string JsonDocument::PrintValue(JSON *value, PrintOptions print_options) {
154  assert(value);
155 
156  string result;
157  for (unsigned i = 0; i < print_options.num_indent; ++i) result.push_back(' ');
158  if (value->name) {
159  result += "\"" + EscapeString(value->name) + "\":";
160  if (print_options.with_whitespace) result += " ";
161  }
162  switch (value->type) {
163  case JSON_NULL:
164  result += "null";
165  break;
166  case JSON_OBJECT:
167  result += PrintObject(value->first_child, print_options);
168  break;
169  case JSON_ARRAY:
170  result += PrintArray(value->first_child, print_options);
171  break;
172  case JSON_STRING:
173  result += "\"" + EscapeString(value->string_value) + "\"";
174  break;
175  case JSON_INT:
176  result += StringifyInt(value->int_value);
177  break;
178  case JSON_FLOAT:
179  result += StringifyDouble(value->float_value);
180  break;
181  case JSON_BOOL:
182  result += value->int_value ? "true" : "false";
183  break;
184  default:
185  PANIC(NULL);
186  }
187  return result;
188 }
189 
190 JSON *JsonDocument::SearchInObject(const JSON *json_object, const string &name,
191  const json_type type) {
192  if (!json_object || (json_object->type != JSON_OBJECT)) return NULL;
193 
194  JSON *walker = json_object->first_child;
195  while (walker != NULL) {
196  if (string(walker->name) == name) {
197  return (walker->type == type) ? walker : NULL;
198  }
199  walker = walker->next_sibling;
200  }
201  return NULL;
202 }
203 
204 template <>
205 bool GetFromJSON<std::string>(const JSON *object, const std::string &name,
206  std::string *value) {
207  const JSON *o = JsonDocument::SearchInObject(object, name, JSON_STRING);
208 
209  if (o == NULL) {
210  return false;
211  }
212 
213  if (value) {
214  *value = o->string_value;
215  }
216 
217  return true;
218 }
219 
220 template <>
221 bool GetFromJSON<int>(const JSON *object, const std::string &name, int *value) {
222  const JSON *o = JsonDocument::SearchInObject(object, name, JSON_INT);
223 
224  if (o == NULL || value == NULL) {
225  return false;
226  }
227 
228  *value = o->int_value;
229 
230  return true;
231 }
232 
233 template <>
234 bool GetFromJSON<float>(const JSON *object, const std::string &name,
235  float *value) {
236  const JSON *o = JsonDocument::SearchInObject(object, name, JSON_FLOAT);
237 
238  if (o == NULL || value == NULL) {
239  return false;
240  }
241 
242  *value = o->float_value;
243 
244  return true;
245 }
block_allocator allocator_
Definition: json_document.h:47
std::string PrintValue(JSON *value, PrintOptions print_options)
std::string PrintObject(JSON *first_child, PrintOptions print_options)
static JSON * SearchInObject(const JSON *json_object, const std::string &name, const json_type type)
#define PANIC(...)
Definition: exception.h:29
std::string PrintArray(JSON *first_child, PrintOptions print_options)
bool Parse(const std::string &text)
assert((mem||(size==0))&&"Out Of Memory")
string StringifyDouble(const double value)
Definition: string.cc:96
std::string PrintCanonical()
std::string PrintPretty()
static JsonDocument * Create(const std::string &text)
string StringifyInt(const int64_t value)
Definition: string.cc:78
static std::string EscapeString(const std::string &input)
bool GetFromJSON< int >(const JSON *object, const std::string &name, int *value)
char * raw_text_
Definition: json_document.h:49
struct json_value JSON
Definition: helper_allow.cc:11
bool GetFromJSON< float >(const JSON *object, const std::string &name, float *value)
const JSON * root() const
Definition: json_document.h:25
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)
Definition: logging.cc:528