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