[svn] commit: r765 - in /branches/jinmei-dnsrdata2/src/lib/dns/cpp: rdata.cc rdata.h
BIND 10 source code commits
bind10-changes at lists.isc.org
Tue Feb 9 05:03:49 UTC 2010
Author: jinmei
Date: Tue Feb 9 05:03:48 2010
New Revision: 765
Log:
used pimpl idiom to hide the internal use of std::vector (and therefore for
better portability)
Modified:
branches/jinmei-dnsrdata2/src/lib/dns/cpp/rdata.cc
branches/jinmei-dnsrdata2/src/lib/dns/cpp/rdata.h
Modified: branches/jinmei-dnsrdata2/src/lib/dns/cpp/rdata.cc
==============================================================================
--- branches/jinmei-dnsrdata2/src/lib/dns/cpp/rdata.cc (original)
+++ branches/jinmei-dnsrdata2/src/lib/dns/cpp/rdata.cc Tue Feb 9 05:03:48 2010
@@ -19,6 +19,7 @@
#include <sstream>
#include <iomanip>
#include <ios>
+#include <vector>
#include <stdint.h>
#include <string.h>
@@ -95,49 +96,93 @@
}
namespace generic {
-Generic::Generic(InputBuffer& buffer, size_t rdata_len) :
- data_(rdata_len)
-{
- buffer.readData(&data_[0], rdata_len);
- data_.resize(rdata_len);
+struct GenericImpl {
+ GenericImpl(const vector<uint8_t>& data) : data_(data) {}
+ vector<uint8_t> data_;
+};
+
+Generic::Generic(InputBuffer& buffer, size_t rdata_len)
+{
+ vector<uint8_t> data(rdata_len);
+ buffer.readData(&data[0], rdata_len);
+ data.resize(rdata_len);
+
+ impl_ = new GenericImpl(data);
}
Generic::Generic(const string& rdata_string)
{
istringstream iss(rdata_string);
string unknown_mark;
- int32_t rdlen;
-
iss >> unknown_mark;
if (unknown_mark != "\\#") {
dns_throw(InvalidRdataText,
"Missing the special token (\\#) for generic RDATA encoding");
}
- iss >> rdlen;
- if (iss.bad() || iss.fail() || rdlen < 0 || rdlen > 0xffff) {
+ // RDLENGTH: read into a string so that we can easily reject invalid tokens
+ string rdlen_txt;
+ iss >> rdlen_txt;
+ istringstream iss_rdlen(rdlen_txt);
+ int32_t rdlen;
+ iss_rdlen >> rdlen;
+ if (iss_rdlen.rdstate() != ios::eofbit) {
+ dns_throw(InvalidRdataText,
+ "Invalid representation for a generic RDLENGTH");
+ }
+ if (rdlen < 0 || rdlen > 0xffff) {
dns_throw(InvalidRdataLength, "RDATA length is out of range");
}
- while (!iss.eof() && data_.size() < rdlen) {
+ vector<uint8_t> data;
+ while (!iss.eof() && data.size() < rdlen) {
string bytes;
iss >> bytes;
- if (iss.bad() || iss.fail() || (bytes.size() % 2) != 0) {
+ // Hexadecimal encoding of RDATA: each segment must consist of an even
+ // number of hex digits.
+ if ((iss.rdstate() & (ios::badbit | ios::failbit)) != 0 ||
+ (bytes.size() % 2) != 0) {
dns_throw(InvalidRdataText,
"Invalid hex encoding of generic RDATA");
}
for (int pos = 0; pos < bytes.size(); pos += 2) {
+ istringstream iss_hex(bytes.substr(pos, 2));
+
unsigned int ch;
- istringstream(bytes.substr(pos, 2)) >> hex >> ch;
- data_.push_back(ch);
+ iss_hex >> hex >> ch;
+ if (iss_hex.rdstate() != ios::eofbit) {
+ dns_throw(InvalidRdataText,
+ "Invalid hex encoding of generic RDATA");
+ }
+ data.push_back(ch);
}
}
- if (data_.size() != rdlen) {
+ if (data.size() != rdlen) {
dns_throw(InvalidRdataLength,
"Generic RDATA code doesn't match RDLENGTH");
}
+
+ impl_ = new GenericImpl(data);
+}
+
+Generic::Generic(const Generic& source) :
+ impl_(new GenericImpl(*source.impl_))
+{}
+
+Generic&
+Generic::operator=(const Generic& source)
+{
+ if (impl_ == source.impl_) {
+ return (*this);
+ }
+
+ GenericImpl* newimpl = new GenericImpl(*impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
}
namespace {
@@ -158,10 +203,10 @@
{
ostringstream oss;
- oss << "\\# " << data_.size() << " ";
+ oss << "\\# " << impl_->data_.size() << " ";
oss.fill('0');
oss << right << hex;
- for_each(data_.begin(), data_.end(), UnknownRdataDumper(oss));
+ for_each(impl_->data_.begin(), impl_->data_.end(), UnknownRdataDumper(oss));
return (oss.str());
}
@@ -169,13 +214,13 @@
void
Generic::toWire(OutputBuffer& buffer) const
{
- buffer.writeData(&data_[0], data_.size());
+ buffer.writeData(&impl_->data_[0], impl_->data_.size());
}
void
Generic::toWire(MessageRenderer& renderer) const
{
- renderer.writeData(&data_[0], data_.size());
+ renderer.writeData(&impl_->data_[0], impl_->data_.size());
}
int
@@ -183,12 +228,13 @@
{
const Generic& other_rdata = dynamic_cast<const Generic&>(other);
- size_t this_len = data_.size();
- size_t other_len = other_rdata.data_.size();
+ size_t this_len = impl_->data_.size();
+ size_t other_len = other_rdata.impl_->data_.size();
size_t len = (this_len < other_len) ? this_len : other_len;
int cmp;
- if ((cmp = memcmp(&data_[0], &other_rdata.data_[0], len)) != 0) {
+ if ((cmp = memcmp(&impl_->data_[0], &other_rdata.impl_->data_[0], len))
+ != 0) {
return (cmp);
} else {
return ((this_len == other_len) ? 0 :
Modified: branches/jinmei-dnsrdata2/src/lib/dns/cpp/rdata.h
==============================================================================
--- branches/jinmei-dnsrdata2/src/lib/dns/cpp/rdata.h (original)
+++ branches/jinmei-dnsrdata2/src/lib/dns/cpp/rdata.h Tue Feb 9 05:03:48 2010
@@ -117,10 +117,14 @@
};
namespace generic {
+struct GenericImpl;
+
class Generic : public Rdata {
public:
explicit Generic(const std::string& rdata_string);
explicit Generic(InputBuffer& buffer, size_t rdata_len);
+ explicit Generic(const Generic& source);
+ Generic& operator=(const Generic& source);
virtual std::string toText() const;
virtual void toWire(OutputBuffer& buffer) const;
virtual void toWire(MessageRenderer& renderer) const;
@@ -131,7 +135,7 @@
///
virtual int compare(const Rdata& other) const;
private:
- std::vector<uint8_t> data_;
+ GenericImpl* impl_;
};
} // end of namespace "generic"
More information about the bind10-changes
mailing list