9 static const char rcsid[] __attribute__((used)) =
"$Id: Object.cpp 1702 2016-08-13 23:26:06Z sella $";
13 #include "../util/String.h"
14 #include "../util/CommonMacro.h"
18 using namespace sella::variant;
20 Object::Object() throw () :
Nullable(std::make_shared<std::map<std::
string,
Variant>>()) { }
22 Object::Object(
const std::string &value)
throw (TypeCastException) :
Nullable() {
24 this->value = std::make_shared<std::map<std::string, Variant>>();
26 std::vector<std::string> token = this->tokenize(value, Object::Pattern());
31 this->it = std::static_pointer_cast<std::map<std::string, Variant>>(this->value)->begin();
34 Object::Object(
const std::vector<std::string> &token)
throw (TypeCastException) :
Nullable() {
36 this->value = std::make_shared<std::map<std::string, Variant>>();
41 this->it = std::static_pointer_cast<std::map<std::string, Variant>>(this->value)->begin();
45 unmsgpack(mpack, offset);
46 this->it = std::static_pointer_cast<std::map<std::string, Variant>>(this->value)->begin();
49 Object::Object(
const std::map<std::string, Variant> &value)
throw () :
Nullable() {
50 this->value = std::make_shared<std::map<std::string, Variant>>(value);
51 this->it = std::static_pointer_cast<std::map<std::string, Variant>>(this->value)->begin();
54 Object::Object(std::map<std::string, Variant> &&value) throw () :
Nullable() {
55 this->value = std::make_shared<std::map<std::string, Variant>>(std::move(value));
56 this->it = std::static_pointer_cast<std::map<std::string, Variant>>(this->value)->begin();
60 if (LIKELY(
this != &other)) {
61 if (LIKELY(!other.isNull())) {
62 if (UNLIKELY(isNull())) {
63 this->value = std::make_shared<std::map<std::string, Variant>>(other.get());
65 *std::static_pointer_cast<std::map<std::string, Variant>>(this->value) = *std::static_pointer_cast<std::map<std::string, Variant>>(other.value);
75 if (LIKELY(!other.isNull())) {
76 this->value = std::move(other.value);
77 this->it = std::move(other.it);
83 Object::~Object() throw () { }
85 std::map<std::string, Variant>::iterator Object::begin() throw (UnsupportedOperatorException) {
89 std::map<std::string, Variant>::iterator Object::end() throw (UnsupportedOperatorException) {
93 std::map<std::string, Variant>::const_iterator Object::cbegin()
const throw (UnsupportedOperatorException) {
94 return get().cbegin();
97 std::map<std::string, Variant>::const_iterator Object::cend()
const throw (UnsupportedOperatorException) {
101 bool Object::operator==(
const Object &other)
const throw () {
102 return (*std::static_pointer_cast<std::map<std::string, Variant>>(this->value) == *std::static_pointer_cast<std::map<std::string, Variant>>(other.value));
105 bool Object::operator!=(
const Object &other)
const throw () {
106 return !(*
this == other);
109 Object& Object::operator=(
const Object &other)
throw () {
110 if (LIKELY(
this != &other)) {
111 if (LIKELY(!other.isNull())) {
112 if (UNLIKELY(isNull())) {
113 this->value = std::make_shared<std::map<std::string, Variant>>(other.get());
115 *std::static_pointer_cast<std::map<std::string, Variant>>(this->value) = *std::static_pointer_cast<std::map<std::string, Variant>>(other.value);
127 if (LIKELY(
this != &other)) {
128 if (LIKELY(!other.isNull())) {
129 this->value = std::move(other.value);
130 this->it = std::move(other.it);
140 if (UNLIKELY(isNull())) {
141 this->value = std::make_shared<std::map<std::string, Variant>>();
144 if (UNLIKELY(
this == &(other.get<
Object>()))) {
148 auto &o = *std::static_pointer_cast<std::map<std::string, Variant>>(this->value);
149 auto &o2 = other.get<
Object>().
get();
151 o.insert(o2.begin(), o2.end());
157 if (UNLIKELY(isNull())) {
158 this->value = std::make_shared<std::map<std::string, Variant>>();
161 if (UNLIKELY(
this == &(other.get<
Object>()))) {
165 auto &o = *std::static_pointer_cast<std::map<std::string, Variant>>(this->value);
166 auto &o2 = other.get<
Object>().
get();
169 std::move(o2.begin(), o2.end(), std::inserter(o, o.begin()));
174 Variant& Object::operator[](
const std::string &key)
throw () {
175 if (UNLIKELY(isNull())) {
176 this->value = std::make_shared<std::map<std::string, Variant>>();
179 auto &o = *std::static_pointer_cast<std::map<std::string, Variant>>(this->value);
184 Variant& Object::operator[](std::string &&key) throw () {
185 if (UNLIKELY(isNull())) {
186 this->value = std::make_shared<std::map<std::string, Variant>>();
189 auto &o = *std::static_pointer_cast<std::map<std::string, Variant>>(this->value);
191 return o[std::move(key)];
194 const std::map<std::string, Variant>& Object::get()
const throw (UnsupportedOperatorException) {
195 if (UNLIKELY(isNull())) {
196 THROW(UnsupportedOperatorException,
"unable to take reference of null value");
199 return *std::static_pointer_cast<std::map<std::string, Variant>>(this->value);
202 std::map<std::string, Variant>& Object::get() throw (UnsupportedOperatorException) {
203 if (UNLIKELY(isNull())) {
204 THROW(UnsupportedOperatorException,
"unable to take reference of null value");
207 return *std::static_pointer_cast<std::map<std::string, Variant>>(this->value);
210 size_t Object::size()
const throw () {
211 if (UNLIKELY(isNull())) {
218 bool Object::empty()
const throw () {
219 if (UNLIKELY(isNull())) {
223 return get().empty();
226 void Object::clear() throw() {
227 if (UNLIKELY(isNull())) {
228 this->value = std::make_shared<std::map<std::string, Variant>>();
230 std::static_pointer_cast<std::map<std::string, Variant>>(this->value)->clear();
234 bool Object::erase(
const std::string &value)
throw () {
235 auto &o = *std::static_pointer_cast<std::map<std::string, Variant>>(this->value);
239 return (o.erase(value) > 0);
242 std::string Object::str(
int type)
const throw () {
270 if (UNLIKELY(isNull())) {
271 c = mpack.append(offset);
275 if (UNLIKELY(c == 0)) {
276 THROW(TypeCastException,
"Failed to append object '%s' at offset %d (buffer length: %d)", str(JSON).c_str(), offset, mpack.length());
279 const std::map<std::string, Variant> &data = *std::static_pointer_cast<std::map<std::string, Variant>>(this->value);
281 c = mpack.append_object(offset, data.size());
285 if (UNLIKELY(c == 0)) {
286 THROW(TypeCastException,
"Failed to append object '%s' at offset %d (buffer length: %d)", str(JSON).c_str(), offset, mpack.length());
289 for (
auto it = data.begin(), end = data.end(); it != end; ++it) {
290 auto nx = std::next(it);
293 PREFETCH(&nx->second.value, PREFETCH_RO, PREFETCH_LOCALITY_MEDIUM);
296 c = mpack.append(offset, it->first);
300 if (UNLIKELY(c == 0)) {
301 THROW(TypeCastException,
"Failed to append object '%s' at offset %d (buffer length: %d)", str(JSON).c_str(), offset, mpack.length());
304 it->second.value->msgpack(mpack, offset);
310 uint32_t c, o = offset;
312 if (UNLIKELY(isNull())) {
313 c = mpack.append(offset);
320 const std::map<std::string, Variant> &data = *std::static_pointer_cast<std::map<std::string, Variant>>(this->value);
322 if (UNLIKELY((c = mpack.append_object(offset, data.size())) == 0)) {
323 THROW(TypeCastException,
"Failed to append '%s' at offset %d (buffer length: %d)", str(JSON).c_str(), offset, mpack.length());
328 for (
auto it = data.begin(), end = data.end(); it != end; ++it) {
329 if (UNLIKELY((c = mpack.append(offset, it->first)) == 0)) {
330 THROW(TypeCastException,
"Failed to append '%s' at offset %d (buffer length: %d)", str(JSON).c_str(), offset, mpack.length());
335 if (UNLIKELY(it->second.isNull())) {
336 c = mpack.append(offset);
340 int type = it->second.getType();
344 c = mpack.append(offset, it->second.get<
Boolean>().get());
348 c = mpack.append(offset, it->second.get<
Signed>().get());
352 c = mpack.append(offset, it->second.get<
Unsigned>().get());
356 c = mpack.append(offset, it->second.get<
Double>().get());
360 c = mpack.append(offset, it->second.get<
UUID>().get().str());
364 c = mpack.append(offset, it->second.get<
String>().get());
368 c = it->second.get<
Binary>().msgpack(mpack, offset);
372 c = mpack.append(offset, (uint64_t) it->second.get<
Pointer>().get());
375 case IPAddress::Type:
376 c = mpack.append(offset, it->second.get<
IPAddress>().get().str());
380 c = mpack.append(offset, it->second.get<
IPPrefix>().get().str());
384 c = mpack.append(offset, it->second.get<
Interval>().str(JSON));
388 c = mpack.append(offset, it->second.get<
Time>().str(JSON));
392 c = mpack.append(offset, it->second.get<
Date>().str(JSON));
395 case TimeStamp::Type:
396 c = mpack.append(offset, it->second.get<
TimeStamp>().str(JSON));
400 c = it->second.get<
Vector>().msgpack(mpack, offset);
404 c = it->second.get<
Object>().msgpack(mpack, offset);
408 if (type != Object::Type && type != Vector::Type && type != Binary::Type) {
413 if (UNLIKELY(c == 0)) {
414 THROW(TypeCastException,
"Failed to append '%s' at offset %d (buffer length: %d)", str(JSON).c_str(), offset, mpack.length());
422 void Object::msgpackBufferSize(
size_t &size)
const throw () {
423 if (UNLIKELY(isNull())) {
429 const std::map<std::string, Variant> &data = *std::static_pointer_cast<std::map<std::string, Variant>>(this->value);
431 for (
auto it = data.begin(), end = data.end(); it != end; ++it) {
432 size += 5 + it->first.size();
433 it->second.value->msgpackBufferSize(size);
439 std::string Object::json()
const throw () {
440 if (UNLIKELY(isNull())) {
445 const std::map<std::string, Variant> &data = this->
get();
452 for (
auto it = data.begin(), end = data.end(); it != end; ++it) {
453 if (it->second.isNull()) {
454 output.append(
"\"").append(it->first).append(
"\": ").append(
"null, ");
455 }
else if ((!it->second.isScalar() && !it->second.isNetwork()) || it->second.isNumeric() || it->second.isBoolean()) {
456 output.append(
"\"").append(it->first).append(
"\": ").append(it->second.value->str(JSON)).append(
", ");
458 output.append(
"\"").append(it->first).append(
"\": \"").append(it->second.value->str(JSON)).append(
"\", ");
462 output.erase(output.size() - 2);
469 std::string Object::cjson()
const throw () {
470 if (UNLIKELY(isNull())) {
475 const std::map<std::string, Variant> &data = this->
get();
482 for (
auto it = data.begin(), end = data.end(); it != end; ++it) {
483 if (it->second.isNull()) {
484 output.append(
"\"").append(it->first).append(
"\":").append(
"null,");
485 }
else if ((!it->second.isScalar() && !it->second.isNetwork()) || it->second.isNumeric() || it->second.isBoolean()) {
486 output.append(
"\"").append(it->first).append(
"\":").append(it->second.value->str(CJSON)).push_back(
',');
488 output.append(
"\"").append(it->first).append(
"\":\"").append(it->second.value->str(CJSON)).append(
"\",");
492 output.erase(output.size() - 1);
493 output.push_back(
'}');
499 std::string Object::xml()
const throw () {
500 if (UNLIKELY(isNull())) {
501 return "<root null=\"true\" />";
505 const std::map<std::string, Variant> &data = this->
get();
507 for (
auto it = data.begin(), end = data.end(); it != end; ++it) {
508 if (it->second.isNull()) {
509 output.append(
"<").append(it->first).append(
" null=\"true\" />");
510 }
else if (it->second.isObject() && it->second.empty()) {
511 output.append(
"<").append(it->first).append(
" />");
513 output.append(
"<").append(it->first).append(
">").append(it->second.value->str(XML)).append(
"</").append(it->first).append(
">");
520 std::string Object::csv()
const throw () {
521 if (UNLIKELY(isNull())) {
526 const std::map<std::string, Variant> &data = this->
get();
529 for (
auto it = data.begin(), end = data.end(); it != end; ++it) {
530 if (it->second.isNull()) {
531 output.append(
"\\N,");
532 }
else if (it->second.isScalar()) {
533 output.append(
"\"").append(sella::util::String::escape((it->second.value->str(CSV)))).append(
"\",");
535 output.append(
"\"").append(sella::util::String::escape(it->second.value->str(JSON))).append(
"\",");
539 output.erase(output.size() - 1);
545 void Object::parse(
const std::vector<std::string> &token)
throw (TypeCastException) {
546 auto t = token.begin();
548 std::stack<int> type;
549 std::shared_ptr<std::map<std::string, Variant>> m = std::make_shared<std::map<std::string, Variant>>();
551 for (
auto it = token.begin(), end = token.end(); it != end; ++it) {
568 if (UNLIKELY(type.empty() || (type.top() !=
'v'))) {
569 THROW(TypeCastException,
"mismatched vector [ ... ] in text (%s)", t->c_str());
574 m->insert(std::make_pair(label,
Variant(std::vector<std::string>(t, it))));
580 if (UNLIKELY(type.empty() || (type.top() !=
'o'))) {
581 THROW(TypeCastException,
"mismatched object { ... } in text (%s)", t->c_str());
586 m->insert(std::make_pair(label,
Variant(std::vector<std::string>(t, it))));
598 label = std::string(it->begin() + 1, it->end() - 1);
600 std::string value(it->begin() + 1, it->end() - 1);
601 m->insert(std::make_pair(label,
Variant(value, Variant::TypeQuoted)));
609 m->insert(std::make_pair(label,
Variant(*it, Variant::TypeNonQuoted)));
619 std::shared_ptr<std::map<std::string, Variant>> m = std::make_shared<std::map<std::string, Variant>>();
629 mpack.scan(offset, [
this, &mpack, &m, &u](uint32_t i, uint32_t value) {
632 if (UNLIKELY(!mpack.decode(key, i))) {
633 THROW(TypeCastException,
"Failed to decode object key");
636 switch (mpack.typeof(value)) {
637 case sella::util::MessagePack::TYPE_NULL:
638 m->insert(std::make_pair(std::move(key), std::move(
Variant())));
641 case sella::util::MessagePack::TYPE_BOOLEAN:
642 if (LIKELY(mpack.decode(u.b, value))) {
643 m->insert(std::make_pair(std::move(key), std::move(
Variant(u.b))));
645 THROW(TypeCastException,
"Failed to decode boolean");
649 case sella::util::MessagePack::TYPE_SIGNED:
650 if (LIKELY(mpack.decode(u.s, value))) {
651 m->insert(std::make_pair(std::move(key), std::move(
Variant(u.s))));
653 THROW(TypeCastException,
"Failed to decode signed");
657 case sella::util::MessagePack::TYPE_UNSIGNED:
658 if (LIKELY(mpack.decode(u.u, value))) {
659 m->insert(std::make_pair(std::move(key), std::move(
Variant(u.u))));
661 THROW(TypeCastException,
"Failed to decode unsigned");
665 case sella::util::MessagePack::TYPE_FLOAT:
666 if (LIKELY(mpack.decode(u.d, value))) {
667 m->insert(std::make_pair(std::move(key), std::move(
Variant(u.d))));
669 THROW(TypeCastException,
"Failed to decode double");
673 case sella::util::MessagePack::TYPE_STRING: {
676 if (LIKELY(mpack.decode(str, value))) {
677 m->insert(std::make_pair(std::move(key), std::move(
Variant(std::move(str)))));
679 THROW(TypeCastException,
"Failed to decode string");
684 case sella::util::MessagePack::TYPE_VECTOR:
685 m->insert(std::make_pair(std::move(key), std::move(
Variant(std::move(std::make_shared<Vector>(mpack, value))))));
688 case sella::util::MessagePack::TYPE_OBJECT:
689 m->insert(std::make_pair(std::move(key), std::move(
Variant(std::move(std::make_shared<Object>(mpack, value))))));
693 THROW(TypeCastException,
"Unsupported type %u in input", mpack.typeof(value));
698 }
catch (sella::util::MemoryException &e) {
699 RETHROW(TypeCastException, e);
700 }
catch (TypeCastException &e) {
701 RETHROW(TypeCastException, e);
702 }
catch (std::exception &e) {
703 THROW(TypeCastException,
"%s", e.what());
709 bool Object::isType(
const char *value,
size_t size)
throw () {
710 return (size > 1 && value[0] ==
'{' && value[size - 1] ==
'}');