LCOV - code coverage report
Current view: top level - DCPS - FilterEvaluator.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 544 0.0 %
Date: 2023-04-30 01:32:43 Functions: 0 163 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Distributed under the OpenDDS License.
       3             :  * See: http://www.opendds.org/license.html
       4             :  */
       5             : 
       6             : #include <DCPS/DdsDcps_pch.h> // Only the _pch include should start with DCPS/
       7             : 
       8             : #include "Definitions.h"
       9             : 
      10             : #ifndef OPENDDS_NO_CONTENT_SUBSCRIPTION_PROFILE
      11             : 
      12             : #include "FilterEvaluator.h"
      13             : #include "FilterExpressionGrammar.h"
      14             : #include "AstNodeWrapper.h"
      15             : #include "Definitions.h"
      16             : #include "SafetyProfileStreams.h"
      17             : #include "TypeSupportImpl.h"
      18             : 
      19             : #include <ace/ACE.h>
      20             : 
      21             : #include <stdexcept>
      22             : #include <cstring>
      23             : #include <algorithm>
      24             : #include <sstream>
      25             : 
      26             : namespace {
      27             :   const char MOD[] = "MOD";
      28             : }
      29             : 
      30             : using namespace OpenDDS::DCPS::FilterExpressionGrammar;
      31             : 
      32             : OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL
      33             : 
      34             : namespace OpenDDS {
      35             : namespace DCPS {
      36             : 
      37           0 : FilterEvaluator::DataForEval::~DataForEval()
      38           0 : {}
      39             : 
      40           0 : FilterEvaluator::DeserializedForEval::~DeserializedForEval()
      41           0 : {}
      42             : 
      43           0 : FilterEvaluator::FilterEvaluator(const char* filter, bool allowOrderBy)
      44           0 :   : extended_grammar_(false)
      45           0 :   , filter_root_(0)
      46           0 :   , number_parameters_(0)
      47             : {
      48           0 :   const char* out = filter + std::strlen(filter);
      49           0 :   yard::SimpleTextParser parser(filter, out);
      50           0 :   if (!(allowOrderBy ? parser.Parse<QueryCompleteInput>()
      51           0 :       : parser.Parse<FilterCompleteInput>())) {
      52           0 :     reportErrors(parser, filter);
      53             :   }
      54             : 
      55           0 :   bool found_order_by = false;
      56           0 :   for (AstNode* iter = parser.GetAstRoot()->GetFirstChild(); iter;
      57           0 :       iter = iter->GetSibling()) {
      58           0 :     if (iter->TypeMatches<ORDERBY>()) {
      59           0 :       found_order_by = true;
      60           0 :     } else if (found_order_by && iter->TypeMatches<FieldName>()) {
      61           0 :       order_bys_.push_back(toString(iter));
      62             :     } else {
      63           0 :       filter_root_ = walkAst(iter);
      64             :     }
      65             :   }
      66           0 : }
      67             : 
      68           0 : FilterEvaluator::FilterEvaluator(const AstNodeWrapper& yardNode)
      69           0 :   : extended_grammar_(false)
      70           0 :   , filter_root_(walkAst(yardNode))
      71           0 :   , number_parameters_(0)
      72             : {
      73           0 : }
      74             : 
      75             : class FilterEvaluator::EvalNode {
      76             : public:
      77           0 :   void addChild(EvalNode* n)
      78             :   {
      79           0 :     children_.push_back(n);
      80           0 :   }
      81             : 
      82           0 :   virtual ~EvalNode()
      83           0 :   {
      84           0 :     std::for_each(children_.begin(), children_.end(), deleteChild);
      85           0 :   }
      86             : 
      87           0 :   virtual bool has_non_key_fields(const TypeSupportImpl& ts) const
      88             :   {
      89           0 :     for (OPENDDS_VECTOR(EvalNode*)::const_iterator i = children_.begin(); i != children_.end(); ++i) {
      90           0 :       EvalNode* child = *i;
      91           0 :       if (child->has_non_key_fields(ts)) {
      92           0 :         return true;
      93             :       }
      94             :     }
      95           0 :     return false;
      96             :   }
      97             : 
      98             :   virtual Value eval(DataForEval& data) = 0;
      99             : 
     100             : private:
     101           0 :   static void deleteChild(EvalNode* child)
     102             :   {
     103           0 :     delete child;
     104           0 :   }
     105             : 
     106             : protected:
     107             :   OPENDDS_VECTOR(EvalNode*) children_;
     108             : };
     109             : 
     110             : class FilterEvaluator::Operand : public FilterEvaluator::EvalNode {
     111             : public:
     112           0 :   virtual bool isParameter() const { return false; }
     113             : };
     114             : 
     115             : Value
     116           0 : FilterEvaluator::DeserializedForEval::lookup(const char* field) const
     117             : {
     118           0 :   return meta_.getValue(deserialized_, field);
     119             : }
     120             : 
     121           0 : FilterEvaluator::SerializedForEval::SerializedForEval(ACE_Message_Block* data,
     122             :                                                       const TypeSupportImpl& type_support,
     123             :                                                       const DDS::StringSeq& params,
     124           0 :                                                       Encoding encoding)
     125           0 :   : DataForEval(type_support.getMetaStructForType(), params)
     126           0 :   , serialized_(data)
     127           0 :   , encoding_(encoding)
     128           0 :   , type_support_(type_support)
     129           0 :   , exten_(type_support.base_extensibility())
     130           0 : {}
     131             : 
     132             : Value
     133           0 : FilterEvaluator::SerializedForEval::lookup(const char* field) const
     134             : {
     135           0 :   const OPENDDS_MAP(OPENDDS_STRING, Value)::const_iterator iter = cache_.find(field);
     136           0 :   if (iter != cache_.end()) {
     137           0 :     return iter->second;
     138             :   }
     139           0 :   Message_Block_Ptr mb(serialized_->duplicate());
     140           0 :   Serializer ser(mb.get(), encoding_);
     141           0 :   if (encoding_.is_encapsulated()) {
     142           0 :     EncapsulationHeader encap;
     143           0 :     if (!(ser >> encap)) {
     144           0 :       ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR ")
     145             :         ACE_TEXT("FilterEvaluator::SerializedForEval::lookup: ")
     146             :         ACE_TEXT("deserialization of encapsulation header failed.\n")));
     147           0 :       throw std::runtime_error("FilterEvaluator::SerializedForEval::lookup:"
     148           0 :         "deserialization of encapsulation header failed.\n");
     149             :     }
     150           0 :     Encoding encoding;
     151           0 :     if (!encap.to_encoding(encoding, exten_)) {
     152           0 :       ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR ")
     153             :         ACE_TEXT("FilterEvaluator::SerializedForEval::lookup: ")
     154             :         ACE_TEXT("failed to convert encapsulation header to encoding.\n")));
     155           0 :       throw std::runtime_error("FilterEvaluator::SerializedForEval::lookup:"
     156           0 :         "failed to convert encapsulation header to encoding.\n");
     157             :     }
     158           0 :     ser.encoding(encoding);
     159             :   }
     160           0 :   const Value v = meta_.getValue(ser, field, &type_support_);
     161           0 :   cache_.insert(std::make_pair(OPENDDS_STRING(field), v));
     162           0 :   return v;
     163           0 : }
     164             : 
     165           0 : FilterEvaluator::~FilterEvaluator()
     166             : {
     167           0 :   delete filter_root_;
     168           0 : }
     169             : 
     170           0 : bool FilterEvaluator::has_non_key_fields(const TypeSupportImpl& ts) const
     171             : {
     172           0 :   for (OPENDDS_VECTOR(OPENDDS_STRING)::const_iterator i = order_bys_.begin(); i != order_bys_.end(); ++i) {
     173           0 :     if (!ts.is_dcps_key(i->c_str())) {
     174           0 :       return true;
     175             :     }
     176             :   }
     177             : 
     178           0 :   return filter_root_->has_non_key_fields(ts);
     179             : }
     180             : 
     181             : namespace {
     182             : 
     183             :   class FieldLookup : public FilterEvaluator::Operand {
     184             :   public:
     185           0 :     explicit FieldLookup(AstNode* fnNode)
     186           0 :       : fieldName_(toString(fnNode))
     187             :     {
     188           0 :     }
     189             : 
     190           0 :     Value eval(FilterEvaluator::DataForEval& data)
     191             :     {
     192           0 :       return data.lookup(fieldName_.c_str());
     193             :     }
     194             : 
     195           0 :     bool has_non_key_fields(const TypeSupportImpl& ts) const
     196             :     {
     197           0 :       return !ts.is_dcps_key(fieldName_.c_str());
     198             :     }
     199             : 
     200             :     OPENDDS_STRING fieldName_;
     201             :   };
     202             : 
     203             :   class LiteralInt : public FilterEvaluator::Operand {
     204             :   public:
     205           0 :     explicit LiteralInt(AstNode* fnNode)
     206           0 :       : value_(0, true)
     207             :     {
     208           0 :       const OPENDDS_STRING strVal = toString(fnNode);
     209           0 :       if (strVal.length() > 2 && strVal[0] == '0'
     210           0 :           && (strVal[1] == 'x' || strVal[1] == 'X')) {
     211           0 :         std::istringstream is(strVal.c_str() + 2);
     212             :         ACE_UINT64 val;
     213           0 :         is >> std::hex >> val;
     214           0 :         value_ = Value(val, true);
     215           0 :       } else if (!strVal.empty() && strVal[0] == '-') {
     216             :         ACE_INT64 val;
     217           0 :         std::istringstream is(strVal.c_str());
     218           0 :         is >> val;
     219           0 :         value_ = Value(val, true);
     220           0 :       } else {
     221             :         ACE_UINT64 val;
     222           0 :         std::istringstream is(strVal.c_str());
     223           0 :         is >> val;
     224           0 :         value_ = Value(val, true);
     225           0 :       }
     226           0 :     }
     227             : 
     228           0 :     Value eval(FilterEvaluator::DataForEval&)
     229             :     {
     230           0 :       return value_;
     231             :     }
     232             : 
     233             :     Value value_;
     234             :   };
     235             : 
     236             :   class LiteralChar : public FilterEvaluator::Operand {
     237             :   public:
     238           0 :     explicit LiteralChar(AstNode* fnNode)
     239           0 :       : value_(toString(fnNode)[1])
     240           0 :     {}
     241             : 
     242           0 :     Value eval(FilterEvaluator::DataForEval&)
     243             :     {
     244           0 :       return Value(value_, true);
     245             :     }
     246             : 
     247             :     char value_;
     248             :   };
     249             : 
     250             :   class LiteralFloat : public FilterEvaluator::Operand {
     251             :   public:
     252           0 :     explicit LiteralFloat(AstNode* fnNode)
     253           0 :       : value_(std::atof(toString(fnNode).c_str()))
     254           0 :     {}
     255             : 
     256           0 :     Value eval(FilterEvaluator::DataForEval&)
     257             :     {
     258           0 :       return Value(value_, true);
     259             :     }
     260             : 
     261             :     double value_;
     262             :   };
     263             : 
     264             :   class LiteralString : public FilterEvaluator::Operand {
     265             :   public:
     266           0 :     explicit LiteralString(AstNode* fnNode)
     267           0 :       : value_(toString(fnNode).substr(1) /* trim left ' */)
     268             :     {
     269           0 :       value_.erase(value_.length() - 1); // trim right '
     270           0 :     }
     271             : 
     272           0 :     Value eval(FilterEvaluator::DataForEval&)
     273             :     {
     274           0 :       return Value(value_.c_str(), true);
     275             :     }
     276             : 
     277             :     OPENDDS_STRING value_;
     278             :   };
     279             : 
     280             :   class Parameter : public FilterEvaluator::Operand {
     281             :   public:
     282           0 :     explicit Parameter(AstNode* fnNode)
     283           0 :       : param_(std::atoi(toString(fnNode).c_str() + 1 /* skip % */))
     284           0 :     {}
     285             : 
     286           0 :     bool isParameter() const { return true; }
     287             : 
     288           0 :     Value eval(FilterEvaluator::DataForEval& data)
     289             :     {
     290           0 :       return Value(data.params_[static_cast<CORBA::ULong>(param_)], true);
     291             :     }
     292             : 
     293           0 :     size_t param() { return param_; }
     294             : 
     295             :     size_t param_;
     296             :   };
     297             : 
     298             :   class Comparison : public FilterEvaluator::EvalNode {
     299             :   public:
     300             :     enum Operator {OPER_EQ, OPER_LT, OPER_GT, OPER_LTEQ, OPER_GTEQ, OPER_NEQ,
     301             :       OPER_LIKE, OPER_INVALID};
     302             : 
     303           0 :     explicit Comparison(AstNode* op, FilterEvaluator::Operand* left, FilterEvaluator::Operand* right)
     304           0 :       : left_(left)
     305           0 :       , right_(right)
     306             :     {
     307           0 :       addChild(left_);
     308           0 :       addChild(right_);
     309           0 :       setOperator(op);
     310           0 :     }
     311             : 
     312           0 :     Value eval(FilterEvaluator::DataForEval& data)
     313             :     {
     314           0 :       Value left = left_->eval(data);
     315           0 :       Value right = right_->eval(data);
     316           0 :       switch (oper_type_) {
     317           0 :       case OPER_EQ:
     318           0 :         return left == right;
     319           0 :       case OPER_LT:
     320           0 :         return left < right;
     321           0 :       case OPER_GT:
     322           0 :         return right < left;
     323           0 :       case OPER_LTEQ:
     324           0 :         return !(right < left);
     325           0 :       case OPER_GTEQ:
     326           0 :         return !(left < right);
     327           0 :       case OPER_NEQ:
     328           0 :         return !(left == right);
     329           0 :       case OPER_LIKE:
     330           0 :         return left.like(right);
     331           0 :       default:
     332           0 :         break;
     333             :       }
     334           0 :       return false; // not reached
     335           0 :     }
     336             : 
     337             :   private:
     338           0 :     void setOperator(AstNode* node)
     339             :     {
     340           0 :       if (node->TypeMatches<OP_EQ>()) {
     341           0 :         oper_type_ = OPER_EQ;
     342           0 :       } else if (node->TypeMatches<OP_LT>()) {
     343           0 :         oper_type_ = OPER_LT;
     344           0 :       } else if (node->TypeMatches<OP_GT>()) {
     345           0 :         oper_type_ = OPER_GT;
     346           0 :       } else if (node->TypeMatches<OP_LTEQ>()) {
     347           0 :         oper_type_ = OPER_LTEQ;
     348           0 :       } else if (node->TypeMatches<OP_GTEQ>()) {
     349           0 :         oper_type_ = OPER_GTEQ;
     350           0 :       } else if (node->TypeMatches<OP_NEQ>()) {
     351           0 :         oper_type_ = OPER_NEQ;
     352           0 :       } else if (node->TypeMatches<OP_LIKE>()) {
     353           0 :         oper_type_ = OPER_LIKE;
     354             :       } else {
     355           0 :         oper_type_ = OPER_INVALID;
     356             :       }
     357           0 :     }
     358             : 
     359             :     FilterEvaluator::Operand* left_;
     360             :     FilterEvaluator::Operand* right_;
     361             :     Operator oper_type_;
     362             :   };
     363             : 
     364             :   class Between : public FilterEvaluator::EvalNode {
     365             :   public:
     366           0 :     Between(FilterEvaluator::Operand* field, AstNode* betweenOrNot, FilterEvaluator::Operand* left, FilterEvaluator::Operand* right)
     367           0 :       : invert_(betweenOrNot->TypeMatches<NOT_BETWEEN>())
     368           0 :       , field_(field)
     369           0 :       , left_(left)
     370           0 :       , right_(right)
     371             :     {
     372           0 :       addChild(field_);
     373           0 :       addChild(left_);
     374           0 :       addChild(right_);
     375           0 :     }
     376             : 
     377           0 :     Value eval(FilterEvaluator::DataForEval& data)
     378             :     {
     379           0 :       Value field = field_->eval(data);
     380           0 :       Value left = left_->eval(data);
     381           0 :       Value right = right_->eval(data);
     382           0 :       bool btwn = !(field < left) && !(right < field);
     383           0 :       return invert_ ? !btwn : btwn;
     384           0 :     }
     385             : 
     386             :   private:
     387             :     bool invert_;
     388             :     FilterEvaluator::Operand* field_;
     389             :     FilterEvaluator::Operand* left_;
     390             :     FilterEvaluator::Operand* right_;
     391             :   };
     392             : 
     393             :   class Call : public FilterEvaluator::Operand {
     394             :   public:
     395             :     enum Operator { OP_MOD };
     396             : 
     397           0 :     explicit Call(const OPENDDS_STRING& name)
     398           0 :     {
     399           0 :       if (name == MOD) {
     400           0 :         op_ = OP_MOD;
     401             :       } else {
     402           0 :         throw std::runtime_error("Unknown function: " + std::string(name.c_str ()));
     403             :       }
     404           0 :     }
     405             : 
     406           0 :     virtual Value eval(FilterEvaluator::DataForEval& data)
     407             :     {
     408           0 :       switch (op_) {
     409           0 :       case OP_MOD:
     410             :         {
     411           0 :           if (children_.size() != 2) {
     412           0 :             std::stringstream ss;
     413           0 :             ss << MOD << " expects 2 arguments, given " << children_.size();
     414           0 :             throw std::runtime_error(ss.str ());
     415           0 :           }
     416           0 :           Value left = children_[0]->eval(data);
     417           0 :           Value right = children_[1]->eval(data);
     418           0 :           return left % right;
     419           0 :         }
     420             :         break;
     421             :       }
     422           0 :       OPENDDS_ASSERT(0);
     423             :       return Value(0);
     424             :     }
     425             : 
     426             :   private:
     427             :     Operator op_;
     428             :   };
     429             : 
     430             :   class Logical : public FilterEvaluator::EvalNode {
     431             :   public:
     432             :     enum LogicalOp {LG_AND, LG_OR, LG_NOT};
     433             : 
     434           0 :     explicit Logical(EvalNode* child)
     435           0 :       : op_(LG_NOT)
     436             :     {
     437           0 :       addChild(child);
     438           0 :     }
     439             : 
     440           0 :     Logical(AstNode* op, EvalNode* left, EvalNode* right)
     441           0 :     {
     442           0 :       addChild(left);
     443           0 :       addChild(right);
     444           0 :       if (op->TypeMatches<AND>()) {
     445           0 :         op_ = LG_AND;
     446           0 :       } else if (op->TypeMatches<OR>()) {
     447           0 :         op_ = LG_OR;
     448             :       } else {
     449           0 :         OPENDDS_ASSERT(0);
     450             :       }
     451           0 :     }
     452             : 
     453           0 :     Value eval(FilterEvaluator::DataForEval& data)
     454             :     {
     455           0 :       Value left = children_[0]->eval(data);
     456           0 :       OPENDDS_ASSERT(left.type_ == Value::VAL_BOOL);
     457           0 :       switch (op_) {
     458           0 :       case LG_NOT:
     459           0 :         return !left.b_;
     460           0 :       case LG_AND:
     461           0 :         if (!left.b_) return false;
     462           0 :         break;
     463           0 :       case LG_OR:
     464           0 :         if (left.b_) return true;
     465           0 :         break;
     466             :       }
     467           0 :       return children_[1]->eval(data);
     468           0 :     }
     469             : 
     470             :   private:
     471             :     LogicalOp op_;
     472             :   };
     473             : }
     474             : 
     475           0 : static size_t arity(const FilterEvaluator::AstNodeWrapper& node)
     476             : {
     477           0 :   size_t a = 0;
     478           0 :   for (AstNode* iter = node->GetFirstChild(); iter; iter = iter->GetSibling()) {
     479           0 :     ++a;
     480             :   }
     481           0 :   return a;
     482             : }
     483             : 
     484           0 : static FilterEvaluator::AstNodeWrapper child(const FilterEvaluator::AstNodeWrapper& node, size_t idx)
     485             : {
     486           0 :   AstNode* iter = 0;
     487           0 :   for (iter = node->GetFirstChild(); idx != 0; iter = iter->GetSibling(), --idx) {}
     488           0 :   return iter;
     489             : }
     490             : 
     491             : FilterEvaluator::EvalNode*
     492           0 : FilterEvaluator::walkAst(const FilterEvaluator::AstNodeWrapper& node)
     493             : {
     494           0 :   if (node->TypeMatches<CompPredDef>()) {
     495           0 :     Operand* left = walkOperand(child(node, 0));
     496           0 :     const FilterEvaluator::AstNodeWrapper& op = child(node, 1);
     497           0 :     Operand* right = walkOperand(child(node, 2));
     498           0 :     if (left->isParameter() && right->isParameter()) {
     499           0 :       extended_grammar_ = true;
     500             :     }
     501           0 :     return new Comparison(op, left, right);
     502           0 :   } else if (node->TypeMatches<BetweenPredDef>()) {
     503           0 :     Operand* field = walkOperand(child(node, 0));
     504           0 :     const FilterEvaluator::AstNodeWrapper& op = child(node, 1);
     505           0 :     Operand* low = walkOperand(child(node, 2));
     506           0 :     Operand* high = walkOperand(child(node, 3));
     507           0 :     return new Between(field, op, low, high);
     508           0 :   } else if (node->TypeMatches<CondDef>() || node->TypeMatches<Cond>()) {
     509           0 :     size_t a = arity(node);
     510           0 :     if (a == 1) {
     511           0 :       return walkAst(child(node, 0));
     512           0 :     } else if (a == 2) {
     513           0 :       OPENDDS_ASSERT(child(node, 0)->TypeMatches<NOT>());
     514           0 :       return new Logical(walkAst(child(node, 1)));
     515           0 :     } else if (a == 3) {
     516           0 :       EvalNode* left = walkAst(child(node, 0));
     517           0 :       const FilterEvaluator::AstNodeWrapper& op = child(node, 1);
     518           0 :       EvalNode* right = walkAst(child(node, 2));
     519           0 :       return new Logical(op, left, right);
     520             :     }
     521             :   }
     522             : 
     523           0 :   OPENDDS_ASSERT(0);
     524             :   return 0;
     525             : }
     526             : 
     527             : FilterEvaluator::Operand*
     528           0 : FilterEvaluator::walkOperand(const FilterEvaluator::AstNodeWrapper& node)
     529             : {
     530           0 :   if (node->TypeMatches<FieldName>()) {
     531           0 :     return new FieldLookup(node);
     532           0 :   } else if (node->TypeMatches<IntVal>()) {
     533           0 :     return new LiteralInt(node);
     534           0 :   } else if (node->TypeMatches<CharVal>()) {
     535           0 :     return new LiteralChar(node);
     536           0 :   } else if (node->TypeMatches<FloatVal>()) {
     537           0 :     return new LiteralFloat(node);
     538           0 :   } else if (node->TypeMatches<StrVal>()) {
     539           0 :     return new LiteralString(node);
     540           0 :   } else if (node->TypeMatches<ParamVal>()) {
     541           0 :     Parameter* retval = new Parameter(node);
     542             :     // Keep track of the highest parameter number
     543           0 :     if (retval->param() + 1 > number_parameters_) {
     544           0 :       number_parameters_ = retval->param() + 1;
     545             :     }
     546           0 :     return retval;
     547           0 :   } else if (node->TypeMatches<CallDef>()) {
     548           0 :     if (arity(node) == 1) {
     549           0 :       return walkOperand(child(node, 0));
     550             :     } else {
     551           0 :       extended_grammar_ = true;
     552           0 :       Call* call = new Call(toString(child(node, 0)));
     553           0 :       for (AstNode* iter = child(node, 1); iter != 0; iter = iter->GetSibling()) {
     554           0 :         call->addChild(walkOperand(iter));
     555             :       }
     556           0 :       return call;
     557             :     }
     558             :   }
     559           0 :   OPENDDS_ASSERT(0);
     560             :   return 0;
     561             : }
     562             : 
     563             : bool
     564           0 : FilterEvaluator::eval_i(DataForEval& data) const
     565             : {
     566           0 :   return filter_root_->eval(data).b_;
     567             : }
     568             : 
     569             : OPENDDS_VECTOR(OPENDDS_STRING)
     570           0 : FilterEvaluator::getOrderBys() const
     571             : {
     572           0 :   return order_bys_;
     573             : }
     574             : 
     575             : bool
     576           0 : FilterEvaluator::hasFilter() const
     577             : {
     578           0 :   return filter_root_ != 0;
     579             : }
     580             : 
     581           0 : Value::Value(bool b, bool conversion_preferred)
     582           0 :   : type_(VAL_BOOL), b_(b), conversion_preferred_(conversion_preferred)
     583           0 : {}
     584             : 
     585           0 : Value::Value(int i, bool conversion_preferred)
     586           0 :   : type_(VAL_INT), i_(i), conversion_preferred_(conversion_preferred)
     587           0 : {}
     588             : 
     589           0 : Value::Value(unsigned int u, bool conversion_preferred)
     590           0 :   : type_(VAL_UINT), u_(u), conversion_preferred_(conversion_preferred)
     591           0 : {}
     592             : 
     593           0 : Value::Value(ACE_INT64 l, bool conversion_preferred)
     594           0 :   : type_(VAL_I64), l_(l), conversion_preferred_(conversion_preferred)
     595           0 : {}
     596             : 
     597           0 : Value::Value(ACE_UINT64 m, bool conversion_preferred)
     598           0 :   : type_(VAL_UI64), m_(m), conversion_preferred_(conversion_preferred)
     599           0 : {}
     600             : 
     601           0 : Value::Value(char c, bool conversion_preferred)
     602           0 :   : type_(VAL_CHAR), c_(c), conversion_preferred_(conversion_preferred)
     603           0 : {}
     604             : 
     605           0 : Value::Value(double f, bool conversion_preferred)
     606           0 :   : type_(VAL_FLOAT), f_(f), conversion_preferred_(conversion_preferred)
     607           0 : {}
     608             : 
     609           0 : Value::Value(ACE_CDR::LongDouble ld, bool conversion_preferred)
     610           0 :   : type_(VAL_LNGDUB), ld_(ld), conversion_preferred_(conversion_preferred)
     611           0 : {}
     612             : 
     613             : #ifdef NONNATIVE_LONGDOUBLE
     614             : Value::Value(long double ld, bool conversion_preferred)
     615             :   : type_(VAL_LNGDUB), conversion_preferred_(conversion_preferred)
     616             : {
     617             :   ACE_CDR_LONG_DOUBLE_ASSIGNMENT(ld_, ld);
     618             : }
     619             : #endif
     620             : 
     621           0 : Value::Value(const char* s, bool conversion_preferred)
     622           0 :   : type_(VAL_STRING), s_(ACE_OS::strdup(s))
     623           0 :   , conversion_preferred_(conversion_preferred)
     624           0 : {}
     625             : 
     626           0 : Value::Value(const std::string& s, bool conversion_preferred)
     627           0 :   : type_(VAL_STRING), s_(ACE_OS::strdup(s.c_str()))
     628           0 :   , conversion_preferred_(conversion_preferred)
     629           0 : {}
     630             : 
     631             : #ifdef DDS_HAS_WCHAR
     632           0 : Value::Value(const std::wstring& s, bool conversion_preferred)
     633           0 :   : type_(VAL_STRING), s_(ACE_OS::strdup(ACE_Wide_To_Ascii(s.c_str()).char_rep()))
     634           0 :   , conversion_preferred_(conversion_preferred)
     635           0 : {}
     636             : #endif
     637             : 
     638           0 : Value::Value(const TAO::String_Manager& s, bool conversion_preferred)
     639           0 :   : type_(VAL_STRING), s_(ACE_OS::strdup(s.in()))
     640           0 :   , conversion_preferred_(conversion_preferred)
     641           0 : {}
     642             : 
     643           0 : Value::Value(const TAO::WString_Manager& s, bool conversion_preferred)
     644           0 :   : type_(VAL_STRING)
     645             : #ifdef DDS_HAS_WCHAR
     646           0 :   , s_(ACE_OS::strdup(ACE_Wide_To_Ascii(s.in()).char_rep()))
     647             : #else
     648             :   , s_(0)
     649             : #endif
     650           0 :   , conversion_preferred_(conversion_preferred)
     651             : {
     652             : #ifndef DDS_HAS_WCHAR
     653             :   ACE_UNUSED_ARG(s);
     654             : #endif
     655           0 : }
     656             : 
     657           0 : template<> bool& Value::get() { return b_; }
     658           0 : template<> int& Value::get() { return i_; }
     659           0 : template<> unsigned int& Value::get() { return u_; }
     660           0 : template<> ACE_INT64& Value::get() { return l_; }
     661           0 : template<> ACE_UINT64& Value::get() { return m_; }
     662           0 : template<> char& Value::get() { return c_; }
     663           0 : template<> double& Value::get() { return f_; }
     664           0 : template<> ACE_CDR::LongDouble& Value::get() { return ld_; }
     665           0 : template<> const char*& Value::get() { return s_; }
     666             : 
     667           0 : template<> const bool& Value::get() const { return b_; }
     668           0 : template<> const int& Value::get() const { return i_; }
     669           0 : template<> const unsigned int& Value::get() const { return u_; }
     670           0 : template<> const ACE_INT64& Value::get() const { return l_; }
     671           0 : template<> const ACE_UINT64& Value::get() const { return m_; }
     672           0 : template<> const char& Value::get() const { return c_; }
     673           0 : template<> const double& Value::get() const { return f_; }
     674           0 : template<> const ACE_CDR::LongDouble& Value::get() const { return ld_; }
     675           0 : template<> const char* const& Value::get() const { return s_; }
     676             : 
     677           0 : Value::~Value()
     678             : {
     679           0 :   if (type_ == VAL_STRING) ACE_OS::free((void*)s_);
     680           0 : }
     681             : 
     682             : namespace {
     683             :   template<typename Visitor, typename Val>
     684           0 :   typename Visitor::result_type visit(Visitor& vis, Val& val)
     685             :   {
     686           0 :     switch (val.type_) {
     687           0 :     case Value::VAL_BOOL:
     688           0 :       return vis(val.b_);
     689           0 :     case Value::VAL_INT:
     690           0 :       return vis(val.i_);
     691           0 :     case Value::VAL_UINT:
     692           0 :       return vis(val.u_);
     693           0 :     case Value::VAL_I64:
     694           0 :       return vis(val.l_);
     695           0 :     case Value::VAL_UI64:
     696           0 :       return vis(val.m_);
     697           0 :     case Value::VAL_FLOAT:
     698           0 :       return vis(val.f_);
     699           0 :     case Value::VAL_LNGDUB:
     700           0 :       return vis(val.ld_);
     701           0 :     case Value::VAL_CHAR:
     702           0 :       return vis(val.c_);
     703           0 :     case Value::VAL_STRING:
     704           0 :       return vis(val.s_);
     705           0 :     default:
     706           0 :       throw std::runtime_error("Unexpected type of Value");
     707             :     }
     708             :   }
     709             : 
     710             :   template<typename ResultType = void>
     711             :   struct VisitorBase {
     712             :     typedef ResultType result_type;
     713             :   };
     714             : 
     715             :   struct Assign : VisitorBase<> {
     716           0 :     explicit Assign(Value& target, bool steal = false)
     717           0 :       : tgt_(target), steal_(steal) {}
     718             : 
     719           0 :     void operator()(const char* s)
     720             :     {
     721           0 :       tgt_.s_ = steal_ ? s : ACE_OS::strdup(s);
     722           0 :     }
     723             : 
     724           0 :     template<typename T> void operator()(const T& s)
     725             :     {
     726           0 :       tgt_.get<T>() = s;
     727           0 :     }
     728             : 
     729             :     Value& tgt_;
     730             :     bool steal_;
     731             :   };
     732             : }
     733             : 
     734           0 : Value::Value(const Value& v)
     735           0 :   : type_(v.type_), conversion_preferred_(v.conversion_preferred_)
     736             : {
     737           0 :   Assign visitor(*this);
     738           0 :   visit(visitor, v);
     739           0 : }
     740             : 
     741             : Value&
     742           0 : Value::operator=(const Value& v)
     743             : {
     744           0 :   Value cpy(v);
     745           0 :   swap(cpy);
     746           0 :   return *this;
     747           0 : }
     748             : 
     749             : void
     750           0 : Value::swap(Value& v)
     751             : {
     752           0 :   Value t(v);
     753             : 
     754           0 :   if (v.type_ == VAL_STRING) {
     755           0 :     ACE_OS::free((void*)v.s_);
     756             :   }
     757             : 
     758           0 :   Assign visitor1(v, true);
     759           0 :   visit(visitor1, *this);
     760           0 :   if (type_ == VAL_STRING) {
     761           0 :     s_ = 0;
     762             :   }
     763             : 
     764           0 :   Assign visitor2(*this, true);
     765           0 :   visit(visitor2, t);
     766           0 :   if (t.type_ == VAL_STRING) {
     767           0 :     t.s_ = 0;
     768             :   }
     769             : 
     770           0 :   std::swap(conversion_preferred_, v.conversion_preferred_);
     771           0 :   std::swap(type_, v.type_);
     772           0 : }
     773             : 
     774             : namespace {
     775             :   struct Equals : VisitorBase<bool> {
     776           0 :     explicit Equals(const Value& lhs) : lhs_(lhs) {}
     777             : 
     778           0 :     bool operator()(const char* s) const
     779             :     {
     780           0 :       return std::strcmp(lhs_.s_, s) == 0;
     781             :     }
     782             : 
     783           0 :     template<typename T> bool operator()(const T& rhs) const
     784             :     {
     785           0 :       return lhs_.get<T>() == rhs;
     786             :     }
     787             : 
     788             :     const Value& lhs_;
     789             :   };
     790             : 
     791             :   struct Less : VisitorBase<bool> {
     792           0 :     explicit Less(const Value& lhs) : lhs_(lhs) {}
     793             : 
     794           0 :     bool operator()(const char* s) const
     795             :     {
     796           0 :       return std::strcmp(lhs_.s_, s) < 0;
     797             :     }
     798             : 
     799           0 :     template<typename T> bool operator()(const T& rhs) const
     800             :     {
     801           0 :       return lhs_.get<T>() < rhs;
     802             :     }
     803             : 
     804             :     const Value& lhs_;
     805             :   };
     806             : 
     807             :   struct Modulus : VisitorBase<Value> {
     808           0 :     explicit Modulus(const Value& lhs) : lhs_(lhs) {}
     809             : 
     810           0 :     bool operator()(const char*&) const
     811             :     {
     812           0 :       throw std::runtime_error(std::string(MOD) + " cannot be applied to strings");
     813             :     }
     814             : 
     815           0 :     Value operator()(const bool&) const
     816             :     {
     817           0 :       throw std::runtime_error(std::string(MOD) + " cannot be applied to booleans");
     818             :     }
     819             : 
     820             :     template<typename T>
     821           0 :     Value operator()(const T& rhs) const
     822             :     {
     823           0 :       return lhs_.get<T>() % rhs;
     824             :     }
     825             : 
     826           0 :     Value operator()(const double&) const
     827             :     {
     828           0 :       throw std::runtime_error(std::string(MOD) + " cannot be applied to doubles");
     829             :     }
     830             : 
     831           0 :     Value operator()(const ACE_CDR::LongDouble&) const
     832             :     {
     833           0 :       throw std::runtime_error(std::string(MOD) + " cannot be applied to ACE_CDR::LongDoubles");
     834             :     }
     835             : 
     836             :     const Value& lhs_;
     837             :   };
     838             : }
     839             : 
     840             : bool
     841           0 : Value::operator==(const Value& v) const
     842             : {
     843           0 :   Value lhs = *this;
     844           0 :   Value rhs = v;
     845           0 :   conversion(lhs, rhs);
     846           0 :   Equals visitor(lhs);
     847           0 :   return visit(visitor, rhs);
     848           0 : }
     849             : 
     850             : bool
     851           0 : Value::operator<(const Value& v) const
     852             : {
     853           0 :   Value lhs = *this;
     854           0 :   Value rhs = v;
     855           0 :   conversion(lhs, rhs);
     856           0 :   Less visitor(lhs);
     857           0 :   return visit(visitor, rhs);
     858           0 : }
     859             : 
     860             : Value
     861           0 : Value::operator%(const Value& v) const
     862             : {
     863           0 :   Value lhs = *this;
     864           0 :   Value rhs = v;
     865           0 :   conversion(lhs, rhs);
     866           0 :   Modulus visitor(lhs);
     867           0 :   return visit(visitor, rhs);
     868           0 : }
     869             : 
     870             : bool
     871           0 : Value::like(const Value& v) const
     872             : {
     873           0 :   if (type_ != VAL_STRING || v.type_ != VAL_STRING) {
     874           0 :     throw std::runtime_error("'like' operator called on non-string arguments.");
     875             :   }
     876           0 :   OPENDDS_STRING pattern(v.s_);
     877             :   // escape ? or * in the pattern string so they are not wildcards
     878           0 :   for (size_t i = pattern.find_first_of("?*"); i < pattern.length();
     879           0 :       i = pattern.find_first_of("?*", i + 1)) {
     880           0 :     pattern.insert(i++, 1, '\\');
     881             :   }
     882             :   // translate _ and % wildcards into those used by ACE::wild_match() (?, *)
     883           0 :   for (size_t i = pattern.find_first_of("_%"); i < pattern.length();
     884           0 :       i = pattern.find_first_of("_%", i + 1)) {
     885           0 :     pattern[i] = (pattern[i] == '_') ? '?' : '*';
     886             :   }
     887           0 :   return ACE::wild_match(s_, pattern.c_str(), true, true);
     888           0 : }
     889             : 
     890             : namespace {
     891             :   struct StreamInsert : VisitorBase<> {
     892           0 :     explicit StreamInsert(std::ostream& os) : os_(os) {}
     893             : 
     894           0 :     template<typename T> void operator()(const T& t)
     895             :     {
     896           0 :       os_ << t;
     897           0 :     }
     898             : 
     899             :     std::ostream& os_;
     900             :   };
     901             : 
     902             :   struct StreamExtract : VisitorBase<> {
     903           0 :     explicit StreamExtract(std::istream& is) : is_(is) {}
     904             : 
     905           0 :     void operator()(const char*) {}
     906             :     // not called.  prevents instantiation of the following with T = const char*
     907             : 
     908           0 :     void operator()(ACE_CDR::LongDouble& ld)
     909             :     {
     910             : #ifdef NONNATIVE_LONGDOUBLE
     911             :       ACE_CDR::LongDouble::NativeImpl ni;
     912             :       is_ >> ni;
     913             :       ld.assign(ni);
     914             : #else
     915           0 :       is_ >> ld;
     916             : #endif
     917           0 :     }
     918             : 
     919           0 :     template<typename T> void operator()(T& t)
     920             :     {
     921           0 :       is_ >> t;
     922           0 :     }
     923             : 
     924             :     std::istream& is_;
     925             :   };
     926             : }
     927             : 
     928             : bool
     929           0 : Value::convert(Value::Type t)
     930             : {
     931           0 :   OPENDDS_STRING asString;
     932           0 :   if (type_ == VAL_STRING) {
     933           0 :     asString = s_;
     934             :   } else {
     935           0 :     std::ostringstream oss;
     936           0 :     StreamInsert visitor(oss);
     937           0 :     visit(visitor, *this);
     938           0 :     asString = oss.str();
     939           0 :   }
     940             : 
     941           0 :   Value newval = 0;
     942           0 :   newval.type_ = t;
     943           0 :   newval.conversion_preferred_ = false;
     944           0 :   if (t == VAL_STRING) {
     945           0 :     newval.s_ = ACE_OS::strdup(asString.c_str());
     946           0 :     swap(newval);
     947           0 :     return true;
     948             :   } else {
     949           0 :     std::istringstream iss(asString);
     950           0 :     StreamExtract visitor(iss);
     951           0 :     visit(visitor, newval);
     952           0 :     if (iss.eof() && !iss.bad()) {
     953           0 :       swap(newval);
     954           0 :       return true;
     955             :     }
     956           0 :     return false;
     957           0 :   }
     958           0 : }
     959             : 
     960             : void
     961           0 : Value::conversion(Value& lhs, Value& rhs)
     962             : {
     963           0 :   if (lhs.type_ == rhs.type_) {
     964           0 :     return;
     965             :   }
     966           0 :   bool ok = false;
     967           0 :   Value& smaller = (lhs.type_ < rhs.type_) ? lhs : rhs;
     968           0 :   Value& larger = (lhs.type_ < rhs.type_) ? rhs : lhs;
     969           0 :   if (smaller.conversion_preferred_) {
     970           0 :     ok = smaller.convert(larger.type_);
     971           0 :   } else if (larger.conversion_preferred_) {
     972           0 :     ok = larger.convert(smaller.type_);
     973           0 :   } else if (smaller.type_ == VAL_CHAR && larger.type_ == VAL_STRING) {
     974           0 :     ok = smaller.convert(VAL_STRING);
     975           0 :   } else if (larger.type_ <= VAL_LARGEST_NUMERIC) {
     976           0 :     ok = smaller.convert(larger.type_);
     977           0 :   } else if (larger.type_ == VAL_STRING) {
     978           0 :     if (larger.convert(smaller.type_)) {
     979           0 :       ok = true;
     980             :     } else {
     981           0 :       ok = smaller.convert(VAL_STRING);
     982             :     }
     983             :   }
     984           0 :   if (!ok) {
     985           0 :     throw std::runtime_error("Types don't match and aren't convertible.");
     986             :   }
     987             : }
     988             : 
     989           0 : MetaStruct::~MetaStruct()
     990             : {
     991           0 : }
     992             : 
     993             : }
     994             : }
     995             : 
     996             : OPENDDS_END_VERSIONED_NAMESPACE_DECL
     997             : 
     998             : #endif

Generated by: LCOV version 1.16