Added memstreambuf and imemfile
This commit is contained in:
parent
9dbb05d26c
commit
4550b1fc05
14
src/imemfile.cpp
Normal file
14
src/imemfile.cpp
Normal 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());
|
||||
}
|
@ -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
79
src/memstreambuf.cpp
Normal 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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user