diff --git a/src/gmio_core/transfer.c b/src/gmio_core/transfer.c index db1af5e..405ddd5 100644 --- a/src/gmio_core/transfer.c +++ b/src/gmio_core/transfer.c @@ -23,3 +23,10 @@ gmio_bool_t gmio_transfer_is_stop_requested(const gmio_transfer_t* trsf) return trsf->is_stop_requested_func(trsf->cookie); return GMIO_FALSE; } + +gmio_bool_t gmio_transfer_handle_progress( + const gmio_transfer_t* trsf, size_t value, size_t max_value) +{ + if (trsf != NULL && trsf->handle_progress_func != NULL) + trsf->handle_progress_func(trsf->cookie, value, max_value); +} diff --git a/src/gmio_core/transfer.h b/src/gmio_core/transfer.h index 165e52a..35bac92 100644 --- a/src/gmio_core/transfer.h +++ b/src/gmio_core/transfer.h @@ -35,11 +35,20 @@ struct gmio_transfer /*! Optional pointer on a function that says if the currently running * operation must stop * - * If GMIO_TRUE is returned then the current transfer should abort as + * If \c GMIO_TRUE is returned then the current transfer should abort as * soon as possible, otherwise it can continue execution. */ gmio_bool_t (*is_stop_requested_func)(void* cookie); + /*! Optional pointer on a function that is called anytime some progress + * was done during transfer + * + * \param cookie The cookie set inside the gmio_transfer object + * \param value Current value of the transfer progress (<= \p max_value ) + * \param max_value Maximum value of the transfer progress + */ + void (*handle_progress_func)(void* cookie, size_t value, size_t max_value); + /*! The stream object to be used for I/O */ gmio_stream_t stream; @@ -53,9 +62,25 @@ struct gmio_transfer typedef struct gmio_transfer gmio_transfer_t; +/*! Safe and convenient function for gmio_transfer::is_stop_requested_func() + * + * Same as: \code trsf->is_stop_requested_func(trsf->cookie) \endcode + * + * TODO: don't export, move to gmio_core/internal + */ GMIO_LIB_EXPORT gmio_bool_t gmio_transfer_is_stop_requested(const gmio_transfer_t* trsf); +/*! Safe and convenient function for gmio_transfer::handle_progress_func() + * + * Same as: \code trsf->handle_progress_func(trsf->cookie, v, maxv) \endcode + * + * TODO: don't export, move to gmio_core/internal + */ +GMIO_LIB_EXPORT +gmio_bool_t gmio_transfer_handle_progress( + const gmio_transfer_t* trsf, size_t value, size_t max_value); + GMIO_C_LINKAGE_END #endif /* GMIO_TRANSFER_H */ diff --git a/src/gmio_stl/stl_io.h b/src/gmio_stl/stl_io.h index 3cbdb69..74b50b2 100644 --- a/src/gmio_stl/stl_io.h +++ b/src/gmio_stl/stl_io.h @@ -34,13 +34,22 @@ GMIO_C_LINKAGE_BEGIN /*! Options for gmio_stla_read() * - * No options yet, it just exists for future needs, which could possibly be: + * Possible other options in the future: * - flag to force locale ? * - case sensitive/insensitive ? */ struct gmio_stla_read_options { - void* dummy; /*!< Structs must have at least one member in strict ISO-C90 */ + /*! Hint about the total size (in bytes) of the STL ascii data to be read + * from stream + * + * \p stream_size is passed to gmio_transfer::handle_progress_func() as + * the \p max_value argument. + * + * It's defaulted to \c 0 if options argument is set to NULL (when + * calling gmio_stla_read()) + */ + size_t stream_size; }; typedef struct gmio_stla_read_options gmio_stla_read_options_t; @@ -51,7 +60,7 @@ typedef struct gmio_stla_read_options gmio_stla_read_options_t; GMIO_LIBSTL_EXPORT int gmio_stla_read(gmio_stl_mesh_creator_t* creator, gmio_transfer_t* trsf, - const gmio_stla_read_options_t* options /* NULL */); + const gmio_stla_read_options_t* options); /*! Options for gmio_stla_write() */ struct gmio_stla_write_options diff --git a/src/gmio_stl/stla_read.c b/src/gmio_stl/stla_read.c index 66f6b03..14c6413 100644 --- a/src/gmio_stl/stla_read.c +++ b/src/gmio_stl/stla_read.c @@ -78,8 +78,13 @@ /* gmio_stream_fwd_iterator_stla_cookie */ typedef struct { + /* Copy of gmio_stla_read() corresponding argument */ gmio_transfer_t* transfer; + /* Copy of gmio_stla_read_options::stream_size */ + size_t stream_size; + /* Offset (in bytes) from beginning of stream : current position */ size_t stream_offset; + /* Cache for gmio_transfer::is_stop_requested_func */ gmio_bool_t is_stop_requested; } gmio_string_stream_fwd_iterator_cookie_t; @@ -118,10 +123,12 @@ static void gmio_stream_fwd_iterator_stla_read_hook(void* cookie, gmio_string_stream_fwd_iterator_cookie_t* tcookie = (gmio_string_stream_fwd_iterator_cookie_t*)(cookie); const gmio_transfer_t* trsf = tcookie != NULL ? tcookie->transfer : NULL; - if (trsf != NULL) - tcookie->is_stop_requested = gmio_transfer_is_stop_requested(trsf); - if (tcookie != NULL) + if (tcookie != NULL) { tcookie->stream_offset += buffer->len; + tcookie->is_stop_requested = gmio_transfer_is_stop_requested(trsf); + gmio_transfer_handle_progress( + trsf, tcookie->stream_offset, tcookie->stream_size); + } } GMIO_INLINE static gmio_bool_t parsing_can_continue(const gmio_stla_parse_data_t* data) @@ -294,8 +301,9 @@ static void parse_beginsolid(gmio_stla_parse_data_t* data) && data->creator != NULL && data->creator->ascii_begin_solid_func != NULL) { - data->creator->ascii_begin_solid_func(data->creator->cookie, - current_token_as_identifier(data)); + data->creator->ascii_begin_solid_func( + data->creator->cookie, + current_token_as_identifier(data)); } if (data->token == ID_token) parsing_eat_token(ID_token, data); @@ -377,10 +385,12 @@ static void parse_facets(gmio_stla_parse_data_t* data) { uint32_t i_facet_offset = 0; gmio_stl_triangle_t facet; + const gmio_bool_t is_add_triangle_available = + data->creator != NULL && data->creator->add_triangle_func != NULL; while (data->token == FACET_token && parsing_can_continue(data)) { parse_facet(data, &facet); - if (data->creator != NULL && data->creator->add_triangle_func != NULL) + if (is_add_triangle_available) data->creator->add_triangle_func(data->creator->cookie, i_facet_offset, &facet); ++i_facet_offset; } diff --git a/src/gmio_stl/stla_write.c b/src/gmio_stl/stla_write.c index ab16c7f..81a95c5 100644 --- a/src/gmio_stl/stla_write.c +++ b/src/gmio_stl/stla_write.c @@ -167,6 +167,8 @@ int gmio_stla_write(const gmio_stl_mesh_t* mesh, gmio_stl_triangle_t tri; uint32_t ibuffer_facet; + gmio_transfer_handle_progress(trsf, ifacet, total_facet_count); + /* Writing of facets is buffered */ buffer_iterator = trsf->buffer; for (ibuffer_facet = ifacet; ibuffer_facet < clamped_facet_count; ++ibuffer_facet) { diff --git a/src/gmio_stl/stlb_read.c b/src/gmio_stl/stlb_read.c index cd07986..f709e5e 100644 --- a/src/gmio_stl/stlb_read.c +++ b/src/gmio_stl/stlb_read.c @@ -107,6 +107,9 @@ int gmio_stlb_read(gmio_stl_mesh_creator_t *creator, while (gmio_no_error(error) && rparams.i_facet_offset < total_facet_count) { + gmio_transfer_handle_progress( + trsf, rparams.i_facet_offset, total_facet_count); + rparams.facet_count = gmio_size_to_uint32( gmio_stream_read( diff --git a/src/gmio_stl/stlb_write.c b/src/gmio_stl/stlb_write.c index bd2e10f..c03ac39 100644 --- a/src/gmio_stl/stlb_write.c +++ b/src/gmio_stl/stlb_write.c @@ -106,6 +106,8 @@ int gmio_stlb_write(const gmio_stl_mesh_t* mesh, i_facet < facet_count && gmio_no_error(error); i_facet += wparams.facet_count) { + gmio_transfer_handle_progress(trsf, i_facet, facet_count); + /* Write to buffer */ wparams.facet_count = GMIO_MIN(wparams.facet_count, facet_count - wparams.i_facet_offset);