LCOV - code coverage report
Current view: top level - dns/rdata/generic/detail - txt_like.h (source / functions) Hit Total Coverage
Test: report.info Lines: 59 61 96.7 %
Date: 2012-05-15 Functions: 8 8 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 138 232 59.5 %

           Branch data     Line data    Source code
       1                 :            : // Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
       2                 :            : //
       3                 :            : // Permission to use, copy, modify, and/or distribute this software for any
       4                 :            : // purpose with or without fee is hereby granted, provided that the above
       5                 :            : // copyright notice and this permission notice appear in all copies.
       6                 :            : //
       7                 :            : // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
       8                 :            : // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
       9                 :            : // AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
      10                 :            : // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      11                 :            : // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
      12                 :            : // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      13                 :            : // PERFORMANCE OF THIS SOFTWARE.
      14                 :            : 
      15                 :            : #ifndef __TXT_LIKE_H
      16                 :            : #define __TXT_LIKE_H 1
      17                 :            : 
      18                 :            : #include <stdint.h>
      19                 :            : 
      20                 :            : #include <string>
      21                 :            : #include <vector>
      22                 :            : 
      23                 :            : using namespace std;
      24                 :            : using namespace isc::util;
      25                 :            : 
      26                 :            : /// \brief \c rdata::TXTLikeImpl class represents the TXT-like RDATA for TXT
      27                 :            : /// and SPF types.
      28                 :            : ///
      29                 :            : /// This class implements the basic interfaces inherited by the TXT and SPF
      30                 :            : /// classes from the abstract \c rdata::Rdata class, and provides trivial
      31                 :            : /// accessors to TXT-like RDATA.
      32                 :       7500 : template<class Type, uint16_t typeCode>class TXTLikeImpl {
      33                 :            : public:
      34                 :            :     /// \brief Constructor from wire-format data.
      35                 :            :     ///
      36                 :            :     /// \param buffer A buffer storing the wire format data.
      37                 :            :     /// \param rdata_len The length of the RDATA in bytes, normally expected
      38                 :            :     /// to be the value of the RDLENGTH field of the corresponding RR.
      39                 :            :     ///
      40                 :            :     /// <b>Exceptions</b>
      41                 :            :     ///
      42                 :            :     /// \c InvalidRdataLength is thrown if rdata_len exceeds the maximum.
      43                 :            :     /// \c DNSMessageFORMERR is thrown if the RR is misformed.
      44                 :          7 :     TXTLikeImpl(InputBuffer& buffer, size_t rdata_len) {
      45 [ +  + ][ +  + ]:         17 :         if (rdata_len > MAX_RDLENGTH) {
      46 [ +  - ][ +  - ]:          6 :             isc_throw(InvalidRdataLength, "RDLENGTH too large: " << rdata_len);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
      47                 :            :         }
      48                 :            : 
      49 [ +  + ][ +  + ]:         15 :         if (rdata_len == 0) {    // note that this couldn't happen in the loop.
      50 [ +  - ][ +  - ]:         17 :             isc_throw(DNSMessageFORMERR, "Error in parsing " <<
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
      51                 :            :                       RRType(typeCode) << " RDATA: 0-length character string");
      52                 :            :         }
      53                 :            : 
      54   [ +  +  +  + ]:        524 :         do {
      55 [ +  - ][ +  - ]:        527 :             const uint8_t len = buffer.readUint8();
      56 [ +  + ][ +  + ]:        527 :             if (rdata_len < len + 1) {
      57 [ +  - ][ +  - ]:          6 :                 isc_throw(DNSMessageFORMERR, "Error in parsing " <<
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
      58                 :            :                           RRType(typeCode) <<
      59                 :            :                           " RDATA: character string length is too large: " <<
      60                 :            :                           static_cast<int>(len));
      61                 :            :             }
      62 [ +  - ][ +  - ]:        524 :             vector<uint8_t> data(len + 1);
      63                 :        524 :             data[0] = len;
      64 [ +  - ][ +  - ]:        524 :             buffer.readData(&data[0] + 1, len);
      65 [ +  - ][ +  - ]:        524 :             string_list_.push_back(data);
      66                 :            : 
      67                 :        524 :             rdata_len -= (len + 1);
      68                 :            :         } while (rdata_len > 0);
      69                 :         10 :     }
      70                 :            : 
      71                 :            :     /// \brief Constructor from string.
      72                 :            :     ///
      73                 :            :     /// <b>Exceptions</b>
      74                 :            :     ///
      75                 :            :     /// \c CharStringTooLong is thrown if the parameter string length exceeds
      76                 :            :     /// maximum.
      77                 :            :     /// \c InvalidRdataText is thrown if the method cannot process the
      78                 :            :     /// parameter data.
      79                 :          7 :     explicit TXTLikeImpl(const std::string& txtstr) {
      80                 :            :         // TBD: this is a simple, incomplete implementation that only supports
      81                 :            :         // a single character-string.
      82                 :            : 
      83                 :       3877 :         size_t length = txtstr.size();
      84                 :       3877 :         size_t pos_begin = 0;
      85                 :            : 
      86 [ +  + ][ +  + ]:       3877 :         if (length > 1 && txtstr[0] == '"' && txtstr[length - 1] == '"') {
         [ -  + ][ +  + ]
         [ +  + ][ +  + ]
         [ -  + ][ +  + ]
      87                 :         48 :             pos_begin = 1;
      88                 :         48 :             length -= 2;
      89                 :            :         }
      90                 :            : 
      91 [ +  + ][ +  + ]:       3877 :         if (length > MAX_CHARSTRING_LEN) {
      92 [ +  - ][ +  - ]:          9 :             isc_throw(CharStringTooLong, RRType(typeCode) <<
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
      93                 :            :                       " RDATA construction from text:"
      94                 :            :                       " string length is too long: " << length);
      95                 :            :         }
      96                 :            : 
      97                 :            :         // TBD: right now, we don't support escaped characters
      98 [ +  - ][ +  + ]:       3874 :         if (txtstr.find('\\') != string::npos) {
         [ +  - ][ +  + ]
      99 [ +  - ][ +  - ]:          8 :             isc_throw(InvalidRdataText, RRType(typeCode) <<
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     100                 :            :                       " RDATA from text:"
     101                 :            :                       " escaped character is currently not supported: " <<
     102                 :            :                       txtstr);
     103                 :            :         }
     104                 :            : 
     105                 :            :         vector<uint8_t> data;
     106 [ +  - ][ +  - ]:       3870 :         data.reserve(length + 1);
     107 [ +  - ][ +  - ]:       3870 :         data.push_back(length);
     108 [ +  - ][ +  - ]:       3870 :         data.insert(data.end(), txtstr.begin() + pos_begin,
     109                 :            :                     txtstr.begin() + pos_begin + length);
     110 [ +  - ][ +  - ]:       3870 :         string_list_.push_back(data);
     111                 :       3870 :     }
     112                 :            : 
     113                 :            :     /// \brief The copy constructor.
     114                 :            :     ///
     115                 :            :     /// Trivial for now, we could've used the default one.
     116                 :            :     TXTLikeImpl(const TXTLikeImpl& other) :
     117   [ +  -  +  - ]:       3620 :         string_list_(other.string_list_)
           [ +  -  +  - ]
     118                 :            :     {}
     119                 :            : 
     120                 :            :     /// \brief Render the TXT-like data in the wire format to an OutputBuffer
     121                 :            :     /// object.
     122                 :            :     ///
     123                 :            :     /// \param buffer An output buffer to store the wire data.
     124                 :            :     void
     125                 :        282 :     toWire(OutputBuffer& buffer) const {
     126 [ +  + ][ +  + ]:       1076 :         for (vector<vector<uint8_t> >::const_iterator it =
     127                 :       1358 :                                                           string_list_.begin();
     128                 :            :              it != string_list_.end();
     129                 :            :              ++it)
     130                 :            :         {
     131                 :        794 :             buffer.writeData(&(*it)[0], (*it).size());
     132                 :            :         }
     133                 :        282 :     }
     134                 :            : 
     135                 :            :     /// \brief Render the TXT-like data in the wire format to an
     136                 :            :     /// AbstractMessageRenderer object.
     137                 :            :     ///
     138                 :            :     /// \param buffer An output AbstractMessageRenderer to send the wire data
     139                 :            :     /// to.
     140                 :            :     void
     141                 :            :     toWire(AbstractMessageRenderer& renderer) const {
     142 [ +  + ][ +  + ]:         46 :         for (vector<vector<uint8_t> >::const_iterator it =
     143                 :         22 :                                                           string_list_.begin();
     144                 :            :              it != string_list_.end();
     145                 :            :              ++it)
     146                 :            :         {
     147                 :         24 :             renderer.writeData(&(*it)[0], (*it).size());
     148                 :            :         }
     149                 :            :     }
     150                 :            : 
     151                 :            :     /// \brief Convert the TXT-like data to a string.
     152                 :            :     ///
     153                 :            :     /// \return A \c string object that represents the TXT-like data.
     154                 :            :     string
     155                 :            :     toText() const {
     156                 :          0 :         string s;
     157                 :            : 
     158                 :            :         // XXX: this implementation is not entirely correct.  for example, it
     159                 :            :         // should escape double-quotes if they appear in the character string.
     160 [ +  + ][ +  + ]:         80 :         for (vector<vector<uint8_t> >::const_iterator it =
     161                 :         40 :                                                           string_list_.begin();
     162                 :            :              it != string_list_.end();
     163                 :            :              ++it)
     164                 :            :         {
     165 [ -  + ][ -  + ]:         40 :             if (!s.empty()) {
     166 [ #  # ][ #  # ]:          0 :                 s.push_back(' ');
     167                 :            :             }
     168 [ +  - ][ +  - ]:         40 :             s.push_back('"');
     169 [ +  - ][ +  - ]:         40 :             s.insert(s.end(), (*it).begin() + 1, (*it).end());
         [ +  - ][ +  - ]
     170 [ +  - ][ +  - ]:         40 :             s.push_back('"');
     171                 :            :         }
     172                 :            : 
     173                 :            :         return (s);
     174                 :            :     }
     175                 :            : 
     176                 :            :     /// \brief Compare two instances of TXT-like RDATA.
     177                 :            :     ///
     178                 :            :     /// It is up to the caller to make sure that \c other is an object of the
     179                 :            :     /// same \c TXTLikeImpl class.
     180                 :            :     ///
     181                 :            :     /// \param other the right-hand operand to compare against.
     182                 :            :     /// \return < 0 if \c this would be sorted before \c other.
     183                 :            :     /// \return 0 if \c this is identical to \c other in terms of sorting
     184                 :            :     /// order.
     185                 :            :     /// \return > 0 if \c this would be sorted after \c other.
     186                 :            :     int
     187                 :        135 :     compare(const TXTLikeImpl& other) const {
     188                 :            :         // This implementation is not efficient.  Revisit this (TBD).
     189                 :        135 :         OutputBuffer this_buffer(0);
     190   [ +  -  +  - ]:        135 :         toWire(this_buffer);
     191                 :        135 :         uint8_t const* const this_data = (uint8_t const*)this_buffer.getData();
     192                 :        135 :         size_t this_len = this_buffer.getLength();
     193                 :            : 
     194 [ +  - ][ +  - ]:        135 :         OutputBuffer other_buffer(0);
     195 [ +  - ][ +  - ]:        135 :         other.toWire(other_buffer);
     196                 :            :         uint8_t const* const other_data
     197                 :        135 :                                       = (uint8_t const*)other_buffer.getData();
     198                 :        135 :         const size_t other_len = other_buffer.getLength();
     199                 :            : 
     200                 :        135 :         const size_t cmplen = min(this_len, other_len);
     201                 :        135 :         const int cmp = memcmp(this_data, other_data, cmplen);
     202                 :            : 
     203 [ +  + ][ +  + ]:        135 :         if (cmp != 0) {
     204                 :            :             return (cmp);
     205                 :            :         } else {
     206                 :            :             return ((this_len == other_len) ? 0 :
     207 [ -  + ][ #  # ]:        109 :                     (this_len < other_len) ? -1 : 1);
         [ -  + ][ #  # ]
     208                 :            :         }
     209                 :            :     }
     210                 :            : 
     211                 :            : private:
     212                 :            :     /// Note: this is a prototype version; we may reconsider
     213                 :            :     /// this representation later.
     214                 :            :     std::vector<std::vector<uint8_t> > string_list_;
     215                 :            : };
     216                 :            : 
     217                 :            : // END_RDATA_NAMESPACE
     218                 :            : // END_ISC_NAMESPACE
     219                 :            : 
     220                 :            : #endif //  __TXT_LIKE_H
     221                 :            : 
     222                 :            : // Local Variables: 
     223                 :            : // mode: c++
     224                 :            : // End: 

Generated by: LCOV version 1.9