gereon
12 years ago
2 changed files with 132 additions and 105 deletions
@ -0,0 +1,128 @@ |
|||||
|
#include "src/parser/parser.h"
|
||||
|
|
||||
|
#if defined LINUX || defined MACOSX
|
||||
|
#include <sys/mman.h>
|
||||
|
#elif defined WINDOWS
|
||||
|
#endif
|
||||
|
|
||||
|
#include <sys/stat.h>
|
||||
|
#include <fcntl.h>
|
||||
|
#include <errno.h>
|
||||
|
#include <iostream>
|
||||
|
|
||||
|
#include <pantheios/pantheios.hpp>
|
||||
|
#include "src/exceptions/file_IO_exception.h"
|
||||
|
#include "src/exceptions/wrong_file_format.h"
|
||||
|
|
||||
|
/*!
|
||||
|
* Calls strtol() internally and checks if the new pointer is different |
||||
|
* from the original one, i.e. if str != *end. If they are the same, a |
||||
|
* mrmc::exceptions::wrong_file_format will be thrown. |
||||
|
* @param str String to parse |
||||
|
* @param end New pointer will be written there |
||||
|
* @return Result of strtol() |
||||
|
*/ |
||||
|
uint_fast64_t mrmc::parser::checked_strtol(const char* str, char** end) |
||||
|
{ |
||||
|
uint_fast64_t res = strtol(str, end, 10); |
||||
|
if (str == *end) throw mrmc::exceptions::wrong_file_format(); |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Skips spaces, tabs, newlines and carriage returns. Returns pointer |
||||
|
* to first char that is not a whitespace. |
||||
|
* @param buf String buffer |
||||
|
* @return pointer to first non-whitespace character |
||||
|
*/ |
||||
|
char* mrmc::parser::skipWS(char* buf) |
||||
|
{ |
||||
|
while ((*buf == ' ') || (*buf == '\t') || (*buf == '\n') || (*buf == '\r')) buf++; |
||||
|
return buf; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Will stat the given file, open it and map it to memory. |
||||
|
* If anything of this fails, an appropriate exception is raised |
||||
|
* and a log entry is written. |
||||
|
* @param filename file to be opened |
||||
|
*/ |
||||
|
mrmc::parser::MappedFile::MappedFile(const char* filename) |
||||
|
{ |
||||
|
#if defined LINUX || defined MACOSX
|
||||
|
/*
|
||||
|
* Do file mapping for reasonable systems. |
||||
|
* stat64(), open(), mmap() |
||||
|
*/ |
||||
|
if (stat64(filename, &(this->st)) != 0) |
||||
|
{ |
||||
|
pantheios::log_ERROR("Could not stat ", filename, ". Does it exist? Is it readable?"); |
||||
|
throw exceptions::file_IO_exception("mrmc::parser::MappedFile Error in stat()"); |
||||
|
} |
||||
|
this->file = open(filename, O_RDONLY); |
||||
|
|
||||
|
if (this->file < 0) |
||||
|
{ |
||||
|
pantheios::log_ERROR("Could not open ", filename, ". Does it exist? Is it readable?"); |
||||
|
throw exceptions::file_IO_exception("mrmc::parser::MappedFile Error in open()"); |
||||
|
} |
||||
|
|
||||
|
this->data = (char*) mmap(NULL, this->st.st_size, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, this->file, 0); |
||||
|
if (this->data == (char*)-1) |
||||
|
{ |
||||
|
close(this->file); |
||||
|
pantheios::log_ERROR("Could not mmap ", filename, "."); |
||||
|
throw exceptions::file_IO_exception("mrmc::parser::MappedFile Error in mmap()"); |
||||
|
} |
||||
|
this->dataend = this->data + this->st.st_size; |
||||
|
#elif defined WINDOWS
|
||||
|
/*
|
||||
|
* Do file mapping for windows. |
||||
|
* _stat64(), CreateFile(), CreateFileMapping(), MapViewOfFile() |
||||
|
*/ |
||||
|
if (_stat64(filename, &(this->st)) != 0) |
||||
|
{ |
||||
|
pantheios::log_ERROR("Could not stat ", filename, ". Does it exist? Is it readable?"); |
||||
|
throw exceptions::file_IO_exception("mrmc::parser::MappedFile Error in stat()"); |
||||
|
} |
||||
|
|
||||
|
this->file = CreateFileA(filename, GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); |
||||
|
if (this->file == INVALID_HANDLE_VALUE) |
||||
|
{ |
||||
|
pantheios::log_ERROR("Could not open ", filename, ". Does it exist? Is it readable?"); |
||||
|
throw exceptions::file_IO_exception("mrmc::parser::MappedFile Error in CreateFile()"); |
||||
|
} |
||||
|
|
||||
|
this->mapping = CreateFileMappingA(this->file, NULL, PAGE_READONLY, (DWORD)(st.st_size >> 32), (DWORD)st.st_size, NULL); |
||||
|
if (this->mapping == NULL) |
||||
|
{ |
||||
|
CloseHandle(this->file); |
||||
|
pantheios::log_ERROR("Could not create file mapping for ", filename, "."); |
||||
|
throw exceptions::file_IO_exception("mrmc::parser::MappedFile Error in CreateFileMapping()"); |
||||
|
} |
||||
|
|
||||
|
this->data = static_cast<char*>(MapViewOfFile(this->mapping, FILE_MAP_READ, 0, 0, this->st.st_size)); |
||||
|
if (this->data == NULL) |
||||
|
{ |
||||
|
CloseHandle(this->mapping); |
||||
|
CloseHandle(this->file); |
||||
|
pantheios::log_ERROR("Could not create file map view for ", filename, "."); |
||||
|
throw exceptions::file_IO_exception("mrmc::parser::MappedFile Error in MapViewOfFile()"); |
||||
|
} |
||||
|
this->dataend = this->data + this->st.st_size; |
||||
|
#endif
|
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Will unmap the data and close the file. |
||||
|
*/ |
||||
|
mrmc::parser::MappedFile::~MappedFile() |
||||
|
{ |
||||
|
#if defined LINUX || defined MACOSX
|
||||
|
munmap(this->data, this->st.st_size); |
||||
|
close(this->file); |
||||
|
#elif defined WINDOWS
|
||||
|
CloseHandle(this->mapping); |
||||
|
CloseHandle(this->file); |
||||
|
#endif
|
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue