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
|