summaryrefslogtreecommitdiff
path: root/source/utilities/MemMappedFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/utilities/MemMappedFile.cpp')
-rw-r--r--source/utilities/MemMappedFile.cpp205
1 files changed, 205 insertions, 0 deletions
diff --git a/source/utilities/MemMappedFile.cpp b/source/utilities/MemMappedFile.cpp
new file mode 100644
index 0000000..287c5b9
--- /dev/null
+++ b/source/utilities/MemMappedFile.cpp
@@ -0,0 +1,205 @@
+/*******************************************************************************
+ * Copyright (C) ST-Ericsson SA 2011
+ * License terms: 3-clause BSD license
+ ******************************************************************************/
+
+#include "lcdriver_error_codes.h"
+#include "MemMappedFile.h"
+#if defined(_WIN32)
+#include <windows.h>
+#elif defined(__linux__)
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <string.h>
+using namespace std;
+#else
+#error "Unknown target"
+#endif
+
+MemMappedFile::MemMappedFile(uint32 alignmentLength):
+ size_(0),
+ isMapped_(false),
+ mappedData_(0),
+ error_(0),
+ alignmentLength_(alignmentLength),
+#ifdef _WIN32
+ handle_(INVALID_HANDLE_VALUE),
+ memmap_(INVALID_HANDLE_VALUE)
+#else
+ descriptor_(-1)
+#endif
+{
+}
+
+MemMappedFile::~MemMappedFile()
+{
+#ifdef _WIN32
+
+ if (0 != mappedData_) {
+ UnmapViewOfFile(mappedData_);
+ }
+
+ if (INVALID_HANDLE_VALUE != memmap_) {
+ CloseHandle(memmap_);
+ }
+
+ if (INVALID_HANDLE_VALUE != handle_) {
+ CloseHandle(handle_);
+ }
+
+#else
+
+ if (0 != mappedData_) {
+ munmap(mappedData_, size_);
+ }
+
+ if (-1 != descriptor_) {
+ close(descriptor_);
+ }
+
+#endif
+}
+
+int MemMappedFile::LoadFileData(const char *path)
+{
+ path_ = path;
+#ifdef _WIN32
+ handle_ = CreateFile(path_.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (INVALID_HANDLE_VALUE == handle_) {
+ return FILE_OPENING_ERROR;
+ }
+
+ size_ = ::GetFileSize(handle_, NULL);
+
+ if (0 == size_) {
+ return 0;
+ }
+
+ memmap_ = CreateFileMapping(handle_, NULL, PAGE_READONLY, 0, 0, NULL);
+
+ if (INVALID_HANDLE_VALUE == memmap_) {
+ return FILE_CREATE_MAPPING_ERROR;
+ }
+
+ mappedData_ = static_cast<uint8 *>(MapViewOfFile(memmap_, FILE_MAP_READ, 0, 0, 0));
+
+ if (0 != mappedData_) {
+ isMapped_ = true;
+ volatile char tmp;
+
+ for (uint64 i = 0; i < size_; i += 4096) {
+ tmp = mappedData_[i];
+ }
+ } else {
+ isMapped_ = false;
+ CloseHandle(memmap_);
+ memmap_ = INVALID_HANDLE_VALUE;
+ }
+
+#else
+ descriptor_ = open(path_.c_str(), O_RDONLY);
+
+ if (-1 == descriptor_) {
+ return FILE_OPENING_ERROR;
+ }
+
+ struct stat fileStat;
+
+ if (0 != fstat(descriptor_, &fileStat)) {
+ return FILE_FAILED_TO_GET_SIZE;
+ }
+
+ size_ = fileStat.st_size;
+
+ mappedData_ = static_cast<uint8 *>(mmap(0, size_, PROT_READ, MAP_PRIVATE | MAP_POPULATE, descriptor_, 0));
+
+ if (MAP_FAILED != mappedData_) {
+ isMapped_ = true;
+ } else {
+ isMapped_ = false;
+ }
+
+#endif
+ return 0;
+}
+
+uint8 *MemMappedFile::AllocateFileData(uint64 offset, uint64 size)
+{
+ if (size_ < offset + size) {
+ error_ = FILE_READ_INVALID_OFFSET;
+ return 0;
+ }
+
+ uint32 alignedSize = (static_cast<uint32>(size) + (alignmentLength_ - 1)) & (~(alignmentLength_ - 1));
+
+ if (isMapped_) {
+ if (size_ < offset + alignedSize) {
+ uint8 *data = new uint8[alignedSize];
+ memcpy(data, mappedData_ + offset, static_cast<size_t>(size));
+ return data;
+ } else {
+ return mappedData_ + offset;
+ }
+ } else {
+ // file is not memory mapped fall back to plain read
+ uint32 readSize = static_cast<uint32>(size);
+ uint8 *data = new uint8[alignedSize];
+#ifdef _WIN32
+ LARGE_INTEGER liOffset;
+ liOffset.QuadPart = offset;
+
+ if (!SetFilePointerEx(handle_, liOffset, NULL, FILE_BEGIN)) {
+ delete[] data;
+ error_ = FILE_READ_INVALID_OFFSET;
+ return 0;
+ }
+
+ uint32 bytesRead;
+
+ if (ReadFile(handle_, data, readSize, (LPDWORD)&bytesRead, NULL) && bytesRead == size) {
+ return data;
+ } else {
+ delete[] data;
+ error_ = FILE_READ_ERROR;
+ return 0;
+ }
+
+#else
+
+ if (-1 == lseek64(descriptor_, offset, SEEK_SET)) {
+ delete[] data;
+ error_ = FILE_READ_INVALID_OFFSET;
+ return 0;
+ }
+
+ if (readSize == (uint32)read(descriptor_, data, readSize)) {
+ return data;
+ } else {
+ delete[] data;
+ error_ = FILE_READ_ERROR;
+ return 0;
+ }
+
+#endif
+ }
+}
+
+void MemMappedFile::ReleaseFileData(uint8 *data, uint64 offset, uint64 size)
+{
+ uint32 alignedSize = (static_cast<uint32>(size) + (alignmentLength_ - 1)) & (~(alignmentLength_ - 1));
+ if (!isMapped_ || size_ < offset + alignedSize) {
+ delete[] data;
+ }
+}
+
+uint64 MemMappedFile::GetFileSize()
+{
+ return size_;
+}
+
+int MemMappedFile::GetError()
+{
+ return error_;
+}