96 lines
2.2 KiB
C++
96 lines
2.2 KiB
C++
//
|
|
// fdiobuf.cpp
|
|
// libscio
|
|
//
|
|
// Created by Bob Polis at 2020-02-14
|
|
// Copyright (c) 2020 SwiftCoder. All rights reserved.
|
|
//
|
|
|
|
#include "fdiobuf.hpp"
|
|
#include <iostream>
|
|
|
|
#ifdef _MSC_VER
|
|
#include <io.h>
|
|
#else
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
std::streambuf::int_type sc::io::fdiobuf::underflow() {
|
|
int num = ::read(_fd, &_ch, 1);
|
|
if (num <= 0) {
|
|
return EOF;
|
|
}
|
|
setg(&_ch, &_ch, &_ch + 1);
|
|
return _ch;
|
|
}
|
|
|
|
std::streamsize sc::io::fdiobuf::xsgetn(char* s, std::streamsize n) {
|
|
std::streamsize tot_read = 0;
|
|
std::streamsize next_amount = n;
|
|
while (next_amount) {
|
|
ssize_t num_read = ::read(_fd, s, next_amount);
|
|
if (num_read == -1) {
|
|
if (errno == EINTR) { // interrupted => restart
|
|
continue;
|
|
} else {
|
|
return -1; // real error
|
|
}
|
|
} else if (num_read == 0) { // EOF
|
|
break;
|
|
} else {
|
|
tot_read += num_read;
|
|
next_amount -= num_read;
|
|
}
|
|
}
|
|
return tot_read;
|
|
}
|
|
|
|
std::streambuf::int_type sc::io::fdiobuf::overflow(std::streambuf::int_type c) {
|
|
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::fdiobuf::xsputn(const char* s, std::streamsize num) {
|
|
int res = ::write(_fd, s, num);
|
|
if (res != num) {
|
|
std::cerr << "write result = " << res << ", errno = " << errno << '\n';
|
|
return EOF;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
std::streambuf::pos_type sc::io::fdiobuf::seekoff(std::streambuf::off_type off,
|
|
std::ios_base::seekdir dir,
|
|
std::ios_base::openmode /*which*/) {
|
|
int whence;
|
|
switch (dir) {
|
|
case std::ios_base::beg: whence = SEEK_SET; break;
|
|
case std::ios_base::end: whence = SEEK_END; break;
|
|
case std::ios_base::cur: whence = SEEK_CUR; break;
|
|
default: throw std::runtime_error("invalid seekdir");
|
|
}
|
|
return ::lseek(_fd, off, whence);
|
|
}
|
|
|
|
std::streambuf::pos_type sc::io::fdiobuf::seekpos(std::streambuf::pos_type pos,
|
|
std::ios_base::openmode /*which*/) {
|
|
return ::lseek(_fd, pos, SEEK_SET);
|
|
}
|
|
|
|
std::streambuf::int_type sc::io::fdiobuf::pbackfail(std::streambuf::int_type /*c*/) {
|
|
if (::lseek(_fd, -1, SEEK_CUR) == -1) {
|
|
return EOF;
|
|
}
|
|
return 0;
|
|
}
|