rsys

Basic data structures and low-level features
git clone git://git.meso-star.fr/rsys.git
Log | Files | Refs | README | LICENSE

commit 7f0bf5323b951e61ce3ef2e8f0932e72158b0793
parent b50aaf88815505e6e9381f364ca8061ae6b10377
Author: vaplv <vaplv@free.fr>
Date:   Thu, 28 Nov 2019 14:55:05 +0100

First implementation of the text_reader

Diffstat:
Mcmake/CMakeLists.txt | 6++++--
Asrc/text_reader.c | 199+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/text_reader.h | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 268 insertions(+), 2 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -52,7 +52,8 @@ set(RSYS_FILES_SRC mem_lifo_allocator.c mem_proxy_allocator.c quaternion.c - str.c) + str.c + text_reader.c) if(CMAKE_USE_PTHREADS_INIT) set(RSYS_FILES_SRC_THREAD @@ -121,7 +122,8 @@ set(RSYS_FILES_INC_API rsys.h signal.h str.h - stretchy_array.h) + stretchy_array.h + text_reader.h) set(RSYS_FILES_DOC COPYING COPYING.LESSER README.md) diff --git a/src/text_reader.c b/src/text_reader.c @@ -0,0 +1,199 @@ +/* Copyright (C) 2013-2019 Vincent Forest (vaplv@free.fr) + * + * The RSys library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The RSys library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the RSys library. If not, see <http://www.gnu.org/licenses/>. */ + +#include "dynamic_array_char.h" +#include "mem_allocator.h" +#include "ref_count.h" +#include "str.h" +#include "text_reader.h" + +/* #chars to add to the line buffer when there is no sufficient space to store + * the text */ +#define CHUNK 32 + +struct txtrdr { + FILE* stream; /* Stream of the text to read */ + struct str name; /* Stream name */ + size_t iline; /* Line index currently read */ + struct darray_char line; /* Buffer storing the read line */ + + /* String of chars from which the remaining line chars are skipped */ + char reject[3]; + + struct mem_allocator* allocator; + ref_T ref; +}; + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static void +release_txtrdr(ref_T* ref) +{ + struct txtrdr* txtrdr = NULL; + ASSERT(ref); + txtrdr = CONTAINER_OF(ref, struct txtrdr, ref); + str_release(&txtrdr->name); + darray_char_release(&txtrdr->line); + MEM_RM(txtrdr->allocator, txtrdr); +} + +/******************************************************************************* + * Text reader API + ******************************************************************************/ +res_T +txtrdr_create + (struct mem_allocator* mem_allocator, + FILE* stream, + const char* name, + const char comment, + struct txtrdr** out_txtrdr) +{ + struct mem_allocator* allocator = NULL; + struct txtrdr* txtrdr = NULL; + res_T res = RES_OK; + ASSERT(stream && out_txtrdr); + + allocator = mem_allocator ? mem_allocator : &mem_default_allocator; + txtrdr = MEM_CALLOC(allocator, 1, sizeof(*txtrdr)); + if(!txtrdr) { + res = RES_MEM_ERR; + goto error; + } + ref_init(&txtrdr->ref); + str_init(allocator, &txtrdr->name); + darray_char_init(allocator, &txtrdr->line); + txtrdr->allocator = allocator; + txtrdr->stream = stream; + txtrdr->iline = (size_t)(-1); + txtrdr->reject[0] = comment; + txtrdr->reject[1] = '\n'; + txtrdr->reject[2] = '\0'; /* Finalize the string */ + + res = str_set(&txtrdr->name, name ? name : "<null>"); + if(res != RES_OK) goto error; + + res = darray_char_resize(&txtrdr->line, CHUNK); + if(res != RES_OK) goto error; + +exit: + *out_txtrdr = txtrdr; + return res; +error: + if(txtrdr) { + txtrdr_ref_put(txtrdr); + txtrdr = NULL; + } + goto exit; +} + +void +txtrdr_ref_get(struct txtrdr* txtrdr) +{ + ASSERT(txtrdr); + ref_get(&txtrdr->ref); +} + +void +txtrdr_ref_put(struct txtrdr* txtrdr) +{ + ASSERT(txtrdr); + ref_put(&txtrdr->ref, release_txtrdr); +} + +res_T +txtrdr_read_line(struct txtrdr* txtrdr) +{ + char* str = NULL; + res_T res = RES_OK; + + if(!txtrdr) { + res = RES_BAD_ARG; + goto error; + } + + do { + /* Read the line */ + str = fgets + (darray_char_data_get(&txtrdr->line), + (int)darray_char_size_get(&txtrdr->line), + txtrdr->stream); + if(!str) { + darray_char_clear(&txtrdr->line); + break; + } + + /* Ensure tht the whole line is read */ + while(!strrchr(DARRAY_BUF(&txtrdr->line), '\n') && !feof(txtrdr->stream)) { + const size_t sz = darray_char_size_get(&txtrdr->line); + char* more = NULL; + + /* Resize the line buffer */ + res = darray_char_resize(&txtrdr->line, sz+CHUNK); + if(res != RES_OK) goto error; + + /* Read the remaing chars */ + more = darray_char_data_get(&txtrdr->line) + sz-1/*null char*/; + str = fgets(more, CHUNK+1/*previous null char*/, txtrdr->stream); + if(!str) { + res = RES_IO_ERR; + goto error; + } + } + + /* Remove new line & comments */ + str = darray_char_data_get(&txtrdr->line); + str[strcspn(str, txtrdr->reject)] = '\0'; + + ++txtrdr->iline; /* Increment the line index */ + + } while(strspn(str, " \t") == strlen(str));/*Keep going if the line is Empty*/ + +exit: + return res; +error: + goto exit; +} + +char* +txtrdr_get_line(struct txtrdr* txtrdr) +{ + ASSERT(txtrdr); + return darray_char_size_get(&txtrdr->line) == 0 + ? NULL : darray_char_data_get(&txtrdr->line); +} + +const char* +txtrdr_get_cline(const struct txtrdr* txtrdr) +{ + ASSERT(txtrdr); + return darray_char_size_get(&txtrdr->line) == 0 + ? NULL : darray_char_cdata_get(&txtrdr->line); +} + +size_t +txtrdr_get_line_num(const struct txtrdr* txtrdr) +{ + ASSERT(txtrdr); + return txtrdr->iline; +} + +const char* +txtrdr_get_name(const struct txtrdr* txtrdr) +{ + ASSERT(txtrdr); + return str_cget(&txtrdr->name); +} + diff --git a/src/text_reader.h b/src/text_reader.h @@ -0,0 +1,65 @@ +/* Copyright (C) 2013-2019 Vincent Forest (vaplv@free.fr) + * + * The RSys library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The RSys library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the RSys library. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef TEXT_READER_H +#define TEXT_READER_H + +#include "rsys.h" + +struct txtrdr; +struct mem_allocator; + +BEGIN_DECLS + +RSYS_API res_T +txtrdr_create + (struct mem_allocator* allocator, /* May be NULL <=> default allocator */ + FILE* stream, + const char* name, /* Stream name. May be NULL */ + const char comment, /* Char defining preceeding a comment */ + struct txtrdr** txtrdr); + +RSYS_API void +txtrdr_ref_get + (struct txtrdr* txtrdr); + +RSYS_API void +txtrdr_ref_put + (struct txtrdr* txtrdr); + +/* Read a non empty line, i.e. line with text that is not a comment */ +RSYS_API res_T +txtrdr_read_line + (struct txtrdr* txtrdr); + +RSYS_API char* +txtrdr_get_line + (struct txtrdr* txtrdr); + +RSYS_API const char* +txtrdr_get_cline + (const struct txtrdr* txtrdr); + +RSYS_API size_t +txtrdr_get_line_num + (const struct txtrdr* txtrdr); + +RSYS_API const char* +txtrdr_get_name + (const struct txtrdr* txtrdr); + +END_DECLS + +#endif /* TEXT_READER_H */