rsys

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

commit 944ed7ee99b37bcc47fc8df972c1a374fc46b414
parent db2ae57e3e03b5939fa17ab8fe6c7b951b12396d
Author: vaplv <vaplv@free.fr>
Date:   Sat, 13 May 2017 16:29:42 +0200

Implement the big_buffer resize function

Diffstat:
Mcmake/CMakeLists.txt | 1+
Asrc/big_buffer.c | 27+++++++++++++++++++++++++++
Msrc/big_buffer.h | 147++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
3 files changed, 132 insertions(+), 43 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -39,6 +39,7 @@ set(VERSION_PATCH 0) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) set(RSYS_FILES_SRC + big_buffer.c clock_time.c cstr.c image.c diff --git a/src/big_buffer.c b/src/big_buffer.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2013-2017 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/>. */ + +#define _POSIX_C_SOURCE 200112L /* ftruncate support */ + +#include <unistd.h> +#include "big_buffer.h" + +res_T +truncate__(FILE* file, const size_t sz) +{ + ASSERT(file); + return ftruncate(fileno(file), (off_t)sz) == 0 ? RES_OK : RES_IO_ERR; +} + diff --git a/src/big_buffer.h b/src/big_buffer.h @@ -30,6 +30,11 @@ enum bigbuf_flag { BIGBUF_LOAD_STREAM = BIT(1) }; +extern LOCAL_SYM res_T +truncate__ + (FILE* file, + const size_t sz); + #endif /* BIGBUF_H */ #else @@ -90,6 +95,7 @@ BIGBUF_FUNC__(flush__)(struct BIGBUF__* bigbuf) { BIGBUF_DATA* buf_data; size_t buf_size, write_size; + long cur, offset; int err; res_T res = RES_OK; ASSERT(bigbuf); @@ -99,16 +105,25 @@ BIGBUF_FUNC__(flush__)(struct BIGBUF__* bigbuf) buf_size = bigbuf->buf.size; buf_data = bigbuf->buf.data; - ASSERT(bigbuf->buf_index + buf_size == bigbuf->size); - err = fseek(bigbuf->file, bigbuf->end, SEEK_SET); + if(bigbuf->buf_index + buf_size == bigbuf->size) { + err = fseek(bigbuf->file, bigbuf->end, SEEK_SET); + } else { + cur = ftell(bigbuf->file); + offset = (long)(sizeof(BIGBUF_DATA)*bigbuf->buf_index) - cur + bigbuf->head; + err = fseek(bigbuf->file, offset, SEEK_CUR); + } if(err < 0) { res = RES_IO_ERR; goto error; } write_size = fwrite(buf_data, sizeof(BIGBUF_DATA), buf_size, bigbuf->file); - bigbuf->end = bigbuf->end + (long)write_size * (long)sizeof(BIGBUF_DATA); + + if(bigbuf->buf_index + buf_size == bigbuf->size) { + bigbuf->end = bigbuf->end + (long)write_size * (long)sizeof(BIGBUF_DATA); + } + if(write_size == buf_size) { bigbuf->buf.size = 0; /* Clear buffered data */ bigbuf->buf_index = bigbuf->size; @@ -129,6 +144,58 @@ error: goto exit; } +static INLINE res_T +BIGBUF_FUNC__(fetch__)(struct BIGBUF__* bigbuf, const size_t index) +{ + BIGBUF_DATA* buf_data; + size_t buf_size; + size_t buf_index; + size_t read_size; + long cur, offset; + int err; + res_T res = RES_OK; + ASSERT(bigbuf && index < bigbuf->size); + + if(index>=bigbuf->buf_index && index<bigbuf->buf_index + bigbuf->buf.size) + goto exit; + + buf_size = bigbuf->buf.size; + buf_data = bigbuf->buf.data; + + if(bigbuf->mode == BIGBUF_WRITE__) { + res = BIGBUF_FUNC__(flush__)(bigbuf); + if(res != RES_OK) goto error; + } + + buf_index = index / bigbuf->buf.capacity * bigbuf->buf.capacity; + + cur = ftell(bigbuf->file); + offset = (long)(sizeof(BIGBUF_DATA)*buf_index) - cur + bigbuf->head; + err = fseek(bigbuf->file, offset, SEEK_CUR); + if(err < 0) { + res = RES_IO_ERR; + goto error; + } + + buf_size = MMIN(bigbuf->size - buf_index, bigbuf->buf.capacity); + bigbuf->buf.size = buf_size; + + read_size = fread(buf_data, sizeof(BIGBUF_DATA), buf_size, bigbuf->file); + bigbuf->buf_index = buf_index; + bigbuf->mode = BIGBUF_READ__; + + if(read_size != buf_size) { + bigbuf->buf.size = read_size; + res = RES_IO_ERR; + goto error; + } + +exit: + return res; +error: + goto exit; +} + /******************************************************************************* * Big buffer API ******************************************************************************/ @@ -284,58 +351,52 @@ BIGBUF_FUNC__(size_get)(const struct BIGBUF__* bigbuf) } static INLINE res_T -BIGBUF_FUNC__(at)(struct BIGBUF__* bigbuf, const size_t at, BIGBUF_DATA* data) +BIGBUF_FUNC__(resize)(struct BIGBUF__* bigbuf, const size_t size) { - BIGBUF_DATA* buf_data; - size_t buf_size; res_T res = RES_OK; - ASSERT(bigbuf && data); - - if(at >= bigbuf->size) { - res = RES_BAD_ARG; - goto error; - } - - buf_size = bigbuf->buf.size; - buf_data = bigbuf->buf.data; + ASSERT(bigbuf); - if(at < bigbuf->buf_index || at >= bigbuf->buf_index + buf_size) { - size_t read_size; - size_t buf_index; - long cur, offset; - int err; + if(size == bigbuf->size) goto exit; - if(bigbuf->mode == BIGBUF_WRITE__) { - res = BIGBUF_FUNC__(flush__)(bigbuf); - if(res != RES_OK) goto error; + if(size < bigbuf->size) { + if(bigbuf->buf_index >= size) { + /* Clear all buffered data */ + bigbuf->buf.size = 0; + bigbuf->buf_index = size; } - - buf_index = at / bigbuf->buf.capacity * bigbuf->buf.capacity; - - cur = ftell(bigbuf->file); - offset = (long)(sizeof(BIGBUF_DATA)*buf_index) - cur + bigbuf->head; - err = fseek(bigbuf->file, offset, SEEK_CUR); - if(err < 0) { - res = RES_IO_ERR; - goto error; + if(bigbuf->buf_index + bigbuf->buf.size > size) { + /* Clear some buffered data */ + bigbuf->buf.size = size - bigbuf->buf_index; } + } + bigbuf->size = size; + bigbuf->end = bigbuf->head + (long)(bigbuf->size*sizeof(BIGBUF_DATA)); - buf_size = MMIN(bigbuf->size - buf_index, bigbuf->buf.capacity); - bigbuf->buf.size = buf_size; + res = truncate__(bigbuf->file, bigbuf->size); + if(res != RES_OK) goto error; - read_size = fread(buf_data, sizeof(BIGBUF_DATA), buf_size, bigbuf->file); - bigbuf->buf_index = buf_index; - bigbuf->mode = BIGBUF_READ__; +exit: + return res; +error: + goto exit; +} - if(read_size != buf_size) { - bigbuf->buf.size = read_size; - res = RES_IO_ERR; - goto error; - } +static INLINE res_T +BIGBUF_FUNC__(at)(struct BIGBUF__* bigbuf, const size_t at, BIGBUF_DATA* data) +{ + res_T res = RES_OK; + ASSERT(bigbuf && data); + + if(at >= bigbuf->size) { + res = RES_BAD_ARG; + goto error; } + res = BIGBUF_FUNC__(fetch__)(bigbuf, at); + if(res != RES_OK) goto error; + ASSERT(at >= bigbuf->buf_index); - *data = buf_data[at - bigbuf->buf_index]; + *data = bigbuf->buf.data[at - bigbuf->buf_index]; exit: return res;