Added fs::file_ptr, fom::rewrite, cleanup

This commit is contained in:
Nekotekina 2015-11-01 13:33:28 +03:00
parent 009aa3dcb9
commit a4db58f5f2
19 changed files with 130 additions and 54 deletions

View file

@ -96,6 +96,7 @@ bool truncate_file(const std::string& file, u64 length)
}
#else
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
@ -306,14 +307,16 @@ bool fs::rename(const std::string& from, const std::string& to)
int OSCopyFile(const char* source, const char* destination, bool overwrite)
{
/* This function was taken from http://stackoverflow.com/questions/2180079/how-can-i-copy-a-file-on-unix-using-c */
/* Source: http://stackoverflow.com/questions/2180079/how-can-i-copy-a-file-on-unix-using-c */
int input, output;
if ((input = open(source, O_RDONLY)) == -1)
const int input = open(source, O_RDONLY);
if (input == -1)
{
return -1;
}
if ((output = open(destination, O_WRONLY | O_CREAT | (overwrite ? O_TRUNC : O_EXCL), 0666)) == -1)
const int output = open(destination, O_WRONLY | O_CREAT | (overwrite ? O_TRUNC : O_EXCL), 0666);
if (output == -1)
{
close(input);
return -1;
@ -322,13 +325,12 @@ int OSCopyFile(const char* source, const char* destination, bool overwrite)
//Here we use kernel-space copying for performance reasons
#if defined(__APPLE__) || defined(__FreeBSD__)
//fcopyfile works on FreeBSD and OS X 10.5+
int result = fcopyfile(input, output, 0, COPYFILE_ALL);
const int result = fcopyfile(input, output, 0, COPYFILE_ALL);
#else
//sendfile will work with non-socket output (i.e. regular file) on Linux 2.6.33+
off_t bytesCopied = 0;
struct stat fileinfo = { 0 };
fstat(input, &fileinfo);
int result = sendfile(output, input, &bytesCopied, fileinfo.st_size) == -1 ? -1 : 0;
const int result = fstat(input, &fileinfo) == -1 || sendfile(output, input, &bytesCopied, fileinfo.st_size) == -1 ? -1 : 0;
#endif
close(input);
@ -662,6 +664,36 @@ fs::dir::~dir()
}
}
void fs::file_ptr::reset(const file& f)
{
reset();
if (f)
{
#ifdef _WIN32
const HANDLE handle = ::CreateFileMapping((HANDLE)f.m_fd, NULL, PAGE_READONLY, 0, 0, NULL);
m_ptr = (char*)::MapViewOfFile(handle, FILE_MAP_READ, 0, 0, 0);
m_size = f.size();
::CloseHandle(handle);
#else
m_ptr = (char*)::mmap(nullptr, m_size = f.size(), PROT_READ, MAP_SHARED, f.m_fd, 0);
if (m_ptr == (void*)-1) m_ptr = nullptr;
#endif
}
}
void fs::file_ptr::reset()
{
if (m_ptr)
{
#ifdef _WIN32
::UnmapViewOfFile(m_ptr);
#else
::munmap(m_ptr, m_size);
#endif
}
}
bool fs::dir::open(const std::string& dirname)
{
this->close();

View file

@ -11,12 +11,14 @@ namespace fom // file open mode
{
enum : u32
{
read = 1 << 0,
write = 1 << 1,
append = 1 << 2,
create = 1 << 3,
trunc = 1 << 4,
excl = 1 << 5,
read = 1 << 0, // enable reading
write = 1 << 1, // enable writing
append = 1 << 2, // enable appending (always write to the end of file)
create = 1 << 3, // create file if it doesn't exist
trunc = 1 << 4, // clear opened file if it's not empty
excl = 1 << 5, // failure if the file already exists (used with `create`)
rewrite = write | create | trunc, // write + create + trunc
};
};
@ -81,6 +83,8 @@ namespace fs
handle_type m_fd = null;
friend class file_ptr;
public:
file() = default;
@ -133,14 +137,63 @@ namespace fs
// Write the data to the file and return the amount of data actually written
u64 write(const void* buffer, u64 count) const;
// Write std::string
u64 write(const std::string& string) const { return write(string.data(), string.size()); }
// Move file pointer
u64 seek(s64 offset, fsm seek_mode = fsm::begin) const;
// Get file size
u64 size() const;
// Write std::string
const file& operator <<(const std::string& str) const
{
CHECK_ASSERTION(write(str.data(), str.size()) == str.size());
return *this;
}
};
class file_ptr final
{
char* m_ptr = nullptr;
u64 m_size;
public:
file_ptr() = default;
file_ptr(file_ptr&& right)
: m_ptr(right.m_ptr)
, m_size(right.m_size)
{
right.m_ptr = 0;
}
file_ptr& operator =(file_ptr&& right)
{
std::swap(m_ptr, right.m_ptr);
std::swap(m_size, right.m_size);
return *this;
}
file_ptr(const file& f)
{
reset(f);
}
~file_ptr()
{
reset();
}
// Open file mapping
void reset(const file& f);
// Close file mapping
void reset();
// Get pointer
operator char*() const
{
return m_ptr;
}
};
class dir final

View file

@ -94,7 +94,7 @@ struct FileListener : LogListener
bool mPrependChannelName;
FileListener(const std::string& name = _PRGNAME_, bool prependChannel = true)
: mFile(rPlatform::getConfigDir() + name + ".log", fom::write | fom::create | fom::trunc)
: mFile(rPlatform::getConfigDir() + name + ".log", fom::rewrite)
, mPrependChannelName(prependChannel)
{
if (!mFile)
@ -120,7 +120,7 @@ struct FileListener : LogListener
}
}
mFile.write(text.c_str(), text.size());
mFile << text;
}
};