diff --git a/coding/coding.pro b/coding/coding.pro index f7fed2819e..12374ec59d 100644 --- a/coding/coding.pro +++ b/coding/coding.pro @@ -25,6 +25,7 @@ SOURCES += \ multilang_utf8_string.cpp \ reader.cpp \ zip_reader.cpp \ + mmap_reader.cpp \ HEADERS += \ internal/xmlparser.h \ @@ -85,3 +86,4 @@ HEADERS += \ zip_reader.hpp \ trie.hpp \ trie_builder.hpp \ + mmap_reader.hpp \ diff --git a/coding/mmap_reader.cpp b/coding/mmap_reader.cpp new file mode 100644 index 0000000000..bfdc9271b5 --- /dev/null +++ b/coding/mmap_reader.cpp @@ -0,0 +1,82 @@ +#include "mmap_reader.hpp" + +#include "../std/target_os.hpp" +#include "../std/memcpy.hpp" + +// @TODO we don't support windows at the moment +#ifndef OMIM_OS_WINDOWS + #include + #include + #include + #include +#endif + +class MmapReader::MmapData +{ + int m_fd; + +public: + uint8_t * m_memory; + uint64_t m_size; + + MmapData(string const & fileName) + { + // @TODO add windows support +#ifndef OMIM_OS_WINDOWS + m_fd = open(fileName.c_str(), O_RDONLY | O_NONBLOCK | O_SYMLINK); + if (m_fd == -1) + MYTHROW(OpenException, ("open failed for file", fileName)); + + struct stat s; + if (-1 == fstat(m_fd, &s)) + MYTHROW(OpenException, ("fstat failed for file", fileName)); + m_size = s.st_size; + + m_memory = (uint8_t *)mmap(0, m_size, PROT_READ, MAP_SHARED, m_fd, 0); + if (m_memory == MAP_FAILED) + { + close(m_fd); + MYTHROW(OpenException, ("mmap failed for file", fileName)); + } +#endif + } + + ~MmapData() + { + // @TODO add windows support +#ifndef OMIM_OS_WINDOWS + munmap(m_memory, m_size); + close(m_fd); +#endif + } +}; + +MmapReader::MmapReader(string const & fileName) + : base_type(fileName), m_offset(0) +{ + m_data = shared_ptr(new MmapData(fileName)); + m_size = m_data->m_size; +} + +MmapReader::MmapReader(MmapReader const & reader, uint64_t offset, uint64_t size) + : base_type(reader.GetName()), m_data(reader.m_data), + m_offset(offset), m_size(size) +{ +} + +uint64_t MmapReader::Size() const +{ + return m_size; +} + +void MmapReader::Read(uint64_t pos, void * p, size_t size) const +{ + ASSERT_LESS_OR_EQUAL(pos + size, Size(), (pos, size)); + memcpy(p, m_data->m_memory + m_offset + pos, size); +} + +MmapReader * MmapReader::CreateSubReader(uint64_t pos, uint64_t size) const +{ + ASSERT_LESS_OR_EQUAL(pos + size, Size(), (pos, size)); + return new MmapReader(*this, m_offset + pos, size); +} diff --git a/coding/mmap_reader.hpp b/coding/mmap_reader.hpp new file mode 100644 index 0000000000..480cd0eefa --- /dev/null +++ b/coding/mmap_reader.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "reader.hpp" + +#include "../std/shared_ptr.hpp" + +/// @TODO Add Windows support +class MmapReader : public ModelReader +{ + typedef ModelReader base_type; + + class MmapData; + shared_ptr m_data; + uint64_t m_offset; + uint64_t m_size; + + MmapReader(MmapReader const & reader, uint64_t offset, uint64_t size); + +public: + explicit MmapReader(string const & fileName); + + virtual uint64_t Size() const; + virtual void Read(uint64_t pos, void * p, size_t size) const; + virtual MmapReader * CreateSubReader(uint64_t pos, uint64_t size) const; +};