Hi
I wanted to show you a simple file loader class that can read both Asynchronously and Synchronously and have you let me know if its "good and clean".
Also, could the buffer be public or should I have some method that returns a pointer to the vector or something for when I want to process it later form outside?
class FileLoader
{
public:
FileLoader(std::string Filename, bool Asynchronous);
~FileLoader();
DWORD GetStatus();
private:
void Tick();
void ReadAsynch();
void ReadSynch();
HANDLE file;
DWORD Size;
DWORD Status;
DWORD NumberOfBytesTransfered;
OVERLAPPED OverlappedInfo;
std::vector<BYTE> buffer;
};
FileLoader::FileLoader(std::string Filename, bool Asynchronous)
{
Size = 0;
Status = 0;
NumberOfBytesTransfered = 0;
ZeroMemory(&OverlappedInfo, sizeof(OverlappedInfo));
if (Asynchronous)
{
file = CreateFileA(Filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_OVERLAPPED, NULL);
}
else {
file = CreateFileA(Filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
}
if (file == INVALID_HANDLE_VALUE)
{
Status = FileLoaderErrorInvalidHandle;
}
else {
Size = GetFileSize(file, NULL);
if (Size == INVALID_FILE_SIZE)
{
Status = FileLoaderErrorInvalidSize;
CloseHandle(file);
}
else {
buffer.resize(Size);
if (Asynchronous)
{
ReadAsynch();
}
else {
ReadSynch();
}
}
}
}
FileLoader::~FileLoader()
{
CloseHandle(file);
}
DWORD FileLoader::GetStatus()
{
Tick();
return Status;
}
void FileLoader::ReadAsynch()
{
OverlappedInfo.hEvent = CreateEvent(NULL, true, false, NULL);
if (ReadFile(file, &buffer[0], Size, NULL, &OverlappedInfo))
{
// Operation has completed immediately.
Status = FileLoaderComplete;
}
else {
if (GetLastError() != ERROR_IO_PENDING)
{
// Some other error occurred while reading the file.
CloseHandle(file);
buffer.clear();
Status = FileLoaderErrorX;
}
else {
//Operation has been queued and will complete in the future.
Status = FileLoaderInTransfer;
}
}
}
void FileLoader::ReadSynch()
{
if (ReadFile(file, &buffer[0], Size, &NumberOfBytesTransfered, NULL))
{
// Operation has completed.
if (Size == NumberOfBytesTransfered){
Status = FileLoaderComplete;
}
else {
Status = FileLoaderErrorReadSize;
}
}
else {
// Some other error occurred while reading the file.
CloseHandle(file);
buffer.clear();
Status = FileLoaderErrorX;
}
}
void FileLoader::Tick()
{
if (Status == FileLoaderInTransfer)
{
if (HasOverlappedIoCompleted(&OverlappedInfo))
{
if (GetOverlappedResult(file, &OverlappedInfo, &NumberOfBytesTransfered, false) != 0)
{
// Operation has completed.
CloseHandle(file);
if (Size == NumberOfBytesTransfered){
Status = FileLoaderComplete;
} else {
Status = FileLoaderErrorReadSize;
}
}
}
}
}
//FileLoader defs
#define FileLoaderUnknown 0
#define FileLoaderComplete 1
#define FileLoaderInTransfer 2
#define FileLoaderErrorInvalidHandle 10
#define FileLoaderErrorInvalidSize 11
#define FileLoaderErrorX 12
#define FileLoaderErrorReadSize 13
#define FileLoaderError4 14
#define FileLoaderError5 15