diff --git a/src/internal/ascii_parse.c b/src/internal/ascii_parse.c index f3ae414..1252862 100644 --- a/src/internal/ascii_parse.c +++ b/src/internal/ascii_parse.c @@ -4,10 +4,20 @@ #include #include +void foug_ascii_stream_fwd_iterator_init(foug_ascii_stream_fwd_iterator_t *it) +{ + /* Trick: declaring the buffer exhausted will actually trigger the first call to + * foug_stream_read() inside foug_next_char() + */ + it->buffer.len = 0; + it->buffer_pos = it->buffer.max_len; + foug_next_char(it); +} + char *foug_current_char(foug_ascii_stream_fwd_iterator_t *it) { - if (it != NULL && it->buffer_offset < it->buffer_size) - return it->buffer + it->buffer_offset; + if (it != NULL && it->buffer_pos < it->buffer.len) + return it->buffer.ptr + it->buffer_pos; return NULL; } @@ -16,35 +26,25 @@ char *foug_next_char(foug_ascii_stream_fwd_iterator_t *it) if (it == NULL) return NULL; - if ((it->buffer_offset + 1) < it->buffer_size) { - ++(it->buffer_offset); - return it->buffer + it->buffer_offset; + if ((it->buffer_pos + 1) < it->buffer.len) { + ++(it->buffer_pos); + return it->buffer.ptr + it->buffer_pos; } else { - size_t char_count_read; - if (foug_stream_error(it->stream) != 0 || foug_stream_at_end(it->stream)) return NULL; /* Read next chunk of data */ - char_count_read = foug_stream_read(it->stream, it->buffer, sizeof(char), it->buffer_size); - if (foug_stream_error(it->stream) != 0) { - return NULL; - } - else { - it->buffer_offset = 0; - it->buffer_size = char_count_read; + it->buffer_pos = 0; + it->buffer.len = foug_stream_read(it->stream, it->buffer.ptr, sizeof(char), it->buffer.max_len); + if (foug_stream_error(it->stream) == 0) { if (it->stream_read_hook != NULL) - it->stream_read_hook(it->cookie, it->buffer, it->buffer_size); - return it->buffer; + it->stream_read_hook(it->cookie, &it->buffer); + return it->buffer.ptr; } } -} -void foug_stream_fwd_iterator_init(foug_ascii_stream_fwd_iterator_t *it) -{ - it->buffer_offset = it->buffer_size; /* This will cause the first call to foug_stream_read() */ - foug_next_char(it); + return NULL; } void foug_skip_spaces(foug_ascii_stream_fwd_iterator_t *it) @@ -54,31 +54,31 @@ void foug_skip_spaces(foug_ascii_stream_fwd_iterator_t *it) curr_char = foug_next_char(it); } -int foug_eat_string(foug_ascii_stream_fwd_iterator_t *it, foug_ascii_string_buffer_t *str_buffer) +int foug_eat_word(foug_ascii_stream_fwd_iterator_t *it, foug_ascii_string_buffer_t *buffer) { const char* stream_curr_char = NULL; int isspace_res = 0; size_t i = 0; - if (str_buffer == NULL || str_buffer->data == NULL || str_buffer->max_len == 0) + if (buffer == NULL || buffer->ptr == NULL) return -1; - str_buffer->len = 0; + buffer->len = 0; foug_skip_spaces(it); stream_curr_char = foug_current_char(it); - while (i < str_buffer->max_len && stream_curr_char != NULL && isspace_res == 0) { + while (i < buffer->max_len && stream_curr_char != NULL && isspace_res == 0) { isspace_res = isspace(*stream_curr_char); if (isspace_res == 0) { - str_buffer->data[i] = *stream_curr_char; + buffer->ptr[i] = *stream_curr_char; stream_curr_char = foug_next_char(it); ++i; } } - if (i < str_buffer->max_len) { - str_buffer->data[i] = 0; /* End string with null terminator */ - str_buffer->len = i ; + if (i < buffer->max_len) { + buffer->ptr[i] = 0; /* End string with terminating null byte */ + buffer->len = i; if (stream_curr_char != NULL || foug_stream_at_end(it->stream)) return 0; return -2; diff --git a/src/internal/ascii_parse.h b/src/internal/ascii_parse.h index f3d52b8..8de967e 100644 --- a/src/internal/ascii_parse.h +++ b/src/internal/ascii_parse.h @@ -6,27 +6,26 @@ typedef struct { - foug_stream_t* stream; - char* buffer; - uint32_t buffer_offset; - uint32_t buffer_size; - - void* cookie; - void (*stream_read_hook)(void*, const char*, uint32_t); -} foug_ascii_stream_fwd_iterator_t; + char* ptr; /*!< Buffer contents */ + size_t len; /*!< Size(length) of current contents */ + size_t max_len; /*!< Maximum contents size(length) */ +} foug_ascii_string_buffer_t; typedef struct { - char* data; - size_t max_len; - size_t len; -} foug_ascii_string_buffer_t; + foug_stream_t* stream; + foug_ascii_string_buffer_t buffer; + size_t buffer_pos; /*!< Position indicator in buffer */ + + void* cookie; + void (*stream_read_hook)(void*, const foug_ascii_string_buffer_t*); +} foug_ascii_stream_fwd_iterator_t; void foug_ascii_stream_fwd_iterator_init(foug_ascii_stream_fwd_iterator_t* it); char* foug_current_char(foug_ascii_stream_fwd_iterator_t* it); char* foug_next_char(foug_ascii_stream_fwd_iterator_t* it); void foug_skip_spaces(foug_ascii_stream_fwd_iterator_t* it); -int foug_eat_string(foug_ascii_stream_fwd_iterator_t* it, foug_ascii_string_buffer_t* str_buffer); +int foug_eat_word(foug_ascii_stream_fwd_iterator_t* it, foug_ascii_string_buffer_t* buffer); int foug_get_real32(const char* str, foug_real32_t* value_ptr); #endif /* FOUG_INTERNAL_ASCII_PARSE_H */ diff --git a/src/libstl/stla_read.c b/src/libstl/stla_read.c index 79499dc..d3249af 100644 --- a/src/libstl/stla_read.c +++ b/src/libstl/stla_read.c @@ -4,6 +4,7 @@ #include "../internal/ascii_parse.h" #include +#include #include /* @@ -59,7 +60,7 @@ typedef struct size_t stream_data_size; size_t stream_offset; foug_bool_t is_stop_requested; -} foug_stream_fwd_iterator_stla_cookie_t; +} _internal_foug_fwd_iterator_cookie_t; /* foug_stla_token */ typedef enum @@ -83,21 +84,20 @@ typedef struct { foug_stla_token_t token; foug_bool_t error; - foug_ascii_stream_fwd_iterator_t stream_iterator; - foug_stream_fwd_iterator_stla_cookie_t stream_iterator_cookie; - foug_ascii_string_buffer_t string_buffer; - foug_stla_geom_input_t* geom; + foug_ascii_stream_fwd_iterator_t stream_iterator; + _internal_foug_fwd_iterator_cookie_t stream_iterator_cookie; + foug_ascii_string_buffer_t string_buffer; + foug_stla_geom_input_t* geom; } foug_stla_parse_data_t; static void foug_stream_fwd_iterator_stla_read_hook(void* cookie, - const char* buffer, - uint32_t buffer_len) + const foug_ascii_string_buffer_t* buffer) { - foug_stream_fwd_iterator_stla_cookie_t* tcookie = (foug_stream_fwd_iterator_stla_cookie_t*)(cookie); + _internal_foug_fwd_iterator_cookie_t* tcookie = (_internal_foug_fwd_iterator_cookie_t*)(cookie); if (tcookie != NULL) { const uint8_t progress_pc = foug_percentage(0, tcookie->stream_data_size, tcookie->stream_offset); tcookie->is_stop_requested = !foug_task_control_handle_progress(tcookie->task_control, progress_pc); - tcookie->stream_offset += buffer_len; + tcookie->stream_offset += buffer->len; } } @@ -110,13 +110,13 @@ foug_bool_t parsing_can_continue(const foug_stla_parse_data_t* data) static const char* current_token_as_identifier(const foug_stla_parse_data_t* data) { - return data->token == ID_token ? data->string_buffer.data : ""; + return data->token == ID_token ? data->string_buffer.ptr : ""; } -static int get_current_token_as_real32(const foug_stla_parse_data_t* data, foug_real32_t* value) +static int get_current_token_as_real32(const foug_stla_parse_data_t* data, foug_real32_t* value_ptr) { if (data->token == FLOAT_token) - return foug_get_real32(data->string_buffer.data, value); + return foug_get_real32(data->string_buffer.ptr, value_ptr); return -3; } @@ -128,57 +128,57 @@ static void parsing_error(foug_stla_parse_data_t* data) static void parsing_advance(foug_stla_parse_data_t* data) { - const char* str = data->string_buffer.data; + const char* word = data->string_buffer.ptr; if (!parsing_can_continue(data)) return; data->token = unknown_token; - if (foug_eat_string(&data->stream_iterator, &data->string_buffer) == 0) { - const size_t str_len = data->string_buffer.len; + if (foug_eat_word(&data->stream_iterator, &data->string_buffer) == 0) { + const size_t word_len = data->string_buffer.len; - if (str_len >= 7 && strncmp(str, "end", 3) == 0) { /* Might be "end..." token */ - switch (str[3]) { + if (word_len >= 7 && strncmp(word, "end", 3) == 0) { /* Might be "end..." token */ + switch (word[3]) { case 'f': - if (strcmp(str + 4, "acet") == 0) + if (strcmp(word + 4, "acet") == 0) data->token = ENDFACET_token; break; case 'l': - if (strcmp(str + 4, "oop") == 0) + if (strcmp(word + 4, "oop") == 0) data->token = ENDLOOP_token; break; case 's': - if (strcmp(str + 4, "olid") == 0) + if (strcmp(word + 4, "olid") == 0) data->token = ENDSOLID_token; break; default: data->token = ID_token; } /* end switch */ } - else if (str_len >= 4) { - switch (str[0]) { + else if (word_len >= 4) { + switch (word[0]) { case 'f': - if (strcmp(str + 1, "acet") == 0) + if (strcmp(word + 1, "acet") == 0) data->token = FACET_token; break; case 'l': - if (strcmp(str + 1, "oop") == 0) + if (strcmp(word + 1, "oop") == 0) data->token = LOOP_token; break; case 'n': - if (strcmp(str + 1, "ormal") == 0) + if (strcmp(word + 1, "ormal") == 0) data->token = NORMAL_token; break; case 'o': - if (strcmp(str + 1, "uter") == 0) + if (strcmp(word + 1, "uter") == 0) data->token = OUTER_token; break; case 's': - if (strcmp(str + 1, "olid") == 0) + if (strcmp(word + 1, "olid") == 0) data->token = SOLID_token; break; case 'v': - if (strcmp(str + 1, "ertex") == 0) + if (strcmp(word + 1, "ertex") == 0) data->token = VERTEX_token; break; default: @@ -187,7 +187,7 @@ static void parsing_advance(foug_stla_parse_data_t* data) } if (data->token == unknown_token) { - if (str[0] == '+' || str[0] == '-' || isdigit(str[0])) /* Try to guess if it's a float */ + if (word[0] == '+' || word[0] == '-' || isdigit(word[0])) /* Try to guess if it's a float */ data->token = FLOAT_token; else data->token = ID_token; @@ -302,47 +302,37 @@ static void parse_xyz_coords(foug_stla_parse_data_t* data, foug_stl_coords_t* co } /* end switch */ } -static void parse_facets(foug_stla_parse_data_t* data, size_t i_facet_offset) +static void parse_facet(foug_stla_parse_data_t* data, foug_stl_triangle_t* facet) { - if (!parsing_can_continue(data)) - return; + parsing_eat_token(FACET_token, data); + parsing_eat_token(NORMAL_token, data); + parse_xyz_coords(data, &facet->normal); - switch (data->token) { - case ENDSOLID_token: - break; - case FACET_token: { - foug_stl_triangle_t facet; + parsing_eat_token(OUTER_token, data); + parsing_eat_token(LOOP_token, data); - parsing_eat_token(FACET_token, data); - parsing_eat_token(NORMAL_token, data); - parse_xyz_coords(data, &facet.normal); + parsing_eat_token(VERTEX_token, data); + parse_xyz_coords(data, &facet->v1); + parsing_eat_token(VERTEX_token, data); + parse_xyz_coords(data, &facet->v2); + parsing_eat_token(VERTEX_token, data); + parse_xyz_coords(data, &facet->v3); - parsing_eat_token(OUTER_token, data); - parsing_eat_token(LOOP_token, data); + parsing_eat_token(ENDLOOP_token, data); + parsing_eat_token(ENDFACET_token, data); +} - parsing_eat_token(VERTEX_token, data); - parse_xyz_coords(data, &facet.v1); - parsing_eat_token(VERTEX_token, data); - parse_xyz_coords(data, &facet.v2); - parsing_eat_token(VERTEX_token, data); - parse_xyz_coords(data, &facet.v3); +static void parse_facets(foug_stla_parse_data_t* data) +{ + uint32_t i_facet_offset = 0; + foug_stl_triangle_t facet; - parsing_eat_token(ENDLOOP_token, data); - parsing_eat_token(ENDFACET_token, data); - - if (parsing_can_continue(data) - && data->geom != NULL - && data->geom->process_triangle_func != NULL) - { + while (data->token == FACET_token && parsing_can_continue(data)) { + parse_facet(data, &facet); + if (data->geom != NULL && data->geom->process_triangle_func != NULL) data->geom->process_triangle_func(data->geom->cookie, i_facet_offset, &facet); - } - - parse_facets(data, i_facet_offset + 1); - break; + ++i_facet_offset; } - default: - parsing_error(data); - } /* end switch */ } static void parse_solid(foug_stla_parse_data_t* data) @@ -350,13 +340,12 @@ static void parse_solid(foug_stla_parse_data_t* data) if (!parsing_can_continue(data)) return; - switch (data->token) { - case SOLID_token: + if (data->token == SOLID_token) { parse_beginsolid(data); - parse_facets(data, 0); + parse_facets(data); parse_endsolid(data); - break; - default: + } + else { parsing_error(data); } } @@ -386,16 +375,15 @@ int foug_stla_read(foug_stla_geom_input_t* geom, parse_data.stream_iterator_cookie.is_stop_requested = 0; parse_data.stream_iterator.stream = &trsf->stream; - parse_data.stream_iterator.buffer = trsf->buffer; - parse_data.stream_iterator.buffer_offset = 0; - parse_data.stream_iterator.buffer_size = trsf->buffer_size; + parse_data.stream_iterator.buffer.ptr = trsf->buffer; + parse_data.stream_iterator.buffer.max_len = trsf->buffer_size; parse_data.stream_iterator.cookie = &parse_data.stream_iterator_cookie; parse_data.stream_iterator.stream_read_hook = foug_stream_fwd_iterator_stla_read_hook; foug_ascii_stream_fwd_iterator_init(&parse_data.stream_iterator); - parse_data.string_buffer.data = fixed_buffer; - parse_data.string_buffer.max_len = FOUG_STLA_READ_STRING_BUFFER_LEN; + parse_data.string_buffer.ptr = &fixed_buffer[0]; parse_data.string_buffer.len = 0; + parse_data.string_buffer.max_len = FOUG_STLA_READ_STRING_BUFFER_LEN; parse_data.geom = geom;