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