00001
00002
00003
00004
00005
00006
00007
00008
00009 static const char rcsid[] __attribute__((used)) = "$Id: Variant.cpp 1197 2014-10-14 22:26:11Z sella $";
00010
00011 #include "Variant.h"
00012
00013 #include "../util/String.h"
00014
00015 using namespace sella::variant;
00016
00017 Variant::Variant() throw () :
00018 value(std::make_shared<Null>()),
00019 type(TypeNull),
00020 cache()
00021 { }
00022
00023 Variant::Variant(std::shared_ptr<Nullable> value, int type) throw (TypeCastException) :
00024 value(value),
00025 type(type),
00026 cache()
00027 {
00028 if ((type > TypeObject) || (type < TypeAuto)) {
00029 THROW(TypeCastException, "unknown type (%d) supplied", type);
00030 } else if (value.get() == NULL) {
00031 THROW(TypeCastException, "null shared_ptr supplied", type);
00032 }
00033 }
00034
00035 Variant::Variant(const std::string &value, int type) throw (TypeCastException) :
00036 cache()
00037 {
00038 parse(value, type);
00039 }
00040
00041 Variant::Variant(const char *value, int type) throw (TypeCastException) :
00042 cache()
00043 {
00044 parse(value, type);
00045 }
00046
00047 Variant::Variant(const sella::util::UUID &value) throw () :
00048 value(std::make_shared<UUID>(value)),
00049 type(TypeUUID),
00050 cache()
00051 { }
00052
00053 Variant::Variant(uuid_t &value) throw () :
00054 value(std::make_shared<UUID>(value)),
00055 type(TypeUUID),
00056 cache()
00057 { }
00058
00059 Variant::Variant(void *ptr) throw () :
00060 value(std::make_shared<Pointer>(ptr)),
00061 type(TypePointer),
00062 cache()
00063 { }
00064
00065 Variant::Variant(bool value) throw () :
00066 value(std::make_shared<Boolean>(value)),
00067 type(TypeBoolean),
00068 cache()
00069 { }
00070
00071 Variant::Variant(uint8_t value) throw () :
00072 value(std::make_shared<Unsigned>(value)),
00073 type(TypeUnsigned),
00074 cache()
00075 { }
00076
00077 Variant::Variant(uint16_t value) throw () :
00078 value(std::make_shared<Unsigned>(value)),
00079 type(TypeUnsigned),
00080 cache()
00081 { }
00082
00083 Variant::Variant(uint32_t value) throw () :
00084 value(std::make_shared<Unsigned>(value)),
00085 type(TypeUnsigned),
00086 cache()
00087 { }
00088
00089 Variant::Variant(uint64_t value) throw () :
00090 value(std::make_shared<Unsigned>(value)),
00091 type(TypeUnsigned),
00092 cache()
00093 { }
00094
00095 Variant::Variant(int8_t value) throw () :
00096 value(std::make_shared<Signed>(value)),
00097 type(TypeSigned),
00098 cache()
00099 { }
00100
00101 Variant::Variant(int16_t value) throw () :
00102 value(std::make_shared<Signed>(value)),
00103 type(TypeSigned),
00104 cache()
00105 { }
00106
00107 Variant::Variant(int32_t value) throw () :
00108 value(std::make_shared<Signed>(value)),
00109 type(TypeSigned),
00110 cache()
00111 { }
00112
00113 Variant::Variant(int64_t value) throw () :
00114 value(std::make_shared<Signed>(value)),
00115 type(TypeSigned),
00116 cache()
00117 { }
00118
00119 Variant::Variant(float value) throw () :
00120 value(std::make_shared<Double>(value)),
00121 type(TypeDouble),
00122 cache()
00123 { }
00124
00125 Variant::Variant(double value) throw () :
00126 value(std::make_shared<Double>(value)),
00127 type(TypeDouble),
00128 cache()
00129 { }
00130
00131 Variant::Variant(const std::vector<std::string> &token) throw (TypeCastException) :
00132 cache()
00133 {
00134 if (token.empty()) {
00135 THROW(TypeCastException, "empty token stream passed to variant");
00136 }
00137
00138 switch (token.front().at(0)) {
00139 case '[':
00140 this->value = std::make_shared<Vector>(std::vector<std::string>(token.begin() + 1, token.end()));
00141 this->type = TypeVector;
00142
00143 break;
00144
00145 case '{':
00146 this->value = std::make_shared<Object>(std::vector<std::string>(token.begin() + 1, token.end()));
00147 this->type = TypeObject;
00148
00149 break;
00150
00151 default:
00152 THROW(TypeCastException, "unknown token stream passed to variant (first token: %s)", token.front().c_str());
00153 }
00154 }
00155
00156 #ifdef __LP64__
00157 Variant::Variant(unsigned long long value) throw () :
00158 value(std::make_shared<Unsigned>(value)),
00159 type(TypeUnsigned),
00160 cache()
00161 { }
00162
00163 Variant::Variant(long long value) throw () :
00164 value(std::make_shared<Unsigned>(value)),
00165 type(TypeSigned),
00166 cache()
00167 { }
00168 #else
00169 Variant::Variant(unsigned long value) throw () :
00170 value(std::make_shared<Unsigned>(value)),
00171 type(TypeUnsigned),
00172 cache()
00173 { }
00174
00175 Variant::Variant(long value) throw () :
00176 value(std::make_shared<Unsigned>(value)),
00177 type(TypeSigned),
00178 cache()
00179 { }
00180 #endif
00181
00182 Variant::Variant(const Variant &other) throw () :
00183 value(),
00184 type(other.type),
00185 cache(other.cache)
00186 {
00187 switch (this->type) {
00188 case TypeNull:
00189 this->value = std::make_shared<Null>();
00190
00191 break;
00192
00193 case TypeBoolean:
00194 this->value = std::make_shared<Boolean>(other.get<Boolean>());
00195
00196 break;
00197
00198 case TypeSigned:
00199 this->value = std::make_shared<Signed>(other.get<Signed>());
00200
00201 break;
00202
00203 case TypeUnsigned:
00204 this->value = std::make_shared<Unsigned>(other.get<Unsigned>());
00205
00206 break;
00207
00208 case TypeDouble:
00209 this->value = std::make_shared<Double>(other.get<Double>());
00210
00211 break;
00212
00213 case TypeString:
00214 this->value = std::make_shared<String>(other.get<String>());
00215
00216 break;
00217
00218 case TypeUUID:
00219 this->value = std::make_shared<UUID>(other.get<UUID>());
00220
00221 break;
00222
00223 case TypeBinary:
00224 this->value = std::make_shared<Binary>(other.get<Binary>());
00225
00226 break;
00227
00228 case TypePointer:
00229 this->value = std::make_shared<Pointer>(other.get<Pointer>());
00230
00231 break;
00232
00233 case TypeIPAddress:
00234 this->value = std::make_shared<IPAddress>(other.get<IPAddress>());
00235
00236 break;
00237
00238 case TypeIPPrefix:
00239 this->value = std::make_shared<IPPrefix>(other.get<IPPrefix>());
00240
00241 break;
00242
00243 case TypeInterval:
00244 this->value = std::make_shared<Interval>(other.get<Interval>());
00245
00246 break;
00247
00248 case TypeTime:
00249 this->value = std::make_shared<Time>(other.get<Time>());
00250
00251 break;
00252
00253 case TypeDate:
00254 this->value = std::make_shared<Date>(other.get<Date>());
00255
00256 break;
00257
00258 case TypeTimeStamp:
00259 this->value = std::make_shared<TimeStamp>(other.get<TimeStamp>());
00260
00261 break;
00262 case TypeVector:
00263 this->value = std::make_shared<Vector>(other.get<Vector>());
00264
00265 break;
00266
00267 case TypeObject:
00268 this->value = std::make_shared<Object>(other.get<Object>());
00269
00270 break;
00271
00272 default:
00273 fprintf(stderr, "DEBUG: Missing Type in switch statements.\n");
00274 abort();
00275 }
00276 }
00277
00278 Variant::Variant(const Variant &&other) throw () :
00279 value(std::move(other.value)),
00280 type(other.type),
00281 cache(std::move(other.cache))
00282 { }
00283
00284 Variant::~Variant() throw () { }
00285
00286 Variant::iterator Variant::begin() throw () {
00287 iterator_t it;
00288 it.v = NULL;
00289
00290 if (getType() == TypeObject) {
00291 it.type = IterObject;
00292 it.oit = get<Object>().begin();
00293 } else if (getType() == TypeVector) {
00294 it.type = IterVector;
00295 it.vit = get<Vector>().begin();
00296 } else {
00297 it.type = IterScalar;
00298 it.v = this;
00299 }
00300
00301 return it;
00302 }
00303
00304 Variant::iterator Variant::end() throw () {
00305 iterator_t it;
00306 it.v = NULL;
00307
00308 if (getType() == TypeObject) {
00309 it.type = IterObject;
00310 it.oit = get<Object>().end();
00311 } else if (getType() == TypeVector) {
00312 it.type = IterVector;
00313 it.vit = get<Vector>().end();
00314 } else {
00315 it.type = IterScalar;
00316 it.v = NULL;
00317 }
00318
00319 return it;
00320 }
00321
00322 int Variant::getType() const throw (UnsupportedOperatorException) {
00323 return this->type;
00324 }
00325
00326 void Variant::setType(int type) throw (TypeCastException) {
00327 if (this->value.get() == NULL) {
00328 this->type = type;
00329 } else if (type != getType()) {
00330 switch (type) {
00331 case TypeNull:
00332 this->value = std::make_shared<Null>();
00333 break;
00334
00335 case TypeBoolean:
00336 this->value = std::make_shared<Boolean>((bool) *this);
00337 break;
00338
00339 case TypeSigned:
00340 this->value = std::make_shared<Signed>((int64_t) *this);
00341 break;
00342
00343 case TypeUnsigned:
00344 this->value = std::make_shared<Unsigned>((uint64_t) *this);
00345 break;
00346
00347 case TypeDouble:
00348 this->value = std::make_shared<Double>((double) *this);
00349 break;
00350
00351 case TypeUUID:
00352 this->value = std::make_shared<UUID>(str());
00353 break;
00354
00355 case TypeString:
00356 this->value = std::make_shared<String>(str());
00357 break;
00358
00359 case TypeBinary:
00360 this->value = std::make_shared<Binary>(str());
00361 break;
00362
00363 case TypePointer:
00364 this->value = std::make_shared<Pointer>(str());
00365 break;
00366
00367 case TypeIPAddress:
00368 this->value = std::make_shared<IPAddress>(str());
00369 break;
00370
00371 case TypeIPPrefix:
00372 this->value = std::make_shared<IPPrefix>(str());
00373 break;
00374
00375 case TypeInterval:
00376 this->value = std::make_shared<Interval>(str());
00377 break;
00378
00379 case TypeTime:
00380 this->value = std::make_shared<Time>(str());
00381 break;
00382
00383 case TypeDate:
00384 this->value = std::make_shared<Date>(str());
00385 break;
00386
00387 case TypeTimeStamp:
00388 this->value = std::make_shared<TimeStamp>(str());
00389 break;
00390
00391 case TypeVector:
00392 if (isScalar()) {
00393 this->value = std::make_shared<Vector>(str());
00394 } else {
00395 this->value = std::make_shared<Vector>(str());
00396 }
00397 break;
00398
00399 case TypeObject:
00400 this->value = std::make_shared<Object>(str());
00401 break;
00402
00403 default:
00404 THROW(TypeCastException, "unable to change type to %s(%d)", getTypeName(type), type);
00405 }
00406
00407 this->type = type;
00408 this->cache.clear();
00409 }
00410 }
00411
00412 const char* Variant::getTypeName(int type) const throw () {
00413 if (type < 0) {
00414 type = getType();
00415 }
00416
00417 switch (type) {
00418 case TypeAuto:
00419 return "auto";
00420
00421 case TypeNull:
00422 return "null";
00423
00424 case TypeBoolean:
00425 return "boolean";
00426
00427 case TypeSigned:
00428 return "signed";
00429
00430 case TypeUnsigned:
00431 return "unsigned";
00432
00433 case TypeDouble:
00434 return "double";
00435
00436 case TypeString:
00437 return "string";
00438
00439 case TypeUUID:
00440 return "uuid";
00441
00442 case TypeBinary:
00443 return "binary";
00444
00445 case TypePointer:
00446 return "pointer";
00447
00448 case TypeIPAddress:
00449 return "ipaddress";
00450
00451 case TypeIPPrefix:
00452 return "ipprefix";
00453
00454 case TypeInterval:
00455 return "interval";
00456
00457 case TypeTime:
00458 return "time";
00459
00460 case TypeDate:
00461 return "date";
00462
00463 case TypeTimeStamp:
00464 return "timestamp";
00465
00466 case TypeVector:
00467 return "vector";
00468
00469 case TypeObject:
00470 return "object";
00471
00472 default:
00473 fprintf(stderr, "DEBUG: Missing Type %d in switch statements.\n", type);
00474 abort();
00475 }
00476 }
00477
00478 Variant& Variant::parse(const std::string &value, int type) throw (TypeCastException) {
00479 std::string trimmed = sella::util::String::trim(value);
00480
00481 if ((type == TypeAuto) && (trimmed.size() > 0)) {
00482 if (boost::regex_match(trimmed, Signed::Pattern)) {
00483 type = TypeSigned;
00484 } else if (boost::regex_match(trimmed, Unsigned::Pattern)) {
00485 type = TypeUnsigned;
00486 } else if (boost::regex_match(trimmed, Double::Pattern)) {
00487 type = TypeDouble;
00488 } else if (boost::regex_match(trimmed, UUID::Pattern)) {
00489 type = TypeUUID;
00490 } else if (boost::regex_match(trimmed, Boolean::Pattern)) {
00491 type = TypeBoolean;
00492 } else if (boost::regex_match(trimmed, Binary::Pattern)) {
00493 type = TypeBinary;
00494 #if 0
00495 } else if (boost::regex_match(trimmed, Pointer::Pattern)) {
00496 type = TypePointer;
00497 #endif
00498 } else if (boost::regex_match(trimmed, IPAddress::Pattern)) {
00499 type = TypeIPAddress;
00500 } else if (boost::regex_match(trimmed, IPPrefix::Pattern)) {
00501 type = TypeIPPrefix;
00502 } else if (boost::regex_match(trimmed, Interval::Pattern)) {
00503 type = TypeInterval;
00504 } else if (boost::regex_match(trimmed, Time::Pattern)) {
00505 type = TypeTime;
00506 } else if (boost::regex_match(trimmed, Date::Pattern)) {
00507 type = TypeDate;
00508 } else if (boost::regex_match(trimmed, TimeStamp::Pattern)) {
00509 type = TypeTimeStamp;
00510 } else if (boost::regex_match(trimmed, Vector::Pattern)) {
00511 type = TypeVector;
00512 } else if (boost::regex_match(trimmed, Object::Pattern)) {
00513 type = TypeObject;
00514 } else {
00515 type = TypeString;
00516 }
00517 } else if (type == TypeAuto) {
00518 type = TypeString;
00519 }
00520
00521 switch (type) {
00522 case TypeNull:
00523 this->value = std::make_shared<Null>();
00524 this->type = TypeNull;
00525 break;
00526
00527 case TypeBoolean:
00528 this->value = std::make_shared<Boolean>(trimmed);
00529 this->type = TypeBoolean;
00530 break;
00531
00532 case TypeSigned:
00533 try {
00534 this->value = std::make_shared<Signed>(trimmed);
00535 this->type = TypeSigned;
00536
00537 break;
00538 } catch (TypeCastException &e) { }
00539
00540 case TypeUnsigned:
00541 this->value = std::make_shared<Unsigned>(trimmed);
00542 this->type = TypeUnsigned;
00543 break;
00544
00545 case TypeDouble:
00546 this->value = std::make_shared<Double>(trimmed);
00547 this->type = TypeDouble;
00548 break;
00549
00550 case TypeUUID:
00551 this->value = std::make_shared<UUID>(trimmed);
00552 this->type = TypeUUID;
00553
00554 break;
00555
00556 case TypeString:
00557 this->value = std::make_shared<String>(value);
00558 this->type = TypeString;
00559 break;
00560
00561 case TypeBinary:
00562 this->value = std::make_shared<Binary>(trimmed);
00563 this->type = TypeBinary;
00564 break;
00565
00566 case TypePointer:
00567 this->value = std::make_shared<Pointer>(trimmed);
00568 this->type = TypePointer;
00569 break;
00570
00571 case TypeIPAddress:
00572 this->value = std::make_shared<IPAddress>(trimmed);
00573 this->type = TypeIPAddress;
00574 break;
00575
00576 case TypeIPPrefix:
00577 this->value = std::make_shared<IPPrefix>(trimmed);
00578 this->type = TypeIPPrefix;
00579 break;
00580
00581 case TypeInterval:
00582 this->value = std::make_shared<Interval>(trimmed);
00583 this->type = TypeInterval;
00584 break;
00585
00586 case TypeTime:
00587 this->value = std::make_shared<Time>(trimmed);
00588 this->type = TypeTime;
00589 break;
00590
00591 case TypeDate:
00592 this->value = std::make_shared<Date>(trimmed);
00593 this->type = TypeDate;
00594 break;
00595
00596 case TypeTimeStamp:
00597 this->value = std::make_shared<TimeStamp>(trimmed);
00598 this->type = TypeTimeStamp;
00599 break;
00600
00601 case TypeVector:
00602 this->value = std::make_shared<Vector>(trimmed);
00603 this->type = TypeVector;
00604 break;
00605
00606 case TypeObject:
00607 this->value = std::make_shared<Object>(trimmed);
00608 this->type = TypeObject;
00609 break;
00610
00611 default:
00612 THROW(TypeCastException, "unknown scalar type %d supplied", type);
00613 }
00614
00615 this->cache.clear();
00616
00617 return *this;
00618 }
00619
00620 bool Variant::erase(const Variant &value) throw () {
00621 if (getType() == TypeObject) {
00622 return get<Object>().erase(value);
00623 } else if (getType() == TypeVector) {
00624 return get<Vector>().erase(value);
00625 }
00626
00627 return false;
00628 }
00629
00630 bool Variant::erase(int index) throw () {
00631 if (getType() == TypeVector) {
00632 return get<Vector>().erase(index);
00633 }
00634
00635 return false;
00636 }
00637
00638 void Variant::shrink_to_fit() throw () {
00639 std::string(cache.begin(), cache.end()).swap(cache);
00640
00641 switch (getType()) {
00642 case TypeUUID:
00643 return get<UUID>().shrink_to_fit();
00644
00645 case TypeString:
00646 return get<String>().shrink_to_fit();
00647
00648 case TypeVector:
00649 return get<Vector>().shrink_to_fit();
00650
00651 default:
00652 return get<Nullable>().shrink_to_fit();
00653 }
00654 }
00655
00656 void Variant::clear() throw () {
00657 value = std::make_shared<Null>();
00658 type = TypeNull;
00659 cache.clear();
00660 }
00661
00662 size_t Variant::size() const throw () {
00663 if (getType() == TypeObject) {
00664 return get<Object>().size();
00665 } else if (getType() == TypeVector) {
00666 return get<Vector>().size();
00667 } else if (getType() == TypeString) {
00668 return get<String>().size();
00669 } else if (getType() == TypeBinary) {
00670 return get<Binary>().size();
00671 } else if (getType() == TypeNull) {
00672 return -1;
00673 }
00674
00675 return -1;
00676 }
00677
00678 bool Variant::empty() const throw () {
00679 if (getType() == TypeObject) {
00680 return get<Object>().empty();
00681 } else if (getType() == TypeVector) {
00682 return get<Vector>().empty();
00683 } else if (getType() == TypeString) {
00684 return get<String>().empty();
00685 } else if (getType() == TypeBinary) {
00686 return get<Binary>().empty();
00687 } else if (getType() == TypeNull) {
00688 return true;
00689 }
00690
00691 return false;
00692 }
00693
00694 bool Variant::isScalar() const throw () {
00695 return !(isVector() || isObject());
00696 }
00697
00698 bool Variant::isNumeric() const throw () {
00699 return (isSigned() || isUnsigned() || isDouble());
00700 }
00701
00702 bool Variant::isTemporal() const throw () {
00703 return (isInterval() || isTime() || isDate() || isTimeStamp());
00704 }
00705
00706 bool Variant::isNull() const throw () {
00707 return (this->value->isNull());
00708 }
00709
00710 bool Variant::isBoolean() const throw () {
00711 return (getType() == TypeBoolean);
00712 }
00713
00714 bool Variant::isSigned() const throw () {
00715 return (getType() == TypeSigned);
00716 }
00717
00718 bool Variant::isUnsigned() const throw () {
00719 return (getType() == TypeUnsigned);
00720 }
00721
00722 bool Variant::isDouble() const throw () {
00723 return (getType() == TypeDouble);
00724 }
00725
00726 bool Variant::isString() const throw () {
00727 return (getType() == TypeString);
00728 }
00729
00730 bool Variant::isUUID() const throw () {
00731 return (getType() == TypeUUID);
00732 }
00733
00734 bool Variant::isBinary() const throw () {
00735 return (getType() == TypeBinary);
00736 }
00737
00738 bool Variant::isPointer() const throw () {
00739 return (getType() == TypePointer);
00740 }
00741
00742 bool Variant::isIPAddress() const throw () {
00743 return (getType() == TypeIPAddress);
00744 }
00745
00746 bool Variant::isIPPrefix() const throw () {
00747 return (getType() == TypeIPPrefix);
00748 }
00749
00750 bool Variant::isInterval() const throw () {
00751 return (getType() == TypeInterval);
00752 }
00753
00754 bool Variant::isTime() const throw () {
00755 return (getType() == TypeTime);
00756 }
00757
00758 bool Variant::isDate() const throw () {
00759 return (getType() == TypeDate);
00760 }
00761
00762 bool Variant::isTimeStamp() const throw () {
00763 return (getType() == TypeTimeStamp);
00764 }
00765
00766 bool Variant::isVector() const throw () {
00767 return (getType() == TypeVector);
00768 }
00769
00770 bool Variant::isObject() const throw () {
00771 return (getType() == TypeObject);
00772 }
00773
00774 const std::string& Variant::str(int type) const throw () {
00775 if (type != JSON) {
00776 abort();
00777 }
00778
00779 if (this->cache.empty()) {
00780 this->cache = this->value->str();
00781 }
00782
00783 return cache;
00784 }
00785
00786 const char* Variant::c_str(int type) const throw () {
00787 return str(type).c_str();
00788 }
00789
00790
00791
00792