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:
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;