Added memstreambuf and imemfile

This commit is contained in:
Bob Polis 2022-12-10 23:03:36 +01:00
parent 9dbb05d26c
commit 4550b1fc05
3 changed files with 156 additions and 1 deletions

14
src/imemfile.cpp Normal file
View File

@ -0,0 +1,14 @@
#include "libscio.hpp"
sc::io::imemfile::imemfile(const std::string& path) : std::istream {&_buf},
_file {path},
_buf {_file.mapping(), _file.size()} {}
sc::io::imemfile::imemfile(imemfile&& other) : std::istream {&_buf},
_file {std::move(other._file)},
_buf {std::move(other._buf)} {}
void sc::io::imemfile::open(const std::string& path, std::ios_base::openmode /* mode */) {
_file.open(path);
_buf.init(_file.mapping(), _file.size());
}

View File

@ -284,7 +284,7 @@ namespace sc {
class mapped_file {
public:
mapped_file();
mapped_file() = default;
mapped_file(const std::string& path);
// no copying
@ -301,6 +301,7 @@ namespace sc {
// it's an error to open an already opened mapped_file
// open() is meant to be used after default constructor
void open(const std::string& path);
bool is_open() const { return _fd != -1; }
// direct (read-only) access to mapped memory
char* mapping() const { return _mapping; }
@ -312,6 +313,67 @@ namespace sc {
size_t _length {0};
};
class memstreambuf : public std::streambuf {
public:
memstreambuf() = default;
void init(char* mem, size_t size);
memstreambuf(char* mem, size_t size);
void mem(char* m) { _mem = m; }
char* mem() const { return _mem; }
void size(size_t sz) { _size = sz; }
size_t size() const { return _size; }
protected:
// input
int_type uflow() override;
std::streamsize xsgetn(char* s, std::streamsize n) override;
// output
int_type overflow(int_type c) override;
std::streamsize xsputn(const char* s, std::streamsize num) override;
// stream offset positioning
pos_type seekoff(off_type off,
std::ios_base::seekdir dir,
std::ios_base::openmode which
= std::ios_base::in | std::ios_base::out) override;
pos_type seekpos(pos_type pos, std::ios_base::openmode which
= std::ios_base::in | std::ios_base::out) override;
int_type pbackfail(int_type c = EOF) override;
private:
char* _mem {nullptr};
size_t _size {0};
};
class imemfile : public std::istream {
public:
imemfile() : std::istream(&_buf) {}
imemfile(const std::string& path);
// no copying
imemfile(const imemfile&) = delete;
imemfile& operator=(const imemfile&) = delete;
// move is allowed
imemfile(imemfile&& other);
imemfile& operator=(imemfile&&) = default;
~imemfile() = default;
bool is_open() const { return _file.is_open(); }
void open(const std::string& path, std::ios_base::openmode mode
= std::ios_base::in | std::ios_base::binary);
char* data() const { return _file.mapping(); }
size_t size() const { return _file.size(); }
private:
mapped_file _file;
memstreambuf _buf;
};
}
}

79
src/memstreambuf.cpp Normal file
View File

@ -0,0 +1,79 @@
#include "libscio.hpp"
#include <unistd.h>
#include <cstring>
sc::io::memstreambuf::memstreambuf(char* mem, size_t size) {
init(mem, size);
}
void sc::io::memstreambuf::init(char* mem, size_t size) {
_mem = mem;
_size = size;
setg(_mem, _mem, _mem + _size);
}
std::streambuf::int_type sc::io::memstreambuf::uflow() {
if (gptr() == _mem + _size) return EOF;
char c = *gptr();
setg(_mem, gptr() + 1, _mem + _size);
return c;
}
std::streamsize sc::io::memstreambuf::xsgetn(char* s, std::streamsize n) {
std::streamsize left = _mem + _size - gptr();
std::streamsize tot_read = std::min(left, n);
if (tot_read == 0) return EOF;
std::memcpy(s, gptr(), tot_read);
return tot_read;
}
std::streambuf::int_type sc::io::memstreambuf::overflow(std::streambuf::int_type c) {
// TODO
// if (c != EOF) {
// int res;
// if ((res = write(_fd, &c, 1)) != 1) {
// return EOF;
// }
// else {
// std::cerr << "write result = " << res << ", errno = " << errno << '\n';
// }
// }
// _ch = c;
// setp(&_ch, &_ch + 1);
return c;
}
std::streamsize sc::io::memstreambuf::xsputn(const char* s, std::streamsize num) {
// TODO
// int res = write(_fd, s, num);
// if (res != num) {
// std::cerr << "write result = " << res << ", errno = " << errno << '\n';
// return EOF;
// }
// return res;
return num;
}
std::streambuf::pos_type sc::io::memstreambuf::seekoff(std::streambuf::off_type off,
std::ios_base::seekdir dir,
std::ios_base::openmode /*which*/) {
switch (dir) {
case std::ios_base::beg: setg(_mem, _mem + off, _mem + _size); break;
case std::ios_base::end: setg(_mem, _mem + _size - off, _mem + _size); break;
case std::ios_base::cur: setg(_mem, gptr() + off, _mem + _size); break;
default: throw std::runtime_error("invalid seekdir");
}
return gptr() - _mem;
}
std::streambuf::pos_type sc::io::memstreambuf::seekpos(std::streambuf::pos_type pos,
std::ios_base::openmode /*which*/) {
setg(_mem, _mem + pos, _mem + _size);
return gptr() - _mem;
}
std::streambuf::int_type sc::io::memstreambuf::pbackfail(std::streambuf::int_type /*c*/) {
setg(_mem, gptr() - 1, _mem + _size);
if (gptr() < _mem) return EOF;
return 0;
}