diff --git a/coding/coding_tests/reader_writer_ops_test.cpp b/coding/coding_tests/reader_writer_ops_test.cpp index 0ca1dccc6a..2004574c90 100644 --- a/coding/coding_tests/reader_writer_ops_test.cpp +++ b/coding/coding_tests/reader_writer_ops_test.cpp @@ -76,6 +76,7 @@ UNIT_TEST(Reverse_Smoke) TEST_EQUAL(str.size(), buffer.size(), ()); TEST(equal(str.begin(), str.end(), buffer.begin()), ()); } + FileWriter::DeleteFileX(tmpFile); } } diff --git a/coding/coding_tests/var_serial_vector_test.cpp b/coding/coding_tests/var_serial_vector_test.cpp index 0afe29cf45..bd0c6d27f1 100644 --- a/coding/coding_tests/var_serial_vector_test.cpp +++ b/coding/coding_tests/var_serial_vector_test.cpp @@ -7,13 +7,45 @@ #include "../../coding/hex.hpp" #include "../../coding/reader.hpp" #include "../../coding/writer.hpp" + #include "../../base/macros.hpp" #include "../../base/pseudo_random.hpp" + #include "../../std/string.hpp" #include "../../std/vector.hpp" + char const kHexSerial[] = "03000000" "01000000" "04000000" "06000000" "616263646566"; +namespace +{ + +template +void WriteVarSerialVector(ItT begin, ItT end, TDstStream & dst) +{ + vector offsets; + uint32_t offset = 0; + for (ItT it = begin; it != end; ++it) + { + offset += it->size() * sizeof((*it)[0]); + offsets.push_back(offset); + } + + WriteToSink(dst, static_cast(end - begin)); + + for (size_t i = 0; i < offsets.size(); ++i) + WriteToSink(dst, offsets[i]); + + for (ItT it = begin; it != end; ++it) + { + typename ItT::value_type const & v = *it; + if (!v.empty()) + dst.Write(&v[0], v.size() * sizeof(v[0])); + } +} + +} + UNIT_TEST(WriteSerial) { vector elements; diff --git a/coding/var_serial_vector.hpp b/coding/var_serial_vector.hpp index 366befb120..2d130f8501 100644 --- a/coding/var_serial_vector.hpp +++ b/coding/var_serial_vector.hpp @@ -1,75 +1,58 @@ #pragma once -#include "endianness.hpp" #include "reader.hpp" #include "write_to_sink.hpp" + #include "../base/assert.hpp" -#include "../base/base.hpp" + #include "../std/string.hpp" #include "../std/utility.hpp" -#include "../std/vector.hpp" -#include "../std/scoped_ptr.hpp" -template -void WriteVarSerialVector(ItT begin, ItT end, TDstStream & dst) -{ - vector offsets; - uint32_t offset = 0; - for (ItT it = begin; it != end; ++it) - { - offset += it->size() * sizeof((*it)[0]); - offsets.push_back(offset); - } - - WriteToSink(dst, static_cast(end - begin)); - - for (size_t i = 0; i < offsets.size(); ++i) - WriteToSink(dst, offsets[i]); - - for (ItT it = begin; it != end; ++it) - { - typename ItT::value_type const & v = *it; - if (!v.empty()) - dst.Write(&v[0], v.size() * sizeof(v[0])); - } -} - template class VarSerialVectorWriter { public: // Actually, it is possible to refactor to accept maxPossibleSize (i.e. capacity) instead of size. VarSerialVectorWriter(WriterT & writer, uint32_t size) - : m_Writer(writer), m_Size(size), m_RecordNumber(0) + : m_writer(writer), m_size(size), m_recordNumber(0) { - WriteToSink(m_Writer, size); - m_SizesOffset = m_Writer.Pos(); - m_Writer.Seek(m_SizesOffset + size * 4); + WriteToSink(m_writer, size); + m_sizesOffset = m_writer.Pos(); + m_writer.Seek(GetDataStartPos()); } ~VarSerialVectorWriter() { - CHECK_EQUAL(m_RecordNumber, m_Size, ()); + CHECK_EQUAL(m_recordNumber, m_size, ()); } void FinishRecord() { - CHECK_LESS(m_RecordNumber, m_Size, ()); - uint64_t const pos = m_Writer.Pos(); - uint64_t recordSize64 = pos - m_SizesOffset - m_Size * 4; - uint32_t recordSize = static_cast(recordSize64); + CHECK_LESS(m_recordNumber, m_size, ()); + + uint64_t const pos = m_writer.Pos(); + uint64_t const recordSize64 = pos - GetDataStartPos(); + uint32_t const recordSize = static_cast(recordSize64); CHECK_EQUAL(recordSize, recordSize64, ()); - m_Writer.Seek(m_SizesOffset + m_RecordNumber * 4); - WriteToSink(m_Writer, recordSize); - m_Writer.Seek(pos); - ++m_RecordNumber; + + m_writer.Seek(m_sizesOffset + m_recordNumber * sizeof(uint32_t)); + WriteToSink(m_writer, recordSize); + m_writer.Seek(pos); + + ++m_recordNumber; } private: - WriterT & m_Writer; - uint64_t m_SizesOffset; - uint32_t m_Size; - uint32_t m_RecordNumber; + uint64_t GetDataStartPos() const + { + return m_sizesOffset + m_size * sizeof(uint32_t); + } + +private: + WriterT & m_writer; + uint64_t m_sizesOffset; + uint32_t m_size; + uint32_t m_recordNumber; }; template @@ -89,34 +72,37 @@ public: { } - string Read(uint64_t i) const + /// Used for unit tests only. Dont't do COW in production code. + string Read(uint32_t i) const { - size_t begin = - i == 0 ? 0 : ReadPrimitiveFromPos(m_offsetsReader, (i - 1) * sizeof(uint32_t)); - size_t end = ReadPrimitiveFromPos(m_offsetsReader, i * sizeof(uint32_t)); + pair const posAsize = GetPosAndSize(i); string result; - result.resize(end - begin); - ReadFromPos(m_dataReader, begin, (void *)result.data(), end - begin); + result.resize(posAsize.second); + ReadFromPos(m_dataReader, posAsize.first, (void *)result.data(), posAsize.second); return result; } - ReaderT SubReader(uint64_t i) const + ReaderT SubReader(uint32_t i) const { - size_t begin = - i == 0 ? 0 : ReadPrimitiveFromPos(m_offsetsReader, (i - 1) * sizeof(uint32_t)); - size_t end = ReadPrimitiveFromPos(m_offsetsReader, i * sizeof(uint32_t)); - - return m_dataReader.SubReader(begin, end - begin); + pair const posAsize = GetPosAndSize(i); + return m_dataReader.SubReader(posAsize.first, posAsize.second); } - uint64_t Size() const + uint64_t Size() const { return m_size; } + +private: + pair GetPosAndSize(uint32_t i) const { - return m_size; + uint32_t const begin = + i == 0 ? 0 : ReadPrimitiveFromPos(m_offsetsReader, (i - 1) * sizeof(uint32_t)); + uint32_t const end = ReadPrimitiveFromPos(m_offsetsReader, i * sizeof(uint32_t)); + + ASSERT_LESS_OR_EQUAL(begin, end, ()); + return make_pair(begin, end - begin); } private: - /// @note Do NOT change declaration order. uint64_t m_size; ReaderT m_offsetsReader; diff --git a/coding/writer.hpp b/coding/writer.hpp index 789d1956d8..c8b51265f0 100644 --- a/coding/writer.hpp +++ b/coding/writer.hpp @@ -66,53 +66,55 @@ class SubWriter { public: inline explicit SubWriter(WriterT & writer) - : m_Writer(writer), m_Pos(0), m_MaxPos(0) + : m_writer(writer), m_pos(0), m_maxPos(0) #ifdef DEBUG - , m_Offset(m_Writer.Pos() - m_Pos) + , m_offset(GetOffset()) #endif { } ~SubWriter() { - ASSERT_EQUAL(m_Offset, m_Writer.Pos() - m_Pos, ()); - if (m_Pos != m_MaxPos) - Seek(m_MaxPos); + ASSERT_EQUAL(m_offset, GetOffset(), ()); + if (m_pos != m_maxPos) + Seek(m_maxPos); } inline void Seek(int64_t pos) { - ASSERT_EQUAL(m_Offset, m_Writer.Pos() - m_Pos, ()); - m_MaxPos = max(m_MaxPos, pos); - m_Writer.Seek(m_Writer.Pos() - m_Pos + pos); - m_Pos = pos; + ASSERT_EQUAL(m_offset, GetOffset(), ()); + m_writer.Seek(GetOffset() + pos); + + m_pos = pos; + m_maxPos = max(m_maxPos, m_pos); } inline int64_t Pos() const { - ASSERT_EQUAL(m_Offset, m_Writer.Pos() - m_Pos, ()); - return m_Pos; + ASSERT_EQUAL(m_offset, GetOffset(), ()); + return m_pos; } inline void Write(void const * p, size_t size) { - ASSERT_EQUAL(m_Offset, m_Writer.Pos() - m_Pos, ()); - m_MaxPos = max(m_MaxPos, static_cast(m_Pos + size)); - m_Writer.Write(p, size); - m_Pos += size; + ASSERT_EQUAL(m_offset, GetOffset(), ()); + m_writer.Write(p, size); + + m_pos += size; + m_maxPos = max(m_maxPos, m_pos); } - inline uint64_t Size() const - { - return m_MaxPos; - } + inline uint64_t Size() const { return m_maxPos; } private: - WriterT & m_Writer; - int64_t m_Pos; - int64_t m_MaxPos; + inline uint64_t GetOffset() const { return m_writer.Pos() - m_pos; } + +private: + WriterT & m_writer; + int64_t m_pos; + int64_t m_maxPos; #ifdef DEBUG - int64_t const m_Offset; + int64_t const m_offset; #endif };