mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Extended MemoryMappedFile to allow loading of file subsections.
This commit is contained in:
parent
1e7ea748ca
commit
e6d817d20d
4 changed files with 67 additions and 23 deletions
|
|
@ -881,6 +881,19 @@ File File::createTempFile (const String& fileNameEnding)
|
|||
return tempFile;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
MemoryMappedFile::MemoryMappedFile (const File& file, MemoryMappedFile::AccessMode mode)
|
||||
: address (nullptr), range (0, file.getSize()), fileHandle (0)
|
||||
{
|
||||
openInternal (file, mode);
|
||||
}
|
||||
|
||||
MemoryMappedFile::MemoryMappedFile (const File& file, const Range<int64>& fileRange, AccessMode mode)
|
||||
: address (nullptr), range (fileRange.getIntersectionWith (Range<int64> (0, file.getSize()))), fileHandle (0)
|
||||
{
|
||||
openInternal (file, mode);
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_UNIT_TESTS
|
||||
|
|
|
|||
|
|
@ -57,6 +57,26 @@ public:
|
|||
*/
|
||||
MemoryMappedFile (const File& file, AccessMode mode);
|
||||
|
||||
/** Opens a section of a file and maps it to an area of virtual memory.
|
||||
|
||||
The file should already exist, and should already be the size that you want to work with
|
||||
when you call this. If the file is resized after being opened, the behaviour is undefined.
|
||||
|
||||
If the file exists and the operation succeeds, the getData() and getSize() methods will
|
||||
return the location and size of the data that can be read or written. Note that the entire
|
||||
file is not read into memory immediately - the OS simply creates a virtual mapping, which
|
||||
will lazily pull the data into memory when blocks are accessed.
|
||||
|
||||
If the file can't be opened for some reason, the getData() method will return a null pointer.
|
||||
|
||||
NOTE: the start of the actual range used may be rounded-down to a multiple of the OS's page-size,
|
||||
so do not assume that the mapped memory will begin at exactly the position you requested - always
|
||||
use getRange() to check the actual range that is being used.
|
||||
*/
|
||||
MemoryMappedFile (const File& file,
|
||||
const Range<int64>& fileRange,
|
||||
AccessMode mode);
|
||||
|
||||
/** Destructor. */
|
||||
~MemoryMappedFile();
|
||||
|
||||
|
|
@ -68,13 +88,15 @@ public:
|
|||
/** Returns the number of bytes of data that are available for reading or writing.
|
||||
This will normally be the size of the file.
|
||||
*/
|
||||
size_t getSize() const noexcept { return length; }
|
||||
size_t getSize() const noexcept { return (size_t) range.getLength(); }
|
||||
|
||||
/** Returns the section of the file at which the mapped memory represents. */
|
||||
Range<int64> getRange() const noexcept { return range; }
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
void* address;
|
||||
size_t length;
|
||||
Range<int64> range;
|
||||
|
||||
#if JUCE_WINDOWS
|
||||
void* fileHandle;
|
||||
|
|
@ -82,6 +104,8 @@ private:
|
|||
int fileHandle;
|
||||
#endif
|
||||
|
||||
void openInternal (const File&, AccessMode);
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MemoryMappedFile)
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -546,36 +546,37 @@ String SystemStats::getEnvironmentVariable (const String& name, const String& de
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
MemoryMappedFile::MemoryMappedFile (const File& file, MemoryMappedFile::AccessMode mode)
|
||||
: address (nullptr),
|
||||
length (0),
|
||||
fileHandle (0)
|
||||
void MemoryMappedFile::openInternal (const File& file, AccessMode mode)
|
||||
{
|
||||
jassert (mode == readOnly || mode == readWrite);
|
||||
|
||||
if (range.getStart() > 0)
|
||||
{
|
||||
const long pageSize = sysconf (_SC_PAGE_SIZE);
|
||||
range.setStart (range.getStart() - (range.getStart() % pageSize));
|
||||
}
|
||||
|
||||
fileHandle = open (file.getFullPathName().toUTF8(),
|
||||
mode == readWrite ? (O_CREAT + O_RDWR) : O_RDONLY, 00644);
|
||||
|
||||
if (fileHandle != -1)
|
||||
{
|
||||
const int64 fileSize = file.getSize();
|
||||
|
||||
void* m = mmap (0, (size_t) fileSize,
|
||||
void* m = mmap (0, (size_t) range.getLength(),
|
||||
mode == readWrite ? (PROT_READ | PROT_WRITE) : PROT_READ,
|
||||
MAP_SHARED, fileHandle, 0);
|
||||
MAP_SHARED, fileHandle,
|
||||
(off_t) range.getStart());
|
||||
|
||||
if (m != MAP_FAILED)
|
||||
{
|
||||
address = m;
|
||||
length = (size_t) fileSize;
|
||||
}
|
||||
else
|
||||
range = Range<int64>();
|
||||
}
|
||||
}
|
||||
|
||||
MemoryMappedFile::~MemoryMappedFile()
|
||||
{
|
||||
if (address != nullptr)
|
||||
munmap (address, length);
|
||||
munmap (address, range.getLength());
|
||||
|
||||
if (fileHandle != 0)
|
||||
close (fileHandle);
|
||||
|
|
|
|||
|
|
@ -310,13 +310,18 @@ Result FileOutputStream::truncate()
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
MemoryMappedFile::MemoryMappedFile (const File& file, MemoryMappedFile::AccessMode mode)
|
||||
: address (nullptr),
|
||||
length (0),
|
||||
fileHandle (nullptr)
|
||||
void MemoryMappedFile::openInternal (const File& file, AccessMode mode)
|
||||
{
|
||||
jassert (mode == readOnly || mode == readWrite);
|
||||
|
||||
if (range.getStart() > 0)
|
||||
{
|
||||
SYSTEM_INFO systemInfo;
|
||||
GetNativeSystemInfo (&systemInfo);
|
||||
|
||||
range.setStart (range.getStart() - (range.getStart() % systemInfo.dwAllocationGranularity));
|
||||
}
|
||||
|
||||
DWORD accessMode = GENERIC_READ, createType = OPEN_EXISTING;
|
||||
DWORD protect = PAGE_READONLY, access = FILE_MAP_READ;
|
||||
|
||||
|
|
@ -334,15 +339,16 @@ MemoryMappedFile::MemoryMappedFile (const File& file, MemoryMappedFile::AccessMo
|
|||
if (h != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
fileHandle = (void*) h;
|
||||
const int64 fileSize = file.getSize();
|
||||
|
||||
HANDLE mappingHandle = CreateFileMapping (h, 0, protect, (DWORD) (fileSize >> 32), (DWORD) fileSize, 0);
|
||||
HANDLE mappingHandle = CreateFileMapping (h, 0, protect, (DWORD) (range.getEnd() >> 32), (DWORD) range.getEnd(), 0);
|
||||
|
||||
if (mappingHandle != 0)
|
||||
{
|
||||
address = MapViewOfFile (mappingHandle, access, 0, 0, (SIZE_T) fileSize);
|
||||
address = MapViewOfFile (mappingHandle, access, (DWORD) (range.getStart() >> 32),
|
||||
(DWORD) range.getStart(), (SIZE_T) range.getLength());
|
||||
|
||||
if (address != nullptr)
|
||||
length = (size_t) fileSize;
|
||||
if (address == nullptr)
|
||||
range = Range<int64>();
|
||||
|
||||
CloseHandle (mappingHandle);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue