Clean up InputHandler_SextetStream (#1985)

Before, this ended up calling a virtual method in the constructor,
which C++ does not allow, and I got weird crashes.

This removes a lot of unused code and gets rid of unnecessary abstractions.
This commit is contained in:
aeubanks
2020-04-30 13:24:23 -07:00
committed by GitHub
parent f79dc3dbda
commit e16017bd1a
2 changed files with 59 additions and 159 deletions
@@ -33,22 +33,44 @@ namespace
{
class LineReader
{
protected:
private:
// The buffer size isn't critical; the RString will simply be
// extended until the line is done.
static const size_t BUFFER_SIZE = 64;
char buffer[BUFFER_SIZE];
std::FILE * file;
int timeout_ms;
public:
LineReader()
LineReader(const RString& filename)
{
timeout_ms = DEFAULT_TIMEOUT_MS;
LOG->Info("Starting InputHandler_SextetStreamFromFile from std::FILE with filename '%s'",
filename.c_str());
file = std::fopen(filename.c_str(), "rb");
if(file == nullptr) {
LOG->Warn("Error opening file '%s' for input (cstdio): %s", filename.c_str(),
std::strerror(errno));
}
else {
LOG->Info("File opened");
// Disable buffering on the file
std::setbuf(file, nullptr);
}
}
virtual ~LineReader()
~LineReader()
{
if(file != nullptr) {
std::fclose(file);
}
}
virtual bool IsValid()
bool IsValid()
{
return false;
return file != nullptr;
}
// Ideally, this method should return if timeout_ms passes
@@ -74,7 +96,26 @@ namespace
// false (line undefined) if there is an error or EOF condition,
// true (line = next line from stream) if a whole line is available,
// true (line = "") if no error but still waiting for next line.
virtual bool ReadLine(RString& line) = 0;
bool ReadLine(RString& line)
{
bool afterFirst = false;
size_t len;
line = "";
if(file != nullptr) {
while(fgets(buffer, BUFFER_SIZE, file) != nullptr) {
afterFirst = true;
line += buffer;
len = line.length();
if(len > 0 && line[len - 1] == 0xA) {
break;
}
}
}
return afterFirst;
}
};
}
@@ -82,6 +123,7 @@ class InputHandler_SextetStream::Impl
{
private:
InputHandler_SextetStream * handler;
RString filename;
protected:
void ButtonPressed(const DeviceInput& di)
@@ -94,12 +136,6 @@ class InputHandler_SextetStream::Impl
RageThread inputThread;
bool continueInputThread;
// Construct and return the LineReader that makes sense for this
// object. getLineReader() calls this; if the returned object claims
// it is valid, it is returned. Otherwise, it is destroyed and nullptr
// is returned.
virtual LineReader * getUnvalidatedLineReader() = 0;
inline void clearStateBuffer()
{
memset(stateBuffer, 0, STATE_BUFFER_SIZE);
@@ -114,30 +150,29 @@ class InputHandler_SextetStream::Impl
LineReader * getLineReader()
{
LineReader * linereader = getUnvalidatedLineReader();
if(linereader != nullptr) {
if(!linereader->IsValid()) {
delete linereader;
linereader = nullptr;
}
LineReader * linereader = new LineReader(filename);
if(!linereader->IsValid()) {
delete linereader;
linereader = nullptr;
}
return linereader;
}
public:
Impl(InputHandler_SextetStream * _this)
Impl(InputHandler_SextetStream * _this, const RString& filename)
{
LOG->Info("Number of button states supported by current InputHandler_SextetStream: %u",
(unsigned)BUTTON_COUNT);
continueInputThread = false;
timeout_ms = DEFAULT_TIMEOUT_MS;
this->filename = filename;
handler = _this;
clearStateBuffer();
createThread();
}
virtual ~Impl()
~Impl()
{
if(inputThread.IsCreated()) {
continueInputThread = false;
@@ -145,7 +180,7 @@ class InputHandler_SextetStream::Impl
}
}
virtual void GetDevicesAndDescriptions(vector<InputDeviceInfo>& vDevicesOut)
void GetDevicesAndDescriptions(vector<InputDeviceInfo>& vDevicesOut)
{
vDevicesOut.push_back(InputDeviceInfo(FIRST_DEVICE, "SextetStream"));
}
@@ -287,137 +322,9 @@ REGISTER_INPUT_HANDLER_CLASS (SextetStreamFromFile);
#endif
static Preference<RString> g_sSextetStreamInputFilename("SextetStreamInputFilename", DEFAULT_INPUT_FILENAME);
namespace
{
class StdCFileLineReader: public LineReader
{
private:
// The buffer size isn't critical; the RString will simply be
// extended until the line is done.
static const size_t BUFFER_SIZE = 64;
char buffer[BUFFER_SIZE];
protected:
std::FILE * file;
public:
StdCFileLineReader(std::FILE * file)
{
LOG->Info("Starting InputHandler_SextetStreamFromFile from open std::FILE");
this->file = file;
}
StdCFileLineReader(const RString& filename)
{
LOG->Info("Starting InputHandler_SextetStreamFromFile from std::FILE with filename '%s'",
filename.c_str());
file = std::fopen(filename.c_str(), "rb");
if(file == nullptr) {
LOG->Warn("Error opening file '%s' for input (cstdio): %s", filename.c_str(),
std::strerror(errno));
}
else {
LOG->Info("File opened");
// Disable buffering on the file
std::setbuf(file, nullptr);
}
}
~StdCFileLineReader()
{
if(file != nullptr) {
std::fclose(file);
}
}
virtual bool IsValid()
{
return file != nullptr;
}
virtual bool ReadLine(RString& line)
{
bool afterFirst = false;
size_t len;
line = "";
if(file != nullptr) {
while(fgets(buffer, BUFFER_SIZE, file) != nullptr) {
afterFirst = true;
line += buffer;
len = line.length();
if(len > 0 && line[len - 1] == 0xA) {
break;
}
}
}
return afterFirst;
}
};
class StdCFileHandleImpl: public InputHandler_SextetStream::Impl
{
protected:
std::FILE * file;
public:
StdCFileHandleImpl(InputHandler_SextetStreamFromFile * handler, std::FILE * file) :
InputHandler_SextetStream::Impl(handler)
{
this->file = file;
}
virtual LineReader * getUnvalidatedLineReader()
{
return new StdCFileLineReader(this->file);
}
virtual ~StdCFileHandleImpl()
{
// line reader dtor will close file for us
}
};
class StdCFileNameImpl: public InputHandler_SextetStream::Impl
{
protected:
RString filename;
public:
StdCFileNameImpl(InputHandler_SextetStreamFromFile * handler, const RString& filename) :
InputHandler_SextetStream::Impl(handler)
{
this->filename = filename;
}
virtual LineReader * getUnvalidatedLineReader()
{
return new StdCFileLineReader(filename);
}
virtual ~StdCFileNameImpl()
{
// Nothing to destroy
}
};
}
InputHandler_SextetStreamFromFile::InputHandler_SextetStreamFromFile(FILE * file)
{
_impl = new StdCFileHandleImpl(this, file);
}
InputHandler_SextetStreamFromFile::InputHandler_SextetStreamFromFile(const RString& filename)
{
_impl = new StdCFileNameImpl(this, filename);
}
InputHandler_SextetStreamFromFile::InputHandler_SextetStreamFromFile()
{
_impl = new StdCFileNameImpl(this, g_sSextetStreamInputFilename);
_impl = new Impl(this, g_sSextetStreamInputFilename);
}
/*
@@ -8,9 +8,8 @@ class InputHandler_SextetStream: public InputHandler
{
public:
InputHandler_SextetStream();
virtual ~InputHandler_SextetStream();
//virtual void Update();
virtual void GetDevicesAndDescriptions(vector<InputDeviceInfo>& vDevicesOut);
~InputHandler_SextetStream();
void GetDevicesAndDescriptions(vector<InputDeviceInfo>& vDevicesOut);
public:
class Impl;
@@ -36,12 +35,6 @@ public:
// couldn't get RageFile to work here, possibly because I haven't
// determined how to disable buffering on an input file.)
InputHandler_SextetStreamFromFile();
InputHandler_SextetStreamFromFile(const RString& filename);
// The file object passed here must already be open and buffering should
// be disabled. The file object will be closed in the destructor.
InputHandler_SextetStreamFromFile(std::FILE * file);
};
#endif