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