summaryrefslogtreecommitdiff
path: root/qpid/cpp
diff options
context:
space:
mode:
Diffstat (limited to 'qpid/cpp')
-rw-r--r--qpid/cpp/include/qpid/framing/FieldTable.h4
-rw-r--r--qpid/cpp/src/qpid/framing/FieldTable.cpp36
2 files changed, 32 insertions, 8 deletions
diff --git a/qpid/cpp/include/qpid/framing/FieldTable.h b/qpid/cpp/include/qpid/framing/FieldTable.h
index b404a06c9a..2592e8f124 100644
--- a/qpid/cpp/include/qpid/framing/FieldTable.h
+++ b/qpid/cpp/include/qpid/framing/FieldTable.h
@@ -58,7 +58,9 @@ class FieldTable
typedef ValueMap::value_type value_type;
QPID_COMMON_EXTERN FieldTable();
- // Compiler default copy, assignment and destructor are fine
+ QPID_COMMON_EXTERN FieldTable(const FieldTable&);
+ QPID_COMMON_EXTERN FieldTable& operator=(const FieldTable&);
+ // Compiler default destructor fine
QPID_COMMON_EXTERN uint32_t encodedSize() const;
QPID_COMMON_EXTERN void encode(Buffer& buffer) const;
QPID_COMMON_EXTERN void decode(Buffer& buffer);
diff --git a/qpid/cpp/src/qpid/framing/FieldTable.cpp b/qpid/cpp/src/qpid/framing/FieldTable.cpp
index 9d33093df8..b696b5e54f 100644
--- a/qpid/cpp/src/qpid/framing/FieldTable.cpp
+++ b/qpid/cpp/src/qpid/framing/FieldTable.cpp
@@ -36,6 +36,25 @@ FieldTable::FieldTable() :
{
}
+FieldTable::FieldTable(const FieldTable& ft) :
+ cachedBytes(ft.cachedBytes),
+ cachedSize(ft.cachedSize)
+{
+ // Only copy the values if we have no raw data
+ // - copying the map is expensive and we can
+ // reconstruct it if necessary from the raw data
+ if (!cachedBytes && !ft.values.empty()) values = ft.values;
+}
+
+FieldTable& FieldTable::operator=(const FieldTable& ft)
+{
+ FieldTable nft(ft);
+ values.swap(nft.values);
+ cachedBytes.swap(nft.cachedBytes);
+ cachedSize = nft.cachedSize;
+ return (*this);
+}
+
uint32_t FieldTable::encodedSize() const {
if (cachedSize != 0) {
return cachedSize;
@@ -211,18 +230,23 @@ void FieldTable::encode(Buffer& buffer) const {
if (cachedBytes) {
buffer.putRawData(&cachedBytes[0], cachedSize);
} else {
+ uint32_t p = buffer.getPosition();
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);
}
+ // Now create raw bytes in case we are used again
+ cachedSize = buffer.getPosition() - p;
+ cachedBytes = boost::shared_array<uint8_t>(new uint8_t[cachedSize]);
+ buffer.setPosition(p);
+ buffer.getRawData(&cachedBytes[0], cachedSize);
}
}
// 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();
@@ -232,6 +256,8 @@ void FieldTable::decode(Buffer& buffer){
if ((available < len) || (available < 4))
throw IllegalArgumentException(QPID_MSG("Not enough data for field table."));
}
+ // Throw away previous stored values
+ values.clear();
// Copy data into our buffer
cachedBytes = boost::shared_array<uint8_t>(new uint8_t[len + 4]);
cachedSize = len + 4;
@@ -260,16 +286,12 @@ void FieldTable::realDecode() const
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();
+ // Avoid recreating shared array unless we actually have one.
+ if (cachedBytes) cachedBytes.reset();
cachedSize = 0;
}