/* Copyright (C) 2015-2020, Dirk Krause SPDX-License-Identifier: BSD-3-Clause */ /* WARNING: This file was generated by the dkct program (see http://dktools.sourceforge.net/ for details). Changes you make here will be lost if dkct is run again! You should modify the original source and run dkct on it. Original source: dk4strm.ctr */ /** @file dk4strm.c The dk4strm module. */ #line 370 "dk4strm.ctr" #include "dk4conf.h" #include "dk4strm.h" #include "dk4mem.h" #include "dk4enc.h" #include "dk4numco.h" #if DK4_HAVE_ASSERT_H #ifndef ASSERT_H_INCLUDED #include #define ASSERT_H_INCLUDED 1 #endif #endif #line 388 "dk4strm.ctr" static void dk4stream_api_init(dk4_stream_api_t *ptr) { #line 397 "dk4strm.ctr" #if DK4_USE_ASSERT assert(NULL != ptr); #endif 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; #line 408 "dk4strm.ctr" } /** Release memory allocated by a stream. @param strm Stream to release. */ static void dk4stream_release_memory(dk4_stream_t *strm) { #line 420 "dk4strm.ctr" #if DK4_USE_ASSERT assert(NULL != strm); #endif 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); } #line 439 "dk4strm.ctr" } /** 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; #line 453 "dk4strm.ctr" /* Write buffer contents (if any) downwards. */ #if DK4_USE_ASSERT assert(NULL != strm); #endif if (0 != strm->usbo) { #line 459 "dk4strm.ctr" 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) { #line 473 "dk4strm.ctr" 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; #line 486 "dk4strm.ctr" 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; #line 503 "dk4strm.ctr" #if DK4_USE_ASSERT assert(NULL != strm); #endif 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); } } #line 516 "dk4strm.ctr" return back; } /** Internal function to read a single character. @param dst Pointer to variable for result. @param strm Stream to read from. @return 1 on success, 0 on error. */ static int dk4stream_i_c8_read_byte(char *dst, dk4_stream_t *strm) { dk4_stream_api_t api; int back = 0; #if DK4_USE_ASSERT assert(NULL != strm); assert(NULL != dst); #endif #line 538 "dk4strm.ctr" if ((0 == strm->feoi) && ((strm->usbi == 0) || (strm->rebi >= strm->usbi))) { #line 540 "dk4strm.ctr" 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) { #line 547 "dk4strm.ctr" strm->rebi = 0; strm->usbi = api.sz_out; if (api.sz_out < strm->szbi) { #line 550 "dk4strm.ctr" 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) { #line 556 "dk4strm.ctr" strm->feoi = 1; } } } } else { #line 561 "dk4strm.ctr" 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) { #line 569 "dk4strm.ctr" strm->feoi = 1; } } } } else { #line 574 "dk4strm.ctr" } if ((0 < strm->usbi) && (strm->rebi < strm->usbi)) { #line 577 "dk4strm.ctr" *dst = (strm->bi)[strm->rebi]; strm->rebi += 1; back = 1; } else { #line 581 "dk4strm.ctr" } #line 583 "dk4strm.ctr" 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; #line 602 "dk4strm.ctr" /* Check arguments */ #if DK4_USE_ASSERT assert(NULL != obj); assert(NULL != fct); #endif 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; #if DK4_ON_WINDOWS back->oenc = DK4_FILE_ENCODING_WIN1252; #else back->oenc = DK4_FILE_ENCODING_PLAIN; #endif 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: #line 670 "dk4strm.ctr" return back; } int dk4stream_close(dk4_stream_t *strm, dk4_er_t *erp) { dk4_stream_api_t api; int back = 0; #line 681 "dk4strm.ctr" /* Check argument. */ #if DK4_USE_ASSERT assert(NULL != strm); #endif 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 ((0 != ((strm->fl) & DK4_STREAM_WRITE)) && (0 < strm->usbo)) { 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; #line 706 "dk4strm.ctr" 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; #line 719 "dk4strm.ctr" 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; #line 731 "dk4strm.ctr" dk4error_set_simple_error_code(erp, DK4_E_CLOSE_FAILED); } /* Release memory. */ dk4stream_release_memory(strm); finished: #line 740 "dk4strm.ctr" return back; } int dk4stream_write_byte(dk4_stream_t *strm, char c, dk4_er_t *erp) { int back = 0; #line 750 "dk4strm.ctr" #if DK4_USE_ASSERT assert(NULL != strm); #endif 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); } #line 762 "dk4strm.ctr" 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; #line 775 "dk4strm.ctr" #if DK4_USE_ASSERT assert(NULL != strm); assert(NULL != b); assert(0 < sz); #endif 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); } #line 795 "dk4strm.ctr" 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; #line 809 "dk4strm.ctr" #if DK4_USE_ASSERT assert(NULL != strm); assert(NULL != b); assert(0 < sz); #endif if ((NULL != strm) && (NULL != b) && (0 < sz)) { if ((strm->fl) & DK4_STREAM_WRITE) { back = 1; cptr = (char *)b; do { cc = 0; #line 820 "dk4strm.ctr" if (0 < sz) { if (strm->usbo < strm->szbo) { #line 822 "dk4strm.ctr" /* Attempt to copy as many bytes as still free in output buffer */ bc = strm->szbo - strm->usbo; #line 824 "dk4strm.ctr" /* If not enough bytes available, correct number of bytes */ if (bc > sz) { bc = sz; } #line 826 "dk4strm.ctr" DK4_MEMCPY(&((strm->bo)[strm->usbo]), cptr, bc); strm->usbo += bc; #line 828 "dk4strm.ctr" cptr = &(cptr[bc]); sz -= bc; #line 830 "dk4strm.ctr" if ((DK4_UM_MAX - (dk4_um_t)bc) < strm->bwr) { strm->bwo = 1; #line 832 "dk4strm.ctr" back = 0; } strm->bwr += (dk4_um_t)bc; #line 835 "dk4strm.ctr" if (strm->usbo >= strm->szbo) { #line 836 "dk4strm.ctr" if (0 == dk4stream_i_flush_write(strm, 0, erp)) { back = 0; #line 838 "dk4strm.ctr" } } if (0 < sz) { cc = 1; } } else { #line 842 "dk4strm.ctr" if (0 == dk4stream_i_flush_write(strm, 0, erp)) { back = 0; #line 844 "dk4strm.ctr" } } } } while(0 != cc); } else { #line 849 "dk4strm.ctr" dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } } else { #line 852 "dk4strm.ctr" dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } #line 854 "dk4strm.ctr" 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 DK4_USE_ASSERT assert(NULL != strm); assert(NULL != str); #endif 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; #line 887 "dk4strm.ctr" #if DK4_USE_ASSERT assert(NULL != strm); #endif 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); } #line 901 "dk4strm.ctr" return back; } int dk4stream_flush_write(dk4_stream_t *strm, int flfl, dk4_er_t *erp) { int back = 0; #line 911 "dk4strm.ctr" #if DK4_USE_ASSERT assert(NULL != strm); #endif 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); } #line 923 "dk4strm.ctr" return back; } int dk4stream_flush(dk4_stream_t *strm, int flfl, dk4_er_t *erp) { int back = 0; #line 933 "dk4strm.ctr" #if DK4_USE_ASSERT assert(NULL != strm); #endif 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); } #line 951 "dk4strm.ctr" return back; } int dk4stream_c8_read_byte(char *dst, dk4_stream_t *strm, dk4_er_t *erp) { int back = 0; #line 961 "dk4strm.ctr" #if DK4_USE_ASSERT assert(NULL != strm); assert(NULL != dst); #endif if ((NULL != dst) && (NULL != strm)) { #line 966 "dk4strm.ctr" if ((strm->fl) & DK4_STREAM_READ) { #line 967 "dk4strm.ctr" back = dk4stream_i_c8_read_byte(dst, strm); } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } #line 974 "dk4strm.ctr" 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 */ #line 988 "dk4strm.ctr" #if DK4_USE_ASSERT assert(NULL != strm); assert(NULL != b); assert(NULL != szptr); assert(0 < *szptr); #endif 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)) { 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); } #line 1025 "dk4strm.ctr" return back; } dk4_um_t dk4stream_bytes_written(const dk4_stream_t *strm) { dk4_um_t back = (dk4_um_t)0UL; #if DK4_USE_ASSERT assert(NULL != strm); #endif if (NULL != strm) { back = strm->bwr; } return back; } int dk4stream_overflow_bytes_written(const dk4_stream_t *strm) { int back = 0; #if DK4_USE_ASSERT assert(NULL != strm); #endif if (NULL != strm) { back = strm->bwo; } return back; } int dk4stream_found_eof(const dk4_stream_t *strm) { int back = 0; #if DK4_USE_ASSERT assert(NULL != strm); #endif if (NULL != strm) { back = strm->feoi; } return back; }