diff options
Diffstat (limited to 'qpid/cpp/src')
| -rw-r--r-- | qpid/cpp/src/qpid/framing/FieldTable.cpp | 156 |
1 files changed, 118 insertions, 38 deletions
diff --git a/qpid/cpp/src/qpid/framing/FieldTable.cpp b/qpid/cpp/src/qpid/framing/FieldTable.cpp index d5c42c3ade..9d33093df8 100644 --- a/qpid/cpp/src/qpid/framing/FieldTable.cpp +++ b/qpid/cpp/src/qpid/framing/FieldTable.cpp @@ -31,25 +31,11 @@ namespace qpid { namespace framing { -FieldTable::FieldTable() : cachedSize(0) +FieldTable::FieldTable() : + cachedSize(0) { } -FieldTable::FieldTable(const FieldTable& ft) -{ - *this = ft; -} - -FieldTable& FieldTable::operator=(const FieldTable& ft) -{ - clear(); - values = ft.values; - cachedSize = ft.cachedSize; - return *this; -} - -FieldTable::~FieldTable() {} - uint32_t FieldTable::encodedSize() const { if (cachedSize != 0) { return cachedSize; @@ -75,6 +61,7 @@ std::ostream& operator<<(std::ostream& out, const FieldTable::ValueMap::value_ty } std::ostream& operator<<(std::ostream& out, const FieldTable& t) { + t.realDecode(); out << "{"; FieldTable::ValueMap::const_iterator i = t.begin(); if (i != t.end()) out << *i++; @@ -86,58 +73,70 @@ std::ostream& operator<<(std::ostream& out, const FieldTable& t) { } void FieldTable::set(const std::string& name, const ValuePtr& value){ + realDecode(); values[name] = value; - cachedSize = 0; + flushRawCache(); } void FieldTable::setString(const std::string& name, const std::string& value){ + realDecode(); values[name] = ValuePtr(new Str16Value(value)); - cachedSize = 0; + flushRawCache(); } void FieldTable::setInt(const std::string& name, const int value){ + realDecode(); values[name] = ValuePtr(new IntegerValue(value)); - cachedSize = 0; + flushRawCache(); } void FieldTable::setInt64(const std::string& name, const int64_t value){ + realDecode(); values[name] = ValuePtr(new Integer64Value(value)); - cachedSize = 0; + flushRawCache(); } void FieldTable::setTimestamp(const std::string& name, const uint64_t value){ + realDecode(); values[name] = ValuePtr(new TimeValue(value)); - cachedSize = 0; + flushRawCache(); } void FieldTable::setUInt64(const std::string& name, const uint64_t value){ + realDecode(); values[name] = ValuePtr(new Unsigned64Value(value)); - cachedSize = 0; + flushRawCache(); } void FieldTable::setTable(const std::string& name, const FieldTable& value) { + realDecode(); values[name] = ValuePtr(new FieldTableValue(value)); - cachedSize = 0; + flushRawCache(); } void FieldTable::setArray(const std::string& name, const Array& value) { + realDecode(); values[name] = ValuePtr(new ArrayValue(value)); - cachedSize = 0; + flushRawCache(); } void FieldTable::setFloat(const std::string& name, const float value){ + realDecode(); values[name] = ValuePtr(new FloatValue(value)); - cachedSize = 0; + flushRawCache(); } void FieldTable::setDouble(const std::string& name, double value){ + realDecode(); values[name] = ValuePtr(new DoubleValue(value)); - cachedSize = 0; + flushRawCache(); } FieldTable::ValuePtr FieldTable::get(const std::string& name) const { + // Ensure we have any values we're trying to read + realDecode(); ValuePtr value; ValueMap::const_iterator i = values.find(name); if ( i!=values.end() ) @@ -207,38 +206,76 @@ bool FieldTable::getDouble(const std::string& name, double& value) const { //} void FieldTable::encode(Buffer& buffer) const { - buffer.putLong(encodedSize() - 4); - buffer.putLong(values.size()); - for (ValueMap::const_iterator i = values.begin(); i!=values.end(); ++i) { - buffer.putShortString(i->first); - i->second->encode(buffer); + // If we've still got the input field table + // we can just copy it directly to the output + if (cachedBytes) { + buffer.putRawData(&cachedBytes[0], cachedSize); + } else { + buffer.putLong(encodedSize() - 4); + buffer.putLong(values.size()); + for (ValueMap::const_iterator i = values.begin(); i!=values.end(); ++i) { + buffer.putShortString(i->first); + i->second->encode(buffer); + } } } +// Decode lazily - just record the raw bytes until we need them void FieldTable::decode(Buffer& buffer){ clear(); if (buffer.available() < 4) throw IllegalArgumentException(QPID_MSG("Not enough data for field table.")); + uint32_t p = buffer.getPosition(); uint32_t len = buffer.getLong(); if (len) { uint32_t available = buffer.available(); if ((available < len) || (available < 4)) throw IllegalArgumentException(QPID_MSG("Not enough data for field table.")); + } + // Copy data into our buffer + cachedBytes = boost::shared_array<uint8_t>(new uint8_t[len + 4]); + cachedSize = len + 4; + buffer.setPosition(p); + buffer.getRawData(&cachedBytes[0], cachedSize); +} + +void FieldTable::realDecode() const +{ + // If we've got no raw data stored up then nothing to do + if (!cachedBytes) + return; + + Buffer buffer((char*)&cachedBytes[0], cachedSize); + uint32_t len = buffer.getLong(); + if (len) { + uint32_t available = buffer.available(); uint32_t count = buffer.getLong(); uint32_t leftover = available - len; while(buffer.available() > leftover && count--){ std::string name; ValuePtr value(new FieldValue); - + buffer.getShortString(name); value->decode(buffer); values[name] = ValuePtr(value); - } + } } + cachedSize = len + 4; + // We've done the delayed decoding throw away the raw data + // (later on we may find a way to keep this and avoid some + // other allocations) + cachedBytes.reset(); +} + +void FieldTable::flushRawCache() const +{ + cachedBytes.reset(); cachedSize = 0; } bool FieldTable::operator==(const FieldTable& x) const { + realDecode(); + x.realDecode(); if (values.size() != x.values.size()) return false; for (ValueMap::const_iterator i = values.begin(); i != values.end(); ++i) { ValueMap::const_iterator j = x.values.find(i->first); @@ -250,29 +287,72 @@ bool FieldTable::operator==(const FieldTable& x) const { void FieldTable::erase(const std::string& name) { + realDecode(); if (values.find(name) != values.end()) { values.erase(name); - cachedSize = 0; + flushRawCache(); } } + void FieldTable::clear() { values.clear(); - cachedSize = 0; + flushRawCache(); +} + +// Map-like interface. +FieldTable::ValueMap::const_iterator FieldTable::begin() const +{ + realDecode(); + return values.begin(); +} + +FieldTable::ValueMap::const_iterator FieldTable::end() const +{ + realDecode(); + return values.end(); +} + +FieldTable::ValueMap::const_iterator FieldTable::find(const std::string& s) const +{ + realDecode(); + return values.find(s); +} + +FieldTable::ValueMap::iterator FieldTable::begin() +{ + realDecode(); + flushRawCache(); + return values.begin(); +} + +FieldTable::ValueMap::iterator FieldTable::end() +{ + realDecode(); + flushRawCache(); + return values.end(); +} + +FieldTable::ValueMap::iterator FieldTable::find(const std::string& s) +{ + realDecode(); + flushRawCache(); + return values.find(s); } std::pair<FieldTable::ValueMap::iterator, bool> FieldTable::insert(const ValueMap::value_type& value) { - cachedSize = 0; + realDecode(); + flushRawCache(); return values.insert(value); } FieldTable::ValueMap::iterator FieldTable::insert(ValueMap::iterator position, const ValueMap::value_type& value) { - cachedSize = 0; + realDecode(); + flushRawCache(); return values.insert(position, value); } - } } |
