00001
00002
00003
00004
00005
00006
00007
00008
00009 static const char rcsid[] __attribute__((used)) = "$Id: Nullable.cpp 1197 2014-10-14 22:26:11Z sella $";
00010
00011 #include "Nullable.h"
00012
00013 using namespace sella::variant;
00014
00015 Nullable::Nullable() throw () :
00016 value(),
00017 cache()
00018 { }
00019
00020 Nullable::Nullable(std::shared_ptr<void> value) throw () :
00021 value(value),
00022 cache()
00023 { }
00024
00025 Nullable::Nullable(const Nullable &other) throw () :
00026 value(),
00027 cache(other.cache)
00028 { }
00029
00030 Nullable::~Nullable() throw () { }
00031
00032 Nullable& Nullable::operator=(const Nullable &other) throw () {
00033 if (this != &other) {
00034 this->value.reset();
00035 this->cache = other.cache;
00036 }
00037
00038 return *this;
00039 }
00040
00041 const std::shared_ptr<void> Nullable::get() const throw () {
00042 return this->value;
00043 }
00044
00045 std::shared_ptr<void> Nullable::get() throw () {
00046 return this->value;
00047 }
00048
00049 void Nullable::shrink_to_fit() throw () {
00050 std::string(cache.begin(), cache.end()).swap(cache);
00051 }
00052
00053 const char* Nullable::c_str() const throw () {
00054 return str().c_str();
00055 }
00056
00057 bool Nullable::isNull() const throw () {
00058 return (this->value == NULL);
00059 }
00060
00061 std::vector<std::string> Nullable::tokenize(const std::string &value, const boost::regex &pattern) const throw (TypeCastException) {
00062 std::vector<std::string> tokens;
00063 boost::smatch match;
00064
00065 if (!boost::regex_match(value, match, pattern)) {
00066 if (value.at(0) == '[') {
00067 THROW(TypeCastException, "unable to tokenize vector '%s'", value.c_str());
00068 } else if (value.at(0) == '{') {
00069 THROW(TypeCastException, "unable to tokenize object '%s'", value.c_str());
00070 } else {
00071 THROW(TypeCastException, "unable to tokenize '%s'", value.c_str());
00072 }
00073 }
00074
00075 const std::string &data = match[1].str();
00076
00077 auto begin = data.begin();
00078
00079 bool str = false;
00080 bool esc = false;
00081
00082 for (auto it = data.begin(); it != data.end(); ++it) {
00083 switch (*it) {
00084 case '\\':
00085 if (!esc) {
00086 esc = true;
00087
00088 continue;
00089 }
00090 break;
00091
00092 case '"':
00093 if (str && !esc) {
00094 tokens.push_back(std::string(begin, it + 1));
00095 begin = it + 1;
00096
00097 str = false;
00098 } else if (!esc) {
00099 begin = it;
00100
00101 str = true;
00102 }
00103 break;
00104
00105 case ' ': case '\t': case '\r': case '\n': case '\f':
00106 if (!str) {
00107 if (begin != it) {
00108 tokens.push_back(std::string(begin, it));
00109 }
00110 begin = it + 1;
00111 }
00112 break;
00113
00114 case '[': case ']': case '{': case '}': case ',': case ':':
00115 if (!str) {
00116 if (begin != it) {
00117 tokens.push_back(std::string(begin, it));
00118 }
00119 tokens.push_back(std::string(1, *it));
00120 begin = it + 1;
00121 }
00122 break;
00123
00124 default:
00125 if (!str && data.end() == std::next(it)) {
00126 tokens.push_back(std::string(begin, data.end()));
00127 }
00128 }
00129
00130
00131 if (esc) {
00132 esc = false;
00133 }
00134 }
00135
00136 return tokens;
00137 }
00138
00139
00140
00141