diff --git a/src/gmio_core/internal/helper_stream.h b/src/gmio_core/internal/helper_stream.h index eece70d..3e27610 100644 --- a/src/gmio_core/internal/helper_stream.h +++ b/src/gmio_core/internal/helper_stream.h @@ -60,11 +60,21 @@ GMIO_INLINE size_t gmio_stream_size(gmio_stream_t* stream) return 0; } -/*! Safe and convenient function for gmio_stream::func_rewind() */ -GMIO_INLINE void gmio_stream_rewind(gmio_stream_t* stream) +/*! Safe and convenient function for gmio_stream::func_get_pos() */ +GMIO_INLINE int gmio_stream_get_pos( + gmio_stream_t* stream, gmio_stream_pos_t* pos) { - if (stream != NULL && stream->func_rewind != NULL) - stream->func_rewind(stream->cookie); + if (stream != NULL && stream->func_get_pos != NULL) + return stream->func_get_pos(stream->cookie, pos); + return -1; } +/*! Safe and convenient function for gmio_stream::func_set_pos() */ +GMIO_INLINE int gmio_stream_set_pos( + gmio_stream_t* stream, const gmio_stream_pos_t* pos) +{ + if (stream != NULL && stream->func_set_pos != NULL) + return stream->func_set_pos(stream->cookie, pos); + return -1; +} #endif /* GMIO_INTERNAL_HELPER_STREAM_H */ diff --git a/src/gmio_core/stream.c b/src/gmio_core/stream.c index 8a4958d..050024d 100644 --- a/src/gmio_core/stream.c +++ b/src/gmio_core/stream.c @@ -129,9 +129,19 @@ static size_t gmio_stream_stdio_size(void* cookie) #endif } -static void gmio_stream_stdio_rewind(void* cookie) +static int gmio_stream_stdio_get_pos(void* cookie, gmio_stream_pos_t* pos) { - rewind((FILE*) cookie); + fpos_t fpos; + int res = fgetpos((FILE*)cookie, &fpos); + memcpy(&pos->cookie[0], &fpos, sizeof(fpos_t)); + return res; +} + +static int gmio_stream_stdio_set_pos(void* cookie, const gmio_stream_pos_t* pos) +{ + fpos_t fpos; + memcpy(&fpos, &pos->cookie[0], sizeof(fpos_t)); + return fsetpos((FILE*)cookie, &fpos); } gmio_stream_t gmio_stream_stdio(FILE* file) @@ -143,6 +153,7 @@ gmio_stream_t gmio_stream_stdio(FILE* file) stream.func_read = gmio_stream_stdio_read; stream.func_write = gmio_stream_stdio_write; stream.func_size = gmio_stream_stdio_size; - stream.func_rewind = gmio_stream_stdio_rewind; + stream.func_get_pos = gmio_stream_stdio_get_pos; + stream.func_set_pos = gmio_stream_stdio_set_pos; return stream; } diff --git a/src/gmio_core/stream.h b/src/gmio_core/stream.h index 6454596..6487adc 100644 --- a/src/gmio_core/stream.h +++ b/src/gmio_core/stream.h @@ -24,6 +24,7 @@ #define GMIO_STREAM_H #include "global.h" +#include "stream_pos.h" #include /*! Stream that can get input from an arbitrary data source or can write @@ -94,17 +95,13 @@ struct gmio_stream /*! Pointer on a function that returns the size(in bytes) of the stream */ size_t (*func_size)(void* cookie); - /*! Pointer on a function that moves the position indicator within the - * stream to the beginning - * - * The function should behaves like C standard [rewind()] - * (http://pubs.opengroup.org/onlinepubs/007904975/functions/rewind.html) - */ - void (*func_rewind)(void* cookie); + int (*func_get_pos)(void* cookie, gmio_stream_pos_t* pos); + int (*func_set_pos)(void* cookie, const gmio_stream_pos_t* pos); }; typedef struct gmio_stream gmio_stream_t; + GMIO_C_LINKAGE_BEGIN /* Initialization */ diff --git a/src/gmio_core/stream_pos.c b/src/gmio_core/stream_pos.c new file mode 100644 index 0000000..0bdc0b1 --- /dev/null +++ b/src/gmio_core/stream_pos.c @@ -0,0 +1,25 @@ +/**************************************************************************** +** gmio +** Copyright Fougue (2 Mar. 2015) +** contact@fougue.pro +** +** This software is a reusable library whose purpose is to provide complete +** I/O support for various CAD file formats (eg. STL) +** +** This software is governed by the CeCILL-B license under French law and +** abiding by the rules of distribution of free software. You can use, +** modify and/ or redistribute the software under the terms of the CeCILL-B +** license as circulated by CEA, CNRS and INRIA at the following URL +** "http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html". +****************************************************************************/ + +#include "stream_pos.h" + +#include +#include + +gmio_stream_pos_t gmio_stream_pos_null() +{ + gmio_stream_pos_t pos = {0}; + return pos; +} diff --git a/src/gmio_core/stream_pos.h b/src/gmio_core/stream_pos.h new file mode 100644 index 0000000..fb793c5 --- /dev/null +++ b/src/gmio_core/stream_pos.h @@ -0,0 +1,46 @@ +/**************************************************************************** +** gmio +** Copyright Fougue (2 Mar. 2015) +** contact@fougue.pro +** +** This software is a reusable library whose purpose is to provide complete +** I/O support for various CAD file formats (eg. STL) +** +** This software is governed by the CeCILL-B license under French law and +** abiding by the rules of distribution of free software. You can use, +** modify and/ or redistribute the software under the terms of the CeCILL-B +** license as circulated by CEA, CNRS and INRIA at the following URL +** "http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html". +****************************************************************************/ + +/*! \file stream_pos.h + * Declaration of gmio_stream_pos and utility functions + * + * \addtogroup gmio_core + * @{ + */ + +#ifndef GMIO_STREAM_POS_H +#define GMIO_STREAM_POS_H + +#include "global.h" + +enum { GMIO_STREAM_POS_COOKIE_SIZE = 32 }; /* 32 bytes */ + +/*! Stream position + * + */ +struct gmio_stream_pos +{ + uint8_t cookie[GMIO_STREAM_POS_COOKIE_SIZE]; +}; +typedef struct gmio_stream_pos gmio_stream_pos_t; + +GMIO_C_LINKAGE_BEGIN + +GMIO_LIB_EXPORT gmio_stream_pos_t gmio_stream_pos_null(); + +GMIO_C_LINKAGE_END + +#endif /* GMIO_STREAM_POS_H */ +/*! @} */ diff --git a/src/gmio_stl/stl_format.c b/src/gmio_stl/stl_format.c index 336256c..97de791 100644 --- a/src/gmio_stl/stl_format.c +++ b/src/gmio_stl/stl_format.c @@ -33,16 +33,20 @@ gmio_stl_format_t gmio_stl_get_format(gmio_stream_t *stream) { char fixed_buffer[GMIO_FIXED_BUFFER_SIZE]; size_t read_size = 0; + gmio_stream_pos_t stream_start_pos = gmio_stream_pos_null(); if (stream == NULL) return GMIO_STL_FORMAT_UNKNOWN; - /* Read a chunk of bytes from stream, then try to find format from that */ + /* Read a chunk of bytes from stream, then try to find format from that + * + * First keep stream start position, it will be restored after read + */ + gmio_stream_get_pos(stream, &stream_start_pos); memset(fixed_buffer, 0, GMIO_FIXED_BUFFER_SIZE); read_size = gmio_stream_read(stream, &fixed_buffer, 1, GMIO_FIXED_BUFFER_SIZE); read_size = GMIO_MIN(read_size, GMIO_FIXED_BUFFER_SIZE); - - gmio_stream_rewind(stream); + gmio_stream_set_pos(stream, &stream_start_pos); /* Binary STL ? */ if (read_size >= (GMIO_STLB_HEADER_SIZE + 4)) { diff --git a/src/gmio_support/stream_qt.cpp b/src/gmio_support/stream_qt.cpp index 7a89140..4dd24ed 100644 --- a/src/gmio_support/stream_qt.cpp +++ b/src/gmio_support/stream_qt.cpp @@ -18,6 +18,8 @@ #include #include +#include + QT_USE_NAMESPACE static gmio_bool_t gmio_stream_qiodevice_at_end(void* cookie) @@ -62,10 +64,23 @@ static size_t gmio_stream_qiodevice_size(void* cookie) return device->size(); } -static void gmio_stream_qiodevice_rewind(void* cookie) +static int gmio_stream_qiodevice_get_pos(void* cookie, gmio_stream_pos_t* pos) { QIODevice* device = static_cast(cookie); - device->seek(0); + qint64 qpos = device->pos(); + std::memcpy(&pos->cookie[0], &qpos, sizeof(qint64)); + return 0; +} + +static int gmio_stream_qiodevice_set_pos( + void* cookie, const gmio_stream_pos_t* pos) +{ + QIODevice* device = static_cast(cookie); + qint64 qpos; + std::memcpy(&qpos, &pos->cookie[0], sizeof(qint64)); + if (device->seek(qpos)) + return 0; + return -1; /* TODO: return error code */ } gmio_stream_t gmio_stream_qiodevice(QIODevice* device) @@ -77,6 +92,7 @@ gmio_stream_t gmio_stream_qiodevice(QIODevice* device) stream.func_read = gmio_stream_qiodevice_read; stream.func_write = gmio_stream_qiodevice_write; stream.func_size = gmio_stream_qiodevice_size; - stream.func_rewind = gmio_stream_qiodevice_rewind; + stream.func_get_pos = gmio_stream_qiodevice_get_pos; + stream.func_set_pos = gmio_stream_qiodevice_set_pos; return stream; } diff --git a/tests/fake_support/qt/QtCore/QIODevice b/tests/fake_support/qt/QtCore/QIODevice index 2a4010b..8ffd421 100644 --- a/tests/fake_support/qt/QtCore/QIODevice +++ b/tests/fake_support/qt/QtCore/QIODevice @@ -22,6 +22,9 @@ public: virtual qint64 size() const { return 0; } + virtual qint64 pos() const + { return 0; } + virtual bool seek(qint64 /*pos*/) { return true; } }; diff --git a/tests/stream_buffer.c b/tests/stream_buffer.c index 94a3c64..061bab7 100644 --- a/tests/stream_buffer.c +++ b/tests/stream_buffer.c @@ -84,12 +84,6 @@ static size_t gmio_stream_buffer_size(void* cookie) return buff->len; } -static void gmio_stream_buffer_rewind(void* cookie) -{ - gmio_stream_buffer_t* buff = (gmio_stream_buffer_t*)cookie; - buff->pos = 0; -} - void gmio_stream_set_buffer(gmio_stream_t *stream, gmio_stream_buffer_t* buff) { stream->cookie = buff; @@ -98,5 +92,5 @@ void gmio_stream_set_buffer(gmio_stream_t *stream, gmio_stream_buffer_t* buff) stream->func_read = gmio_stream_buffer_read; stream->func_write = gmio_stream_buffer_write; stream->func_size = gmio_stream_buffer_size; - stream->func_rewind = gmio_stream_buffer_rewind; + /* TODO: implement func_get/set_pos functions */ }