Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
MemoryMappedFileReader.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include "Stroika/Foundation/StroikaPreComp.h"
5
6#include <fcntl.h>
7#include <sys/types.h>
8
9#if qStroika_Foundation_Common_Platform_Windows
10#include <windows.h>
11#elif qStroika_Foundation_Common_Platform_POSIX
12#include <sys/mman.h>
13#include <unistd.h>
14#endif
15
16#include "Stroika/Foundation/Execution/Activity.h"
17#include "Stroika/Foundation/Execution/Exceptions.h"
18#include "Stroika/Foundation/Execution/Throw.h"
19#if qStroika_Foundation_Common_Platform_Windows
20#include "Stroika/Foundation/Execution/Platform/Windows/Exception.h"
21#include "Stroika/Foundation/Execution/Platform/Windows/HRESULTErrorException.h"
22#endif
23#include "FileSystem.h"
25
26#include "MemoryMappedFileReader.h"
27
28using std::byte;
29
30using namespace Stroika::Foundation;
32using namespace Stroika::Foundation::IO;
34using namespace Stroika::Foundation::Execution;
35using namespace Stroika::Foundation::Memory;
36
37#if qStroika_Foundation_Common_Platform_Windows
39#endif
40
41/*
42 ********************************************************************************
43 ***************************** MemoryMappedFileReader ***************************
44 ********************************************************************************
45 */
46MemoryMappedFileReader::MemoryMappedFileReader (const filesystem::path& fileName)
47{
48 auto activity = LazyEvalActivity ([&] () -> String { return "memory mapping {} for read access"_f(fileName); });
49 DeclareActivity currentActivity{&activity};
50#if qStroika_Foundation_Common_Platform_POSIX
51 int fd = -1;
52 Execution::ThrowPOSIXErrNoIfNegative (fd = open (fileName.c_str (), O_RDONLY));
53 auto fileLength = filesystem::file_size (fileName);
54 //WRONG BUT NOT GROSSLY - @todo fix -- AssertNotImplemented (); // size of file - compute -- must check for overlflow and throw...
55 // offset must be a multiple of the page size as returned by sysconf(_SC_PAGE_SIZE). from http://linux.die.net/man/2/mmap
56 if (fileLength >= numeric_limits<size_t>::max ()) {
57 Execution::Throw (Execution::RuntimeErrorException{"file too large to be memory mapped"sv});
58 }
59 fSpan_ = span{reinterpret_cast<const byte*> (::mmap (nullptr, fileLength, PROT_READ, MAP_PRIVATE, fd, 0)), static_cast<size_t> (fileLength)};
60 ::close (fd); //http://linux.die.net/man/2/mmap says don't need to keep FD open while mmapped
61#elif qStroika_Foundation_Common_Platform_Windows
62 try {
63 // FILE_READ_DATA fails on WinME - generates ERROR_INVALID_PARAMETER - so use GENERIC_READ
64 fFileHandle_ = ::CreateFile (fileName.c_str (), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
65 if (fFileHandle_ == INVALID_HANDLE_VALUE) {
66 Execution::ThrowSystemErrNo ();
67 }
68 DWORD fileSize = ::GetFileSize (fFileHandle_, nullptr);
69 if (fileSize != 0) {
70 fFileMapping_ = ::CreateFileMapping (fFileHandle_, nullptr, PAGE_READONLY, 0, fileSize, 0);
71 ThrowIfZeroGetLastError (fFileMapping_);
72 AssertNotNull (fFileMapping_);
73 fSpan_ = span{reinterpret_cast<const byte*> (::MapViewOfFile (fFileMapping_, FILE_MAP_READ, 0, 0, 0)), fileSize};
74 ThrowIfZeroGetLastError (fSpan_.data ());
75 }
76 }
77 catch (...) {
78 if (fFileMapping_ != INVALID_HANDLE_VALUE) {
79 ::CloseHandle (fFileMapping_);
80 }
81 if (fFileHandle_ != INVALID_HANDLE_VALUE) {
82 ::CloseHandle (fFileHandle_);
83 }
85 }
86#else
88#endif
89}
90
91MemoryMappedFileReader::~MemoryMappedFileReader ()
92{
93#if qStroika_Foundation_Common_Platform_POSIX
94 if (::munmap (const_cast<byte*> (fSpan_.data ()), fSpan_.size ())) {
95 DbgTrace ("munmap failed: Cannot throw in DTOR, so just DbgTrace log: errno={}"_f, errno);
96 }
97#elif qStroika_Foundation_Common_Platform_Windows
98 if (fSpan_.data () != nullptr) {
99 (void)::UnmapViewOfFile (fSpan_.data ());
100 }
101 if (fFileMapping_ != INVALID_HANDLE_VALUE) {
102 ::CloseHandle (fFileMapping_);
103 }
104 if (fFileHandle_ != INVALID_HANDLE_VALUE) {
105 ::CloseHandle (fFileHandle_);
106 }
107#else
109#endif
110}
#define AssertNotNull(p)
Definition Assertions.h:333
#define AssertNotImplemented()
Definition Assertions.h:401
#define DbgTrace
Definition Trace.h:309
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
void Throw(T &&e2Throw)
identical to builtin C++ 'throw' except that it does helpful, type dependent DbgTrace() messages firs...
Definition Throw.inl:43
INT_TYPE ThrowPOSIXErrNoIfNegative(INT_TYPE returnCode)