File.h
// File.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2004
#pragma once
#ifndef Ceda_cxUtils_File_H
#define Ceda_cxUtils_File_H
#include "cxUtils.h"
#include "MsWindows.h"
#include "xstring.h"
#include "SubString.h"
#include "Stream.h"
#include "HPTime.h"
#include <stdio.h>
#include <cstdio>
#ifdef _WIN32_WCE
// missing in Windows Mobile,so we provide our own implementation
cxUtils_API void GetSystemTimeAsFileTime(LPFILETIME filetime);
#endif
namespace ceda
{
class PagedBuffer;
///////////////////////////////////////////////////////////////////////////////////////////////////
// IFile
// Is the file opened for reading or writing?
enum EFileDirection
{
FD_READING,
FD_WRITING
};
struct IFile : public ISeekableInputStream, public IOutputStream
{
// The following methods may throw a file exception on error
virtual void Close() = 0;
// Is the file opened for reading or writing?
virtual EFileDirection Direction() const = 0;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
// File
inline FILE* fopen_u8(ConstStringZ filename, ConstStringZ mode)
{
#ifdef _WIN32
return cxWIN32::_wfopen(as_LPCWSTR(filename), as_LPCWSTR(mode));
#else
return fopen(filename, mode);
#endif
}
enum EMode
{
// Text file
FM_READ_TEXT,
FM_WRITE_TEXT,
FM_APPEND_TEXT,
// Binary file
FM_READ_BINARY,
FM_WRITE_BINARY,
FM_APPEND_BINARY,
};
class cxUtils_API File : public IFile
{
cxNotCloneable(File)
public:
// If default ctor used then use Open() to open the file
File();
// Will throw exceptions if the file can't be opened
File(const xstring& filename, EMode mode);
~File();
bool IsOpen() const { return m_fp != nullptr; }
// Try to open the file. returns false if file could not be opened
// Will close the existing file that has previously been opened if any.
bool Open(const xstring& filename, EMode mode);
// Implementation of IInputStream
virtual ssize_t ReadStream(void* buffer, ssize_t numBytes);
// Implementation of ISeekableInputStream
virtual ssize_t GetStreamLength() const;
virtual ssize_t GetStreamPosition() const;
virtual void SetStreamPosition(ssize_t pos);
// Implementation of IOutputStream
virtual void WriteStream(const void* buffer, ssize_t numBytes);
virtual void FlushStream();
// Implementation of IFile
virtual void Close();
virtual EFileDirection Direction() const;
bool SeekFromCurrentPosition(ssize_t position);
bool SeekFromStart(ssize_t position);
bool SeekFromEnd(ssize_t position);
private:
FILE* m_fp;
EMode m_mode;
xstring m_filename;
ssize_t m_numBytesWritten;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
// Read a buffer from a binary file. Returns false if file not found. Throws exceptions
// on I/O errors
cxUtils_API bool ReadBufferFromFile(xvector<octet_t>& buffer, const xstring& filename);
// Write a buffer to a binary file. Throws exceptions on I/O errors.
cxUtils_API void WriteBufferToFile(const void* buffer, ssize_t size, const xstring& filename);
cxUtils_API void WritePagedBufferToFile(const PagedBuffer& pb, const xstring& filename);
///////////////////////////////////////////////////////////////////////////////////////////////////
// Validated versions of ReadBufferFromFile()/WriteBufferToFile()
/*
WriteBufferToFile() and ReadBufferFromFile() are relatively dangerous for using Archive and
InputArchive to write/read binary files. This is because InputArchive doesn't use any concept of
checking for writing past the end of the buffer. It is only appropriate for reading a binary
format from a trusted source.
For various reasons binary files cannot always be trusted. For example, a process can fail part
way through writing a file, in which case the file is truncated.
The following functions use a header on the file consisting of:
- the length of the buffer in bytes (recorded as an int64)
- A 32 bit CRC checksum on the buffer.
*/
cxUtils_API void WriteValidatedPagedBufferToFile(int32 magic, const PagedBuffer& pb, const xstring& filename);
cxUtils_API bool ReadValidatedBufferFromFile(int32 magic, xvector<octet_t>& buffer, const xstring& filename);
} // namespace ceda
#endif // include guard