encoding: optimize Block::encode
refs #4159
Change-Id: I1436e8211262d19195ac630b4c37c5d5c20b41ff
diff --git a/src/encoding/block.cpp b/src/encoding/block.cpp
index 3aa2701..09acafd 100644
--- a/src/encoding/block.cpp
+++ b/src/encoding/block.cpp
@@ -27,6 +27,7 @@
#include "tlv.hpp"
#include <boost/asio/buffer.hpp>
+#include <boost/range/adaptor/reversed.hpp>
namespace ndn {
@@ -368,49 +369,52 @@
if (hasWire())
return;
- OBufferStream os;
- tlv::writeVarNumber(os, type());
+ EncodingEstimator estimator;
+ size_t estimatedSize = encode(estimator);
+ EncodingBuffer buffer(estimatedSize, 0);
+ encode(buffer);
+}
+
+size_t
+Block::encode(EncodingEstimator& estimator) const
+{
if (hasValue()) {
- tlv::writeVarNumber(os, value_size());
- os.write(reinterpret_cast<const char*>(value()), value_size());
+ return m_size;
}
- else if (m_elements.size() == 0) {
- tlv::writeVarNumber(os, 0);
+
+ size_t len = 0;
+ for (const Block& element : m_elements | boost::adaptors::reversed) {
+ len += element.encode(estimator);
+ }
+ len += estimator.prependVarNumber(len);
+ len += estimator.prependVarNumber(m_type);
+ return len;
+}
+
+size_t
+Block::encode(EncodingBuffer& encoder)
+{
+ size_t len = 0;
+ m_end = encoder.begin();
+ if (hasValue()) {
+ len += encoder.prependRange(m_valueBegin, m_valueEnd);
}
else {
- size_t valueSize = 0;
- for (element_const_iterator i = m_elements.begin(); i != m_elements.end(); ++i) {
- valueSize += i->size();
- }
-
- tlv::writeVarNumber(os, valueSize);
-
- for (element_const_iterator i = m_elements.begin(); i != m_elements.end(); ++i) {
- if (i->hasWire())
- os.write(reinterpret_cast<const char*>(i->wire()), i->size());
- else if (i->hasValue()) {
- tlv::writeVarNumber(os, i->type());
- tlv::writeVarNumber(os, i->value_size());
- os.write(reinterpret_cast<const char*>(i->value()), i->value_size());
- }
- else
- BOOST_THROW_EXCEPTION(Error("Underlying value buffer is empty"));
+ for (Block& element : m_elements | boost::adaptors::reversed) {
+ len += element.encode(encoder);
}
}
+ m_valueEnd = m_end;
+ m_valueBegin = encoder.begin();
- // now assign correct block
+ len += encoder.prependVarNumber(len);
+ len += encoder.prependVarNumber(m_type);
+ m_begin = encoder.begin();
- m_buffer = os.buf();
- m_begin = m_buffer->begin();
- m_end = m_buffer->end();
- m_size = m_end - m_begin;
-
- m_valueBegin = m_buffer->begin();
- m_valueEnd = m_buffer->end();
-
- tlv::readType(m_valueBegin, m_valueEnd);
- tlv::readVarNumber(m_valueBegin, m_valueEnd);
+ m_buffer = encoder.getBuffer();
+ m_size = len;
+ return len;
}
const Block&
diff --git a/src/encoding/block.hpp b/src/encoding/block.hpp
index 91ab51c..031b00f 100644
--- a/src/encoding/block.hpp
+++ b/src/encoding/block.hpp
@@ -385,6 +385,19 @@
*/
operator boost::asio::const_buffer() const;
+private:
+ /** @brief Estimate Block size as if sub elements are encoded into TLV-VALUE
+ */
+ size_t
+ encode(EncodingEstimator& estimator) const;
+
+ /** @brief Encode sub elements into TLV-VALUE and prepend Block to encoder
+ * @post TLV-VALUE contains sub elements from elements()
+ * @post internal buffer and iterators point to Encoder's buffer
+ */
+ size_t
+ encode(EncodingBuffer& encoder);
+
protected:
/** @brief underlying buffer storing TLV-VALUE and possibly TLV-TYPE and TLV-LENGTH fields
*