LCOV - code coverage report
Current view: top level - DCPS - Serializer.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 355 456 77.9 %
Date: 2023-04-30 01:32:43 Functions: 28 34 82.4 %

          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

Generated by: LCOV version 1.16