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 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); // CDR encapsulation header
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) /* trim left ' */)
00213     {
00214       value_.erase(value_.length() - 1); // trim right '
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 /* skip % */))
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; // not reached
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     // Keep track of the highest parameter number
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   // escape ? or * in the pattern string so they are not wildcards
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   // translate _ and % wildcards into those used by ACE::wild_match() (?, *)
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     // not called.  prevents instantiation of the following with T = const char*
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 10 Aug 2018 for OpenDDS by  doxygen 1.6.1