X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Fcommon%2Fceph_json.cc;fp=src%2Fceph%2Fsrc%2Fcommon%2Fceph_json.cc;h=e326fdebcf3267d64ed8524facf1a5eae54b2817;hb=812ff6ca9fcd3e629e49d4328905f33eee8ca3f5;hp=0000000000000000000000000000000000000000;hpb=15280273faafb77777eab341909a3f495cf248d9;p=stor4nfv.git diff --git a/src/ceph/src/common/ceph_json.cc b/src/ceph/src/common/ceph_json.cc new file mode 100644 index 0000000..e326fde --- /dev/null +++ b/src/ceph/src/common/ceph_json.cc @@ -0,0 +1,518 @@ +#include "common/ceph_json.h" +#include "include/utime.h" + +// for testing DELETE ME +#include +#include + +using namespace std; +using namespace json_spirit; + +#define dout_subsys ceph_subsys_rgw + +JSONObjIter::JSONObjIter() +{ +} + +JSONObjIter::~JSONObjIter() +{ +} + +void JSONObjIter::set(const JSONObjIter::map_iter_t &_cur, const JSONObjIter::map_iter_t &_last) +{ + cur = _cur; + last = _last; +} + +void JSONObjIter::operator++() +{ + if (cur != last) + ++cur; +} + +JSONObj *JSONObjIter::operator*() +{ + return cur->second; +} + +// does not work, FIXME +ostream& operator<<(ostream &out, const JSONObj &obj) { + out << obj.name << ": " << obj.data_string; + return out; +} + +JSONObj::~JSONObj() +{ + multimap::iterator iter; + for (iter = children.begin(); iter != children.end(); ++iter) { + JSONObj *obj = iter->second; + delete obj; + } +} + + +void JSONObj::add_child(string el, JSONObj *obj) +{ + children.insert(pair(el, obj)); +} + +bool JSONObj::get_attr(string name, string& attr) +{ + map::iterator iter = attr_map.find(name); + if (iter == attr_map.end()) + return false; + attr = iter->second; + return true; +} + +JSONObjIter JSONObj::find(const string& name) +{ + JSONObjIter iter; + map::iterator first; + map::iterator last; + first = children.find(name); + if (first != children.end()) { + last = children.upper_bound(name); + iter.set(first, last); + } + return iter; +} + +JSONObjIter JSONObj::find_first() +{ + JSONObjIter iter; + iter.set(children.begin(), children.end()); + return iter; +} + +JSONObjIter JSONObj::find_first(const string& name) +{ + JSONObjIter iter; + map::iterator first; + first = children.find(name); + iter.set(first, children.end()); + return iter; +} + +JSONObj *JSONObj::find_obj(const string& name) +{ + JSONObjIter iter = find(name); + if (iter.end()) + return NULL; + + return *iter; +} + +bool JSONObj::get_data(const string& key, string *dest) +{ + JSONObj *obj = find_obj(key); + if (!obj) + return false; + + *dest = obj->get_data(); + + return true; +} + +/* accepts a JSON Array or JSON Object contained in + * a JSON Spirit Value, v, and creates a JSONObj for each + * child contained in v + */ +void JSONObj::handle_value(Value v) +{ + if (v.type() == obj_type) { + Object temp_obj = v.get_obj(); + for (Object::size_type i = 0; i < temp_obj.size(); i++) { + Pair temp_pair = temp_obj[i]; + string temp_name = temp_pair.name_; + Value temp_value = temp_pair.value_; + JSONObj *child = new JSONObj; + child->init(this, temp_value, temp_name); + add_child(temp_name, child); + } + } else if (v.type() == array_type) { + Array temp_array = v.get_array(); + Value value; + + for (unsigned j = 0; j < temp_array.size(); j++) { + Value cur = temp_array[j]; + string temp_name; + + JSONObj *child = new JSONObj; + child->init(this, cur, temp_name); + add_child(child->get_name(), child); + } + } +} + +void JSONObj::init(JSONObj *p, Value v, string n) +{ + name = n; + parent = p; + data = v; + + handle_value(v); + if (v.type() == str_type) + data_string = v.get_str(); + else + data_string = write(v, raw_utf8); + attr_map.insert(pair(name, data_string)); +} + +JSONObj *JSONObj::get_parent() +{ + return parent; +} + +bool JSONObj::is_object() +{ + return (data.type() == obj_type); +} + +bool JSONObj::is_array() +{ + return (data.type() == array_type); +} + +vector JSONObj::get_array_elements() +{ + vector elements; + Array temp_array; + + if (data.type() == array_type) + temp_array = data.get_array(); + + int array_size = temp_array.size(); + if (array_size > 0) + for (int i = 0; i < array_size; i++) { + Value temp_value = temp_array[i]; + string temp_string; + temp_string = write(temp_value, raw_utf8); + elements.push_back(temp_string); + } + + return elements; +} + +JSONParser::JSONParser() : buf_len(0), success(true) +{ +} + +JSONParser::~JSONParser() +{ +} + + + +void JSONParser::handle_data(const char *s, int len) +{ + json_buffer.append(s, len); // check for problems with null termination FIXME + buf_len += len; +} + +// parse a supplied JSON fragment +bool JSONParser::parse(const char *buf_, int len) +{ + if (!buf_) { + set_failure(); + return false; + } + + string json_string(buf_, len); + success = read(json_string, data); + if (success) + handle_value(data); + else + set_failure(); + + return success; +} + +// parse the internal json_buffer up to len +bool JSONParser::parse(int len) +{ + string json_string = json_buffer.substr(0, len); + success = read(json_string, data); + if (success) + handle_value(data); + else + set_failure(); + + return success; +} + +// parse the complete internal json_buffer +bool JSONParser::parse() +{ + success = read(json_buffer, data); + if (success) + handle_value(data); + else + set_failure(); + + return success; +} + +// parse a supplied ifstream, for testing. DELETE ME +bool JSONParser::parse(const char *file_name) +{ + ifstream is(file_name); + success = read(is, data); + if (success) + handle_value(data); + else + set_failure(); + + return success; +} + + +void decode_json_obj(long& val, JSONObj *obj) +{ + string s = obj->get_data(); + const char *start = s.c_str(); + char *p; + + errno = 0; + val = strtol(start, &p, 10); + + /* Check for various possible errors */ + + if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || + (errno != 0 && val == 0)) { + throw JSONDecoder::err("failed to parse number"); + } + + if (p == start) { + throw JSONDecoder::err("failed to parse number"); + } + + while (*p != '\0') { + if (!isspace(*p)) { + throw JSONDecoder::err("failed to parse number"); + } + p++; + } +} + +void decode_json_obj(unsigned long& val, JSONObj *obj) +{ + string s = obj->get_data(); + const char *start = s.c_str(); + char *p; + + errno = 0; + val = strtoul(start, &p, 10); + + /* Check for various possible errors */ + + if ((errno == ERANGE && val == ULONG_MAX) || + (errno != 0 && val == 0)) { + throw JSONDecoder::err("failed to number"); + } + + if (p == start) { + throw JSONDecoder::err("failed to parse number"); + } + + while (*p != '\0') { + if (!isspace(*p)) { + throw JSONDecoder::err("failed to parse number"); + } + p++; + } +} + +void decode_json_obj(long long& val, JSONObj *obj) +{ + string s = obj->get_data(); + const char *start = s.c_str(); + char *p; + + errno = 0; + val = strtoll(start, &p, 10); + + /* Check for various possible errors */ + + if ((errno == ERANGE && (val == LLONG_MAX || val == LLONG_MIN)) || + (errno != 0 && val == 0)) { + throw JSONDecoder::err("failed to parse number"); + } + + if (p == start) { + throw JSONDecoder::err("failed to parse number"); + } + + while (*p != '\0') { + if (!isspace(*p)) { + throw JSONDecoder::err("failed to parse number"); + } + p++; + } +} + +void decode_json_obj(unsigned long long& val, JSONObj *obj) +{ + string s = obj->get_data(); + const char *start = s.c_str(); + char *p; + + errno = 0; + val = strtoull(start, &p, 10); + + /* Check for various possible errors */ + + if ((errno == ERANGE && val == ULLONG_MAX) || + (errno != 0 && val == 0)) { + throw JSONDecoder::err("failed to number"); + } + + if (p == start) { + throw JSONDecoder::err("failed to parse number"); + } + + while (*p != '\0') { + if (!isspace(*p)) { + throw JSONDecoder::err("failed to parse number"); + } + p++; + } +} + +void decode_json_obj(int& val, JSONObj *obj) +{ + long l; + decode_json_obj(l, obj); +#if LONG_MAX > INT_MAX + if (l > INT_MAX || l < INT_MIN) { + throw JSONDecoder::err("integer out of range"); + } +#endif + + val = (int)l; +} + +void decode_json_obj(unsigned& val, JSONObj *obj) +{ + unsigned long l; + decode_json_obj(l, obj); +#if ULONG_MAX > UINT_MAX + if (l > UINT_MAX) { + throw JSONDecoder::err("unsigned integer out of range"); + } +#endif + + val = (unsigned)l; +} + +void decode_json_obj(bool& val, JSONObj *obj) +{ + string s = obj->get_data(); + if (strcasecmp(s.c_str(), "true") == 0) { + val = true; + return; + } + if (strcasecmp(s.c_str(), "false") == 0) { + val = false; + return; + } + int i; + decode_json_obj(i, obj); + val = (bool)i; +} + +void decode_json_obj(bufferlist& val, JSONObj *obj) +{ + string s = obj->get_data(); + + bufferlist bl; + bl.append(s.c_str(), s.size()); + try { + val.decode_base64(bl); + } catch (buffer::error& err) { + throw JSONDecoder::err("failed to decode base64"); + } +} + +void decode_json_obj(utime_t& val, JSONObj *obj) +{ + string s = obj->get_data(); + uint64_t epoch; + uint64_t nsec; + int r = utime_t::parse_date(s, &epoch, &nsec); + if (r == 0) { + val = utime_t(epoch, nsec); + } else { + throw JSONDecoder::err("failed to decode utime_t"); + } +} + +void encode_json(const char *name, const string& val, Formatter *f) +{ + f->dump_string(name, val); +} + +void encode_json(const char *name, const char *val, Formatter *f) +{ + f->dump_string(name, val); +} + +void encode_json(const char *name, bool val, Formatter *f) +{ + string s; + if (val) + s = "true"; + else + s = "false"; + + f->dump_string(name, s); +} + +void encode_json(const char *name, int val, Formatter *f) +{ + f->dump_int(name, val); +} + +void encode_json(const char *name, long val, Formatter *f) +{ + f->dump_int(name, val); +} + +void encode_json(const char *name, unsigned val, Formatter *f) +{ + f->dump_unsigned(name, val); +} + +void encode_json(const char *name, unsigned long val, Formatter *f) +{ + f->dump_unsigned(name, val); +} + +void encode_json(const char *name, unsigned long long val, Formatter *f) +{ + f->dump_unsigned(name, val); +} + +void encode_json(const char *name, long long val, Formatter *f) +{ + f->dump_int(name, val); +} + +void encode_json(const char *name, const utime_t& val, Formatter *f) +{ + val.gmtime(f->dump_stream(name)); +} + +void encode_json(const char *name, const bufferlist& bl, Formatter *f) +{ + /* need to copy data from bl, as it is const bufferlist */ + bufferlist src = bl; + + bufferlist b64; + src.encode_base64(b64); + + string s(b64.c_str(), b64.length()); + + encode_json(name, s, f); +} +