Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
253
libs/coding/files_container.hpp
Normal file
253
libs/coding/files_container.hpp
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
#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;
|
||||
|
||||
struct TagInfo
|
||||
{
|
||||
TagInfo() = default;
|
||||
TagInfo(Tag const & tag, uint64_t offset) : m_tag(tag), m_offset(offset) {}
|
||||
|
||||
Tag m_tag;
|
||||
uint64_t m_offset = 0;
|
||||
uint64_t m_size = 0;
|
||||
};
|
||||
|
||||
/// 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 constexpr kSectionAlignment = 8;
|
||||
|
||||
bool IsExist(Tag const & tag) const { return GetInfo(tag) != 0; }
|
||||
|
||||
template <typename ToDo>
|
||||
void ForEachTagInfo(ToDo && toDo) const
|
||||
{
|
||||
std::for_each(m_info.begin(), m_info.end(), std::forward<ToDo>(toDo));
|
||||
}
|
||||
|
||||
protected:
|
||||
struct LessInfo
|
||||
{
|
||||
bool operator()(TagInfo const & t1, TagInfo const & t2) const { return (t1.m_tag < t2.m_tag); }
|
||||
bool operator()(TagInfo const & t1, Tag const & t2) const { return (t1.m_tag < t2); }
|
||||
bool operator()(Tag const & t1, TagInfo const & t2) const { return (t1 < t2.m_tag); }
|
||||
};
|
||||
|
||||
struct LessOffset
|
||||
{
|
||||
bool operator()(TagInfo const & t1, TagInfo 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()(TagInfo const & t1, uint64_t const & t2) const { return (t1.m_offset < t2); }
|
||||
bool operator()(uint64_t const & t1, TagInfo const & t2) const { return (t1 < t2.m_offset); }
|
||||
};
|
||||
|
||||
class EqualTag
|
||||
{
|
||||
public:
|
||||
EqualTag(Tag const & tag) : m_tag(tag) {}
|
||||
bool operator()(TagInfo const & t) const { return (t.m_tag == m_tag); }
|
||||
|
||||
private:
|
||||
Tag const & m_tag;
|
||||
};
|
||||
|
||||
TagInfo const * GetInfo(Tag const & tag) const;
|
||||
|
||||
template <typename Reader>
|
||||
void ReadInfo(Reader & reader);
|
||||
|
||||
using InfoContainer = std::vector<TagInfo>;
|
||||
InfoContainer m_info;
|
||||
};
|
||||
|
||||
std::string DebugPrint(FilesContainerBase::TagInfo const & 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 & operator=(Handle && h)
|
||||
{
|
||||
Assign(std::move(h));
|
||||
return *this;
|
||||
}
|
||||
|
||||
~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;
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue