/* WARNING: This file was generated by dkct. 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 */ /* Copyright (C) 2015-2017, Dirk Krause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above opyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file dk4strm.c The dk4strm module. */ #line 358 "dk4strm.ctr" #include "dk4strm.h" #include "dk4mem.h" #include "dk4enc.h" #include "dk4numco.h" #line 369 "dk4strm.ctr" static void dk4stream_api_init(dk4_stream_api_t *ptr) { #line 378 "dk4strm.ctr" 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 386 "dk4strm.ctr" } /** Release memory allocated by a stream. @param strm Stream to release. */ static void dk4stream_release_memory(dk4_stream_t *strm) { #line 398 "dk4strm.ctr" 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 414 "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 428 "dk4strm.ctr" /* Write buffer contents (if any) downwards. */ if (0 != strm->usbo) { #line 431 "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 445 "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 458 "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 475 "dk4strm.ctr" 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 485 "dk4strm.ctr" 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; #line 504 "dk4strm.ctr" if ((0 == strm->feoi) && ((strm->usbi == 0) || (strm->rebi >= strm->usbi))) { #line 506 "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 513 "dk4strm.ctr" strm->rebi = 0; strm->usbi = api.sz_out; if (api.sz_out < strm->szbi) { #line 516 "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 522 "dk4strm.ctr" strm->feoi = 1; } } } } else { #line 527 "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 535 "dk4strm.ctr" strm->feoi = 1; } } } } else { #line 540 "dk4strm.ctr" } if ((0 < strm->usbi) && (strm->rebi < strm->usbi)) { #line 543 "dk4strm.ctr" *dst = (strm->bi)[strm->rebi]; strm->rebi += 1; back = 1; } else { #line 547 "dk4strm.ctr" } #line 549 "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 568 "dk4strm.ctr" /* 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: #line 628 "dk4strm.ctr" return back; } int dk4stream_close(dk4_stream_t *strm, dk4_er_t *erp) { dk4_stream_api_t api; int back = 0; #line 639 "dk4strm.ctr" /* 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: #line 695 "dk4strm.ctr" return back; } int dk4stream_write_byte(dk4_stream_t *strm, char c, dk4_er_t *erp) { int back = 0; #line 705 "dk4strm.ctr" 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 714 "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 727 "dk4strm.ctr" 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 742 "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 756 "dk4strm.ctr" if ((NULL != strm) && (NULL != b) && (0 < sz)) { if ((strm->fl) & DK4_STREAM_WRITE) { back = 1; cptr = (char *)b; do { cc = 0; #line 762 "dk4strm.ctr" if (0 < sz) { if (strm->usbo < strm->szbo) { #line 764 "dk4strm.ctr" /* Attempt to copy as many bytes as still free in output buffer */ bc = strm->szbo - strm->usbo; #line 766 "dk4strm.ctr" /* If not enough bytes available, correct number of bytes */ if (bc > sz) { bc = sz; } #line 768 "dk4strm.ctr" DK4_MEMCPY(&((strm->bo)[strm->usbo]), cptr, bc); strm->usbo += bc; #line 770 "dk4strm.ctr" cptr = &(cptr[bc]); sz -= bc; #line 772 "dk4strm.ctr" if ((DK4_UM_MAX - (dk4_um_t)bc) < strm->bwr) { strm->bwo = 1; #line 774 "dk4strm.ctr" back = 0; } strm->bwr += (dk4_um_t)bc; #line 777 "dk4strm.ctr" if (strm->usbo >= strm->szbo) { #line 778 "dk4strm.ctr" if (0 == dk4stream_i_flush_write(strm, 0, erp)) { back = 0; #line 780 "dk4strm.ctr" } } if (0 < sz) { cc = 1; } } else { #line 784 "dk4strm.ctr" if (0 == dk4stream_i_flush_write(strm, 0, erp)) { back = 0; #line 786 "dk4strm.ctr" } } } } while(0 != cc); } else { #line 791 "dk4strm.ctr" dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } } else { #line 794 "dk4strm.ctr" dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } #line 796 "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 ((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 825 "dk4strm.ctr" 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 836 "dk4strm.ctr" return back; } int dk4stream_flush_write(dk4_stream_t *strm, int flfl, dk4_er_t *erp) { int back = 0; #line 846 "dk4strm.ctr" 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 855 "dk4strm.ctr" return back; } int dk4stream_flush(dk4_stream_t *strm, int flfl, dk4_er_t *erp) { int back = 0; #line 865 "dk4strm.ctr" 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 880 "dk4strm.ctr" return back; } int dk4stream_c8_read_byte(char *dst, dk4_stream_t *strm, dk4_er_t *erp) { int back = 0; #line 890 "dk4strm.ctr" if ((NULL != dst) && (NULL != strm)) { #line 891 "dk4strm.ctr" if ((strm->fl) & DK4_STREAM_READ) { #line 892 "dk4strm.ctr" 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); } #line 899 "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 913 "dk4strm.ctr" 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); } #line 944 "dk4strm.ctr" 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; }