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>
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>
15 : # include <dds/DCPS/SafetyProfileStreams.h>
16 :
17 : # include <algorithm>
18 :
19 : OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL
20 : namespace OpenDDS {
21 : namespace XTypes {
22 :
23 : using DCPS::retcode_to_string;
24 : using DCPS::LogLevel;
25 : using DCPS::log_level;
26 :
27 62 : DDS::ReturnCode_t extensibility(DDS::DynamicType_ptr type, DCPS::Extensibility& ext)
28 : {
29 62 : DDS::DynamicType_var base_type = get_base_type(type);
30 62 : if (!base_type) {
31 0 : return DDS::RETCODE_BAD_PARAMETER;
32 : }
33 62 : switch (base_type->get_kind()) {
34 34 : case TK_STRUCTURE:
35 : case TK_UNION:
36 : {
37 34 : DDS::TypeDescriptor_var td;
38 34 : const DDS::ReturnCode_t rc = type->get_descriptor(td);
39 34 : if (rc != DDS::RETCODE_OK) {
40 0 : return rc;
41 : }
42 34 : ext = dds_to_opendds_ext(td->extensibility_kind());
43 34 : }
44 34 : break;
45 28 : default:
46 28 : ext = DCPS::FINAL;
47 : }
48 62 : return DDS::RETCODE_OK;
49 62 : }
50 :
51 53 : DDS::ReturnCode_t max_extensibility(DDS::DynamicType_ptr type, DCPS::Extensibility& ext)
52 : {
53 53 : DDS::ReturnCode_t rc = extensibility(type, ext);
54 53 : if (rc != DDS::RETCODE_OK) {
55 0 : return rc;
56 : }
57 :
58 53 : DDS::DynamicType_var base_type = get_base_type(type);
59 53 : const TypeKind tk = base_type->get_kind();
60 53 : if (tk != TK_STRUCTURE && tk != TK_UNION) {
61 28 : return DDS::RETCODE_OK;
62 : }
63 :
64 25 : DDS::DynamicTypeMembersById_var members;
65 25 : rc = base_type->get_all_members(members);
66 25 : if (rc != DDS::RETCODE_OK) {
67 0 : return rc;
68 : }
69 :
70 : DynamicTypeMembersByIdImpl* const members_impl =
71 25 : dynamic_cast<DynamicTypeMembersByIdImpl*>(members.in());
72 25 : if (!members_impl) {
73 0 : return DDS::RETCODE_BAD_PARAMETER;
74 : }
75 :
76 25 : for (DynamicTypeMembersByIdImpl::const_iterator it = members_impl->begin();
77 69 : it != members_impl->end(); ++it) {
78 44 : DDS::MemberDescriptor_var md;
79 44 : rc = it->second->get_descriptor(md);
80 44 : if (rc != DDS::RETCODE_OK) {
81 0 : return rc;
82 : }
83 :
84 44 : DDS::DynamicType_ptr member_type = md->type();
85 44 : if (!member_type) {
86 0 : return DDS::RETCODE_BAD_PARAMETER;
87 : }
88 : DCPS::Extensibility member_ext;
89 44 : DDS::ReturnCode_t rc = max_extensibility(member_type, member_ext);
90 44 : if (rc != DDS::RETCODE_OK) {
91 0 : return rc;
92 : }
93 44 : ext = std::max(member_ext, ext);
94 44 : }
95 :
96 25 : return DDS::RETCODE_OK;
97 53 : }
98 :
99 34 : DCPS::Extensibility dds_to_opendds_ext(DDS::ExtensibilityKind ext)
100 : {
101 34 : switch (ext) {
102 17 : case DDS::FINAL:
103 17 : return DCPS::FINAL;
104 11 : case DDS::APPENDABLE:
105 11 : return DCPS::APPENDABLE;
106 6 : case DDS::MUTABLE:
107 6 : return DCPS::MUTABLE;
108 : }
109 0 : OPENDDS_ASSERT(false);
110 : return DCPS::FINAL;
111 : }
112 :
113 61 : bool MemberPathParser::consume(size_t by)
114 : {
115 61 : if (by > left) {
116 0 : if (log_level >= LogLevel::Warning) {
117 0 : 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 0 : error = true;
121 0 : return false;
122 : }
123 61 : pos += by;
124 61 : left -= by;
125 61 : path += by;
126 61 : return true;
127 : }
128 :
129 49 : bool MemberPathParser::get_next_subpath()
130 : {
131 49 : if (!path) {
132 1 : if (log_level >= LogLevel::Notice) {
133 0 : ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: MemberPathParser::get_next_subpath: "
134 : "empty or null path\n"));
135 : }
136 1 : error = true;
137 1 : return false;
138 : }
139 :
140 : // See if we're in a nested member or subscript and move past the '.' or '[' if we are.
141 48 : in_subscript = left > 0 ? path[0] == '[' : false;
142 48 : const bool nested_member = left > 0 ? path[0] == '.' : false;
143 48 : if (nested_member && pos == 0) {
144 1 : if (log_level >= LogLevel::Notice) {
145 0 : ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: MemberPathParser::get_next_subpath: "
146 : "at pos 0 found unexpected '.'\n"));
147 : }
148 1 : error = true;
149 1 : return false;
150 : }
151 47 : if (nested_member || in_subscript) {
152 29 : consume(1);
153 : }
154 :
155 47 : size_t i = 0; // Char count to consume
156 47 : size_t got = 0; // Char count to use for the result
157 47 : char c = '\0';
158 47 : bool scan = true;
159 164 : for (; i < left && scan; ++i) {
160 121 : c = path[i];
161 121 : switch (c) {
162 19 : case '.':
163 : case '[':
164 19 : if (in_subscript) {
165 4 : if (log_level >= LogLevel::Notice) {
166 0 : 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 4 : error = true;
170 4 : return false;
171 : }
172 15 : --i; // Don't consume, leave for next iteration
173 : // fallthrough
174 31 : case ']':
175 31 : scan = false;
176 31 : break;
177 :
178 86 : default:
179 86 : ++got;
180 : }
181 : }
182 :
183 43 : if (in_subscript && c != ']') {
184 0 : if (log_level >= LogLevel::Notice) {
185 0 : 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 0 : error = true;
189 0 : return false;
190 : }
191 :
192 43 : if (got == 0) {
193 11 : if (in_subscript || nested_member) {
194 3 : if (log_level >= LogLevel::Notice) {
195 0 : const char* const expected = in_subscript ? "index or key" : "member name";
196 0 : if (c) {
197 0 : 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 0 : 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 3 : error = true;
205 : }
206 11 : return false;
207 : }
208 :
209 32 : subpath.assign(path, got);
210 32 : return consume(i);
211 : }
212 :
213 3 : bool MemberPathParser::get_index(DDS::UInt32& index)
214 : {
215 6 : if (!in_subscript || subpath.empty() ||
216 3 : subpath.find_first_not_of("0123456789") != DCPS::String::npos) {
217 1 : if (log_level >= LogLevel::Notice) {
218 0 : 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 1 : return false;
223 : }
224 2 : return DCPS::convertToInteger(subpath, index);
225 : }
226 :
227 0 : DDS::ReturnCode_t MemberPath::resolve_string_path(DDS::DynamicType_ptr type, const DCPS::String& path)
228 : {
229 0 : DDS::DynamicType_var current_type = get_base_type(type);
230 0 : if (!current_type) {
231 0 : return DDS::RETCODE_BAD_PARAMETER;
232 : }
233 :
234 0 : MemberPathParser parser(path);
235 0 : while (parser.get_next_subpath()) {
236 0 : if (parser.in_subscript) {
237 0 : if (log_level >= LogLevel::Notice) {
238 0 : 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 : }
242 0 : return DDS::RETCODE_UNSUPPORTED;
243 : }
244 0 : DDS::DynamicTypeMember_var dtm;
245 0 : DDS::ReturnCode_t rc = current_type->get_member_by_name(dtm, parser.subpath.c_str());
246 0 : if (rc != DDS::RETCODE_OK) {
247 0 : return rc;
248 : }
249 0 : id(dtm->get_id());
250 :
251 0 : DDS::MemberDescriptor_var md;
252 0 : rc = dtm->get_descriptor(md);
253 0 : if (rc != DDS::RETCODE_OK) {
254 0 : return rc;
255 : }
256 0 : DDS::DynamicType_var next = get_base_type(md->type());
257 0 : if (!next) {
258 0 : return DDS::RETCODE_BAD_PARAMETER;
259 : }
260 0 : current_type = next;
261 0 : }
262 :
263 0 : if (log_level >= LogLevel::Notice) {
264 0 : ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: MemberPath::resolve_string_path: "
265 : "parser failed to parse \"%C\"\n", path.c_str()));
266 0 : return DDS::RETCODE_OK;
267 : }
268 :
269 0 : return DDS::RETCODE_BAD_PARAMETER;
270 0 : }
271 :
272 3 : DDS::ReturnCode_t MemberPath::get_member_from_type(
273 : DDS::DynamicType_ptr type, DDS::DynamicTypeMember_var& member)
274 : {
275 3 : member = 0;
276 3 : if (ids.empty()) {
277 0 : return DDS::RETCODE_ILLEGAL_OPERATION;
278 : }
279 :
280 3 : DDS::DynamicType_var base_type = get_base_type(type);
281 3 : if (!base_type) {
282 0 : return DDS::RETCODE_BAD_PARAMETER;
283 : }
284 :
285 3 : MemberIdVec::iterator it = ids.begin();
286 3 : DDS::DynamicType_var current_type = DDS::DynamicType::_duplicate(type);
287 3 : DDS::DynamicTypeMember_var current_member;
288 : while (true) {
289 5 : DDS::ReturnCode_t rc = current_type->get_member(current_member, *it);
290 5 : if (rc != DDS::RETCODE_OK) {
291 0 : return rc;
292 : }
293 :
294 5 : if (++it == ids.end()) {
295 3 : break;
296 : }
297 :
298 2 : DDS::MemberDescriptor_var md;
299 2 : rc = current_member->get_descriptor(md);
300 2 : if (rc != DDS::RETCODE_OK) {
301 0 : return rc;
302 : }
303 2 : DDS::DynamicType_var next = get_base_type(md->type());
304 2 : if (!next) {
305 0 : return DDS::RETCODE_BAD_PARAMETER;
306 : }
307 2 : current_type = next;
308 4 : }
309 3 : member = current_member;
310 :
311 3 : return DDS::RETCODE_OK;
312 3 : }
313 :
314 1563 : DDS::ReturnCode_t MemberPath::get_member_from_data(
315 : DDS::DynamicData_ptr data, DDS::DynamicData_var& container, DDS::MemberId& member_id)
316 : {
317 1563 : container = 0;
318 1563 : if (ids.empty()) {
319 0 : return DDS::RETCODE_ILLEGAL_OPERATION;
320 : }
321 :
322 1563 : MemberIdVec::iterator it = ids.begin();
323 1563 : DDS::DynamicData_var current_container = DDS::DynamicData::_duplicate(data);
324 : while (true) {
325 1673 : const DDS::MemberId current_id = *it;
326 1673 : if (++it == ids.end()) {
327 1563 : member_id = current_id;
328 1563 : break;
329 : }
330 :
331 110 : DDS::DynamicData_var next;
332 110 : DDS::ReturnCode_t rc = current_container->get_complex_value(next, current_id);
333 110 : if (rc != DDS::RETCODE_OK) {
334 0 : return rc;
335 : }
336 110 : current_container = next;
337 220 : }
338 1563 : container = current_container;
339 :
340 1563 : return DDS::RETCODE_OK;
341 1563 : }
342 :
343 : namespace {
344 1151 : DDS::ReturnCode_t get_values_i(DDS::DynamicType_ptr type, MemberPathVec& paths, Filter filter,
345 : const MemberPath& base_path)
346 : {
347 1151 : DDS::DynamicType_var base_type = get_base_type(type);
348 1151 : if (!base_type) {
349 0 : return DDS::RETCODE_BAD_PARAMETER;
350 : }
351 1151 : const TypeKind kind = base_type->get_kind();
352 1151 : switch (kind) {
353 111 : case TK_STRUCTURE:
354 : {
355 111 : DDS::DynamicTypeMembersById_var members;
356 111 : DDS::ReturnCode_t rc = type->get_all_members(members);
357 111 : if (rc != DDS::RETCODE_OK) {
358 0 : return rc;
359 : }
360 :
361 : DynamicTypeMembersByIdImpl* const members_i =
362 111 : dynamic_cast<DynamicTypeMembersByIdImpl*>(members.in());
363 111 : if (!members_i) {
364 0 : return DDS::RETCODE_BAD_PARAMETER;
365 : }
366 :
367 111 : bool include_all = filter == Filter_All;
368 111 : 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 7 : include_all = true;
372 7 : for (DynamicTypeMembersByIdImpl::const_iterator it = members_i->begin();
373 13 : it != members_i->end(); ++it) {
374 10 : DDS::MemberDescriptor_var md;
375 10 : DDS::ReturnCode_t rc = it->second->get_descriptor(md);
376 10 : if (rc != DDS::RETCODE_OK) {
377 0 : return rc;
378 : }
379 10 : if (md->is_key()) {
380 4 : include_all = false;
381 4 : break;
382 : }
383 10 : }
384 : }
385 :
386 111 : for (DynamicTypeMembersByIdImpl::const_iterator it = members_i->begin();
387 1213 : it != members_i->end(); ++it) {
388 1102 : DDS::MemberDescriptor_var md;
389 1102 : DDS::ReturnCode_t rc = it->second->get_descriptor(md);
390 1102 : if (rc != DDS::RETCODE_OK) {
391 0 : return rc;
392 : }
393 1102 : if ((filter == Filter_NonKeys) != (include_all || md->is_key())) {
394 1091 : const MemberPath path(base_path, md->id());
395 1091 : rc = get_values_i(md->type(), paths,
396 : filter == Filter_Keys ? Filter_NestedKeys : filter, path);
397 1091 : if (rc != DDS::RETCODE_OK) {
398 0 : return rc;
399 : }
400 1091 : }
401 1102 : }
402 111 : }
403 111 : break;
404 :
405 52 : case TK_UNION:
406 : {
407 52 : DDS::DynamicTypeMember_var disc;
408 52 : const MemberId id = DISCRIMINATOR_ID;
409 52 : const MemberPath this_path(base_path, id);
410 52 : bool include = false;
411 52 : switch (filter) {
412 2 : case Filter_Keys:
413 : case Filter_NonKeys:
414 : {
415 2 : DDS::ReturnCode_t rc = type->get_member(disc, id);
416 2 : if (rc != DDS::RETCODE_OK) {
417 0 : return rc;
418 : }
419 2 : DDS::MemberDescriptor_var md;
420 2 : rc = disc->get_descriptor(md);
421 2 : if (rc != DDS::RETCODE_OK) {
422 0 : return rc;
423 : }
424 2 : include = (filter == Filter_NonKeys) != md->is_key();
425 2 : }
426 2 : break;
427 50 : 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 50 : include = true;
433 50 : break;
434 : }
435 52 : if (include) {
436 51 : paths.push_back(this_path);
437 : }
438 52 : }
439 52 : break;
440 :
441 988 : default:
442 988 : if (base_path.level() == 0) {
443 0 : if (log_level >= LogLevel::Notice) {
444 0 : 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 : }
448 0 : return DDS::RETCODE_BAD_PARAMETER;
449 : }
450 988 : paths.push_back(base_path);
451 988 : break;
452 : }
453 :
454 1151 : return DDS::RETCODE_OK;
455 1151 : }
456 : }
457 :
458 60 : DDS::ReturnCode_t get_values(DDS::DynamicType_ptr type, MemberPathVec& paths, Filter filter)
459 : {
460 60 : return get_values_i(type, paths, filter, MemberPath());
461 : }
462 :
463 14 : DDS::ReturnCode_t get_keys(DDS::DynamicType_ptr type, MemberPathVec& paths)
464 : {
465 14 : return get_values(type, paths, Filter_Keys);
466 : }
467 :
468 0 : DDS::ReturnCode_t key_count(DDS::DynamicType_ptr type, size_t& count)
469 : {
470 0 : MemberPathVec paths;
471 0 : const DDS::ReturnCode_t rc = get_keys(type, paths);
472 0 : if (rc == DDS::RETCODE_OK) {
473 0 : count = paths.size();
474 : }
475 0 : return rc;
476 0 : }
477 :
478 0 : bool is_key(DDS::DynamicType_ptr type, const char* field)
479 : {
480 0 : MemberPathVec paths;
481 0 : if (get_keys(type, paths) != DDS::RETCODE_OK) {
482 0 : return false;
483 : }
484 0 : for (size_t i = 0; i < paths.size(); ++i) {
485 0 : DDS::DynamicTypeMember_var m;
486 0 : if (paths[i].get_member_from_type(type, m) != DDS::RETCODE_OK) {
487 0 : return false;
488 : }
489 0 : const CORBA::String_var name = m->get_name();
490 0 : if (0 == std::strcmp(name, field)) {
491 0 : return true;
492 : }
493 0 : }
494 0 : return false;
495 0 : }
496 :
497 : namespace {
498 : template <typename T>
499 722 : void cmp(int& result, T a, T b)
500 : {
501 722 : if (a < b) {
502 20 : result = -1;
503 702 : } else if (a > b) {
504 0 : result = 1;
505 : } else {
506 702 : result = 0;
507 : }
508 722 : }
509 :
510 834 : 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 834 : DDS::DynamicType_var a_type;
515 834 : DDS::ReturnCode_t rc = get_member_type(a_type, a_data, a_id);
516 834 : if (rc != DDS::RETCODE_OK) {
517 0 : return rc;
518 : }
519 834 : const DDS::TypeKind tk = a_type->get_kind();
520 :
521 834 : DDS::DynamicType_var b_type;
522 834 : rc = get_member_type(b_type, b_data, b_id);
523 834 : if (rc != DDS::RETCODE_OK) {
524 0 : return rc;
525 : }
526 834 : const DDS::TypeKind b_tk = b_type->get_kind();
527 :
528 834 : if (tk != b_tk) {
529 0 : if (log_level >= LogLevel::Notice) {
530 0 : 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 : }
535 0 : return DDS::RETCODE_BAD_PARAMETER;
536 : }
537 :
538 834 : DDS::ReturnCode_t a_rc = DDS::RETCODE_OK;
539 834 : DDS::ReturnCode_t b_rc = DDS::RETCODE_OK;
540 :
541 834 : switch (tk) {
542 45 : case TK_BOOLEAN:
543 : {
544 : DDS::Boolean a_value;
545 45 : a_rc = a_data->get_boolean_value(a_value, a_id);
546 45 : if (a_rc == DDS::RETCODE_OK) {
547 : DDS::Boolean b_value;
548 45 : b_rc = b_data->get_boolean_value(b_value, b_id);
549 45 : if (b_rc == DDS::RETCODE_OK) {
550 45 : cmp(result, a_value, b_value);
551 : }
552 : }
553 : }
554 45 : break;
555 :
556 46 : case TK_BYTE:
557 : {
558 : DDS::Byte a_value;
559 46 : a_rc = a_data->get_byte_value(a_value, a_id);
560 46 : if (a_rc == DDS::RETCODE_OK) {
561 : DDS::Byte b_value;
562 46 : b_rc = b_data->get_byte_value(b_value, b_id);
563 46 : if (b_rc == DDS::RETCODE_OK) {
564 46 : cmp(result, a_value, b_value);
565 : }
566 : }
567 : }
568 46 : break;
569 :
570 223 : case TK_UINT8:
571 : case TK_UINT16:
572 : case TK_UINT32:
573 : case TK_UINT64:
574 : {
575 : DDS::UInt64 a_value;
576 223 : a_rc = get_uint_value(a_value, a_data, a_id, tk);
577 223 : if (a_rc == DDS::RETCODE_OK) {
578 : DDS::UInt64 b_value;
579 223 : b_rc = get_uint_value(b_value, b_data, b_id, tk);
580 223 : if (b_rc == DDS::RETCODE_OK) {
581 223 : cmp(result, a_value, b_value);
582 : }
583 : }
584 : }
585 223 : break;
586 :
587 209 : case TK_INT8:
588 : case TK_INT16:
589 : case TK_INT32:
590 : case TK_INT64:
591 : {
592 : DDS::Int64 a_value;
593 209 : a_rc = get_int_value(a_value, a_data, a_id, tk);
594 209 : if (a_rc == DDS::RETCODE_OK) {
595 : DDS::Int64 b_value;
596 209 : b_rc = get_int_value(b_value, b_data, b_id, tk);
597 209 : if (b_rc == DDS::RETCODE_OK) {
598 209 : cmp(result, a_value, b_value);
599 : }
600 : }
601 : }
602 209 : break;
603 :
604 36 : case TK_FLOAT32:
605 : {
606 : DDS::Float32 a_value;
607 36 : a_rc = a_data->get_float32_value(a_value, a_id);
608 36 : if (a_rc == DDS::RETCODE_OK) {
609 : DDS::Float32 b_value;
610 36 : b_rc = b_data->get_float32_value(b_value, b_id);
611 36 : if (b_rc == DDS::RETCODE_OK) {
612 36 : cmp(result, a_value, b_value);
613 : }
614 : }
615 : }
616 36 : break;
617 :
618 35 : case TK_FLOAT64:
619 : {
620 : DDS::Float64 a_value;
621 35 : a_rc = a_data->get_float64_value(a_value, a_id);
622 35 : if (a_rc == DDS::RETCODE_OK) {
623 : DDS::Float64 b_value;
624 35 : b_rc = b_data->get_float64_value(b_value, b_id);
625 35 : if (b_rc == DDS::RETCODE_OK) {
626 35 : cmp(result, a_value, b_value);
627 : }
628 : }
629 : }
630 35 : break;
631 :
632 34 : case TK_FLOAT128:
633 : {
634 : DDS::Float128 a_value;
635 34 : a_rc = a_data->get_float128_value(a_value, a_id);
636 34 : if (a_rc == DDS::RETCODE_OK) {
637 : DDS::Float128 b_value;
638 34 : b_rc = b_data->get_float128_value(b_value, b_id);
639 34 : if (b_rc == DDS::RETCODE_OK) {
640 34 : cmp(result, a_value, b_value);
641 : }
642 : }
643 : }
644 34 : break;
645 :
646 33 : case TK_CHAR8:
647 : {
648 : CORBA::Char a_value;
649 33 : a_rc = a_data->get_char8_value(a_value, a_id);
650 33 : if (a_rc == DDS::RETCODE_OK) {
651 : CORBA::Char b_value;
652 33 : b_rc = b_data->get_char8_value(b_value, b_id);
653 33 : if (b_rc == DDS::RETCODE_OK) {
654 33 : cmp(result, a_value, b_value);
655 : }
656 : }
657 : }
658 33 : break;
659 :
660 32 : case TK_CHAR16:
661 : {
662 : CORBA::WChar a_value;
663 32 : a_rc = a_data->get_char16_value(a_value, a_id);
664 32 : if (a_rc == DDS::RETCODE_OK) {
665 : CORBA::WChar b_value;
666 32 : b_rc = b_data->get_char16_value(b_value, b_id);
667 32 : if (b_rc == DDS::RETCODE_OK) {
668 32 : cmp(result, a_value, b_value);
669 : }
670 : }
671 : }
672 32 : break;
673 :
674 31 : case TK_STRING8:
675 : {
676 31 : CORBA::String_var a_value;
677 31 : a_rc = a_data->get_string_value(a_value, a_id);
678 31 : if (a_rc == DDS::RETCODE_OK) {
679 31 : CORBA::String_var b_value;
680 31 : b_rc = b_data->get_string_value(b_value, b_id);
681 31 : if (b_rc == DDS::RETCODE_OK) {
682 31 : result = std::strcmp(a_value.in(), b_value.in());
683 : }
684 31 : }
685 31 : }
686 31 : break;
687 :
688 30 : case TK_STRING16:
689 : {
690 30 : CORBA::WString_var a_value;
691 30 : a_rc = a_data->get_wstring_value(a_value, a_id);
692 30 : if (a_rc == DDS::RETCODE_OK) {
693 30 : CORBA::WString_var b_value;
694 30 : b_rc = b_data->get_wstring_value(b_value, b_id);
695 30 : if (b_rc == DDS::RETCODE_OK) {
696 30 : result = std::wcscmp(a_value.in(), b_value.in());
697 : }
698 30 : }
699 30 : }
700 30 : break;
701 :
702 29 : case TK_ENUM:
703 : {
704 : DDS::Int32 a_value;
705 29 : a_rc = get_enum_value(a_value, a_type, a_data, a_id);
706 29 : if (a_rc == DDS::RETCODE_OK) {
707 : DDS::Int32 b_value;
708 29 : b_rc = get_enum_value(b_value, b_type, b_data, b_id);
709 29 : if (b_rc == DDS::RETCODE_OK) {
710 29 : cmp(result, a_value, b_value);
711 : }
712 : }
713 : }
714 29 : break;
715 :
716 0 : case TK_BITMASK:
717 : {
718 : DDS::UInt64 a_value;
719 0 : a_rc = get_bitmask_value(a_value, a_type, a_data, a_id);
720 0 : if (a_rc == DDS::RETCODE_OK) {
721 : DDS::UInt64 b_value;
722 0 : b_rc = get_bitmask_value(b_value, b_type, b_data, b_id);
723 0 : if (b_rc == DDS::RETCODE_OK) {
724 0 : cmp(result, a_value, b_value);
725 : }
726 : }
727 : }
728 0 : 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 51 : case TK_SEQUENCE:
738 : case TK_ARRAY:
739 : {
740 51 : DDS::DynamicData_var a_value;
741 51 : a_rc = a_data->get_complex_value(a_value, a_id);
742 51 : if (a_rc == DDS::RETCODE_OK) {
743 51 : DDS::DynamicData_var b_value;
744 51 : b_rc = b_data->get_complex_value(b_value, b_id);
745 51 : if (b_rc == DDS::RETCODE_OK) {
746 51 : switch (tk) {
747 51 : case TK_ARRAY:
748 : case TK_SEQUENCE:
749 : {
750 51 : const DDS::UInt32 a_count = a_value->get_item_count();
751 51 : const DDS::UInt32 b_count = b_value->get_item_count();
752 51 : const DDS::UInt32 count = std::min(a_count, b_count);
753 51 : for (DDS::UInt32 i = 0;
754 104 : a_rc == DDS::RETCODE_OK && i < count && result == 0; ++i) {
755 106 : a_rc = b_rc = member_compare(result,
756 53 : a_value, a_value->get_member_id_at_index(i),
757 53 : b_value, b_value->get_member_id_at_index(i));
758 : }
759 51 : if (result == 0 && a_count != b_count) {
760 1 : result = count == a_count ? -1 : 1;
761 : }
762 : }
763 51 : break;
764 :
765 0 : default:
766 0 : OPENDDS_ASSERT(false);
767 : break;
768 : }
769 : }
770 51 : }
771 51 : }
772 51 : break;
773 :
774 0 : 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 0 : if (log_level >= LogLevel::Warning) {
783 0 : ACE_ERROR((LM_WARNING, "(%P|%t) WARNING: member_compare(DynamicData): "
784 : "member has unexpected TypeKind %C\n", typekind_to_string(b_tk)));
785 : }
786 0 : a_rc = DDS::RETCODE_BAD_PARAMETER;
787 0 : b_rc = DDS::RETCODE_BAD_PARAMETER;
788 : }
789 :
790 834 : if (a_rc != DDS::RETCODE_OK || b_rc != DDS::RETCODE_OK) {
791 0 : const CORBA::String_var b_type_name = b_data->type()->get_name();
792 0 : const CORBA::String_var a_type_name = a_data->type()->get_name();
793 0 : if (log_level >= LogLevel::Warning) {
794 0 : 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 0 : }
801 :
802 834 : return DDS::RETCODE_OK;
803 834 : }
804 : }
805 :
806 46 : DDS::ReturnCode_t less_than(
807 : bool& result, DDS::DynamicData_ptr a, DDS::DynamicData_ptr b, Filter filter)
808 : {
809 46 : DDS::DynamicType_var a_type = a->type();
810 46 : MemberPathVec paths;
811 46 : DDS::ReturnCode_t rc = get_values(a_type, paths, filter);
812 46 : if (rc != DDS::RETCODE_OK) {
813 0 : if (log_level >= LogLevel::Notice) {
814 0 : ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: key_compare: get_keys failed: %C\n",
815 : retcode_to_string(rc)));
816 : }
817 0 : return rc;
818 : }
819 :
820 46 : result = false;
821 804 : for (MemberPathVec::iterator it = paths.begin(); it != paths.end(); it++) {
822 781 : DDS::DynamicData_var a_container;
823 : DDS::MemberId a_member_id;
824 781 : rc = it->get_member_from_data(a, a_container, a_member_id);
825 781 : if (rc != DDS::RETCODE_OK) {
826 0 : if (log_level >= LogLevel::Notice) {
827 0 : 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 0 : return rc;
832 : }
833 :
834 781 : DDS::DynamicData_var b_container;
835 : DDS::MemberId b_member_id;
836 781 : rc = it->get_member_from_data(b, b_container, b_member_id);
837 781 : if (rc != DDS::RETCODE_OK) {
838 0 : if (log_level >= LogLevel::Notice) {
839 0 : 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 0 : return rc;
844 : }
845 :
846 781 : int compare = 0;
847 781 : rc = member_compare(compare, a_container, a_member_id, b_container, b_member_id);
848 781 : if (rc != DDS::RETCODE_OK) {
849 0 : return rc;
850 : }
851 781 : if (compare != 0) {
852 23 : result = compare < 0;
853 23 : return DDS::RETCODE_OK;
854 : }
855 804 : }
856 :
857 23 : return DDS::RETCODE_OK;
858 46 : }
859 :
860 0 : DDS::ReturnCode_t key_less_than(bool& result, DDS::DynamicData_ptr a, DDS::DynamicData_ptr b)
861 : {
862 0 : return less_than(result, a, b, Filter_Keys);
863 : }
864 :
865 0 : DDS::ReturnCode_t compare_members(int& result, DDS::DynamicData_ptr a, DDS::DynamicData_ptr b, DDS::MemberId id)
866 : {
867 0 : return member_compare(result, a, id, b, id);
868 : }
869 :
870 3284 : DDS::ReturnCode_t get_member_type(DDS::DynamicType_var& member_type,
871 : DDS::DynamicType_ptr container_type, DDS::MemberId id)
872 : {
873 3284 : const DDS::TypeKind container_kind = container_type->get_kind();
874 3284 : if (is_sequence_like(container_kind)) {
875 818 : DDS::TypeDescriptor_var td;
876 818 : DDS::ReturnCode_t rc = container_type->get_descriptor(td);
877 818 : if (rc != DDS::RETCODE_OK) {
878 0 : return rc;
879 : }
880 818 : member_type = get_base_type(td->element_type());
881 3284 : } else if (is_scalar(container_kind)) {
882 10 : if (id != MEMBER_ID_INVALID && log_level >= LogLevel::Warning) {
883 0 : 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 10 : member_type = DDS::DynamicType::_duplicate(container_type);
888 10 : return DDS::RETCODE_OK;
889 : } else {
890 2456 : DDS::DynamicTypeMember_var dtm;
891 2456 : DDS::ReturnCode_t rc = container_type->get_member(dtm, id);
892 2456 : if (rc != DDS::RETCODE_OK) {
893 0 : return rc;
894 : }
895 2456 : DDS::MemberDescriptor_var md;
896 2456 : rc = dtm->get_descriptor(md);
897 2456 : if (rc != DDS::RETCODE_OK) {
898 0 : return rc;
899 : }
900 2456 : member_type = get_base_type(md->type());
901 2456 : }
902 3274 : return DDS::RETCODE_OK;
903 : }
904 :
905 601 : DDS::ReturnCode_t get_uint_value(
906 : DDS::UInt64& value, DDS::DynamicData_ptr src, DDS::MemberId id, DDS::TypeKind kind)
907 : {
908 601 : DDS::ReturnCode_t rc = DDS::RETCODE_BAD_PARAMETER;
909 601 : switch (kind) {
910 106 : case TK_UINT8:
911 : {
912 : DDS::UInt8 v;
913 106 : rc = src->get_uint8_value(v, id);
914 106 : if (rc == DDS::RETCODE_OK) {
915 106 : value = v;
916 : }
917 : }
918 106 : break;
919 104 : case TK_UINT16:
920 : {
921 : DDS::UInt16 v;
922 104 : rc = src->get_uint16_value(v, id);
923 104 : if (rc == DDS::RETCODE_OK) {
924 104 : value = v;
925 : }
926 : }
927 104 : break;
928 291 : case TK_UINT32:
929 : {
930 : DDS::UInt32 v;
931 291 : rc = src->get_uint32_value(v, id);
932 291 : if (rc == DDS::RETCODE_OK) {
933 291 : value = v;
934 : }
935 : }
936 291 : break;
937 100 : case TK_UINT64:
938 100 : rc = src->get_uint64_value(value, id);
939 100 : break;
940 : }
941 601 : return rc;
942 : }
943 :
944 128 : DDS::ReturnCode_t set_uint_value(
945 : DDS::DynamicData_ptr dest, DDS::MemberId id, DDS::TypeKind kind, DDS::UInt64 value)
946 : {
947 128 : switch (kind) {
948 18 : case TK_UINT8:
949 18 : return dest->set_uint8_value(id, static_cast<DDS::UInt8>(value));
950 18 : case TK_UINT16:
951 18 : return dest->set_uint16_value(id, static_cast<DDS::UInt16>(value));
952 74 : case TK_UINT32:
953 74 : return dest->set_uint32_value(id, static_cast<DDS::UInt32>(value));
954 18 : case TK_UINT64:
955 18 : return dest->set_uint64_value(id, value);
956 : }
957 0 : return DDS::RETCODE_BAD_PARAMETER;
958 : }
959 :
960 594 : DDS::ReturnCode_t get_int_value(
961 : DDS::Int64& value, DDS::DynamicData_ptr src, DDS::MemberId id, DDS::TypeKind kind)
962 : {
963 594 : DDS::ReturnCode_t rc = DDS::RETCODE_BAD_PARAMETER;
964 594 : switch (kind) {
965 98 : case TK_INT8:
966 : {
967 : DDS::Int8 v;
968 98 : rc = src->get_int8_value(v, id);
969 98 : if (rc == DDS::RETCODE_OK) {
970 98 : value = v;
971 : }
972 : }
973 98 : break;
974 96 : case TK_INT16:
975 : {
976 : DDS::Int16 v;
977 96 : rc = src->get_int16_value(v, id);
978 96 : if (rc == DDS::RETCODE_OK) {
979 96 : value = v;
980 : }
981 : }
982 96 : break;
983 308 : case TK_INT32:
984 : {
985 : DDS::Int32 v;
986 308 : rc = src->get_int32_value(v, id);
987 308 : if (rc == DDS::RETCODE_OK) {
988 308 : value = v;
989 : }
990 : }
991 308 : break;
992 92 : case TK_INT64:
993 92 : rc = src->get_int64_value(value, id);
994 92 : break;
995 : }
996 594 : return rc;
997 : }
998 :
999 107 : DDS::ReturnCode_t set_int_value(
1000 : DDS::DynamicData_ptr dest, DDS::MemberId id, DDS::TypeKind kind, DDS::Int64 value)
1001 : {
1002 107 : switch (kind) {
1003 18 : case TK_INT8:
1004 18 : return dest->set_int8_value(id, static_cast<DDS::Int8>(value));
1005 18 : case TK_INT16:
1006 18 : return dest->set_int16_value(id, static_cast<DDS::Int16>(value));
1007 53 : case TK_INT32:
1008 53 : return dest->set_int32_value(id, static_cast<DDS::Int32>(value));
1009 18 : case TK_INT64:
1010 18 : return dest->set_int64_value(id, value);
1011 : }
1012 0 : return DDS::RETCODE_BAD_PARAMETER;
1013 : }
1014 :
1015 1100 : DDS::UInt32 bound_total(DDS::TypeDescriptor_var descriptor)
1016 : {
1017 1100 : DDS::UInt32 total = 1;
1018 1100 : const DDS::BoundSeq& bounds = descriptor->bound();
1019 2200 : for (DDS::UInt32 i = 0; i < bounds.length(); ++i) {
1020 1100 : total *= bounds[i];
1021 : }
1022 1100 : return total;
1023 : }
1024 :
1025 0 : DDS::ReturnCode_t bitmask_bound(DDS::DynamicType_ptr type, DDS::TypeKind& bound_kind)
1026 : {
1027 0 : const DDS::TypeKind kind = type->get_kind();
1028 0 : if (kind != TK_BITMASK) {
1029 0 : if (log_level >= LogLevel::Notice) {
1030 0 : ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: bitmask_bound: "
1031 : "expected bitmask, got %C\n",
1032 : typekind_to_string(kind)));
1033 : }
1034 0 : return DDS::RETCODE_BAD_PARAMETER;
1035 : }
1036 :
1037 0 : DDS::TypeDescriptor_var td;
1038 0 : const DDS::ReturnCode_t rc = type->get_descriptor(td);
1039 0 : if (rc != DDS::RETCODE_OK) {
1040 0 : return rc;
1041 : }
1042 :
1043 0 : const size_t bound_size = td->bound()[0];
1044 0 : if (bound_size >= 1 && bound_size <= 8) {
1045 0 : bound_kind = TK_UINT8;
1046 0 : } else if (bound_size >= 9 && bound_size <= 16) {
1047 0 : bound_kind = TK_UINT16;
1048 0 : } else if (bound_size >= 17 && bound_size <= 32) {
1049 0 : bound_kind = TK_UINT32;
1050 0 : } else if (bound_size >= 33 && bound_size <= 64) {
1051 0 : bound_kind = TK_UINT64;
1052 : } else {
1053 0 : if (log_level >= LogLevel::Notice) {
1054 0 : ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: bitmask_bound: "
1055 : "Got unexpected bound size %B\n",
1056 : bound_size));
1057 : }
1058 0 : return DDS::RETCODE_BAD_PARAMETER;
1059 : }
1060 0 : return DDS::RETCODE_OK;
1061 0 : }
1062 :
1063 0 : DDS::ReturnCode_t get_bitmask_value(
1064 : DDS::UInt64& value, DDS::DynamicType_ptr type, DDS::DynamicData_ptr src, DDS::MemberId id)
1065 : {
1066 : DDS::TypeKind bound_kind;
1067 0 : const DDS::ReturnCode_t rc = bitmask_bound(type, bound_kind);
1068 0 : if (rc != DDS::RETCODE_OK) {
1069 0 : return rc;
1070 : }
1071 0 : return get_uint_value(value, src, id, bound_kind);
1072 : }
1073 :
1074 326 : DDS::ReturnCode_t enum_bound(DDS::DynamicType_ptr enum_type, DDS::TypeKind& bound_kind)
1075 : {
1076 326 : const DDS::TypeKind kind = enum_type->get_kind();
1077 326 : if (kind != TK_ENUM) {
1078 0 : if (log_level >= LogLevel::Notice) {
1079 0 : ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: enum_bound: "
1080 : "expected enum, got %C\n",
1081 : typekind_to_string(kind)));
1082 : }
1083 0 : return DDS::RETCODE_BAD_PARAMETER;
1084 : }
1085 :
1086 326 : DDS::TypeDescriptor_var td;
1087 326 : const DDS::ReturnCode_t rc = enum_type->get_descriptor(td);
1088 326 : if (rc != DDS::RETCODE_OK) {
1089 0 : return rc;
1090 : }
1091 :
1092 326 : const size_t bound_size = td->bound()[0];
1093 326 : if (bound_size >= 1 && bound_size <= 8) {
1094 0 : bound_kind = TK_INT8;
1095 326 : } else if (bound_size >= 9 && bound_size <= 16) {
1096 0 : bound_kind = TK_INT16;
1097 326 : } else if (bound_size >= 17 && bound_size <= 32) {
1098 326 : bound_kind = TK_INT32;
1099 : } else {
1100 0 : if (log_level >= LogLevel::Notice) {
1101 0 : ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: enum_bound: "
1102 : "Got unexpected bound size %B\n",
1103 : bound_size));
1104 : }
1105 0 : return DDS::RETCODE_BAD_PARAMETER;
1106 : }
1107 326 : return DDS::RETCODE_OK;
1108 326 : }
1109 :
1110 94 : DDS::ReturnCode_t get_enum_value(
1111 : DDS::Int32& value, DDS::DynamicType_ptr enum_type, DDS::DynamicData_ptr src, DDS::MemberId id)
1112 : {
1113 : DDS::TypeKind bound_kind;
1114 94 : DDS::ReturnCode_t rc = enum_bound(enum_type, bound_kind);
1115 94 : if (rc != DDS::RETCODE_OK) {
1116 0 : return rc;
1117 : }
1118 94 : DDS::Int64 v = 0;
1119 94 : rc = get_int_value(v, src, id, bound_kind);
1120 94 : if (rc != DDS::RETCODE_OK) {
1121 0 : return rc;
1122 : }
1123 94 : value = static_cast<DDS::Int32>(v);
1124 94 : return rc;
1125 : }
1126 :
1127 2 : DDS::ReturnCode_t get_enumerator_name(
1128 : DDS::String8_var& name, DDS::Int32 value, DDS::DynamicType_ptr type)
1129 : {
1130 2 : DDS::DynamicTypeMember_var dtm;
1131 2 : DDS::ReturnCode_t rc = type->get_member(dtm, static_cast<DDS::MemberId>(value));
1132 2 : if (rc != DDS::RETCODE_OK) {
1133 0 : return rc;
1134 : }
1135 :
1136 2 : DDS::MemberDescriptor_var md;
1137 2 : rc = dtm->get_descriptor(md);
1138 2 : if (rc != DDS::RETCODE_OK) {
1139 0 : return rc;
1140 : }
1141 :
1142 2 : name = md->name();
1143 2 : return DDS::RETCODE_OK;
1144 2 : }
1145 :
1146 1 : DDS::ReturnCode_t get_enumerator_value(
1147 : DDS::Int32& value, const char* name, DDS::DynamicType_ptr type)
1148 : {
1149 1 : DDS::DynamicTypeMember_var dtm;
1150 1 : DDS::ReturnCode_t rc = type->get_member_by_name(dtm, name);
1151 1 : if (rc != DDS::RETCODE_OK) {
1152 0 : return rc;
1153 : }
1154 :
1155 1 : DDS::MemberDescriptor_var md;
1156 1 : rc = dtm->get_descriptor(md);
1157 1 : if (rc != DDS::RETCODE_OK) {
1158 0 : return rc;
1159 : }
1160 :
1161 1 : value = static_cast<DDS::Int32>(md->id());
1162 1 : return DDS::RETCODE_OK;
1163 1 : }
1164 :
1165 25 : DDS::ReturnCode_t set_enum_value(
1166 : DDS::DynamicType_ptr enum_type, DDS::DynamicData_ptr dest, DDS::MemberId id, DDS::Int32 value)
1167 : {
1168 : DDS::TypeKind bound_kind;
1169 25 : const DDS::ReturnCode_t rc = enum_bound(enum_type, bound_kind);
1170 25 : if (rc != DDS::RETCODE_OK) {
1171 0 : return rc;
1172 : }
1173 25 : return set_int_value(dest, id, bound_kind, value);
1174 : }
1175 :
1176 0 : DDS::ReturnCode_t set_enum_value(
1177 : DDS::DynamicType_ptr type, DDS::DynamicData_ptr dest, DDS::MemberId id, const char* enumeral_name)
1178 : {
1179 0 : DDS::DynamicTypeMember_var dtm;
1180 0 : DDS::ReturnCode_t rc = type->get_member_by_name(dtm, enumeral_name);
1181 0 : if (rc != DDS::RETCODE_OK) {
1182 0 : if (log_level >= LogLevel::Notice) {
1183 0 : ACE_ERROR((LM_NOTICE, "(%P|%t) NOTICE: set_enum_value: "
1184 : "No such enumeral named \"%C\"\n",
1185 : enumeral_name));
1186 : }
1187 0 : return rc;
1188 : }
1189 0 : DDS::MemberDescriptor_var md;
1190 0 : rc = dtm->get_descriptor(md);
1191 0 : if (rc != DDS::RETCODE_OK) {
1192 0 : return rc;
1193 : }
1194 0 : return set_enum_value(type, dest, id, md->id());
1195 0 : }
1196 :
1197 608 : DDS::ReturnCode_t copy_member(
1198 : DDS::DynamicData_ptr dest, DDS::MemberId dest_id,
1199 : DDS::DynamicData_ptr src, DDS::MemberId src_id)
1200 : {
1201 608 : DDS::ReturnCode_t rc = DDS::RETCODE_OK;
1202 608 : if (dest == src) {
1203 0 : return rc;
1204 : }
1205 :
1206 608 : const DDS::DynamicType_var dest_type = dest->type();
1207 608 : DDS::DynamicType_var use_dest_type;
1208 608 : if (dest_id != MEMBER_ID_INVALID) {
1209 608 : rc = get_member_type(use_dest_type, dest_type, dest_id);
1210 608 : if (rc != DDS::RETCODE_OK) {
1211 0 : return rc;
1212 : }
1213 : } else {
1214 0 : use_dest_type = get_base_type(dest_type);
1215 : }
1216 608 : const DDS::TypeKind dest_tk = use_dest_type->get_kind();
1217 :
1218 608 : const DDS::DynamicType_var src_type = src->type();
1219 608 : DDS::DynamicType_var use_src_type;
1220 608 : if (src_id != MEMBER_ID_INVALID) {
1221 608 : rc = get_member_type(use_src_type, src_type, src_id);
1222 608 : if (rc != DDS::RETCODE_OK) {
1223 0 : return rc;
1224 : }
1225 : } else {
1226 0 : use_src_type = get_base_type(src_type);
1227 : }
1228 608 : const DDS::TypeKind src_tk = use_src_type->get_kind();
1229 :
1230 608 : if (DCPS::DCPS_debug_level >= 8) {
1231 0 : const CORBA::String_var src_type_name = src_type->get_name();
1232 0 : const CORBA::String_var dest_type_name = dest_type->get_name();
1233 0 : 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 0 : }
1237 :
1238 608 : if (src_tk != dest_tk) {
1239 0 : if (log_level >= LogLevel::Warning) {
1240 0 : 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 0 : return DDS::RETCODE_OK;
1245 : }
1246 :
1247 608 : DDS::ReturnCode_t get_rc = DDS::RETCODE_OK;
1248 608 : DDS::ReturnCode_t set_rc = DDS::RETCODE_OK;
1249 608 : switch (src_tk) {
1250 18 : case TK_BOOLEAN:
1251 : {
1252 : DDS::Boolean value;
1253 18 : get_rc = src->get_boolean_value(value, src_id);
1254 18 : if (get_rc == DDS::RETCODE_OK) {
1255 18 : set_rc = dest->set_boolean_value(dest_id, value);
1256 : }
1257 : }
1258 18 : break;
1259 :
1260 18 : case TK_BYTE:
1261 : {
1262 : DDS::Byte value;
1263 18 : get_rc = src->get_byte_value(value, src_id);
1264 18 : if (get_rc == DDS::RETCODE_OK) {
1265 18 : set_rc = dest->set_byte_value(dest_id, value);
1266 : }
1267 : }
1268 18 : break;
1269 :
1270 82 : case TK_INT8:
1271 : case TK_INT16:
1272 : case TK_INT32:
1273 : case TK_INT64:
1274 : {
1275 : DDS::Int64 value;
1276 82 : get_rc = get_int_value(value, src, src_id, src_tk);
1277 82 : if (get_rc == DDS::RETCODE_OK) {
1278 82 : set_rc = set_int_value(dest, dest_id, dest_tk, value);
1279 : }
1280 : }
1281 82 : break;
1282 :
1283 128 : case TK_UINT8:
1284 : case TK_UINT16:
1285 : case TK_UINT32:
1286 : case TK_UINT64:
1287 : {
1288 : DDS::UInt64 value;
1289 128 : get_rc = get_uint_value(value, src, src_id, src_tk);
1290 128 : if (get_rc == DDS::RETCODE_OK) {
1291 128 : set_rc = set_uint_value(dest, dest_id, dest_tk, value);
1292 : }
1293 : }
1294 128 : break;
1295 :
1296 18 : case TK_FLOAT32:
1297 : {
1298 : DDS::Float32 value;
1299 18 : get_rc = src->get_float32_value(value, src_id);
1300 18 : if (get_rc == DDS::RETCODE_OK) {
1301 18 : set_rc = dest->set_float32_value(dest_id, value);
1302 : }
1303 : }
1304 18 : break;
1305 :
1306 20 : case TK_FLOAT64:
1307 : {
1308 : DDS::Float64 value;
1309 20 : get_rc = src->get_float64_value(value, src_id);
1310 20 : if (get_rc == DDS::RETCODE_OK) {
1311 20 : set_rc = dest->set_float64_value(dest_id, value);
1312 : }
1313 : }
1314 20 : break;
1315 :
1316 16 : case TK_FLOAT128:
1317 : {
1318 : DDS::Float128 value;
1319 16 : get_rc = src->get_float128_value(value, src_id);
1320 16 : if (get_rc == DDS::RETCODE_OK) {
1321 16 : set_rc = dest->set_float128_value(dest_id, value);
1322 : }
1323 : }
1324 16 : break;
1325 :
1326 18 : case TK_CHAR8:
1327 : {
1328 : DDS::Char8 value;
1329 18 : get_rc = src->get_char8_value(value, src_id);
1330 18 : if (get_rc == DDS::RETCODE_OK) {
1331 18 : set_rc = dest->set_char8_value(dest_id, value);
1332 : }
1333 : }
1334 18 : break;
1335 :
1336 18 : case TK_CHAR16:
1337 : {
1338 : DDS::Char16 value;
1339 18 : get_rc = src->get_char16_value(value, src_id);
1340 18 : if (get_rc == DDS::RETCODE_OK) {
1341 18 : set_rc = dest->set_char16_value(dest_id, value);
1342 : }
1343 : }
1344 18 : break;
1345 :
1346 20 : case TK_STRING8:
1347 : {
1348 20 : CORBA::String_var value;
1349 20 : get_rc = src->get_string_value(value, src_id);
1350 20 : if (get_rc == DDS::RETCODE_OK) {
1351 20 : set_rc = dest->set_string_value(dest_id, value);
1352 : }
1353 20 : }
1354 20 : break;
1355 :
1356 18 : case TK_STRING16:
1357 : {
1358 18 : CORBA::WString_var value;
1359 18 : get_rc = src->get_wstring_value(value, src_id);
1360 18 : if (get_rc == DDS::RETCODE_OK) {
1361 18 : set_rc = dest->set_wstring_value(dest_id, value);
1362 : }
1363 18 : }
1364 18 : break;
1365 :
1366 24 : case TK_ENUM:
1367 : {
1368 : DDS::Int32 value;
1369 24 : get_rc = get_enum_value(value, use_src_type, src, src_id);
1370 24 : if (get_rc == DDS::RETCODE_OK) {
1371 24 : set_rc = set_enum_value(use_dest_type, dest, dest_id, value);
1372 : }
1373 : }
1374 24 : break;
1375 :
1376 210 : case TK_STRUCTURE:
1377 : case TK_UNION:
1378 : case TK_SEQUENCE:
1379 : case TK_ARRAY:
1380 : {
1381 210 : DDS::DynamicData_var subsrc;
1382 210 : get_rc = src->get_complex_value(subsrc, src_id);
1383 210 : if (get_rc == DDS::RETCODE_OK) {
1384 210 : DDS::DynamicData_var subdest;
1385 210 : get_rc = dest->get_complex_value(subdest, dest_id);
1386 210 : if (get_rc == DDS::RETCODE_OK) {
1387 210 : set_rc = copy(subdest, subsrc);
1388 : }
1389 210 : }
1390 210 : }
1391 210 : break;
1392 :
1393 0 : case TK_MAP:
1394 : case TK_BITSET:
1395 : case TK_ALIAS:
1396 : case TK_ANNOTATION:
1397 : default:
1398 0 : if (log_level >= LogLevel::Warning) {
1399 0 : ACE_ERROR((LM_WARNING, "(%P|%t) WARNING: copy(DynamicData): "
1400 : "member has unexpected TypeKind %C\n", typekind_to_string(src_tk)));
1401 : }
1402 0 : get_rc = DDS::RETCODE_UNSUPPORTED;
1403 : }
1404 :
1405 608 : if (get_rc == DDS::RETCODE_NO_DATA) {
1406 0 : if (DCPS::DCPS_debug_level >= 8) {
1407 0 : const CORBA::String_var src_type_name = src_type->get_name();
1408 0 : const CORBA::String_var dest_type_name = dest_type->get_name();
1409 0 : 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 0 : }
1414 0 : return DDS::RETCODE_OK;
1415 : }
1416 :
1417 608 : if (get_rc != DDS::RETCODE_OK || set_rc != DDS::RETCODE_OK) {
1418 0 : if (log_level >= LogLevel::Warning) {
1419 0 : const CORBA::String_var src_type_name = src_type->get_name();
1420 0 : const CORBA::String_var dest_type_name = dest_type->get_name();
1421 0 : const DDS::TypeKind tk = src_type->get_kind();
1422 0 : if (tk == TK_STRUCTURE || tk == TK_UNION) {
1423 0 : CORBA::String_var src_member_name;
1424 0 : DDS::MemberDescriptor_var src_md;
1425 0 : DDS::ReturnCode_t rc = src->get_descriptor(src_md, src_id);
1426 0 : if (rc == DDS::RETCODE_OK) {
1427 0 : src_member_name = src_md->name();
1428 : }
1429 0 : CORBA::String_var dest_member_name;
1430 0 : DDS::MemberDescriptor_var dest_md;
1431 0 : rc = dest->get_descriptor(dest_md, dest_id);
1432 0 : if (rc == DDS::RETCODE_OK) {
1433 0 : dest_member_name = dest_md->name();
1434 : }
1435 0 : 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 0 : } else {
1442 0 : 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 0 : }
1448 0 : rc = get_rc != DDS::RETCODE_OK ? get_rc : set_rc;
1449 : }
1450 :
1451 608 : return rc;
1452 608 : }
1453 :
1454 218 : DDS::ReturnCode_t copy(DDS::DynamicData_ptr dest, DDS::DynamicData_ptr src)
1455 : {
1456 218 : if (dest == src) {
1457 0 : return DDS::RETCODE_OK;
1458 : }
1459 :
1460 218 : const DDS::DynamicType_var dest_type = dest->type();
1461 218 : const DDS::DynamicType_var actual_dest_type = get_base_type(dest_type);
1462 218 : const DDS::TypeKind dest_tk = actual_dest_type->get_kind();
1463 :
1464 218 : const DDS::DynamicType_var src_type = src->type();
1465 218 : const DDS::DynamicType_var actual_src_type = get_base_type(src_type);
1466 218 : const DDS::TypeKind src_tk = actual_src_type->get_kind();
1467 :
1468 218 : if (src_tk != dest_tk) {
1469 0 : if (log_level >= LogLevel::Notice) {
1470 0 : 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 0 : return DDS::RETCODE_OK;
1475 : }
1476 :
1477 218 : DDS::ReturnCode_t rc = DDS::RETCODE_OK;
1478 218 : switch (src_tk) {
1479 0 : 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 0 : return copy_member(dest, MEMBER_ID_INVALID, src, MEMBER_ID_INVALID);
1498 :
1499 24 : case TK_UNION:
1500 : {
1501 24 : if (src->get_item_count() == 2) {
1502 24 : const DDS::MemberId id = src->get_member_id_at_index(1);
1503 24 : rc = copy_member(dest, id, src, id);
1504 24 : if (rc != DDS::RETCODE_OK) {
1505 0 : if (log_level >= LogLevel::Warning) {
1506 0 : ACE_ERROR((LM_WARNING, "(%P|%t) WARNING: copy(DynamicData): "
1507 : "Couldn't set union branch: %C\n", retcode_to_string(rc)));
1508 : }
1509 0 : return rc;
1510 : }
1511 : }
1512 24 : rc = copy_member(dest, DISCRIMINATOR_ID, src, DISCRIMINATOR_ID);
1513 24 : if (rc != DDS::RETCODE_OK && log_level >= LogLevel::Warning) {
1514 0 : ACE_ERROR((LM_WARNING, "(%P|%t) WARNING: copy(DynamicData): "
1515 : "Couldn't set union disciminator: %C\n", retcode_to_string(rc)));
1516 : }
1517 24 : return rc;
1518 : }
1519 :
1520 30 : case TK_STRUCTURE:
1521 : {
1522 30 : DDS::DynamicTypeMembersById_var src_members_var;
1523 30 : rc = actual_src_type->get_all_members(src_members_var);
1524 30 : if (rc != DDS::RETCODE_OK) {
1525 0 : return rc;
1526 : }
1527 : DynamicTypeMembersByIdImpl* src_members =
1528 30 : dynamic_cast<DynamicTypeMembersByIdImpl*>(src_members_var.in());
1529 :
1530 30 : DDS::DynamicTypeMembersById_var dest_members_var;
1531 30 : rc = actual_dest_type->get_all_members(dest_members_var);
1532 30 : if (rc != DDS::RETCODE_OK) {
1533 0 : return rc;
1534 : }
1535 : DynamicTypeMembersByIdImpl* dest_members =
1536 30 : dynamic_cast<DynamicTypeMembersByIdImpl*>(dest_members_var.in());
1537 :
1538 30 : for (DynamicTypeMembersByIdImpl::const_iterator src_it = src_members->begin();
1539 262 : src_it != src_members->end(); ++src_it) {
1540 232 : const DDS::MemberId id = src_it->first;
1541 232 : const DynamicTypeMembersByIdImpl::const_iterator dest_it = dest_members->find(id);
1542 232 : if (dest_it == dest_members->end()) {
1543 0 : continue;
1544 : }
1545 :
1546 232 : const DDS::ReturnCode_t this_rc = copy_member(dest, id, src, id);
1547 232 : if (this_rc != DDS::RETCODE_OK && rc == DDS::RETCODE_OK) {
1548 0 : rc = this_rc;
1549 : }
1550 : }
1551 30 : }
1552 30 : break;
1553 :
1554 164 : case TK_SEQUENCE:
1555 : case TK_ARRAY:
1556 : {
1557 164 : const DDS::UInt32 count = src->get_item_count();
1558 492 : for (DDS::UInt32 i = 0; i < count; ++i) {
1559 328 : const DDS::ReturnCode_t this_rc = copy_member(
1560 328 : dest, dest->get_member_id_at_index(i),
1561 328 : src, src->get_member_id_at_index(i));
1562 328 : if (this_rc != DDS::RETCODE_OK && rc == DDS::RETCODE_OK) {
1563 0 : rc = this_rc;
1564 : }
1565 : }
1566 : }
1567 164 : break;
1568 :
1569 0 : case TK_MAP:
1570 : case TK_BITSET:
1571 : case TK_ALIAS:
1572 : case TK_ANNOTATION:
1573 : default:
1574 0 : if (log_level >= LogLevel::Warning) {
1575 0 : ACE_ERROR((LM_WARNING, "(%P|%t) WARNING: copy(DynamicData): "
1576 : "member has unexpected TypeKind %C\n", typekind_to_string(src_tk)));
1577 : }
1578 0 : rc = DDS::RETCODE_UNSUPPORTED;
1579 : }
1580 :
1581 194 : return rc;
1582 218 : }
1583 :
1584 : } // namespace XTypes
1585 : } // namespace OpenDDS
1586 : OPENDDS_END_VERSIONED_NAMESPACE_DECL
1587 :
1588 : #endif // OPENDDS_SAFETY_PROFILE
|