%% 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 #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
if obj or fct is NULL or fl is invalid, - DK4_E_MATH_OVERFLOW
if ibs or obs is too large, - DK4_E_MEMORY_ALLOCATION_FAILED
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
if strm is NULL, - DK4_E_WRITE_FAILED
if writing one ore multiple bytes to the stream failed, - DK4_E_FLUSH_FAILED
if flushing data downwards failed, - DK4_E_CLOSE_FAILED
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
if strm is NULL or not opened for writing, - DK4_E_WRITE_FAILED
if writing one ore multiple bytes to the stream failed, - DK4_E_FLUSH_FAILED
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
if strm is NULL or not opened for writing, - DK4_E_WRITE_FAILED
if writing one ore multiple bytes to the stream failed, - DK4_E_FLUSH_FAILED
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
if strm is NULL or not opened for writing, - DK4_E_WRITE_FAILED
if writing one ore multiple bytes to the stream failed, - DK4_E_FLUSH_FAILED
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
if strm is NULL. - DK4_E_WRITE_FAILED
if writing one ore multiple bytes to the stream failed - DK4_E_FLUSH_FAILED
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
if strm is NULL or not opened for writing, - DK4_E_WRITE_FAILED
if writing one ore multiple bytes to the stream failed, - DK4_E_FLUSH_FAILED
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
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
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
if strm is NULL or not opened for reading, - DK4_E_NOT_FOUND
if end of input was detected in read attempt, - DK4_E_READ_FAILED
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; }