OpenDDS  Snapshot(2023/04/07-19:43)
XTypes/Utils.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>
7 
8 #ifndef OPENDDS_SAFETY_PROFILE
9 # include "Utils.h"
10 
11 # include "DynamicDataImpl.h"
12 
13 # include <dds/DCPS/debug.h>
14 # include <dds/DCPS/DCPS_Utils.h>
16 
17 # include <algorithm>
18 
20 namespace OpenDDS {
21 namespace XTypes {
22 
24 using DCPS::LogLevel;
25 using DCPS::log_level;
26 
27 DDS::ReturnCode_t extensibility(DDS::DynamicType_ptr type, DCPS::Extensibility& ext)
28 {
29  DDS::DynamicType_var base_type = get_base_type(type);
30  if (!base_type) {
32  }
33  switch (base_type->get_kind()) {
34  case TK_STRUCTURE:
35  case TK_UNION:
36  {
37  DDS::TypeDescriptor_var td;
38  const DDS::ReturnCode_t rc = type->get_descriptor(td);
39  if (rc != DDS::RETCODE_OK) {
40  return rc;
41  }
42  ext = dds_to_opendds_ext(td->extensibility_kind());
43  }
44  break;
45  default:
46  ext = DCPS::FINAL;
47  }
48  return DDS::RETCODE_OK;
49 }
50 
52 {
53  DDS::ReturnCode_t rc = extensibility(type, ext);
54  if (rc != DDS::RETCODE_OK) {
55  return rc;
56  }
57 
58  DDS::DynamicType_var base_type = get_base_type(type);
59  const TypeKind tk = base_type->get_kind();
60  if (tk != TK_STRUCTURE && tk != TK_UNION) {
61  return DDS::RETCODE_OK;
62  }
63 
64  DDS::DynamicTypeMembersById_var members;
65  rc = base_type->get_all_members(members);
66  if (rc != DDS::RETCODE_OK) {
67  return rc;
68  }
69 
70  DynamicTypeMembersByIdImpl* const members_impl =
71  dynamic_cast<DynamicTypeMembersByIdImpl*>(members.in());
72  if (!members_impl) {
74  }
75 
76  for (DynamicTypeMembersByIdImpl::const_iterator it = members_impl->begin();
77  it != members_impl->end(); ++it) {
78  DDS::MemberDescriptor_var md;
79  rc = it->second->get_descriptor(md);
80  if (rc != DDS::RETCODE_OK) {
81  return rc;
82  }
83 
84  DDS::DynamicType_ptr member_type = md->type();
85  if (!member_type) {
87  }
88  DCPS::Extensibility member_ext;
89  DDS::ReturnCode_t rc = max_extensibility(member_type, member_ext);
90  if (rc != DDS::RETCODE_OK) {
91  return rc;
92  }
93  ext = std::max(member_ext, ext);
94  }
95 
96  return DDS::RETCODE_OK;
97 }
98 
100 {
101  switch (ext) {
102  case DDS::FINAL:
103  return DCPS::FINAL;
104  case DDS::APPENDABLE:
105  return DCPS::APPENDABLE;
106  case DDS::MUTABLE:
107  return DCPS::MUTABLE;
108  }
109  OPENDDS_ASSERT(false);
110  return DCPS::FINAL;
111 }
112 
114 {
115  if (by > left) {
116  if (log_level >= LogLevel::Warning) {
117  ACE_ERROR((LM_WARNING, "(%P|%t) Warning: MemberPathParser::consume: "
118  "at pos %B with %B left trying to increment by %B\n", pos, left, by));
119  }
120  error = true;
121  return false;
122  }
123  pos += by;
124  left -= by;
125  path += by;
126  return true;
127 }
128 
130 {
131  if (!path) {
132  if (log_level >= LogLevel::Notice) {
133  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: MemberPathParser::get_next_subpath: "
134  "empty or null path\n"));
135  }
136  error = true;
137  return false;
138  }
139 
140  // See if we're in a nested member or subscript and move past the '.' or '[' if we are.
141  in_subscript = left > 0 ? path[0] == '[' : false;
142  const bool nested_member = left > 0 ? path[0] == '.' : false;
143  if (nested_member && pos == 0) {
144  if (log_level >= LogLevel::Notice) {
145  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: MemberPathParser::get_next_subpath: "
146  "at pos 0 found unexpected '.'\n"));
147  }
148  error = true;
149  return false;
150  }
151  if (nested_member || in_subscript) {
152  consume(1);
153  }
154 
155  size_t i = 0; // Char count to consume
156  size_t got = 0; // Char count to use for the result
157  char c = '\0';
158  bool scan = true;
159  for (; i < left && scan; ++i) {
160  c = path[i];
161  switch (c) {
162  case '.':
163  case '[':
164  if (in_subscript) {
165  if (log_level >= LogLevel::Notice) {
166  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: MemberPathParser::get_next_subpath: "
167  "at pos %B unexpected '%c' in a subscript\n", pos + i, c));
168  }
169  error = true;
170  return false;
171  }
172  --i; // Don't consume, leave for next iteration
173  // fallthrough
174  case ']':
175  scan = false;
176  break;
177 
178  default:
179  ++got;
180  }
181  }
182 
183  if (in_subscript && c != ']') {
184  if (log_level >= LogLevel::Notice) {
185  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: MemberPathParser::get_next_subpath: "
186  "at pos %B expected to find a ']' to end subscript\n", pos + i));
187  }
188  error = true;
189  return false;
190  }
191 
192  if (got == 0) {
193  if (in_subscript || nested_member) {
194  if (log_level >= LogLevel::Notice) {
195  const char* const expected = in_subscript ? "index or key" : "member name";
196  if (c) {
197  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: MemberPathParser::get_next_subpath: "
198  "at pos %B expected to find %C before '%c'\n", pos + i, expected, c));
199  } else {
200  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: MemberPathParser::get_next_subpath: "
201  "at pos %B expected to find %C before the end of the path\n", pos + i, expected));
202  }
203  }
204  error = true;
205  }
206  return false;
207  }
208 
209  subpath.assign(path, got);
210  return consume(i);
211 }
212 
214 {
215  if (!in_subscript || subpath.empty() ||
216  subpath.find_first_not_of("0123456789") != DCPS::String::npos) {
217  if (log_level >= LogLevel::Notice) {
218  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: MemberPathParser::get_index: "
219  "\"%C\" is not a valid subscript index\n", subpath.c_str()));
220 
221  }
222  return false;
223  }
224  return DCPS::convertToInteger(subpath, index);
225 }
226 
228 {
229  DDS::DynamicType_var current_type = get_base_type(type);
230  if (!current_type) {
232  }
233 
234  MemberPathParser parser(path);
235  while (parser.get_next_subpath()) {
236  if (parser.in_subscript) {
237  if (log_level >= LogLevel::Notice) {
238  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: MemberPath::resolve_string_path: "
239  "given \"%C\", which contains subscripts and these are currently not supported\n",
240  path.c_str()));
241  }
243  }
244  DDS::DynamicTypeMember_var dtm;
245  DDS::ReturnCode_t rc = current_type->get_member_by_name(dtm, parser.subpath.c_str());
246  if (rc != DDS::RETCODE_OK) {
247  return rc;
248  }
249  id(dtm->get_id());
250 
251  DDS::MemberDescriptor_var md;
252  rc = dtm->get_descriptor(md);
253  if (rc != DDS::RETCODE_OK) {
254  return rc;
255  }
256  DDS::DynamicType_var next = get_base_type(md->type());
257  if (!next) {
259  }
260  current_type = next;
261  }
262 
263  if (log_level >= LogLevel::Notice) {
264  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: MemberPath::resolve_string_path: "
265  "parser failed to parse \"%C\"\n", path.c_str()));
266  return DDS::RETCODE_OK;
267  }
268 
270 }
271 
273  DDS::DynamicType_ptr type, DDS::DynamicTypeMember_var& member)
274 {
275  member = 0;
276  if (ids.empty()) {
278  }
279 
280  DDS::DynamicType_var base_type = get_base_type(type);
281  if (!base_type) {
283  }
284 
285  MemberIdVec::iterator it = ids.begin();
286  DDS::DynamicType_var current_type = DDS::DynamicType::_duplicate(type);
287  DDS::DynamicTypeMember_var current_member;
288  while (true) {
289  DDS::ReturnCode_t rc = current_type->get_member(current_member, *it);
290  if (rc != DDS::RETCODE_OK) {
291  return rc;
292  }
293 
294  if (++it == ids.end()) {
295  break;
296  }
297 
298  DDS::MemberDescriptor_var md;
299  rc = current_member->get_descriptor(md);
300  if (rc != DDS::RETCODE_OK) {
301  return rc;
302  }
303  DDS::DynamicType_var next = get_base_type(md->type());
304  if (!next) {
306  }
307  current_type = next;
308  }
309  member = current_member;
310 
311  return DDS::RETCODE_OK;
312 }
313 
315  DDS::DynamicData_ptr data, DDS::DynamicData_var& container, DDS::MemberId& member_id)
316 {
317  container = 0;
318  if (ids.empty()) {
320  }
321 
322  MemberIdVec::iterator it = ids.begin();
323  DDS::DynamicData_var current_container = DDS::DynamicData::_duplicate(data);
324  while (true) {
325  const DDS::MemberId current_id = *it;
326  if (++it == ids.end()) {
327  member_id = current_id;
328  break;
329  }
330 
331  DDS::DynamicData_var next;
332  DDS::ReturnCode_t rc = current_container->get_complex_value(next, current_id);
333  if (rc != DDS::RETCODE_OK) {
334  return rc;
335  }
336  current_container = next;
337  }
338  container = current_container;
339 
340  return DDS::RETCODE_OK;
341 }
342 
343 namespace {
344  DDS::ReturnCode_t get_values_i(DDS::DynamicType_ptr type, MemberPathVec& paths, Filter filter,
345  const MemberPath& base_path)
346  {
347  DDS::DynamicType_var base_type = get_base_type(type);
348  if (!base_type) {
350  }
351  const TypeKind kind = base_type->get_kind();
352  switch (kind) {
353  case TK_STRUCTURE:
354  {
355  DDS::DynamicTypeMembersById_var members;
356  DDS::ReturnCode_t rc = type->get_all_members(members);
357  if (rc != DDS::RETCODE_OK) {
358  return rc;
359  }
360 
361  DynamicTypeMembersByIdImpl* const members_i =
362  dynamic_cast<DynamicTypeMembersByIdImpl*>(members.in());
363  if (!members_i) {
365  }
366 
367  bool include_all = filter == Filter_All;
368  if (filter == Filter_NestedKeys) {
369  // If there are no explicit keys, then they are implied to all be keys.
370  // TODO: Except when @key(FALSE)
371  include_all = true;
372  for (DynamicTypeMembersByIdImpl::const_iterator it = members_i->begin();
373  it != members_i->end(); ++it) {
374  DDS::MemberDescriptor_var md;
375  DDS::ReturnCode_t rc = it->second->get_descriptor(md);
376  if (rc != DDS::RETCODE_OK) {
377  return rc;
378  }
379  if (md->is_key()) {
380  include_all = false;
381  break;
382  }
383  }
384  }
385 
386  for (DynamicTypeMembersByIdImpl::const_iterator it = members_i->begin();
387  it != members_i->end(); ++it) {
388  DDS::MemberDescriptor_var md;
389  DDS::ReturnCode_t rc = it->second->get_descriptor(md);
390  if (rc != DDS::RETCODE_OK) {
391  return rc;
392  }
393  if ((filter == Filter_NonKeys) != (include_all || md->is_key())) {
394  const MemberPath path(base_path, md->id());
395  rc = get_values_i(md->type(), paths,
396  filter == Filter_Keys ? Filter_NestedKeys : filter, path);
397  if (rc != DDS::RETCODE_OK) {
398  return rc;
399  }
400  }
401  }
402  }
403  break;
404 
405  case TK_UNION:
406  {
407  DDS::DynamicTypeMember_var disc;
408  const MemberId id = DISCRIMINATOR_ID;
409  const MemberPath this_path(base_path, id);
410  bool include = false;
411  switch (filter) {
412  case Filter_Keys:
413  case Filter_NonKeys:
414  {
415  DDS::ReturnCode_t rc = type->get_member(disc, id);
416  if (rc != DDS::RETCODE_OK) {
417  return rc;
418  }
419  DDS::MemberDescriptor_var md;
420  rc = disc->get_descriptor(md);
421  if (rc != DDS::RETCODE_OK) {
422  return rc;
423  }
424  include = (filter == Filter_NonKeys) != md->is_key();
425  }
426  break;
427  case Filter_All:
428  case Filter_NestedKeys:
429  // If we're here then the union field has been marked so the
430  // disciminator is an implied key even if it doesn't have @key.
431  // TODO: Except when @key(FALSE)
432  include = true;
433  break;
434  }
435  if (include) {
436  paths.push_back(this_path);
437  }
438  }
439  break;
440 
441  default:
442  if (base_path.level() == 0) {
443  if (log_level >= LogLevel::Notice) {
444  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: get_values_i: "
445  "get_values was passed an invalid topic type: %C\n",
446  typekind_to_string(kind)));
447  }
449  }
450  paths.push_back(base_path);
451  break;
452  }
453 
454  return DDS::RETCODE_OK;
455  }
456 }
457 
458 DDS::ReturnCode_t get_values(DDS::DynamicType_ptr type, MemberPathVec& paths, Filter filter)
459 {
460  return get_values_i(type, paths, filter, MemberPath());
461 }
462 
463 DDS::ReturnCode_t get_keys(DDS::DynamicType_ptr type, MemberPathVec& paths)
464 {
465  return get_values(type, paths, Filter_Keys);
466 }
467 
468 DDS::ReturnCode_t key_count(DDS::DynamicType_ptr type, size_t& count)
469 {
470  MemberPathVec paths;
471  const DDS::ReturnCode_t rc = get_keys(type, paths);
472  if (rc == DDS::RETCODE_OK) {
473  count = paths.size();
474  }
475  return rc;
476 }
477 
478 bool is_key(DDS::DynamicType_ptr type, const char* field)
479 {
480  MemberPathVec paths;
481  if (get_keys(type, paths) != DDS::RETCODE_OK) {
482  return false;
483  }
484  for (size_t i = 0; i < paths.size(); ++i) {
485  DDS::DynamicTypeMember_var m;
486  if (paths[i].get_member_from_type(type, m) != DDS::RETCODE_OK) {
487  return false;
488  }
489  const CORBA::String_var name = m->get_name();
490  if (0 == std::strcmp(name, field)) {
491  return true;
492  }
493  }
494  return false;
495 }
496 
497 namespace {
498  template <typename T>
499  void cmp(int& result, T a, T b)
500  {
501  if (a < b) {
502  result = -1;
503  } else if (a > b) {
504  result = 1;
505  } else {
506  result = 0;
507  }
508  }
509 
510  bool sequence_like(DDS::TypeKind tk)
511  {
512  return tk == TK_ARRAY || tk == TK_SEQUENCE;
513  }
514 
515  DDS::ReturnCode_t member_compare(int& result,
516  DDS::DynamicData_ptr a_data, DDS::MemberId a_id,
517  DDS::DynamicData_ptr b_data, DDS::MemberId b_id)
518  {
519  DDS::DynamicType_var a_type;
520  DDS::ReturnCode_t rc = get_member_type(a_type, a_data, a_id);
521  if (rc != DDS::RETCODE_OK) {
522  return rc;
523  }
524  const DDS::TypeKind tk = a_type->get_kind();
525 
526  DDS::DynamicType_var b_type;
527  rc = get_member_type(b_type, b_data, b_id);
528  if (rc != DDS::RETCODE_OK) {
529  return rc;
530  }
531  const DDS::TypeKind b_tk = b_type->get_kind();
532 
533  if (tk != b_tk) {
534  if (log_level >= LogLevel::Notice) {
535  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: member_compare: "
536  "trying to compare a %C to a %C\n",
537  typekind_to_string(tk),
538  typekind_to_string(b_tk)));
539  }
541  }
542 
545 
546  switch (tk) {
547  case TK_BOOLEAN:
548  {
549  CORBA::Boolean a_value;
550  a_rc = a_data->get_boolean_value(a_value, a_id);
551  if (a_rc == DDS::RETCODE_OK) {
552  CORBA::Boolean b_value;
553  b_rc = b_data->get_boolean_value(b_value, b_id);
554  if (b_rc == DDS::RETCODE_OK) {
555  cmp(result, a_value, b_value);
556  }
557  }
558  }
559  break;
560 
561  case TK_BYTE:
562  {
563  CORBA::Octet a_value;
564  a_rc = a_data->get_byte_value(a_value, a_id);
565  if (a_rc == DDS::RETCODE_OK) {
566  CORBA::Octet b_value;
567  b_rc = b_data->get_byte_value(b_value, b_id);
568  if (b_rc == DDS::RETCODE_OK) {
569  cmp(result, a_value, b_value);
570  }
571  }
572  }
573  break;
574 
575  case TK_UINT8:
576  case TK_UINT16:
577  case TK_UINT32:
578  case TK_UINT64:
579  {
580  CORBA::UInt64 a_value;
581  a_rc = get_uint_value(a_value, a_data, a_id, tk);
582  if (a_rc == DDS::RETCODE_OK) {
583  CORBA::UInt64 b_value;
584  b_rc = get_uint_value(b_value, b_data, b_id, tk);
585  if (b_rc == DDS::RETCODE_OK) {
586  cmp(result, a_value, b_value);
587  }
588  }
589  }
590  break;
591 
592  case TK_INT8:
593  case TK_INT16:
594  case TK_INT32:
595  case TK_INT64:
596  {
597  CORBA::Int64 a_value;
598  a_rc = get_int_value(a_value, a_data, a_id, tk);
599  if (a_rc == DDS::RETCODE_OK) {
600  CORBA::Int64 b_value;
601  b_rc = get_int_value(b_value, b_data, b_id, tk);
602  if (b_rc == DDS::RETCODE_OK) {
603  cmp(result, a_value, b_value);
604  }
605  }
606  }
607  break;
608 
609  case TK_FLOAT32:
610  {
611  CORBA::Float a_value;
612  a_rc = a_data->get_float32_value(a_value, a_id);
613  if (a_rc == DDS::RETCODE_OK) {
614  CORBA::Float b_value;
615  b_rc = b_data->get_float32_value(b_value, b_id);
616  if (b_rc == DDS::RETCODE_OK) {
617  cmp(result, a_value, b_value);
618  }
619  }
620  }
621  break;
622 
623  case TK_FLOAT64:
624  {
625  CORBA::Double a_value;
626  a_rc = a_data->get_float64_value(a_value, a_id);
627  if (a_rc == DDS::RETCODE_OK) {
628  CORBA::Double b_value;
629  b_rc = b_data->get_float64_value(b_value, b_id);
630  if (b_rc == DDS::RETCODE_OK) {
631  cmp(result, a_value, b_value);
632  }
633  }
634  }
635  break;
636 
637  case TK_FLOAT128:
638  {
639  CORBA::LongDouble a_value;
640  a_rc = a_data->get_float128_value(a_value, a_id);
641  if (a_rc == DDS::RETCODE_OK) {
642  CORBA::LongDouble b_value;
643  b_rc = b_data->get_float128_value(b_value, b_id);
644  if (b_rc == DDS::RETCODE_OK) {
645  cmp(result, a_value, b_value);
646  }
647  }
648  }
649  break;
650 
651  case TK_CHAR8:
652  {
653  CORBA::Char a_value;
654  a_rc = a_data->get_char8_value(a_value, a_id);
655  if (a_rc == DDS::RETCODE_OK) {
656  CORBA::Char b_value;
657  b_rc = b_data->get_char8_value(b_value, b_id);
658  if (b_rc == DDS::RETCODE_OK) {
659  cmp(result, a_value, b_value);
660  }
661  }
662  }
663  break;
664 
665  case TK_CHAR16:
666  {
667  CORBA::WChar a_value;
668  a_rc = a_data->get_char16_value(a_value, a_id);
669  if (a_rc == DDS::RETCODE_OK) {
670  CORBA::WChar b_value;
671  b_rc = b_data->get_char16_value(b_value, b_id);
672  if (b_rc == DDS::RETCODE_OK) {
673  cmp(result, a_value, b_value);
674  }
675  }
676  }
677  break;
678 
679  case TK_STRING8:
680  {
681  CORBA::String_var a_value;
682  a_rc = a_data->get_string_value(a_value, a_id);
683  if (a_rc == DDS::RETCODE_OK) {
684  CORBA::String_var b_value;
685  b_rc = b_data->get_string_value(b_value, b_id);
686  if (b_rc == DDS::RETCODE_OK) {
687  result = std::strcmp(a_value.in(), b_value.in());
688  }
689  }
690  }
691  break;
692 
693  case TK_STRING16:
694  {
695  CORBA::WString_var a_value;
696  a_rc = a_data->get_wstring_value(a_value, a_id);
697  if (a_rc == DDS::RETCODE_OK) {
698  CORBA::WString_var b_value;
699  b_rc = b_data->get_wstring_value(b_value, b_id);
700  if (b_rc == DDS::RETCODE_OK) {
701  result = std::wcscmp(a_value.in(), b_value.in());
702  }
703  }
704  }
705  break;
706 
707  case TK_ENUM:
708  {
709  CORBA::Int32 a_value;
710  a_rc = get_enum_value(a_value, a_type, a_data, a_id);
711  if (a_rc == DDS::RETCODE_OK) {
712  CORBA::Int32 b_value;
713  b_rc = get_enum_value(b_value, b_type, b_data, b_id);
714  if (b_rc == DDS::RETCODE_OK) {
715  cmp(result, a_value, b_value);
716  }
717  }
718  }
719  break;
720 
721  case TK_BITMASK:
722  {
723  CORBA::UInt64 a_value;
724  a_rc = get_bitmask_value(a_value, a_type, a_data, a_id);
725  if (a_rc == DDS::RETCODE_OK) {
726  CORBA::UInt64 b_value;
727  b_rc = get_bitmask_value(b_value, b_type, b_data, b_id);
728  if (b_rc == DDS::RETCODE_OK) {
729  cmp(result, a_value, b_value);
730  }
731  }
732  }
733  break;
734 
735  // TODO(iguessthislldo): I hate to leave this for later because it makes maps
736  // and bitsets just that tiny bit harder, but I'm not certain how keys
737  // would work with them.
738  /*
739  case TK_MAP:
740  case TK_BITSET:
741  */
742  case TK_SEQUENCE:
743  case TK_ARRAY:
744  {
745  DDS::DynamicData_var a_value;
746  a_rc = a_data->get_complex_value(a_value, a_id);
747  if (a_rc == DDS::RETCODE_OK) {
748  DDS::DynamicData_var b_value;
749  b_rc = b_data->get_complex_value(b_value, b_id);
750  if (b_rc == DDS::RETCODE_OK) {
751  switch (tk) {
752  case TK_ARRAY:
753  case TK_SEQUENCE:
754  {
755  const ACE_CDR::UInt32 a_count = a_value->get_item_count();
756  const ACE_CDR::UInt32 b_count = b_value->get_item_count();
757  const ACE_CDR::UInt32 count = std::min(a_count, b_count);
758  for (ACE_CDR::UInt32 i = 0;
759  a_rc == DDS::RETCODE_OK && i < count && result == 0; ++i) {
760  a_rc = b_rc = member_compare(result,
761  a_value, a_value->get_member_id_at_index(i),
762  b_value, b_value->get_member_id_at_index(i));
763  }
764  if (result == 0 && a_count != b_count) {
765  result = count == a_count ? -1 : 1;
766  }
767  }
768  break;
769 
770  default:
771  OPENDDS_ASSERT(false);
772  break;
773  }
774  }
775  }
776  }
777  break;
778 
779  case TK_STRUCTURE:
780  case TK_UNION:
781  // get_keys shouldn't be returning these directly, they should be
782  // returning either the key members of the structure or the
783  // discriminator of the union.
784  case TK_ALIAS:
785  case TK_ANNOTATION:
786  default:
787  if (log_level >= LogLevel::Warning) {
788  ACE_ERROR((LM_WARNING, "(%P|%t) WARNING: member_compare(DynamicData): "
789  "member has unexpected TypeKind %C\n", typekind_to_string(b_tk)));
790  }
793  }
794 
795  if (a_rc != DDS::RETCODE_OK || b_rc != DDS::RETCODE_OK) {
796  const CORBA::String_var b_type_name = b_data->type()->get_name();
797  const CORBA::String_var a_type_name = a_data->type()->get_name();
798  if (log_level >= LogLevel::Warning) {
799  ACE_ERROR((LM_WARNING, "(%P|%t) WARNING: member_compare(DynamicData): "
800  "Could not compare member type %C id %u from %C (%C) to %C (%C)\n",
801  typekind_to_string(tk), a_id,
802  a_type_name.in(), retcode_to_string(a_rc),
803  b_type_name.in(), retcode_to_string(b_rc)));
804  }
805  }
806 
807  return DDS::RETCODE_OK;
808  }
809 }
810 
812  bool& result, DDS::DynamicData_ptr a, DDS::DynamicData_ptr b, Filter filter)
813 {
814  DDS::DynamicType_var a_type = a->type();
815  MemberPathVec paths;
816  DDS::ReturnCode_t rc = get_values(a_type, paths, filter);
817  if (rc != DDS::RETCODE_OK) {
818  if (log_level >= LogLevel::Notice) {
819  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: key_compare: get_keys failed: %C\n",
820  retcode_to_string(rc)));
821  }
822  return rc;
823  }
824 
825  result = false;
826  for (MemberPathVec::iterator it = paths.begin(); it != paths.end(); it++) {
827  DDS::DynamicData_var a_container;
828  DDS::MemberId a_member_id;
829  rc = it->get_member_from_data(a, a_container, a_member_id);
830  if (rc != DDS::RETCODE_OK) {
831  if (log_level >= LogLevel::Notice) {
832  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: key_compare: "
833  "get_member_from_data for a failed: %C\n",
834  retcode_to_string(rc)));
835  }
836  return rc;
837  }
838 
839  DDS::DynamicData_var b_container;
840  DDS::MemberId b_member_id;
841  rc = it->get_member_from_data(b, b_container, b_member_id);
842  if (rc != DDS::RETCODE_OK) {
843  if (log_level >= LogLevel::Notice) {
844  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: key_compare: "
845  "get_member_from_data for b failed: %C\n",
846  retcode_to_string(rc)));
847  }
848  return rc;
849  }
850 
851  int compare = 0;
852  rc = member_compare(compare, a_container, a_member_id, b_container, b_member_id);
853  if (rc != DDS::RETCODE_OK) {
854  return rc;
855  }
856  if (compare != 0) {
857  result = compare < 0;
858  return DDS::RETCODE_OK;
859  }
860  }
861 
862  return DDS::RETCODE_OK;
863 }
864 
865 DDS::ReturnCode_t key_less_than(bool& result, DDS::DynamicData_ptr a, DDS::DynamicData_ptr b)
866 {
867  return less_than(result, a, b, Filter_Keys);
868 }
869 
870 DDS::ReturnCode_t compare_members(int& result, DDS::DynamicData_ptr a, DDS::DynamicData_ptr b, DDS::MemberId id)
871 {
872  return member_compare(result, a, id, b, id);
873 }
874 
875 DDS::ReturnCode_t get_member_type(DDS::DynamicType_var& member_type,
876  DDS::DynamicType_ptr container_type, DDS::MemberId id)
877 {
878  if (sequence_like(container_type->get_kind())) {
879  DDS::TypeDescriptor_var td;
880  DDS::ReturnCode_t rc = container_type->get_descriptor(td);
881  if (rc != DDS::RETCODE_OK) {
882  return rc;
883  }
884  member_type = get_base_type(td->element_type());
885  } else {
886  DDS::DynamicTypeMember_var dtm;
887  DDS::ReturnCode_t rc = container_type->get_member(dtm, id);
888  if (rc != DDS::RETCODE_OK) {
889  return rc;
890  }
891  DDS::MemberDescriptor_var md;
892  rc = dtm->get_descriptor(md);
893  if (rc != DDS::RETCODE_OK) {
894  return rc;
895  }
896  member_type = get_base_type(md->type());
897  }
898  return DDS::RETCODE_OK;
899 }
900 
902 {
903  switch (tk) {
904  case TK_INT8:
905  case TK_INT16:
906  case TK_INT32:
907  case TK_INT64:
908  return true;
909  default:
910  return false;
911  }
912 }
913 
915 {
916  switch (tk) {
917  case TK_UINT8:
918  case TK_UINT16:
919  case TK_UINT32:
920  case TK_UINT64:
921  return true;
922  default:
923  return false;
924  }
925 }
926 
928  CORBA::UInt64& value, DDS::DynamicData_ptr src, DDS::MemberId id, DDS::TypeKind kind)
929 {
931  switch (kind) {
932  case TK_UINT8:
933  {
934  CORBA::UInt8 v;
935  rc = src->get_uint8_value(v, id);
936  if (rc == DDS::RETCODE_OK) {
937  value = v;
938  }
939  }
940  break;
941  case TK_UINT16:
942  {
943  CORBA::UInt16 v;
944  rc = src->get_uint16_value(v, id);
945  if (rc == DDS::RETCODE_OK) {
946  value = v;
947  }
948  }
949  break;
950  case TK_UINT32:
951  {
952  CORBA::UInt32 v;
953  rc = src->get_uint32_value(v, id);
954  if (rc == DDS::RETCODE_OK) {
955  value = v;
956  }
957  }
958  break;
959  case TK_UINT64:
960  rc = src->get_uint64_value(value, id);
961  break;
962  }
963  return rc;
964 }
965 
967  DDS::DynamicData_ptr src, DDS::MemberId id, DDS::TypeKind kind, CORBA::UInt64 value)
968 {
969  switch (kind) {
970  case TK_UINT8:
971  return src->set_uint8_value(id, static_cast<DDS::UInt8>(value));
972  case TK_UINT16:
973  return src->set_uint16_value(id, static_cast<DDS::UInt16>(value));
974  case TK_UINT32:
975  return src->set_uint32_value(id, static_cast<DDS::UInt32>(value));
976  case TK_UINT64:
977  return src->set_uint64_value(id, value);
978  }
980 }
981 
983  CORBA::Int64& value, DDS::DynamicData_ptr src, DDS::MemberId id, DDS::TypeKind kind)
984 {
986  switch (kind) {
987  case TK_INT8:
988  {
989  CORBA::Int8 v;
990  rc = src->get_int8_value(v, id);
991  if (rc == DDS::RETCODE_OK) {
992  value = v;
993  }
994  }
995  break;
996  case TK_INT16:
997  {
998  CORBA::Int16 v;
999  rc = src->get_int16_value(v, id);
1000  if (rc == DDS::RETCODE_OK) {
1001  value = v;
1002  }
1003  }
1004  break;
1005  case TK_INT32:
1006  {
1007  CORBA::Int32 v;
1008  rc = src->get_int32_value(v, id);
1009  if (rc == DDS::RETCODE_OK) {
1010  value = v;
1011  }
1012  }
1013  break;
1014  case TK_INT64:
1015  rc = src->get_int64_value(value, id);
1016  break;
1017  }
1018  return rc;
1019 }
1020 
1022  DDS::DynamicData_ptr src, DDS::MemberId id, DDS::TypeKind kind, CORBA::Int64 value)
1023 {
1024  switch (kind) {
1025  case TK_INT8:
1026  return src->set_int8_value(id, static_cast<DDS::Int8>(value));
1027  case TK_INT16:
1028  return src->set_int16_value(id, static_cast<DDS::Int16>(value));
1029  case TK_INT32:
1030  return src->set_int32_value(id, static_cast<DDS::Int32>(value));
1031  case TK_INT64:
1032  return src->set_int64_value(id, value);
1033  }
1035 }
1036 
1037 DDS::ReturnCode_t bitmask_bound(DDS::DynamicType_ptr type, DDS::TypeKind& bound_kind)
1038 {
1039  const DDS::TypeKind kind = type->get_kind();
1040  if (kind != TK_BITMASK) {
1041  if (log_level >= LogLevel::Notice) {
1042  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: bitmask_bound: "
1043  "expected bitmask, got %C\n",
1044  typekind_to_string(kind)));
1045  }
1047  }
1048 
1049  DDS::TypeDescriptor_var td;
1050  const DDS::ReturnCode_t rc = type->get_descriptor(td);
1051  if (rc != DDS::RETCODE_OK) {
1052  return rc;
1053  }
1054 
1055  const size_t bound_size = td->bound()[0];
1056  if (bound_size >= 1 && bound_size <= 8) {
1057  bound_kind = TK_UINT8;
1058  } else if (bound_size >= 9 && bound_size <= 16) {
1059  bound_kind = TK_UINT16;
1060  } else if (bound_size >= 17 && bound_size <= 32) {
1061  bound_kind = TK_UINT32;
1062  } else if (bound_size >= 33 && bound_size <= 64) {
1063  bound_kind = TK_UINT64;
1064  } else {
1065  if (log_level >= LogLevel::Notice) {
1066  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: bitmask_bound: "
1067  "Got unexpected bound size %B\n",
1068  bound_size));
1069  }
1071  }
1072  return DDS::RETCODE_OK;
1073 }
1074 
1076  CORBA::UInt64& value, DDS::DynamicType_ptr type, DDS::DynamicData_ptr src, DDS::MemberId id)
1077 {
1078  DDS::TypeKind bound_kind;
1079  const DDS::ReturnCode_t rc = bitmask_bound(type, bound_kind);
1080  if (rc != DDS::RETCODE_OK) {
1081  return rc;
1082  }
1083  return get_uint_value(value, src, id, bound_kind);
1084 }
1085 
1086 DDS::ReturnCode_t enum_bound(DDS::DynamicType_ptr type, DDS::TypeKind& bound_kind)
1087 {
1088  const DDS::TypeKind kind = type->get_kind();
1089  if (kind != TK_ENUM) {
1090  if (log_level >= LogLevel::Notice) {
1091  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: enum_bound: "
1092  "expected enum, got %C\n",
1093  typekind_to_string(kind)));
1094  }
1096  }
1097 
1098  DDS::TypeDescriptor_var td;
1099  const DDS::ReturnCode_t rc = type->get_descriptor(td);
1100  if (rc != DDS::RETCODE_OK) {
1101  return rc;
1102  }
1103 
1104  const size_t bound_size = td->bound()[0];
1105  if (bound_size >= 1 && bound_size <= 8) {
1106  bound_kind = TK_INT8;
1107  } else if (bound_size >= 9 && bound_size <= 16) {
1108  bound_kind = TK_INT16;
1109  } else if (bound_size >= 17 && bound_size <= 32) {
1110  bound_kind = TK_INT32;
1111  } else {
1112  if (log_level >= LogLevel::Notice) {
1113  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: enum_bound: "
1114  "Got unexpected bound size %B\n",
1115  bound_size));
1116  }
1118  }
1119  return DDS::RETCODE_OK;
1120 }
1121 
1123  CORBA::Int32& value, DDS::DynamicType_ptr type, DDS::DynamicData_ptr src, DDS::MemberId id)
1124 {
1125  DDS::TypeKind bound_kind;
1126  DDS::ReturnCode_t rc = enum_bound(type, bound_kind);
1127  if (rc != DDS::RETCODE_OK) {
1128  return rc;
1129  }
1130  CORBA::Int64 v;
1131  rc = get_int_value(v, src, id, bound_kind);
1132  if (rc != DDS::RETCODE_OK) {
1133  return rc;
1134  }
1135  value = static_cast<CORBA::Int32>(v);
1136  return rc;
1137 }
1138 
1140  DDS::String8_var& name, DDS::Int32 value, DDS::DynamicType_ptr type)
1141 {
1142  DDS::DynamicTypeMember_var dtm;
1143  DDS::ReturnCode_t rc = type->get_member(dtm, static_cast<DDS::MemberId>(value));
1144  if (rc != DDS::RETCODE_OK) {
1145  return rc;
1146  }
1147 
1148  DDS::MemberDescriptor_var md;
1149  rc = dtm->get_descriptor(md);
1150  if (rc != DDS::RETCODE_OK) {
1151  return rc;
1152  }
1153 
1154  name = md->name();
1155  return DDS::RETCODE_OK;
1156 }
1157 
1159  DDS::Int32& value, const char* name, DDS::DynamicType_ptr type)
1160 {
1161  DDS::DynamicTypeMember_var dtm;
1162  DDS::ReturnCode_t rc = type->get_member_by_name(dtm, name);
1163  if (rc != DDS::RETCODE_OK) {
1164  return rc;
1165  }
1166 
1167  DDS::MemberDescriptor_var md;
1168  rc = dtm->get_descriptor(md);
1169  if (rc != DDS::RETCODE_OK) {
1170  return rc;
1171  }
1172 
1173  value = static_cast<DDS::Int32>(md->id());
1174  return DDS::RETCODE_OK;
1175 }
1176 
1178  DDS::DynamicType_ptr type, DDS::DynamicData_ptr src, DDS::MemberId id, CORBA::Int32 value)
1179 {
1180  DDS::TypeKind bound_kind;
1181  const DDS::ReturnCode_t rc = enum_bound(type, bound_kind);
1182  if (rc != DDS::RETCODE_OK) {
1183  return rc;
1184  }
1185  return set_int_value(src, id, bound_kind, value);
1186 }
1187 
1189  DDS::DynamicType_ptr type, DDS::DynamicData_ptr src, DDS::MemberId id, const char* enumeral_name)
1190 {
1191  DDS::DynamicTypeMember_var dtm;
1192  DDS::ReturnCode_t rc = type->get_member_by_name(dtm, enumeral_name);
1193  if (rc != DDS::RETCODE_OK) {
1194  if (log_level >= LogLevel::Notice) {
1195  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: set_enum_value: "
1196  "No such enumeral named \"%C\"\n",
1197  enumeral_name));
1198  }
1199  return rc;
1200  }
1201  DDS::MemberDescriptor_var md;
1202  rc = dtm->get_descriptor(md);
1203  if (rc != DDS::RETCODE_OK) {
1204  return rc;
1205  }
1206  return set_enum_value(type, src, id, md->id());
1207 }
1208 
1209 } // namespace XTypes
1210 } // namespace OpenDDS
1212 
1213 #endif // OPENDDS_SAFETY_PROFILE
OpenDDS_Dcps_Export LogLevel log_level
#define ACE_ERROR(X)
ACE_CDR::ULong MemberId
Definition: TypeObject.h:910
const TypeKind TK_INT8
Definition: TypeObject.h:225
const char * retcode_to_string(DDS::ReturnCode_t value)
Definition: DCPS_Utils.cpp:29
const LogLevel::Value value
Definition: debug.cpp:61
ACE_CDR::Int32 Int32
const TypeKind TK_ANNOTATION
Definition: TypeObject.h:242
DDS::ReturnCode_t get_enumerator_value(DDS::Int32 &value, const char *name, DDS::DynamicType_ptr type)
const ReturnCode_t RETCODE_ILLEGAL_OPERATION
const TypeKind TK_FLOAT128
Definition: TypeObject.h:224
DDS::ReturnCode_t get_member_type(DDS::DynamicType_var &member_type, DDS::DynamicType_ptr container_type, DDS::MemberId id)
const ReturnCode_t RETCODE_OK
DDS::DynamicType_var get_base_type(DDS::DynamicType_ptr type)
DDS::ReturnCode_t get_int_value(CORBA::Int64 &value, DDS::DynamicData_ptr src, DDS::MemberId id, DDS::TypeKind kind)
const ReturnCode_t RETCODE_BAD_PARAMETER
const TypeKind TK_CHAR16
Definition: TypeObject.h:228
DDS::ReturnCode_t max_extensibility(DDS::DynamicType_ptr type, DCPS::Extensibility &ext)
#define OPENDDS_END_VERSIONED_NAMESPACE_DECL
DDS::ReturnCode_t key_count(DDS::DynamicType_ptr type, size_t &count)
const TypeKind TK_ALIAS
Definition: TypeObject.h:235
DDS::ReturnCode_t set_enum_value(DDS::DynamicType_ptr type, DDS::DynamicData_ptr src, DDS::MemberId id, CORBA::Int32 value)
const ACE_CDR::ULong DISCRIMINATOR_ID
Implementation specific sentinel for a union discriminator used in DynamicData.
Definition: TypeObject.h:913
const TypeKind TK_INT32
Definition: TypeObject.h:217
#define OPENDDS_ASSERT(C)
Definition: Definitions.h:66
bool is_key(DDS::DynamicType_ptr type, const char *field)
const TypeKind TK_CHAR8
Definition: TypeObject.h:227
const TypeKind TK_STRING16
Definition: TypeObject.h:232
DDS::ReturnCode_t key_less_than(bool &result, DDS::DynamicData_ptr a, DDS::DynamicData_ptr b)
The Internal API and Implementation of OpenDDS.
Definition: AddressCache.h:28
bool convertToInteger(const String &s, T &value)
const TypeKind TK_STRUCTURE
Definition: TypeObject.h:243
bool get_index(CORBA::UInt32 &index)
DDS::ReturnCode_t set_int_value(DDS::DynamicData_ptr src, DDS::MemberId id, DDS::TypeKind kind, CORBA::Int64 value)
const TypeKind TK_UINT16
Definition: TypeObject.h:219
DDS::ReturnCode_t compare_members(int &result, DDS::DynamicData_ptr a, DDS::DynamicData_ptr b, DDS::MemberId id)
const TypeKind TK_INT64
Definition: TypeObject.h:218
DDS::ReturnCode_t bitmask_bound(DDS::DynamicType_ptr type, DDS::TypeKind &bound_kind)
ACE_CDR::Boolean Boolean
const TypeKind TK_BITMASK
Definition: TypeObject.h:239
const TypeKind TK_UINT8
Definition: TypeObject.h:226
const TypeKind TK_FLOAT32
Definition: TypeObject.h:222
ACE_CDR::UInt64 UInt64
DDS::ReturnCode_t get_keys(DDS::DynamicType_ptr type, MemberPathVec &paths)
DDS::ReturnCode_t set_uint_value(DDS::DynamicData_ptr src, DDS::MemberId id, DDS::TypeKind kind, CORBA::UInt64 value)
const TypeKind TK_BOOLEAN
Definition: TypeObject.h:214
DDS::ReturnCode_t enum_bound(DDS::DynamicType_ptr type, DDS::TypeKind &bound_kind)
bool is_int(DDS::TypeKind tk)
const TypeKind TK_INT16
Definition: TypeObject.h:216
LM_NOTICE
DDS::ReturnCode_t get_member_from_type(DDS::DynamicType_ptr type, DDS::DynamicTypeMember_var &member)
const TypeKind TK_FLOAT64
Definition: TypeObject.h:223
LM_WARNING
const TypeKind TK_STRING8
Definition: TypeObject.h:231
DDS::ReturnCode_t get_bitmask_value(CORBA::UInt64 &value, DDS::DynamicType_ptr type, DDS::DynamicData_ptr src, DDS::MemberId id)
const char *const name
Definition: debug.cpp:60
ACE_CDR::Int64 Int64
const TypeKind TK_SEQUENCE
Definition: TypeObject.h:248
const TypeKind TK_ENUM
Definition: TypeObject.h:238
DDS::ReturnCode_t get_member_from_data(DDS::DynamicData_ptr data, DDS::DynamicData_var &container, DDS::MemberId &member_id)
MemberPath & id(DDS::MemberId id)
Definition: XTypes/Utils.h:101
bool is_uint(DDS::TypeKind tk)
DDS::ReturnCode_t get_uint_value(CORBA::UInt64 &value, DDS::DynamicData_ptr src, DDS::MemberId id, DDS::TypeKind kind)
const TypeKind TK_UINT32
Definition: TypeObject.h:220
DDS::ReturnCode_t less_than(bool &result, DDS::DynamicData_ptr a, DDS::DynamicData_ptr b, Filter filter)
const char * typekind_to_string(TypeKind tk)
const TypeKind TK_BYTE
Definition: TypeObject.h:215
DDS::ReturnCode_t get_enum_value(CORBA::Int32 &value, DDS::DynamicType_ptr type, DDS::DynamicData_ptr src, DDS::MemberId id)
ACE_CDR::Char Char
const TypeKind TK_UNION
Definition: TypeObject.h:244
ULong UInt32
const TypeKind TK_UINT64
Definition: TypeObject.h:221
ACE_CDR::Octet Octet
std::string String
ACE_CDR::Int16 Int16
ACE_CDR::WChar WChar
const TypeKind TK_ARRAY
Definition: TypeObject.h:249
DDS::ReturnCode_t get_enumerator_name(DDS::String8_var &name, DDS::Int32 value, DDS::DynamicType_ptr type)
DDS::ReturnCode_t get_values(DDS::DynamicType_ptr type, MemberPathVec &paths, Filter filter)
const character_type * in(void) const
const ReturnCode_t RETCODE_UNSUPPORTED
ACE_CDR::UInt32 UInt32
ACE_CDR::Octet TypeKind
Definition: TypeObject.h:210
extensibility(MUTABLE) struct TypeLookup_getTypes_In
Definition: TypeLookup.idl:29
ExtensibilityKind
ACE_CDR::UInt16 UInt16
DDS::ReturnCode_t resolve_string_path(DDS::DynamicType_ptr type, const DCPS::String &path)
DCPS::Extensibility dds_to_opendds_ext(DDS::ExtensibilityKind ext)