From 5605934628c4828813d3e51ca5042d119e39087a Mon Sep 17 00:00:00 2001 From: Hugues Delorme Date: Fri, 22 Jan 2016 12:42:34 +0100 Subject: [PATCH] gmio_stl: faster(2x) version of gmio_stla_infos_get() --- src/gmio_stl/internal/stla_infos_get.c | 178 +++++++++++++++++++++++++ 1 file changed, 178 insertions(+) diff --git a/src/gmio_stl/internal/stla_infos_get.c b/src/gmio_stl/internal/stla_infos_get.c index dcc69ae..f251140 100644 --- a/src/gmio_stl/internal/stla_infos_get.c +++ b/src/gmio_stl/internal/stla_infos_get.c @@ -15,6 +15,183 @@ #include "stla_infos_get.h" +#include "../../gmio_core/error.h" +#include "../../gmio_core/internal/min_max.h" +#include "../../gmio_core/internal/stringstream.h" +#include "../stl_error.h" +#include "stla_parsing.h" +#include "stl_rw_common.h" + +#include + +static const char* gmio_stringstream_skip_until_ascii_space( + struct gmio_stringstream* sstream) +{ + const char* curr_char = gmio_stringstream_current_char(sstream); + while (curr_char != NULL && !gmio_ascii_isspace(*curr_char)) + curr_char = gmio_stringstream_next_char(sstream); + return curr_char; +} + +static const char* gmio_stringstream_skip_word( + struct gmio_stringstream* sstream) +{ + gmio_stringstream_skip_ascii_spaces(sstream); + return gmio_stringstream_skip_until_ascii_space(sstream); +} + +static void gmio_skip_xyz_coords(struct gmio_stla_parse_data* data) +{ + struct gmio_stringstream* sstream = &data->strstream; + gmio_stringstream_skip_word(sstream); + gmio_stringstream_skip_word(sstream); + gmio_stringstream_skip_word(sstream); + data->strbuff.len = 0; + data->token = unknown_token; +} + +static int gmio_skip_facet(struct gmio_stla_parse_data* data) +{ + int errc = 0; + if (data->token != FACET_token) + errc += gmio_stla_eat_next_token_inplace(data, FACET_token); + + errc += gmio_stringstream_skip_word(&data->strstream) == NULL; /* normal */ + gmio_skip_xyz_coords(data); + + errc += gmio_stringstream_skip_word(&data->strstream) == NULL; /* outer */ + errc += gmio_stringstream_skip_word(&data->strstream) == NULL; /* loop */ + + errc += gmio_stringstream_skip_word(&data->strstream) == NULL; /* vertex */ + gmio_skip_xyz_coords(data); + errc += gmio_stringstream_skip_word(&data->strstream) == NULL; /* vertex */ + gmio_skip_xyz_coords(data); + errc += gmio_stringstream_skip_word(&data->strstream) == NULL; /* vertex */ + gmio_skip_xyz_coords(data); + + errc += gmio_stringstream_skip_word(&data->strstream) == NULL; /* endloop */ + errc += gmio_stringstream_skip_word(&data->strstream) == NULL; /* endfacet */ + + return errc; +} + +static int gmio_stla_check_next_token( + struct gmio_stringstream* sstream, const char* expected_token_str) +{ + const char* stream_char = NULL; + + stream_char = gmio_stringstream_skip_ascii_spaces(sstream); + for (;;) { + if (stream_char == NULL || gmio_ascii_isspace(*stream_char)) { + if (*expected_token_str == 0) + return 1; + break; + } + else if (!gmio_ascii_char_iequals(*stream_char, *expected_token_str) + || *expected_token_str == 0) + { + break; + } + stream_char = gmio_stringstream_next_char(sstream); + ++expected_token_str; + } + gmio_stringstream_skip_word(sstream); + return 0; +} + +static void gmio_stringstream_stla_read_hook( + void* cookie, const struct gmio_string* strbuff) +{ + struct gmio_stringstream_stla_cookie* tcookie = + (struct gmio_stringstream_stla_cookie*)(cookie); + if (tcookie != NULL) + tcookie->stream_offset += strbuff->len; +} + +int gmio_stla_infos_get( + struct gmio_stl_infos_get_args* args, unsigned flags) +{ + const gmio_bool_t flag_facet_count = + (flags & GMIO_STL_INFO_FLAG_FACET_COUNT) != 0; + const gmio_bool_t flag_size = + (flags & GMIO_STL_INFO_FLAG_SIZE) != 0; + const gmio_bool_t flag_stla_solidname = + (flags & GMIO_STLA_INFO_FLAG_SOLIDNAME) != 0; + + struct gmio_stl_infos* infos = &args->infos; + void* const mblock_ptr = args->stream_memblock.ptr; + /* Leave one byte to end the string buffer with 0 */ + const size_t mblock_size = args->stream_memblock.size - 1; + struct gmio_stla_parse_data parse_data = {0}; + struct gmio_stringstream* sstream = &parse_data.strstream; + struct gmio_string* strbuff = &parse_data.strbuff; + char fixed_buffer[GMIO_STLA_READ_STRING_MAX_LEN]; + + int err = GMIO_ERROR_OK; + + if (flags == 0) + return err; + if (!gmio_check_memblock(&err, &args->stream_memblock)) + return err; + + parse_data.strstream = + gmio_stringstream( + args->stream, + gmio_string(mblock_ptr, 0, mblock_size)); + parse_data.strstream.func_stream_read_hook = gmio_stringstream_stla_read_hook; + parse_data.strbuff = gmio_string(fixed_buffer, 0, sizeof(fixed_buffer)); + + gmio_stringstream_skip_word(sstream); /* Skip "\s*solid" */ + gmio_stla_parse_solidname_beg(&parse_data); + if (flag_stla_solidname) { + const size_t name_len_for_cpy = + GMIO_MIN(infos->stla_solidname_maxlen, strbuff->len); + strncpy(infos->stla_solidname, strbuff->ptr, name_len_for_cpy); + /* Null terminate C string */ + if (name_len_for_cpy != 0) + infos->stla_solidname[name_len_for_cpy - 1] = 0; + else if (infos->stla_solidname_maxlen != 0) + infos->stla_solidname[0] = 0; + gmio_string_clear(strbuff); + } + + if (flag_facet_count) { + infos->facet_count = 0; + while (parse_data.token == FACET_token + && !parse_data.error + && gmio_stringstream_current_char(sstream) != NULL) + { + if (gmio_skip_facet(&parse_data) == 0) { + ++infos->facet_count; + /* Eat next unknown token */ + strbuff->len = 0; + gmio_stringstream_eat_word(sstream, strbuff); + parse_data.token = + gmio_stla_find_token(strbuff->ptr, strbuff->len); + } + } + } + + if (flag_size) { + if (flag_facet_count) { /* We should be near "endsolid" token */ + if (parse_data.token != ENDSOLID_token) + gmio_stla_eat_next_token(&parse_data, ENDSOLID_token); + } + else { + while (!gmio_stla_check_next_token(sstream, "endsolid") + && !parse_data.error + && gmio_stringstream_current_char(sstream) != NULL) + { + } + } + infos->size = parse_data.strstream_cookie.stream_offset; + infos->size += sstream->strbuff_at - strbuff->ptr; + } + + return err; +} + +#if 0 #include "../../gmio_core/error.h" #include "../../gmio_core/internal/min_max.h" #include "../../gmio_core/internal/string.h" @@ -148,3 +325,4 @@ int gmio_stla_infos_get( return err; } +#endif