gmio_stl: fix case where solid name is composed of many words
This commit is contained in:
parent
2857f5ca30
commit
26fc957569
@ -22,6 +22,7 @@
|
|||||||
#include "../gmio_core/error.h"
|
#include "../gmio_core/error.h"
|
||||||
#include "../gmio_core/internal/helper_stream.h"
|
#include "../gmio_core/internal/helper_stream.h"
|
||||||
#include "../gmio_core/internal/helper_transfer.h"
|
#include "../gmio_core/internal/helper_transfer.h"
|
||||||
|
#include "../gmio_core/internal/min_max.h"
|
||||||
#include "../gmio_core/internal/string_parse.h"
|
#include "../gmio_core/internal/string_parse.h"
|
||||||
#include "../gmio_core/internal/string_utils.h"
|
#include "../gmio_core/internal/string_utils.h"
|
||||||
|
|
||||||
@ -77,6 +78,9 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Fixed maximum length of any string_buffer user in this source file */
|
||||||
|
enum { GMIO_STLA_READ_STRING_BUFFER_LEN = 1024 };
|
||||||
|
|
||||||
/* gmio_stream_fwd_iterator_stla_cookie */
|
/* gmio_stream_fwd_iterator_stla_cookie */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -93,19 +97,19 @@ typedef struct
|
|||||||
/* gmio_stla_token */
|
/* gmio_stla_token */
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
ENDFACET_token,
|
ENDFACET_token = 0x0001,
|
||||||
ENDLOOP_token,
|
ENDLOOP_token = 0x0002,
|
||||||
ENDSOLID_token,
|
ENDSOLID_token = 0x0004,
|
||||||
FACET_token,
|
FACET_token = 0x0008,
|
||||||
ID_token,
|
ID_token = 0x0010,
|
||||||
FLOAT_token = ID_token,
|
FLOAT_token = ID_token,
|
||||||
LOOP_token,
|
LOOP_token = 0x0020,
|
||||||
NORMAL_token,
|
NORMAL_token = 0x0040,
|
||||||
OUTER_token,
|
OUTER_token = 0x0080,
|
||||||
SOLID_token,
|
SOLID_token = 0x0100,
|
||||||
VERTEX_token,
|
VERTEX_token = 0x0200,
|
||||||
empty_token,
|
empty_token = 0x0400,
|
||||||
unknown_token
|
unknown_token = 0x0800
|
||||||
} gmio_stla_token_t;
|
} gmio_stla_token_t;
|
||||||
|
|
||||||
/* gmio_stla_parse_data */
|
/* gmio_stla_parse_data */
|
||||||
@ -141,12 +145,6 @@ GMIO_INLINE gmio_bool_t parsing_can_continue(
|
|||||||
return GMIO_FALSE;
|
return GMIO_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
GMIO_INLINE const char* current_token_as_identifier(
|
|
||||||
const gmio_stla_parse_data_t* data)
|
|
||||||
{
|
|
||||||
return data->token == ID_token ? data->string_buffer.ptr : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
GMIO_INLINE int get_current_token_as_float32(
|
GMIO_INLINE int get_current_token_as_float32(
|
||||||
const gmio_stla_parse_data_t* data, gmio_float32_t* value_ptr)
|
const gmio_stla_parse_data_t* data, gmio_float32_t* value_ptr)
|
||||||
{
|
{
|
||||||
@ -206,12 +204,8 @@ GMIO_INLINE void parsing_error_token_expected(
|
|||||||
parsing_error_msg(data, msg);
|
parsing_error_msg(data, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gmio_stla_token_t parsing_find_token(
|
static gmio_stla_token_t parsing_find_token(const char* word, size_t word_len)
|
||||||
const gmio_string_buffer_t* str_buffer)
|
|
||||||
{
|
{
|
||||||
const char* word = str_buffer->ptr;
|
|
||||||
const size_t word_len = str_buffer->len;
|
|
||||||
|
|
||||||
/* Get rid of ill-formed token */
|
/* Get rid of ill-formed token */
|
||||||
if (word_len == 0)
|
if (word_len == 0)
|
||||||
return empty_token;
|
return empty_token;
|
||||||
@ -280,13 +274,20 @@ static gmio_stla_token_t parsing_find_token(
|
|||||||
return ID_token;
|
return ID_token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GMIO_INLINE gmio_stla_token_t parsing_find_token_from_buff(
|
||||||
|
const gmio_string_buffer_t* str_buffer)
|
||||||
|
{
|
||||||
|
return parsing_find_token(str_buffer->ptr, str_buffer->len);
|
||||||
|
}
|
||||||
|
|
||||||
GMIO_INLINE void parsing_advance(gmio_stla_parse_data_t* data)
|
GMIO_INLINE void parsing_advance(gmio_stla_parse_data_t* data)
|
||||||
{
|
{
|
||||||
if (!parsing_can_continue(data))
|
if (!parsing_can_continue(data))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
data->string_buffer.len = 0;
|
||||||
if (gmio_eat_word(&data->stream_iterator, &data->string_buffer) == 0)
|
if (gmio_eat_word(&data->stream_iterator, &data->string_buffer) == 0)
|
||||||
data->token = parsing_find_token(&data->string_buffer);
|
data->token = parsing_find_token_from_buff(&data->string_buffer);
|
||||||
else
|
else
|
||||||
data->token = unknown_token;
|
data->token = unknown_token;
|
||||||
|
|
||||||
@ -306,15 +307,65 @@ GMIO_INLINE void parsing_eat_token(
|
|||||||
parsing_error_token_expected(data, token);
|
parsing_error_token_expected(data, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void parse_eat_until_token(
|
||||||
|
gmio_stla_parse_data_t* data,
|
||||||
|
int end_tokens)
|
||||||
|
{
|
||||||
|
if (!parsing_can_continue(data))
|
||||||
|
return;
|
||||||
|
if ((data->token & end_tokens) == 0) {
|
||||||
|
gmio_string_stream_fwd_iterator_t* stream_it = &data->stream_iterator;
|
||||||
|
gmio_string_buffer_t* string_buf = &data->string_buffer;
|
||||||
|
int end_token_found = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
const size_t previous_buff_len = string_buf->len;
|
||||||
|
int res_eat_word = 0; /* Result of gmio_eat_word() */
|
||||||
|
const char* next_word = NULL; /* Pointer on next word string */
|
||||||
|
size_t next_word_len = 0; /* Length of next word string */
|
||||||
|
|
||||||
|
gmio_copy_spaces(stream_it, string_buf);
|
||||||
|
/* Next word */
|
||||||
|
next_word = string_buf->ptr + string_buf->len;
|
||||||
|
res_eat_word = gmio_eat_word(stream_it, string_buf);
|
||||||
|
next_word_len =
|
||||||
|
(string_buf->ptr + string_buf->len) - next_word;
|
||||||
|
/* Qualify token */
|
||||||
|
data->token =
|
||||||
|
res_eat_word == 0 ?
|
||||||
|
parsing_find_token(next_word, next_word_len) :
|
||||||
|
unknown_token;
|
||||||
|
/* End token found ? */
|
||||||
|
end_token_found = data->token & end_tokens;
|
||||||
|
/* True ?
|
||||||
|
* trim string_buf so it contains only contents before end token */
|
||||||
|
if (end_token_found) {
|
||||||
|
string_buf->len = previous_buff_len;
|
||||||
|
string_buf->ptr[previous_buff_len] = 0;
|
||||||
|
}
|
||||||
|
} while (!end_token_found && string_buf->len < string_buf->max_len);
|
||||||
|
|
||||||
|
if (!end_token_found) {
|
||||||
|
parsing_error_msg(
|
||||||
|
data,
|
||||||
|
"end token not found in parse_eat_until_token()");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void parse_solidname_beg(gmio_stla_parse_data_t* data)
|
static void parse_solidname_beg(gmio_stla_parse_data_t* data)
|
||||||
{
|
{
|
||||||
if (!parsing_can_continue(data))
|
if (!parsing_can_continue(data))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (data->token) {
|
switch (data->token) {
|
||||||
case ENDSOLID_token:
|
|
||||||
case FACET_token:
|
|
||||||
case ID_token:
|
case ID_token:
|
||||||
|
/* Solid name can be made of multiple words */
|
||||||
|
parse_eat_until_token(data, FACET_token | ENDSOLID_token);
|
||||||
|
break;
|
||||||
|
case FACET_token:
|
||||||
|
case ENDSOLID_token:
|
||||||
|
gmio_string_buffer_clear(&data->string_buffer);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
parsing_error_msg(data, "unexpected token for 'solid <name>'");
|
parsing_error_msg(data, "unexpected token for 'solid <name>'");
|
||||||
@ -349,7 +400,7 @@ static void parse_beginsolid(gmio_stla_parse_data_t* data)
|
|||||||
gmio_stl_mesh_creator_ascii_begin_solid(
|
gmio_stl_mesh_creator_ascii_begin_solid(
|
||||||
data->creator,
|
data->creator,
|
||||||
data->stream_iterator_cookie.stream_size,
|
data->stream_iterator_cookie.stream_size,
|
||||||
current_token_as_identifier(data));
|
data->string_buffer.ptr);
|
||||||
}
|
}
|
||||||
if (data->token == ID_token)
|
if (data->token == ID_token)
|
||||||
parsing_eat_token(ID_token, data);
|
parsing_eat_token(ID_token, data);
|
||||||
@ -452,8 +503,6 @@ static void parse_solid(gmio_stla_parse_data_t* data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum { GMIO_STLA_READ_STRING_BUFFER_LEN = 512 };
|
|
||||||
|
|
||||||
int gmio_stla_read(gmio_transfer_t* trsf, gmio_stl_mesh_creator_t* creator)
|
int gmio_stla_read(gmio_transfer_t* trsf, gmio_stl_mesh_creator_t* creator)
|
||||||
{
|
{
|
||||||
char fixed_buffer[GMIO_STLA_READ_STRING_BUFFER_LEN];
|
char fixed_buffer[GMIO_STLA_READ_STRING_BUFFER_LEN];
|
||||||
|
@ -22,6 +22,24 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
struct stl_testcase_result
|
||||||
|
{
|
||||||
|
char solid_name[2048];
|
||||||
|
};
|
||||||
|
typedef struct stl_testcase_result stl_testcase_result_t;
|
||||||
|
|
||||||
|
void ascii_begin_solid(
|
||||||
|
void* cookie, size_t stream_size, const char* solid_name)
|
||||||
|
{
|
||||||
|
GMIO_UNUSED(stream_size);
|
||||||
|
stl_testcase_result_t* res = (stl_testcase_result_t*)cookie;
|
||||||
|
if (res != NULL) {
|
||||||
|
res->solid_name[0] = 0;
|
||||||
|
if (solid_name != NULL)
|
||||||
|
strcpy(&res->solid_name[0], solid_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void add_triangle(
|
static void add_triangle(
|
||||||
void* cookie, uint32_t tri_id, const gmio_stl_triangle_t* triangle)
|
void* cookie, uint32_t tri_id, const gmio_stl_triangle_t* triangle)
|
||||||
{
|
{
|
||||||
@ -30,35 +48,102 @@ static void add_triangle(
|
|||||||
GMIO_UNUSED(triangle);
|
GMIO_UNUSED(triangle);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct filepath_errorcode
|
struct stl_testcase
|
||||||
{
|
{
|
||||||
const char* filepath;
|
const char* filepath;
|
||||||
int errorcode;
|
int errorcode;
|
||||||
|
gmio_stl_format_t format;
|
||||||
|
const char* solid_name;
|
||||||
};
|
};
|
||||||
typedef struct filepath_errorcode filepath_errorcode_t;
|
typedef struct stl_testcase stl_testcase;
|
||||||
|
|
||||||
const char* test_stl_read()
|
const char* test_stl_read()
|
||||||
{
|
{
|
||||||
const filepath_errorcode_t expected[] = {
|
const stl_testcase expected[] = {
|
||||||
{ "tests/models/file_empty", GMIO_STL_ERROR_UNKNOWN_FORMAT },
|
{ "tests/models/file_empty",
|
||||||
{ "tests/models/solid_4vertex.stla", GMIO_STL_ERROR_PARSING },
|
GMIO_STL_ERROR_UNKNOWN_FORMAT,
|
||||||
{ "tests/models/solid_anonymous_empty.stla", GMIO_ERROR_OK },
|
GMIO_STL_FORMAT_UNKNOWN,
|
||||||
{ "tests/models/solid_empty.stla", GMIO_ERROR_OK },
|
NULL
|
||||||
{ "tests/models/solid_empty.stlb", GMIO_ERROR_OK },
|
},
|
||||||
{ "tests/models/solid_lack_z.stla", GMIO_STL_ERROR_PARSING },
|
{ "tests/models/solid_4vertex.stla",
|
||||||
{ "tests/models/solid_one_facet.stla", GMIO_ERROR_OK },
|
GMIO_STL_ERROR_PARSING,
|
||||||
{ "tests/models/solid_one_facet.le_stlb", GMIO_ERROR_OK },
|
GMIO_STL_FORMAT_ASCII,
|
||||||
{ "tests/models/solid_one_facet_uppercase.stla", GMIO_ERROR_OK }
|
NULL
|
||||||
|
},
|
||||||
|
{ "tests/models/solid_anonymous_empty.stla",
|
||||||
|
GMIO_ERROR_OK,
|
||||||
|
GMIO_STL_FORMAT_ASCII,
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
{ "tests/models/solid_empty.stla",
|
||||||
|
GMIO_ERROR_OK,
|
||||||
|
GMIO_STL_FORMAT_ASCII,
|
||||||
|
"emptysolid"
|
||||||
|
},
|
||||||
|
{ "tests/models/solid_empty.stlb",
|
||||||
|
GMIO_ERROR_OK,
|
||||||
|
GMIO_STL_FORMAT_BINARY_LE,
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
{ "tests/models/solid_empty_name_many_words.stla",
|
||||||
|
GMIO_ERROR_OK,
|
||||||
|
GMIO_STL_FORMAT_ASCII,
|
||||||
|
"name with multiple words"
|
||||||
|
},
|
||||||
|
{ "tests/models/solid_empty_name_many_words_single_letters.stla",
|
||||||
|
GMIO_ERROR_OK,
|
||||||
|
GMIO_STL_FORMAT_ASCII,
|
||||||
|
"a b c d e f\t\tg h"
|
||||||
|
},
|
||||||
|
{ "tests/models/solid_lack_z.stla",
|
||||||
|
GMIO_STL_ERROR_PARSING,
|
||||||
|
GMIO_STL_FORMAT_ASCII,
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
{ "tests/models/solid_one_facet.stla",
|
||||||
|
GMIO_ERROR_OK,
|
||||||
|
GMIO_STL_FORMAT_ASCII,
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
{ "tests/models/solid_one_facet.le_stlb",
|
||||||
|
GMIO_ERROR_OK,
|
||||||
|
GMIO_STL_FORMAT_BINARY_LE,
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
{ "tests/models/solid_one_facet_uppercase.stla",
|
||||||
|
GMIO_ERROR_OK,
|
||||||
|
GMIO_STL_FORMAT_ASCII,
|
||||||
|
NULL
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const size_t expected_count =
|
const size_t expected_count =
|
||||||
sizeof(expected) / sizeof(filepath_errorcode_t);
|
sizeof(expected) / sizeof(stl_testcase);
|
||||||
size_t i; /* for loop counter */
|
size_t i; /* for loop counter */
|
||||||
gmio_stl_mesh_creator_t meshc = {0};
|
gmio_stl_mesh_creator_t meshc = {0};
|
||||||
|
stl_testcase_result_t result = {0};
|
||||||
|
|
||||||
|
meshc.cookie = &result;
|
||||||
|
meshc.ascii_begin_solid_func = &ascii_begin_solid;
|
||||||
meshc.add_triangle_func = &add_triangle;
|
meshc.add_triangle_func = &add_triangle;
|
||||||
|
|
||||||
for (i = 0; i < expected_count; ++i) {
|
for (i = 0; i < expected_count; ++i) {
|
||||||
const int err = gmio_stl_read_file(expected[i].filepath, &meshc, NULL);
|
const gmio_stl_format_t format =
|
||||||
|
gmio_stl_get_format_file(expected[i].filepath);
|
||||||
|
const int err =
|
||||||
|
gmio_stl_read_file(expected[i].filepath, &meshc, NULL);
|
||||||
|
|
||||||
|
/* Check format */
|
||||||
|
if (format != expected[i].format) {
|
||||||
|
printf("\nfilepath : %s\n"
|
||||||
|
"expected format : %d\n"
|
||||||
|
"actual format : %d\n",
|
||||||
|
expected[i].filepath,
|
||||||
|
expected[i].format,
|
||||||
|
format);
|
||||||
|
}
|
||||||
|
UTEST_ASSERT(format == expected[i].format);
|
||||||
|
|
||||||
|
/* Check error code */
|
||||||
if (err != expected[i].errorcode) {
|
if (err != expected[i].errorcode) {
|
||||||
printf("\nfilepath : %s\n"
|
printf("\nfilepath : %s\n"
|
||||||
"expected error : 0x%x\n"
|
"expected error : 0x%x\n"
|
||||||
@ -68,12 +153,26 @@ const char* test_stl_read()
|
|||||||
err);
|
err);
|
||||||
}
|
}
|
||||||
UTEST_ASSERT(err == expected[i].errorcode);
|
UTEST_ASSERT(err == expected[i].errorcode);
|
||||||
|
|
||||||
|
/* Check solid name */
|
||||||
|
if (expected[i].format == GMIO_STL_FORMAT_ASCII) {
|
||||||
|
const char* expected_name =
|
||||||
|
expected[i].solid_name != NULL ? expected[i].solid_name : "";
|
||||||
|
if (strcmp(result.solid_name, expected_name) != 0) {
|
||||||
|
printf("\nfilepath : %s\n"
|
||||||
|
"expected solidname : %s\n"
|
||||||
|
"actual solidname : %s\n",
|
||||||
|
expected[i].filepath,
|
||||||
|
expected_name,
|
||||||
|
result.solid_name);
|
||||||
|
}
|
||||||
|
UTEST_ASSERT(strcmp(result.solid_name, expected_name) == 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct stl_triangle_array
|
struct stl_triangle_array
|
||||||
{
|
{
|
||||||
gmio_stl_triangle_t* ptr;
|
gmio_stl_triangle_t* ptr;
|
||||||
|
Loading…
Reference in New Issue
Block a user