/
githubmirror
/
omim
Обзор
Документация
Войти
/
githubmirror
/
omim
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
android-95
coding/files_container.hpp
269 строк
6 KB
Maxim Pimenov
[coding] Moved FilesContainer Writers to file_writer.hpp.
20 сен 2019, 18:29
20 сен 2019, 18:29
bf4f6a3
Код
Авторство
О чём код?
#pragma once #include "coding/file_reader.hpp" #include "coding/file_writer.hpp" #include "base/assert.hpp" #include "base/macros.hpp" #include <algorithm> #include <cstddef> #include <cstdint> #include <memory> #include <string> #include <utility> #include <vector> class FilesContainerBase { public: using Tag = std::string; /// Alignment of each new section that will be added to a file /// container, i.e. section's offset in bytes will be a multiple of /// this value. /// /// WARNING! Existing sections may not be properly aligned. static uint64_t const kSectionAlignment = 8; bool IsExist(Tag const & tag) const { return GetInfo(tag) != 0; } template <typename ToDo> void ForEachTag(ToDo && toDo) const { std::for_each(m_info.begin(), m_info.end(), std::forward<ToDo>(toDo)); } protected: struct Info { Tag m_tag; uint64_t m_offset; uint64_t m_size; Info() {} Info(Tag const & tag, uint64_t offset) : m_tag(tag), m_offset(offset) {} }; struct LessInfo { bool operator() (Info const & t1, Info const & t2) const { return (t1.m_tag < t2.m_tag); } bool operator() (Info const & t1, Tag const & t2) const { return (t1.m_tag < t2); } bool operator() (Tag const & t1, Info const & t2) const { return (t1 < t2.m_tag); } }; struct LessOffset { bool operator() (Info const & t1, Info const & t2) const { if (t1.m_offset == t2.m_offset) { // Element with nonzero size should be the last one, // for correct append writer mode (FilesContainerW::GetWriter). return (t1.m_size < t2.m_size); } else return (t1.m_offset < t2.m_offset); } bool operator() (Info const & t1, uint64_t const & t2) const { return (t1.m_offset < t2); } bool operator() (uint64_t const & t1, Info const & t2) const { return (t1 < t2.m_offset); } }; class EqualTag { public: EqualTag(Tag const & tag) : m_tag(tag) {} bool operator() (Info const & t) const { return (t.m_tag == m_tag); } private: Tag const & m_tag; }; friend std::string DebugPrint(Info const & info); Info const * GetInfo(Tag const & tag) const; template <typename Reader> void ReadInfo(Reader & reader); using InfoContainer = std::vector<Info>; InfoContainer m_info; }; class FilesContainerR : public FilesContainerBase { public: using TReader = ModelReaderPtr; explicit FilesContainerR(std::string const & filePath, uint32_t logPageSize = 10, uint32_t logPageCount = 10); explicit FilesContainerR(TReader const & file); TReader GetReader(Tag const & tag) const; template <typename F> void ForEachTag(F && f) const { for (size_t i = 0; i < m_info.size(); ++i) f(m_info[i].m_tag); } uint64_t GetFileSize() const { return m_source.Size(); } std::string const & GetFileName() const { return m_source.GetName(); } std::pair<uint64_t, uint64_t> GetAbsoluteOffsetAndSize(Tag const & tag) const; private: TReader m_source; }; namespace detail { class MappedFile { public: MappedFile() = default; ~MappedFile() { Close(); } void Open(std::string const & fName); void Close(); class Handle { public: Handle() = default; Handle(char const * base, char const * alignBase, uint64_t size, uint64_t origSize) : m_base(base), m_origBase(alignBase), m_size(size), m_origSize(origSize) { } Handle(Handle && h) { Assign(std::move(h)); } ~Handle(); void Assign(Handle && h); void Unmap(); bool IsValid() const { return (m_base != 0); } uint64_t GetSize() const { return m_size; } template <typename T> T const * GetData() const { ASSERT_EQUAL(m_size % sizeof(T), 0, ()); return reinterpret_cast<T const *>(m_base); } template <typename T> size_t GetDataCount() const { ASSERT_EQUAL(m_size % sizeof(T), 0, ()); return (m_size / sizeof(T)); } private: void Reset(); char const * m_base = nullptr; char const * m_origBase = nullptr; uint64_t m_size = 0; uint64_t m_origSize = 0; DISALLOW_COPY(Handle); }; Handle Map(uint64_t offset, uint64_t size, std::string const & tag) const; private: #ifdef OMIM_OS_WINDOWS void * m_hFile = (void *)-1; void * m_hMapping = (void *)-1; #else int m_fd = -1; #endif DISALLOW_COPY(MappedFile); }; } // namespace detail class FilesMappingContainer : public FilesContainerBase { public: using Handle = detail::MappedFile::Handle; /// Do nothing by default, call Open to attach to file. FilesMappingContainer() = default; explicit FilesMappingContainer(std::string const & fName); ~FilesMappingContainer(); void Open(std::string const & fName); void Close(); Handle Map(Tag const & tag) const; FileReader GetReader(Tag const & tag) const; std::string const & GetName() const { return m_name; } private: std::string m_name; detail::MappedFile m_file; }; class FilesContainerW : public FilesContainerBase { public: FilesContainerW(std::string const & fName, FileWriter::Op op = FileWriter::OP_WRITE_TRUNCATE); ~FilesContainerW(); std::unique_ptr<FilesContainerWriter> GetWriter(Tag const & tag); void Write(std::string const & fPath, Tag const & tag); void Write(ModelReaderPtr reader, Tag const & tag); void Write(void const * buffer, size_t size, Tag const & tag); void Write(std::vector<char> const & buffer, Tag const & tag); void Write(std::vector<uint8_t> const & buffer, Tag const & tag); void Finish(); /// Delete section with rewriting file. /// @precondition Container should be opened with FileWriter::OP_WRITE_EXISTING. void DeleteSection(Tag const & tag); std::string const & GetFileName() const { return m_name; } private: uint64_t SaveCurrentSize(); void Open(FileWriter::Op op); void StartNew(); std::string m_name; bool m_needRewrite; bool m_finished; };