OpenDDS  Snapshot(2023/04/28-20:55)
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 
213 bool MemberPathParser::get_index(DDS::UInt32& index)
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  DDS::ReturnCode_t member_compare(int& result,
511  DDS::DynamicData_ptr a_data, DDS::MemberId a_id,
512  DDS::DynamicData_ptr b_data, DDS::MemberId b_id)
513  {
514  DDS::DynamicType_var a_type;
515  DDS::ReturnCode_t rc = get_member_type(a_type, a_data, a_id);
516  if (rc != DDS::RETCODE_OK) {
517  return rc;
518  }
519  const DDS::TypeKind tk = a_type->get_kind();
520 
521  DDS::DynamicType_var b_type;
522  rc = get_member_type(b_type, b_data, b_id);
523  if (rc != DDS::RETCODE_OK) {
524  return rc;
525  }
526  const DDS::TypeKind b_tk = b_type->get_kind();
527 
528  if (tk != b_tk) {
529  if (log_level >= LogLevel::Notice) {
530  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: member_compare: "
531  "trying to compare a %C to a %C\n",
532  typekind_to_string(tk),
533  typekind_to_string(b_tk)));
534  }
536  }
537 
540 
541  switch (tk) {
542  case TK_BOOLEAN:
543  {
544  DDS::Boolean a_value;
545  a_rc = a_data->get_boolean_value(a_value, a_id);
546  if (a_rc == DDS::RETCODE_OK) {
547  DDS::Boolean b_value;
548  b_rc = b_data->get_boolean_value(b_value, b_id);
549  if (b_rc == DDS::RETCODE_OK) {
550  cmp(result, a_value, b_value);
551  }
552  }
553  }
554  break;
555 
556  case TK_BYTE:
557  {
558  DDS::Byte a_value;
559  a_rc = a_data->get_byte_value(a_value, a_id);
560  if (a_rc == DDS::RETCODE_OK) {
561  DDS::Byte b_value;
562  b_rc = b_data->get_byte_value(b_value, b_id);
563  if (b_rc == DDS::RETCODE_OK) {
564  cmp(result, a_value, b_value);
565  }
566  }
567  }
568  break;
569 
570  case TK_UINT8:
571  case TK_UINT16:
572  case TK_UINT32:
573  case TK_UINT64:
574  {
575  DDS::UInt64 a_value;
576  a_rc = get_uint_value(a_value, a_data, a_id, tk);
577  if (a_rc == DDS::RETCODE_OK) {
578  DDS::UInt64 b_value;
579  b_rc = get_uint_value(b_value, b_data, b_id, tk);
580  if (b_rc == DDS::RETCODE_OK) {
581  cmp(result, a_value, b_value);
582  }
583  }
584  }
585  break;
586 
587  case TK_INT8:
588  case TK_INT16:
589  case TK_INT32:
590  case TK_INT64:
591  {
592  DDS::Int64 a_value;
593  a_rc = get_int_value(a_value, a_data, a_id, tk);
594  if (a_rc == DDS::RETCODE_OK) {
595  DDS::Int64 b_value;
596  b_rc = get_int_value(b_value, b_data, b_id, tk);
597  if (b_rc == DDS::RETCODE_OK) {
598  cmp(result, a_value, b_value);
599  }
600  }
601  }
602  break;
603 
604  case TK_FLOAT32:
605  {
606  DDS::Float32 a_value;
607  a_rc = a_data->get_float32_value(a_value, a_id);
608  if (a_rc == DDS::RETCODE_OK) {
609  DDS::Float32 b_value;
610  b_rc = b_data->get_float32_value(b_value, b_id);
611  if (b_rc == DDS::RETCODE_OK) {
612  cmp(result, a_value, b_value);
613  }
614  }
615  }
616  break;
617 
618  case TK_FLOAT64:
619  {
620  DDS::Float64 a_value;
621  a_rc = a_data->get_float64_value(a_value, a_id);
622  if (a_rc == DDS::RETCODE_OK) {
623  DDS::Float64 b_value;
624  b_rc = b_data->get_float64_value(b_value, b_id);
625  if (b_rc == DDS::RETCODE_OK) {
626  cmp(result, a_value, b_value);
627  }
628  }
629  }
630  break;
631 
632  case TK_FLOAT128:
633  {
634  DDS::Float128 a_value;
635  a_rc = a_data->get_float128_value(a_value, a_id);
636  if (a_rc == DDS::RETCODE_OK) {
637  DDS::Float128 b_value;
638  b_rc = b_data->get_float128_value(b_value, b_id);
639  if (b_rc == DDS::RETCODE_OK) {
640  cmp(result, a_value, b_value);
641  }
642  }
643  }
644  break;
645 
646  case TK_CHAR8:
647  {
648  CORBA::Char a_value;
649  a_rc = a_data->get_char8_value(a_value, a_id);
650  if (a_rc == DDS::RETCODE_OK) {
651  CORBA::Char b_value;
652  b_rc = b_data->get_char8_value(b_value, b_id);
653  if (b_rc == DDS::RETCODE_OK) {
654  cmp(result, a_value, b_value);
655  }
656  }
657  }
658  break;
659 
660  case TK_CHAR16:
661  {
662  CORBA::WChar a_value;
663  a_rc = a_data->get_char16_value(a_value, a_id);
664  if (a_rc == DDS::RETCODE_OK) {
665  CORBA::WChar b_value;
666  b_rc = b_data->get_char16_value(b_value, b_id);
667  if (b_rc == DDS::RETCODE_OK) {
668  cmp(result, a_value, b_value);
669  }
670  }
671  }
672  break;
673 
674  case TK_STRING8:
675  {
676  CORBA::String_var a_value;
677  a_rc = a_data->get_string_value(a_value, a_id);
678  if (a_rc == DDS::RETCODE_OK) {
679  CORBA::String_var b_value;
680  b_rc = b_data->get_string_value(b_value, b_id);
681  if (b_rc == DDS::RETCODE_OK) {
682  result = std::strcmp(a_value.in(), b_value.in());
683  }
684  }
685  }
686  break;
687 
688  case TK_STRING16:
689  {
690  CORBA::WString_var a_value;
691  a_rc = a_data->get_wstring_value(a_value, a_id);
692  if (a_rc == DDS::RETCODE_OK) {
693  CORBA::WString_var b_value;
694  b_rc = b_data->get_wstring_value(b_value, b_id);
695  if (b_rc == DDS::RETCODE_OK) {
696  result = std::wcscmp(a_value.in(), b_value.in());
697  }
698  }
699  }
700  break;
701 
702  case TK_ENUM:
703  {
704  DDS::Int32 a_value;
705  a_rc = get_enum_value(a_value, a_type, a_data, a_id);
706  if (a_rc == DDS::RETCODE_OK) {
707  DDS::Int32 b_value;
708  b_rc = get_enum_value(b_value, b_type, b_data, b_id);
709  if (b_rc == DDS::RETCODE_OK) {
710  cmp(result, a_value, b_value);
711  }
712  }
713  }
714  break;
715 
716  case TK_BITMASK:
717  {
718  DDS::UInt64 a_value;
719  a_rc = get_bitmask_value(a_value, a_type, a_data, a_id);
720  if (a_rc == DDS::RETCODE_OK) {
721  DDS::UInt64 b_value;
722  b_rc = get_bitmask_value(b_value, b_type, b_data, b_id);
723  if (b_rc == DDS::RETCODE_OK) {
724  cmp(result, a_value, b_value);
725  }
726  }
727  }
728  break;
729 
730  // TODO(iguessthislldo): I hate to leave this for later because it makes maps
731  // and bitsets just that tiny bit harder, but I'm not certain how keys
732  // would work with them.
733  /*
734  case TK_MAP:
735  case TK_BITSET:
736  */
737  case TK_SEQUENCE:
738  case TK_ARRAY:
739  {
740  DDS::DynamicData_var a_value;
741  a_rc = a_data->get_complex_value(a_value, a_id);
742  if (a_rc == DDS::RETCODE_OK) {
743  DDS::DynamicData_var b_value;
744  b_rc = b_data->get_complex_value(b_value, b_id);
745  if (b_rc == DDS::RETCODE_OK) {
746  switch (tk) {
747  case TK_ARRAY:
748  case TK_SEQUENCE:
749  {
750  const DDS::UInt32 a_count = a_value->get_item_count();
751  const DDS::UInt32 b_count = b_value->get_item_count();
752  const DDS::UInt32 count = std::min(a_count, b_count);
753  for (DDS::UInt32 i = 0;
754  a_rc == DDS::RETCODE_OK && i < count && result == 0; ++i) {
755  a_rc = b_rc = member_compare(result,
756  a_value, a_value->get_member_id_at_index(i),
757  b_value, b_value->get_member_id_at_index(i));
758  }
759  if (result == 0 && a_count != b_count) {
760  result = count == a_count ? -1 : 1;
761  }
762  }
763  break;
764 
765  default:
766  OPENDDS_ASSERT(false);
767  break;
768  }
769  }
770  }
771  }
772  break;
773 
774  case TK_STRUCTURE:
775  case TK_UNION:
776  // get_keys shouldn't be returning these directly, they should be
777  // returning either the key members of the structure or the
778  // discriminator of the union.
779  case TK_ALIAS:
780  case TK_ANNOTATION:
781  default:
782  if (log_level >= LogLevel::Warning) {
783  ACE_ERROR((LM_WARNING, "(%P|%t) WARNING: member_compare(DynamicData): "
784  "member has unexpected TypeKind %C\n", typekind_to_string(b_tk)));
785  }
788  }
789 
790  if (a_rc != DDS::RETCODE_OK || b_rc != DDS::RETCODE_OK) {
791  const CORBA::String_var b_type_name = b_data->type()->get_name();
792  const CORBA::String_var a_type_name = a_data->type()->get_name();
793  if (log_level >= LogLevel::Warning) {
794  ACE_ERROR((LM_WARNING, "(%P|%t) WARNING: member_compare(DynamicData): "
795  "Could not compare member type %C id %u from %C (%C) to %C (%C)\n",
796  typekind_to_string(tk), a_id,
797  a_type_name.in(), retcode_to_string(a_rc),
798  b_type_name.in(), retcode_to_string(b_rc)));
799  }
800  }
801 
802  return DDS::RETCODE_OK;
803  }
804 }
805 
807  bool& result, DDS::DynamicData_ptr a, DDS::DynamicData_ptr b, Filter filter)
808 {
809  DDS::DynamicType_var a_type = a->type();
810  MemberPathVec paths;
811  DDS::ReturnCode_t rc = get_values(a_type, paths, filter);
812  if (rc != DDS::RETCODE_OK) {
813  if (log_level >= LogLevel::Notice) {
814  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: key_compare: get_keys failed: %C\n",
815  retcode_to_string(rc)));
816  }
817  return rc;
818  }
819 
820  result = false;
821  for (MemberPathVec::iterator it = paths.begin(); it != paths.end(); it++) {
822  DDS::DynamicData_var a_container;
823  DDS::MemberId a_member_id;
824  rc = it->get_member_from_data(a, a_container, a_member_id);
825  if (rc != DDS::RETCODE_OK) {
826  if (log_level >= LogLevel::Notice) {
827  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: key_compare: "
828  "get_member_from_data for a failed: %C\n",
829  retcode_to_string(rc)));
830  }
831  return rc;
832  }
833 
834  DDS::DynamicData_var b_container;
835  DDS::MemberId b_member_id;
836  rc = it->get_member_from_data(b, b_container, b_member_id);
837  if (rc != DDS::RETCODE_OK) {
838  if (log_level >= LogLevel::Notice) {
839  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: key_compare: "
840  "get_member_from_data for b failed: %C\n",
841  retcode_to_string(rc)));
842  }
843  return rc;
844  }
845 
846  int compare = 0;
847  rc = member_compare(compare, a_container, a_member_id, b_container, b_member_id);
848  if (rc != DDS::RETCODE_OK) {
849  return rc;
850  }
851  if (compare != 0) {
852  result = compare < 0;
853  return DDS::RETCODE_OK;
854  }
855  }
856 
857  return DDS::RETCODE_OK;
858 }
859 
860 DDS::ReturnCode_t key_less_than(bool& result, DDS::DynamicData_ptr a, DDS::DynamicData_ptr b)
861 {
862  return less_than(result, a, b, Filter_Keys);
863 }
864 
865 DDS::ReturnCode_t compare_members(int& result, DDS::DynamicData_ptr a, DDS::DynamicData_ptr b, DDS::MemberId id)
866 {
867  return member_compare(result, a, id, b, id);
868 }
869 
870 DDS::ReturnCode_t get_member_type(DDS::DynamicType_var& member_type,
871  DDS::DynamicType_ptr container_type, DDS::MemberId id)
872 {
873  const DDS::TypeKind container_kind = container_type->get_kind();
874  if (is_sequence_like(container_kind)) {
875  DDS::TypeDescriptor_var td;
876  DDS::ReturnCode_t rc = container_type->get_descriptor(td);
877  if (rc != DDS::RETCODE_OK) {
878  return rc;
879  }
880  member_type = get_base_type(td->element_type());
881  } else if (is_scalar(container_kind)) {
883  ACE_ERROR((LM_WARNING, "(%P|%t) WARNING: get_member_type: "
884  "Accessing a %C DynamicData via id %u, not MEMBER_ID_INVALID\n",
885  typekind_to_string(container_kind), id));
886  }
887  member_type = DDS::DynamicType::_duplicate(container_type);
888  return DDS::RETCODE_OK;
889  } else {
890  DDS::DynamicTypeMember_var dtm;
891  DDS::ReturnCode_t rc = container_type->get_member(dtm, id);
892  if (rc != DDS::RETCODE_OK) {
893  return rc;
894  }
895  DDS::MemberDescriptor_var md;
896  rc = dtm->get_descriptor(md);
897  if (rc != DDS::RETCODE_OK) {
898  return rc;
899  }
900  member_type = get_base_type(md->type());
901  }
902  return DDS::RETCODE_OK;
903 }
904 
906  DDS::UInt64& value, DDS::DynamicData_ptr src, DDS::MemberId id, DDS::TypeKind kind)
907 {
909  switch (kind) {
910  case TK_UINT8:
911  {
912  DDS::UInt8 v;
913  rc = src->get_uint8_value(v, id);
914  if (rc == DDS::RETCODE_OK) {
915  value = v;
916  }
917  }
918  break;
919  case TK_UINT16:
920  {
921  DDS::UInt16 v;
922  rc = src->get_uint16_value(v, id);
923  if (rc == DDS::RETCODE_OK) {
924  value = v;
925  }
926  }
927  break;
928  case TK_UINT32:
929  {
930  DDS::UInt32 v;
931  rc = src->get_uint32_value(v, id);
932  if (rc == DDS::RETCODE_OK) {
933  value = v;
934  }
935  }
936  break;
937  case TK_UINT64:
938  rc = src->get_uint64_value(value, id);
939  break;
940  }
941  return rc;
942 }
943 
945  DDS::DynamicData_ptr dest, DDS::MemberId id, DDS::TypeKind kind, DDS::UInt64 value)
946 {
947  switch (kind) {
948  case TK_UINT8:
949  return dest->set_uint8_value(id, static_cast<DDS::UInt8>(value));
950  case TK_UINT16:
951  return dest->set_uint16_value(id, static_cast<DDS::UInt16>(value));
952  case TK_UINT32:
953  return dest->set_uint32_value(id, static_cast<DDS::UInt32>(value));
954  case TK_UINT64:
955  return dest->set_uint64_value(id, value);
956  }
958 }
959 
961  DDS::Int64& value, DDS::DynamicData_ptr src, DDS::MemberId id, DDS::TypeKind kind)
962 {
964  switch (kind) {
965  case TK_INT8:
966  {
967  DDS::Int8 v;
968  rc = src->get_int8_value(v, id);
969  if (rc == DDS::RETCODE_OK) {
970  value = v;
971  }
972  }
973  break;
974  case TK_INT16:
975  {
976  DDS::Int16 v;
977  rc = src->get_int16_value(v, id);
978  if (rc == DDS::RETCODE_OK) {
979  value = v;
980  }
981  }
982  break;
983  case TK_INT32:
984  {
985  DDS::Int32 v;
986  rc = src->get_int32_value(v, id);
987  if (rc == DDS::RETCODE_OK) {
988  value = v;
989  }
990  }
991  break;
992  case TK_INT64:
993  rc = src->get_int64_value(value, id);
994  break;
995  }
996  return rc;
997 }
998 
1000  DDS::DynamicData_ptr dest, DDS::MemberId id, DDS::TypeKind kind, DDS::Int64 value)
1001 {
1002  switch (kind) {
1003  case TK_INT8:
1004  return dest->set_int8_value(id, static_cast<DDS::Int8>(value));
1005  case TK_INT16:
1006  return dest->set_int16_value(id, static_cast<DDS::Int16>(value));
1007  case TK_INT32:
1008  return dest->set_int32_value(id, static_cast<DDS::Int32>(value));
1009  case TK_INT64:
1010  return dest->set_int64_value(id, value);
1011  }
1013 }
1014 
1015 DDS::UInt32 bound_total(DDS::TypeDescriptor_var descriptor)
1016 {
1017  DDS::UInt32 total = 1;
1018  const DDS::BoundSeq& bounds = descriptor->bound();
1019  for (DDS::UInt32 i = 0; i < bounds.length(); ++i) {
1020  total *= bounds[i];
1021  }
1022  return total;
1023 }
1024 
1025 DDS::ReturnCode_t bitmask_bound(DDS::DynamicType_ptr type, DDS::TypeKind& bound_kind)
1026 {
1027  const DDS::TypeKind kind = type->get_kind();
1028  if (kind != TK_BITMASK) {
1029  if (log_level >= LogLevel::Notice) {
1030  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: bitmask_bound: "
1031  "expected bitmask, got %C\n",
1032  typekind_to_string(kind)));
1033  }
1035  }
1036 
1037  DDS::TypeDescriptor_var td;
1038  const DDS::ReturnCode_t rc = type->get_descriptor(td);
1039  if (rc != DDS::RETCODE_OK) {
1040  return rc;
1041  }
1042 
1043  const size_t bound_size = td->bound()[0];
1044  if (bound_size >= 1 && bound_size <= 8) {
1045  bound_kind = TK_UINT8;
1046  } else if (bound_size >= 9 && bound_size <= 16) {
1047  bound_kind = TK_UINT16;
1048  } else if (bound_size >= 17 && bound_size <= 32) {
1049  bound_kind = TK_UINT32;
1050  } else if (bound_size >= 33 && bound_size <= 64) {
1051  bound_kind = TK_UINT64;
1052  } else {
1053  if (log_level >= LogLevel::Notice) {
1054  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: bitmask_bound: "
1055  "Got unexpected bound size %B\n",
1056  bound_size));
1057  }
1059  }
1060  return DDS::RETCODE_OK;
1061 }
1062 
1064  DDS::UInt64& value, DDS::DynamicType_ptr type, DDS::DynamicData_ptr src, DDS::MemberId id)
1065 {
1066  DDS::TypeKind bound_kind;
1067  const DDS::ReturnCode_t rc = bitmask_bound(type, bound_kind);
1068  if (rc != DDS::RETCODE_OK) {
1069  return rc;
1070  }
1071  return get_uint_value(value, src, id, bound_kind);
1072 }
1073 
1074 DDS::ReturnCode_t enum_bound(DDS::DynamicType_ptr enum_type, DDS::TypeKind& bound_kind)
1075 {
1076  const DDS::TypeKind kind = enum_type->get_kind();
1077  if (kind != TK_ENUM) {
1078  if (log_level >= LogLevel::Notice) {
1079  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: enum_bound: "
1080  "expected enum, got %C\n",
1081  typekind_to_string(kind)));
1082  }
1084  }
1085 
1086  DDS::TypeDescriptor_var td;
1087  const DDS::ReturnCode_t rc = enum_type->get_descriptor(td);
1088  if (rc != DDS::RETCODE_OK) {
1089  return rc;
1090  }
1091 
1092  const size_t bound_size = td->bound()[0];
1093  if (bound_size >= 1 && bound_size <= 8) {
1094  bound_kind = TK_INT8;
1095  } else if (bound_size >= 9 && bound_size <= 16) {
1096  bound_kind = TK_INT16;
1097  } else if (bound_size >= 17 && bound_size <= 32) {
1098  bound_kind = TK_INT32;
1099  } else {
1100  if (log_level >= LogLevel::Notice) {
1101  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: enum_bound: "
1102  "Got unexpected bound size %B\n",
1103  bound_size));
1104  }
1106  }
1107  return DDS::RETCODE_OK;
1108 }
1109 
1111  DDS::Int32& value, DDS::DynamicType_ptr enum_type, DDS::DynamicData_ptr src, DDS::MemberId id)
1112 {
1113  DDS::TypeKind bound_kind;
1114  DDS::ReturnCode_t rc = enum_bound(enum_type, bound_kind);
1115  if (rc != DDS::RETCODE_OK) {
1116  return rc;
1117  }
1118  DDS::Int64 v = 0;
1119  rc = get_int_value(v, src, id, bound_kind);
1120  if (rc != DDS::RETCODE_OK) {
1121  return rc;
1122  }
1123  value = static_cast<DDS::Int32>(v);
1124  return rc;
1125 }
1126 
1128  DDS::String8_var& name, DDS::Int32 value, DDS::DynamicType_ptr type)
1129 {
1130  DDS::DynamicTypeMember_var dtm;
1131  DDS::ReturnCode_t rc = type->get_member(dtm, static_cast<DDS::MemberId>(value));
1132  if (rc != DDS::RETCODE_OK) {
1133  return rc;
1134  }
1135 
1136  DDS::MemberDescriptor_var md;
1137  rc = dtm->get_descriptor(md);
1138  if (rc != DDS::RETCODE_OK) {
1139  return rc;
1140  }
1141 
1142  name = md->name();
1143  return DDS::RETCODE_OK;
1144 }
1145 
1147  DDS::Int32& value, const char* name, DDS::DynamicType_ptr type)
1148 {
1149  DDS::DynamicTypeMember_var dtm;
1150  DDS::ReturnCode_t rc = type->get_member_by_name(dtm, name);
1151  if (rc != DDS::RETCODE_OK) {
1152  return rc;
1153  }
1154 
1155  DDS::MemberDescriptor_var md;
1156  rc = dtm->get_descriptor(md);
1157  if (rc != DDS::RETCODE_OK) {
1158  return rc;
1159  }
1160 
1161  value = static_cast<DDS::Int32>(md->id());
1162  return DDS::RETCODE_OK;
1163 }
1164 
1166  DDS::DynamicType_ptr enum_type, DDS::DynamicData_ptr dest, DDS::MemberId id, DDS::Int32 value)
1167 {
1168  DDS::TypeKind bound_kind;
1169  const DDS::ReturnCode_t rc = enum_bound(enum_type, bound_kind);
1170  if (rc != DDS::RETCODE_OK) {
1171  return rc;
1172  }
1173  return set_int_value(dest, id, bound_kind, value);
1174 }
1175 
1177  DDS::DynamicType_ptr type, DDS::DynamicData_ptr dest, DDS::MemberId id, const char* enumeral_name)
1178 {
1179  DDS::DynamicTypeMember_var dtm;
1180  DDS::ReturnCode_t rc = type->get_member_by_name(dtm, enumeral_name);
1181  if (rc != DDS::RETCODE_OK) {
1182  if (log_level >= LogLevel::Notice) {
1183  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: set_enum_value: "
1184  "No such enumeral named \"%C\"\n",
1185  enumeral_name));
1186  }
1187  return rc;
1188  }
1189  DDS::MemberDescriptor_var md;
1190  rc = dtm->get_descriptor(md);
1191  if (rc != DDS::RETCODE_OK) {
1192  return rc;
1193  }
1194  return set_enum_value(type, dest, id, md->id());
1195 }
1196 
1198  DDS::DynamicData_ptr dest, DDS::MemberId dest_id,
1199  DDS::DynamicData_ptr src, DDS::MemberId src_id)
1200 {
1202  if (dest == src) {
1203  return rc;
1204  }
1205 
1206  const DDS::DynamicType_var dest_type = dest->type();
1207  DDS::DynamicType_var use_dest_type;
1208  if (dest_id != MEMBER_ID_INVALID) {
1209  rc = get_member_type(use_dest_type, dest_type, dest_id);
1210  if (rc != DDS::RETCODE_OK) {
1211  return rc;
1212  }
1213  } else {
1214  use_dest_type = get_base_type(dest_type);
1215  }
1216  const DDS::TypeKind dest_tk = use_dest_type->get_kind();
1217 
1218  const DDS::DynamicType_var src_type = src->type();
1219  DDS::DynamicType_var use_src_type;
1220  if (src_id != MEMBER_ID_INVALID) {
1221  rc = get_member_type(use_src_type, src_type, src_id);
1222  if (rc != DDS::RETCODE_OK) {
1223  return rc;
1224  }
1225  } else {
1226  use_src_type = get_base_type(src_type);
1227  }
1228  const DDS::TypeKind src_tk = use_src_type->get_kind();
1229 
1230  if (DCPS::DCPS_debug_level >= 8) {
1231  const CORBA::String_var src_type_name = src_type->get_name();
1232  const CORBA::String_var dest_type_name = dest_type->get_name();
1233  ACE_DEBUG((LM_DEBUG, "(%P|%t) copy_member(DynamicData): "
1234  "type %C from %C id %u to %C id %u\n",
1235  typekind_to_string(src_tk), src_type_name.in(), src_id, dest_type_name.in(), dest_id));
1236  }
1237 
1238  if (src_tk != dest_tk) {
1239  if (log_level >= LogLevel::Warning) {
1240  ACE_ERROR((LM_WARNING, "(%P|%t) WARNING: copy_member(DynamicData): "
1241  "Can not copy member type %C id %u to type %C id %u\n",
1242  typekind_to_string(src_tk), src_id, typekind_to_string(dest_tk), dest_id));
1243  }
1244  return DDS::RETCODE_OK;
1245  }
1246 
1249  switch (src_tk) {
1250  case TK_BOOLEAN:
1251  {
1252  DDS::Boolean value;
1253  get_rc = src->get_boolean_value(value, src_id);
1254  if (get_rc == DDS::RETCODE_OK) {
1255  set_rc = dest->set_boolean_value(dest_id, value);
1256  }
1257  }
1258  break;
1259 
1260  case TK_BYTE:
1261  {
1262  DDS::Byte value;
1263  get_rc = src->get_byte_value(value, src_id);
1264  if (get_rc == DDS::RETCODE_OK) {
1265  set_rc = dest->set_byte_value(dest_id, value);
1266  }
1267  }
1268  break;
1269 
1270  case TK_INT8:
1271  case TK_INT16:
1272  case TK_INT32:
1273  case TK_INT64:
1274  {
1275  DDS::Int64 value;
1276  get_rc = get_int_value(value, src, src_id, src_tk);
1277  if (get_rc == DDS::RETCODE_OK) {
1278  set_rc = set_int_value(dest, dest_id, dest_tk, value);
1279  }
1280  }
1281  break;
1282 
1283  case TK_UINT8:
1284  case TK_UINT16:
1285  case TK_UINT32:
1286  case TK_UINT64:
1287  {
1288  DDS::UInt64 value;
1289  get_rc = get_uint_value(value, src, src_id, src_tk);
1290  if (get_rc == DDS::RETCODE_OK) {
1291  set_rc = set_uint_value(dest, dest_id, dest_tk, value);
1292  }
1293  }
1294  break;
1295 
1296  case TK_FLOAT32:
1297  {
1299  get_rc = src->get_float32_value(value, src_id);
1300  if (get_rc == DDS::RETCODE_OK) {
1301  set_rc = dest->set_float32_value(dest_id, value);
1302  }
1303  }
1304  break;
1305 
1306  case TK_FLOAT64:
1307  {
1309  get_rc = src->get_float64_value(value, src_id);
1310  if (get_rc == DDS::RETCODE_OK) {
1311  set_rc = dest->set_float64_value(dest_id, value);
1312  }
1313  }
1314  break;
1315 
1316  case TK_FLOAT128:
1317  {
1319  get_rc = src->get_float128_value(value, src_id);
1320  if (get_rc == DDS::RETCODE_OK) {
1321  set_rc = dest->set_float128_value(dest_id, value);
1322  }
1323  }
1324  break;
1325 
1326  case TK_CHAR8:
1327  {
1328  DDS::Char8 value;
1329  get_rc = src->get_char8_value(value, src_id);
1330  if (get_rc == DDS::RETCODE_OK) {
1331  set_rc = dest->set_char8_value(dest_id, value);
1332  }
1333  }
1334  break;
1335 
1336  case TK_CHAR16:
1337  {
1339  get_rc = src->get_char16_value(value, src_id);
1340  if (get_rc == DDS::RETCODE_OK) {
1341  set_rc = dest->set_char16_value(dest_id, value);
1342  }
1343  }
1344  break;
1345 
1346  case TK_STRING8:
1347  {
1349  get_rc = src->get_string_value(value, src_id);
1350  if (get_rc == DDS::RETCODE_OK) {
1351  set_rc = dest->set_string_value(dest_id, value);
1352  }
1353  }
1354  break;
1355 
1356  case TK_STRING16:
1357  {
1359  get_rc = src->get_wstring_value(value, src_id);
1360  if (get_rc == DDS::RETCODE_OK) {
1361  set_rc = dest->set_wstring_value(dest_id, value);
1362  }
1363  }
1364  break;
1365 
1366  case TK_ENUM:
1367  {
1368  DDS::Int32 value;
1369  get_rc = get_enum_value(value, use_src_type, src, src_id);
1370  if (get_rc == DDS::RETCODE_OK) {
1371  set_rc = set_enum_value(use_dest_type, dest, dest_id, value);
1372  }
1373  }
1374  break;
1375 
1376  case TK_STRUCTURE:
1377  case TK_UNION:
1378  case TK_SEQUENCE:
1379  case TK_ARRAY:
1380  {
1381  DDS::DynamicData_var subsrc;
1382  get_rc = src->get_complex_value(subsrc, src_id);
1383  if (get_rc == DDS::RETCODE_OK) {
1384  DDS::DynamicData_var subdest;
1385  get_rc = dest->get_complex_value(subdest, dest_id);
1386  if (get_rc == DDS::RETCODE_OK) {
1387  set_rc = copy(subdest, subsrc);
1388  }
1389  }
1390  }
1391  break;
1392 
1393  case TK_MAP:
1394  case TK_BITSET:
1395  case TK_ALIAS:
1396  case TK_ANNOTATION:
1397  default:
1398  if (log_level >= LogLevel::Warning) {
1399  ACE_ERROR((LM_WARNING, "(%P|%t) WARNING: copy(DynamicData): "
1400  "member has unexpected TypeKind %C\n", typekind_to_string(src_tk)));
1401  }
1402  get_rc = DDS::RETCODE_UNSUPPORTED;
1403  }
1404 
1405  if (get_rc == DDS::RETCODE_NO_DATA) {
1406  if (DCPS::DCPS_debug_level >= 8) {
1407  const CORBA::String_var src_type_name = src_type->get_name();
1408  const CORBA::String_var dest_type_name = dest_type->get_name();
1409  ACE_DEBUG((LM_DEBUG, "(%P|%t) copy(DynamicData): "
1410  "Did not copy member type %C from %C id %u to %C id %u: get returned %C\n",
1411  typekind_to_string(src_tk), src_type_name.in(), src_id, dest_type_name.in(), dest_id,
1412  retcode_to_string(get_rc)));
1413  }
1414  return DDS::RETCODE_OK;
1415  }
1416 
1417  if (get_rc != DDS::RETCODE_OK || set_rc != DDS::RETCODE_OK) {
1418  if (log_level >= LogLevel::Warning) {
1419  const CORBA::String_var src_type_name = src_type->get_name();
1420  const CORBA::String_var dest_type_name = dest_type->get_name();
1421  const DDS::TypeKind tk = src_type->get_kind();
1422  if (tk == TK_STRUCTURE || tk == TK_UNION) {
1423  CORBA::String_var src_member_name;
1424  DDS::MemberDescriptor_var src_md;
1425  DDS::ReturnCode_t rc = src->get_descriptor(src_md, src_id);
1426  if (rc == DDS::RETCODE_OK) {
1427  src_member_name = src_md->name();
1428  }
1429  CORBA::String_var dest_member_name;
1430  DDS::MemberDescriptor_var dest_md;
1431  rc = dest->get_descriptor(dest_md, dest_id);
1432  if (rc == DDS::RETCODE_OK) {
1433  dest_member_name = dest_md->name();
1434  }
1435  ACE_ERROR((LM_WARNING, "(%P|%t) WARNING: copy(DynamicData): "
1436  "Could not copy member type %C from %C.%C id %u to %C.%C id %u: get: %C set: %C\n",
1437  typekind_to_string(src_tk),
1438  src_type_name.in(), src_member_name.in() ? src_member_name.in() : "?", src_id,
1439  dest_type_name.in(), dest_member_name.in() ? dest_member_name.in() : "?", dest_id,
1440  retcode_to_string(get_rc), retcode_to_string(set_rc)));
1441  } else {
1442  ACE_ERROR((LM_WARNING, "(%P|%t) WARNING: copy(DynamicData): "
1443  "Could not copy member type %C from %C id %u to %C id %u: get: %C set: %C\n",
1444  typekind_to_string(src_tk), src_type_name.in(), src_id, dest_type_name.in(), dest_id,
1445  retcode_to_string(get_rc), retcode_to_string(set_rc)));
1446  }
1447  }
1448  rc = get_rc != DDS::RETCODE_OK ? get_rc : set_rc;
1449  }
1450 
1451  return rc;
1452 }
1453 
1454 DDS::ReturnCode_t copy(DDS::DynamicData_ptr dest, DDS::DynamicData_ptr src)
1455 {
1456  if (dest == src) {
1457  return DDS::RETCODE_OK;
1458  }
1459 
1460  const DDS::DynamicType_var dest_type = dest->type();
1461  const DDS::DynamicType_var actual_dest_type = get_base_type(dest_type);
1462  const DDS::TypeKind dest_tk = actual_dest_type->get_kind();
1463 
1464  const DDS::DynamicType_var src_type = src->type();
1465  const DDS::DynamicType_var actual_src_type = get_base_type(src_type);
1466  const DDS::TypeKind src_tk = actual_src_type->get_kind();
1467 
1468  if (src_tk != dest_tk) {
1469  if (log_level >= LogLevel::Notice) {
1470  ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: copy(DynamicData): "
1471  "Can not copy type %C to type %C\n",
1472  typekind_to_string(src_tk), typekind_to_string(dest_tk)));
1473  }
1474  return DDS::RETCODE_OK;
1475  }
1476 
1478  switch (src_tk) {
1479  case TK_BOOLEAN:
1480  case TK_BYTE:
1481  case TK_INT8:
1482  case TK_INT16:
1483  case TK_INT32:
1484  case TK_INT64:
1485  case TK_UINT8:
1486  case TK_UINT16:
1487  case TK_UINT32:
1488  case TK_UINT64:
1489  case TK_FLOAT32:
1490  case TK_FLOAT64:
1491  case TK_FLOAT128:
1492  case TK_CHAR8:
1493  case TK_CHAR16:
1494  case TK_STRING8:
1495  case TK_STRING16:
1496  case TK_ENUM:
1497  return copy_member(dest, MEMBER_ID_INVALID, src, MEMBER_ID_INVALID);
1498 
1499  case TK_UNION:
1500  {
1501  if (src->get_item_count() == 2) {
1502  const DDS::MemberId id = src->get_member_id_at_index(1);
1503  rc = copy_member(dest, id, src, id);
1504  if (rc != DDS::RETCODE_OK) {
1505  if (log_level >= LogLevel::Warning) {
1506  ACE_ERROR((LM_WARNING, "(%P|%t) WARNING: copy(DynamicData): "
1507  "Couldn't set union branch: %C\n", retcode_to_string(rc)));
1508  }
1509  return rc;
1510  }
1511  }
1512  rc = copy_member(dest, DISCRIMINATOR_ID, src, DISCRIMINATOR_ID);
1513  if (rc != DDS::RETCODE_OK && log_level >= LogLevel::Warning) {
1514  ACE_ERROR((LM_WARNING, "(%P|%t) WARNING: copy(DynamicData): "
1515  "Couldn't set union disciminator: %C\n", retcode_to_string(rc)));
1516  }
1517  return rc;
1518  }
1519 
1520  case TK_STRUCTURE:
1521  {
1522  DDS::DynamicTypeMembersById_var src_members_var;
1523  rc = actual_src_type->get_all_members(src_members_var);
1524  if (rc != DDS::RETCODE_OK) {
1525  return rc;
1526  }
1527  DynamicTypeMembersByIdImpl* src_members =
1528  dynamic_cast<DynamicTypeMembersByIdImpl*>(src_members_var.in());
1529 
1530  DDS::DynamicTypeMembersById_var dest_members_var;
1531  rc = actual_dest_type->get_all_members(dest_members_var);
1532  if (rc != DDS::RETCODE_OK) {
1533  return rc;
1534  }
1535  DynamicTypeMembersByIdImpl* dest_members =
1536  dynamic_cast<DynamicTypeMembersByIdImpl*>(dest_members_var.in());
1537 
1538  for (DynamicTypeMembersByIdImpl::const_iterator src_it = src_members->begin();
1539  src_it != src_members->end(); ++src_it) {
1540  const DDS::MemberId id = src_it->first;
1541  const DynamicTypeMembersByIdImpl::const_iterator dest_it = dest_members->find(id);
1542  if (dest_it == dest_members->end()) {
1543  continue;
1544  }
1545 
1546  const DDS::ReturnCode_t this_rc = copy_member(dest, id, src, id);
1547  if (this_rc != DDS::RETCODE_OK && rc == DDS::RETCODE_OK) {
1548  rc = this_rc;
1549  }
1550  }
1551  }
1552  break;
1553 
1554  case TK_SEQUENCE:
1555  case TK_ARRAY:
1556  {
1557  const DDS::UInt32 count = src->get_item_count();
1558  for (DDS::UInt32 i = 0; i < count; ++i) {
1559  const DDS::ReturnCode_t this_rc = copy_member(
1560  dest, dest->get_member_id_at_index(i),
1561  src, src->get_member_id_at_index(i));
1562  if (this_rc != DDS::RETCODE_OK && rc == DDS::RETCODE_OK) {
1563  rc = this_rc;
1564  }
1565  }
1566  }
1567  break;
1568 
1569  case TK_MAP:
1570  case TK_BITSET:
1571  case TK_ALIAS:
1572  case TK_ANNOTATION:
1573  default:
1574  if (log_level >= LogLevel::Warning) {
1575  ACE_ERROR((LM_WARNING, "(%P|%t) WARNING: copy(DynamicData): "
1576  "member has unexpected TypeKind %C\n", typekind_to_string(src_tk)));
1577  }
1579  }
1580 
1581  return rc;
1582 }
1583 
1584 } // namespace XTypes
1585 } // namespace OpenDDS
1587 
1588 #endif // OPENDDS_SAFETY_PROFILE
DCPS::Extensibility dds_to_opendds_ext(DDS::ExtensibilityKind ext)
#define ACE_DEBUG(X)
const TypeKind TK_SEQUENCE
Definition: TypeObject.h:248
bool is_key(DDS::DynamicType_ptr type, const char *field)
DDS::ReturnCode_t key_less_than(bool &result, DDS::DynamicData_ptr a, DDS::DynamicData_ptr b)
#define ACE_ERROR(X)
ACE_CDR::ULong MemberId
Definition: TypeObject.h:910
const LogLevel::Value value
Definition: debug.cpp:61
const TypeKind TK_INT32
Definition: TypeObject.h:217
DDS::ReturnCode_t get_enumerator_value(DDS::Int32 &value, const char *name, DDS::DynamicType_ptr type)
std::string String
sequence< unsigned long > BoundSeq
const TypeKind TK_STRING16
Definition: TypeObject.h:232
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)
DDS::ReturnCode_t set_int_value(DDS::DynamicData_ptr dest, DDS::MemberId id, DDS::TypeKind kind, DDS::Int64 value)
const TypeKind TK_BYTE
Definition: TypeObject.h:215
DDS::ReturnCode_t resolve_string_path(DDS::DynamicType_ptr type, const DCPS::String &path)
const TypeKind TK_UNION
Definition: TypeObject.h:244
const TypeKind TK_INT16
Definition: TypeObject.h:216
DDS::DynamicType_var get_base_type(DDS::DynamicType_ptr type)
const ACE_CDR::ULong DISCRIMINATOR_ID
Implementation specific sentinel for a union discriminator used in DynamicData.
Definition: TypeObject.h:913
const TypeKind TK_UINT16
Definition: TypeObject.h:219
#define OPENDDS_ASSERT(C)
Definition: Definitions.h:72
DDS::ReturnCode_t get_keys(DDS::DynamicType_ptr type, MemberPathVec &paths)
octet Byte
Definition: DdsDcpsCore.idl:31
DDS::ReturnCode_t copy_member(DDS::DynamicData_ptr dest, DDS::MemberId dest_id, DDS::DynamicData_ptr src, DDS::MemberId src_id)
const TypeKind TK_INT8
Definition: TypeObject.h:225
bool is_sequence_like(TypeKind tk)
ACE_CDR::Octet TypeKind
Definition: TypeObject.h:210
DDS::ReturnCode_t compare_members(int &result, DDS::DynamicData_ptr a, DDS::DynamicData_ptr b, DDS::MemberId id)
bool get_index(DDS::UInt32 &index)
LM_DEBUG
const_iterator find(MemberId key) const
const TypeKind TK_BOOLEAN
Definition: TypeObject.h:214
const char * typekind_to_string(TypeKind tk)
DDS::ReturnCode_t get_enum_value(DDS::Int32 &value, DDS::DynamicType_ptr enum_type, DDS::DynamicData_ptr src, DDS::MemberId id)
double Float64
Definition: DdsDcpsCore.idl:42
const TypeKind TK_BITMASK
Definition: TypeObject.h:239
MemberPath & id(DDS::MemberId id)
Definition: XTypes/Utils.h:101
LM_NOTICE
DDS::ReturnCode_t get_bitmask_value(DDS::UInt64 &value, DDS::DynamicType_ptr type, DDS::DynamicData_ptr src, DDS::MemberId id)
char Char8
Definition: DdsDcpsCore.idl:44
DDS::UInt32 bound_total(DDS::TypeDescriptor_var descriptor)
DDS::ReturnCode_t get_values(DDS::DynamicType_ptr type, MemberPathVec &paths, Filter filter)
const TypeKind TK_CHAR8
Definition: TypeObject.h:227
const ACE_CDR::ULong MEMBER_ID_INVALID
Definition: TypeObject.h:911
const ReturnCode_t RETCODE_ILLEGAL_OPERATION
LM_WARNING
const TypeKind TK_STRUCTURE
Definition: TypeObject.h:243
const char *const name
Definition: debug.cpp:60
DDS::ReturnCode_t less_than(bool &result, DDS::DynamicData_ptr a, DDS::DynamicData_ptr b, Filter filter)
const TypeKind TK_FLOAT32
Definition: TypeObject.h:222
const TypeKind TK_STRING8
Definition: TypeObject.h:231
DDS::ReturnCode_t get_member_from_data(DDS::DynamicData_ptr data, DDS::DynamicData_var &container, DDS::MemberId &member_id)
ExtensibilityKind
const ReturnCode_t RETCODE_NO_DATA
OpenDDS_Dcps_Export unsigned int DCPS_debug_level
Definition: debug.cpp:30
const TypeKind TK_UINT64
Definition: TypeObject.h:221
OpenDDS_Dcps_Export LogLevel log_level
DDS::ReturnCode_t enum_bound(DDS::DynamicType_ptr enum_type, DDS::TypeKind &bound_kind)
bool is_scalar(TypeKind tk)
const TypeKind TK_INT64
Definition: TypeObject.h:218
const char * retcode_to_string(DDS::ReturnCode_t value)
Definition: DCPS_Utils.cpp:29
const TypeKind TK_UINT32
Definition: TypeObject.h:220
ACE_CDR::Char Char
const TypeKind TK_ALIAS
Definition: TypeObject.h:235
DDS::ReturnCode_t copy(DDS::DynamicData_ptr dest, DDS::DynamicData_ptr src)
#define OPENDDS_END_VERSIONED_NAMESPACE_DECL
const TypeKind TK_ANNOTATION
Definition: TypeObject.h:242
DDS::ReturnCode_t get_enumerator_name(DDS::String8_var &name, DDS::Int32 value, DDS::DynamicType_ptr type)
const TypeKind TK_ENUM
Definition: TypeObject.h:238
const ReturnCode_t RETCODE_OK
DDS::ReturnCode_t get_int_value(DDS::Int64 &value, DDS::DynamicData_ptr src, DDS::MemberId id, DDS::TypeKind kind)
const ReturnCode_t RETCODE_UNSUPPORTED
wchar Char16
Definition: DdsDcpsCore.idl:45
DDS::ReturnCode_t set_enum_value(DDS::DynamicType_ptr enum_type, DDS::DynamicData_ptr dest, DDS::MemberId id, DDS::Int32 value)
ACE_CDR::WChar WChar
const TypeKind TK_ARRAY
Definition: TypeObject.h:249
const TypeKind TK_UINT8
Definition: TypeObject.h:226
DDS::ReturnCode_t get_uint_value(DDS::UInt64 &value, DDS::DynamicData_ptr src, DDS::MemberId id, DDS::TypeKind kind)
const character_type * in(void) const
DDS::ReturnCode_t max_extensibility(DDS::DynamicType_ptr type, DCPS::Extensibility &ext)
DDS::ReturnCode_t set_uint_value(DDS::DynamicData_ptr dest, DDS::MemberId id, DDS::TypeKind kind, DDS::UInt64 value)
const TypeKind TK_MAP
Definition: TypeObject.h:250
float Float32
Definition: DdsDcpsCore.idl:41
DDS::ReturnCode_t bitmask_bound(DDS::DynamicType_ptr type, DDS::TypeKind &bound_kind)
The Internal API and Implementation of OpenDDS.
Definition: AddressCache.h:28
DDS::ReturnCode_t key_count(DDS::DynamicType_ptr type, size_t &count)
const TypeKind TK_CHAR16
Definition: TypeObject.h:228
const TypeKind TK_FLOAT64
Definition: TypeObject.h:223
const TypeKind TK_BITSET
Definition: TypeObject.h:245
DDS::ReturnCode_t get_member_from_type(DDS::DynamicType_ptr type, DDS::DynamicTypeMember_var &member)
extensibility(MUTABLE) struct TypeLookup_getTypes_In
Definition: TypeLookup.idl:29
bool convertToInteger(const String &s, T &value)
long double Float128
Definition: DdsDcpsCore.idl:43
const ReturnCode_t RETCODE_BAD_PARAMETER