aboutsummaryrefslogtreecommitdiff
path: root/src/streams.h
diff options
context:
space:
mode:
authorCory Fields <cory-nospam-@coryfields.com>2016-11-10 17:05:23 -0500
committerCory Fields <cory-nospam-@coryfields.com>2016-11-25 12:09:58 -0500
commit2ec935dcaab9557addcf73c33aa7f2db8cc01fee (patch)
tree3d5d7a29e05f457cee199fd273f24be8fd33550c /src/streams.h
parentb7695c2275d977f20343020f2e9ba5d746928a6e (diff)
downloadbitcoin-2ec935dcaab9557addcf73c33aa7f2db8cc01fee.tar.xz
net: add CVectorWriter and CNetMsgMaker
CVectorWriter is useful for overwriting or appending an existing byte vector. CNetMsgMaker is a shortcut for creating messages on-the-fly which are suitable for pushing to CConnman.
Diffstat (limited to 'src/streams.h')
-rw-r--r--src/streams.h69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/streams.h b/src/streams.h
index c3e7c9e9e4..b508784238 100644
--- a/src/streams.h
+++ b/src/streams.h
@@ -69,6 +69,75 @@ OverrideStream<S> WithOrVersion(S* s, int nVersionFlag)
return OverrideStream<S>(s, s->GetType(), s->GetVersion() | nVersionFlag);
}
+/* Minimal stream for overwriting and/or appending to an existing byte vector
+ *
+ * The referenced vector will grow as necessary
+ */
+class CVectorWriter
+{
+ public:
+
+/*
+ * @param[in] nTypeIn Serialization Type
+ * @param[in] nVersionIn Serialization Version (including any flags)
+ * @param[in] vchDataIn Referenced byte vector to overwrite/append
+ * @param[in] nPosIn Starting position. Vector index where writes should start. The vector will initially
+ * grow as necessary to max(index, vec.size()). So to append, use vec.size().
+*/
+ CVectorWriter(int nTypeIn, int nVersionIn, std::vector<unsigned char>& vchDataIn, size_t nPosIn) : nType(nTypeIn), nVersion(nVersionIn), vchData(vchDataIn), nPos(nPosIn)
+ {
+ if(nPos > vchData.size())
+ vchData.resize(nPos);
+ }
+/*
+ * (other params same as above)
+ * @param[in] args A list of items to serialize starting at nPos.
+*/
+ template <typename... Args>
+ CVectorWriter(int nTypeIn, int nVersionIn, std::vector<unsigned char>& vchDataIn, size_t nPosIn, Args&&... args) : CVectorWriter(nTypeIn, nVersionIn, vchDataIn, nPosIn)
+ {
+ ::SerializeMany(*this, std::forward<Args>(args)...);
+ }
+ void write(const char* pch, size_t nSize)
+ {
+ assert(nPos <= vchData.size());
+ size_t nOverwrite = std::min(nSize, vchData.size() - nPos);
+ if (nOverwrite) {
+ memcpy(vchData.data() + nPos, reinterpret_cast<const unsigned char*>(pch), nOverwrite);
+ }
+ if (nOverwrite < nSize) {
+ vchData.insert(vchData.end(), reinterpret_cast<const unsigned char*>(pch) + nOverwrite, reinterpret_cast<const unsigned char*>(pch) + nSize);
+ }
+ nPos += nSize;
+ }
+ template<typename T>
+ CVectorWriter& operator<<(const T& obj)
+ {
+ // Serialize to this stream
+ ::Serialize(*this, obj);
+ return (*this);
+ }
+ int GetVersion() const
+ {
+ return nVersion;
+ }
+ int GetType() const
+ {
+ return nType;
+ }
+ void seek(size_t nSize)
+ {
+ nPos += nSize;
+ if(nPos > vchData.size())
+ vchData.resize(nPos);
+ }
+private:
+ const int nType;
+ const int nVersion;
+ std::vector<unsigned char>& vchData;
+ size_t nPos;
+};
+
/** Double ended buffer combining vector and stream-like interfaces.
*
* >> and << read and write unformatted data using the above serialization templates.