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 : #include "TypeAssignability.h"
8 :
9 : #include <set>
10 :
11 : OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL
12 :
13 : namespace OpenDDS {
14 : namespace XTypes {
15 :
16 : /**
17 : * @brief Both input type objects must be minimal
18 : */
19 351 : bool TypeAssignability::assignable(const TypeObject& ta,
20 : const TypeObject& tb) const
21 : {
22 351 : if (EK_MINIMAL == ta.kind && EK_MINIMAL == tb.kind) {
23 351 : if (TK_ALIAS == ta.minimal.kind || TK_ALIAS == tb.minimal.kind) {
24 78 : return assignable_alias(ta.minimal, tb.minimal);
25 : }
26 :
27 273 : switch (ta.minimal.kind) {
28 0 : case TK_ANNOTATION:
29 0 : return assignable_annotation(ta.minimal, tb.minimal);
30 79 : case TK_STRUCTURE:
31 79 : return assignable_struct(ta.minimal, tb.minimal);
32 21 : case TK_UNION:
33 21 : return assignable_union(ta.minimal, tb.minimal);
34 0 : case TK_BITSET:
35 0 : return assignable_bitset(ta.minimal, tb.minimal);
36 48 : case TK_SEQUENCE:
37 48 : return assignable_sequence(ta.minimal, tb.minimal);
38 48 : case TK_ARRAY:
39 48 : return assignable_array(ta.minimal, tb.minimal);
40 48 : case TK_MAP:
41 48 : return assignable_map(ta.minimal, tb.minimal);
42 17 : case TK_ENUM:
43 17 : return assignable_enum(ta.minimal, tb.minimal);
44 12 : case TK_BITMASK:
45 12 : return assignable_bitmask(ta.minimal, tb.minimal);
46 0 : default:
47 0 : return assignable_extended(ta.minimal, tb.minimal);
48 : }
49 : }
50 :
51 0 : return false;
52 : }
53 :
54 : /**
55 : * @brief The first argument must be a minimal type object
56 : */
57 171 : bool TypeAssignability::assignable(const TypeObject& ta,
58 : const TypeIdentifier& tb) const
59 : {
60 171 : if (EK_MINIMAL == ta.kind) {
61 171 : if (TK_ALIAS == ta.minimal.kind) {
62 48 : return assignable(get_base_type(ta.minimal), tb);
63 : }
64 :
65 123 : switch (ta.minimal.kind) {
66 0 : case TK_ANNOTATION:
67 0 : return assignable_annotation(ta.minimal, tb);
68 0 : case TK_STRUCTURE:
69 0 : return assignable_struct(ta.minimal, tb);
70 0 : case TK_UNION:
71 0 : return assignable_union(ta.minimal, tb);
72 0 : case TK_BITSET:
73 0 : return assignable_bitset(ta.minimal, tb);
74 20 : case TK_SEQUENCE:
75 20 : return assignable_sequence(ta.minimal, tb);
76 0 : case TK_ARRAY:
77 0 : return assignable_array(ta.minimal, tb);
78 12 : case TK_MAP:
79 12 : return assignable_map(ta.minimal, tb);
80 42 : case TK_ENUM:
81 42 : return assignable_enum(ta.minimal, tb);
82 49 : case TK_BITMASK:
83 49 : return assignable_bitmask(ta.minimal, tb);
84 0 : default:
85 0 : return false;
86 : }
87 : }
88 :
89 0 : return false;
90 : }
91 :
92 : /**
93 : * @brief Both input can be of any type
94 : */
95 647 : bool TypeAssignability::assignable(const TypeIdentifier& ta,
96 : const TypeIdentifier& tb) const
97 : {
98 647 : if (ta == tb) {
99 140 : return true;
100 : }
101 :
102 507 : switch (ta.kind()) {
103 167 : case TK_BOOLEAN:
104 : case TK_BYTE:
105 : case TK_INT16:
106 : case TK_INT32:
107 : case TK_INT64:
108 : case TK_UINT16:
109 : case TK_UINT32:
110 : case TK_UINT64:
111 : case TK_FLOAT32:
112 : case TK_FLOAT64:
113 : case TK_FLOAT128:
114 : case TK_INT8:
115 : case TK_UINT8:
116 : case TK_CHAR8:
117 : case TK_CHAR16:
118 167 : return assignable_primitive(ta, tb);
119 241 : case TI_STRING8_SMALL:
120 : case TI_STRING8_LARGE:
121 : case TI_STRING16_SMALL:
122 : case TI_STRING16_LARGE:
123 241 : return assignable_string(ta, tb);
124 13 : case TI_PLAIN_SEQUENCE_SMALL:
125 : case TI_PLAIN_SEQUENCE_LARGE:
126 13 : return assignable_plain_sequence(ta, tb);
127 11 : case TI_PLAIN_ARRAY_SMALL:
128 : case TI_PLAIN_ARRAY_LARGE:
129 11 : return assignable_plain_array(ta, tb);
130 10 : case TI_PLAIN_MAP_SMALL:
131 : case TI_PLAIN_MAP_LARGE:
132 10 : return assignable_plain_map(ta, tb);
133 0 : case TI_STRONGLY_CONNECTED_COMPONENT:
134 : // No rule in the spec for strongly connected components
135 0 : return false;
136 0 : case EK_COMPLETE:
137 : // Assuming only equivalence kind of EK_MINIMAL is supported
138 0 : return false;
139 65 : case EK_MINIMAL: {
140 65 : const MinimalTypeObject& base_type_a = lookup_minimal(ta);
141 65 : return assignable(TypeObject(base_type_a), tb);
142 : }
143 0 : default:
144 0 : return false; // Future extensions
145 : }
146 : }
147 :
148 : /**
149 : * @brief The second argument must be a minimal type object
150 : */
151 56 : bool TypeAssignability::assignable(const TypeIdentifier& ta,
152 : const TypeObject& tb) const
153 : {
154 56 : if (EK_MINIMAL == tb.kind) {
155 56 : if (TK_ALIAS == tb.minimal.kind) {
156 48 : return assignable(ta, get_base_type(tb.minimal));
157 : }
158 :
159 8 : switch (ta.kind()) {
160 8 : case TK_BOOLEAN:
161 : case TK_BYTE:
162 : case TK_INT16:
163 : case TK_INT32:
164 : case TK_INT64:
165 : case TK_UINT16:
166 : case TK_UINT32:
167 : case TK_UINT64:
168 : case TK_FLOAT32:
169 : case TK_FLOAT64:
170 : case TK_FLOAT128:
171 : case TK_INT8:
172 : case TK_UINT8:
173 : case TK_CHAR8:
174 : case TK_CHAR16:
175 8 : return assignable_primitive(ta, tb.minimal);
176 0 : case TI_STRING8_SMALL:
177 : case TI_STRING8_LARGE:
178 : case TI_STRING16_SMALL:
179 : case TI_STRING16_LARGE:
180 0 : return assignable_string(ta, tb.minimal);
181 0 : case TI_PLAIN_SEQUENCE_SMALL:
182 : case TI_PLAIN_SEQUENCE_LARGE:
183 0 : return assignable_plain_sequence(ta, tb.minimal);
184 0 : case TI_PLAIN_ARRAY_SMALL:
185 : case TI_PLAIN_ARRAY_LARGE:
186 0 : return assignable_plain_array(ta, tb.minimal);
187 0 : case TI_PLAIN_MAP_SMALL:
188 : case TI_PLAIN_MAP_LARGE:
189 0 : return assignable_plain_map(ta, tb.minimal);
190 0 : case TI_STRONGLY_CONNECTED_COMPONENT:
191 0 : return false;
192 0 : case EK_COMPLETE:
193 0 : return false;
194 0 : case EK_MINIMAL: {
195 0 : const MinimalTypeObject& tobj_a = lookup_minimal(ta);
196 0 : return assignable(TypeObject(tobj_a), tb);
197 : }
198 0 : default:
199 0 : return false;
200 : }
201 : }
202 :
203 0 : return false;
204 : }
205 :
206 : /**
207 : * @brief At least one input type object must be TK_ALIAS
208 : */
209 78 : bool TypeAssignability::assignable_alias(const MinimalTypeObject& ta,
210 : const MinimalTypeObject& tb) const
211 : {
212 78 : if (TK_ALIAS == ta.kind && TK_ALIAS != tb.kind) {
213 10 : const TypeIdentifier& tia = ta.alias_type.body.common.related_type;
214 10 : switch (tia.kind()) {
215 0 : case TK_BOOLEAN:
216 : case TK_BYTE:
217 : case TK_INT16:
218 : case TK_INT32:
219 : case TK_INT64:
220 : case TK_UINT16:
221 : case TK_UINT32:
222 : case TK_UINT64:
223 : case TK_FLOAT32:
224 : case TK_FLOAT64:
225 : case TK_FLOAT128:
226 : case TK_INT8:
227 : case TK_UINT8:
228 : case TK_CHAR8:
229 : case TK_CHAR16:
230 0 : return assignable_primitive(tia, tb);
231 0 : case TI_STRING8_SMALL:
232 : case TI_STRING8_LARGE:
233 : case TI_STRING16_SMALL:
234 : case TI_STRING16_LARGE:
235 0 : return assignable_string(tia, tb);
236 2 : case TI_PLAIN_SEQUENCE_SMALL:
237 : case TI_PLAIN_SEQUENCE_LARGE:
238 2 : return assignable_plain_sequence(tia, tb);
239 2 : case TI_PLAIN_ARRAY_SMALL:
240 : case TI_PLAIN_ARRAY_LARGE:
241 2 : return assignable_plain_array(tia, tb);
242 2 : case TI_PLAIN_MAP_SMALL:
243 : case TI_PLAIN_MAP_LARGE:
244 2 : return assignable_plain_map(tia, tb);
245 0 : case TI_STRONGLY_CONNECTED_COMPONENT:
246 : // Does alias ever have SCC as its base type?
247 0 : return false;
248 0 : case EK_COMPLETE:
249 : // Supporting minimal base type only
250 0 : return false;
251 4 : case EK_MINIMAL: {
252 4 : const MinimalTypeObject& base_type_a = lookup_minimal(tia);
253 4 : return assignable(TypeObject(base_type_a), TypeObject(tb));
254 : }
255 0 : default:
256 0 : return false; // Future extensions
257 : }
258 68 : } else if (TK_ALIAS != ta.kind && TK_ALIAS == tb.kind) {
259 10 : const TypeIdentifier& tib = tb.alias_type.body.common.related_type;
260 10 : switch (ta.kind) {
261 0 : case TK_ANNOTATION:
262 0 : return assignable_annotation(ta, tib);
263 0 : case TK_STRUCTURE:
264 0 : return assignable_struct(ta, tib);
265 0 : case TK_UNION:
266 0 : return assignable_union(ta, tib);
267 0 : case TK_BITSET:
268 0 : return assignable_bitset(ta, tib);
269 2 : case TK_SEQUENCE:
270 2 : return assignable_sequence(ta, tib);
271 2 : case TK_ARRAY:
272 2 : return assignable_array(ta, tib);
273 2 : case TK_MAP:
274 2 : return assignable_map(ta, tib);
275 2 : case TK_ENUM:
276 2 : return assignable_enum(ta, tib);
277 2 : case TK_BITMASK:
278 2 : return assignable_bitmask(ta, tib);
279 0 : default:
280 0 : return false; // Future extensions
281 : }
282 58 : } else if (TK_ALIAS == ta.kind && TK_ALIAS == tb.kind) {
283 58 : const TypeIdentifier& tia = ta.alias_type.body.common.related_type;
284 58 : const TypeIdentifier& tib = tb.alias_type.body.common.related_type;
285 58 : return assignable(tia, tib);
286 : }
287 :
288 0 : return false;
289 : }
290 :
291 : /**
292 : * @brief The first type must be TK_ANNOTATION.
293 : * The second type must not be TK_ALIAS.
294 : */
295 0 : bool TypeAssignability::assignable_annotation(const MinimalTypeObject&,
296 : const MinimalTypeObject&) const
297 : {
298 : // No rule for annotation in the spec
299 0 : return false;
300 : }
301 :
302 : /**
303 : * @brief The first type must be TK_ANNOTATION.
304 : * The second type can be anything.
305 : */
306 0 : bool TypeAssignability::assignable_annotation(const MinimalTypeObject&,
307 : const TypeIdentifier&) const
308 : {
309 : // No rule for annotation in the spec
310 0 : return false;
311 : }
312 :
313 : /**
314 : * @brief The first type must be TK_STRUCTURE.
315 : * The second type must not be TK_ALIAS.
316 : */
317 79 : bool TypeAssignability::assignable_struct(const MinimalTypeObject& ta,
318 : const MinimalTypeObject& tb) const
319 : {
320 79 : if (TK_STRUCTURE != tb.kind) {
321 0 : return false;
322 : }
323 :
324 : // Extensibility kind must match
325 79 : const TypeFlag extensibility_mask = IS_FINAL | IS_APPENDABLE | IS_MUTABLE;
326 79 : const ACE_CDR::UShort a_exten = ta.struct_type.struct_flags & extensibility_mask;
327 79 : if (a_exten != (tb.struct_type.struct_flags & extensibility_mask)) {
328 1 : return false;
329 : }
330 :
331 : // If T1 is appendable, then members with the same member_index have the
332 : // same member ID, the same setting for the 'optional' attribute and the
333 : // T1 member type is strongly assignable from the T2 member type.
334 : // If T1 is final, then they meet the same condition as for T1 being
335 : // appendable and in addition T1 and T2 have the same set of member IDs.
336 80 : if (IS_FINAL == a_exten &&
337 2 : ta.struct_type.member_seq.length() != tb.struct_type.member_seq.length()) {
338 0 : return false;
339 : }
340 78 : if (IS_APPENDABLE == a_exten || IS_FINAL == a_exten) {
341 41 : const unsigned num_members = (std::min)(ta.struct_type.member_seq.length(),
342 41 : tb.struct_type.member_seq.length());
343 102 : for (unsigned i = 0; i < num_members; ++i) {
344 63 : if (ta.struct_type.member_seq[i].common.member_id !=
345 63 : tb.struct_type.member_seq[i].common.member_id ||
346 62 : (ta.struct_type.member_seq[i].common.member_flags & IS_OPTIONAL) !=
347 187 : (tb.struct_type.member_seq[i].common.member_flags & IS_OPTIONAL) ||
348 62 : !strongly_assignable(ta.struct_type.member_seq[i].common.member_type_id,
349 62 : tb.struct_type.member_seq[i].common.member_type_id)) {
350 2 : return false;
351 : }
352 : }
353 : }
354 :
355 : // Any members in T1 and T2 that have the same name also have
356 : // the same ID, and vice versa
357 76 : MatchedSet matched_members;
358 250 : for (unsigned i = 0; i < ta.struct_type.member_seq.length(); ++i) {
359 176 : MemberId id_a = ta.struct_type.member_seq[i].common.member_id;
360 176 : const NameHash& h_a = ta.struct_type.member_seq[i].detail.name_hash;
361 176 : ACE_CDR::ULong name_a = (h_a[0] << 24) | (h_a[1] << 16) | (h_a[2] << 8) | (h_a[3]);
362 448 : for (unsigned j = 0; j < tb.struct_type.member_seq.length(); ++j) {
363 445 : MemberId id_b = tb.struct_type.member_seq[j].common.member_id;
364 445 : const NameHash& h_b = tb.struct_type.member_seq[j].detail.name_hash;
365 445 : ACE_CDR::ULong name_b = (h_b[0] << 24) | (h_b[1] << 16) | (h_b[2] << 8) | (h_b[3]);
366 :
367 445 : if (!type_consistency_.ignore_member_names) {
368 238 : if ((name_a == name_b && id_a != id_b) || (id_a == id_b && name_a != name_b)) {
369 2 : return false;
370 236 : } else if (name_a == name_b && id_a == id_b) {
371 95 : matched_members.push_back(std::make_pair(&ta.struct_type.member_seq[i],
372 95 : &tb.struct_type.member_seq[j]));
373 95 : break;
374 : }
375 207 : } else if (id_a == id_b) {
376 76 : matched_members.push_back(std::make_pair(&ta.struct_type.member_seq[i],
377 76 : &tb.struct_type.member_seq[j]));
378 76 : break;
379 : }
380 : }
381 : }
382 :
383 : // There is at least one member m1 of T1 and one corresponding member
384 : // m2 of T2 such that m1.id == m2.id
385 74 : if (matched_members.size() == 0) {
386 1 : return false;
387 : }
388 :
389 : // For any member m2 of T2, if there is a member m1 of T1 with the same
390 : // ID, then the type KeyErased(m1.type) is-assignable-from the type
391 : // KeyErased(m2.type).
392 : // For any non-aggregated type T, we consider that KeyErased(T) = T
393 : // (whereas the spec only defines KeyErased for aggregated types).
394 : // Consequently, this rule applies to any pair of members m2 of T2 and
395 : // m1 of T1 with the same ID.
396 231 : for (size_t i = 0; i < matched_members.size(); ++i) {
397 168 : const CommonStructMember& member = matched_members[i].second->common;
398 168 : const MinimalTypeObject* toa = 0;
399 168 : const MinimalTypeObject* tob = 0;
400 168 : bool aggregated_type_matched = false;
401 168 : if (get_struct_member(tob, member)) {
402 20 : if (!get_struct_member(toa, matched_members[i].first->common)) {
403 10 : return false;
404 : }
405 20 : aggregated_type_matched = true;
406 148 : } else if (get_union_member(tob, member)) {
407 4 : if (!get_union_member(toa, matched_members[i].first->common)) {
408 0 : return false;
409 : }
410 4 : aggregated_type_matched = true;
411 : }
412 :
413 168 : if (aggregated_type_matched) {
414 24 : MinimalTypeObject key_erased_a = *toa, key_erased_b = *tob;
415 24 : erase_key(key_erased_a);
416 24 : erase_key(key_erased_b);
417 24 : if (!assignable(TypeObject(key_erased_a), TypeObject(key_erased_b))) {
418 4 : return false;
419 : }
420 172 : } else if (!assignable(matched_members[i].first->common.member_type_id,
421 144 : matched_members[i].second->common.member_type_id)) {
422 6 : return false;
423 : }
424 : }
425 :
426 : // Members for which both optional is false and must_understand is true in
427 : // either T1 or T2 appear in both T1 and T2.
428 : // Members marked as key in either T1 or T2 appear in both T1 and T2.
429 221 : for (unsigned i = 0; i < ta.struct_type.member_seq.length(); ++i) {
430 158 : const MemberFlag& flags = ta.struct_type.member_seq[i].common.member_flags;
431 158 : MemberId id = ta.struct_type.member_seq[i].common.member_id;
432 158 : bool found = false;
433 158 : if ((flags & (IS_OPTIONAL | IS_MUST_UNDERSTAND)) == IS_MUST_UNDERSTAND) {
434 32 : for (size_t j = 0; j < matched_members.size(); ++j) {
435 32 : if (id == matched_members[j].first->common.member_id) {
436 16 : found = true;
437 16 : break;
438 : }
439 : }
440 16 : if (!found) {
441 0 : return false;
442 : }
443 : }
444 :
445 158 : found = false;
446 158 : if ((flags & IS_KEY) == IS_KEY) {
447 41 : for (size_t j = 0; j < matched_members.size(); ++j) {
448 41 : if (id == matched_members[j].first->common.member_id) {
449 41 : found = true;
450 41 : break;
451 : }
452 : }
453 41 : if (!found) {
454 0 : return false;
455 : }
456 : }
457 : }
458 :
459 231 : for (unsigned i = 0; i < tb.struct_type.member_seq.length(); ++i) {
460 168 : const MemberFlag& flags = tb.struct_type.member_seq[i].common.member_flags;
461 168 : MemberId id = tb.struct_type.member_seq[i].common.member_id;
462 168 : bool found = false;
463 168 : if ((flags & (IS_OPTIONAL | IS_MUST_UNDERSTAND)) == IS_MUST_UNDERSTAND) {
464 16 : for (size_t j = 0; j < matched_members.size(); ++j) {
465 16 : if (id == matched_members[j].second->common.member_id) {
466 16 : found = true;
467 16 : break;
468 : }
469 : }
470 16 : if (!found) {
471 0 : return false;
472 : }
473 : }
474 :
475 168 : found = false;
476 168 : if ((flags & IS_KEY) == IS_KEY) {
477 341 : for (size_t j = 0; j < matched_members.size(); ++j) {
478 341 : if (id == matched_members[j].second->common.member_id) {
479 99 : found = true;
480 99 : break;
481 : }
482 : }
483 99 : if (!found) {
484 0 : return false;
485 : }
486 : }
487 : }
488 :
489 : // For any string key member m2 in T2, the m1 member of T1 with the
490 : // same member ID verifies m1.type.length >= m2.type.length
491 220 : for (size_t i = 0; i < matched_members.size(); ++i) {
492 158 : const CommonStructMember& member = matched_members[i].second->common;
493 158 : MemberFlag flags = member.member_flags;
494 : LBound bound_a, bound_b;
495 158 : if ((flags & IS_KEY) == IS_KEY && get_string_bound(bound_b, member)) {
496 15 : if (!get_string_bound(bound_a, matched_members[i].first->common)) {
497 1 : return false;
498 : }
499 15 : if (bound_a < bound_b) {
500 1 : return false;
501 : }
502 : }
503 : }
504 :
505 : // For any enumerated key member m2 in T2, the m1 member of T1 with
506 : // the same member ID verifies that all literals in m2.type appear as
507 : // literals in m1.type
508 218 : for (size_t i = 0; i < matched_members.size(); ++i) {
509 157 : const CommonStructMember& member = matched_members[i].second->common;
510 157 : MemberFlag flags = member.member_flags;
511 255 : if ((flags & IS_KEY) == IS_KEY &&
512 98 : EK_MINIMAL == member.member_type_id.kind()) {
513 50 : const MinimalTypeObject& tob = lookup_minimal(member.member_type_id);
514 50 : if (TK_ENUM == tob.kind) {
515 13 : if (!struct_rule_enum_key(tob, matched_members[i].first->common)) {
516 1 : return false;
517 : }
518 37 : } else if (TK_ALIAS == tob.kind) {
519 0 : const TypeIdentifier& base_b = get_base_type(tob);
520 0 : if (EK_MINIMAL == base_b.kind()) {
521 0 : const MinimalTypeObject& base_obj_b = lookup_minimal(base_b);
522 0 : if (TK_ENUM == base_obj_b.kind &&
523 0 : !struct_rule_enum_key(base_obj_b, matched_members[i].first->common)) {
524 0 : return false;
525 : }
526 : }
527 : }
528 : }
529 : }
530 :
531 : // For any sequence or map key member m2 in T2, the m1 member of T1
532 : // with the same member ID verifies m1.type.length >= m2.type.length
533 215 : for (size_t i = 0; i < matched_members.size(); ++i) {
534 156 : const CommonStructMember& member = matched_members[i].second->common;
535 156 : MemberFlag flags = member.member_flags;
536 : LBound bound_a, bound_b;
537 156 : if ((flags & IS_KEY) == IS_KEY) {
538 97 : if (get_sequence_bound(bound_b, member)) {
539 19 : if (!get_sequence_bound(bound_a, matched_members[i].first->common)) {
540 2 : return false;
541 : }
542 19 : if (bound_a < bound_b) {
543 1 : return false;
544 : }
545 78 : } else if (get_map_bound(bound_b, member)) {
546 11 : if (!get_map_bound(bound_a, matched_members[i].first->common)) {
547 0 : return false;
548 : }
549 11 : if (bound_a < bound_b) {
550 1 : return false;
551 : }
552 : }
553 : }
554 : }
555 :
556 : // For any structure or union key member m2 in T2, the m1 member
557 : // of T1 with the same member ID verifies that KeyHolder(m1.type)
558 : // is-assignable-from KeyHolder(m2.type)
559 213 : for (size_t i = 0; i < matched_members.size(); ++i) {
560 154 : const CommonStructMember& member = matched_members[i].second->common;
561 154 : MemberFlag flags = member.member_flags;
562 154 : if ((flags & IS_KEY) == IS_KEY) {
563 95 : const MinimalTypeObject* toa = 0;
564 95 : const MinimalTypeObject* tob = 0;
565 95 : bool type_matched = false;
566 95 : if (get_struct_member(tob, member)) {
567 18 : if (!get_struct_member(toa, matched_members[i].first->common)) {
568 0 : return false;
569 : }
570 18 : type_matched = true;
571 77 : } else if (get_union_member(tob, member)) {
572 2 : if (!get_union_member(toa, matched_members[i].first->common)) {
573 0 : return false;
574 : }
575 2 : type_matched = true;
576 : }
577 :
578 95 : if (type_matched) {
579 20 : MinimalTypeObject key_holder_a = *toa, key_holder_b = *tob;
580 20 : hold_key(key_holder_a);
581 20 : hold_key(key_holder_b);
582 20 : if (!assignable(TypeObject(key_holder_a), TypeObject(key_holder_b))) {
583 0 : return false;
584 : }
585 :
586 : // For any union key member m2 in T2, the m1 member of T1 with the
587 : // same ID verifies that: for every discriminator value of m2.type
588 : // that selects a member m22 in m2.type, the discriminator value
589 : // selects a member m11 in m1.type that verifies KeyHolder(m11.type)
590 : // is-assignable-from KeyHolder(m22.type)
591 20 : if (TK_UNION == tob->kind) {
592 2 : const MinimalUnionMemberSeq& mseq_a = toa->union_type.member_seq;
593 2 : const MinimalUnionMemberSeq& mseq_b = tob->union_type.member_seq;
594 6 : for (unsigned j = 0; j < mseq_b.length(); ++j) {
595 4 : const UnionCaseLabelSeq& labels_b = mseq_b[j].common.label_seq;
596 12 : for (unsigned k = 0; k < mseq_a.length(); ++k) {
597 8 : const UnionCaseLabelSeq& labels_a = mseq_a[k].common.label_seq;
598 8 : bool matched = false;
599 14 : for (unsigned p = 0; p < labels_b.length(); ++p) {
600 34 : for (unsigned q = 0; q < labels_a.length(); ++q) {
601 28 : if (labels_b[p] == labels_a[q]) {
602 6 : const TypeIdentifier& tib = mseq_b[j].common.type_id;
603 6 : const TypeIdentifier& tia = mseq_a[k].common.type_id;
604 6 : MinimalTypeObject kh_a, kh_b;
605 6 : bool ret_b = hold_key(tib, kh_b);
606 6 : bool ret_a = hold_key(tia, kh_a);
607 12 : if ((ret_a && ret_b && !assignable(TypeObject(kh_a), TypeObject(kh_b))) ||
608 6 : (ret_a && !ret_b && !assignable(TypeObject(kh_a), tib)) ||
609 18 : (!ret_a && ret_b && !assignable(tia, TypeObject(kh_b))) ||
610 6 : (!ret_a && !ret_b && !assignable(tia, tib))) {
611 0 : return false;
612 : }
613 6 : matched = true;
614 6 : break;
615 12 : }
616 : } // labels_a
617 12 : if (matched) break;
618 : } // labels_b
619 : } // mseq_a
620 : } // mseq_b
621 : }
622 20 : }
623 : } // IS_KEY
624 : }
625 :
626 59 : return true;
627 76 : }
628 :
629 : /**
630 : * @brief The first type must be TK_STRUCTURE.
631 : * The second type can be anything.
632 : */
633 0 : bool TypeAssignability::assignable_struct(const MinimalTypeObject& ta,
634 : const TypeIdentifier& tb) const
635 : {
636 0 : if (EK_MINIMAL == tb.kind()) {
637 0 : const MinimalTypeObject& tob = lookup_minimal(tb);
638 0 : if (TK_STRUCTURE == tob.kind) {
639 0 : return assignable_struct(ta, tob);
640 0 : } else if (TK_ALIAS == tob.kind) {
641 0 : const TypeIdentifier& base = tob.alias_type.body.common.related_type;
642 0 : return assignable_struct(ta, base);
643 : }
644 0 : } else if (EK_COMPLETE == tb.kind()) {
645 : // Assuming tb.kind of EK_COMPLETE is not supported
646 0 : return false;
647 : }
648 :
649 0 : return false;
650 : }
651 :
652 : /**
653 : * @brief The first type must be TK_UNION.
654 : * The second type must not be TK_ALIAS.
655 : */
656 21 : bool TypeAssignability::assignable_union(const MinimalTypeObject& ta,
657 : const MinimalTypeObject& tb) const
658 : {
659 21 : if (TK_UNION != tb.kind) {
660 0 : return false;
661 : }
662 :
663 : // Extensibility kind must match
664 21 : const TypeFlag extensibility_mask = IS_FINAL | IS_APPENDABLE | IS_MUTABLE;
665 21 : if ((ta.union_type.union_flags & extensibility_mask) !=
666 21 : (tb.union_type.union_flags & extensibility_mask)) {
667 1 : return false;
668 : }
669 :
670 20 : OPENDDS_SET(ACE_CDR::Long) labels_set_a;
671 58 : for (unsigned i = 0; i < ta.union_type.member_seq.length(); ++i) {
672 38 : const UnionCaseLabelSeq& labels_a = ta.union_type.member_seq[i].common.label_seq;
673 38 : labels_set_a.insert(labels_a.members.begin(), labels_a.members.end());
674 : }
675 :
676 : // If extensibility is final, then the set of labels must be identical.
677 : // Assuming labels are mapped to values identically in both input types.
678 20 : if ((ta.union_type.union_flags & extensibility_mask) == IS_FINAL) {
679 8 : for (unsigned i = 0; i < tb.union_type.member_seq.length(); ++i) {
680 6 : const UnionCaseLabelSeq& labels_b = tb.union_type.member_seq[i].common.label_seq;
681 13 : for (unsigned j = 0; j < labels_b.length(); ++j) {
682 8 : if (labels_set_a.find(labels_b.members[j]) == labels_set_a.end()) {
683 1 : return false;
684 : }
685 7 : labels_set_a.erase(labels_b.members[j]);
686 : }
687 : }
688 2 : if (labels_set_a.size() > 0) {
689 0 : return false;
690 : }
691 : } else { // Must have at least one common label other than the default
692 : // This implementation assumes that the default member has IS_DEFAULT
693 : // flag turned on, but the label "default" does not map into a numeric
694 : // value for storing on the member's UnionCaseLabelSeq. Instead, only
695 : // the other labels, if any, for this default members will have their
696 : // numeric values stored in its UnionCaseLabelSeq.
697 17 : bool found = false;
698 20 : for (unsigned i = 0; i < tb.union_type.member_seq.length(); ++i) {
699 18 : const UnionCaseLabelSeq& labels_b = tb.union_type.member_seq[i].common.label_seq;
700 23 : for (unsigned j = 0; j < labels_b.length(); ++j) {
701 20 : if (labels_set_a.find(labels_b[j]) != labels_set_a.end()) {
702 15 : found = true;
703 15 : break;
704 : }
705 : }
706 18 : if (found) break;
707 : }
708 17 : if (!found) {
709 2 : return false;
710 : }
711 : }
712 :
713 : // Discriminator type must be one of these: (i) non-float primitive types,
714 : // or (ii) enumerated types, or (iii) an alias type that resolves to
715 : // one of the above two type kinds
716 17 : const TypeIdentifier& tia = ta.union_type.discriminator.common.type_id;
717 17 : const TypeIdentifier& tib = tb.union_type.discriminator.common.type_id;
718 17 : if (!strongly_assignable(tia, tib)) {
719 2 : return false;
720 : }
721 :
722 : // Both discriminators are keys or neither are keys
723 15 : const MemberFlag& flags_a = ta.union_type.discriminator.common.member_flags;
724 15 : const MemberFlag& flags_b = tb.union_type.discriminator.common.member_flags;
725 15 : if ((((flags_a & IS_KEY) == IS_KEY) && ((flags_b & IS_KEY) != IS_KEY)) ||
726 14 : (((flags_a & IS_KEY) != IS_KEY) && ((flags_b & IS_KEY) == IS_KEY))) {
727 1 : return false;
728 : }
729 :
730 : // Members with the same ID must have the same name, and vice versa
731 14 : if (!type_consistency_.ignore_member_names) {
732 11 : OPENDDS_MAP(MemberId, ACE_CDR::ULong) id_to_name_a;
733 11 : OPENDDS_MAP(ACE_CDR::ULong, MemberId) name_to_id_a;
734 32 : for (unsigned i = 0; i < ta.union_type.member_seq.length(); ++i) {
735 21 : MemberId id = ta.union_type.member_seq[i].common.member_id;
736 21 : const NameHash& h = ta.union_type.member_seq[i].detail.name_hash;
737 21 : ACE_CDR::ULong name = (h[0] << 24) | (h[1] << 16) | (h[2] << 8) | (h[3]);
738 21 : id_to_name_a[id] = name;
739 21 : name_to_id_a[name] = id;
740 : }
741 :
742 28 : for (unsigned i = 0; i < tb.union_type.member_seq.length(); ++i) {
743 19 : MemberId id = tb.union_type.member_seq[i].common.member_id;
744 19 : const NameHash& h = tb.union_type.member_seq[i].detail.name_hash;
745 19 : ACE_CDR::ULong name = (h[0] << 24) | (h[1] << 16) | (h[2] << 8) | (h[3]);
746 33 : if (id_to_name_a.find(id) != id_to_name_a.end() &&
747 14 : id_to_name_a[id] != name) {
748 2 : return false;
749 : }
750 :
751 32 : if (name_to_id_a.find(name) != name_to_id_a.end() &&
752 14 : name_to_id_a[name] != id) {
753 1 : return false;
754 : }
755 : }
756 13 : }
757 :
758 : // For all non-default labels in T2 that select some member in T1,
759 : // the type of the selected member in T1 is assignable from the
760 : // type of the T2 member
761 29 : for (unsigned i = 0; i < tb.union_type.member_seq.length(); ++i) {
762 20 : const UnionCaseLabelSeq& label_seq_b = tb.union_type.member_seq[i].common.label_seq;
763 53 : for (unsigned j = 0; j < ta.union_type.member_seq.length(); ++j) {
764 : // Consider a case when tb has multiple labels for a member, e.g.,
765 : // "LABEL1" and "LABEL2" are associated with a member of type MemberB,
766 : // and ta has two members, one has label "LABEL1" and
767 : // type MemberA1, and the other has label "LABEL2" and
768 : // type MemberA2. There are two possible ways to check assignability:
769 : // (i) check whether BOTH MemberA1 and MemberA2 are assignable from
770 : // MemberB since labels for MemberB match the labels of both MemberA1
771 : // and MemberA2 (i.e., all must be assignable), or (ii) check EITHER
772 : // MemberA1 OR MemberA2 is assignable from MemberB (i.e., one member
773 : // of ta that is assignable is sufficient). The spec does not clearly
774 : // say which way we should do it. For now we are going with method (i).
775 36 : const UnionCaseLabelSeq& label_seq_a = ta.union_type.member_seq[j].common.label_seq;
776 36 : bool matched = false;
777 56 : for (unsigned k = 0; k < label_seq_b.length(); ++k) {
778 106 : for (unsigned t = 0; t < label_seq_a.length(); ++t) {
779 86 : if (label_seq_b.members[k] == label_seq_a.members[t]) {
780 26 : const TypeIdentifier& tia = ta.union_type.member_seq[j].common.type_id;
781 26 : const TypeIdentifier& tib = tb.union_type.member_seq[i].common.type_id;
782 26 : if (!assignable(tia, tib)) {
783 3 : return false;
784 : }
785 23 : matched = true;
786 23 : break;
787 : }
788 : }
789 43 : if (matched) break;
790 : }
791 : }
792 : }
793 :
794 : // If any non-default labels of T1 that select the default member of T2,
795 : // the type of the member in T1 is assignable from the type of the default
796 : // member in T2
797 10 : for (unsigned i = 0; i < tb.union_type.member_seq.length(); ++i) {
798 9 : const UnionMemberFlag& flags_b = tb.union_type.member_seq[i].common.member_flags;
799 9 : if ((flags_b & IS_DEFAULT) == IS_DEFAULT) {
800 8 : const UnionCaseLabelSeq& label_seq_b = tb.union_type.member_seq[i].common.label_seq;
801 24 : for (unsigned j = 0; j < ta.union_type.member_seq.length(); ++j) {
802 16 : const UnionCaseLabelSeq& label_seq_a = ta.union_type.member_seq[j].common.label_seq;
803 16 : bool matched = false;
804 34 : for (unsigned k = 0; k < label_seq_a.length(); ++k) {
805 62 : for (unsigned t = 0; t < label_seq_b.length(); ++t) {
806 44 : if (label_seq_a[k] == label_seq_b[t]) {
807 10 : const TypeIdentifier& tia = ta.union_type.member_seq[j].common.type_id;
808 10 : const TypeIdentifier& tib = tb.union_type.member_seq[i].common.type_id;
809 10 : if (!assignable(tia, tib)) {
810 0 : return false;
811 : }
812 10 : matched = true;
813 10 : break;
814 : }
815 : }
816 28 : if (matched) break;
817 : }
818 : }
819 8 : break;
820 : }
821 : }
822 :
823 : // If T1 and T2 both have default labels, the type of T1's default member
824 : // is assignable from the type of T2's default member
825 18 : for (unsigned i = 0; i < ta.union_type.member_seq.length(); ++i) {
826 16 : const UnionMemberFlag& flags_a = ta.union_type.member_seq[i].common.member_flags;
827 16 : if ((flags_a & IS_DEFAULT) == IS_DEFAULT) {
828 7 : for (unsigned j = 0; j < tb.union_type.member_seq.length(); ++j) {
829 7 : const UnionMemberFlag& flags_b = tb.union_type.member_seq[j].common.member_flags;
830 7 : if ((flags_b & IS_DEFAULT) == IS_DEFAULT) {
831 7 : const TypeIdentifier& tia = ta.union_type.member_seq[i].common.type_id;
832 7 : const TypeIdentifier& tib = tb.union_type.member_seq[j].common.type_id;
833 7 : if (!assignable(tia, tib)) {
834 0 : return false;
835 : }
836 7 : break;
837 : }
838 : }
839 7 : break;
840 : }
841 : }
842 :
843 9 : return true;
844 20 : }
845 :
846 : /**
847 : * @brief The first type must be TK_UNION.
848 : * The second type can be anything.
849 : */
850 0 : bool TypeAssignability::assignable_union(const MinimalTypeObject& ta,
851 : const TypeIdentifier& tb) const
852 : {
853 0 : if (EK_MINIMAL == tb.kind()) {
854 0 : const MinimalTypeObject& tob = lookup_minimal(tb);
855 0 : if (TK_UNION == tob.kind) {
856 0 : return assignable_union(ta, tob);
857 0 : } else if (TK_ALIAS == tob.kind) {
858 0 : const TypeIdentifier& base = tob.alias_type.body.common.related_type;
859 0 : return assignable_union(ta, base);
860 : }
861 0 : } else if (EK_COMPLETE == tb.kind()) {
862 : // Assuming tb.kind of EK_COMPLETE is not supported
863 0 : return false;
864 : }
865 :
866 0 : return false;
867 : }
868 :
869 : /**
870 : * @brief The first type must be TK_BITSET.
871 : * The second type must not be TK_ALIAS.
872 : */
873 0 : bool TypeAssignability::assignable_bitset(const MinimalTypeObject&,
874 : const MinimalTypeObject&) const
875 : {
876 : // No rule for bitset in the spec
877 0 : return false;
878 : }
879 :
880 : /**
881 : * @brief The first type must be TK_BITSET.
882 : * The second type can be anything.
883 : */
884 0 : bool TypeAssignability::assignable_bitset(const MinimalTypeObject&,
885 : const TypeIdentifier&) const
886 : {
887 : // No rule for bitset in the spec
888 0 : return false;
889 : }
890 :
891 : /**
892 : * @brief The first type must be TK_SEQUENCE.
893 : * The second type must not be TK_ALIAS.
894 : */
895 59 : bool TypeAssignability::assignable_sequence(const MinimalTypeObject& ta,
896 : const MinimalTypeObject& tb) const
897 : {
898 59 : if (TK_SEQUENCE != tb.kind) {
899 0 : return false;
900 : }
901 118 : return strongly_assignable(ta.sequence_type.element.common.type,
902 59 : tb.sequence_type.element.common.type);
903 : }
904 :
905 : /**
906 : * @brief The first type must be TK_SEQUENCE.
907 : * The second type can be anything.
908 : */
909 22 : bool TypeAssignability::assignable_sequence(const MinimalTypeObject& ta,
910 : const TypeIdentifier& tb) const
911 : {
912 22 : if (TI_PLAIN_SEQUENCE_SMALL == tb.kind()) {
913 10 : return strongly_assignable(ta.sequence_type.element.common.type,
914 20 : *tb.seq_sdefn().element_identifier);
915 12 : } else if (TI_PLAIN_SEQUENCE_LARGE == tb.kind()) {
916 1 : return strongly_assignable(ta.sequence_type.element.common.type,
917 2 : *tb.seq_ldefn().element_identifier);
918 11 : } else if (EK_MINIMAL == tb.kind()) {
919 11 : const MinimalTypeObject& tob = lookup_minimal(tb);
920 11 : if (TK_SEQUENCE == tob.kind) {
921 11 : return assignable_sequence(ta, tob);
922 0 : } else if (TK_ALIAS == tob.kind) {
923 0 : const TypeIdentifier& base = tob.alias_type.body.common.related_type;
924 0 : return assignable_sequence(ta, base);
925 : }
926 0 : } else if (EK_COMPLETE == tb.kind()) {
927 : // Assuming tb.kind of EK_COMPLETE is not supported
928 0 : return false;
929 : }
930 :
931 0 : return false;
932 : }
933 :
934 : /**
935 : * @brief The first type must be TK_ARRAY.
936 : * The second type must not be TK_ALIAS.
937 : */
938 48 : bool TypeAssignability::assignable_array(const MinimalTypeObject& ta,
939 : const MinimalTypeObject& tb) const
940 : {
941 48 : if (TK_ARRAY != tb.kind) {
942 0 : return false;
943 : }
944 :
945 : // Bounds must match
946 48 : const LBoundSeq& bounds_a = ta.array_type.header.common.bound_seq;
947 48 : const LBoundSeq& bounds_b = tb.array_type.header.common.bound_seq;
948 48 : if (bounds_a.members.size() != bounds_b.members.size()) {
949 0 : return false;
950 : }
951 :
952 192 : for (unsigned i = 0; i < bounds_a.members.size(); ++i) {
953 144 : if (bounds_a.members[i] != bounds_b.members[i]) {
954 0 : return false;
955 : }
956 : }
957 96 : return strongly_assignable(ta.array_type.element.common.type,
958 48 : tb.array_type.element.common.type);
959 : }
960 :
961 : /**
962 : * @brief The first type must be TK_ARRAY.
963 : * The second type can be anything.
964 : */
965 2 : bool TypeAssignability::assignable_array(const MinimalTypeObject& ta,
966 : const TypeIdentifier& tb) const
967 : {
968 2 : const LBoundSeq& bounds_a = ta.array_type.header.common.bound_seq;
969 2 : if (TI_PLAIN_ARRAY_SMALL == tb.kind()) {
970 2 : const SBoundSeq& bounds_b = tb.array_sdefn().array_bound_seq;
971 2 : if (bounds_a.members.size() != bounds_b.members.size()) {
972 0 : return false;
973 : }
974 :
975 8 : for (unsigned i = 0; i < bounds_a.members.size(); ++i) {
976 6 : if (bounds_a.members[i] != static_cast<LBound>(bounds_b.members[i])) {
977 0 : return false;
978 : }
979 : }
980 :
981 2 : return strongly_assignable(ta.array_type.element.common.type,
982 4 : *tb.array_sdefn().element_identifier);
983 0 : } else if (TI_PLAIN_ARRAY_LARGE == tb.kind()) {
984 0 : const LBoundSeq& bounds_b = tb.array_ldefn().array_bound_seq;
985 0 : if (bounds_a.members.size() != bounds_b.members.size()) {
986 0 : return false;
987 : }
988 :
989 0 : for (unsigned i = 0; i < bounds_a.members.size(); ++i) {
990 0 : if (bounds_a.members[i] != bounds_b.members[i]) {
991 0 : return false;
992 : }
993 : }
994 0 : return strongly_assignable(ta.array_type.element.common.type,
995 0 : *tb.array_ldefn().element_identifier);
996 0 : } else if (EK_MINIMAL == tb.kind()) {
997 0 : const MinimalTypeObject& tob = lookup_minimal(tb);
998 0 : if (TK_ARRAY == tob.kind) {
999 0 : return assignable_array(ta, tob);
1000 0 : } else if (TK_ALIAS == tob.kind) {
1001 0 : const TypeIdentifier& base = tob.alias_type.body.common.related_type;
1002 0 : return assignable_array(ta, base);
1003 : }
1004 0 : } else if (EK_COMPLETE == tb.kind()) {
1005 : // Assuming tb.kind of EK_COMPLETE is not supported
1006 0 : return false;
1007 : }
1008 :
1009 0 : return false;
1010 : }
1011 :
1012 : /**
1013 : * @brief The first type must be TK_MAP.
1014 : * The second type must not be TK_ALIAS.
1015 : */
1016 55 : bool TypeAssignability::assignable_map(const MinimalTypeObject& ta,
1017 : const MinimalTypeObject& tb) const
1018 : {
1019 55 : if (TK_MAP != tb.kind) {
1020 0 : return false;
1021 : }
1022 110 : return strongly_assignable(ta.map_type.key.common.type,
1023 105 : tb.map_type.key.common.type) &&
1024 50 : strongly_assignable(ta.map_type.element.common.type,
1025 105 : tb.map_type.element.common.type);
1026 : }
1027 :
1028 : /**
1029 : * @brief The first type must be TK_MAP.
1030 : * The second type can be anything.
1031 : */
1032 14 : bool TypeAssignability::assignable_map(const MinimalTypeObject& ta,
1033 : const TypeIdentifier& tb) const
1034 : {
1035 14 : if (TI_PLAIN_MAP_SMALL == tb.kind()) {
1036 0 : return strongly_assignable(ta.map_type.key.common.type,
1037 0 : *tb.map_sdefn().key_identifier) &&
1038 0 : strongly_assignable(ta.map_type.element.common.type,
1039 0 : *tb.map_sdefn().element_identifier);
1040 14 : } else if (TI_PLAIN_MAP_LARGE == tb.kind()) {
1041 7 : return strongly_assignable(ta.map_type.key.common.type,
1042 20 : *tb.map_ldefn().key_identifier) &&
1043 6 : strongly_assignable(ta.map_type.element.common.type,
1044 13 : *tb.map_ldefn().element_identifier);
1045 7 : } else if (EK_MINIMAL == tb.kind()) {
1046 7 : const MinimalTypeObject& tob = lookup_minimal(tb);
1047 7 : if (TK_MAP == tob.kind) {
1048 7 : return assignable_map(ta, tob);
1049 0 : } else if (TK_ALIAS == tob.kind) {
1050 0 : const TypeIdentifier& base = tob.alias_type.body.common.related_type;
1051 0 : return assignable_map(ta, base);
1052 : }
1053 0 : } else if (EK_COMPLETE == tb.kind()) {
1054 : // Assuming tb.kind of EK_COMPLETE is not supported
1055 0 : return false;
1056 : }
1057 :
1058 0 : return false;
1059 : }
1060 :
1061 : /**
1062 : * @brief The first type must be TK_ENUM.
1063 : * The second type must not be TK_ALIAS.
1064 : */
1065 34 : bool TypeAssignability::assignable_enum(const MinimalTypeObject& ta,
1066 : const MinimalTypeObject& tb) const
1067 : {
1068 34 : if (TK_ENUM != tb.kind) {
1069 8 : return false;
1070 : }
1071 :
1072 : // Assuming that EnumTypeFlag is used and contains extensibility
1073 : // of the containing type.
1074 26 : const TypeFlag extensibility_mask = IS_FINAL | IS_APPENDABLE | IS_MUTABLE;
1075 26 : TypeFlag ta_ext = ta.enumerated_type.enum_flags & extensibility_mask;
1076 26 : TypeFlag tb_ext = tb.enumerated_type.enum_flags & extensibility_mask;
1077 26 : if (ta_ext != tb_ext &&
1078 : // Backwards compatibility.
1079 1 : ta_ext != 0 && tb_ext != 0) {
1080 1 : return false;
1081 : }
1082 :
1083 : // T1.bit_bound and T2.bit_bound must be equal (DDSXTY14-34)
1084 25 : if (ta.enumerated_type.header.common.bit_bound !=
1085 25 : tb.enumerated_type.header.common.bit_bound) {
1086 7 : return false;
1087 : }
1088 :
1089 18 : const size_t size_a = ta.enumerated_type.literal_seq.members.size();
1090 18 : const size_t size_b = tb.enumerated_type.literal_seq.members.size();
1091 18 : OPENDDS_MAP(ACE_CDR::ULong, ACE_CDR::Long) ta_name_to_value;
1092 85 : for (size_t i = 0; i < size_a; ++i) {
1093 67 : const NameHash& h = ta.enumerated_type.literal_seq.members[i].detail.name_hash;
1094 67 : ACE_CDR::ULong key_a = (h[0] << 24) | (h[1] << 16) | (h[2] << 8) | (h[3]);
1095 67 : ta_name_to_value[key_a] = ta.enumerated_type.literal_seq.members[i].common.value;
1096 : }
1097 :
1098 : // If extensibility is FINAL, both must have the same literals.
1099 18 : if (IS_FINAL == ta_ext) {
1100 1 : if (size_a != size_b) {
1101 0 : return false;
1102 : }
1103 :
1104 3 : for (size_t i = 0; i < size_b; ++i) {
1105 2 : const NameHash& h = tb.enumerated_type.literal_seq.members[i].detail.name_hash;
1106 2 : ACE_CDR::ULong key_b = (h[0] << 24) | (h[1] << 16) | (h[2] << 8) | (h[3]);
1107 :
1108 : // Literals that have the same name must have the same value.
1109 4 : if (ta_name_to_value.find(key_b) == ta_name_to_value.end() ||
1110 2 : ta_name_to_value[key_b] != tb.enumerated_type.literal_seq.members[i].common.value) {
1111 0 : return false;
1112 : }
1113 : }
1114 : } else {
1115 : // Any literals that have the same name also have the same value
1116 72 : for (size_t i = 0; i < size_b; ++i) {
1117 55 : const NameHash& h = tb.enumerated_type.literal_seq.members[i].detail.name_hash;
1118 55 : ACE_CDR::ULong key_b = (h[0] << 24) | (h[1] << 16) | (h[2] << 8) | (h[3]);
1119 107 : if (ta_name_to_value.find(key_b) != ta_name_to_value.end() &&
1120 52 : ta_name_to_value[key_b] != tb.enumerated_type.literal_seq.members[i].common.value) {
1121 0 : return false;
1122 : }
1123 : }
1124 :
1125 17 : OPENDDS_MAP(ACE_CDR::ULong, ACE_CDR::ULong) ta_value_to_name;
1126 82 : for (size_t i = 0; i < size_a; ++i) {
1127 65 : ACE_CDR::ULong value_a = ta.enumerated_type.literal_seq.members[i].common.value;
1128 65 : const NameHash& h = ta.enumerated_type.literal_seq.members[i].detail.name_hash;
1129 65 : ACE_CDR::ULong name_a = (h[0] << 24) | (h[1] << 16) | (h[2] << 8) | (h[3]);
1130 65 : ta_value_to_name[value_a] = name_a;
1131 : }
1132 :
1133 : // Any literals that have the same value also have the same name
1134 72 : for (size_t i = 0; i < size_b; ++i) {
1135 55 : ACE_CDR::ULong value_b = tb.enumerated_type.literal_seq.members[i].common.value;
1136 55 : const NameHash& h = tb.enumerated_type.literal_seq.members[i].detail.name_hash;
1137 55 : ACE_CDR::ULong name_b = (h[0] << 24) | (h[1] << 16) | (h[2] << 8) | (h[3]);
1138 107 : if (ta_value_to_name.find(value_b) != ta_value_to_name.end() &&
1139 52 : ta_value_to_name[value_b] != name_b) {
1140 0 : return false;
1141 : }
1142 : }
1143 17 : }
1144 :
1145 18 : return true;
1146 18 : }
1147 :
1148 : /**
1149 : * @brief The first type must be TK_ENUM.
1150 : * The second type can be anything.
1151 : */
1152 44 : bool TypeAssignability::assignable_enum(const MinimalTypeObject& ta,
1153 : const TypeIdentifier& tb) const
1154 : {
1155 44 : if (EK_MINIMAL == tb.kind()) {
1156 17 : const MinimalTypeObject& tob = lookup_minimal(tb);
1157 17 : if (TK_ENUM == tob.kind) {
1158 17 : return assignable_enum(ta, tob);
1159 0 : } else if (TK_ALIAS == tob.kind) {
1160 0 : const TypeIdentifier& base = tob.alias_type.body.common.related_type;
1161 0 : return assignable_enum(ta, base);
1162 : }
1163 27 : } else if (EK_COMPLETE == tb.kind()) {
1164 : // Assuming tb.kind of EK_COMPLETE is not supported
1165 1 : return false;
1166 : }
1167 :
1168 26 : return false;
1169 : }
1170 :
1171 : /**
1172 : * @brief The first type must be TK_BITMASK.
1173 : * The second type must not be TK_ALIAS.
1174 : */
1175 16 : bool TypeAssignability::assignable_bitmask(const MinimalTypeObject& ta,
1176 : const MinimalTypeObject& tb) const
1177 : {
1178 16 : if (TK_BITMASK == tb.kind) {
1179 8 : return ta.bitmask_type.header.common.bit_bound ==
1180 8 : tb.bitmask_type.header.common.bit_bound;
1181 : }
1182 :
1183 8 : return false;
1184 : }
1185 :
1186 : /**
1187 : * @brief The first type must be TK_BITMASK.
1188 : * The second type can be anything.
1189 : */
1190 51 : bool TypeAssignability::assignable_bitmask(const MinimalTypeObject& ta,
1191 : const TypeIdentifier& tb) const
1192 : {
1193 51 : BitBound ta_bit_bound = ta.bitmask_type.header.common.bit_bound;
1194 51 : if (TK_UINT8 == tb.kind()) {
1195 5 : return 1 <= ta_bit_bound && ta_bit_bound <= 8;
1196 46 : } else if (TK_UINT16 == tb.kind()) {
1197 7 : return 9 <= ta_bit_bound && ta_bit_bound <= 16;
1198 39 : } else if (TK_UINT32 == tb.kind()) {
1199 8 : return 17 <= ta_bit_bound && ta_bit_bound <= 32;
1200 31 : } else if (TK_UINT64 == tb.kind()) {
1201 4 : return 33 <= ta_bit_bound && ta_bit_bound <= 64;
1202 27 : } else if (EK_MINIMAL == tb.kind()) {
1203 4 : const MinimalTypeObject& tob = lookup_minimal(tb);
1204 4 : if (TK_BITMASK == tob.kind) {
1205 4 : return assignable_bitmask(ta, tob);
1206 0 : } else if (TK_ALIAS == tob.kind) {
1207 0 : const TypeIdentifier& base = tob.alias_type.body.common.related_type;
1208 0 : return assignable_bitmask(ta, base);
1209 : }
1210 23 : } else if (EK_COMPLETE == tb.kind()) {
1211 : // Assuming tb.kind of EK_COMPLETE is not supported
1212 1 : return false;
1213 : }
1214 :
1215 22 : return false;
1216 : }
1217 :
1218 : /**
1219 : * @brief The first type must be a future extension type kind.
1220 : * The second type must not be TK_ALIAS.
1221 : */
1222 0 : bool TypeAssignability::assignable_extended(const MinimalTypeObject&,
1223 : const MinimalTypeObject&) const
1224 : {
1225 : // Future extensions
1226 0 : return false;
1227 : }
1228 :
1229 : /**
1230 : * @brief The first type must be a primitive type.
1231 : * The second type can be anything.
1232 : */
1233 167 : bool TypeAssignability::assignable_primitive(const TypeIdentifier& ta,
1234 : const TypeIdentifier& tb) const
1235 : {
1236 167 : if (ta.kind() == tb.kind()) {
1237 0 : return true;
1238 : }
1239 :
1240 167 : if (EK_MINIMAL == tb.kind()) {
1241 32 : const MinimalTypeObject& tob = lookup_minimal(tb);
1242 32 : if (TK_BITMASK == tob.kind) {
1243 32 : return assignable_primitive(ta, tob);
1244 0 : } else if (TK_ALIAS == tob.kind) {
1245 0 : const TypeIdentifier& base = tob.alias_type.body.common.related_type;
1246 0 : return assignable_primitive(ta, base);
1247 : }
1248 135 : } else if (EK_COMPLETE == tb.kind()) {
1249 : // Assuming tb.kind of EK_COMPLETE is not supported
1250 0 : return false;
1251 : }
1252 :
1253 135 : return false;
1254 : }
1255 :
1256 : /**
1257 : * @brief The first type must be a primitive type.
1258 : * The second type must not be TK_ALIAS.
1259 : */
1260 40 : bool TypeAssignability::assignable_primitive(const TypeIdentifier& ta,
1261 : const MinimalTypeObject& tb) const
1262 : {
1263 111 : if (TK_BITMASK != tb.kind ||
1264 101 : !(TK_UINT8 == ta.kind() || TK_UINT16 == ta.kind() ||
1265 30 : TK_UINT32 == ta.kind() || TK_UINT64 == ta.kind())) {
1266 0 : return false;
1267 : }
1268 :
1269 40 : BitBound bit_bound = tb.bitmask_type.header.common.bit_bound;
1270 40 : if (TK_UINT8 == ta.kind()) {
1271 9 : return 1 <= bit_bound && bit_bound <= 8;
1272 31 : } else if (TK_UINT16 == ta.kind()) {
1273 11 : return 9 <= bit_bound && bit_bound <= 16;
1274 20 : } else if (TK_UINT32 == ta.kind()) {
1275 10 : return 17 <= bit_bound && bit_bound <= 32;
1276 : } else { // TK_UINT64
1277 10 : return 33 <= bit_bound && bit_bound <= 64;
1278 : }
1279 : }
1280 :
1281 : /**
1282 : * @brief The first type must be a string type.
1283 : * The second type can be anything.
1284 : */
1285 241 : bool TypeAssignability::assignable_string(const TypeIdentifier& ta,
1286 : const TypeIdentifier& tb) const
1287 : {
1288 241 : if (TI_STRING8_SMALL == tb.kind() || TI_STRING8_LARGE == tb.kind()) {
1289 102 : if (TI_STRING8_SMALL == ta.kind() || TI_STRING8_LARGE == ta.kind()) {
1290 88 : return true;
1291 : }
1292 139 : } else if (TI_STRING16_SMALL == tb.kind() || TI_STRING16_LARGE == tb.kind()) {
1293 43 : if (TI_STRING16_SMALL == ta.kind() || TI_STRING16_LARGE == ta.kind()) {
1294 32 : return true;
1295 : }
1296 96 : } else if (EK_MINIMAL == tb.kind()) {
1297 4 : const MinimalTypeObject& tob = lookup_minimal(tb);
1298 4 : if (TK_ALIAS == tob.kind) {
1299 0 : const TypeIdentifier& base = tob.alias_type.body.common.related_type;
1300 0 : return assignable_string(ta, base);
1301 : }
1302 92 : } else if (EK_COMPLETE == tb.kind()) {
1303 : // Assuming tb.kind of EK_COMPLETE is not supported
1304 4 : return false;
1305 : }
1306 :
1307 117 : return false;
1308 : }
1309 :
1310 : /**
1311 : * @brief The first type must be a string type.
1312 : * The second type must not be TK_ALIAS.
1313 : */
1314 0 : bool TypeAssignability::assignable_string(const TypeIdentifier&,
1315 : const MinimalTypeObject&) const
1316 : {
1317 : // The second type cannot be string since string types do not have
1318 : // type object. Thus the first type is not assignable from the second type.
1319 0 : return false;
1320 : }
1321 :
1322 : /**
1323 : * @brief The first type must be a plain sequence type.
1324 : * The second type can be anything.
1325 : */
1326 13 : bool TypeAssignability::assignable_plain_sequence(const TypeIdentifier& ta,
1327 : const TypeIdentifier& tb) const
1328 : {
1329 13 : if (TI_PLAIN_SEQUENCE_SMALL == tb.kind()) {
1330 2 : if (TI_PLAIN_SEQUENCE_SMALL == ta.kind()) {
1331 0 : return strongly_assignable(*ta.seq_sdefn().element_identifier,
1332 0 : *tb.seq_sdefn().element_identifier);
1333 : } else { // TI_PLAIN_SEQUENCE_LARGE
1334 2 : return strongly_assignable(*ta.seq_ldefn().element_identifier,
1335 4 : *tb.seq_sdefn().element_identifier);
1336 : }
1337 11 : } else if (TI_PLAIN_SEQUENCE_LARGE == tb.kind()) {
1338 9 : if (TI_PLAIN_SEQUENCE_SMALL == ta.kind()) {
1339 9 : return strongly_assignable(*ta.seq_sdefn().element_identifier,
1340 18 : *tb.seq_ldefn().element_identifier);
1341 : } else { // TI_PLAIN_SEQUENCE_LARGE
1342 0 : return strongly_assignable(*ta.seq_ldefn().element_identifier,
1343 0 : *tb.seq_ldefn().element_identifier);
1344 : }
1345 2 : } else if (EK_MINIMAL == tb.kind()) {
1346 2 : const MinimalTypeObject& tob = lookup_minimal(tb);
1347 2 : if (TK_SEQUENCE == tob.kind) {
1348 2 : return assignable_plain_sequence(ta, tob);
1349 0 : } else if (TK_ALIAS == tob.kind) {
1350 0 : const TypeIdentifier& base = tob.alias_type.body.common.related_type;
1351 0 : return assignable_plain_sequence(ta, base);
1352 : }
1353 0 : } else if (EK_COMPLETE == tb.kind()) {
1354 : // Can tb.kind be EK_COMPLETE? More generally, can a MinimalTypeObject
1355 : // depend on a TypeIdentifier that identifies a class of types which have
1356 : // COMPLETE equivalence relation.
1357 : // For now, assuming tb.kind of EK_COMPLETE is not supported.
1358 0 : return false;
1359 : }
1360 :
1361 0 : return false;
1362 : }
1363 :
1364 : /**
1365 : * @brief The first type must be a plain sequence type.
1366 : * The second type must not be TK_ALIAS.
1367 : */
1368 4 : bool TypeAssignability::assignable_plain_sequence(const TypeIdentifier& ta,
1369 : const MinimalTypeObject& tb) const
1370 : {
1371 4 : if (TK_SEQUENCE == tb.kind) {
1372 4 : if (TI_PLAIN_SEQUENCE_SMALL == ta.kind()) {
1373 4 : return strongly_assignable(*ta.seq_sdefn().element_identifier,
1374 8 : tb.sequence_type.element.common.type);
1375 : } else { // TI_PLAIN_SEQUENCE_LARGE
1376 0 : return strongly_assignable(*ta.seq_ldefn().element_identifier,
1377 0 : tb.sequence_type.element.common.type);
1378 : }
1379 : }
1380 :
1381 0 : return false;
1382 : }
1383 :
1384 : /**
1385 : * @brief The first type must be a plain array type.
1386 : * The second type can be anything.
1387 : */
1388 11 : bool TypeAssignability::assignable_plain_array(const TypeIdentifier& ta,
1389 : const TypeIdentifier& tb) const
1390 : {
1391 11 : if (TI_PLAIN_ARRAY_SMALL == tb.kind()) {
1392 3 : const Sequence<SBound>& bounds_b = tb.array_sdefn().array_bound_seq;
1393 3 : if (TI_PLAIN_ARRAY_SMALL == ta.kind()) {
1394 3 : const Sequence<SBound>& bounds_a = ta.array_sdefn().array_bound_seq;
1395 3 : if (bounds_a.members.size() != bounds_b.members.size()) {
1396 0 : return false;
1397 : }
1398 :
1399 12 : for (size_t i = 0; i < bounds_a.members.size(); ++i) {
1400 9 : if (bounds_a.members[i] != bounds_b.members[i]) {
1401 0 : return false;
1402 : }
1403 : }
1404 :
1405 3 : return strongly_assignable(*ta.array_sdefn().element_identifier,
1406 6 : *tb.array_sdefn().element_identifier);
1407 : } else { // TI_PLAIN_ARRAY_LARGE
1408 0 : const Sequence<LBound>& bounds_a = ta.array_ldefn().array_bound_seq;
1409 0 : if (bounds_a.members.size() != bounds_b.members.size()) {
1410 0 : return false;
1411 : }
1412 :
1413 0 : for (size_t i = 0; i < bounds_a.members.size(); ++i) {
1414 0 : if (bounds_a.members[i] != static_cast<LBound>(bounds_b.members[i])) {
1415 0 : return false;
1416 : }
1417 : }
1418 :
1419 0 : return strongly_assignable(*ta.array_ldefn().element_identifier,
1420 0 : *tb.array_sdefn().element_identifier);
1421 : }
1422 8 : } else if (TI_PLAIN_ARRAY_LARGE == tb.kind()) {
1423 6 : const Sequence<LBound>& bounds_b = tb.array_ldefn().array_bound_seq;
1424 6 : if (TI_PLAIN_ARRAY_SMALL == ta.kind()) {
1425 6 : const Sequence<SBound>& bounds_a = ta.array_sdefn().array_bound_seq;
1426 6 : if (bounds_a.members.size() != bounds_b.members.size()) {
1427 0 : return false;
1428 : }
1429 :
1430 22 : for (size_t i = 0; i < bounds_a.members.size(); ++i) {
1431 18 : if (static_cast<LBound>(bounds_a.members[i]) != bounds_b.members[i]) {
1432 2 : return false;
1433 : }
1434 : }
1435 :
1436 4 : return strongly_assignable(*ta.array_sdefn().element_identifier,
1437 8 : *tb.array_ldefn().element_identifier);
1438 : } else { // TI_PLAIN_ARRAY_LARGE
1439 0 : const Sequence<LBound>& bounds_a = ta.array_ldefn().array_bound_seq;
1440 0 : if (bounds_a.members.size() != bounds_b.members.size()) {
1441 0 : return false;
1442 : }
1443 :
1444 0 : for (size_t i = 0; i < bounds_a.members.size(); ++i) {
1445 0 : if (bounds_a.members[i] != bounds_b.members[i]) {
1446 0 : return false;
1447 : }
1448 : }
1449 :
1450 0 : return strongly_assignable(*ta.array_ldefn().element_identifier,
1451 0 : *tb.array_ldefn().element_identifier);
1452 : }
1453 2 : } else if (EK_MINIMAL == tb.kind()) {
1454 2 : const MinimalTypeObject& tob = lookup_minimal(tb);
1455 2 : if (TK_ARRAY == tob.kind) {
1456 2 : return assignable_plain_array(ta, tob);
1457 0 : } else if (TK_ALIAS == tob.kind) {
1458 0 : const TypeIdentifier& base = tob.alias_type.body.common.related_type;
1459 0 : return assignable_plain_array(ta, base);
1460 : }
1461 0 : } else if (EK_COMPLETE == tb.kind()) {
1462 : // Assuming tb.kind of EK_COMPLETE is not supported (similar to the way
1463 : // assignability for plain sequences and plain maps are being handled)
1464 0 : return false;
1465 : }
1466 :
1467 0 : return false;
1468 : }
1469 :
1470 : /**
1471 : * @brief The first type must be a plain array type.
1472 : * The second type must not be TK_ALIAS.
1473 : */
1474 4 : bool TypeAssignability::assignable_plain_array(const TypeIdentifier& ta,
1475 : const MinimalTypeObject& tb) const
1476 : {
1477 4 : if (TK_ARRAY == tb.kind) {
1478 4 : const Sequence<LBound>& bounds_b = tb.array_type.header.common.bound_seq;
1479 4 : if (TI_PLAIN_ARRAY_SMALL == ta.kind()) {
1480 4 : const Sequence<SBound>& bounds_a = ta.array_sdefn().array_bound_seq;
1481 4 : if (bounds_a.members.size() != bounds_b.members.size()) {
1482 0 : return false;
1483 : }
1484 :
1485 16 : for (size_t i = 0; i < bounds_a.members.size(); ++i) {
1486 12 : if (static_cast<LBound>(bounds_a.members[i]) != bounds_b.members[i]) {
1487 0 : return false;
1488 : }
1489 : }
1490 :
1491 4 : return strongly_assignable(*ta.array_sdefn().element_identifier,
1492 8 : tb.array_type.element.common.type);
1493 : } else { // TI_PLAIN_ARRAY_LARGE
1494 0 : const Sequence<LBound>& bounds_a = ta.array_ldefn().array_bound_seq;
1495 0 : if (bounds_a.members.size() != bounds_b.members.size()) {
1496 0 : return false;
1497 : }
1498 :
1499 0 : for (size_t i = 0; i < bounds_a.members.size(); ++i) {
1500 0 : if (bounds_a.members[i] != bounds_b.members[i]) {
1501 0 : return false;
1502 : }
1503 : }
1504 :
1505 0 : return strongly_assignable(*ta.array_ldefn().element_identifier,
1506 0 : tb.array_type.element.common.type);
1507 : }
1508 : }
1509 :
1510 0 : return false;
1511 : }
1512 :
1513 : /**
1514 : * @brief The first type must be a plain map type.
1515 : * The second type can be anything.
1516 : */
1517 10 : bool TypeAssignability::assignable_plain_map(const TypeIdentifier& ta,
1518 : const TypeIdentifier& tb) const
1519 : {
1520 10 : if (TI_PLAIN_MAP_SMALL == tb.kind()) {
1521 4 : if (TI_PLAIN_MAP_SMALL == ta.kind()) {
1522 0 : return strongly_assignable(*ta.map_sdefn().key_identifier,
1523 0 : *tb.map_sdefn().key_identifier) &&
1524 0 : strongly_assignable(*ta.map_sdefn().element_identifier,
1525 0 : *tb.map_sdefn().element_identifier);
1526 : } else { // TI_PLAIN_MAP_LARGE
1527 4 : return strongly_assignable(*ta.map_ldefn().key_identifier,
1528 10 : *tb.map_sdefn().key_identifier) &&
1529 2 : strongly_assignable(*ta.map_ldefn().element_identifier,
1530 6 : *tb.map_sdefn().element_identifier);
1531 : }
1532 6 : } else if (TI_PLAIN_MAP_LARGE == tb.kind()) {
1533 4 : if (TI_PLAIN_MAP_SMALL == ta.kind()) {
1534 4 : return strongly_assignable(*ta.map_sdefn().key_identifier,
1535 11 : *tb.map_ldefn().key_identifier) &&
1536 3 : strongly_assignable(*ta.map_sdefn().element_identifier,
1537 7 : *tb.map_ldefn().element_identifier);
1538 : } else { // TI_PLAIN_MAP_LARGE
1539 0 : return strongly_assignable(*ta.map_ldefn().key_identifier,
1540 0 : *tb.map_ldefn().key_identifier) &&
1541 0 : strongly_assignable(*ta.map_ldefn().element_identifier,
1542 0 : *tb.map_ldefn().element_identifier);
1543 : }
1544 2 : } else if (EK_MINIMAL == tb.kind()) {
1545 2 : const MinimalTypeObject& tob = lookup_minimal(tb);
1546 2 : if (TK_MAP == tob.kind) {
1547 2 : return assignable_plain_map(ta, tob);
1548 0 : } else if (TK_ALIAS == tob.kind) {
1549 0 : const TypeIdentifier& base = tob.alias_type.body.common.related_type;
1550 0 : return assignable_plain_map(ta, base);
1551 : }
1552 0 : } else if (EK_COMPLETE == tb.kind()) {
1553 : // Assuming tb.kind of EK_COMPLETE is not supported (similar to how
1554 : // assignability for plain sequences and plain arrays are being handled)
1555 0 : return false;
1556 : }
1557 :
1558 0 : return false;
1559 : }
1560 :
1561 : /**
1562 : * @brief The first type must be a plain map type.
1563 : * The second type must not be TK_ALIAS.
1564 : */
1565 4 : bool TypeAssignability::assignable_plain_map(const TypeIdentifier& ta,
1566 : const MinimalTypeObject& tb) const
1567 : {
1568 4 : if (TK_MAP == tb.kind) {
1569 4 : if (TI_PLAIN_MAP_SMALL == ta.kind()) {
1570 0 : return strongly_assignable(*ta.map_sdefn().key_identifier,
1571 0 : tb.map_type.key.common.type) &&
1572 0 : strongly_assignable(*ta.map_sdefn().element_identifier,
1573 0 : tb.map_type.element.common.type);
1574 : } else { // TI_PLAIN_MAP_LARGE
1575 4 : return strongly_assignable(*ta.map_ldefn().key_identifier,
1576 12 : tb.map_type.key.common.type) &&
1577 4 : strongly_assignable(*ta.map_ldefn().element_identifier,
1578 8 : tb.map_type.element.common.type);
1579 : }
1580 : }
1581 :
1582 0 : return false;
1583 : }
1584 :
1585 : /**
1586 : * @brief If types T1 and T2 are equivalent using the MINIMAL relation,
1587 : * or alternatively if T1 is-assignable-from T2 and T2 is a delimited type,
1588 : * then T1 is said to be strongly assignable from T2
1589 : */
1590 364 : bool TypeAssignability::strongly_assignable(const TypeIdentifier& tia,
1591 : const TypeIdentifier& tib) const
1592 : {
1593 364 : if (equal_type_id(tia, tib)) {
1594 206 : return true;
1595 : }
1596 :
1597 158 : if (assignable(tia, tib) && is_delimited(tib)) {
1598 61 : return true;
1599 : }
1600 97 : return false;
1601 : }
1602 :
1603 : /**
1604 : * @brief Check whether two type identifiers are equal
1605 : */
1606 364 : bool TypeAssignability::equal_type_id(const TypeIdentifier& tia,
1607 : const TypeIdentifier& tib) const
1608 : {
1609 364 : switch (tia.kind()) {
1610 301 : case TK_BOOLEAN:
1611 : case TK_BYTE:
1612 : case TK_INT16:
1613 : case TK_INT32:
1614 : case TK_INT64:
1615 : case TK_UINT16:
1616 : case TK_UINT32:
1617 : case TK_UINT64:
1618 : case TK_FLOAT32:
1619 : case TK_FLOAT64:
1620 : case TK_FLOAT128:
1621 : case TK_INT8:
1622 : case TK_UINT8:
1623 : case TK_CHAR8:
1624 : case TK_CHAR16: {
1625 301 : if (tib.kind() == tia.kind()) {
1626 206 : return true;
1627 : }
1628 95 : break;
1629 : }
1630 45 : case TI_STRING8_SMALL:
1631 : case TI_STRING16_SMALL: {
1632 45 : if (tib.kind() == tia.kind() && tib.string_sdefn().bound == tia.string_sdefn().bound) {
1633 0 : return true;
1634 : }
1635 45 : break;
1636 : }
1637 5 : case TI_STRING8_LARGE:
1638 : case TI_STRING16_LARGE: {
1639 5 : if (tib.kind() == tia.kind() && tib.string_ldefn().bound == tia.string_ldefn().bound) {
1640 0 : return true;
1641 : }
1642 5 : break;
1643 : }
1644 5 : case TI_PLAIN_SEQUENCE_SMALL: {
1645 5 : if (tib.kind() == tia.kind() &&
1646 5 : tib.seq_sdefn().bound == tia.seq_sdefn().bound &&
1647 0 : equal_type_id(*tia.seq_sdefn().element_identifier,
1648 0 : *tib.seq_sdefn().element_identifier)) {
1649 0 : return true;
1650 : }
1651 5 : break;
1652 : }
1653 0 : case TI_PLAIN_SEQUENCE_LARGE: {
1654 0 : if (tib.kind() == tia.kind() &&
1655 0 : tib.seq_ldefn().bound == tia.seq_ldefn().bound &&
1656 0 : equal_type_id(*tia.seq_ldefn().element_identifier,
1657 0 : *tib.seq_ldefn().element_identifier)) {
1658 0 : return true;
1659 : }
1660 0 : break;
1661 : }
1662 6 : case TI_PLAIN_ARRAY_SMALL: {
1663 6 : if (tib.kind() == tia.kind()) {
1664 0 : const SBoundSeq& bounds_a = tia.array_sdefn().array_bound_seq;
1665 0 : const SBoundSeq& bounds_b = tia.array_sdefn().array_bound_seq;
1666 0 : if (bounds_a.members.size() != bounds_b.members.size()) {
1667 0 : break;
1668 : }
1669 0 : bool equal_bounds = true;
1670 0 : for (size_t i = 0; i < bounds_a.members.size(); ++i) {
1671 0 : if (bounds_a.members[i] != bounds_b.members[i]) {
1672 0 : equal_bounds = false;
1673 0 : break;
1674 : }
1675 : }
1676 0 : if (!equal_bounds) {
1677 0 : break;
1678 : }
1679 0 : if (equal_type_id(*tia.array_sdefn().element_identifier,
1680 0 : *tib.array_sdefn().element_identifier)) {
1681 0 : return true;
1682 : }
1683 : }
1684 6 : break;
1685 : }
1686 0 : case TI_PLAIN_ARRAY_LARGE: {
1687 0 : if (tib.kind() == tia.kind()) {
1688 0 : const LBoundSeq& bounds_a = tia.array_ldefn().array_bound_seq;
1689 0 : const LBoundSeq& bounds_b = tib.array_ldefn().array_bound_seq;
1690 0 : if (bounds_a.members.size() != bounds_b.members.size()) {
1691 0 : break;
1692 : }
1693 0 : bool equal_bounds = true;
1694 0 : for (size_t i = 0; i < bounds_a.members.size(); ++i) {
1695 0 : if (bounds_a.members[i] != bounds_b.members[i]) {
1696 0 : equal_bounds = false;
1697 0 : break;
1698 : }
1699 : }
1700 0 : if (!equal_bounds) {
1701 0 : break;
1702 : }
1703 0 : if (equal_type_id(*tia.array_ldefn().element_identifier,
1704 0 : *tib.array_ldefn().element_identifier)) {
1705 0 : return true;
1706 : }
1707 : }
1708 0 : break;
1709 : }
1710 2 : case TI_PLAIN_MAP_SMALL: {
1711 2 : if (tib.kind() == tia.kind() &&
1712 0 : tib.map_sdefn().bound == tia.map_sdefn().bound &&
1713 0 : equal_type_id(*tia.map_sdefn().key_identifier,
1714 2 : *tib.map_sdefn().key_identifier) &&
1715 0 : equal_type_id(*tia.map_sdefn().element_identifier,
1716 0 : *tib.map_sdefn().element_identifier)) {
1717 0 : return true;
1718 : }
1719 2 : break;
1720 : }
1721 0 : case TI_PLAIN_MAP_LARGE: {
1722 0 : if (tib.kind() == tia.kind() &&
1723 0 : tib.map_ldefn().bound == tia.map_ldefn().bound &&
1724 0 : equal_type_id(*tia.map_ldefn().key_identifier,
1725 0 : *tib.map_ldefn().key_identifier) &&
1726 0 : equal_type_id(*tia.map_ldefn().element_identifier,
1727 0 : *tib.map_ldefn().element_identifier)) {
1728 0 : return true;
1729 : }
1730 0 : break;
1731 : }
1732 0 : case TI_STRONGLY_CONNECTED_COMPONENT: {
1733 0 : if (tib.kind() == tia.kind() &&
1734 0 : tib.sc_component_id().scc_length == tia.sc_component_id().scc_length &&
1735 0 : tib.sc_component_id().sc_component_id.kind ==
1736 0 : tia.sc_component_id().sc_component_id.kind) {
1737 0 : const EquivalenceHash& ha = tia.sc_component_id().sc_component_id.hash;
1738 0 : const EquivalenceHash& hb = tib.sc_component_id().sc_component_id.hash;
1739 0 : bool equal_hash = true;
1740 0 : for (size_t i = 0; i < 14; ++i) {
1741 0 : if (ha[i] != hb[i]) {
1742 0 : equal_hash = false;
1743 0 : break;
1744 : }
1745 : }
1746 0 : if (equal_hash) {
1747 0 : return true;
1748 : }
1749 : }
1750 0 : break;
1751 : }
1752 0 : case EK_COMPLETE:
1753 : case EK_MINIMAL: {
1754 0 : if (tib.kind() == tia.kind()) {
1755 0 : bool equal_hash = true;
1756 0 : for (size_t i = 0; i < 14; ++i) {
1757 0 : if (tia.equivalence_hash()[i] != tib.equivalence_hash()[i]) {
1758 0 : equal_hash = false;
1759 0 : break;
1760 : }
1761 : }
1762 0 : if (equal_hash) {
1763 0 : return true;
1764 : }
1765 : }
1766 0 : break;
1767 : }
1768 0 : default:
1769 0 : return false; // Future extensions
1770 : }
1771 :
1772 158 : return false;
1773 : }
1774 :
1775 : /**
1776 : * @brief Concept of delimited types (sub-clause 7.2.4.2)
1777 : */
1778 69 : bool TypeAssignability::is_delimited(const TypeIdentifier& ti) const
1779 : {
1780 69 : switch (ti.kind()) {
1781 50 : case TK_BOOLEAN:
1782 : case TK_BYTE:
1783 : case TK_INT16:
1784 : case TK_INT32:
1785 : case TK_INT64:
1786 : case TK_UINT16:
1787 : case TK_UINT32:
1788 : case TK_UINT64:
1789 : case TK_FLOAT32:
1790 : case TK_FLOAT64:
1791 : case TK_FLOAT128:
1792 : case TK_INT8:
1793 : case TK_UINT8:
1794 : case TK_CHAR8:
1795 : case TK_CHAR16:
1796 : case TI_STRING8_SMALL:
1797 : case TI_STRING8_LARGE:
1798 : case TI_STRING16_SMALL:
1799 : case TI_STRING16_LARGE:
1800 50 : return true;
1801 0 : case TI_PLAIN_SEQUENCE_SMALL:
1802 0 : return is_delimited(*ti.seq_sdefn().element_identifier);
1803 3 : case TI_PLAIN_SEQUENCE_LARGE:
1804 3 : return is_delimited(*ti.seq_ldefn().element_identifier);
1805 0 : case TI_PLAIN_ARRAY_SMALL:
1806 0 : return is_delimited(*ti.array_sdefn().element_identifier);
1807 3 : case TI_PLAIN_ARRAY_LARGE:
1808 3 : return is_delimited(*ti.array_ldefn().element_identifier);
1809 0 : case TI_PLAIN_MAP_SMALL:
1810 0 : return is_delimited(*ti.map_sdefn().key_identifier) &&
1811 0 : is_delimited(*ti.map_sdefn().element_identifier);
1812 1 : case TI_PLAIN_MAP_LARGE:
1813 2 : return is_delimited(*ti.map_ldefn().key_identifier) &&
1814 2 : is_delimited(*ti.map_ldefn().element_identifier);
1815 12 : case EK_COMPLETE:
1816 : case EK_MINIMAL: {
1817 12 : const MinimalTypeObject& tobj = lookup_minimal(ti);
1818 12 : return is_delimited(tobj);
1819 : }
1820 0 : default:
1821 : // Future extensions and strongly connected components
1822 0 : return false;
1823 : }
1824 : }
1825 :
1826 : /**
1827 : * @brief Check if a type is delimited (sub-clause 7.2.4.2)
1828 : */
1829 12 : bool TypeAssignability::is_delimited(const MinimalTypeObject& tobj) const
1830 : {
1831 12 : switch (tobj.kind) {
1832 0 : case TK_ALIAS: {
1833 0 : const TypeIdentifier& base = get_base_type(tobj);
1834 0 : return is_delimited(base);
1835 : }
1836 0 : case TK_ANNOTATION:
1837 0 : return is_delimited_with_flags(tobj.annotation_type.annotation_flag);
1838 0 : case TK_STRUCTURE:
1839 0 : return is_delimited_with_flags(tobj.struct_type.struct_flags);
1840 0 : case TK_UNION:
1841 0 : return is_delimited_with_flags(tobj.union_type.union_flags);
1842 0 : case TK_BITSET:
1843 0 : return is_delimited_with_flags(tobj.bitset_type.bitset_flags);
1844 0 : case TK_SEQUENCE:
1845 0 : return is_delimited(tobj.sequence_type.element.common.type);
1846 0 : case TK_ARRAY:
1847 0 : return is_delimited(tobj.array_type.element.common.type);
1848 0 : case TK_MAP:
1849 0 : return is_delimited(tobj.map_type.key.common.type) &&
1850 0 : is_delimited(tobj.map_type.element.common.type);
1851 12 : case TK_ENUM:
1852 : case TK_BITMASK:
1853 12 : return true;
1854 0 : default:
1855 0 : return false; // Future extensions
1856 : }
1857 : }
1858 :
1859 0 : bool TypeAssignability::is_delimited_with_flags(TypeFlag flags) const
1860 : {
1861 0 : if ((flags & IS_FINAL) == IS_FINAL) {
1862 0 : return false;
1863 0 : } else if ((flags & IS_MUTABLE) == IS_MUTABLE) {
1864 : // Mutable types are delimited with both encoding versions 1 and 2
1865 0 : return true;
1866 : } else { // Default extensibility is APPENDABLE (7.3.1.2.1.8)
1867 : // Types with extensibility kind APPENDABLE are delimited
1868 : // if serialized with encoding version 2 and are not
1869 : // delimited if serialized with encoding version 1.
1870 : // We are supporting XCDR2 in this iteration.
1871 0 : return true;
1872 : }
1873 : }
1874 :
1875 : /**
1876 : * @brief Key-Erased type of an aggregated type T (struct or union)
1877 : * is constructed from T by removing the key designation from
1878 : * any member that has it (sub-clause 7.2.2.4.6).
1879 : * The input type must be either a struct or an union.
1880 : */
1881 48 : void TypeAssignability::erase_key(MinimalTypeObject& type) const
1882 : {
1883 48 : if (TK_STRUCTURE == type.kind) {
1884 40 : MinimalStructMemberSeq& mseq = type.struct_type.member_seq;
1885 129 : for (size_t i = 0; i < mseq.members.size(); ++i) {
1886 89 : MemberFlag& flags = mseq.members[i].common.member_flags;
1887 89 : if ((flags & IS_KEY) == IS_KEY) {
1888 40 : flags &= ~IS_KEY;
1889 : }
1890 : }
1891 8 : } else if (TK_UNION == type.kind) {
1892 8 : MemberFlag& flags = type.union_type.discriminator.common.member_flags;
1893 8 : if ((flags & IS_KEY) == IS_KEY) {
1894 2 : flags &= ~IS_KEY;
1895 : }
1896 : }
1897 48 : }
1898 :
1899 : /**
1900 : * @brief Key-Holder type of an aggregated type T (struct or union)
1901 : * is constructed from T (sub-clause 7.2.2.4.7)
1902 : * The input MinimalTypeObject is modified to get the corresponding KeyHolder type.
1903 : * The input must be either a struct or an union.
1904 : */
1905 40 : void TypeAssignability::hold_key(MinimalTypeObject& type) const
1906 : {
1907 40 : if (TK_STRUCTURE == type.kind) {
1908 36 : MinimalStructMemberSeq& mseq = type.struct_type.member_seq;
1909 36 : bool found_key = false;
1910 36 : for (size_t i = 0; i < mseq.members.size(); ++i) {
1911 36 : const MemberFlag& flags = mseq.members[i].common.member_flags;
1912 36 : if ((flags & IS_KEY) == IS_KEY) {
1913 36 : found_key = true;
1914 36 : break;
1915 : }
1916 : }
1917 :
1918 36 : if (found_key) { // Remove all non-key members
1919 36 : Sequence<MinimalStructMember> key_members;
1920 117 : for (size_t i = 0; i < mseq.members.size(); ++i) {
1921 81 : const MemberFlag& flags = mseq.members[i].common.member_flags;
1922 81 : if ((flags & IS_KEY) == IS_KEY) {
1923 36 : key_members.append(mseq.members[i]);
1924 : }
1925 : }
1926 36 : mseq.members = key_members.members;
1927 36 : } else { // Add a key designator to each member
1928 0 : for (size_t i = 0; i < mseq.members.size(); ++i) {
1929 0 : const MemberFlag& flags = mseq.members[i].common.member_flags;
1930 0 : if ((flags & IS_KEY) != IS_KEY) {
1931 0 : mseq.members[i].common.member_flags |= IS_KEY;
1932 : }
1933 : }
1934 : }
1935 4 : } else if (TK_UNION == type.kind) {
1936 4 : if ((type.union_type.discriminator.common.member_flags & IS_KEY) == IS_KEY) {
1937 : // Remove all non-key members
1938 0 : type.union_type.member_seq = Sequence<MinimalUnionMember>();
1939 : }
1940 : }
1941 40 : }
1942 :
1943 : /**
1944 : * @brief Return false if the input type does not have type object; the output
1945 : * MinimalTypeObject is not used in this case.
1946 : * Return true if the input type has type object; the output MinimalTypeObject
1947 : * contains the KeyHolder type of the corresponding type.
1948 : */
1949 12 : bool TypeAssignability::hold_key(const TypeIdentifier& ti, MinimalTypeObject& to) const
1950 : {
1951 12 : if (EK_MINIMAL != ti.kind() && EK_COMPLETE != ti.kind()) {
1952 12 : return false;
1953 : }
1954 :
1955 0 : to = lookup_minimal(ti);
1956 0 : switch (to.kind) {
1957 0 : case TK_STRUCTURE:
1958 : case TK_UNION: {
1959 0 : hold_key(to);
1960 0 : return true;
1961 : }
1962 0 : case TK_ALIAS: {
1963 0 : const TypeIdentifier& base = get_base_type(to);
1964 0 : return hold_key(base, to);
1965 : }
1966 0 : default: // KeyHolder is not defined for other types
1967 0 : return true;
1968 : }
1969 : }
1970 :
1971 : /**
1972 : * @brief The input must be of type TK_ALIAS
1973 : * Return the non-alias base type identifier of the input
1974 : */
1975 96 : const TypeIdentifier& TypeAssignability::get_base_type(const MinimalTypeObject& type) const
1976 : {
1977 96 : const TypeIdentifier& base = type.alias_type.body.common.related_type;
1978 96 : switch (base.kind()) {
1979 16 : case EK_COMPLETE:
1980 : case EK_MINIMAL: {
1981 16 : const MinimalTypeObject& type_obj = lookup_minimal(base);
1982 16 : if (TK_ALIAS == type_obj.kind) {
1983 0 : return get_base_type(type_obj);
1984 : }
1985 16 : return base;
1986 : }
1987 80 : default:
1988 80 : return base;
1989 : }
1990 : }
1991 :
1992 : /**
1993 : * @brief The first argument must be TK_ENUM and is the type object
1994 : * of a key member of the containing struct. Therefore, there must be a
1995 : * member with the same ID (and name) in the other struct type.
1996 : */
1997 13 : bool TypeAssignability::struct_rule_enum_key(const MinimalTypeObject& tb,
1998 : const CommonStructMember& ma) const
1999 : {
2000 13 : if (EK_MINIMAL != ma.member_type_id.kind()) {
2001 0 : return false;
2002 : }
2003 :
2004 13 : const MinimalEnumeratedLiteralSeq& literals_b = tb.enumerated_type.literal_seq;
2005 13 : const MinimalTypeObject& toa = lookup_minimal(ma.member_type_id);
2006 13 : const MinimalEnumeratedLiteralSeq* literals_a = 0;
2007 13 : if (TK_ENUM == toa.kind) {
2008 13 : literals_a = &toa.enumerated_type.literal_seq;
2009 0 : } else if (TK_ALIAS == toa.kind) {
2010 0 : const TypeIdentifier& base_a = get_base_type(toa);
2011 0 : if (EK_MINIMAL == base_a.kind()) {
2012 0 : const MinimalTypeObject& base_obj_a = lookup_minimal(base_a);
2013 0 : if (TK_ENUM == base_obj_a.kind) {
2014 0 : literals_a = &base_obj_a.enumerated_type.literal_seq;
2015 : } else {
2016 0 : return false;
2017 : }
2018 : } else {
2019 0 : return false;
2020 : }
2021 : } else {
2022 0 : return false;
2023 : }
2024 :
2025 : // All literals in tb must appear as literals in toa
2026 51 : for (size_t j = 0; j < literals_b.members.size(); ++j) {
2027 39 : const NameHash& h_b = literals_b.members[j].detail.name_hash;
2028 39 : ACE_CDR::ULong key_b = (h_b[0] << 24) | (h_b[1] << 16) | (h_b[2] << 8) | (h_b[3]);
2029 39 : bool found = false;
2030 79 : for (size_t k = 0; k < literals_a->members.size(); ++k) {
2031 78 : const NameHash& h_a = literals_a->members[k].detail.name_hash;
2032 78 : ACE_CDR::ULong key_a = (h_a[0] << 24) | (h_a[1] << 16) | (h_a[2] << 8) | (h_a[3]);
2033 78 : if (key_a == key_b) {
2034 38 : found = true;
2035 38 : break;
2036 : }
2037 : }
2038 39 : if (!found) {
2039 1 : return false;
2040 : }
2041 : }
2042 12 : return true;
2043 : }
2044 :
2045 : /**
2046 : * @brief Check whether a struct member is of sequence type and
2047 : * if so compute its bound into the first argument
2048 : */
2049 116 : bool TypeAssignability::get_sequence_bound(LBound& bound,
2050 : const CommonStructMember& member) const
2051 : {
2052 116 : ACE_CDR::Octet kind = member.member_type_id.kind();
2053 116 : bool is_sequence = false;
2054 116 : if (EK_MINIMAL == kind) {
2055 68 : const MinimalTypeObject& tobj = lookup_minimal(member.member_type_id);
2056 68 : if (TK_SEQUENCE == tobj.kind) {
2057 30 : bound = tobj.sequence_type.header.common.bound;
2058 30 : is_sequence = true;
2059 38 : } else if (TK_ALIAS == tobj.kind) {
2060 0 : const TypeIdentifier& base = get_base_type(tobj);
2061 0 : if (EK_MINIMAL == base.kind()) {
2062 0 : const MinimalTypeObject& base_obj = lookup_minimal(base);
2063 0 : if (TK_SEQUENCE == base_obj.kind) {
2064 0 : bound = base_obj.sequence_type.header.common.bound;
2065 0 : is_sequence = true;
2066 : }
2067 0 : } else if (TI_PLAIN_SEQUENCE_SMALL == base.kind()) {
2068 0 : bound = static_cast<LBound>(base.seq_sdefn().bound);
2069 0 : is_sequence = true;
2070 0 : } else if (TI_PLAIN_SEQUENCE_LARGE == base.kind()) {
2071 0 : bound = base.seq_ldefn().bound;
2072 0 : is_sequence = true;
2073 : }
2074 : }
2075 48 : } else if (TI_PLAIN_SEQUENCE_SMALL == kind) {
2076 8 : bound = static_cast<LBound>(member.member_type_id.seq_sdefn().bound);
2077 8 : is_sequence = true;
2078 40 : } else if (TI_PLAIN_SEQUENCE_LARGE == kind) {
2079 0 : bound = member.member_type_id.seq_ldefn().bound;
2080 0 : is_sequence = true;
2081 : }
2082 116 : return is_sequence;
2083 : }
2084 :
2085 : /**
2086 : * @brief Check whether a struct member is of map type and if so
2087 : * compute its bound into the first argument
2088 : */
2089 89 : bool TypeAssignability::get_map_bound(LBound& bound,
2090 : const CommonStructMember& member) const
2091 : {
2092 89 : ACE_CDR::Octet kind = member.member_type_id.kind();
2093 89 : bool is_map = false;
2094 89 : if (EK_MINIMAL == kind) {
2095 49 : const MinimalTypeObject& tobj = lookup_minimal(member.member_type_id);
2096 49 : if (TK_MAP == tobj.kind) {
2097 17 : bound = tobj.map_type.header.common.bound;
2098 17 : is_map = true;
2099 32 : } else if (TK_ALIAS == tobj.kind) {
2100 0 : const TypeIdentifier& base = get_base_type(tobj);
2101 0 : if (EK_MINIMAL == base.kind()) {
2102 0 : const MinimalTypeObject& base_obj = lookup_minimal(base);
2103 0 : if (TK_MAP == base_obj.kind) {
2104 0 : bound = base_obj.map_type.header.common.bound;
2105 0 : is_map = true;
2106 : }
2107 0 : } else if (TI_PLAIN_MAP_SMALL == base.kind()) {
2108 0 : bound = static_cast<LBound>(base.map_sdefn().bound);
2109 0 : is_map = true;
2110 0 : } else if (TI_PLAIN_MAP_LARGE == base.kind()) {
2111 0 : bound = base.map_ldefn().bound;
2112 0 : is_map = true;
2113 : }
2114 : }
2115 40 : } else if (TI_PLAIN_MAP_SMALL == kind) {
2116 0 : bound = static_cast<LBound>(member.member_type_id.map_sdefn().bound);
2117 0 : is_map = true;
2118 40 : } else if (TI_PLAIN_MAP_LARGE == kind) {
2119 5 : bound = member.member_type_id.map_ldefn().bound;
2120 5 : is_map = true;
2121 : }
2122 89 : return is_map;
2123 : }
2124 :
2125 : /**
2126 : * @brief Check whether the input struct member is of string type and
2127 : * if so compute its bound into the first argument
2128 : */
2129 114 : bool TypeAssignability::get_string_bound(LBound& bound,
2130 : const CommonStructMember& member) const
2131 : {
2132 114 : ACE_CDR::Octet kind = member.member_type_id.kind();
2133 114 : bool is_string = false;
2134 114 : if (EK_MINIMAL == kind) {
2135 50 : const MinimalTypeObject& tobj = lookup_minimal(member.member_type_id);
2136 50 : if (TK_ALIAS == tobj.kind) {
2137 0 : const TypeIdentifier& base = get_base_type(tobj);
2138 0 : if (TI_STRING8_SMALL == base.kind() || TI_STRING16_SMALL == base.kind()) {
2139 0 : bound = static_cast<LBound>(base.string_sdefn().bound);
2140 0 : is_string = true;
2141 0 : } else if (TI_STRING8_LARGE == base.kind() || TI_STRING16_LARGE == base.kind()) {
2142 0 : bound = base.string_ldefn().bound;
2143 0 : is_string = true;
2144 : }
2145 : }
2146 64 : } else if (TI_STRING8_SMALL == kind || TI_STRING16_SMALL == kind) {
2147 15 : bound = static_cast<LBound>(member.member_type_id.string_sdefn().bound);
2148 15 : is_string = true;
2149 49 : } else if (TI_STRING8_LARGE == kind || TI_STRING16_LARGE == kind) {
2150 15 : bound = member.member_type_id.string_ldefn().bound;
2151 15 : is_string = true;
2152 : }
2153 114 : return is_string;
2154 : }
2155 :
2156 : /**
2157 : * @brief Check if the second argument is of a struct type and if so
2158 : * return its type object as the first argument
2159 : */
2160 301 : bool TypeAssignability::get_struct_member(const MinimalTypeObject*& ret,
2161 : const CommonStructMember& member) const
2162 : {
2163 301 : ACE_CDR::Octet kind = member.member_type_id.kind();
2164 301 : bool is_struct = false;
2165 301 : if (EK_MINIMAL == kind) {
2166 141 : const MinimalTypeObject& tobj = lookup_minimal(member.member_type_id);
2167 141 : if (TK_STRUCTURE == tobj.kind) {
2168 76 : ret = &tobj;
2169 76 : is_struct = true;
2170 65 : } else if (TK_ALIAS == tobj.kind) {
2171 0 : const TypeIdentifier& base = get_base_type(tobj);
2172 0 : if (EK_MINIMAL == base.kind()) {
2173 0 : const MinimalTypeObject& base_obj = lookup_minimal(base);
2174 0 : if (TK_STRUCTURE == base_obj.kind) {
2175 0 : ret = &base_obj;
2176 0 : is_struct = true;
2177 : }
2178 : }
2179 : }
2180 : }
2181 301 : return is_struct;
2182 : }
2183 :
2184 : /**
2185 : * @brief Check if the second argument is of a union type and if so
2186 : * return its type object as the first argument
2187 : */
2188 231 : bool TypeAssignability::get_union_member(const MinimalTypeObject*& ret,
2189 : const CommonStructMember& member) const
2190 : {
2191 231 : ACE_CDR::Octet kind = member.member_type_id.kind();
2192 231 : bool is_union = false;
2193 231 : if (EK_MINIMAL == kind) {
2194 71 : const MinimalTypeObject& tobj = lookup_minimal(member.member_type_id);
2195 71 : if (TK_UNION == tobj.kind) {
2196 12 : ret = &tobj;
2197 12 : is_union = true;
2198 59 : } else if (TK_ALIAS == tobj.kind) {
2199 0 : const TypeIdentifier& base = get_base_type(tobj);
2200 0 : if (EK_MINIMAL == base.kind()) {
2201 0 : const MinimalTypeObject& base_obj = lookup_minimal(base);
2202 0 : if (TK_UNION == base_obj.kind) {
2203 0 : ret = &base_obj;
2204 0 : is_union = true;
2205 : }
2206 : }
2207 : }
2208 : }
2209 231 : return is_union;
2210 : }
2211 :
2212 : } // namespace XTypes
2213 : } // namespace OpenDDS
2214 :
2215 : OPENDDS_END_VERSIONED_NAMESPACE_DECL
|