From b7bceff74891cf2682f4dfb81e4901d49d3bcc77 Mon Sep 17 00:00:00 2001 From: Hugues Delorme Date: Wed, 3 Feb 2016 11:43:52 +0100 Subject: [PATCH] gmio_stl: simplify code of gmio_stla_infos_get() --- benchmarks/benchmark_gmio/main.c | 32 +++- src/gmio_stl/internal/stla_infos_get.c | 205 ++++++++++++------------- tests/test_stl_infos.c | 41 +++-- 3 files changed, 153 insertions(+), 125 deletions(-) diff --git a/benchmarks/benchmark_gmio/main.c b/benchmarks/benchmark_gmio/main.c index 6d223e4..0d4b0d5 100644 --- a/benchmarks/benchmark_gmio/main.c +++ b/benchmarks/benchmark_gmio/main.c @@ -214,7 +214,7 @@ static void bmk_gmio_stl_readwrite_conv(const void* filepath) fclose(outfile); } -void bmk_gmio_stl_infos_get(const void* filepath) +void bmk_gmio_stl_infos_get_all(const void* filepath) { static bool already_exec = false; FILE* file = fopen(filepath, "rb"); @@ -225,7 +225,7 @@ void bmk_gmio_stl_infos_get(const void* filepath) gmio_stl_infos_get(&infos, stream, GMIO_STL_INFO_FLAG_ALL, NULL); if (!already_exec) { - printf("stl_infos_get()\n" + printf("stl_infos_get(ALL)\n" " File: %s\n" " Size: %uKo\n" " Facets: %u\n", @@ -247,6 +247,29 @@ void bmk_gmio_stl_infos_get(const void* filepath) fclose(file); } +void bmk_gmio_stl_infos_get_size(const void* filepath) +{ + static bool already_exec = false; + FILE* file = fopen(filepath, "rb"); + + if (file != NULL) { + const struct gmio_stream stream = gmio_stream_stdio(file); + struct gmio_stl_infos infos = {0}; + gmio_stl_infos_get(&infos, stream, GMIO_STL_INFO_FLAG_SIZE, NULL); + + if (!already_exec) { + printf("stl_infos_get(SIZE)\n" + " File: %s\n" + " Size: %uKo\n", + (const char*)filepath, + infos.size / 1024); + } + already_exec = true; + } + + fclose(file); +} + int main(int argc, char** argv) { if (argc > 1) { @@ -261,7 +284,10 @@ int main(int argc, char** argv) bmk_gmio_stl_readwrite_conv, NULL, NULL, NULL }, { "stl_infos_get(ALL)", - bmk_gmio_stl_infos_get, NULL, + bmk_gmio_stl_infos_get_all, NULL, + NULL, NULL }, + { "stl_infos_get(size)", + bmk_gmio_stl_infos_get_size, NULL, NULL, NULL }, {0} }; diff --git a/src/gmio_stl/internal/stla_infos_get.c b/src/gmio_stl/internal/stla_infos_get.c index 4f2577f..a7dcb19 100644 --- a/src/gmio_stl/internal/stla_infos_get.c +++ b/src/gmio_stl/internal/stla_infos_get.c @@ -25,6 +25,7 @@ #include +/* Skip characters until an ASCII space is met */ static const char* gmio_stringstream_skip_until_ascii_space( struct gmio_stringstream* sstream) { @@ -34,79 +35,27 @@ static const char* gmio_stringstream_skip_until_ascii_space( return curr_char; } -static const char* gmio_stringstream_skip_word( - struct gmio_stringstream* sstream) +/* Eats \p str case-insensitive, stops on any difference */ +static bool gmio_stringstream_icase_eat( + struct gmio_stringstream* sstream, const char* str) { - 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; + const char* c = gmio_stringstream_next_char(sstream); + while (c != NULL && *str != 0) { + if (!gmio_ascii_char_iequals(*c, *str)) + return false; + c = gmio_stringstream_next_char(sstream); + ++str; } - gmio_stringstream_skip_word(sstream); - return 0; + return *str == 0; } -static void gmio_stringstream_stla_read_hook( +/* Callback invoked by gmio_stringstream */ +static void gmio_stringstream_update_streamsize( 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; + gmio_streamsize_t* ptr_size = (gmio_streamsize_t*)(cookie); + if (ptr_size != NULL) + *ptr_size += strbuff->len; } int gmio_stla_infos_get( @@ -123,13 +72,9 @@ int gmio_stla_infos_get( (flags & GMIO_STLA_INFO_FLAG_SOLIDNAME) != 0; void* const mblock_ptr = opts->stream_memblock.ptr; - /* Leave one byte to end the string buffer with 0 */ + /* Leave one byte to end of string buffer */ const size_t mblock_size = opts->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]; - + struct gmio_stringstream sstream = {0}; int err = GMIO_ERROR_OK; if (flags == 0) @@ -137,56 +82,96 @@ int gmio_stla_infos_get( if (!gmio_check_memblock(&err, &opts->stream_memblock)) return err; - parse_data.strstream = - gmio_stringstream(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)); + /* Initialize string stream */ + sstream.stream = stream; + sstream.strbuff = gmio_string(mblock_ptr, 0, mblock_size); + if (flag_size) { + infos->size = 0; + sstream.cookie = &infos->size; + sstream.func_stream_read_hook = gmio_stringstream_update_streamsize; + } + gmio_stringstream_init_pos(&sstream); - 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); + struct gmio_stla_parse_data parse_data = {0}; + const struct gmio_string* strbuff = &parse_data.strbuff; + char fixed_buffer[GMIO_STLA_READ_STRING_MAX_LEN] = {0}; + + parse_data.strstream = sstream; + parse_data.strbuff = gmio_string(fixed_buffer, 0, sizeof(fixed_buffer)); + + /* Skip "\s*solid" */ + gmio_stringstream_skip_ascii_spaces(&parse_data.strstream); + gmio_stringstream_skip_until_ascii_space(&parse_data.strstream); + + /* Eat solid name */ + gmio_stla_parse_solidname_beg(&parse_data); + + /* Copy parsed solid name into infos->stla_solid_name */ + { + const size_t name_len_for_cpy = + GMIO_MIN(infos->stla_solidname_maxlen - 1, 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] = 0; + else if (infos->stla_solidname_maxlen != 0) + infos->stla_solidname[0] = 0; + } + sstream = parse_data.strstream; } if (flag_facet_count) { + bool endfound = false; + 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); + + while (!endfound) { + const char* c = gmio_stringstream_skip_ascii_spaces(&sstream); + if (c != NULL) { + if (gmio_ascii_char_iequals(*c, 'f')) { + if (gmio_stringstream_icase_eat(&sstream, "acet")) + ++infos->facet_count; + } + else { + endfound = + gmio_ascii_char_iequals(*c, 'e') + && gmio_stringstream_icase_eat(&sstream, "ndsolid"); + } } + else { + endfound = true; + } + gmio_stringstream_skip_until_ascii_space(&sstream); } } 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) - { + /* On case flag_facet_count is on, we should already be after "endsolid" + * token */ + if (!flag_facet_count) { + bool endfound = false; + while (!endfound) { + const char* c = gmio_stringstream_skip_ascii_spaces(&sstream); + if (c != NULL) { + endfound = + gmio_ascii_char_iequals(*c, 'e') + && gmio_stringstream_icase_eat(&sstream, "ndsolid"); + } + else { + endfound = true; + } + gmio_stringstream_skip_until_ascii_space(&sstream); } } - infos->size = parse_data.strstream_cookie.stream_offset; - infos->size += sstream->strbuff_at - strbuff->ptr; + { /* Eat whole line */ + const char* c = gmio_stringstream_current_char(&sstream); + while (c != NULL && *c != '\n' && *c != '\r') + c = gmio_stringstream_next_char(&sstream); + } + infos->size -= sstream.strbuff_end - sstream.strbuff_at; + infos->size = GMIO_MAX(0, infos->size); } return err; diff --git a/tests/test_stl_infos.c b/tests/test_stl_infos.c index faf6ca5..1d34277 100644 --- a/tests/test_stl_infos.c +++ b/tests/test_stl_infos.c @@ -26,35 +26,39 @@ struct gmio_test_stl_infos const char* filepath; enum gmio_stl_format format; uint32_t expected_facet_count; - gmio_streamsize_t expected_size; /* -2: don't check size - * -1: check against actual file size */ + gmio_streamsize_t expected_size; /* -1: check against actual file size */ }; static const struct gmio_test_stl_infos tests[] = { { "models/file_empty", GMIO_STL_FORMAT_UNKNOWN, 0, 0 }, - { "models/solid_4vertex.stla", GMIO_STL_FORMAT_ASCII, 1, -2 }, - { "models/solid_anonymous_empty.stla", GMIO_STL_FORMAT_ASCII, 0, -2 }, - { "models/solid_empty.stla", GMIO_STL_FORMAT_ASCII, 0, -2 }, + { "models/solid_4vertex.stla", GMIO_STL_FORMAT_ASCII, 1, -1 }, + { "models/solid_anonymous_empty.stla", GMIO_STL_FORMAT_ASCII, 0, -1 }, + { "models/solid_empty.stla", GMIO_STL_FORMAT_ASCII, 0, -1 }, { "models/solid_empty.stlb", GMIO_STL_FORMAT_BINARY_LE, 0, -1 }, - { "models/solid_empty_name_many_words.stla", GMIO_STL_FORMAT_ASCII, 0, -2 }, - { "models/solid_empty_name_many_words_single_letters.stla", GMIO_STL_FORMAT_ASCII, 0, -2 }, + { "models/solid_empty_name_many_words.stla", GMIO_STL_FORMAT_ASCII, 0, -1 }, + { "models/solid_empty_name_many_words_single_letters.stla", GMIO_STL_FORMAT_ASCII, 0, -1 }, { "models/solid_grabcad_arm11_link0_hb.le_stlb", GMIO_STL_FORMAT_BINARY_LE, 1436, -1 }, - { "models/solid_jburkardt_sphere.stla", GMIO_STL_FORMAT_ASCII, 228, -2 }, - { "models/solid_lack_z.stla", GMIO_STL_FORMAT_ASCII, 1, -2 }, + { "models/solid_jburkardt_sphere.stla", GMIO_STL_FORMAT_ASCII, 228, -1 }, + { "models/solid_lack_z.stla", GMIO_STL_FORMAT_ASCII, 1, -1 }, { "models/solid_one_facet.be_stlb", GMIO_STL_FORMAT_BINARY_BE, 1, -1 }, { "models/solid_one_facet.le_stlb", GMIO_STL_FORMAT_BINARY_LE, 1, -1 }, - { "models/solid_one_facet.stla", GMIO_STL_FORMAT_ASCII, 1, -2 }, - { "models/solid_one_facet_uppercase.stla", GMIO_STL_FORMAT_ASCII, 1, -2 } + { "models/solid_one_facet.stla", GMIO_STL_FORMAT_ASCII, 1, -1 }, + { "models/solid_one_facet_uppercase.stla", GMIO_STL_FORMAT_ASCII, 1, -1 } }; const char* generic_test_stl_infos(const struct gmio_test_stl_infos* test) { FILE* file = fopen(test->filepath, "rb"); gmio_streamsize_t expected_size = test->expected_size; + char stla_solid_name[512] = {0}; struct gmio_stl_infos infos = {0}; struct gmio_stream stream = gmio_stream_stdio(file); int error = GMIO_ERROR_OK; + puts(test->filepath); + + infos.stla_solidname = stla_solid_name; + infos.stla_solidname_maxlen = sizeof(stla_solid_name) - 1; error = gmio_stl_infos_get(&infos, stream, GMIO_STL_INFO_FLAG_ALL, NULL); if (test->format != GMIO_STL_FORMAT_UNKNOWN) { UTEST_COMPARE_INT(GMIO_ERROR_OK, error); @@ -68,8 +72,21 @@ const char* generic_test_stl_infos(const struct gmio_test_stl_infos* test) fclose(file); - if (test->expected_size != -2) + if (test->format == GMIO_STL_FORMAT_ASCII) { + const size_t name_len = strlen(stla_solid_name); +#if 0 + printf("expected_size=%d " + "name_len=%d " + "infos.size=%d " + "infos.solid_name=%s\n", + expected_size, name_len, infos.size, infos.stla_solidname); +#endif + UTEST_ASSERT((expected_size - name_len) <= infos.size); + UTEST_ASSERT(infos.size <= (expected_size + name_len)); + } + else { UTEST_COMPARE_INT(expected_size, infos.size); + } return NULL; }