2018-07-19 16:04:20 -04:00
|
|
|
/***********************************************************************************************************************************
|
2018-08-14 14:21:53 -04:00
|
|
|
IO Write Interface
|
2018-07-19 16:04:20 -04:00
|
|
|
***********************************************************************************************************************************/
|
2019-04-26 08:08:23 -04:00
|
|
|
#include "build.auto.h"
|
|
|
|
|
2018-10-07 17:50:10 +01:00
|
|
|
#include <string.h>
|
|
|
|
|
2018-07-19 16:04:20 -04:00
|
|
|
#include "common/debug.h"
|
2018-08-14 14:21:53 -04:00
|
|
|
#include "common/io/io.h"
|
2018-09-15 21:07:00 -04:00
|
|
|
#include "common/io/write.intern.h"
|
2018-07-19 16:04:20 -04:00
|
|
|
#include "common/log.h"
|
|
|
|
#include "common/memContext.h"
|
|
|
|
|
|
|
|
/***********************************************************************************************************************************
|
2018-08-14 14:21:53 -04:00
|
|
|
Object type
|
2018-07-19 16:04:20 -04:00
|
|
|
***********************************************************************************************************************************/
|
|
|
|
struct IoWrite
|
|
|
|
{
|
2019-05-03 15:46:15 -04:00
|
|
|
MemContext *memContext; // Mem context
|
2018-07-19 16:04:20 -04:00
|
|
|
void *driver; // Driver object
|
2018-09-15 21:07:00 -04:00
|
|
|
IoWriteInterface interface; // Driver interface
|
2018-07-24 21:08:27 -04:00
|
|
|
IoFilterGroup *filterGroup; // IO filters
|
2018-08-14 14:21:53 -04:00
|
|
|
Buffer *output; // Output buffer
|
2018-07-24 21:08:27 -04:00
|
|
|
|
2018-08-14 14:21:53 -04:00
|
|
|
#ifdef DEBUG
|
2019-06-24 10:20:47 -04:00
|
|
|
bool filterGroupSet; // Were filters set?
|
2018-08-14 14:21:53 -04:00
|
|
|
bool opened; // Has the io been opened?
|
|
|
|
bool closed; // Has the io been closed?
|
|
|
|
#endif
|
2018-07-19 16:04:20 -04:00
|
|
|
};
|
|
|
|
|
2020-04-03 18:01:28 -04:00
|
|
|
/**********************************************************************************************************************************/
|
2018-07-19 16:04:20 -04:00
|
|
|
IoWrite *
|
2018-09-15 21:07:00 -04:00
|
|
|
ioWriteNew(void *driver, IoWriteInterface interface)
|
2018-07-19 16:04:20 -04:00
|
|
|
{
|
2019-01-21 17:41:59 +02:00
|
|
|
FUNCTION_LOG_BEGIN(logLevelTrace);
|
2019-01-28 22:33:29 +02:00
|
|
|
FUNCTION_LOG_PARAM_P(VOID, driver);
|
2019-01-21 17:41:59 +02:00
|
|
|
FUNCTION_LOG_PARAM(IO_WRITE_INTERFACE, interface);
|
|
|
|
FUNCTION_LOG_END();
|
2018-07-19 16:04:20 -04:00
|
|
|
|
2019-01-21 17:41:59 +02:00
|
|
|
ASSERT(driver != NULL);
|
|
|
|
ASSERT(interface.write != NULL);
|
2018-07-19 16:04:20 -04:00
|
|
|
|
2018-11-15 16:25:46 -05:00
|
|
|
IoWrite *this = NULL;
|
|
|
|
|
|
|
|
MEM_CONTEXT_NEW_BEGIN("IoWrite")
|
|
|
|
{
|
|
|
|
this = memNew(sizeof(IoWrite));
|
2020-01-23 14:15:58 -07:00
|
|
|
|
|
|
|
*this = (IoWrite)
|
|
|
|
{
|
|
|
|
.memContext = memContextCurrent(),
|
|
|
|
.driver = driver,
|
|
|
|
.interface = interface,
|
|
|
|
.filterGroup = ioFilterGroupNew(),
|
|
|
|
.output = bufNew(ioBufferSize()),
|
|
|
|
};
|
2018-11-15 16:25:46 -05:00
|
|
|
}
|
|
|
|
MEM_CONTEXT_NEW_END();
|
2018-07-19 16:04:20 -04:00
|
|
|
|
2019-01-21 17:41:59 +02:00
|
|
|
FUNCTION_LOG_RETURN(IO_WRITE, this);
|
2018-07-19 16:04:20 -04:00
|
|
|
}
|
|
|
|
|
2020-04-03 18:01:28 -04:00
|
|
|
/**********************************************************************************************************************************/
|
2018-07-19 16:04:20 -04:00
|
|
|
void
|
|
|
|
ioWriteOpen(IoWrite *this)
|
|
|
|
{
|
2019-01-21 17:41:59 +02:00
|
|
|
FUNCTION_LOG_BEGIN(logLevelTrace);
|
|
|
|
FUNCTION_LOG_PARAM(IO_WRITE, this);
|
|
|
|
FUNCTION_LOG_END();
|
2018-07-19 16:04:20 -04:00
|
|
|
|
2019-01-21 17:41:59 +02:00
|
|
|
ASSERT(this != NULL);
|
|
|
|
ASSERT(!this->opened && !this->closed);
|
2018-07-19 16:04:20 -04:00
|
|
|
|
2018-09-15 21:07:00 -04:00
|
|
|
if (this->interface.open != NULL)
|
|
|
|
this->interface.open(this->driver);
|
2018-07-19 16:04:20 -04:00
|
|
|
|
2019-06-24 10:20:47 -04:00
|
|
|
// Track whether filters were added to prevent flush() from being called later since flush() won't work with most filters
|
|
|
|
#ifdef DEBUG
|
|
|
|
this->filterGroupSet = ioFilterGroupSize(this->filterGroup) > 0;
|
|
|
|
#endif
|
2018-08-14 14:21:53 -04:00
|
|
|
|
2019-06-24 10:20:47 -04:00
|
|
|
// Open the filter group
|
2018-08-14 14:21:53 -04:00
|
|
|
ioFilterGroupOpen(this->filterGroup);
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
this->opened = true;
|
|
|
|
#endif
|
|
|
|
|
2019-01-21 17:41:59 +02:00
|
|
|
FUNCTION_LOG_RETURN_VOID();
|
2018-07-19 16:04:20 -04:00
|
|
|
}
|
|
|
|
|
2020-04-03 18:01:28 -04:00
|
|
|
/**********************************************************************************************************************************/
|
2018-07-19 16:04:20 -04:00
|
|
|
void
|
|
|
|
ioWrite(IoWrite *this, const Buffer *buffer)
|
|
|
|
{
|
2019-01-21 17:41:59 +02:00
|
|
|
FUNCTION_LOG_BEGIN(logLevelTrace);
|
|
|
|
FUNCTION_LOG_PARAM(IO_WRITE, this);
|
|
|
|
FUNCTION_LOG_PARAM(BUFFER, buffer);
|
|
|
|
FUNCTION_LOG_END();
|
2018-07-19 16:04:20 -04:00
|
|
|
|
2019-01-21 17:41:59 +02:00
|
|
|
ASSERT(this != NULL);
|
|
|
|
ASSERT(this->opened && !this->closed);
|
2018-07-19 16:04:20 -04:00
|
|
|
|
|
|
|
// Only write if there is data to write
|
2021-02-01 09:22:01 -05:00
|
|
|
if (buffer != NULL && !bufEmpty(buffer))
|
2018-07-19 16:04:20 -04:00
|
|
|
{
|
2018-08-14 14:21:53 -04:00
|
|
|
do
|
|
|
|
{
|
|
|
|
ioFilterGroupProcess(this->filterGroup, buffer, this->output);
|
|
|
|
|
|
|
|
// Write data if the buffer is full
|
|
|
|
if (bufRemains(this->output) == 0)
|
|
|
|
{
|
2018-09-15 21:07:00 -04:00
|
|
|
this->interface.write(this->driver, this->output);
|
2018-08-14 14:21:53 -04:00
|
|
|
bufUsedZero(this->output);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (ioFilterGroupInputSame(this->filterGroup));
|
2018-07-19 16:04:20 -04:00
|
|
|
}
|
|
|
|
|
2019-01-21 17:41:59 +02:00
|
|
|
FUNCTION_LOG_RETURN_VOID();
|
2018-07-19 16:04:20 -04:00
|
|
|
}
|
|
|
|
|
2020-04-03 18:01:28 -04:00
|
|
|
/**********************************************************************************************************************************/
|
2018-10-07 17:50:10 +01:00
|
|
|
void
|
2019-04-22 18:46:29 -04:00
|
|
|
ioWriteLine(IoWrite *this, const Buffer *buffer)
|
|
|
|
{
|
|
|
|
FUNCTION_LOG_BEGIN(logLevelTrace);
|
|
|
|
FUNCTION_LOG_PARAM(IO_WRITE, this);
|
|
|
|
FUNCTION_LOG_PARAM(BUFFER, buffer);
|
|
|
|
FUNCTION_LOG_END();
|
|
|
|
|
|
|
|
ASSERT(this != NULL);
|
|
|
|
ASSERT(buffer != NULL);
|
|
|
|
|
|
|
|
ioWrite(this, buffer);
|
|
|
|
ioWrite(this, LF_BUF);
|
|
|
|
|
|
|
|
FUNCTION_LOG_RETURN_VOID();
|
|
|
|
}
|
|
|
|
|
2020-08-08 11:23:37 -04:00
|
|
|
/**********************************************************************************************************************************/
|
|
|
|
bool
|
|
|
|
ioWriteReady(IoWrite *this, IoWriteReadyParam param)
|
|
|
|
{
|
|
|
|
FUNCTION_LOG_BEGIN(logLevelTrace);
|
|
|
|
FUNCTION_LOG_PARAM(IO_WRITE, this);
|
|
|
|
FUNCTION_LOG_PARAM(BOOL, param.error);
|
|
|
|
FUNCTION_LOG_END();
|
|
|
|
|
|
|
|
ASSERT(this != NULL);
|
|
|
|
|
|
|
|
bool result = true;
|
|
|
|
|
|
|
|
if (this->interface.ready != NULL)
|
|
|
|
result = this->interface.ready(this->driver, param.error);
|
|
|
|
|
|
|
|
FUNCTION_LOG_RETURN(BOOL, result);
|
|
|
|
}
|
|
|
|
|
2020-04-03 18:01:28 -04:00
|
|
|
/**********************************************************************************************************************************/
|
2019-04-22 18:46:29 -04:00
|
|
|
void
|
|
|
|
ioWriteStr(IoWrite *this, const String *string)
|
|
|
|
{
|
|
|
|
FUNCTION_LOG_BEGIN(logLevelTrace);
|
|
|
|
FUNCTION_LOG_PARAM(IO_WRITE, this);
|
|
|
|
FUNCTION_LOG_PARAM(STRING, string);
|
|
|
|
FUNCTION_LOG_END();
|
|
|
|
|
|
|
|
ASSERT(this != NULL);
|
|
|
|
ASSERT(string != NULL);
|
|
|
|
|
|
|
|
ioWrite(this, BUFSTR(string));
|
|
|
|
|
|
|
|
FUNCTION_LOG_RETURN_VOID();
|
|
|
|
}
|
|
|
|
|
2020-04-03 18:01:28 -04:00
|
|
|
/**********************************************************************************************************************************/
|
2019-04-22 18:46:29 -04:00
|
|
|
void
|
|
|
|
ioWriteStrLine(IoWrite *this, const String *string)
|
2018-10-07 17:50:10 +01:00
|
|
|
{
|
2019-01-21 17:41:59 +02:00
|
|
|
FUNCTION_LOG_BEGIN(logLevelTrace);
|
|
|
|
FUNCTION_LOG_PARAM(IO_WRITE, this);
|
|
|
|
FUNCTION_LOG_PARAM(STRING, string);
|
|
|
|
FUNCTION_LOG_END();
|
2018-10-07 17:50:10 +01:00
|
|
|
|
2019-01-21 17:41:59 +02:00
|
|
|
ASSERT(this != NULL);
|
|
|
|
ASSERT(string != NULL);
|
2018-10-07 17:50:10 +01:00
|
|
|
|
2019-04-20 08:16:17 -04:00
|
|
|
ioWrite(this, BUFSTR(string));
|
|
|
|
ioWrite(this, LF_BUF);
|
2018-10-07 17:50:10 +01:00
|
|
|
|
2019-01-21 17:41:59 +02:00
|
|
|
FUNCTION_LOG_RETURN_VOID();
|
2018-10-07 17:50:10 +01:00
|
|
|
}
|
|
|
|
|
2020-04-03 18:01:28 -04:00
|
|
|
/**********************************************************************************************************************************/
|
2018-11-14 08:53:42 -05:00
|
|
|
void
|
|
|
|
ioWriteFlush(IoWrite *this)
|
|
|
|
{
|
2019-01-21 17:41:59 +02:00
|
|
|
FUNCTION_LOG_BEGIN(logLevelTrace);
|
|
|
|
FUNCTION_LOG_PARAM(IO_WRITE, this);
|
|
|
|
FUNCTION_LOG_END();
|
2018-11-14 08:53:42 -05:00
|
|
|
|
2019-01-21 17:41:59 +02:00
|
|
|
ASSERT(this != NULL);
|
|
|
|
ASSERT(this->opened && !this->closed);
|
2019-04-20 11:25:04 -04:00
|
|
|
ASSERT(!this->filterGroupSet);
|
2018-11-14 08:53:42 -05:00
|
|
|
|
2021-02-01 09:22:01 -05:00
|
|
|
if (!bufEmpty(this->output))
|
2018-11-14 08:53:42 -05:00
|
|
|
{
|
|
|
|
this->interface.write(this->driver, this->output);
|
|
|
|
bufUsedZero(this->output);
|
|
|
|
}
|
|
|
|
|
2019-01-21 17:41:59 +02:00
|
|
|
FUNCTION_LOG_RETURN_VOID();
|
2018-11-14 08:53:42 -05:00
|
|
|
}
|
|
|
|
|
2020-04-03 18:01:28 -04:00
|
|
|
/**********************************************************************************************************************************/
|
2018-07-19 16:04:20 -04:00
|
|
|
void
|
|
|
|
ioWriteClose(IoWrite *this)
|
|
|
|
{
|
2019-01-21 17:41:59 +02:00
|
|
|
FUNCTION_LOG_BEGIN(logLevelTrace);
|
|
|
|
FUNCTION_LOG_PARAM(IO_WRITE, this);
|
|
|
|
FUNCTION_LOG_END();
|
2018-07-19 16:04:20 -04:00
|
|
|
|
2019-01-21 17:41:59 +02:00
|
|
|
ASSERT(this != NULL);
|
|
|
|
ASSERT(this->opened && !this->closed);
|
2018-07-19 16:04:20 -04:00
|
|
|
|
2018-08-14 14:21:53 -04:00
|
|
|
// Flush remaining data
|
|
|
|
do
|
|
|
|
{
|
|
|
|
ioFilterGroupProcess(this->filterGroup, NULL, this->output);
|
|
|
|
|
|
|
|
// Write data if the buffer is full or if this is the last buffer to be written
|
2021-02-01 09:22:01 -05:00
|
|
|
if (bufRemains(this->output) == 0 || (ioFilterGroupDone(this->filterGroup) && !bufEmpty(this->output)))
|
2018-08-14 14:21:53 -04:00
|
|
|
{
|
2018-09-15 21:07:00 -04:00
|
|
|
this->interface.write(this->driver, this->output);
|
2018-08-14 14:21:53 -04:00
|
|
|
bufUsedZero(this->output);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (!ioFilterGroupDone(this->filterGroup));
|
|
|
|
|
2018-07-24 21:08:27 -04:00
|
|
|
// Close the filter group and gather results
|
2018-08-14 14:21:53 -04:00
|
|
|
ioFilterGroupClose(this->filterGroup);
|
2018-07-24 21:08:27 -04:00
|
|
|
|
|
|
|
// Close the driver if there is a close function
|
2018-09-15 21:07:00 -04:00
|
|
|
if (this->interface.close != NULL)
|
|
|
|
this->interface.close(this->driver);
|
2018-07-19 16:04:20 -04:00
|
|
|
|
2018-08-14 14:21:53 -04:00
|
|
|
#ifdef DEBUG
|
|
|
|
this->closed = true;
|
|
|
|
#endif
|
|
|
|
|
2019-01-21 17:41:59 +02:00
|
|
|
FUNCTION_LOG_RETURN_VOID();
|
2018-07-19 16:04:20 -04:00
|
|
|
}
|
|
|
|
|
2020-04-03 18:01:28 -04:00
|
|
|
/**********************************************************************************************************************************/
|
2019-06-04 12:56:04 -04:00
|
|
|
IoFilterGroup *
|
2018-07-24 21:08:27 -04:00
|
|
|
ioWriteFilterGroup(const IoWrite *this)
|
|
|
|
{
|
|
|
|
FUNCTION_TEST_BEGIN();
|
|
|
|
FUNCTION_TEST_PARAM(IO_WRITE, this);
|
|
|
|
FUNCTION_TEST_END();
|
|
|
|
|
2019-01-21 17:41:59 +02:00
|
|
|
ASSERT(this != NULL);
|
|
|
|
|
2019-01-28 15:06:28 +02:00
|
|
|
FUNCTION_TEST_RETURN(this->filterGroup);
|
2018-07-24 21:08:27 -04:00
|
|
|
}
|
|
|
|
|
2020-04-03 18:01:28 -04:00
|
|
|
/**********************************************************************************************************************************/
|
2019-04-29 14:54:49 -04:00
|
|
|
int
|
2020-08-05 18:25:07 -04:00
|
|
|
ioWriteFd(const IoWrite *this)
|
2019-04-29 14:54:49 -04:00
|
|
|
{
|
|
|
|
FUNCTION_LOG_BEGIN(logLevelTrace);
|
|
|
|
FUNCTION_LOG_PARAM(IO_WRITE, this);
|
|
|
|
FUNCTION_LOG_END();
|
|
|
|
|
|
|
|
ASSERT(this != NULL);
|
|
|
|
|
2020-08-05 18:25:07 -04:00
|
|
|
FUNCTION_LOG_RETURN(INT, this->interface.fd == NULL ? -1 : this->interface.fd(this->driver));
|
2019-04-29 14:54:49 -04:00
|
|
|
}
|