Skip to content

Commit

Permalink
Add basic file mapping support.
Browse files Browse the repository at this point in the history
  • Loading branch information
abellgithub committed Jun 24, 2020
1 parent 341fe1b commit c596a38
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 2 deletions.
77 changes: 76 additions & 1 deletion pdal/util/FileUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@
* OF SUCH DAMAGE.
****************************************************************************/

#include <fcntl.h>
#include <sys/stat.h>

#include <iostream>
#include <sstream>
#ifndef _WIN32
#include <glob.h>
#include <sys/mman.h>
#else
#include <io.h>
#include <codecvt>
#include <Windows.h>
#endif
Expand Down Expand Up @@ -444,7 +447,79 @@ std::vector<std::string> glob(std::string path)
return filenames;
}

} // namespace FileUtils

MapContext mapFile(const std::string& filename, bool readOnly,
size_t pos, size_t size)
{
MapContext ctx;

if (!readOnly)
{
ctx.m_error = "readOnly must be true.";
return ctx;
}

#ifndef WIN32
ctx.m_fd = ::open(filename.c_str(), readOnly ? O_RDONLY : O_RDWR);
#else
ctx.m_fd = ::_open(filename.c_str(), readOnly ? O_RDONLY : O_RDWR);
#endif

if (ctx.m_fd == -1)
{
ctx.m_error = "Mapped file couldn't be opened.";
return ctx;
}
ctx.m_size = size;

#ifndef _WIN32
ctx.m_addr = ::mmap(0, size, PROT_READ, MAP_SHARED, ctx.m_fd, (off_t)pos);
if (ctx.m_addr == MAP_FAILED)
{
ctx.m_addr = nullptr;
ctx.m_error = "Couldn't map file";
}
#else
ctx.m_handle = CreateFileMapping((HANDLE)_get_osfhandle(ctx.m_fd),
NULL, PAGE_READONLY, 0, 0, NULL);
uint32_t low = pos & 0xFFFFFFFF;
uint32_t high = (pos >> 8);
ctx.m_addr = MapViewOfFile(ctx.m_handle, FILE_MAP_READ, high, low,
ctx.m_size);
if (ctx.m_addr == nullptr)
ctx.m_error = "Couldn't map file";
#endif

return ctx;
}

MapContext unmapFile(MapContext ctx)
{
#ifndef _WIN32
if (::munmap(ctx.m_addr, ctx.m_size) == -1)
ctx.m_error = "Couldn't unmap file.";
else
{
ctx.m_addr = nullptr;
ctx.m_size = 0;
ctx.m_error = "";
}
::close(ctx.m_fd);
#else
if (UnmapViewOfFile(ctx.m_addr) == 0)
ctx.m_error = "Couldn't unmap file.";
else
{
ctx.m_addr = nullptr;
ctx.m_size = 0;
ctx.m_error = "";
}
CloseHandle(ctx.m_handle);
::_close(ctx.m_fd);
#endif
return ctx;
}

} // namespace FileUtils
} // namespace pdal

45 changes: 44 additions & 1 deletion pdal/util/FileUtils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@
#include <string>
#include <vector>

#ifdef _WIN32
#include <Windows.h>
#endif

#include "pdal_util_export.hpp"

namespace pdal
Expand Down Expand Up @@ -258,6 +262,45 @@ namespace FileUtils
\return List of files that correspond to provided file specification.
*/
PDAL_DLL std::vector<std::string> glob(std::string filespec);
}


struct PDAL_DLL MapContext
{
public:
MapContext() : m_fd(-1), m_addr(nullptr)
{}

void *addr() const
{ return m_addr; }
std::string what() const
{ return m_error; }

int m_fd;
size_t m_size;
void *m_addr;
std::string m_error;
#ifdef _WIN32
HANDLE m_handle;
#endif
};
/**
Map a file to memory.
\param filename Filename to map.
\param readOnly Must be true at this time.
\param pos Starting position of file to map.
\param size Number of bytes in file to map.
\return MapContext. addr() gets the mapped address. what() gets
any error message. addr() returns nullptr on error.
*/
PDAL_DLL MapContext mapFile(const std::string& filename, bool readOnly,
size_t pos, size_t size);

/**
Unmap a previously mapped file.
\param ctx Previously returned MapContext
\return MapContext indicating current state of the file mapping.
*/
PDAL_DLL MapContext unmapFile(MapContext ctx);

} // namespace FileUtils
} // namespace pdal

0 comments on commit c596a38

Please sign in to comment.