00001
00002
00003
00004
00005
00006
00007
00008
00009 static const char rcsid[] __attribute__((used)) = "$Id: Object.cpp 1197 2014-10-14 22:26:11Z sella $";
00010
00011 #include "Object.h"
00012 #include "Variant.h"
00013
00014 #include <stack>
00015
00016 using namespace sella::variant;
00017
00018 const boost::regex Object::Pattern("^\\{(.*)\\}$");
00019
00020 Object::Object() throw () : Nullable() { }
00021
00022 Object::Object(const std::string &value) throw (TypeCastException) : Nullable() {
00023 std::vector<std::string> token = this->tokenize(value, Object::Pattern);
00024
00025 parse(token);
00026 this->it = std::static_pointer_cast<std::map<std::string, Variant>>(this->value)->begin();
00027 }
00028
00029 Object::Object(const std::vector<std::string> &token) throw (TypeCastException) : Nullable() {
00030 parse(token);
00031 this->it = std::static_pointer_cast<std::map<std::string, Variant>>(this->value)->begin();
00032 }
00033
00034 Object::Object(const std::map<std::string, Variant> &value) throw () : Nullable() {
00035 this->value = std::make_shared<std::map<std::string, Variant>>(value);
00036 this->it = std::static_pointer_cast<std::map<std::string, Variant>>(this->value)->begin();
00037 }
00038
00039 Object::Object(const Object &other) throw () : Nullable(other) {
00040 if (!other.isNull()) {
00041 this->value = std::make_shared<std::map<std::string, Variant>>(*other.getObject());
00042 }
00043 this->it = other.it;
00044 }
00045
00046 Object::~Object() throw () { }
00047
00048 std::map<std::string, Variant>::iterator Object::begin() throw () {
00049 return getRef().begin();
00050 }
00051
00052 std::map<std::string, Variant>::iterator Object::end() throw () {
00053 return getRef().end();
00054 }
00055
00056 std::map<std::string, Variant>::const_iterator Object::cbegin() const throw () {
00057 return getRef().cbegin();
00058 }
00059
00060 std::map<std::string, Variant>::const_iterator Object::cend() const throw () {
00061 return getRef().cend();
00062 }
00063
00064 bool Object::operator==(const Object &other) const throw () {
00065 return (*std::static_pointer_cast<std::map<std::string, Variant>>(this->value) == *std::static_pointer_cast<std::map<std::string, Variant>>(other.value));
00066 }
00067
00068 bool Object::operator!=(const Object &other) const throw () {
00069 return !(*this == other);
00070 }
00071
00072 Object& Object::operator=(const Object &other) throw () {
00073 if (this != &other) {
00074 Nullable::operator=(other);
00075 if (!other.isNull()) {
00076 this->value = std::make_shared<std::map<std::string, Variant>>(*other.getObject());
00077 }
00078 it = other.it;
00079 }
00080
00081 return *this;
00082 }
00083
00084 Object& Object::operator+=(const Variant &other) throw () {
00085 if (isNull()) {
00086 this->value = std::make_shared<std::map<std::string, Variant>>();
00087 }
00088
00089 if (this == &(other.get<Object>())) {
00090 fprintf(stderr, "DEBUG: Attempt to append object to itself\n");
00091
00092 return *this;
00093 }
00094
00095 cache.clear();
00096
00097 auto &o = *std::static_pointer_cast<std::map<std::string, Variant>>(this->value);
00098 auto &o2 = *(other.get<Object>().getObject());
00099
00100 o.insert(o2.begin(), o2.end());
00101
00102 return *this;
00103 }
00104
00105 const Variant& Object::operator[](const std::string &key) const throw () {
00106 const static Variant n;
00107
00108 if (isNull()) {
00109 return n;
00110 }
00111
00112 auto &o = *std::static_pointer_cast<std::map<std::string, Variant>>(this->value);
00113
00114 return o[key];
00115 }
00116
00117 Variant& Object::operator[](const std::string &key) throw () {
00118 if (isNull()) {
00119 this->value = std::make_shared<std::map<std::string, Variant>>();
00120 }
00121
00122 cache.clear();
00123
00124 auto &o = *std::static_pointer_cast<std::map<std::string, Variant>>(this->value);
00125
00126 return o[key];
00127 }
00128
00129 const std::map<std::string, Variant>* Object::getObject() const throw (UnsupportedOperatorException) {
00130 if (isNull()) {
00131 THROW(UnsupportedOperatorException, "unable to take reference of null value");
00132 }
00133
00134 return &(*std::static_pointer_cast<std::map<std::string, Variant>>(this->value));
00135 }
00136
00137 size_t Object::size() const throw () {
00138 if (isNull()) {
00139 return -1;
00140 }
00141
00142 return getObject()->size();
00143 }
00144
00145 bool Object::empty() const throw () {
00146 if (isNull()) {
00147 return true;
00148 }
00149
00150 return getObject()->empty();
00151 }
00152
00153 bool Object::erase(const Variant &value) throw () {
00154 auto &o = *std::static_pointer_cast<std::map<std::string, Variant>>(this->value);
00155
00156 cache.clear();
00157 it = o.begin();
00158
00159 return (o.erase(value.str()) > 0);
00160 }
00161
00162 const std::string& Object::str() const throw () {
00163 if (cache.empty()) {
00164 if (this->isNull()) {
00165 cache = "null";
00166 } else {
00167 const std::map<std::string, Variant> *data = this->getObject();
00168
00169 if (data->empty()) {
00170 cache = std::string("{ }");
00171 } else {
00172 std::string buffer("{ ");
00173
00174 for (auto it = data->begin(); it != data->end(); ++it) {
00175 if (!it->second.isScalar() || it->second.isNumeric() || it->second.isBoolean() || it->second.isNull()) {
00176 buffer.append("\"").append(it->first).append("\": ").append(it->second.str()).append(", ");
00177 } else {
00178 buffer.append("\"").append(it->first).append("\": \"").append(it->second.str()).append("\", ");
00179 }
00180 }
00181 buffer.erase(buffer.size() - 2);
00182 cache = buffer.append(" }");
00183 }
00184 }
00185 }
00186
00187 return cache;
00188 }
00189
00190 std::map<std::string, Variant>& Object::getRef() throw () {
00191 return *std::static_pointer_cast<std::map<std::string, Variant>>(this->value);
00192 }
00193
00194 const std::map<std::string, Variant>& Object::getRef() const throw () {
00195 return *std::static_pointer_cast<std::map<std::string, Variant>>(this->value);
00196 }
00197
00198 void Object::parse(const std::vector<std::string> &token) throw (TypeCastException) {
00199 auto t = token.begin();
00200 std::string label;
00201 std::stack<int> type;
00202 std::shared_ptr<std::map<std::string, Variant>> m = std::make_shared<std::map<std::string, Variant>>();
00203
00204 for (auto it = token.begin(); it != token.end(); ++it) {
00205 switch (it->at(0)) {
00206 case '[':
00207 if (type.empty()) {
00208 t = it;
00209 }
00210 type.push('v');
00211 break;
00212
00213 case '{':
00214 if (type.empty()) {
00215 t = it;
00216 }
00217 type.push('o');
00218 break;
00219
00220 case ']':
00221 if (type.empty() || (type.top() != 'v')) {
00222 THROW(TypeCastException, "mismatched vector [ ... ] in text (%s)", "TODO");
00223 }
00224 type.pop();
00225
00226 if (type.empty()) {
00227 m->insert(std::make_pair(label, Variant(std::vector<std::string>(t, it))));
00228 label.clear();
00229 }
00230 break;
00231
00232 case '}':
00233 if (type.empty() || (type.top() != 'o')) {
00234 THROW(TypeCastException, "mismatched object { ... } in text (%s)", "TODO");
00235 }
00236 type.pop();
00237
00238 if (type.empty()) {
00239 m->insert(std::make_pair(label, Variant(std::vector<std::string>(t, it))));
00240 label.clear();
00241 }
00242 break;
00243
00244 case ':':
00245 case ',':
00246 break;
00247
00248 case '"':
00249 if (type.empty()) {
00250 if (label.empty()) {
00251 label = std::string(it->begin() + 1, it->end() - 1);
00252 } else {
00253 m->insert(std::make_pair(label, Variant(std::string(it->begin() + 1, it->end() - 1), Variant::TypeString)));
00254 label.clear();
00255 }
00256 }
00257 break;
00258
00259 default:
00260 if (type.empty()) {
00261 m->insert(std::make_pair(label, Variant(*it, Variant::TypeAuto)));
00262 label.clear();
00263 }
00264 }
00265 }
00266
00267 this->value = m;
00268 }
00269
00270
00271
00272