/* 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: dk4tsp32.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 dk4tsp32.c The dk4tsp32 module. */ #line 215 "dk4tsp32.ctr" #include "dk4tsp32.h" #include "dk4enc.h" #include "dk4mem.h" #include "dk4ansi.h" #include "dk4utf8.h" #include "dk4utf16.h" #include "dk4c32.h" #line 227 "dk4tsp32.ctr" /** Initialize text stream processing structure. @param tsp Text stream processor. @param eie Expected input encoding. */ static void dk4tsp32_init(dk4_tsp32_t *tsp, int eie) { DK4_MEMRES(tsp, sizeof(dk4_tsp32_t)); dk4bom_detect_init(&(tsp->bomd), eie); dk4error_init(&(tsp->er_en)); dk4error_init(&(tsp->er_pr)); tsp->inbuf = NULL; tsp->obj = NULL; tsp->in_sz = 0; tsp->in_us = 0; tsp->ief = eie; tsp->iee = eie; tsp->pst = 0; (tsp->pos).bytes = (dk4_um_t)0UL; (tsp->pos).chars = (dk4_um_t)1UL; (tsp->pos).lineno = (dk4_um_t)1UL; (tsp->pos).charil = (dk4_um_t)1UL; } /** Process a 32 bit character. @param tsp Text stream processor. @param chr Character to process. @return DK4_TSP_RES_OK if the characters were processed successfully, DK4_TSP_RES_ERROR if there was an error but we can continue, DK4_TSP_RES_FATAL if there was a fatal error so we should abort processing. */ static int dk4tsp32_process_character( dk4_tsp32_t *tsp, dk4_c32_t chr ) { int back = DK4_TSP_RES_FATAL; #line 276 "dk4tsp32.ctr" /* Increase position */ (tsp->pos).chars += (dk4_um_t)1UL; (tsp->pos).charil += (dk4_um_t)1UL; /* Check for line buffering or direct processing */ if ((NULL != tsp->inbuf) && (0 < tsp->in_sz) && (NULL != (tsp->fct).lh)) { #line 282 "dk4tsp32.ctr" if (tsp->in_us < tsp->in_sz) { #line 283 "dk4tsp32.ctr" (tsp->inbuf)[tsp->in_us] = chr; tsp->in_us += 1; back = DK4_TSP_RES_OK; if ((dk4_c32_t)'\n' == chr) { back = DK4_TSP_RES_FATAL; if (tsp->in_us < tsp->in_sz) { (tsp->inbuf)[tsp->in_us] = (dk4_c32_t)0UL; back = (*((tsp->fct).lh))( tsp->obj,tsp->inbuf,(tsp->pos).lineno,&(tsp->er_pr) ); } else { dk4error_set_with_position( &(tsp->er_en), DK4_E_BUFFER_TOO_SMALL, (tsp->pos).bytes, (tsp->pos).lineno, (tsp->pos).chars, (tsp->pos).charil ); } /* 2015-07-18 Bugfix: We must reset the number of used characters to 0 after processing and flushing the line buffer. */ tsp->in_us = 0; } } else { #line 307 "dk4tsp32.ctr" dk4error_set_with_position( &(tsp->er_en), DK4_E_BUFFER_TOO_SMALL, (tsp->pos).bytes, (tsp->pos).lineno, (tsp->pos).chars, (tsp->pos).charil ); } } else { #line 315 "dk4tsp32.ctr" if (NULL != (tsp->fct).ch) { back = (*((tsp->fct).ch))(tsp->obj, chr, &(tsp->pos), &(tsp->er_pr)); } } if ((dk4_c32_t)('\n') == chr) { (tsp->pos).lineno += (dk4_um_t)1UL; (tsp->pos).charil = (dk4_um_t)1UL; } #line 324 "dk4tsp32.ctr" return back; } /** Normal processing for one byte. Retrieve a 32 bit character first, either by decoding directly or by adding to a decoder. @param tsp Text stream processor. @param inbyte Byte to process. @return Operation result, one from DK4_TSP_RES_OK, DK4_TSP_RES_ERROR or DK4_TSP_RES_FATAL. */ static int dk4tsp32_process_byte( dk4_tsp32_t *tsp, unsigned char inbyte ) { dk4_c32_t c32 = (dk4_c32_t)0UL; /* 32 bit character */ int back = DK4_TSP_RES_FATAL; /* Function result */ int cuc32 = 0; /* Flag: Have 32 bit char */ int res = 0; /* Operation result */ switch (tsp->ief) { case DK4_FILE_ENCODING_ASCII: { c32 = (dk4_c32_t)inbyte; cuc32 = 1; } break; case DK4_FILE_ENCODING_ANSI: { if (0 != dk4ansi_decode(&c32, inbyte)) { cuc32 = 1; } else { dk4error_set_with_position( &(tsp->er_en), DK4_E_DECODING_FAILED, (tsp->pos).bytes, (tsp->pos).lineno, (tsp->pos).chars, (tsp->pos).charil ); } } break; case DK4_FILE_ENCODING_UTF8: { res = dk4utf8_add(&((tsp->dec).u08), inbyte); switch (res) { case DK4_EDSTM_ERROR: { dk4error_set_with_position( &(tsp->er_en), DK4_E_DECODING_FAILED, (tsp->pos).bytes, (tsp->pos).lineno, (tsp->pos).chars, (tsp->pos).charil ); } break; case DK4_EDSTM_FINISHED: { c32 = dk4utf8_get(&((tsp->dec).u08)); cuc32 = 1; dk4utf8_init(&((tsp->dec).u08)); } break; case DK4_EDSTM_ACCEPT: { back = DK4_TSP_RES_OK; } break; } } break; case DK4_FILE_ENCODING_UTF16_LE: { res = dk4utf16_byte_add(&((tsp->dec).u16), inbyte); switch (res) { case DK4_EDSTM_ERROR: { dk4error_set_with_position( &(tsp->er_en), DK4_E_DECODING_FAILED, (tsp->pos).bytes, (tsp->pos).lineno, (tsp->pos).chars, (tsp->pos).charil ); } break; case DK4_EDSTM_FINISHED: { c32 = dk4utf16_byte_get(&((tsp->dec).u16)); cuc32 = 1; dk4utf16_byte_init(&((tsp->dec).u16), 0); } break; case DK4_EDSTM_ACCEPT: { back = DK4_TSP_RES_OK; } break; } } break; case DK4_FILE_ENCODING_UTF16_BE: { res = dk4utf16_byte_add(&((tsp->dec).u16), inbyte); switch (res) { case DK4_EDSTM_ERROR: { dk4error_set_with_position( &(tsp->er_en), DK4_E_DECODING_FAILED, (tsp->pos).bytes, (tsp->pos).lineno, (tsp->pos).chars, (tsp->pos).charil ); } break; case DK4_EDSTM_FINISHED: { c32 = dk4utf16_byte_get(&((tsp->dec).u16)); cuc32 = 1; dk4utf16_byte_init(&((tsp->dec).u16), 1); } break; case DK4_EDSTM_ACCEPT: { back = DK4_TSP_RES_OK; } break; } } break; case DK4_FILE_ENCODING_32_LE: { res = dk4c32_decoder_add(&((tsp->dec).c32), inbyte); switch (res) { case DK4_EDSTM_ERROR: { dk4error_set_with_position( &(tsp->er_en), DK4_E_DECODING_FAILED, (tsp->pos).bytes, (tsp->pos).lineno, (tsp->pos).chars, (tsp->pos).charil ); } break; case DK4_EDSTM_FINISHED: { c32 = dk4c32_decoder_get(&((tsp->dec).c32)); cuc32 = 1; dk4c32_decoder_init(&((tsp->dec).c32), 0); } break; case DK4_EDSTM_ACCEPT: { back = DK4_TSP_RES_OK; } break; } } break; case DK4_FILE_ENCODING_32_BE: { res = dk4c32_decoder_add(&((tsp->dec).c32), inbyte); switch (res) { case DK4_EDSTM_ERROR: { dk4error_set_with_position( &(tsp->er_en), DK4_E_DECODING_FAILED, (tsp->pos).bytes, (tsp->pos).lineno, (tsp->pos).chars, (tsp->pos).charil ); } break; case DK4_EDSTM_FINISHED: { c32 = dk4c32_decoder_get(&((tsp->dec).c32)); cuc32 = 1; dk4c32_decoder_init(&((tsp->dec).c32), 1); } break; case DK4_EDSTM_ACCEPT: { back = DK4_TSP_RES_OK; } break; } } break; } if (0 != cuc32) { back = dk4tsp32_process_character(tsp, c32); } if (DK4_TSP_RES_FATAL == back) { tsp->pst = 2; } return back; } /** Initialize decoder for found input encoding. @param tsp Text stream processor. */ static void dk4tsp32_initialize_decoder(dk4_tsp32_t *tsp) { switch (tsp->ief) { case DK4_FILE_ENCODING_UTF8: { dk4utf8_init(&((tsp->dec).u08)); } break; case DK4_FILE_ENCODING_UTF16_LE: { dk4utf16_byte_init(&((tsp->dec).u16), 0); } break; case DK4_FILE_ENCODING_UTF16_BE: { dk4utf16_byte_init(&((tsp->dec).u16), 1); } break; case DK4_FILE_ENCODING_32_LE: { dk4c32_decoder_init(&((tsp->dec).c32), 0); } break; case DK4_FILE_ENCODING_32_BE: { dk4c32_decoder_init(&((tsp->dec).c32), 1); } break; } } #if TRACE_DEBUG static unsigned long byte_number = 0UL; #endif /** Add one single byte. @param tsp Text stream processor. @param inbyte Byte to process. @return DK4_TSP_RES_OK if the character was processed successfully, DK4_TSP_RES_ERROR if there was an error but we can continue, DK4_TSP_RES_FATAL if there was a fata error so we should abort processing. */ static int dk4tsp32_i_add_one_byte( dk4_tsp32_t *tsp, unsigned char inbyte ) { size_t nrej; /* Number of unused bytes */ size_t i; /* Current unused byte index */ int back = DK4_TSP_RES_FATAL; /* Function result */ int res; /* Operation result */ unsigned char uc; /* Current unused byte */ #line 531 "dk4tsp32.ctr" (tsp->pos).bytes += (dk4_um_t)1UL; switch (tsp->pst) { case 0: { res = dk4bom_detect_add(&(tsp->bomd), inbyte); switch (res) { case DK4_EDSTM_ACCEPT: { back = DK4_TSP_RES_OK; } break; case DK4_EDSTM_FINISHED: case DK4_EDSTM_FINISHED_WITH_UNUSED: { back = DK4_TSP_RES_OK; tsp->ief = dk4bom_detect_get_encoding(&(tsp->bomd)); dk4tsp32_initialize_decoder(tsp); tsp->pst = 1; if (DK4_EDSTM_FINISHED_WITH_UNUSED == res) { nrej = dk4bom_detect_num_unused_bytes(&(tsp->bomd)); if (0 < nrej) { for (i = 0; ((i < nrej) && (DK4_TSP_RES_FATAL != back)); i++) { uc = dk4bom_detect_unused_byte(&(tsp->bomd), i); switch (dk4tsp32_process_byte(tsp, uc)) { case DK4_TSP_RES_FATAL: { back = DK4_TSP_RES_FATAL; } break; case DK4_TSP_RES_ERROR: { if (DK4_TSP_RES_OK == back) { back = DK4_TSP_RES_ERROR; } } break; } } } } } break; } } break; case 1: { back = dk4tsp32_process_byte(tsp, inbyte); } break; /* Processing stage 2 indicates there was a serious error before, we must skip further processing. This situation is covered by the initialization value DK4_TSP_RES_FATAL, so we do not need a case branch here. */ } #line 576 "dk4tsp32.ctr" return back; } int dk4tsp32_setup_char( dk4_tsp32_t *tsp, void *obj, dk4_c32_handler_t *fct, int eie, dk4_er_t *erp ) { int back = 0; if (NULL != tsp) { dk4tsp32_init(tsp, eie); if (NULL != fct) { tsp->obj = obj; (tsp->fct).ch = fct; tsp->iee = eie; tsp->ief = eie; tsp->pst = 0; back = 1; } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); tsp->pst = 2; } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } return back; } int dk4tsp32_setup_line( dk4_tsp32_t *tsp, void *obj, dk4_c32_line_handler_t *fct, dk4_c32_t *inbuf, size_t szin, int eie, dk4_er_t *erp ) { int back = 0; if (NULL != tsp) { dk4tsp32_init(tsp, eie); if ((NULL != fct) && (NULL != inbuf) && (0 < szin)) { tsp->obj = obj; (tsp->fct).lh = fct; tsp->inbuf = inbuf; tsp->in_sz = szin; tsp->in_us = 0; tsp->iee = eie; tsp->ief = eie; tsp->pst = 0; back = 1; } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); tsp->pst = 2; } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } return back; } int dk4tsp32_add_one_byte( dk4_tsp32_t *tsp, unsigned char inbyte ) { int back = DK4_TSP_RES_FATAL; #line 656 "dk4tsp32.ctr" if (NULL != tsp) { if (2 > tsp->pst) { back = dk4tsp32_i_add_one_byte(tsp, inbyte); } } #line 662 "dk4tsp32.ctr" return back; } int dk4tsp32_add_bytes( dk4_tsp32_t *tsp, const unsigned char *buffer, size_t sz ) { int back = DK4_TSP_RES_FATAL; /* Function result */ int res; /* Processing result */ #line 677 "dk4tsp32.ctr" if ((NULL != tsp) && (NULL != buffer) && (0 < sz)) { if (2 > tsp->pst) { back = DK4_TSP_RES_OK; while ((sz--) && (2 > tsp->pst)) { res = dk4tsp32_i_add_one_byte(tsp, *(buffer++)); switch (res) { case DK4_TSP_RES_FATAL: { back = DK4_TSP_RES_FATAL; } break; case DK4_TSP_RES_ERROR: { if (DK4_TSP_RES_OK == back) { back = DK4_TSP_RES_ERROR; } } break; } } } } #line 696 "dk4tsp32.ctr" return back; } int dk4tsp32_finish(dk4_tsp32_t *tsp) { size_t nrej = 0; /* Number of unused bytes */ size_t i = 0; /* Current unused byte index */ int back = DK4_TSP_RES_FATAL; /* Function result */ int res; /* Operation result */ unsigned char uc; /* Current unused byte */ #line 710 "dk4tsp32.ctr" if (NULL != tsp) { /* Flush all unprocessed output 1. If there are unprocessed bytes in the BOM detector as BOM detection was not completed, process these bytes. 2. If there are characters in the line buffer, finalize the line buffer text and process it. */ back = DK4_TSP_RES_OK; /* Retrieve an process bytes stored in BOM detector */ if (0 == tsp->pst) { tsp->pst = 1; nrej = dk4bom_detect_num_unused_bytes(&(tsp->bomd)); if (0 < nrej) { dk4tsp32_initialize_decoder(tsp); for (i = 0; ((i < nrej) && (2 > tsp->pst)); i++) { uc = dk4bom_detect_unused_byte(&(tsp->bomd), i); switch (dk4tsp32_process_byte(tsp, uc)) { case DK4_TSP_RES_FATAL: { back = DK4_TSP_RES_FATAL; tsp->pst = 2; } break; case DK4_TSP_RES_ERROR: { if (DK4_TSP_RES_OK == back) { back = DK4_TSP_RES_ERROR; } } break; } } } } /* Process final line */ if ((NULL != tsp->inbuf) && (0 < tsp->in_sz) && (NULL != (tsp->fct).lh)) { if (0 < tsp->in_us) { if (2 > tsp->pst) { if (tsp->in_us < tsp->in_sz) { (tsp->inbuf)[tsp->in_us] = (dk4_c32_t)0UL; res = (*((tsp->fct).lh))( tsp->obj,tsp->inbuf,(tsp->pos).lineno,&(tsp->er_pr) ); switch (res) { case DK4_TSP_RES_FATAL: { back = DK4_TSP_RES_FATAL; tsp->pst = 2; } break; case DK4_TSP_RES_ERROR: { if (DK4_TSP_RES_OK == back) { back = DK4_TSP_RES_ERROR; } } break; } } else { back = DK4_TSP_RES_FATAL; tsp->pst = 2; dk4error_set_with_position( &(tsp->er_en), DK4_E_BUFFER_TOO_SMALL, (tsp->pos).bytes, (tsp->pos).lineno, (tsp->pos).chars, (tsp->pos).charil ); } } } } } #line 771 "dk4tsp32.ctr" return back; } void dk4tsp32_get_errors(dk4_er_t *er_en, dk4_er_t *er_pr, dk4_tsp32_t *tsp) { if (NULL != tsp) { if (NULL != er_en) { DK4_MEMCPY(er_en, &(tsp->er_en), sizeof(dk4_er_t)); } if (NULL != er_pr) { DK4_MEMCPY(er_pr, &(tsp->er_pr), sizeof(dk4_er_t)); } } }