Stroika Library 3.0d25
 
Loading...
Searching...
No Matches
MemoryMappedFileReader.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
4#include "Stroika/Foundation/StroikaPreComp.h"
5
6#include <fcntl.h>
7#include <sys/types.h>
8
9#if qStroika_Platform_Windows
10#include <windows.h>
11#elif qStroika_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_Platform_Windows
20#include "Stroika/Foundation/Execution/Platform/Windows/Exception.h"
21#include "Stroika/Foundation/Execution/Platform/Windows/HRESULTErrorException.h"
22#endif
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_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_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::Exception<runtime_error>{"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_Platform_Windows
62 try {
63 fFileHandle_ = ::CreateFile (fileName.c_str (), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
64 if (fFileHandle_ == INVALID_HANDLE_VALUE) {
65 Execution::ThrowSystemErrNo ();
66 }
67 DWORD fileSize = ::GetFileSize (fFileHandle_, nullptr);
68 if (fileSize != 0) {
69 fFileMapping_ = ::CreateFileMapping (fFileHandle_, nullptr, PAGE_READONLY, 0, fileSize, 0);
70 ThrowIfZeroGetLastError (fFileMapping_);
71 AssertNotNull (fFileMapping_);
72 fSpan_ = span{reinterpret_cast<const byte*> (::MapViewOfFile (fFileMapping_, FILE_MAP_READ, 0, 0, 0)), fileSize};
73 ThrowIfZeroGetLastError (fSpan_.data ());
74 }
75 }
76 catch (...) {
77 if (fFileMapping_ != INVALID_HANDLE_VALUE) {
78 ::CloseHandle (fFileMapping_);
79 }
80 if (fFileHandle_ != INVALID_HANDLE_VALUE) {
81 ::CloseHandle (fFileHandle_);
82 }
84 }
85#else
87#endif
88}
89
90MemoryMappedFileReader::~MemoryMappedFileReader ()
91{
92#if qStroika_Platform_POSIX
93 if (::munmap (const_cast<byte*> (fSpan_.data ()), fSpan_.size ())) {
94 DbgTrace ("munmap failed: Cannot throw in DTOR, so just DbgTrace log: errno={}"_f, errno);
95 }
96#elif qStroika_Platform_Windows
97 if (fSpan_.data () != nullptr) {
98 (void)::UnmapViewOfFile (fSpan_.data ());
99 }
100 if (fFileMapping_ != INVALID_HANDLE_VALUE) {
101 ::CloseHandle (fFileMapping_);
102 }
103 if (fFileHandle_ != INVALID_HANDLE_VALUE) {
104 ::CloseHandle (fFileHandle_);
105 }
106#else
108#endif
109}
#define AssertNotNull(p)
Definition Assertions.h:336
#define AssertNotImplemented()
Definition Assertions.h:404
#define DbgTrace
Definition Trace.h:327
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
Exception<> is a replacement (subclass) for any std c++ exception class (e.g. the default 'std::excep...
Definition Exceptions.h:219
void Throw(T &&e2Throw)
like the builtin C++ 'throw', but stamps in the current Activity context and does helpful,...
Definition Throw.inl:54
INT_TYPE ThrowPOSIXErrNoIfNegative(INT_TYPE returnCode)