summaryrefslogtreecommitdiff
path: root/support/dktools/dk4strm.ctr
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/dktools/dk4strm.ctr
Initial commit
Diffstat (limited to 'support/dktools/dk4strm.ctr')
-rw-r--r--support/dktools/dk4strm.ctr978
1 files changed, 978 insertions, 0 deletions
diff --git a/support/dktools/dk4strm.ctr b/support/dktools/dk4strm.ctr
new file mode 100644
index 0000000000..f26d0f93cb
--- /dev/null
+++ b/support/dktools/dk4strm.ctr
@@ -0,0 +1,978 @@
+%% options
+
+copyright owner = Dirk Krause
+copyright year = 2015-xxxx
+license = bsd
+
+
+
+%% header
+
+/** @file
+ Generic dk4_stream_t interface for
+ input and output operations.
+
+ CRT on Windows: Optional.
+*/
+
+#ifndef DK4CONF_H_INCLUDED
+#include "dk4conf.h"
+#endif
+
+#ifndef DK4TYPES_H_INCLUDED
+#include "dk4types.h"
+#endif
+
+#ifndef DK4ERROR_H_INCLUDED
+#include "dk4error.h"
+#endif
+
+#ifndef STDLIB_H_INCLUDED
+#include <stdlib.h>
+#define STDLIB_H_INCLUDED 1
+#endif
+
+/** API for stream function.
+*/
+typedef struct {
+ void *d; /**< In: Low level data. */
+ char *b; /**< In: Buffer for data to write or read. */
+ size_t sz_in; /**< In: Number of bytes to write or read. */
+ size_t sz_out; /**< Out: Number of bytes written or read. */
+ int cmd; /**< In: Command to execute. */
+ int res; /**< Out: Low level operation result. */
+} dk4_stream_api_t;
+
+/** Function to execute one low level command.
+*/
+typedef void dk4_stream_api_fct_t(dk4_stream_api_t *);
+
+/** Generic I/O stream.
+*/
+typedef struct {
+ void *d; /**< Low level data object. */
+ dk4_stream_api_fct_t *fct; /**< Function for low level operations. */
+ char *bi; /**< Buffer for input. */
+ char *bo; /**< Buffer for output. */
+ dk4_um_t bwr; /**< Number of bytes written. */
+ size_t szbi; /**< Input buffer size. */
+ size_t szbo; /**< Output buffer size. */
+ size_t usbi; /**< Bytes used in input buffer. */
+ size_t usbo; /**< Bytes used in output buffer. */
+ size_t rebi; /**< Read bytes from input buffer. */
+ int fl; /**< Flags for allowed operations. */
+ int feoi; /**< Flag: Found end of input. */
+ int bwo; /**< Flag: Numeric overflow in bwr. */
+ int oenc; /**< Output encoding for 32 bit characters. */
+ int zreof; /**< Flag: Zero bytes read indicates EOF. */
+} dk4_stream_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Open new stream, allocate memory.
+ @param obj Low level object.
+ @param fct Low level function.
+ @param fl Read/write flags: DK4_STREAM_READ, DK4_STREAM_WRITE
+ or (DK4_STREAM_READ | DK4_STREAM_WRITE).
+ @param ibs Input buffer size (0 for default).
+ @param obs Output buffer size (0 for default).
+ @param erp Error report, may be NULL.
+ @return Pointer to new stream on success, NULL on error.
+
+ Error codes:
+ - DK4_E_INVALID_ARGUMENTS<br>
+ if obj or fct is NULL or fl is invalid,
+ - DK4_E_MATH_OVERFLOW<br>
+ if ibs or obs is too large,
+ - DK4_E_MEMORY_ALLOCATION_FAILED<br>
+ if allocation of input or output buffer failed.
+*/
+dk4_stream_t *
+dk4stream_open(
+ void *obj,
+ dk4_stream_api_fct_t *fct,
+ int fl,
+ size_t ibs,
+ size_t obs,
+ dk4_er_t *erp
+);
+
+/** Close data stream, release memory.
+ @param strm Stream to close.
+ @param erp Error report, may be NULL.
+ @return 1 on success, 0 on error.
+
+ Error codes:
+ - DK4_E_INVALID_ARGUMENTS<br>
+ if strm is NULL,
+ - DK4_E_WRITE_FAILED<br>
+ if writing one ore multiple bytes to the stream failed,
+ - DK4_E_FLUSH_FAILED<br>
+ if flushing data downwards failed,
+ - DK4_E_CLOSE_FAILED<br>
+ if closing downward data failed.
+*/
+int
+dk4stream_close(dk4_stream_t *strm, dk4_er_t *erp);
+
+/** Write one byte to output stream.
+ @param strm Output stream.
+ @param c Byte to write.
+ @param erp Error report, may be NULL.
+ @return 1 on success, 0 on error.
+
+ Error codes:
+ - DK4_E_INVALID_ARGUMENTS<br>
+ if strm is NULL or not opened for writing,
+ - DK4_E_WRITE_FAILED<br>
+ if writing one ore multiple bytes to the stream failed,
+ - DK4_E_FLUSH_FAILED<br>
+ if flusing data downwards failed.
+*/
+int
+dk4stream_write_byte(dk4_stream_t *strm, char c, dk4_er_t *erp);
+
+/** Write a buffer to output stream.
+ @param strm Output stream.
+ @param b Buffer start address.
+ @param sz Number of bytes to write.
+ @param erp Error report, may be NULL.
+ @return 1 on success (all bytes written), 0 on error.
+
+ Error codes:
+ - DK4_E_INVALID_ARGUMENTS<br>
+ if strm is NULL or not opened for writing,
+ - DK4_E_WRITE_FAILED<br>
+ if writing one ore multiple bytes to the stream failed,
+ - DK4_E_FLUSH_FAILED<br>
+ if flusing data downwards failed.
+*/
+int
+dk4stream_write(dk4_stream_t *strm, const void *b, size_t sz, dk4_er_t *erp);
+
+
+/** Write a char string to the stream.
+ @param strm Output stream.
+ @param str String to write.
+ @param erp Error report, may be NULL.
+ @return 1 on success (all bytes written), 0 on error.
+
+ Error codes:
+ - DK4_E_INVALID_ARGUMENTS<br>
+ if strm is NULL or not opened for writing,
+ - DK4_E_WRITE_FAILED<br>
+ if writing one ore multiple bytes to the stream failed,
+ - DK4_E_FLUSH_FAILED<br>
+ if flusing data downwards failed.
+*/
+int
+dk4stream_write_char_string(dk4_stream_t *strm, const char *str, dk4_er_t *erp);
+
+/** Flush stream input and output data.
+ @param strm Stream to flush.
+ @param flfl Flush type: 0=just flush output buffer
+ contents to low level object, 1=0+flush low level object,
+ 2=1+flush all low level objects recursively (for output filtering).
+ @param erp Error report, may be NULL.
+ @return 1 on success, 0 on error.
+
+ Error codes:
+ - DK4_E_INVALID_ARGUMENTS<br>
+ if strm is NULL.
+ - DK4_E_WRITE_FAILED<br>
+ if writing one ore multiple bytes to the stream failed
+ - DK4_E_FLUSH_FAILED<br>
+ if flusing data downwards failed.
+*/
+int
+dk4stream_flush(dk4_stream_t *strm, int flfl, dk4_er_t *erp);
+
+/** Flush stream output data.
+ @param strm Stream to flush.
+ @param flfl Flush type: 0=just flush output buffer
+ contents to low level object, 1=0+flush low level object,
+ 2=1+flush all low level objects recursively (for output filtering).
+ @param erp Error report, may be NULL.
+ @return 1 on success, 0 on error.
+
+ Error codes:
+ - DK4_E_INVALID_ARGUMENTS<br>
+ if strm is NULL or not opened for writing,
+ - DK4_E_WRITE_FAILED<br>
+ if writing one ore multiple bytes to the stream failed,
+ - DK4_E_FLUSH_FAILED<br>
+ if flushing data downwards failed.
+*/
+int
+dk4stream_flush_write(dk4_stream_t *strm, int flfl, dk4_er_t *erp);
+
+/** Flush stream input data (discard data in input buffer).
+ @param strm Stream to flush.
+ @param erp Error report, may be NULL.
+ @return 1 on success, 0 on error.
+
+ Error codes:
+ - DK4_E_INVALID_ARGUMENTS<br>
+ if strm is NULL or not opened for writing.
+*/
+int
+dk4stream_flush_read(dk4_stream_t *strm, dk4_er_t *erp);
+
+/** Read a single character.
+ @param dst Pointer to variable for result.
+ @param strm Stream to read from.
+ @param erp Error report, may be NULL.
+ @return 1 on success, 0 on error.
+
+ Error codes:
+ - DK4_E_INVALID_ARGUMENTS<br>
+ if strm is NULL or not opened for reading,
+*/
+int
+dk4stream_c8_read_byte(char *dst, dk4_stream_t *strm, dk4_er_t *erp);
+
+/** Read multiple bytes into buffer.
+ @param b Pointer to buffer start address.
+ @param szptr Pointer to size variable, in: available size,
+ out: number of bytes read.
+ @param strm Stream to read from.
+ @param erp Error report, may be NULL.
+ @return 1 on success (there were bytes read), 0 on error.
+
+ Error codes:
+ - DK4_E_INVALID_ARGUMENTS<br>
+ if strm is NULL or not opened for reading,
+ - DK4_E_NOT_FOUND<br>
+ if end of input was detected in read attempt,
+ - DK4_E_READ_FAILED<br>
+ if a read attempt failed for other reasons.
+*/
+int
+dk4stream_read(void *b, size_t *szptr, dk4_stream_t *strm, dk4_er_t *erp);
+
+/** Get number of bytes written.
+ @param strm Stream to get number of bytes for.
+ @return Number of bytes written to the stream (number of bytes
+ received from the upside, not number of bytes written
+ downwards).
+*/
+dk4_um_t
+dk4stream_bytes_written(const dk4_stream_t *strm);
+
+/** Check for numeric overflow in number of bytes written.
+ @param strm Stream to check.
+ @return 1 if overflow occured, 0 if there was no overflow.
+*/
+int
+dk4stream_overflow_bytes_written(const dk4_stream_t *strm);
+
+/** Check whether end of input was found during read attempt.
+ @param strm Stream to check.
+ @return 1 if EOF was detected, 0 otherwise.
+*/
+int
+dk4stream_found_eof(const dk4_stream_t *strm);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+/** Flags whether read or write operations allowed.
+*/
+enum {
+ DK4_STREAM_READ = 1, /**< Reading from stream allowed. */
+ DK4_STREAM_WRITE = 2 /**< Writing to stream allowed. */
+};
+
+
+
+/** Low level commands to execute in the stream API function.
+ The api.cmd is set to one of the values.
+ Depending on api.cmd, other api attributes must be set
+ on input or must be set as response by the low level function.
+*/
+enum {
+ /** Read data.
+ Input api.d: Low level data.
+ Input api.b: Input data buffer.
+ Input api.sz_in: Input data buffer
+ size.
+ Output api.res: 1=any bytes found,
+ 0=no bytes found.
+ Output api.sz_out: Number of bytes
+ read into input
+ buffer.
+ */
+ DK4_STREAM_API_READ = 1,
+
+ /** Write data.
+ Input api.d: Low level data.
+ Input api.b: Output data buffer.
+ Input api.sz_in: Output data buffer
+ size.
+ Output api.res: 1=all bytes
+ written,
+ 0=not all bytes
+ written.
+ Output api.sz_out: Number of bytes
+ written.
+ */
+ DK4_STREAM_API_WRITE ,
+
+ /** Flush data.
+ Input api.d: Low level data.
+ Output api.res: 1=no error reported,
+ 0=error reported.
+ */
+ DK4_STREAM_API_FLUSH ,
+
+ /** Check whether end of input is found.
+ Input api.d: Low level data.
+ Output api.res 1=end of input
+ reached,
+ 0=not yet reached.
+ */
+ DK4_STREAM_API_AT_END ,
+
+ /** Close low level data.
+ Input api.d: Low level data.
+ Output api.res: 1=no error reported,
+ 0=error reported.
+ */
+ DK4_STREAM_API_CLOSE ,
+
+ /** Check whether a read result of 0
+ indicates EOF.
+ Input api.d: Low level data.
+ Output api.res 1=reading zero bytes
+ indicates EOF, 0=no.
+ */
+ DK4_STREAM_API_ZERO_READ_IS_EOF
+};
+
+%% module
+
+
+
+#include "dk4strm.h"
+#include "dk4mem.h"
+#include "dk4enc.h"
+#include "dk4numco.h"
+
+
+
+$!trace-include
+
+
+
+
+static
+void
+dk4stream_api_init(dk4_stream_api_t *ptr)
+{
+ $? "+ dk4stream_api_init"
+ DK4_MEMRES(ptr, sizeof(dk4_stream_api_t));
+ ptr->d = NULL;
+ ptr->b = NULL;
+ ptr->sz_in = 0;
+ ptr->sz_out = 0;
+ ptr->res = 0;
+ ptr->cmd = 0;
+ $? "- dk4stream_api_init"
+}
+
+
+
+/** Release memory allocated by a stream.
+ @param strm Stream to release.
+*/
+static
+void
+dk4stream_release_memory(dk4_stream_t *strm)
+{
+ $? "+ dk4stream_release_memory PTR=%d", TR_IPTR(strm)
+ if (NULL != strm) {
+ dk4mem_release(strm->bi);
+ dk4mem_release(strm->bo);
+ strm->d = NULL;
+ strm->fct = NULL;
+ strm->bwr = (dk4_um_t)0UL;
+ strm->szbi = 0;
+ strm->szbo = 0;
+ strm->usbi = 0;
+ strm->usbo = 0;
+ strm->rebi = 0;
+ strm->fl = 0;
+ strm->feoi = 0;
+ strm->bwo = 0;
+ dk4mem_free(strm);
+ } $? "- dk4stream_release_memory"
+}
+
+
+
+
+/** Flush write buffer.
+*/
+static
+int
+dk4stream_i_flush_write(dk4_stream_t *strm, int flfl, dk4_er_t *erp)
+{
+ dk4_stream_api_t api;
+ int back = 1;
+ $? "+ dk4stream_i_flush_write"
+ /* Write buffer contents (if any) downwards.
+ */
+ if (0 != strm->usbo) { $? ". bytes in output buffer"
+ dk4stream_api_init(&api);
+ api.cmd = DK4_STREAM_API_WRITE;
+ api.d = strm->d;
+ api.b = strm->bo;
+ api.sz_in = strm->usbo;
+ (*(strm->fct))(&api);
+ if (0 == api.res) {
+ back = 0;
+ dk4error_set_simple_error_code(erp, DK4_E_WRITE_FAILED);
+ }
+ }
+ /* Flush downwards.
+ */
+ if (0 < flfl) { $? ". downward flush"
+ dk4stream_api_init(&api);
+ api.cmd = DK4_STREAM_API_FLUSH;
+ api.d = strm->d;
+ (*(strm->fct))(&api);
+ if (0 == api.res) {
+ back = 0;
+ dk4error_set_simple_error_code(erp, DK4_E_FLUSH_FAILED);
+ }
+ }
+ /* Indicate output buffer is empty.
+ */
+ strm->usbo = 0;
+ $? "- dk4stream_i_flush_write %d", back
+ return back;
+}
+
+
+
+/** Internal function to write one character after checking stream.
+ @param strm Stream to write to.
+ @param c Character to write.
+ @param erp Error report, may be NULL.
+ @return 1 on success, 0 on error.
+*/
+static
+int
+dk4stream_i_write_byte(dk4_stream_t *strm, char c, dk4_er_t *erp)
+{
+ int back = 0;
+ $? "+ dk4stream_i_write_byte"
+ if (strm->usbo < strm->szbo) {
+ (strm->bo)[strm->usbo] = c;
+ strm->usbo += 1;
+ strm->bwr += (dk4_um_t)1UL;
+ if ((dk4_um_t)0UL == strm->bwr) { strm->bwo = 1; }
+ back = 1;
+ if (strm->usbo >= strm->szbo) {
+ back = dk4stream_i_flush_write(strm, 0, erp);
+ }
+ } $? "- dk4stream_i_write_byte %d", back
+ return back;
+}
+
+
+
+
+/** Internal function to read a single character.
+ @param dst Pointer to variable for result.
+ @param strm Stream to read from.
+ @param erp Error report, may be NULL.
+ @return 1 on success, 0 on error.
+*/
+static
+int
+dk4stream_i_c8_read_byte(char *dst, dk4_stream_t *strm, dk4_er_t *erp)
+{
+ dk4_stream_api_t api;
+ int back = 0;
+ $? "+ dk4stream_i_c8_read_byte"
+ if ((0 == strm->feoi) && ((strm->usbi == 0) || (strm->rebi >= strm->usbi))) {
+ $? ". low level read required"
+ dk4stream_api_init(&api);
+ api.cmd = DK4_STREAM_API_READ;
+ api.d = strm->d;
+ api.b = strm->bi;
+ api.sz_in = strm->szbi;
+ (*(strm->fct))(&api);
+ if (0 != api.res) { $? ". low level read succeeded"
+ strm->rebi = 0;
+ strm->usbi = api.sz_out;
+ if (api.sz_out < strm->szbi) { $? ". less bytes than buffer size"
+ if (0 == strm->zreof) {
+ dk4stream_api_init(&api);
+ api.cmd = DK4_STREAM_API_AT_END;
+ api.d = strm->d;
+ (*(strm->fct))(&api);
+ if (0 != api.res) { $? ". EOF found"
+ strm->feoi = 1;
+ }
+ }
+ }
+ } else { $? ". low level read failed"
+ if (0 != strm->zreof) {
+ strm->feoi = 1;
+ } else {
+ dk4stream_api_init(&api);
+ api.cmd = DK4_STREAM_API_AT_END;
+ api.d = strm->d;
+ (*(strm->fct))(&api);
+ if (0 != api.res) { $? ". end of input reached"
+ strm->feoi = 1;
+ }
+ }
+ }
+ } else { $? ". data in buffer available"
+ }
+ if ((0 < strm->usbi) && (strm->rebi < strm->usbi)) {
+ $? ". data in buffer available"
+ *dst = (strm->bi)[strm->rebi];
+ strm->rebi += 1;
+ back = 1;
+ } else { $? ". no data in buffer"
+ }
+ $? "- dk4stream_i_c8_read_byte %d", back
+ return back;
+}
+
+
+
+
+dk4_stream_t *
+dk4stream_open(
+ void *obj,
+ dk4_stream_api_fct_t *fct,
+ int fl,
+ size_t ibs,
+ size_t obs,
+ dk4_er_t *erp
+)
+{
+ dk4_stream_api_t api;
+ dk4_stream_t *back = NULL;
+ $? "+ dk4stream_open"
+ /* Check arguments
+ */
+ if ((NULL == obj) || (NULL == fct)) {
+ dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
+ goto finished;
+ }
+ /* Check flag, at least read or write must be set
+ */
+ if (0 == (fl & (DK4_STREAM_READ | DK4_STREAM_WRITE))) {
+ dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
+ goto finished;
+ }
+ /* Allocate memory for stream itself
+ */
+ back = dk4mem_new(dk4_stream_t,1,erp);
+ if (NULL == back) {
+ goto finished;
+ }
+ /* Initialize members
+ */
+ back->d = obj; back->fct = fct;
+ back->bi = NULL; back->bo = NULL;
+ back->bwr = (dk4_um_t)0UL;
+ back->szbi = 0; back->szbo = 0;
+ back->usbi = 0; back->usbo = 0; back->rebi = 0;
+ back->fl = fl; back->feoi = 0;
+ back->bwo = 0;
+ back->oenc = DK4_FILE_ENCODING_ASCII;
+ back->zreof = 0;
+ /* Allocate input buffer or destroy object
+ */
+ if (fl & DK4_STREAM_READ) {
+ back->szbi = ((0 < ibs) ? ibs : 4096);
+ back->bi = dk4mem_new(char,back->szbi,erp);
+ if (NULL == back->bi) {
+ dk4stream_release_memory(back);
+ back = NULL;
+ goto finished;
+ }
+ }
+ /* Allocate output buffer or destroy object
+ */
+ if (fl & DK4_STREAM_WRITE) {
+ back->szbo = ((0 < obs) ? obs : 4096);
+ back->bo = dk4mem_new(char,back->szbo,erp);
+ if (NULL == back->bo) {
+ dk4stream_release_memory(back);
+ back = NULL;
+ goto finished;
+ }
+ }
+ /* Check whether reading zero bytes indicates end of input
+ */
+ dk4stream_api_init(&api);
+ api.cmd = DK4_STREAM_API_ZERO_READ_IS_EOF;
+ api.d = obj;
+ (*(back->fct))(&api);
+ if (0 != api.res) { back->zreof = 1; }
+finished:
+ $? "- dk4stream_open PTR=%d", TR_IPTR(back)
+ return back;
+}
+
+
+
+int
+dk4stream_close(dk4_stream_t *strm, dk4_er_t *erp)
+{
+ dk4_stream_api_t api;
+ int back = 0;
+ $? "+ dk4stream_close"
+ /* Check argument.
+ */
+ if (NULL == strm) {
+ dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
+ goto finished;
+ }
+
+ /* Success so far, unless there are errors in the next sections.
+ */
+ back = 1;
+
+ /* Write bytes in output buffer downwards.
+ */
+ if ((strm->fl) & DK4_STREAM_WRITE) {
+ dk4stream_api_init(&api);
+ api.cmd = DK4_STREAM_API_WRITE;
+ api.d = strm->d;
+ api.b = strm->bo;
+ api.sz_in = strm->usbo;
+ (*(strm->fct))(&api);
+ if (0 == api.res) {
+ back = 0;
+ dk4error_set_simple_error_code(erp, DK4_E_WRITE_FAILED);
+ }
+ }
+
+ /* Attempt to flush downwards.
+ */
+ if ((strm->fl) & DK4_STREAM_WRITE) {
+ dk4stream_api_init(&api);
+ api.cmd = DK4_STREAM_API_FLUSH;
+ api.d = strm->d;
+ (*(strm->fct))(&api);
+ if (0 == api.res) {
+ back = 0;
+ dk4error_set_simple_error_code(erp, DK4_E_FLUSH_FAILED);
+ }
+ }
+
+ /* Finalize downward data structures.
+ */
+ dk4stream_api_init(&api);
+ api.cmd = DK4_STREAM_API_CLOSE;
+ api.d = strm->d;
+ (*(strm->fct))(&api);
+ if (0 == api.res) {
+ back = 0;
+ dk4error_set_simple_error_code(erp, DK4_E_CLOSE_FAILED);
+ }
+
+ /* Release memory.
+ */
+ dk4stream_release_memory(strm);
+
+finished:
+ $? "- dk4stream_close %d", back
+ return back;
+}
+
+
+
+int
+dk4stream_write_byte(dk4_stream_t *strm, char c, dk4_er_t *erp)
+{
+ int back = 0;
+ $? "+ dk4stream_write_byte"
+ if (NULL != strm) {
+ if ((strm->fl) & DK4_STREAM_WRITE) {
+ back = dk4stream_i_write_byte(strm, c, erp);
+ } else {
+ dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
+ }
+ } else {
+ dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
+ } $? "- dk4stream_write_byte %d", back
+ return back;
+}
+
+
+
+#if NOT_OPTIMIZED
+
+int
+dk4stream_write(dk4_stream_t *strm, const void *b, size_t sz, dk4_er_t *erp)
+{
+ char *cptr; /* Traverse buffer */
+ int back = 0;
+ $? "+ dk4stream_write"
+ if ((NULL != strm) && (NULL != b) && (0 < sz)) {
+ if ((strm->fl) & DK4_STREAM_WRITE) {
+ back = 1;
+ cptr = (char *)b;
+ while(sz--) {
+ if (0 == dk4stream_i_write_byte(strm, *(cptr++), erp)) {
+ back = 0;
+ }
+ }
+ } else {
+ dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
+ }
+ } else {
+ dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
+ } $? "- dk4stream_write %d", back
+ return back;
+}
+
+#else
+
+int
+dk4stream_write(dk4_stream_t *strm, const void *b, size_t sz, dk4_er_t *erp)
+{
+ char *cptr; /* Traverse buffer */
+ size_t bc;
+ int back = 0;
+ int cc;
+
+ $? "+ dk4stream_write %lu", (unsigned long)sz
+ if ((NULL != strm) && (NULL != b) && (0 < sz)) {
+ if ((strm->fl) & DK4_STREAM_WRITE) {
+ back = 1;
+ cptr = (char *)b;
+ do {
+ cc = 0; $? ". loop start"
+ if (0 < sz) {
+ if (strm->usbo < strm->szbo) { $? ". can copy"
+ /* Attempt to copy as many bytes as still free in output buffer */
+ bc = strm->szbo - strm->usbo; $? ". bc = %lu", (unsigned long)bc
+ /* If not enough bytes available, correct number of bytes */
+ if (bc > sz) { bc = sz; } $? ". bc = %lu", (unsigned long)bc
+ DK4_MEMCPY(&((strm->bo)[strm->usbo]), cptr, bc);
+ strm->usbo += bc; $? ". usbo = %lu", (unsigned long)(strm->usbo)
+ cptr = &(cptr[bc]);
+ sz -= bc; $? ". sz = %lu", (unsigned long)sz
+ if ((DK4_UM_MAX - (dk4_um_t)bc) < strm->bwr) {
+ strm->bwo = 1; $? "! numeric overflow"
+ back = 0;
+ }
+ strm->bwr += (dk4_um_t)bc; $? ". bwr = %lu", (unsigned long)(strm->bwr)
+ if (strm->usbo >= strm->szbo) { $? ". must flush"
+ if (0 == dk4stream_i_flush_write(strm, 0, erp)) {
+ back = 0; $? "! flush failed"
+ }
+ }
+ if (0 < sz) { cc = 1; }
+ } else { $? ". must flush first"
+ if (0 == dk4stream_i_flush_write(strm, 0, erp)) {
+ back = 0; $? "! flush failed"
+ }
+ }
+ }
+ } while(0 != cc);
+ } else { $? "! stream not writable"
+ dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
+ }
+ } else { $? "! invalid args"
+ dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
+ } $? "- dk4stream_write %d", back
+ return back;
+}
+
+#endif
+
+
+
+int
+dk4stream_write_char_string(dk4_stream_t *strm, const char *str, dk4_er_t *erp)
+{
+ size_t sl;
+ int back = 0;
+ if ((NULL != strm) && (NULL != str)) {
+ sl = strlen(str);
+ back = dk4stream_write(strm, str, sl, erp);
+ }
+ else {
+ dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
+ }
+ return back;
+}
+
+
+
+int
+dk4stream_flush_read(dk4_stream_t *strm, dk4_er_t *erp)
+{
+ int back = 0;
+ $? "+ dk4stream_flush_read"
+ if (NULL != strm) {
+ if ((strm->fl) & DK4_STREAM_READ) {
+ back = 1;
+ strm->usbi = 0;
+ strm->rebi = 0;
+ } else {
+ dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
+ }
+ } else {
+ dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
+ } $? "- dk4stream_flush_read %d", back
+ return back;
+}
+
+
+
+int
+dk4stream_flush_write(dk4_stream_t *strm, int flfl, dk4_er_t *erp)
+{
+ int back = 0;
+ $? "+ dk4stream_flush_write"
+ if (NULL != strm) {
+ if ((strm->fl) & DK4_STREAM_WRITE) {
+ back = dk4stream_i_flush_write(strm, flfl, erp);
+ } else {
+ dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
+ }
+ } else {
+ dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
+ } $? "- dk4stream_flush_write %d", back
+ return back;
+}
+
+
+
+int
+dk4stream_flush(dk4_stream_t *strm, int flfl, dk4_er_t *erp)
+{
+ int back = 0;
+ $? "+ dk4stream_flush"
+ if (NULL != strm) {
+ back = 1;
+ if ((strm->fl) & DK4_STREAM_WRITE) {
+ if (0 == dk4stream_flush_write(strm, flfl, erp)) {
+ back = 0;
+ }
+ }
+ if ((strm->fl) & DK4_STREAM_READ) {
+ if (0 == dk4stream_flush_read(strm, erp)) {
+ back = 0;
+ }
+ }
+ } else {
+ dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
+ } $? "- dk4stream_flush %d", back
+ return back;
+}
+
+
+
+int
+dk4stream_c8_read_byte(char *dst, dk4_stream_t *strm, dk4_er_t *erp)
+{
+ int back = 0;
+ $? "+ dk4stream_c8_read_byte"
+ if ((NULL != dst) && (NULL != strm)) { $? ". pointers ok"
+ if ((strm->fl) & DK4_STREAM_READ) { $? ". read"
+ back = dk4stream_i_c8_read_byte(dst, strm, erp);
+ } else {
+ dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
+ }
+ } else {
+ dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
+ } $? "- dk4stream_c8_read_byte %d", back
+ return back;
+}
+
+
+
+int
+dk4stream_read(void *b, size_t *szptr, dk4_stream_t *strm, dk4_er_t *erp)
+{
+ char *cptr; /* Traverse the buffer */
+ size_t szin; /* Input: Available buffer size */
+ size_t szout; /* Output: Used buffer size */
+ int back = 0; /* Function result */
+ int cc = 1; /* Flag: Can continue */
+ $? "+ dk4stream_read"
+ if ((NULL != b) && (NULL != szptr) && (NULL != strm)) {
+ if (((strm->fl) & DK4_STREAM_READ) && (0 < *szptr)) {
+ szin = *szptr; szout = 0;
+ cptr = (char *)b;
+ do {
+ if (0 != dk4stream_i_c8_read_byte(cptr++, strm, erp)) {
+ szout++;
+ if (szout >= szin) {
+ cc = 0;
+ back = 1;
+ }
+ } else {
+ cc = 0;
+ if (0 < szout) {
+ back = 1;
+ } else {
+ if (0 != dk4stream_found_eof(strm)) {
+ dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND);
+ } else {
+ dk4error_set_simple_error_code(erp, DK4_E_READ_FAILED);
+ }
+ }
+ }
+ } while (0 != cc);
+ *szptr = szout;
+ } else {
+ dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
+ }
+ } else {
+ dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
+ } $? "- dk4stream_read %d", back
+ return back;
+}
+
+
+
+dk4_um_t
+dk4stream_bytes_written(const dk4_stream_t *strm)
+{
+ dk4_um_t back = (dk4_um_t)0UL;
+ if (NULL != strm) { back = strm->bwr; }
+ return back;
+}
+
+
+
+int
+dk4stream_overflow_bytes_written(const dk4_stream_t *strm)
+{
+ int back = 0;
+ if (NULL != strm) { back = strm->bwo; }
+ return back;
+}
+
+
+
+int
+dk4stream_found_eof(const dk4_stream_t *strm)
+{
+ int back = 0;
+ if (NULL != strm) {
+ back = strm->feoi;
+ }
+ return back;
+}
+