summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmir Taaki <genjix@riseup.net>2014-04-01 03:02:28 (GMT)
committer Amir Taaki <genjix@riseup.net>2014-04-01 03:04:07 (GMT)
commitc40a86b11c20c259342f2966562513cb33667eff (patch)
tree197c790c0c32456fe18da70fb875eeb94876a091
parent24e8268c1e6ed3649f086c484be393e41273c74c (diff)
tidy serializer by moving implementation to .ipp file.
-rw-r--r--include/bitcoin/Makefile.am4
-rw-r--r--include/bitcoin/impl/utility/serializer.ipp359
-rw-r--r--include/bitcoin/utility/serializer.hpp293
3 files changed, 416 insertions, 240 deletions
diff --git a/include/bitcoin/Makefile.am b/include/bitcoin/Makefile.am
index 412fb41..fb10876 100644
--- a/include/bitcoin/Makefile.am
+++ b/include/bitcoin/Makefile.am
@@ -65,3 +65,7 @@ bitcoin_util_include_HEADERS = \
utility/weak_bind.hpp \
utility/timed_section.hpp
+bitcoin_impl_utility_includedir = $(includedir)/bitcoin/impl/utility
+bitcoin_impl_utility_include_HEADERS = \
+ impl/utility/serializer.ipp
+
diff --git a/include/bitcoin/impl/utility/serializer.ipp b/include/bitcoin/impl/utility/serializer.ipp
new file mode 100644
index 0000000..5157ba2
--- /dev/null
+++ b/include/bitcoin/impl/utility/serializer.ipp
@@ -0,0 +1,359 @@
+/*
+ * Copyright (c) 2011-2013 libbitcoin developers (see AUTHORS)
+ *
+ * This file is part of libbitcoin.
+ *
+ * libbitcoin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License with
+ * additional permissions to the one published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option)
+ * any later version. For more information see LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef LIBBITCOIN_SERIALIZER_IPP
+#define LIBBITCOIN_SERIALIZER_IPP
+
+namespace libbitcoin {
+
+template <typename Iterator>
+serializer<Iterator>::serializer(const Iterator begin)
+ : iter_(begin)
+{
+}
+
+template <typename Iterator>
+template <typename T>
+void serializer<Iterator>::write_uint_auto(T value)
+{
+ write_data(uncast_type(value));
+}
+
+template <typename Iterator>
+void serializer<Iterator>::write_byte(uint8_t value)
+{
+ *iter_ = value;
+ ++iter_;
+}
+template <typename Iterator>
+void serializer<Iterator>::write_2_bytes(uint16_t value)
+{
+ write_uint_auto(value);
+}
+template <typename Iterator>
+void serializer<Iterator>::write_4_bytes(uint32_t value)
+{
+ write_uint_auto(value);
+}
+template <typename Iterator>
+void serializer<Iterator>::write_8_bytes(uint64_t value)
+{
+ write_uint_auto(value);
+}
+
+template <typename Iterator>
+void serializer<Iterator>::write_variable_uint(uint64_t value)
+{
+ if (value < 0xfd)
+ {
+ write_byte((uint8_t)value);
+ }
+ else if (value <= 0xffff)
+ {
+ write_byte(0xfd);
+ write_2_bytes((uint16_t)value);
+ }
+ else if (value <= 0xffffffff)
+ {
+ write_byte(0xfe);
+ write_4_bytes((uint32_t)value);
+ }
+ else
+ {
+ write_byte(0xff);
+ write_8_bytes(value);
+ }
+}
+
+template <typename Iterator>
+template <typename T>
+void serializer<Iterator>::write_data(const T& data)
+{
+ internal_copy(data.begin(), data.end());
+}
+
+template <typename Iterator>
+void serializer<Iterator>::write_network_address(network_address_type addr)
+{
+ write_8_bytes(addr.services);
+ write_data(addr.ip);
+ write_data(uncast_type(addr.port, true));
+}
+
+template <typename Iterator>
+void serializer<Iterator>::write_hash(const hash_digest& hash)
+{
+ write_data_reverse(hash);
+}
+
+template <typename Iterator>
+void serializer<Iterator>::write_short_hash(const short_hash& hash)
+{
+ write_data_reverse(hash);
+}
+
+template <typename Iterator>
+void serializer<Iterator>::write_fixed_string(
+ const std::string& command, size_t string_size)
+{
+ BITCOIN_ASSERT(command.size() <= string_size);
+ data_chunk raw_string(string_size);
+ std::copy(command.begin(), command.end(), raw_string.begin());
+ write_data(raw_string);
+}
+
+template <typename Iterator>
+void serializer<Iterator>::write_string(const std::string& str)
+{
+ write_variable_uint(str.size());
+ write_data(str);
+}
+
+/**
+ * Returns underlying iterator.
+ */
+template <typename Iterator>
+Iterator serializer<Iterator>::iterator()
+{
+ return iter_;
+}
+
+/**
+ * Useful if you want to serialize some data using another
+ * routine and then continue with this serializer.
+ */
+template <typename Iterator>
+void serializer<Iterator>::set_iterator(Iterator iter)
+{
+ iter_ = iter;
+}
+
+template <typename Iterator>
+template <typename T>
+void serializer<Iterator>::write_data_reverse(const T& data)
+{
+ internal_copy(data.rbegin(), data.rend());
+}
+
+// We need to advance the internal iterator.
+// std::copy gives no info on length of the data copied.
+template <typename Iterator>
+template <typename InputIterator>
+void serializer<Iterator>::internal_copy(
+ InputIterator first, InputIterator last)
+{
+ while (first != last)
+ {
+ *iter_ = *first;
+ ++first;
+ ++iter_;
+ }
+}
+
+template <typename Iterator>
+serializer<Iterator> make_serializer(Iterator begin)
+{
+ return serializer<Iterator>(begin);
+}
+
+template <typename Iterator>
+deserializer<Iterator>::deserializer(const Iterator begin, const Iterator end)
+ : iter_(begin), end_(end)
+{
+}
+
+template <typename Iterator>
+template <typename T>
+const T deserializer<Iterator>::read_uint_auto()
+{
+ return read_data_impl<T>(iter_, end_);
+}
+
+template <typename Iterator>
+uint8_t deserializer<Iterator>::read_byte()
+{
+ check_distance(iter_, end_, 1);
+ return *(iter_++);
+}
+template <typename Iterator>
+uint16_t deserializer<Iterator>::read_2_bytes()
+{
+ return read_uint_auto<uint16_t>();
+}
+template <typename Iterator>
+uint32_t deserializer<Iterator>::read_4_bytes()
+{
+ return read_uint_auto<uint32_t>();
+}
+template <typename Iterator>
+uint64_t deserializer<Iterator>::read_8_bytes()
+{
+ return read_uint_auto<uint64_t>();
+}
+
+template <typename Iterator>
+uint64_t deserializer<Iterator>::read_variable_uint()
+{
+ uint8_t length = read_byte();
+ if (length < 0xfd)
+ return length;
+ else if (length == 0xfd)
+ return read_2_bytes();
+ else if (length == 0xfe)
+ return read_4_bytes();
+ // length should be 0xff
+ return read_8_bytes();
+}
+
+// NOTE: n_bytes changed to uint32_t to prevent array overflow.
+template <typename Iterator>
+data_chunk deserializer<Iterator>::read_data(uint32_t n_bytes)
+{
+ check_distance(iter_, end_, n_bytes);
+ data_chunk raw_bytes(n_bytes);
+ for (uint32_t i = 0; i < n_bytes; ++i)
+ raw_bytes[i] = read_byte();
+ return raw_bytes;
+}
+
+template <typename Iterator>
+network_address_type deserializer<Iterator>::read_network_address()
+{
+ network_address_type addr;
+ addr.services = read_8_bytes();
+ // Read IP address
+ read_bytes<16>(iter_, end_, addr.ip);
+ addr.port = read_data_impl<uint16_t>(iter_, end_, true);
+ return addr;
+}
+
+template <typename Iterator>
+hash_digest deserializer<Iterator>::read_hash()
+{
+ hash_digest hash;
+ read_bytes<32>(iter_, end_, hash, true);
+ return hash;
+}
+
+template <typename Iterator>
+short_hash deserializer<Iterator>::read_short_hash()
+{
+ short_hash hash;
+ read_bytes<20>(iter_, end_, hash, true);
+ return hash;
+}
+
+template <typename Iterator>
+std::string deserializer<Iterator>::read_fixed_string(size_t len)
+{
+ data_chunk string_bytes = read_data(len);
+ std::string result(string_bytes.begin(), string_bytes.end());
+ // Removes trailing 0s... Needed for string comparisons
+ return result.c_str();
+}
+
+template <typename Iterator>
+std::string deserializer<Iterator>::read_string()
+{
+ uint64_t string_size = read_variable_uint();
+ // Warning: conversion from uint64_t to size_t, possible loss of data.
+ return read_fixed_string((size_t)string_size);
+}
+
+/**
+ * Returns underlying iterator.
+ */
+template <typename Iterator>
+Iterator deserializer<Iterator>::iterator() const
+{
+ return iter_;
+}
+
+/**
+ * Useful if you advance the iterator using other serialization
+ * methods or objects.
+ */
+template <typename Iterator>
+void deserializer<Iterator>::set_iterator(const Iterator iter)
+{
+ iter_ = iter;
+}
+
+// Try to advance iterator 'distance' incremenets forwards.
+// Throw if we prematurely reach the end.
+template <typename Iterator>
+void deserializer<Iterator>::check_distance(
+ Iterator it, const Iterator end, size_t distance)
+{
+ for (size_t i = 0; i < distance; ++i)
+ {
+ // Is this a valid byte?
+ if (it == end)
+ throw end_of_stream();
+ // If so move to next value.
+ ++it;
+ }
+}
+
+template <typename Iterator>
+template <typename T>
+T deserializer<Iterator>::read_data_impl(
+ Iterator& begin, const Iterator end, bool reverse)
+{
+ check_distance(begin, end, sizeof(T));
+ data_chunk chunk(begin, begin + sizeof(T));
+ T val = cast_chunk<T>(chunk, reverse);
+ begin += sizeof(T);
+ return val;
+}
+
+template <typename Iterator>
+template <unsigned int N>
+void deserializer<Iterator>::read_bytes(
+ Iterator& begin, const Iterator& end,
+ std::array<uint8_t, N>& byte_array, bool reverse)
+{
+ check_distance(begin, end, byte_array.size());
+#ifdef BOOST_LITTLE_ENDIAN
+ // do nothing
+#elif BOOST_BIG_ENDIAN
+ reverse = !reverse;
+#else
+ #error "Endian isn't defined!"
+#endif
+
+ if (reverse)
+ std::reverse_copy(
+ begin, begin + byte_array.size(), byte_array.begin());
+ else
+ std::copy(begin, begin + byte_array.size(), byte_array.begin());
+ begin += byte_array.size();
+}
+
+template <typename Iterator>
+deserializer<Iterator> make_deserializer(
+ const Iterator begin, const Iterator end)
+{
+ return deserializer<Iterator>(begin, end);
+}
+
+} // libbitcoin
+
+#endif
+
diff --git a/include/bitcoin/utility/serializer.hpp b/include/bitcoin/utility/serializer.hpp
index b471675..d59673b 100644
--- a/include/bitcoin/utility/serializer.hpp
+++ b/include/bitcoin/utility/serializer.hpp
@@ -52,138 +52,56 @@ template <typename Iterator>
class serializer
{
public:
- serializer(const Iterator begin)
- : iter_(begin) {}
+ serializer(const Iterator begin);
template <typename T>
- void write_uint_auto(T value)
- {
- write_data(uncast_type(value));
- }
-
- void write_byte(uint8_t value)
- {
- *iter_ = value;
- ++iter_;
- }
- void write_2_bytes(uint16_t value)
- {
- write_uint_auto(value);
- }
- void write_4_bytes(uint32_t value)
- {
- write_uint_auto(value);
- }
- void write_8_bytes(uint64_t value)
- {
- write_uint_auto(value);
- }
-
- void write_variable_uint(uint64_t value)
- {
- if (value < 0xfd)
- {
- write_byte((uint8_t)value);
- }
- else if (value <= 0xffff)
- {
- write_byte(0xfd);
- write_2_bytes((uint16_t)value);
- }
- else if (value <= 0xffffffff)
- {
- write_byte(0xfe);
- write_4_bytes((uint32_t)value);
- }
- else
- {
- write_byte(0xff);
- write_8_bytes(value);
- }
- }
+ void write_uint_auto(T value);
+
+ void write_byte(uint8_t value);
+ void write_2_bytes(uint16_t value);
+ void write_4_bytes(uint32_t value);
+ void write_8_bytes(uint64_t value);
+
+ void write_variable_uint(uint64_t value);
template <typename T>
- void write_data(const T& data)
- {
- internal_copy(data.begin(), data.end());
- }
-
- void write_network_address(network_address_type addr)
- {
- write_8_bytes(addr.services);
- write_data(addr.ip);
- write_data(uncast_type(addr.port, true));
- }
-
- void write_hash(const hash_digest& hash)
- {
- write_data_reverse(hash);
- }
-
- void write_short_hash(const short_hash& hash)
- {
- write_data_reverse(hash);
- }
-
- void write_fixed_string(const std::string& command, size_t string_size)
- {
- BITCOIN_ASSERT(command.size() <= string_size);
- data_chunk raw_string(string_size);
- std::copy(command.begin(), command.end(), raw_string.begin());
- write_data(raw_string);
- }
-
- void write_string(const std::string& str)
- {
- write_variable_uint(str.size());
- write_data(str);
- }
+ void write_data(const T& data);
+
+ void write_network_address(network_address_type addr);
+
+ void write_hash(const hash_digest& hash);
+
+ void write_short_hash(const short_hash& hash);
+
+ void write_fixed_string(const std::string& command, size_t string_size);
+
+ void write_string(const std::string& str);
/**
* Returns underlying iterator.
*/
- Iterator iterator()
- {
- return iter_;
- }
+ Iterator iterator();
/**
* Useful if you want to serialize some data using another
* routine and then continue with this serializer.
*/
- void set_iterator(Iterator iter)
- {
- iter_ = iter;
- }
+ void set_iterator(Iterator iter);
private:
template <typename T>
- void write_data_reverse(const T& data)
- {
- internal_copy(data.rbegin(), data.rend());
- }
+ void write_data_reverse(const T& data);
// We need to advance the internal iterator.
// std::copy gives no info on length of the data copied.
template <typename InputIterator>
- void internal_copy(InputIterator first, InputIterator last)
- {
- while (first != last)
- {
- *iter_ = *first;
- ++first;
- ++iter_;
- }
- }
+ void internal_copy(InputIterator first, InputIterator last);
Iterator iter_;
};
template <typename Iterator>
-serializer<Iterator> make_serializer(Iterator begin)
-{
- return serializer<Iterator>(begin);
-}
+serializer<Iterator> make_serializer(Iterator begin);
class end_of_stream
: std::exception {};
@@ -211,159 +129,55 @@ template <typename Iterator>
class deserializer
{
public:
- deserializer(const Iterator begin, const Iterator end)
- : iter_(begin), end_(end) {}
+ deserializer(const Iterator begin, const Iterator end);
template <typename T>
- const T read_uint_auto()
- {
- return read_data_impl<T>(iter_, end_);
- }
-
- uint8_t read_byte()
- {
- check_distance(iter_, end_, 1);
- return *(iter_++);
- }
- uint16_t read_2_bytes()
- {
- return read_uint_auto<uint16_t>();
- }
- uint32_t read_4_bytes()
- {
- return read_uint_auto<uint32_t>();
- }
- uint64_t read_8_bytes()
- {
- return read_uint_auto<uint64_t>();
- }
-
- uint64_t read_variable_uint()
- {
- uint8_t length = read_byte();
- if (length < 0xfd)
- return length;
- else if (length == 0xfd)
- return read_2_bytes();
- else if (length == 0xfe)
- return read_4_bytes();
- // length should be 0xff
- return read_8_bytes();
- }
+ const T read_uint_auto();
+
+ uint8_t read_byte();
+ uint16_t read_2_bytes();
+ uint32_t read_4_bytes();
+ uint64_t read_8_bytes();
+
+ uint64_t read_variable_uint();
// NOTE: n_bytes changed to uint32_t to prevent array overflow.
- data_chunk read_data(uint32_t n_bytes)
- {
- check_distance(iter_, end_, n_bytes);
- data_chunk raw_bytes(n_bytes);
- for (uint32_t i = 0; i < n_bytes; ++i)
- raw_bytes[i] = read_byte();
- return raw_bytes;
- }
-
- network_address_type read_network_address()
- {
- network_address_type addr;
- addr.services = read_8_bytes();
- // Read IP address
- read_bytes<16>(iter_, end_, addr.ip);
- addr.port = read_data_impl<uint16_t>(iter_, end_, true);
- return addr;
- }
-
- hash_digest read_hash()
- {
- hash_digest hash;
- read_bytes<32>(iter_, end_, hash, true);
- return hash;
- }
-
- short_hash read_short_hash()
- {
- short_hash hash;
- read_bytes<20>(iter_, end_, hash, true);
- return hash;
- }
-
- std::string read_fixed_string(size_t len)
- {
- data_chunk string_bytes = read_data(len);
- std::string result(string_bytes.begin(), string_bytes.end());
- // Removes trailing 0s... Needed for string comparisons
- return result.c_str();
- }
-
- std::string read_string()
- {
- uint64_t string_size = read_variable_uint();
- // Warning: conversion from uint64_t to size_t, possible loss of data.
- return read_fixed_string((size_t)string_size);
- }
+ data_chunk read_data(uint32_t n_bytes);
+
+ network_address_type read_network_address();
+
+ hash_digest read_hash();
+
+ short_hash read_short_hash();
+
+ std::string read_fixed_string(size_t len);
+
+ std::string read_string();
/**
* Returns underlying iterator.
*/
- Iterator iterator() const
- {
- return iter_;
- }
+ Iterator iterator() const;
/**
* Useful if you advance the iterator using other serialization
* methods or objects.
*/
- void set_iterator(const Iterator iter)
- {
- iter_ = iter;
- }
+ void set_iterator(const Iterator iter);
private:
// Try to advance iterator 'distance' incremenets forwards.
// Throw if we prematurely reach the end.
static void check_distance(
- Iterator it, const Iterator end, size_t distance)
- {
- for (size_t i = 0; i < distance; ++i)
- {
- // Is this a valid byte?
- if (it == end)
- throw end_of_stream();
- // If so move to next value.
- ++it;
- }
- }
+ Iterator it, const Iterator end, size_t distance);
template <typename T>
static T read_data_impl(
- Iterator& begin, const Iterator end, bool reverse=false)
- {
- check_distance(begin, end, sizeof(T));
- data_chunk chunk(begin, begin + sizeof(T));
- T val = cast_chunk<T>(chunk, reverse);
- begin += sizeof(T);
- return val;
- }
+ Iterator& begin, const Iterator end, bool reverse=false);
template <unsigned int N>
static void read_bytes(Iterator& begin, const Iterator& end,
- std::array<uint8_t, N>& byte_array, bool reverse=false)
- {
- check_distance(begin, end, byte_array.size());
- #ifdef BOOST_LITTLE_ENDIAN
- // do nothing
- #elif BOOST_BIG_ENDIAN
- reverse = !reverse;
- #else
- #error "Endian isn't defined!"
- #endif
-
- if (reverse)
- std::reverse_copy(
- begin, begin + byte_array.size(), byte_array.begin());
- else
- std::copy(begin, begin + byte_array.size(), byte_array.begin());
- begin += byte_array.size();
- }
+ std::array<uint8_t, N>& byte_array, bool reverse=false);
Iterator iter_;
const Iterator end_;
@@ -371,12 +185,11 @@ private:
template <typename Iterator>
deserializer<Iterator> make_deserializer(
- const Iterator begin, const Iterator end)
-{
- return deserializer<Iterator>(begin, end);
-}
+ const Iterator begin, const Iterator end);
} // namespace libbitcoin
+#include <bitcoin/impl/utility/serializer.ipp>
+
#endif