FilterEvaluator.cpp

Go to the documentation of this file.
00001 /*
00002  *
00003  *
00004  * Distributed under the OpenDDS License.
00005  * See: http://www.opendds.org/license.html
00006  */
00007 
00008 #include "DCPS/DdsDcps_pch.h" //Only the _pch include should start with DCPS/
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); // CDR encapsulation header
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) /* trim left ' */)
00208     {
00209       value_.erase(value_.length() - 1); // trim right '
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 /* skip % */))
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; // not reached
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   // escape ? or * in the pattern string so they are not wildcards
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   // translate _ and % wildcards into those used by ACE::wild_match() (?, *)
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     // not called.  prevents instantiation of the following with T = const char*
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

Generated on Fri Feb 12 20:05:23 2016 for OpenDDS by  doxygen 1.4.7