00001
00002
00003
00004
00005
00006
00007
00008 #include "DCPS/DdsDcps_pch.h"
00009
00010 #include "dds/DCPS/Definitions.h"
00011
00012 #ifndef OPENDDS_NO_CONTENT_SUBSCRIPTION_PROFILE
00013
00014 #include "FilterEvaluator.h"
00015 #include "FilterExpressionGrammar.h"
00016 #include "AstNodeWrapper.h"
00017 #include "Definitions.h"
00018 #include "dds/DCPS/SafetyProfileStreams.h"
00019
00020 #include <ace/ACE.h>
00021
00022 #include <stdexcept>
00023 #include <cstring>
00024 #include <algorithm>
00025
00026 namespace {
00027 const char MOD[] = "MOD";
00028 }
00029
00030 using namespace OpenDDS::DCPS::FilterExpressionGrammar;
00031
00032 namespace OpenDDS {
00033 namespace DCPS {
00034
00035 FilterEvaluator::DataForEval::~DataForEval()
00036 {}
00037
00038 FilterEvaluator::DeserializedForEval::~DeserializedForEval()
00039 {}
00040
00041 FilterEvaluator::FilterEvaluator(const char* filter, bool allowOrderBy)
00042 : extended_grammar_(false)
00043 , filter_root_(0)
00044 {
00045 const char* out = filter + std::strlen(filter);
00046 yard::SimpleTextParser parser(filter, out);
00047 if (!(allowOrderBy ? parser.Parse<QueryCompleteInput>()
00048 : parser.Parse<FilterCompleteInput>())) {
00049 reportErrors(parser, filter);
00050 }
00051
00052 bool found_order_by = false;
00053 for (AstNode* iter = parser.GetAstRoot()->GetFirstChild(); iter;
00054 iter = iter->GetSibling()) {
00055 if (iter->TypeMatches<ORDERBY>()) {
00056 found_order_by = true;
00057 } else if (found_order_by && iter->TypeMatches<FieldName>()) {
00058 order_bys_.push_back(toString(iter));
00059 } else {
00060 filter_root_ = walkAst(iter);
00061 }
00062 }
00063 }
00064
00065 FilterEvaluator::FilterEvaluator(const AstNodeWrapper& yardNode)
00066 : extended_grammar_(false)
00067 , filter_root_(walkAst(yardNode))
00068 {
00069 }
00070
00071 class FilterEvaluator::EvalNode {
00072 public:
00073 void addChild(EvalNode* n)
00074 {
00075 children_.push_back(n);
00076 }
00077
00078 virtual ~EvalNode()
00079 {
00080 std::for_each(children_.begin(), children_.end(), deleteChild);
00081 }
00082
00083 virtual Value eval(DataForEval& data) = 0;
00084
00085 private:
00086 static void deleteChild(EvalNode* child)
00087 {
00088 delete child;
00089 }
00090
00091 protected:
00092 OPENDDS_VECTOR(EvalNode*) children_;
00093 };
00094
00095 class FilterEvaluator::Operand : public FilterEvaluator::EvalNode {
00096 public:
00097 virtual bool isParameter() const { return false; }
00098 };
00099
00100 Value
00101 FilterEvaluator::DeserializedForEval::lookup(const char* field) const
00102 {
00103 return meta_.getValue(deserialized_, field);
00104 }
00105
00106 namespace {
00107 struct AMB_Releaser {
00108 explicit AMB_Releaser(ACE_Message_Block* mb) : mb_(mb) {}
00109 ~AMB_Releaser() { mb_->release(); }
00110 ACE_Message_Block* mb_;
00111 };
00112 }
00113
00114 Value
00115 FilterEvaluator::SerializedForEval::lookup(const char* field) const
00116 {
00117 const OPENDDS_MAP(OPENDDS_STRING, Value)::const_iterator iter = cache_.find(field);
00118 if (iter != cache_.end()) {
00119 return iter->second;
00120 }
00121 ACE_Message_Block* const mb = serialized_->duplicate();
00122 AMB_Releaser release(mb);
00123 Serializer ser(mb, swap_,
00124 cdr_ ? Serializer::ALIGN_CDR : Serializer::ALIGN_NONE);
00125 if (cdr_) {
00126 ser.skip(4);
00127 }
00128 const Value v = meta_.getValue(ser, field);
00129 cache_.insert(std::make_pair(OPENDDS_STRING(field), v));
00130 return v;
00131 }
00132
00133 FilterEvaluator::~FilterEvaluator()
00134 {
00135 delete filter_root_;
00136 }
00137
00138 namespace {
00139
00140 class FieldLookup : public FilterEvaluator::Operand {
00141 public:
00142 explicit FieldLookup(AstNode* fnNode)
00143 : fieldName_(toString(fnNode))
00144 {}
00145
00146 Value eval(FilterEvaluator::DataForEval& data)
00147 {
00148 return data.lookup(fieldName_.c_str());
00149 }
00150
00151 OPENDDS_STRING fieldName_;
00152 };
00153
00154 class LiteralInt : public FilterEvaluator::Operand {
00155 public:
00156 explicit LiteralInt(AstNode* fnNode)
00157 {
00158 OPENDDS_STRING strVal = toString(fnNode);
00159 if (strVal.length() > 2 && strVal[0] == '0'
00160 && (strVal[1] == 'x' || strVal[1] == 'X')) {
00161 std::istringstream is(strVal.c_str() + 2);
00162 is >> std::hex >> value_;
00163 } else {
00164 value_ = std::atoi(strVal.c_str());
00165 }
00166 }
00167
00168 Value eval(FilterEvaluator::DataForEval&)
00169 {
00170 return Value(value_, true);
00171 }
00172
00173 int value_;
00174 };
00175
00176 class LiteralChar : public FilterEvaluator::Operand {
00177 public:
00178 explicit LiteralChar(AstNode* fnNode)
00179 : value_(toString(fnNode)[1])
00180 {}
00181
00182 Value eval(FilterEvaluator::DataForEval&)
00183 {
00184 return Value(value_, true);
00185 }
00186
00187 char value_;
00188 };
00189
00190 class LiteralFloat : public FilterEvaluator::Operand {
00191 public:
00192 explicit LiteralFloat(AstNode* fnNode)
00193 : value_(std::atof(toString(fnNode).c_str()))
00194 {}
00195
00196 Value eval(FilterEvaluator::DataForEval&)
00197 {
00198 return Value(value_, true);
00199 }
00200
00201 double value_;
00202 };
00203
00204 class LiteralString : public FilterEvaluator::Operand {
00205 public:
00206 explicit LiteralString(AstNode* fnNode)
00207 : value_(toString(fnNode).substr(1) )
00208 {
00209 value_.erase(value_.length() - 1);
00210 }
00211
00212 Value eval(FilterEvaluator::DataForEval&)
00213 {
00214 return Value(value_.c_str(), true);
00215 }
00216
00217 OPENDDS_STRING value_;
00218 };
00219
00220 class Parameter : public FilterEvaluator::Operand {
00221 public:
00222 explicit Parameter(AstNode* fnNode)
00223 : param_(std::atoi(toString(fnNode).c_str() + 1 ))
00224 {}
00225
00226 bool isParameter() const { return true; }
00227
00228 Value eval(FilterEvaluator::DataForEval& data)
00229 {
00230 return Value(data.params_[param_], true);
00231 }
00232
00233 int param_;
00234 };
00235
00236 class Comparison : public FilterEvaluator::EvalNode {
00237 public:
00238 enum Operator {OPER_EQ, OPER_LT, OPER_GT, OPER_LTEQ, OPER_GTEQ, OPER_NEQ,
00239 OPER_LIKE, OPER_INVALID};
00240
00241 explicit Comparison(AstNode* op, FilterEvaluator::Operand* left, FilterEvaluator::Operand* right)
00242 : left_(left)
00243 , right_(right)
00244 {
00245 addChild(left_);
00246 addChild(right_);
00247 setOperator(op);
00248 }
00249
00250 Value eval(FilterEvaluator::DataForEval& data)
00251 {
00252 Value left = left_->eval(data);
00253 Value right = right_->eval(data);
00254 switch (oper_type_) {
00255 case OPER_EQ:
00256 return left == right;
00257 case OPER_LT:
00258 return left < right;
00259 case OPER_GT:
00260 return right < left;
00261 case OPER_LTEQ:
00262 return !(right < left);
00263 case OPER_GTEQ:
00264 return !(left < right);
00265 case OPER_NEQ:
00266 return !(left == right);
00267 case OPER_LIKE:
00268 return left.like(right);
00269 default:
00270 break;
00271 }
00272 return false;
00273 }
00274
00275 private:
00276 void setOperator(AstNode* node)
00277 {
00278 if (node->TypeMatches<OP_EQ>()) {
00279 oper_type_ = OPER_EQ;
00280 } else if (node->TypeMatches<OP_LT>()) {
00281 oper_type_ = OPER_LT;
00282 } else if (node->TypeMatches<OP_GT>()) {
00283 oper_type_ = OPER_GT;
00284 } else if (node->TypeMatches<OP_LTEQ>()) {
00285 oper_type_ = OPER_LTEQ;
00286 } else if (node->TypeMatches<OP_GTEQ>()) {
00287 oper_type_ = OPER_GTEQ;
00288 } else if (node->TypeMatches<OP_NEQ>()) {
00289 oper_type_ = OPER_NEQ;
00290 } else if (node->TypeMatches<OP_LIKE>()) {
00291 oper_type_ = OPER_LIKE;
00292 } else {
00293 oper_type_ = OPER_INVALID;
00294 }
00295 }
00296
00297 FilterEvaluator::Operand* left_;
00298 FilterEvaluator::Operand* right_;
00299 Operator oper_type_;
00300 };
00301
00302 class Between : public FilterEvaluator::EvalNode {
00303 public:
00304 Between(FilterEvaluator::Operand* field, AstNode* betweenOrNot, FilterEvaluator::Operand* left, FilterEvaluator::Operand* right)
00305 : invert_(betweenOrNot->TypeMatches<NOT_BETWEEN>())
00306 , field_(field)
00307 , left_(left)
00308 , right_(right)
00309 {
00310 addChild(field_);
00311 addChild(left_);
00312 addChild(right_);
00313 }
00314
00315 Value eval(FilterEvaluator::DataForEval& data)
00316 {
00317 Value field = field_->eval(data);
00318 Value left = left_->eval(data);
00319 Value right = right_->eval(data);
00320 bool btwn = !(field < left) && !(right < field);
00321 return invert_ ? !btwn : btwn;
00322 }
00323
00324 private:
00325 bool invert_;
00326 FilterEvaluator::Operand* field_;
00327 FilterEvaluator::Operand* left_;
00328 FilterEvaluator::Operand* right_;
00329 };
00330
00331 class Call : public FilterEvaluator::Operand {
00332 public:
00333 enum Operator { OP_MOD };
00334
00335 explicit Call(const OPENDDS_STRING& name)
00336 {
00337 if (name == MOD) {
00338 op_ = OP_MOD;
00339 } else {
00340 throw std::runtime_error("Unknown function: " + std::string(name.c_str ()));
00341 }
00342 }
00343
00344 virtual Value eval(FilterEvaluator::DataForEval& data)
00345 {
00346 switch (op_) {
00347 case OP_MOD:
00348 {
00349 if (children_.size () != 2) {
00350 std::stringstream ss;
00351 ss << MOD << " expects 2 arguments, given " << 2;
00352 throw std::runtime_error(ss.str ());
00353 }
00354 Value left = children_[0]->eval(data);
00355 Value right = children_[1]->eval(data);
00356 return left % right;
00357 }
00358 break;
00359 }
00360 assert(0);
00361 return Value(0);
00362 }
00363
00364 private:
00365 Operator op_;
00366 };
00367
00368 class Logical : public FilterEvaluator::EvalNode {
00369 public:
00370 enum LogicalOp {LG_AND, LG_OR, LG_NOT};
00371
00372 explicit Logical(EvalNode* child)
00373 : op_(LG_NOT)
00374 {
00375 addChild(child);
00376 }
00377
00378 Logical(AstNode* op, EvalNode* left, EvalNode* right)
00379 {
00380 addChild(left);
00381 addChild(right);
00382 if (op->TypeMatches<AND>()) {
00383 op_ = LG_AND;
00384 } else if (op->TypeMatches<OR>()) {
00385 op_ = LG_OR;
00386 } else {
00387 assert(0);
00388 }
00389 }
00390
00391 Value eval(FilterEvaluator::DataForEval& data)
00392 {
00393 Value left = children_[0]->eval(data);
00394 assert(left.type_ == Value::VAL_BOOL);
00395 switch (op_) {
00396 case LG_NOT:
00397 return !left.b_;
00398 case LG_AND:
00399 if (!left.b_) return false;
00400 break;
00401 case LG_OR:
00402 if (left.b_) return true;
00403 break;
00404 }
00405 return children_[1]->eval(data);
00406 }
00407
00408 private:
00409 LogicalOp op_;
00410 };
00411 }
00412
00413 static size_t arity(const FilterEvaluator::AstNodeWrapper& node)
00414 {
00415 size_t a = 0;
00416 for (AstNode* iter = node->GetFirstChild(); iter; iter = iter->GetSibling()) {
00417 ++a;
00418 }
00419 return a;
00420 }
00421
00422 static FilterEvaluator::AstNodeWrapper child(const FilterEvaluator::AstNodeWrapper& node, size_t idx)
00423 {
00424 AstNode* iter = 0;
00425 for (iter = node->GetFirstChild(); idx != 0; iter = iter->GetSibling(), --idx) {}
00426 return iter;
00427 }
00428
00429 FilterEvaluator::EvalNode*
00430 FilterEvaluator::walkAst(const FilterEvaluator::AstNodeWrapper& node)
00431 {
00432 if (node->TypeMatches<CompPredDef>()) {
00433 Operand* left = walkOperand(child(node, 0));
00434 const FilterEvaluator::AstNodeWrapper& op = child(node, 1);
00435 Operand* right = walkOperand(child(node, 2));
00436 if (left->isParameter() && right->isParameter()) {
00437 extended_grammar_ = true;
00438 }
00439 return new Comparison(op, left, right);
00440 } else if (node->TypeMatches<BetweenPredDef>()) {
00441 Operand* field = walkOperand(child(node, 0));
00442 const FilterEvaluator::AstNodeWrapper& op = child(node, 1);
00443 Operand* low = walkOperand(child(node, 2));
00444 Operand* high = walkOperand(child(node, 3));
00445 return new Between(field, op, low, high);
00446 } else if (node->TypeMatches<CondDef>() || node->TypeMatches<Cond>()) {
00447 size_t a = arity(node);
00448 if (a == 1) {
00449 return walkAst(child(node, 0));
00450 } else if (a == 2) {
00451 assert(child(node, 0)->TypeMatches<NOT>());
00452 return new Logical(walkAst(child(node, 1)));
00453 } else if (a == 3) {
00454 EvalNode* left = walkAst(child(node, 0));
00455 const FilterEvaluator::AstNodeWrapper& op = child(node, 1);
00456 EvalNode* right = walkAst(child(node, 2));
00457 return new Logical(op, left, right);
00458 }
00459 }
00460
00461 assert(0);
00462 return 0;
00463 }
00464
00465 FilterEvaluator::Operand*
00466 FilterEvaluator::walkOperand(const FilterEvaluator::AstNodeWrapper& node)
00467 {
00468 if (node->TypeMatches<FieldName>()) {
00469 return new FieldLookup(node);
00470 } else if (node->TypeMatches<IntVal>()) {
00471 return new LiteralInt(node);
00472 } else if (node->TypeMatches<CharVal>()) {
00473 return new LiteralChar(node);
00474 } else if (node->TypeMatches<FloatVal>()) {
00475 return new LiteralFloat(node);
00476 } else if (node->TypeMatches<StrVal>()) {
00477 return new LiteralString(node);
00478 } else if (node->TypeMatches<ParamVal>()) {
00479 return new Parameter(node);
00480 } else if (node->TypeMatches<CallDef>()) {
00481 if (arity(node) == 1) {
00482 return walkOperand(child(node, 0));
00483 } else {
00484 extended_grammar_ = true;
00485 Call* call = new Call(toString(child(node, 0)));
00486 for (AstNode* iter = child(node, 1); iter != 0; iter = iter->GetSibling()) {
00487 call->addChild(walkOperand(iter));
00488 }
00489 return call;
00490 }
00491 }
00492 assert(0);
00493 return 0;
00494 }
00495
00496 bool
00497 FilterEvaluator::eval_i(DataForEval& data) const
00498 {
00499 return filter_root_->eval(data).b_;
00500 }
00501
00502 OPENDDS_VECTOR(OPENDDS_STRING)
00503 FilterEvaluator::getOrderBys() const
00504 {
00505 return order_bys_;
00506 }
00507
00508 bool
00509 FilterEvaluator::hasFilter() const
00510 {
00511 return filter_root_ != 0;
00512 }
00513
00514 Value::Value(bool b, bool conversion_preferred)
00515 : type_(VAL_BOOL), b_(b), conversion_preferred_(conversion_preferred)
00516 {}
00517
00518 Value::Value(int i, bool conversion_preferred)
00519 : type_(VAL_INT), i_(i), conversion_preferred_(conversion_preferred)
00520 {}
00521
00522 Value::Value(unsigned int u, bool conversion_preferred)
00523 : type_(VAL_UINT), u_(u), conversion_preferred_(conversion_preferred)
00524 {}
00525
00526 Value::Value(ACE_INT64 l, bool conversion_preferred)
00527 : type_(VAL_I64), l_(l), conversion_preferred_(conversion_preferred)
00528 {}
00529
00530 Value::Value(ACE_UINT64 m, bool conversion_preferred)
00531 : type_(VAL_UI64), m_(m), conversion_preferred_(conversion_preferred)
00532 {}
00533
00534 Value::Value(char c, bool conversion_preferred)
00535 : type_(VAL_CHAR), c_(c), conversion_preferred_(conversion_preferred)
00536 {}
00537
00538 Value::Value(double f, bool conversion_preferred)
00539 : type_(VAL_FLOAT), f_(f), conversion_preferred_(conversion_preferred)
00540 {}
00541
00542 Value::Value(ACE_CDR::LongDouble ld, bool conversion_preferred)
00543 : type_(VAL_LNGDUB), ld_(ld), conversion_preferred_(conversion_preferred)
00544 {}
00545
00546 Value::Value(const char* s, bool conversion_preferred)
00547 : type_(VAL_STRING), s_(ACE_OS::strdup(s))
00548 , conversion_preferred_(conversion_preferred)
00549 {}
00550
00551 Value::Value(const TAO::String_Manager& s, bool conversion_preferred)
00552 : type_(VAL_STRING), s_(ACE_OS::strdup(s.in()))
00553 , conversion_preferred_(conversion_preferred)
00554 {}
00555
00556 Value::Value(const TAO::WString_Manager& s, bool conversion_preferred)
00557 : type_(VAL_STRING)
00558 #ifdef DDS_HAS_WCHAR
00559 , s_(ACE_OS::strdup(ACE_Wide_To_Ascii(s.in()).char_rep()))
00560 #else
00561 , s_(0)
00562 #endif
00563 , conversion_preferred_(conversion_preferred)
00564 {
00565 #ifndef DDS_HAS_WCHAR
00566 ACE_UNUSED_ARG(s);
00567 #endif
00568 }
00569
00570 template<> bool& Value::get() { return b_; }
00571 template<> int& Value::get() { return i_; }
00572 template<> unsigned int& Value::get() { return u_; }
00573 template<> ACE_INT64& Value::get() { return l_; }
00574 template<> ACE_UINT64& Value::get() { return m_; }
00575 template<> char& Value::get() { return c_; }
00576 template<> double& Value::get() { return f_; }
00577 template<> ACE_CDR::LongDouble& Value::get() { return ld_; }
00578 template<> const char*& Value::get() { return s_; }
00579
00580 template<> const bool& Value::get() const { return b_; }
00581 template<> const int& Value::get() const { return i_; }
00582 template<> const unsigned int& Value::get() const { return u_; }
00583 template<> const ACE_INT64& Value::get() const { return l_; }
00584 template<> const ACE_UINT64& Value::get() const { return m_; }
00585 template<> const char& Value::get() const { return c_; }
00586 template<> const double& Value::get() const { return f_; }
00587 template<> const ACE_CDR::LongDouble& Value::get() const { return ld_; }
00588 template<> const char* const& Value::get() const { return s_; }
00589
00590 Value::~Value()
00591 {
00592 if (type_ == VAL_STRING) ACE_OS::free((void*)s_);
00593 }
00594
00595 namespace {
00596 template<typename Visitor, typename Val>
00597 typename Visitor::result_type visit(Visitor& vis, Val& val)
00598 {
00599 switch (val.type_) {
00600 case Value::VAL_BOOL:
00601 return vis(val.b_);
00602 case Value::VAL_INT:
00603 return vis(val.i_);
00604 case Value::VAL_UINT:
00605 return vis(val.u_);
00606 case Value::VAL_I64:
00607 return vis(val.l_);
00608 case Value::VAL_UI64:
00609 return vis(val.m_);
00610 case Value::VAL_FLOAT:
00611 return vis(val.f_);
00612 case Value::VAL_LNGDUB:
00613 return vis(val.ld_);
00614 case Value::VAL_CHAR:
00615 return vis(val.c_);
00616 case Value::VAL_STRING:
00617 return vis(val.s_);
00618 default:
00619 throw std::runtime_error("Unexpected type of Value");
00620 }
00621 }
00622
00623 template<typename ResultType = void>
00624 struct VisitorBase {
00625 typedef ResultType result_type;
00626 };
00627
00628 struct Assign : VisitorBase<> {
00629 explicit Assign(Value& target, bool steal = false)
00630 : tgt_(target), steal_(steal) {}
00631
00632 void operator()(const char* s)
00633 {
00634 tgt_.s_ = steal_ ? s : ACE_OS::strdup(s);
00635 }
00636
00637 template<typename T> void operator()(const T& s)
00638 {
00639 tgt_.get<T>() = s;
00640 }
00641
00642 Value& tgt_;
00643 bool steal_;
00644 };
00645 }
00646
00647 Value::Value(const Value& v)
00648 : type_(v.type_), conversion_preferred_(v.conversion_preferred_)
00649 {
00650 Assign visitor(*this);
00651 visit(visitor, v);
00652 }
00653
00654 Value&
00655 Value::operator=(const Value& v)
00656 {
00657 Value cpy(v);
00658 swap(cpy);
00659 return *this;
00660 }
00661
00662 void
00663 Value::swap(Value& v)
00664 {
00665 Value t(v);
00666
00667 if (v.type_ == VAL_STRING) {
00668 ACE_OS::free((void*)v.s_);
00669 }
00670
00671 Assign visitor1(v, true);
00672 visit(visitor1, *this);
00673 if (type_ == VAL_STRING) {
00674 s_ = 0;
00675 }
00676
00677 Assign visitor2(*this, true);
00678 visit(visitor2, t);
00679 if (t.type_ == VAL_STRING) {
00680 t.s_ = 0;
00681 }
00682
00683 std::swap(conversion_preferred_, v.conversion_preferred_);
00684 std::swap(type_, v.type_);
00685 }
00686
00687 namespace {
00688 struct Equals : VisitorBase<bool> {
00689 explicit Equals(const Value& lhs) : lhs_(lhs) {}
00690
00691 bool operator()(const char* s) const
00692 {
00693 return std::strcmp(lhs_.s_, s) == 0;
00694 }
00695
00696 template<typename T> bool operator()(const T& rhs) const
00697 {
00698 return lhs_.get<T>() == rhs;
00699 }
00700
00701 const Value& lhs_;
00702 };
00703
00704 struct Less : VisitorBase<bool> {
00705 explicit Less(const Value& lhs) : lhs_(lhs) {}
00706
00707 bool operator()(const char* s) const
00708 {
00709 return std::strcmp(lhs_.s_, s) < 0;
00710 }
00711
00712 template<typename T> bool operator()(const T& rhs) const
00713 {
00714 return lhs_.get<T>() < rhs;
00715 }
00716
00717 const Value& lhs_;
00718 };
00719
00720 struct Modulus : VisitorBase<Value> {
00721 explicit Modulus(const Value& lhs) : lhs_(lhs) {}
00722
00723 bool operator()(const char*&) const
00724 {
00725 throw std::runtime_error(std::string(MOD) + " cannot be applied to strings");
00726 }
00727
00728 Value operator()(const bool&) const
00729 {
00730 throw std::runtime_error(std::string(MOD) + " cannot be applied to booleans");
00731 }
00732
00733 template<typename T>
00734 Value operator()(const T& rhs) const
00735 {
00736 return lhs_.get<T>() % rhs;
00737 }
00738
00739 Value operator()(const double&) const
00740 {
00741 throw std::runtime_error(std::string(MOD) + " cannot be applied to doubles");
00742 }
00743
00744 Value operator()(const ACE_CDR::LongDouble&) const
00745 {
00746 throw std::runtime_error(std::string(MOD) + " cannot be applied to ACE_CDR::LongDoubles");
00747 }
00748
00749 const Value& lhs_;
00750 };
00751 }
00752
00753 bool
00754 Value::operator==(const Value& v) const
00755 {
00756 Value lhs = *this;
00757 Value rhs = v;
00758 conversion(lhs, rhs);
00759 Equals visitor(lhs);
00760 return visit(visitor, rhs);
00761 }
00762
00763 bool
00764 Value::operator<(const Value& v) const
00765 {
00766 Value lhs = *this;
00767 Value rhs = v;
00768 conversion(lhs, rhs);
00769 Less visitor(lhs);
00770 return visit(visitor, rhs);
00771 }
00772
00773 Value
00774 Value::operator%(const Value& v) const
00775 {
00776 Value lhs = *this;
00777 Value rhs = v;
00778 conversion(lhs, rhs);
00779 Modulus visitor(lhs);
00780 return visit(visitor, rhs);
00781 }
00782
00783 bool
00784 Value::like(const Value& v) const
00785 {
00786 if (type_ != VAL_STRING || v.type_ != VAL_STRING) {
00787 throw std::runtime_error("'like' operator called on non-string arguments.");
00788 }
00789 OPENDDS_STRING pattern(v.s_);
00790
00791 for (size_t i = pattern.find_first_of("?*"); i < pattern.length();
00792 i = pattern.find_first_of("?*", i + 1)) {
00793 pattern.insert(i++, 1, '\\');
00794 }
00795
00796 for (size_t i = pattern.find_first_of("_%"); i < pattern.length();
00797 i = pattern.find_first_of("_%", i + 1)) {
00798 pattern[i] = (pattern[i] == '_') ? '?' : '*';
00799 }
00800 return ACE::wild_match(s_, pattern.c_str(), true, true);
00801 }
00802
00803 namespace {
00804 struct StreamInsert : VisitorBase<> {
00805 explicit StreamInsert(std::ostream& os) : os_(os) {}
00806
00807 template<typename T> void operator()(const T& t)
00808 {
00809 os_ << t;
00810 }
00811
00812 std::ostream& os_;
00813 };
00814
00815 struct StreamExtract : VisitorBase<> {
00816 explicit StreamExtract(std::istream& is) : is_(is) {}
00817
00818 void operator()(const char*) {}
00819
00820
00821 void operator()(ACE_CDR::LongDouble& ld)
00822 {
00823 #ifdef NONNATIVE_LONGDOUBLE
00824 ACE_CDR::LongDouble::NativeImpl ni;
00825 is_ >> ni;
00826 ld.assign(ni);
00827 #else
00828 is_ >> ld;
00829 #endif
00830 }
00831
00832 template<typename T> void operator()(T& t)
00833 {
00834 is_ >> t;
00835 }
00836
00837 std::istream& is_;
00838 };
00839 }
00840
00841 bool
00842 Value::convert(Value::Type t)
00843 {
00844 OPENDDS_STRING asString;
00845 if (type_ == VAL_STRING) {
00846 asString = s_;
00847 } else {
00848 std::ostringstream oss;
00849 StreamInsert visitor(oss);
00850 visit(visitor, *this);
00851 asString = oss.str();
00852 }
00853
00854 Value newval = 0;
00855 newval.type_ = t;
00856 newval.conversion_preferred_ = false;
00857 if (t == VAL_STRING) {
00858 newval.s_ = ACE_OS::strdup(asString.c_str());
00859 swap(newval);
00860 return true;
00861 } else {
00862 std::istringstream iss(asString);
00863 StreamExtract visitor(iss);
00864 visit(visitor, newval);
00865 if (iss.eof() && !iss.bad()) {
00866 swap(newval);
00867 return true;
00868 }
00869 return false;
00870 }
00871 }
00872
00873 void
00874 Value::conversion(Value& lhs, Value& rhs)
00875 {
00876 if (lhs.type_ == rhs.type_) {
00877 return;
00878 }
00879 bool ok = false;
00880 Value& smaller = (lhs.type_ < rhs.type_) ? lhs : rhs;
00881 Value& larger = (lhs.type_ < rhs.type_) ? rhs : lhs;
00882 if (smaller.conversion_preferred_) {
00883 ok = smaller.convert(larger.type_);
00884 } else if (larger.conversion_preferred_) {
00885 ok = larger.convert(smaller.type_);
00886 } else if (smaller.type_ == VAL_CHAR && larger.type_ == VAL_STRING) {
00887 ok = smaller.convert(VAL_STRING);
00888 } else if (larger.type_ <= VAL_LARGEST_NUMERIC) {
00889 ok = smaller.convert(larger.type_);
00890 } else if (larger.type_ == VAL_STRING) {
00891 if (larger.convert(smaller.type_)) {
00892 ok = true;
00893 } else {
00894 ok = smaller.convert(VAL_STRING);
00895 }
00896 }
00897 if (!ok) {
00898 throw std::runtime_error("Types don't match and aren't convertible.");
00899 }
00900 }
00901
00902 MetaStruct::~MetaStruct()
00903 {
00904 }
00905
00906 }
00907 }
00908
00909 #endif