CernVM-FS  2.13.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)
22  return NULL;
23  return json.Release();
24 }
25 
26 string JsonDocument::EscapeString(const string &input) {
27  string escaped;
28  escaped.reserve(input.length());
29 
30  for (unsigned i = 0, s = input.length(); i < s; ++i) {
31  if (input[i] == '\\') {
32  escaped.push_back('\\');
33  escaped.push_back('\\');
34  } else if (input[i] == '"') {
35  escaped.push_back('\\');
36  escaped.push_back('"');
37  } else {
38  escaped.push_back(input[i]);
39  }
40  }
41  return escaped;
42 }
43 
45  : allocator_(kDefaultBlockSize), root_(NULL), raw_text_(NULL) { }
46 
48  if (raw_text_)
49  free(raw_text_);
50 }
51 
57 bool JsonDocument::Parse(const string &text) {
58  assert(root_ == NULL);
59 
60  // The used JSON library 'vjson' is a destructive parser and therefore
61  // alters the content of the provided buffer. The buffer must persist as
62  // name and string values from JSON nodes just point into it.
63  raw_text_ = strdup(text.c_str());
64 
65  char *error_pos = 0;
66  char *error_desc = 0;
67  int error_line = 0;
68  JSON *root = json_parse(raw_text_, &error_pos, &error_desc, &error_line,
69  &allocator_);
70 
71  // check if the json string was parsed successfully
72  if (!root) {
74  "Failed to parse json string. Error at line %d: %s (%s)",
75  error_line, error_desc, error_pos);
76  return false;
77  }
78 
79  root_ = root;
80  return true;
81 }
82 
83 string JsonDocument::PrintArray(JSON *first_child, PrintOptions print_options) {
84  string result = "[";
85  if (print_options.with_whitespace) {
86  result += "\n";
87  print_options.num_indent += 2;
88  }
89  JSON *value = first_child;
90  if (value != NULL) {
91  result += PrintValue(value, print_options);
92  value = value->next_sibling;
93  }
94  while (value != NULL) {
95  result += print_options.with_whitespace ? ",\n" : ",";
96  result += PrintValue(value, print_options);
97  value = value->next_sibling;
98  }
99  if (print_options.with_whitespace) {
100  result += "\n";
101  for (unsigned i = 2; i < print_options.num_indent; ++i)
102  result.push_back(' ');
103  }
104  return result + "]";
105 }
106 
115  if (!root_)
116  return "";
117  PrintOptions print_options;
118  return PrintObject(root_->first_child, print_options);
119 }
120 
121 string JsonDocument::PrintObject(JSON *first_child,
122  PrintOptions print_options) {
123  string result = "{";
124  if (print_options.with_whitespace) {
125  result += "\n";
126  print_options.num_indent += 2;
127  }
128  JSON *value = first_child;
129  if (value != NULL) {
130  result += PrintValue(value, print_options);
131  value = value->next_sibling;
132  }
133  while (value != NULL) {
134  result += print_options.with_whitespace ? ",\n" : ",";
135  result += PrintValue(value, print_options);
136  value = value->next_sibling;
137  }
138  if (print_options.with_whitespace) {
139  result += "\n";
140  for (unsigned i = 2; i < print_options.num_indent; ++i)
141  result.push_back(' ');
142  }
143  return result + "}";
144 }
145 
150  if (!root_)
151  return "";
152  PrintOptions print_options;
153  print_options.with_whitespace = true;
154  return PrintObject(root_->first_child, print_options);
155 }
156 
157 std::string JsonDocument::PrintValue(JSON *value, PrintOptions print_options) {
158  assert(value);
159 
160  string result;
161  for (unsigned i = 0; i < print_options.num_indent; ++i)
162  result.push_back(' ');
163  if (value->name) {
164  result += "\"" + EscapeString(value->name) + "\":";
165  if (print_options.with_whitespace)
166  result += " ";
167  }
168  switch (value->type) {
169  case JSON_NULL:
170  result += "null";
171  break;
172  case JSON_OBJECT:
173  result += PrintObject(value->first_child, print_options);
174  break;
175  case JSON_ARRAY:
176  result += PrintArray(value->first_child, print_options);
177  break;
178  case JSON_STRING:
179  result += "\"" + EscapeString(value->string_value) + "\"";
180  break;
181  case JSON_INT:
182  result += StringifyInt(value->int_value);
183  break;
184  case JSON_FLOAT:
185  result += StringifyDouble(value->float_value);
186  break;
187  case JSON_BOOL:
188  result += value->int_value ? "true" : "false";
189  break;
190  default:
191  PANIC(NULL);
192  }
193  return result;
194 }
195 
196 JSON *JsonDocument::SearchInObject(const JSON *json_object, const string &name,
197  const json_type type) {
198  if (!json_object || (json_object->type != JSON_OBJECT))
199  return NULL;
200 
201  JSON *walker = json_object->first_child;
202  while (walker != NULL) {
203  if (string(walker->name) == name) {
204  return (walker->type == type) ? walker : NULL;
205  }
206  walker = walker->next_sibling;
207  }
208  return NULL;
209 }
210 
211 template<>
212 bool GetFromJSON<std::string>(const JSON *object, const std::string &name,
213  std::string *value) {
214  const JSON *o = JsonDocument::SearchInObject(object, name, JSON_STRING);
215 
216  if (o == NULL) {
217  return false;
218  }
219 
220  if (value) {
221  *value = o->string_value;
222  }
223 
224  return true;
225 }
226 
227 template<>
228 bool GetFromJSON<int>(const JSON *object, const std::string &name, int *value) {
229  const JSON *o = JsonDocument::SearchInObject(object, name, JSON_INT);
230 
231  if (o == NULL || value == NULL) {
232  return false;
233  }
234 
235  *value = o->int_value;
236 
237  return true;
238 }
239 
240 template<>
241 bool GetFromJSON<float>(const JSON *object, const std::string &name,
242  float *value) {
243  const JSON *o = JsonDocument::SearchInObject(object, name, JSON_FLOAT);
244 
245  if (o == NULL || value == NULL) {
246  return false;
247  }
248 
249  *value = o->float_value;
250 
251  return true;
252 }
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:95
std::string PrintCanonical()
std::string PrintPretty()
static JsonDocument * Create(const std::string &text)
string StringifyInt(const int64_t value)
Definition: string.cc:77
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:545