Line data Source code
1 : /*
2 : * Distributed under the OpenDDS License.
3 : * See: http://www.opendds.org/license.html
4 : */
5 :
6 : #include <DCPS/DdsDcps_pch.h> // Only the _pch include should start with DCPS/
7 :
8 : #include "Serializer.h"
9 :
10 : #if !defined (__ACE_INLINE__)
11 : # include "Serializer.inl"
12 : #endif /* !__ACE_INLINE__ */
13 :
14 : #include "SafetyProfileStreams.h"
15 :
16 : #ifndef OPENDDS_UTIL_BUILD
17 : # include <tao/String_Alloc.h>
18 : #endif
19 :
20 : #include <ace/OS_NS_string.h>
21 : #include <ace/OS_Memory.h>
22 : #include <ace/Log_Msg.h>
23 :
24 : #include <cstdlib>
25 :
26 : OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL
27 :
28 : namespace OpenDDS {
29 : namespace DCPS {
30 :
31 : #ifdef OPENDDS_UTIL_BUILD
32 : namespace {
33 :
34 : ACE_CDR::Char* string_alloc(ACE_CDR::ULong size)
35 : {
36 : return static_cast<ACE_CDR::Char*>(std::malloc(size + 1));
37 : }
38 :
39 : void string_free(ACE_CDR::Char* ptr)
40 : {
41 : std::free(ptr);
42 : }
43 :
44 : ACE_CDR::WChar* wstring_alloc(ACE_CDR::ULong size)
45 : {
46 : return static_cast<ACE_CDR::WChar*>(std::malloc(sizeof(ACE_CDR::WChar) * (size + 1)));
47 : }
48 :
49 : void wstring_free(ACE_CDR::WChar* ptr)
50 : {
51 : std::free(ptr);
52 : }
53 :
54 : }
55 : #endif
56 :
57 13 : String endianness_to_string(Endianness endianness)
58 : {
59 13 : switch (endianness) {
60 5 : case ENDIAN_BIG:
61 : return "big-endian ("
62 : #ifdef ACE_LITTLE_ENDIAN
63 : "non-"
64 : #endif
65 5 : "native)";
66 8 : case ENDIAN_LITTLE:
67 : return "little-endian ("
68 : #ifndef ACE_LITTLE_ENDIAN
69 : "non-"
70 : #endif
71 8 : "native)";
72 0 : default:
73 0 : return "invalid endianness";
74 : }
75 : }
76 :
77 2520 : Encoding::Encoding()
78 2520 : : endianness_(ENDIAN_NATIVE)
79 2520 : , skip_sequence_dheader_(false)
80 : {
81 2520 : kind(KIND_XCDR1);
82 2520 : }
83 :
84 218 : Encoding::Encoding(Kind k, Endianness endianness)
85 218 : : endianness_(endianness)
86 218 : , skip_sequence_dheader_(false)
87 : {
88 218 : kind(k);
89 218 : }
90 :
91 12 : Encoding::Encoding(Kind k, bool swap_bytes)
92 12 : : endianness_(swap_bytes ? ENDIAN_NONNATIVE : ENDIAN_NATIVE)
93 12 : , skip_sequence_dheader_(false)
94 : {
95 12 : kind(k);
96 12 : }
97 :
98 21 : EncapsulationHeader::EncapsulationHeader(Kind kind, ACE_CDR::UShort options)
99 21 : : kind_(kind)
100 21 : , options_(options)
101 : {
102 21 : }
103 :
104 3 : EncapsulationHeader::EncapsulationHeader(const Encoding& enc, Extensibility ext, ACE_CDR::UShort options)
105 3 : : kind_(KIND_INVALID)
106 3 : , options_(options)
107 : {
108 3 : if (!from_encoding(enc, ext)) {
109 2 : kind_ = KIND_INVALID;
110 : }
111 3 : }
112 :
113 10 : bool EncapsulationHeader::from_encoding(
114 : const Encoding& encoding, Extensibility extensibility)
115 : {
116 10 : const bool big = encoding.endianness() == ENDIAN_BIG;
117 10 : switch (encoding.kind()) {
118 4 : case Encoding::KIND_XCDR1:
119 4 : switch (extensibility) {
120 3 : case FINAL:
121 : case APPENDABLE:
122 3 : kind_ = big ? KIND_CDR_BE : KIND_CDR_LE;
123 3 : break;
124 1 : case MUTABLE:
125 1 : kind_ = big ? KIND_PL_CDR_BE : KIND_PL_CDR_LE;
126 1 : break;
127 : }
128 4 : break;
129 3 : case Encoding::KIND_XCDR2:
130 3 : switch (extensibility) {
131 1 : case FINAL:
132 1 : kind_ = big ? KIND_CDR2_BE : KIND_CDR2_LE;
133 1 : break;
134 1 : case APPENDABLE:
135 1 : kind_ = big ? KIND_D_CDR2_BE : KIND_D_CDR2_LE;
136 1 : break;
137 1 : case MUTABLE:
138 1 : kind_ = big ? KIND_PL_CDR2_BE : KIND_PL_CDR2_LE;
139 1 : break;
140 : }
141 3 : break;
142 3 : default:
143 3 : if (log_level >= LogLevel::Error) {
144 0 : ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: EncapsulationHeader::from_encoding: "
145 : "Got Encoding With Unsupported Kind: %C\n",
146 : Encoding::kind_to_string(encoding.kind()).c_str()));
147 : }
148 3 : return false;
149 : }
150 7 : return true;
151 : }
152 :
153 14 : bool EncapsulationHeader::to_encoding(
154 : Encoding& encoding, Extensibility expected_extensibility)
155 : {
156 14 : return to_encoding_i(encoding, &expected_extensibility);
157 : }
158 :
159 0 : bool EncapsulationHeader::to_any_encoding(Encoding& encoding)
160 : {
161 0 : return to_encoding_i(encoding, 0);
162 : }
163 :
164 14 : bool EncapsulationHeader::to_encoding_i(
165 : Encoding& encoding, Extensibility* expected_extensibility_ptr)
166 : {
167 14 : Extensibility expected_extensibility = expected_extensibility_ptr ?
168 : *expected_extensibility_ptr : FINAL; // Placeholder, doesn't matter
169 14 : bool wrong_extensibility = true;
170 14 : switch (kind_) {
171 2 : case KIND_CDR_BE:
172 2 : encoding.kind(Encoding::KIND_XCDR1);
173 2 : encoding.endianness(ENDIAN_BIG);
174 2 : wrong_extensibility = expected_extensibility == MUTABLE;
175 2 : break;
176 :
177 2 : case KIND_CDR_LE:
178 2 : encoding.kind(Encoding::KIND_XCDR1);
179 2 : encoding.endianness(ENDIAN_LITTLE);
180 2 : wrong_extensibility = expected_extensibility == MUTABLE;
181 2 : break;
182 :
183 1 : case KIND_PL_CDR_BE:
184 1 : encoding.kind(Encoding::KIND_XCDR1);
185 1 : encoding.endianness(ENDIAN_BIG);
186 1 : wrong_extensibility = expected_extensibility != MUTABLE;
187 1 : break;
188 :
189 1 : case KIND_PL_CDR_LE:
190 1 : encoding.kind(Encoding::KIND_XCDR1);
191 1 : encoding.endianness(ENDIAN_LITTLE);
192 1 : wrong_extensibility = expected_extensibility != MUTABLE;
193 1 : break;
194 :
195 1 : case KIND_CDR2_BE:
196 1 : encoding.kind(Encoding::KIND_XCDR2);
197 1 : encoding.endianness(ENDIAN_BIG);
198 1 : wrong_extensibility = expected_extensibility != FINAL;
199 1 : break;
200 :
201 1 : case KIND_CDR2_LE:
202 1 : encoding.kind(Encoding::KIND_XCDR2);
203 1 : encoding.endianness(ENDIAN_LITTLE);
204 1 : wrong_extensibility = expected_extensibility != FINAL;
205 1 : break;
206 :
207 1 : case KIND_D_CDR2_BE:
208 1 : encoding.kind(Encoding::KIND_XCDR2);
209 1 : encoding.endianness(ENDIAN_BIG);
210 1 : wrong_extensibility = expected_extensibility != APPENDABLE;
211 1 : break;
212 :
213 1 : case KIND_D_CDR2_LE:
214 1 : encoding.kind(Encoding::KIND_XCDR2);
215 1 : encoding.endianness(ENDIAN_LITTLE);
216 1 : wrong_extensibility = expected_extensibility != APPENDABLE;
217 1 : break;
218 :
219 1 : case KIND_PL_CDR2_BE:
220 1 : encoding.kind(Encoding::KIND_XCDR2);
221 1 : encoding.endianness(ENDIAN_BIG);
222 1 : wrong_extensibility = expected_extensibility != MUTABLE;
223 1 : break;
224 :
225 1 : case KIND_PL_CDR2_LE:
226 1 : encoding.kind(Encoding::KIND_XCDR2);
227 1 : encoding.endianness(ENDIAN_LITTLE);
228 1 : wrong_extensibility = expected_extensibility != MUTABLE;
229 1 : break;
230 :
231 2 : default:
232 2 : if (log_level >= LogLevel::Error) {
233 0 : ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: EncapsulationHeader::to_encoding: "
234 : "Unsupported Encoding: %C\n", to_string().c_str()));
235 : }
236 2 : return false;
237 : }
238 :
239 12 : if (expected_extensibility_ptr && wrong_extensibility) {
240 2 : if (log_level >= LogLevel::Error) {
241 0 : ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: EncapsulationHeader::to_encoding: "
242 : "expected %C extensibility, but got %C\n",
243 : ext_to_string(*expected_extensibility_ptr), to_string().c_str()));
244 : }
245 2 : return false;
246 : }
247 :
248 10 : return true;
249 : }
250 :
251 0 : bool EncapsulationHeader::set_encapsulation_options(Message_Block_Ptr& mb)
252 : {
253 0 : if (mb->length() < padding_marker_byte_index + 1) {
254 0 : if (log_level >= LogLevel::Error) {
255 0 : ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: EncapsulationHeader::set_encapsulation_options: "
256 : "Insufficient buffer size %B\n", mb->length()));
257 : }
258 0 : return false;
259 : }
260 :
261 0 : mb->rd_ptr()[padding_marker_byte_index] |= ((padding_marker_alignment - mb->length() % padding_marker_alignment) & 0x03);
262 0 : return true;
263 : }
264 :
265 24 : String EncapsulationHeader::to_string() const
266 : {
267 24 : switch (kind_) {
268 5 : case KIND_CDR_BE:
269 5 : return "CDR/XCDR1 Big Endian Plain";
270 4 : case KIND_CDR_LE:
271 4 : return "CDR/XCDR1 Little Endian Plain";
272 1 : case KIND_PL_CDR_BE:
273 1 : return "CDR/XCDR1 Big Endian Parameter List";
274 2 : case KIND_PL_CDR_LE:
275 2 : return "CDR/XCDR1 Little Endian Parameter List";
276 1 : case KIND_CDR2_BE:
277 1 : return "XCDR2 Big Endian Plain";
278 2 : case KIND_CDR2_LE:
279 2 : return "XCDR2 Little Endian Plain";
280 1 : case KIND_D_CDR2_BE:
281 1 : return "XCDR2 Big Endian Delimited";
282 2 : case KIND_D_CDR2_LE:
283 2 : return "XCDR2 Little Endian Delimited";
284 1 : case KIND_PL_CDR2_BE:
285 1 : return "XCDR2 Big Endian Parameter List";
286 2 : case KIND_PL_CDR2_LE:
287 2 : return "XCDR2 Little Endian Parameter List";
288 1 : case KIND_XML:
289 1 : return "XML";
290 2 : case KIND_INVALID:
291 2 : return "Invalid";
292 0 : default:
293 0 : return "Unknown: " + to_dds_string(static_cast<unsigned>(kind_), true);
294 : }
295 : }
296 :
297 0 : bool operator>>(Serializer& s, EncapsulationHeader& value)
298 : {
299 : ACE_CDR::Octet data[EncapsulationHeader::serialized_size];
300 0 : if (!s.read_octet_array(&data[0], EncapsulationHeader::serialized_size)) {
301 0 : return false;
302 : }
303 0 : value.kind(static_cast<EncapsulationHeader::Kind>(
304 0 : (static_cast<ACE_UINT16>(data[0]) << 8) | data[1]));
305 0 : value.options((static_cast<ACE_UINT16>(data[2]) << 8) | data[3]);
306 0 : s.reset_alignment();
307 0 : return true;
308 : }
309 :
310 0 : bool operator<<(Serializer& s, const EncapsulationHeader& value)
311 : {
312 0 : if (!value.is_good()) {
313 0 : return false;
314 : }
315 : ACE_CDR::Octet data[EncapsulationHeader::serialized_size];
316 0 : data[0] = (value.kind() >> 8) & 0xff;
317 0 : data[1] = value.kind() & 0xff;
318 0 : data[2] = (value.options() >> 8) & 0xff;
319 0 : data[3] = value.options() & 0xff;
320 0 : const bool ok = s.write_octet_array(&data[0],
321 : EncapsulationHeader::serialized_size);
322 0 : s.reset_alignment();
323 0 : return ok;
324 : }
325 :
326 13 : String Encoding::kind_to_string(Kind value)
327 : {
328 13 : switch (value) {
329 3 : case KIND_XCDR1:
330 3 : return "CDR/XCDR1";
331 5 : case KIND_XCDR2:
332 5 : return "XCDR2";
333 5 : case KIND_UNALIGNED_CDR:
334 5 : return "Unaligned CDR";
335 0 : default:
336 0 : return "Unknown: " + to_dds_string(static_cast<unsigned>(value), true);
337 : }
338 : }
339 :
340 13 : String Encoding::to_string() const
341 : {
342 26 : String rv = Encoding::kind_to_string(kind_) + ", " +
343 26 : endianness_to_string(endianness_);
344 13 : if (!zero_init_padding_) {
345 0 : rv += ", non-initialized padding";
346 : }
347 13 : return rv;
348 0 : }
349 :
350 : const char Serializer::ALIGN_PAD[] = {0};
351 :
352 2423 : Serializer::Serializer(ACE_Message_Block* chain, const Encoding& enc)
353 2423 : : current_(chain)
354 2423 : , good_bit_(true)
355 2423 : , construction_status_(ConstructionSuccessful)
356 2423 : , align_rshift_(0)
357 2423 : , align_wshift_(0)
358 2423 : , rpos_(0)
359 2423 : , wpos_(0)
360 : {
361 2423 : encoding(enc);
362 2423 : reset_alignment();
363 2423 : }
364 :
365 70 : Serializer::Serializer(ACE_Message_Block* chain, Encoding::Kind kind,
366 70 : Endianness endianness)
367 70 : : current_(chain)
368 70 : , good_bit_(true)
369 70 : , construction_status_(ConstructionSuccessful)
370 70 : , align_rshift_(0)
371 70 : , align_wshift_(0)
372 70 : , rpos_(0)
373 70 : , wpos_(0)
374 : {
375 70 : encoding(Encoding(kind, endianness));
376 70 : reset_alignment();
377 70 : }
378 :
379 0 : Serializer::Serializer(ACE_Message_Block* chain,
380 0 : Encoding::Kind kind, bool swap_bytes)
381 0 : : current_(chain)
382 0 : , good_bit_(true)
383 0 : , construction_status_(ConstructionSuccessful)
384 0 : , align_rshift_(0)
385 0 : , align_wshift_(0)
386 0 : , rpos_(0)
387 0 : , wpos_(0)
388 : {
389 0 : encoding(Encoding(kind, swap_bytes));
390 0 : reset_alignment();
391 0 : }
392 :
393 2493 : Serializer::~Serializer()
394 : {
395 2493 : }
396 :
397 55 : Serializer::ScopedAlignmentContext::ScopedAlignmentContext(Serializer& ser, size_t min_read)
398 55 : : ser_(ser)
399 55 : , max_align_(ser.encoding().max_align())
400 55 : , start_rpos_(ser.rpos())
401 55 : , rblock_(max_align_ ? (ptrdiff_t(ser.current_->rd_ptr()) - ser.align_rshift_) % max_align_ : 0)
402 55 : , min_read_(min_read)
403 55 : , start_wpos_(ser.wpos())
404 110 : , wblock_(max_align_ ? (ptrdiff_t(ser.current_->wr_ptr()) - ser.align_wshift_) % max_align_ : 0)
405 : {
406 55 : ser_.reset_alignment();
407 55 : }
408 :
409 : void
410 55 : Serializer::ScopedAlignmentContext::restore(Serializer& ser) const
411 : {
412 55 : if (min_read_ != 0 && (ser.rpos() - start_rpos_) < min_read_) {
413 5 : ser.skip(min_read_ - (ser.rpos() - start_rpos_));
414 : }
415 :
416 55 : if (ser.current_ && max_align_) {
417 52 : ser.align_rshift_ = offset(ser.current_->rd_ptr(), ser.rpos() - start_rpos_ + rblock_, max_align_);
418 52 : ser.align_wshift_ = offset(ser.current_->wr_ptr(), ser.wpos() - start_wpos_ + wblock_, max_align_);
419 : }
420 55 : }
421 :
422 : bool
423 118 : Serializer::peek(ACE_CDR::ULong& t)
424 : {
425 : // save
426 118 : const size_t rpos = rpos_;
427 118 : const unsigned char align_rshift = align_rshift_;
428 118 : ACE_Message_Block* const current = current_;
429 :
430 : // read
431 118 : if (!peek_helper(current_, 2 * uint32_cdr_size, t)) {
432 0 : return false;
433 : }
434 :
435 : // reset
436 118 : current_ = current;
437 118 : align_rshift_ = align_rshift;
438 118 : rpos_ = rpos;
439 118 : return true;
440 : }
441 :
442 : void
443 2548 : Serializer::reset_alignment()
444 : {
445 2548 : const ptrdiff_t align = encoding().max_align();
446 2548 : if (current_ && align) {
447 2483 : align_rshift_ = offset(current_->rd_ptr(), 0, align);
448 2483 : align_wshift_ = offset(current_->wr_ptr(), 0, align);
449 : }
450 2548 : }
451 :
452 : void
453 19692 : Serializer::smemcpy(char* to, const char* from, size_t n)
454 : {
455 19692 : OPENDDS_ASSERT(from);
456 19692 : (void) ACE_OS::memcpy(to, from, n);
457 19692 : }
458 :
459 : void
460 5291 : Serializer::swapcpy(char* to, const char* from, size_t n)
461 : {
462 : // Unroll the loop...
463 5291 : switch (n) { // 2 4 8 16
464 20 : case 16:
465 20 : to[ 15] = from[ n - 16]; // x x x 0
466 : // fallthrough
467 20 : case 15:
468 20 : to[ 14] = from[ n - 15]; // x x x 1
469 : // fallthrough
470 20 : case 14:
471 20 : to[ 13] = from[ n - 14]; // x x x 2
472 : // fallthrough
473 20 : case 13:
474 20 : to[ 12] = from[ n - 13]; // x x x 3
475 : // fallthrough
476 20 : case 12:
477 20 : to[ 11] = from[ n - 12]; // x x x 4
478 : // fallthrough
479 20 : case 11:
480 20 : to[ 10] = from[ n - 11]; // x x x 5
481 : // fallthrough
482 20 : case 10:
483 20 : to[ 9] = from[ n - 10]; // x x x 6
484 : // fallthrough
485 20 : case 9:
486 20 : to[ 8] = from[ n - 9]; // x x x 7
487 : // fallthrough
488 165 : case 8:
489 165 : to[ 7] = from[ n - 8]; // x x 0 8
490 : // fallthrough
491 165 : case 7:
492 165 : to[ 6] = from[ n - 7]; // x x 1 9
493 : // fallthrough
494 165 : case 6:
495 165 : to[ 5] = from[ n - 6]; // x x 2 10
496 : // fallthrough
497 165 : case 5:
498 165 : to[ 4] = from[ n - 5]; // x x 3 11
499 : // fallthrough
500 4665 : case 4:
501 4665 : to[ 3] = from[ n - 4]; // x 0 4 12
502 : // fallthrough
503 4665 : case 3:
504 4665 : to[ 2] = from[ n - 3]; // x 1 5 13
505 : // fallthrough
506 5223 : case 2:
507 5223 : to[ 1] = from[ n - 2]; // 0 2 6 14
508 : // fallthrough
509 5291 : case 1:
510 5291 : to[ 0] = from[ n - 1]; // 1 3 7 15
511 : // fallthrough
512 5291 : case 0:
513 5291 : return;
514 0 : default:
515 0 : good_bit_ = false;
516 : }
517 : }
518 :
519 : size_t
520 1049 : Serializer::read_string(ACE_CDR::Char*& dest,
521 : StrAllocate str_alloc,
522 : StrFree str_free)
523 : {
524 1049 : if (str_alloc == 0) {
525 : #ifdef OPENDDS_UTIL_BUILD
526 : str_alloc = string_alloc;
527 : #else
528 1049 : str_alloc = CORBA::string_alloc;
529 : #endif
530 : }
531 :
532 : //
533 : // Ensure no bad values leave the routine.
534 : //
535 1049 : free_string(dest, str_free);
536 1049 : dest = 0;
537 :
538 : //
539 : // Extract the string length.
540 : //
541 : ACE_CDR::ULong length; // includes the null
542 1049 : if (!(*this >> length)) {
543 0 : return 0;
544 : }
545 :
546 1049 : if (length == 0) {
547 : // not legal CDR, but we need to accept it since other implementations may generate this
548 0 : dest = str_alloc(0);
549 0 : return 0;
550 : }
551 :
552 : //
553 : // NOTE: Maintain the ACE implementation where the length check is
554 : // done here before the allocation even though it will be
555 : // checked during the actual read as well.
556 : //
557 1049 : if (current_ && length <= current_->total_length()) {
558 :
559 1047 : dest = str_alloc(length - 1);
560 :
561 1047 : if (dest == 0) {
562 0 : good_bit_ = false;
563 :
564 : } else {
565 : //
566 : // Extract the string.
567 : //
568 1047 : read_char_array(dest, length);
569 :
570 1047 : if (good_bit_ && dest[length - 1]) {
571 : // If the last byte was not a 0 it's not a valid CDR string
572 2 : good_bit_ = false;
573 : }
574 : }
575 :
576 1047 : if (!good_bit_) {
577 2 : free_string(dest, str_free);
578 2 : dest = 0;
579 : }
580 :
581 : } else {
582 2 : good_bit_ = false;
583 : }
584 :
585 1049 : return length - 1;
586 : }
587 :
588 : void
589 2076 : Serializer::free_string(ACE_CDR::Char* str,
590 : StrFree str_free)
591 : {
592 2076 : if (str_free == 0) {
593 : #ifdef OPENDDS_UTIL_BUILD
594 : str_free = string_free;
595 : #else
596 2076 : str_free = CORBA::string_free;
597 : #endif
598 : }
599 2076 : str_free(str);
600 2076 : }
601 :
602 : size_t
603 26 : Serializer::read_string(ACE_CDR::WChar*& dest,
604 : WStrAllocate str_alloc,
605 : WStrFree str_free)
606 : {
607 26 : if (str_alloc == 0) {
608 : #ifdef OPENDDS_UTIL_BUILD
609 : str_alloc = wstring_alloc;
610 : #else
611 26 : str_alloc = CORBA::wstring_alloc;
612 : #endif
613 : }
614 :
615 : //
616 : // Ensure no bad values leave the routine.
617 : //
618 26 : free_string(dest, str_free);
619 26 : dest = 0;
620 :
621 : //
622 : // Extract the string size.
623 : //
624 : ACE_CDR::ULong bytecount;
625 26 : if (!(*this >> bytecount)) {
626 0 : return 0;
627 : }
628 :
629 : //
630 : // NOTE: Maintain the ACE implementation where the length check is
631 : // done here before the allocation even though it will be
632 : // checked during the actual read as well.
633 : //
634 26 : ACE_CDR::ULong length = 0;
635 26 : if (current_ && bytecount <= current_->total_length()) {
636 25 : length = bytecount / char16_cdr_size;
637 25 : dest = str_alloc(length);
638 :
639 25 : if (dest == 0) {
640 0 : good_bit_ = false;
641 0 : return 0;
642 : }
643 :
644 : #if ACE_SIZEOF_WCHAR == 2
645 : read_array(reinterpret_cast<char*>(dest), char16_cdr_size, length, swap_bytes());
646 : #else
647 106 : for (size_t i = 0; i < length && good_bit_; ++i) {
648 : ACE_UINT16 as_utf16;
649 81 : buffer_read(reinterpret_cast<char*>(&as_utf16), char16_cdr_size, swap_bytes());
650 81 : if (good_bit_) {
651 81 : dest[i] = as_utf16;
652 : }
653 : }
654 : #endif
655 :
656 25 : if (good_bit_) {
657 : //
658 : // Null terminate the string.
659 : //
660 25 : dest[length] = L'\0';
661 : } else {
662 0 : free_string(dest, str_free);
663 0 : dest = 0;
664 0 : length = 0;
665 : }
666 :
667 : } else {
668 1 : good_bit_ = false;
669 : }
670 :
671 26 : return length;
672 : }
673 :
674 : void
675 26 : Serializer::free_string(ACE_CDR::WChar* str,
676 : WStrFree str_free)
677 : {
678 26 : if (str_free == 0) {
679 : #ifdef OPENDDS_UTIL_BUILD
680 : str_free = wstring_free;
681 : #else
682 26 : str_free = CORBA::wstring_free;
683 : #endif
684 : }
685 26 : str_free(str);
686 26 : }
687 :
688 5 : ACE_Message_Block* Serializer::trim(size_t n) const
689 : {
690 5 : if (!good_bit() || !current_ || n > length()) {
691 1 : return 0;
692 : }
693 4 : Message_Block_Ptr dup(current_->duplicate());
694 4 : ACE_Message_Block* i = dup.get();
695 6 : for (size_t remain = n; i && remain; i = i->cont()) {
696 6 : if (i->length() >= remain) {
697 4 : i->wr_ptr(i->rd_ptr() + remain);
698 4 : ACE_Message_Block::release(i->cont());
699 4 : i->cont(0);
700 4 : break;
701 : }
702 2 : remain -= i->length();
703 : }
704 4 : return dup.release();
705 4 : }
706 :
707 1072 : bool Serializer::read_parameter_id(unsigned& id, size_t& size, bool& must_understand)
708 : {
709 1072 : const Encoding::XcdrVersion xcdr = encoding().xcdr_version();
710 1072 : if (xcdr == Encoding::XCDR_VERSION_1) {
711 : // Get the "short" id and size
712 0 : if (!align_r(xcdr1_pid_alignment)) {
713 0 : return false;
714 : }
715 : ACE_CDR::UShort pid;
716 0 : if (!(*this >> pid)) {
717 0 : return false;
718 : }
719 0 : const ACE_CDR::UShort short_id = pid & 0x3fff;
720 : ACE_CDR::UShort short_size;
721 0 : if (!(*this >> short_size)) {
722 0 : return false;
723 : }
724 :
725 : // TODO(iguessthislldo): handle PID flags
726 0 : must_understand = false; // Placeholder
727 :
728 : // If extended, get the "long" id and size
729 0 : if (short_id == pid_extended) {
730 : ACE_CDR::ULong long_id, long_size;
731 0 : if (!(*this >> long_id) || !(*this >> long_size)) {
732 0 : return false;
733 : }
734 0 : const unsigned short_size_left = short_size - 8;
735 0 : if (short_size_left) {
736 0 : skip(short_size_left);
737 : }
738 0 : id = long_id;
739 0 : size = long_size;
740 : } else {
741 0 : id = short_id;
742 0 : size = short_size;
743 : }
744 :
745 0 : reset_alignment();
746 1072 : } else if (xcdr == Encoding::XCDR_VERSION_2) {
747 : ACE_CDR::ULong emheader;
748 1072 : if (!(*this >> emheader)) {
749 0 : return false;
750 : }
751 :
752 1072 : must_understand = emheader & emheader_must_understand;
753 :
754 : // Get Size
755 1072 : const unsigned short lc = (emheader >> 28) & 0x7;
756 1072 : if (lc < 4) {
757 762 : size = size_t(1) << lc;
758 : } else {
759 : ACE_CDR::ULong next_int;
760 310 : if (lc == 4 ? !(*this >> next_int) : !peek(next_int)) {
761 0 : return false;
762 : }
763 310 : switch (lc) {
764 198 : case 4:
765 198 : size = next_int;
766 198 : break;
767 32 : case 5:
768 32 : size = uint32_cdr_size + next_int;
769 32 : break;
770 47 : case 6:
771 47 : size = uint32_cdr_size + next_int * 4;
772 47 : break;
773 33 : case 7:
774 33 : size = uint32_cdr_size + next_int * 8;
775 33 : break;
776 : }
777 : }
778 1072 : id = emheader & 0xfffffff;
779 : }
780 :
781 1072 : return true;
782 : }
783 :
784 422 : bool Serializer::write_parameter_id(const unsigned id, const size_t size, const bool must_understand)
785 : {
786 422 : if (static_cast<ACE_CDR::ULong>(id) > MEMBER_ID_MAX) {
787 0 : return false;
788 : }
789 :
790 422 : const Encoding::XcdrVersion xcdr = encoding().xcdr_version();
791 422 : if (xcdr == Encoding::XCDR_VERSION_1) {
792 0 : if (!align_w(xcdr1_pid_alignment)) {
793 0 : return false;
794 : }
795 :
796 : // Determine if we need to use a short or long PID
797 0 : const bool long_pid = id > (1 << 14) || size > (1 << 16);
798 :
799 : // Write the short part of the PID
800 : /*
801 : * TODO(iguessthislldo): Control when to use "must understand" and "impl
802 : * extension"?
803 : *
804 : * The XTypes CDR rules seem to imply they're alway here but that doesn't
805 : * sound quite right.
806 : *
807 : * Also see TODOs above and the TODO below.
808 : */
809 0 : const ACE_CDR::UShort pid_id =
810 0 : pid_impl_extension + pid_must_understand +
811 : (long_pid ? pid_extended : static_cast<ACE_CDR::UShort>(id));
812 0 : if (!(*this << pid_id)) {
813 0 : return false;
814 : }
815 0 : const ACE_CDR::UShort pid_size = long_pid ? 8 : ACE_CDR::UShort(size);
816 0 : if (!(*this << pid_size)) {
817 0 : return false;
818 : }
819 :
820 : // If PID is long, write the extended/long part.
821 0 : if (long_pid && (
822 0 : !(*this << static_cast<ACE_CDR::ULong>(id)) ||
823 0 : !(*this << static_cast<ACE_CDR::ULong>(size)))) {
824 0 : return false;
825 : }
826 :
827 0 : reset_alignment();
828 422 : } else if (xcdr == Encoding::XCDR_VERSION_2) {
829 : // Compute Length Code, write EM Header and NEXTINT
830 422 : const ACE_CDR::ULong lc = (size == 1 ? 0 : size == 2 ? 1 : size == 4 ? 2 : size == 8 ? 3 : 4);
831 422 : const ACE_CDR::ULong emheader = (lc << 28) | id | (must_understand ? emheader_must_understand : 0);
832 422 : if (!(*this << emheader)) {
833 0 : return false;
834 : }
835 422 : if (lc == 4) {
836 226 : return *this << ACE_CDR::ULong(size);
837 : }
838 : }
839 196 : return true;
840 : }
841 :
842 : } // namespace DCPS
843 : } // namespace OpenDDS
844 :
845 : OPENDDS_END_VERSIONED_NAMESPACE_DECL
|