mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-11 23:54:18 +00:00
New class: MemoryMappedFile.
This commit is contained in:
parent
981ef9313c
commit
3213bec481
23 changed files with 556 additions and 66 deletions
|
|
@ -898,6 +898,7 @@
|
|||
4EEF0B0BB4C3D1956B04122B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_FileOutputStream.h; path = ../../src/io/files/juce_FileOutputStream.h; sourceTree = SOURCE_ROOT; };
|
||||
59B2FFF817679AEA84375E1B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_FileSearchPath.cpp; path = ../../src/io/files/juce_FileSearchPath.cpp; sourceTree = SOURCE_ROOT; };
|
||||
49BF2B02A6D7B4438FC24839 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_FileSearchPath.h; path = ../../src/io/files/juce_FileSearchPath.h; sourceTree = SOURCE_ROOT; };
|
||||
00B348FA35A7F691AEF84FBA = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_MemoryMappedFile.h; path = ../../src/io/files/juce_MemoryMappedFile.h; sourceTree = SOURCE_ROOT; };
|
||||
D9B3C04F8EB4228DD59002E7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_NamedPipe.cpp; path = ../../src/io/files/juce_NamedPipe.cpp; sourceTree = SOURCE_ROOT; };
|
||||
42DA88264F768BAACD0414A3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_NamedPipe.h; path = ../../src/io/files/juce_NamedPipe.h; sourceTree = SOURCE_ROOT; };
|
||||
17C3AF03FF7AE88AE0C73311 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_TemporaryFile.cpp; path = ../../src/io/files/juce_TemporaryFile.cpp; sourceTree = SOURCE_ROOT; };
|
||||
|
|
@ -1713,6 +1714,7 @@
|
|||
4EEF0B0BB4C3D1956B04122B,
|
||||
59B2FFF817679AEA84375E1B,
|
||||
49BF2B02A6D7B4438FC24839,
|
||||
00B348FA35A7F691AEF84FBA,
|
||||
D9B3C04F8EB4228DD59002E7,
|
||||
42DA88264F768BAACD0414A3,
|
||||
17C3AF03FF7AE88AE0C73311,
|
||||
|
|
|
|||
|
|
@ -787,6 +787,7 @@
|
|||
<File RelativePath="..\..\src\io\files\juce_FileOutputStream.h"/>
|
||||
<File RelativePath="..\..\src\io\files\juce_FileSearchPath.cpp"/>
|
||||
<File RelativePath="..\..\src\io\files\juce_FileSearchPath.h"/>
|
||||
<File RelativePath="..\..\src\io\files\juce_MemoryMappedFile.h"/>
|
||||
<File RelativePath="..\..\src\io\files\juce_NamedPipe.cpp"/>
|
||||
<File RelativePath="..\..\src\io\files\juce_NamedPipe.h"/>
|
||||
<File RelativePath="..\..\src\io\files\juce_TemporaryFile.cpp"/>
|
||||
|
|
|
|||
|
|
@ -787,6 +787,7 @@
|
|||
<File RelativePath="..\..\src\io\files\juce_FileOutputStream.h"/>
|
||||
<File RelativePath="..\..\src\io\files\juce_FileSearchPath.cpp"/>
|
||||
<File RelativePath="..\..\src\io\files\juce_FileSearchPath.h"/>
|
||||
<File RelativePath="..\..\src\io\files\juce_MemoryMappedFile.h"/>
|
||||
<File RelativePath="..\..\src\io\files\juce_NamedPipe.cpp"/>
|
||||
<File RelativePath="..\..\src\io\files\juce_NamedPipe.h"/>
|
||||
<File RelativePath="..\..\src\io\files\juce_TemporaryFile.cpp"/>
|
||||
|
|
|
|||
|
|
@ -789,6 +789,7 @@
|
|||
<File RelativePath="..\..\src\io\files\juce_FileOutputStream.h"/>
|
||||
<File RelativePath="..\..\src\io\files\juce_FileSearchPath.cpp"/>
|
||||
<File RelativePath="..\..\src\io\files\juce_FileSearchPath.h"/>
|
||||
<File RelativePath="..\..\src\io\files\juce_MemoryMappedFile.h"/>
|
||||
<File RelativePath="..\..\src\io\files\juce_NamedPipe.cpp"/>
|
||||
<File RelativePath="..\..\src\io\files\juce_NamedPipe.h"/>
|
||||
<File RelativePath="..\..\src\io\files\juce_TemporaryFile.cpp"/>
|
||||
|
|
|
|||
|
|
@ -741,6 +741,7 @@
|
|||
<ClInclude Include="..\..\src\io\files\juce_FileInputStream.h"/>
|
||||
<ClInclude Include="..\..\src\io\files\juce_FileOutputStream.h"/>
|
||||
<ClInclude Include="..\..\src\io\files\juce_FileSearchPath.h"/>
|
||||
<ClInclude Include="..\..\src\io\files\juce_MemoryMappedFile.h"/>
|
||||
<ClInclude Include="..\..\src\io\files\juce_NamedPipe.h"/>
|
||||
<ClInclude Include="..\..\src\io\files\juce_TemporaryFile.h"/>
|
||||
<ClInclude Include="..\..\src\io\files\juce_ZipFile.h"/>
|
||||
|
|
|
|||
|
|
@ -2154,6 +2154,9 @@
|
|||
<ClInclude Include="..\..\src\io\files\juce_FileSearchPath.h">
|
||||
<Filter>Juce\Source\io\files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\io\files\juce_MemoryMappedFile.h">
|
||||
<Filter>Juce\Source\io\files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\io\files\juce_NamedPipe.h">
|
||||
<Filter>Juce\Source\io\files</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
|||
|
|
@ -898,6 +898,7 @@
|
|||
4EEF0B0BB4C3D1956B04122B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_FileOutputStream.h; path = ../../src/io/files/juce_FileOutputStream.h; sourceTree = SOURCE_ROOT; };
|
||||
59B2FFF817679AEA84375E1B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_FileSearchPath.cpp; path = ../../src/io/files/juce_FileSearchPath.cpp; sourceTree = SOURCE_ROOT; };
|
||||
49BF2B02A6D7B4438FC24839 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_FileSearchPath.h; path = ../../src/io/files/juce_FileSearchPath.h; sourceTree = SOURCE_ROOT; };
|
||||
00B348FA35A7F691AEF84FBA = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_MemoryMappedFile.h; path = ../../src/io/files/juce_MemoryMappedFile.h; sourceTree = SOURCE_ROOT; };
|
||||
D9B3C04F8EB4228DD59002E7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_NamedPipe.cpp; path = ../../src/io/files/juce_NamedPipe.cpp; sourceTree = SOURCE_ROOT; };
|
||||
42DA88264F768BAACD0414A3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_NamedPipe.h; path = ../../src/io/files/juce_NamedPipe.h; sourceTree = SOURCE_ROOT; };
|
||||
17C3AF03FF7AE88AE0C73311 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_TemporaryFile.cpp; path = ../../src/io/files/juce_TemporaryFile.cpp; sourceTree = SOURCE_ROOT; };
|
||||
|
|
@ -1713,6 +1714,7 @@
|
|||
4EEF0B0BB4C3D1956B04122B,
|
||||
59B2FFF817679AEA84375E1B,
|
||||
49BF2B02A6D7B4438FC24839,
|
||||
00B348FA35A7F691AEF84FBA,
|
||||
D9B3C04F8EB4228DD59002E7,
|
||||
42DA88264F768BAACD0414A3,
|
||||
17C3AF03FF7AE88AE0C73311,
|
||||
|
|
|
|||
|
|
@ -1177,6 +1177,8 @@
|
|||
file="src/io/files/juce_FileSearchPath.cpp"/>
|
||||
<FILE id="YJYo7slcr" name="juce_FileSearchPath.h" compile="0" resource="0"
|
||||
file="src/io/files/juce_FileSearchPath.h"/>
|
||||
<FILE id="gPKPMY" name="juce_MemoryMappedFile.h" compile="0" resource="0"
|
||||
file="src/io/files/juce_MemoryMappedFile.h"/>
|
||||
<FILE id="hwijIMGzE" name="juce_NamedPipe.cpp" compile="1" resource="0"
|
||||
file="src/io/files/juce_NamedPipe.cpp"/>
|
||||
<FILE id="Jv4ugNwIx" name="juce_NamedPipe.h" compile="0" resource="0"
|
||||
|
|
|
|||
|
|
@ -773,6 +773,7 @@ protected:
|
|||
#include <sys/ptrace.h>
|
||||
#include <sys/vfs.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fnmatch.h>
|
||||
#include <utime.h>
|
||||
#include <pwd.h>
|
||||
|
|
@ -922,6 +923,7 @@ protected:
|
|||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fnmatch.h>
|
||||
#include <utime.h>
|
||||
#include <dlfcn.h>
|
||||
|
|
@ -961,6 +963,7 @@ protected:
|
|||
#include <sys/statfs.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/mman.h>
|
||||
#include <pwd.h>
|
||||
#include <dirent.h>
|
||||
#include <fnmatch.h>
|
||||
|
|
@ -7857,53 +7860,48 @@ bool File::isAbsolutePath (const String& path)
|
|||
const File File::getChildFile (String relativePath) const
|
||||
{
|
||||
if (isAbsolutePath (relativePath))
|
||||
{
|
||||
// the path is really absolute..
|
||||
return File (relativePath);
|
||||
}
|
||||
else
|
||||
|
||||
String path (fullPath);
|
||||
|
||||
// It's relative, so remove any ../ or ./ bits at the start..
|
||||
if (relativePath[0] == '.')
|
||||
{
|
||||
// it's relative, so remove any ../ or ./ bits at the start.
|
||||
String path (fullPath);
|
||||
#if JUCE_WINDOWS
|
||||
relativePath = relativePath.replaceCharacter ('/', '\\').trimStart();
|
||||
#else
|
||||
relativePath = relativePath.trimStart();
|
||||
#endif
|
||||
|
||||
if (relativePath[0] == '.')
|
||||
while (relativePath[0] == '.')
|
||||
{
|
||||
#if JUCE_WINDOWS
|
||||
relativePath = relativePath.replaceCharacter ('/', '\\').trimStart();
|
||||
#else
|
||||
relativePath = relativePath.trimStart();
|
||||
#endif
|
||||
|
||||
while (relativePath[0] == '.')
|
||||
if (relativePath[1] == '.')
|
||||
{
|
||||
if (relativePath[1] == '.')
|
||||
if (relativePath [2] == 0 || relativePath[2] == separator)
|
||||
{
|
||||
if (relativePath [2] == 0 || relativePath[2] == separator)
|
||||
{
|
||||
const int lastSlash = path.lastIndexOfChar (separator);
|
||||
if (lastSlash >= 0)
|
||||
path = path.substring (0, lastSlash);
|
||||
const int lastSlash = path.lastIndexOfChar (separator);
|
||||
if (lastSlash >= 0)
|
||||
path = path.substring (0, lastSlash);
|
||||
|
||||
relativePath = relativePath.substring (3);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (relativePath[1] == separator)
|
||||
{
|
||||
relativePath = relativePath.substring (2);
|
||||
relativePath = relativePath.substring (3);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (relativePath[1] == separator)
|
||||
{
|
||||
relativePath = relativePath.substring (2);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return File (addTrailingSeparator (path) + relativePath);
|
||||
}
|
||||
|
||||
return File (addTrailingSeparator (path) + relativePath);
|
||||
}
|
||||
|
||||
const File File::getSiblingFile (const String& fileName) const
|
||||
|
|
@ -8481,6 +8479,39 @@ public:
|
|||
expect (mb[0] == '0');
|
||||
}
|
||||
|
||||
beginTest ("Memory-mapped files");
|
||||
|
||||
{
|
||||
MemoryMappedFile mmf (tempFile, MemoryMappedFile::readOnly);
|
||||
expect (mmf.getSize() == 10);
|
||||
expect (mmf.getData() != nullptr);
|
||||
expect (memcmp (mmf.getData(), "0123456789", 10) == 0);
|
||||
}
|
||||
|
||||
{
|
||||
const File tempFile2 (tempFile.getNonexistentSibling (false));
|
||||
expect (tempFile2.create());
|
||||
expect (tempFile2.appendData ("xxxxxxxxxx", 10));
|
||||
|
||||
{
|
||||
MemoryMappedFile mmf (tempFile2, MemoryMappedFile::readWrite);
|
||||
expect (mmf.getSize() == 10);
|
||||
expect (mmf.getData() != nullptr);
|
||||
memcpy (mmf.getData(), "abcdefghij", 10);
|
||||
}
|
||||
|
||||
{
|
||||
MemoryMappedFile mmf (tempFile2, MemoryMappedFile::readWrite);
|
||||
expect (mmf.getSize() == 10);
|
||||
expect (mmf.getData() != nullptr);
|
||||
expect (memcmp (mmf.getData(), "abcdefghij", 10) == 0);
|
||||
}
|
||||
|
||||
expect (tempFile2.deleteFile());
|
||||
}
|
||||
|
||||
beginTest ("More writing");
|
||||
|
||||
expect (tempFile.appendData ("abcdefghij", 10));
|
||||
expect (tempFile.getSize() == 20);
|
||||
expect (tempFile.replaceWithData ("abcdefghij", 10));
|
||||
|
|
@ -244800,6 +244831,55 @@ void FileOutputStream::flushInternal()
|
|||
status = WindowsFileHelpers::getResultForLastError();
|
||||
}
|
||||
|
||||
MemoryMappedFile::MemoryMappedFile (const File& file, MemoryMappedFile::AccessMode mode)
|
||||
: address (nullptr),
|
||||
internal (nullptr),
|
||||
length (0)
|
||||
{
|
||||
jassert (mode == readOnly || mode == readWrite);
|
||||
|
||||
DWORD accessMode = GENERIC_READ, shareMode = FILE_SHARE_READ, createType = OPEN_EXISTING;
|
||||
DWORD protect = PAGE_READONLY, access = FILE_MAP_READ;
|
||||
|
||||
if (mode == readWrite)
|
||||
{
|
||||
accessMode = GENERIC_READ | GENERIC_WRITE;
|
||||
createType = OPEN_ALWAYS;
|
||||
protect = PAGE_READWRITE;
|
||||
access = FILE_MAP_ALL_ACCESS;
|
||||
}
|
||||
|
||||
HANDLE h = CreateFile (file.getFullPathName().toWideCharPointer(), accessMode, FILE_SHARE_READ, 0,
|
||||
createType, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
|
||||
internal = (void*) h;
|
||||
|
||||
if (h != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
const int64 fileSize = file.getSize();
|
||||
|
||||
HANDLE mappingHandle = CreateFileMapping (h, 0, protect, (DWORD) (fileSize >> 32), (DWORD) fileSize, 0);
|
||||
if (mappingHandle != 0)
|
||||
{
|
||||
address = MapViewOfFile (mappingHandle, access, 0, 0, (SIZE_T) fileSize);
|
||||
|
||||
if (address != nullptr)
|
||||
length = (size_t) fileSize;
|
||||
|
||||
CloseHandle (mappingHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MemoryMappedFile::~MemoryMappedFile()
|
||||
{
|
||||
if (address != nullptr)
|
||||
UnmapViewOfFile (address);
|
||||
|
||||
if (internal != nullptr)
|
||||
CloseHandle ((HANDLE) internal);
|
||||
}
|
||||
|
||||
int64 File::getSize() const
|
||||
{
|
||||
WIN32_FILE_ATTRIBUTE_DATA attributes;
|
||||
|
|
@ -260588,6 +260668,46 @@ void FileOutputStream::flushInternal()
|
|||
status = getResultForErrno();
|
||||
}
|
||||
|
||||
MemoryMappedFile::MemoryMappedFile (const File& file, MemoryMappedFile::AccessMode mode)
|
||||
: address (nullptr),
|
||||
internal (nullptr),
|
||||
length (0)
|
||||
{
|
||||
jassert (mode == readOnly || mode == readWrite);
|
||||
|
||||
const int fd = open (file.getFullPathName().toUTF8(),
|
||||
mode == readWrite ? (O_CREAT + O_RDWR) : O_RDONLY, 00644);
|
||||
|
||||
internal = reinterpret_cast<void*> (fd);
|
||||
|
||||
if (fd != -1)
|
||||
{
|
||||
const int64 fileSize = file.getSize();
|
||||
|
||||
address = mmap (0, (size_t) fileSize,
|
||||
mode == readWrite ? (PROT_READ | PROT_WRITE) : PROT_READ,
|
||||
MAP_SHARED, fd, 0);
|
||||
|
||||
if (address == MAP_FAILED)
|
||||
address = nullptr;
|
||||
else
|
||||
length = (size_t) fileSize;
|
||||
}
|
||||
}
|
||||
|
||||
MemoryMappedFile::~MemoryMappedFile()
|
||||
{
|
||||
const int fd = reinterpret_cast <int> (internal);
|
||||
|
||||
if (fd != 0)
|
||||
{
|
||||
if (address != nullptr)
|
||||
munmap (address, length);
|
||||
|
||||
close (fd);
|
||||
}
|
||||
}
|
||||
|
||||
const File juce_getExecutableFile()
|
||||
{
|
||||
#if JUCE_ANDROID
|
||||
|
|
@ -270579,6 +270699,46 @@ void FileOutputStream::flushInternal()
|
|||
status = getResultForErrno();
|
||||
}
|
||||
|
||||
MemoryMappedFile::MemoryMappedFile (const File& file, MemoryMappedFile::AccessMode mode)
|
||||
: address (nullptr),
|
||||
internal (nullptr),
|
||||
length (0)
|
||||
{
|
||||
jassert (mode == readOnly || mode == readWrite);
|
||||
|
||||
const int fd = open (file.getFullPathName().toUTF8(),
|
||||
mode == readWrite ? (O_CREAT + O_RDWR) : O_RDONLY, 00644);
|
||||
|
||||
internal = reinterpret_cast<void*> (fd);
|
||||
|
||||
if (fd != -1)
|
||||
{
|
||||
const int64 fileSize = file.getSize();
|
||||
|
||||
address = mmap (0, (size_t) fileSize,
|
||||
mode == readWrite ? (PROT_READ | PROT_WRITE) : PROT_READ,
|
||||
MAP_SHARED, fd, 0);
|
||||
|
||||
if (address == MAP_FAILED)
|
||||
address = nullptr;
|
||||
else
|
||||
length = (size_t) fileSize;
|
||||
}
|
||||
}
|
||||
|
||||
MemoryMappedFile::~MemoryMappedFile()
|
||||
{
|
||||
const int fd = reinterpret_cast <int> (internal);
|
||||
|
||||
if (fd != 0)
|
||||
{
|
||||
if (address != nullptr)
|
||||
munmap (address, length);
|
||||
|
||||
close (fd);
|
||||
}
|
||||
}
|
||||
|
||||
const File juce_getExecutableFile()
|
||||
{
|
||||
#if JUCE_ANDROID
|
||||
|
|
@ -287465,6 +287625,46 @@ void FileOutputStream::flushInternal()
|
|||
status = getResultForErrno();
|
||||
}
|
||||
|
||||
MemoryMappedFile::MemoryMappedFile (const File& file, MemoryMappedFile::AccessMode mode)
|
||||
: address (nullptr),
|
||||
internal (nullptr),
|
||||
length (0)
|
||||
{
|
||||
jassert (mode == readOnly || mode == readWrite);
|
||||
|
||||
const int fd = open (file.getFullPathName().toUTF8(),
|
||||
mode == readWrite ? (O_CREAT + O_RDWR) : O_RDONLY, 00644);
|
||||
|
||||
internal = reinterpret_cast<void*> (fd);
|
||||
|
||||
if (fd != -1)
|
||||
{
|
||||
const int64 fileSize = file.getSize();
|
||||
|
||||
address = mmap (0, (size_t) fileSize,
|
||||
mode == readWrite ? (PROT_READ | PROT_WRITE) : PROT_READ,
|
||||
MAP_SHARED, fd, 0);
|
||||
|
||||
if (address == MAP_FAILED)
|
||||
address = nullptr;
|
||||
else
|
||||
length = (size_t) fileSize;
|
||||
}
|
||||
}
|
||||
|
||||
MemoryMappedFile::~MemoryMappedFile()
|
||||
{
|
||||
const int fd = reinterpret_cast <int> (internal);
|
||||
|
||||
if (fd != 0)
|
||||
{
|
||||
if (address != nullptr)
|
||||
munmap (address, length);
|
||||
|
||||
close (fd);
|
||||
}
|
||||
}
|
||||
|
||||
const File juce_getExecutableFile()
|
||||
{
|
||||
#if JUCE_ANDROID
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ namespace JuceDummyNamespace {}
|
|||
*/
|
||||
#define JUCE_MAJOR_VERSION 1
|
||||
#define JUCE_MINOR_VERSION 53
|
||||
#define JUCE_BUILDNUMBER 88
|
||||
#define JUCE_BUILDNUMBER 89
|
||||
|
||||
/** Current Juce version number.
|
||||
|
||||
|
|
@ -19409,6 +19409,68 @@ private:
|
|||
/*** End of inlined file: juce_FileSearchPath.h ***/
|
||||
|
||||
|
||||
#endif
|
||||
#ifndef __JUCE_MEMORYMAPPEDFILE_JUCEHEADER__
|
||||
|
||||
/*** Start of inlined file: juce_MemoryMappedFile.h ***/
|
||||
#ifndef __JUCE_MEMORYMAPPEDFILE_JUCEHEADER__
|
||||
#define __JUCE_MEMORYMAPPEDFILE_JUCEHEADER__
|
||||
|
||||
/**
|
||||
Maps a file into virtual memory for easy reading and/or writing.
|
||||
*/
|
||||
class JUCE_API MemoryMappedFile
|
||||
{
|
||||
public:
|
||||
/** The read/write flags used when opening a memory mapped file. */
|
||||
enum AccessMode
|
||||
{
|
||||
readOnly, /**< Indicates that the memory can only be read. */
|
||||
readWrite /**< Indicates that the memory can be read and written to - changes that are
|
||||
made will be flushed back to disk at the whim of the OS. */
|
||||
};
|
||||
|
||||
/** Opens 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.
|
||||
*/
|
||||
MemoryMappedFile (const File& file, AccessMode mode);
|
||||
|
||||
/** Destructor. */
|
||||
~MemoryMappedFile();
|
||||
|
||||
/** Returns the address at which this file has been mapped, or a null pointer if
|
||||
the file couldn't be successfully mapped.
|
||||
*/
|
||||
void* getData() const noexcept { return address; }
|
||||
|
||||
/** 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; }
|
||||
|
||||
private:
|
||||
|
||||
void* address;
|
||||
void* internal;
|
||||
size_t length;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MemoryMappedFile);
|
||||
};
|
||||
|
||||
#endif // __JUCE_MEMORYMAPPEDFILE_JUCEHEADER__
|
||||
|
||||
/*** End of inlined file: juce_MemoryMappedFile.h ***/
|
||||
|
||||
|
||||
#endif
|
||||
#ifndef __JUCE_NAMEDPIPE_JUCEHEADER__
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
*/
|
||||
#define JUCE_MAJOR_VERSION 1
|
||||
#define JUCE_MINOR_VERSION 53
|
||||
#define JUCE_BUILDNUMBER 88
|
||||
#define JUCE_BUILDNUMBER 89
|
||||
|
||||
/** Current Juce version number.
|
||||
|
||||
|
|
|
|||
|
|
@ -380,53 +380,48 @@ bool File::isAbsolutePath (const String& path)
|
|||
const File File::getChildFile (String relativePath) const
|
||||
{
|
||||
if (isAbsolutePath (relativePath))
|
||||
{
|
||||
// the path is really absolute..
|
||||
return File (relativePath);
|
||||
}
|
||||
else
|
||||
|
||||
String path (fullPath);
|
||||
|
||||
// It's relative, so remove any ../ or ./ bits at the start..
|
||||
if (relativePath[0] == '.')
|
||||
{
|
||||
// it's relative, so remove any ../ or ./ bits at the start.
|
||||
String path (fullPath);
|
||||
#if JUCE_WINDOWS
|
||||
relativePath = relativePath.replaceCharacter ('/', '\\').trimStart();
|
||||
#else
|
||||
relativePath = relativePath.trimStart();
|
||||
#endif
|
||||
|
||||
if (relativePath[0] == '.')
|
||||
while (relativePath[0] == '.')
|
||||
{
|
||||
#if JUCE_WINDOWS
|
||||
relativePath = relativePath.replaceCharacter ('/', '\\').trimStart();
|
||||
#else
|
||||
relativePath = relativePath.trimStart();
|
||||
#endif
|
||||
|
||||
while (relativePath[0] == '.')
|
||||
if (relativePath[1] == '.')
|
||||
{
|
||||
if (relativePath[1] == '.')
|
||||
if (relativePath [2] == 0 || relativePath[2] == separator)
|
||||
{
|
||||
if (relativePath [2] == 0 || relativePath[2] == separator)
|
||||
{
|
||||
const int lastSlash = path.lastIndexOfChar (separator);
|
||||
if (lastSlash >= 0)
|
||||
path = path.substring (0, lastSlash);
|
||||
const int lastSlash = path.lastIndexOfChar (separator);
|
||||
if (lastSlash >= 0)
|
||||
path = path.substring (0, lastSlash);
|
||||
|
||||
relativePath = relativePath.substring (3);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (relativePath[1] == separator)
|
||||
{
|
||||
relativePath = relativePath.substring (2);
|
||||
relativePath = relativePath.substring (3);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (relativePath[1] == separator)
|
||||
{
|
||||
relativePath = relativePath.substring (2);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return File (addTrailingSeparator (path) + relativePath);
|
||||
}
|
||||
|
||||
return File (addTrailingSeparator (path) + relativePath);
|
||||
}
|
||||
|
||||
const File File::getSiblingFile (const String& fileName) const
|
||||
|
|
@ -904,6 +899,8 @@ const File File::createTempFile (const String& fileNameEnding)
|
|||
|
||||
#include "../../utilities/juce_UnitTest.h"
|
||||
#include "../../maths/juce_Random.h"
|
||||
#include "juce_MemoryMappedFile.h"
|
||||
|
||||
|
||||
class FileTests : public UnitTest
|
||||
{
|
||||
|
|
@ -1022,6 +1019,39 @@ public:
|
|||
expect (mb[0] == '0');
|
||||
}
|
||||
|
||||
beginTest ("Memory-mapped files");
|
||||
|
||||
{
|
||||
MemoryMappedFile mmf (tempFile, MemoryMappedFile::readOnly);
|
||||
expect (mmf.getSize() == 10);
|
||||
expect (mmf.getData() != nullptr);
|
||||
expect (memcmp (mmf.getData(), "0123456789", 10) == 0);
|
||||
}
|
||||
|
||||
{
|
||||
const File tempFile2 (tempFile.getNonexistentSibling (false));
|
||||
expect (tempFile2.create());
|
||||
expect (tempFile2.appendData ("xxxxxxxxxx", 10));
|
||||
|
||||
{
|
||||
MemoryMappedFile mmf (tempFile2, MemoryMappedFile::readWrite);
|
||||
expect (mmf.getSize() == 10);
|
||||
expect (mmf.getData() != nullptr);
|
||||
memcpy (mmf.getData(), "abcdefghij", 10);
|
||||
}
|
||||
|
||||
{
|
||||
MemoryMappedFile mmf (tempFile2, MemoryMappedFile::readWrite);
|
||||
expect (mmf.getSize() == 10);
|
||||
expect (mmf.getData() != nullptr);
|
||||
expect (memcmp (mmf.getData(), "abcdefghij", 10) == 0);
|
||||
}
|
||||
|
||||
expect (tempFile2.deleteFile());
|
||||
}
|
||||
|
||||
beginTest ("More writing");
|
||||
|
||||
expect (tempFile.appendData ("abcdefghij", 10));
|
||||
expect (tempFile.getSize() == 20);
|
||||
expect (tempFile.replaceWithData ("abcdefghij", 10));
|
||||
|
|
|
|||
84
src/io/files/juce_MemoryMappedFile.h
Normal file
84
src/io/files/juce_MemoryMappedFile.h
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-11 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online at www.gnu.org/licenses.
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef __JUCE_MEMORYMAPPEDFILE_JUCEHEADER__
|
||||
#define __JUCE_MEMORYMAPPEDFILE_JUCEHEADER__
|
||||
|
||||
#include "juce_File.h"
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Maps a file into virtual memory for easy reading and/or writing.
|
||||
*/
|
||||
class JUCE_API MemoryMappedFile
|
||||
{
|
||||
public:
|
||||
/** The read/write flags used when opening a memory mapped file. */
|
||||
enum AccessMode
|
||||
{
|
||||
readOnly, /**< Indicates that the memory can only be read. */
|
||||
readWrite /**< Indicates that the memory can be read and written to - changes that are
|
||||
made will be flushed back to disk at the whim of the OS. */
|
||||
};
|
||||
|
||||
/** Opens 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.
|
||||
*/
|
||||
MemoryMappedFile (const File& file, AccessMode mode);
|
||||
|
||||
/** Destructor. */
|
||||
~MemoryMappedFile();
|
||||
|
||||
/** Returns the address at which this file has been mapped, or a null pointer if
|
||||
the file couldn't be successfully mapped.
|
||||
*/
|
||||
void* getData() const noexcept { return address; }
|
||||
|
||||
/** 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; }
|
||||
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
void* address;
|
||||
void* internal;
|
||||
size_t length;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MemoryMappedFile);
|
||||
};
|
||||
|
||||
|
||||
#endif // __JUCE_MEMORYMAPPEDFILE_JUCEHEADER__
|
||||
|
|
@ -146,6 +146,9 @@
|
|||
#ifndef __JUCE_FILESEARCHPATH_JUCEHEADER__
|
||||
#include "io/files/juce_FileSearchPath.h"
|
||||
#endif
|
||||
#ifndef __JUCE_MEMORYMAPPEDFILE_JUCEHEADER__
|
||||
#include "io/files/juce_MemoryMappedFile.h"
|
||||
#endif
|
||||
#ifndef __JUCE_NAMEDPIPE_JUCEHEADER__
|
||||
#include "io/files/juce_NamedPipe.h"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ BEGIN_JUCE_NAMESPACE
|
|||
#include "../../io/files/juce_FileOutputStream.h"
|
||||
#include "../../io/files/juce_NamedPipe.h"
|
||||
#include "../../io/files/juce_DirectoryIterator.h"
|
||||
#include "../../io/files/juce_MemoryMappedFile.h"
|
||||
#include "../../io/network/juce_URL.h"
|
||||
#include "../../io/network/juce_MACAddress.h"
|
||||
#include "../../core/juce_PlatformUtilities.h"
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
#include <sys/statfs.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/mman.h>
|
||||
#include <pwd.h>
|
||||
#include <dirent.h>
|
||||
#include <fnmatch.h>
|
||||
|
|
|
|||
|
|
@ -523,6 +523,47 @@ void FileOutputStream::flushInternal()
|
|||
status = getResultForErrno();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
MemoryMappedFile::MemoryMappedFile (const File& file, MemoryMappedFile::AccessMode mode)
|
||||
: address (nullptr),
|
||||
internal (nullptr),
|
||||
length (0)
|
||||
{
|
||||
jassert (mode == readOnly || mode == readWrite);
|
||||
|
||||
const int fd = open (file.getFullPathName().toUTF8(),
|
||||
mode == readWrite ? (O_CREAT + O_RDWR) : O_RDONLY, 00644);
|
||||
|
||||
internal = reinterpret_cast<void*> (fd);
|
||||
|
||||
if (fd != -1)
|
||||
{
|
||||
const int64 fileSize = file.getSize();
|
||||
|
||||
address = mmap (0, (size_t) fileSize,
|
||||
mode == readWrite ? (PROT_READ | PROT_WRITE) : PROT_READ,
|
||||
MAP_SHARED, fd, 0);
|
||||
|
||||
if (address == MAP_FAILED)
|
||||
address = nullptr;
|
||||
else
|
||||
length = (size_t) fileSize;
|
||||
}
|
||||
}
|
||||
|
||||
MemoryMappedFile::~MemoryMappedFile()
|
||||
{
|
||||
const int fd = reinterpret_cast <int> (internal);
|
||||
|
||||
if (fd != 0)
|
||||
{
|
||||
if (address != nullptr)
|
||||
munmap (address, length);
|
||||
|
||||
close (fd);
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
const File juce_getExecutableFile()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ BEGIN_JUCE_NAMESPACE
|
|||
#include "../../io/files/juce_FileInputStream.h"
|
||||
#include "../../io/files/juce_FileOutputStream.h"
|
||||
#include "../../io/files/juce_DirectoryIterator.h"
|
||||
#include "../../io/files/juce_MemoryMappedFile.h"
|
||||
#include "../../io/network/juce_URL.h"
|
||||
#include "../../io/network/juce_MACAddress.h"
|
||||
#include "../../io/streams/juce_MemoryInputStream.h"
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include <sys/ptrace.h>
|
||||
#include <sys/vfs.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fnmatch.h>
|
||||
#include <utime.h>
|
||||
#include <pwd.h>
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ BEGIN_JUCE_NAMESPACE
|
|||
#include "../../io/files/juce_FileOutputStream.h"
|
||||
#include "../../io/files/juce_NamedPipe.h"
|
||||
#include "../../io/files/juce_DirectoryIterator.h"
|
||||
#include "../../io/files/juce_MemoryMappedFile.h"
|
||||
#include "../../io/network/juce_URL.h"
|
||||
#include "../../io/network/juce_MACAddress.h"
|
||||
#include "../../io/streams/juce_MemoryInputStream.h"
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@
|
|||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fnmatch.h>
|
||||
#include <utime.h>
|
||||
#include <dlfcn.h>
|
||||
|
|
|
|||
|
|
@ -299,6 +299,56 @@ void FileOutputStream::flushInternal()
|
|||
status = WindowsFileHelpers::getResultForLastError();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
MemoryMappedFile::MemoryMappedFile (const File& file, MemoryMappedFile::AccessMode mode)
|
||||
: address (nullptr),
|
||||
internal (nullptr),
|
||||
length (0)
|
||||
{
|
||||
jassert (mode == readOnly || mode == readWrite);
|
||||
|
||||
DWORD accessMode = GENERIC_READ, shareMode = FILE_SHARE_READ, createType = OPEN_EXISTING;
|
||||
DWORD protect = PAGE_READONLY, access = FILE_MAP_READ;
|
||||
|
||||
if (mode == readWrite)
|
||||
{
|
||||
accessMode = GENERIC_READ | GENERIC_WRITE;
|
||||
createType = OPEN_ALWAYS;
|
||||
protect = PAGE_READWRITE;
|
||||
access = FILE_MAP_ALL_ACCESS;
|
||||
}
|
||||
|
||||
HANDLE h = CreateFile (file.getFullPathName().toWideCharPointer(), accessMode, FILE_SHARE_READ, 0,
|
||||
createType, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
|
||||
internal = (void*) h;
|
||||
|
||||
if (h != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
const int64 fileSize = file.getSize();
|
||||
|
||||
HANDLE mappingHandle = CreateFileMapping (h, 0, protect, (DWORD) (fileSize >> 32), (DWORD) fileSize, 0);
|
||||
if (mappingHandle != 0)
|
||||
{
|
||||
address = MapViewOfFile (mappingHandle, access, 0, 0, (SIZE_T) fileSize);
|
||||
|
||||
if (address != nullptr)
|
||||
length = (size_t) fileSize;
|
||||
|
||||
CloseHandle (mappingHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MemoryMappedFile::~MemoryMappedFile()
|
||||
{
|
||||
if (address != nullptr)
|
||||
UnmapViewOfFile (address);
|
||||
|
||||
if (internal != nullptr)
|
||||
CloseHandle ((HANDLE) internal);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
int64 File::getSize() const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ BEGIN_JUCE_NAMESPACE
|
|||
#include "../../io/streams/juce_MemoryOutputStream.h"
|
||||
#include "../../io/files/juce_NamedPipe.h"
|
||||
#include "../../io/files/juce_DirectoryIterator.h"
|
||||
#include "../../io/files/juce_MemoryMappedFile.h"
|
||||
#include "../../io/network/juce_URL.h"
|
||||
#include "../../io/network/juce_MACAddress.h"
|
||||
#include "../../core/juce_PlatformUtilities.h"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue