Files
rippled/modules/beast_core/files/beast_RandomAccessFile.h
2013-07-21 12:54:07 -07:00

243 lines
8.0 KiB
C++

//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_RANDOMACCESSFILE_H_INCLUDED
#define BEAST_RANDOMACCESSFILE_H_INCLUDED
#include "../misc/beast_Result.h"
/** Provides random access reading and writing to an operating system file.
This class wraps the underlying native operating system routines for
opening and closing a file for reading and/or writing, seeking within
the file, and performing read and write operations. There are also methods
provided for obtaining an input or output stream which will work with
the file.
Writes are batched using an internal buffer. The buffer is flushed when
it fills, the current position is manually changed, or the file
is closed. It is also possible to explicitly flush the buffer.
@note All files are opened in binary mode. No text newline conversions
are performed.
@see FileInputStream, FileOutputStream
*/
class BEAST_API RandomAccessFile : Uncopyable, LeakChecked <RandomAccessFile>
{
public:
/** The type of an FileOffset.
This can be useful when writing templates.
*/
typedef int64 FileOffset;
/** The type of a byte count.
This can be useful when writing templates.
*/
typedef size_t ByteCount;
/** The access mode.
@see open
*/
enum Mode
{
readOnly,
readWrite
};
//==============================================================================
/** Creates an unopened file object.
@see open, isOpen
*/
explicit RandomAccessFile (int bufferSizeToUse = 16384) noexcept;
/** Destroy the file object.
If the operating system file is open it will be closed.
*/
~RandomAccessFile ();
/** Determine if a file is open.
@return `true` if the operating system file is open.
*/
bool isOpen () const noexcept { return fileHandle != nullptr; }
/** Opens a file object.
The file is opened with the specified permissions. The initial
position is set to the beginning of the file.
@note If a file is already open, it will be closed first.
@param path The path to the file
@param mode The access permissions
@return An indication of the success of the operation.
@see Mode
*/
Result open (File const& path, Mode mode);
/** Closes the file object.
Any data that needs to be flushed will be written before the file is closed.
@note If no file is opened, this call does nothing.
*/
void close ();
/** Retrieve the @ref File associated with this object.
@return The associated @ref File.
*/
File const& getFile () const noexcept { return file; }
/** Get the current position.
The next read or write will take place from here.
@return The current position, as an absolute byte FileOffset from the begining.
*/
FileOffset getPosition () const noexcept { return currentPosition; }
/** Set the current position.
The next read or write will take place at this location.
@param newPosition The byte FileOffset from the beginning of the file to move to.
@return `true` if the operation was successful.
*/
Result setPosition (FileOffset newPosition);
/** Read data at the current position.
The caller is responsible for making sure that the memory pointed to
by `buffer` is at least as large as `bytesToRead`.
@note The file must have been opened with read permission.
@param buffer The memory to store the incoming data
@param numBytes The number of bytes to read.
@param pActualAmount Pointer to store the actual amount read, or `nullptr`.
@return `true` if all the bytes were read.
*/
Result read (void* buffer, ByteCount numBytes, ByteCount* pActualAmount = 0);
/** Write data at the current position.
The current position is advanced past the data written. If data is
written past the end of the file, the file size is increased on disk.
The caller is responsible for making sure that the memory pointed to
by `buffer` is at least as large as `bytesToWrite`.
@note The file must have been opened with write permission.
@param data A pointer to the data buffer to write to the file.
@param numBytes The number of bytes to write.
@param pActualAmount Pointer to store the actual amount written, or `nullptr`.
@return `true` if all the data was written.
*/
Result write (const void* data, ByteCount numBytes, ByteCount* pActualAmount = 0);
/** Truncate the file at the current position.
*/
Result truncate ();
/** Flush the output buffers.
This calls the operating system to make sure all data has been written.
*/
Result flush();
//==============================================================================
private:
Result flushBuffer ();
// Some of these these methods are implemented natively on
// the corresponding platform.
//
// See beast_posix_SharedCode.h and beast_win32_Files.cpp
Result nativeOpen (File const& path, Mode mode);
void nativeClose ();
Result nativeSetPosition (FileOffset newPosition);
Result nativeRead (void* buffer, ByteCount numBytes, ByteCount* pActualAmount = 0);
Result nativeWrite (const void* data, ByteCount numBytes, ByteCount* pActualAmount = 0);
Result nativeTruncate ();
Result nativeFlush ();
private:
File file;
void* fileHandle;
FileOffset currentPosition;
ByteCount const bufferSize;
ByteCount bytesInBuffer;
HeapBlock <char> writeBuffer;
};
class BEAST_API RandomAccessFileInputStream : public InputStream
{
public:
explicit RandomAccessFileInputStream (RandomAccessFile& file) : m_file (file) { }
int64 getTotalLength() { return m_file.getFile ().getSize (); }
bool isExhausted() { return getPosition () == getTotalLength (); }
int read (void* destBuffer, int maxBytesToRead)
{
size_t actualBytes = 0;
m_file.read (destBuffer, maxBytesToRead, &actualBytes);
return actualBytes;
}
int64 getPosition() { return m_file.getPosition (); }
bool setPosition (int64 newPosition) { return m_file.setPosition (newPosition); }
void skipNextBytes (int64 numBytesToSkip) { m_file.setPosition (getPosition () + numBytesToSkip); }
private:
RandomAccessFile& m_file;
};
class BEAST_API RandomAccessFileOutputStream : public OutputStream
{
public:
explicit RandomAccessFileOutputStream (RandomAccessFile& file) : m_file (file) { }
void flush() { m_file.flush (); }
int64 getPosition() { return m_file.getPosition (); }
bool setPosition (int64 newPosition) { return m_file.setPosition (newPosition); }
bool write (const void* dataToWrite, size_t numberOfBytes) { return m_file.write (dataToWrite, numberOfBytes); }
private:
RandomAccessFile& m_file;
};
#endif