commit 2ece078a8792331f46aab354dc134266fabe6835
parent 359302006508ab1e516f930cef2525eeab07d8b4
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Mon, 24 Feb 2025 16:26:38 +0100
Merge branch 'release_0.5.1_r1' into develop
Diffstat:
4 files changed, 88 insertions(+), 47 deletions(-)
diff --git a/README.md b/README.md
@@ -18,6 +18,8 @@ Edit config.mk as needed, then run:
## Release notes
### Version 0.5.1
+- Fix issues when reading on stdin
+- Add a warning if trailing chars detected after the solid in ascii files.
- Add the read data type in the descriptor.
- Fix a false error log message (should have been an information message).
diff --git a/src/sstl.c b/src/sstl.c
@@ -28,6 +28,7 @@
#include <string.h>
#include <stdio.h>
+#include <ctype.h>
#ifdef COMPILER_CL
#pragma warning(push)
@@ -44,12 +45,19 @@ enum allowed_load_steps {
TRY_READ_ALL = 3
};
+enum read_type {
+ STARTED_ASCII = BIT(0),
+ STARTED_BIN = BIT(1),
+ OK_ASCII = BIT(2),
+ OK_BINARY = BIT(3)
+};
+
struct solid {
char* name;
unsigned* indices;
float* vertices;
float* normals;
- enum sstl_read_type read_type;
+ enum read_type read_type;
};
static const struct solid SOLID_NULL = { NULL, NULL, NULL, NULL, 0 };
@@ -125,12 +133,13 @@ streamer_release(struct streamer* streamer)
static char*
streamer_read_line
(struct streamer* streamer,
- int checking_solid)
+ int checking_solid,
+ size_t* count)
{
const size_t buf_chunk = 256;
- size_t read_sz;
+ size_t read_sz, read_count = 0;
char* line;
- ASSERT(streamer);
+ ASSERT(streamer && count);
if(checking_solid) {
size_t current = sa_size(streamer->buf);
@@ -147,6 +156,7 @@ streamer_read_line
for(;(line=fgets(streamer->buf, (int)read_sz, streamer->stream));
++streamer->iline) {
+ size_t l;
/* If checking for a line starting with "solid", stop reading early if the
* line does not. If no error, ensure that the whole line is read */
@@ -155,6 +165,9 @@ streamer_read_line
size_t remain_sz;
if(checking_solid) {
if(0 != strncmp("solid", line, 5)) {
+ l = strlen(line);
+ read_count += l;
+ *count = read_count;
/* Dont read further */
return line;
}
@@ -176,7 +189,9 @@ streamer_read_line
checking_solid = 0;
}
- if(strspn(streamer->buf, " \t\r\n") != strlen(streamer->buf)) { /* Not empty */
+ l = strlen(streamer->buf);
+ read_count += l;
+ if(strspn(streamer->buf, " \t\r\n") != l) { /* Not empty */
/* Remove newline character(s) */
size_t last_char = strlen(line);
while(last_char-- && (line[last_char]=='\n' || line[last_char]=='\r'));
@@ -185,6 +200,7 @@ streamer_read_line
}
}
++streamer->iline;
+ *count += read_count;
return line;
}
@@ -287,7 +303,7 @@ parse_name_string
res = RES_MEM_ERR;
goto error;
}
- strcpy(name, tk);
+ strcpy(remain, tk);
}
exit:
@@ -323,6 +339,8 @@ parse_solid_name
goto error;
}
+ solid->read_type |= STARTED_ASCII;
+
OK(parse_name_string(sstl, strtok_r(NULL, "\0", tok_ctx), &solid->name,
filename, iline, tok_ctx));
@@ -443,7 +461,8 @@ load_ascii_stream
(struct sstl* sstl,
FILE* stream,
const char* stream_name,
- int allowed)
+ int allowed,
+ size_t* count)
{
res_T res = RES_OK;
struct streamer streamer;
@@ -452,11 +471,11 @@ load_ascii_stream
char* tok_ctx;
char* tk;
- ASSERT(sstl && stream && stream_name);
+ ASSERT(sstl && stream && stream_name && count);
streamer_init(&streamer, stream, stream_name);
clear(sstl);
- line = streamer_read_line(&streamer, 1);
+ line = streamer_read_line(&streamer, 1, count);
OK(parse_solid_name(sstl, &solid, line, streamer.name, streamer.iline,
allowed, &tok_ctx));
@@ -465,7 +484,7 @@ load_ascii_stream
unsigned facet[3];
int ivertex;
- line = streamer_read_line(&streamer, 0);
+ line = streamer_read_line(&streamer, 0, count);
if(!line) {
print_log(sstl, LOG_ERROR, "%s:%lu: missing directive.\n",
streamer.name, (unsigned long)streamer.iline);
@@ -493,12 +512,12 @@ load_ascii_stream
streamer.iline, &tok_ctx));
/* Parse the Outer loop directive */
- line = streamer_read_line(&streamer, 0);
+ line = streamer_read_line(&streamer, 0, count);
OK(parse_outer_loop(sstl, line, streamer.name, streamer.iline, &tok_ctx));
/* Parse the facet vertices. Assume that only 3 vertices are submitted */
FOR_EACH(ivertex, 0, 3) {
- line = streamer_read_line(&streamer, 0);
+ line = streamer_read_line(&streamer, 0, count);
OK(parse_solid_vertex(sstl, &solid, facet+ivertex, line, streamer.name,
streamer.iline, &tok_ctx));
}
@@ -513,10 +532,10 @@ load_ascii_stream
}
f3_set(sa_add(solid.normals, 3), normal);
- line = streamer_read_line(&streamer, 0);
+ line = streamer_read_line(&streamer, 0, count);
OK(parse_directive(sstl, "endloop", line, streamer.name, streamer.iline, &tok_ctx));
- line = streamer_read_line(&streamer, 0);
+ line = streamer_read_line(&streamer, 0, count);
OK(parse_directive(sstl, "endfacet", line, streamer.name, streamer.iline, &tok_ctx));
}
@@ -534,9 +553,22 @@ load_ascii_stream
}
sa_release(name);
}
+ if(sstl->verbose) {
+ int tmp, non_space = 0;
+ size_t i = 0;
+ while (EOF != (tmp = fgetc(stream))) {
+ i++;
+ if(!isspace(tmp)) non_space = 1;
+ }
+ if(non_space) {
+ print_log(sstl, LOG_WARNING,
+ "%s: %u unexpected trailing characters.\n",
+ stream_name, i);
+ }
+ }
/* Register the solid */
- solid.read_type = SSTL_ASCII;
+ solid.read_type |= OK_ASCII;
sstl->solid = solid;
exit:
@@ -572,6 +604,9 @@ load_binary_stream
res = RES_BAD_ARG;
goto error;
}
+
+ solid.read_type |= STARTED_BIN;
+
if(1 != fread(&triangles_count, 4, 1, stream)) {
print_log(sstl, LOG_ERROR, "%s: missing triangle count.\n", stream_name);
res = RES_BAD_ARG;
@@ -608,16 +643,18 @@ load_binary_stream
sa_push(solid.indices, index);
}
}
- i = 0;
- while (1 == fread(header, 1, 1, stream)) i++;
- if(i) {
- print_log(sstl, LOG_WARNING,
- "%s: %u unexpected trailing bytes.\n",
- stream_name, i);
+ if(sstl->verbose) {
+ i = 0;
+ while (1 == fread(header, 1, 1, stream)) i++;
+ if(i) {
+ print_log(sstl, LOG_WARNING,
+ "%s: %u unexpected trailing bytes.\n",
+ stream_name, i);
+ }
}
/* Register the solid */
- solid.read_type = SSTL_BINARY;
+ solid.read_type |= OK_BINARY;
sstl->solid = solid;
exit:
@@ -627,16 +664,6 @@ error:
goto exit;
}
-#if defined(COMPILER_GCC)
- #define FTELL(P, S) \
- if(-1L == ((P) = ftell(S))) { res = RES_IO_ERR; goto error; }
-#elif defined(COMPILER_CL)
- #define FTELL(S) \
- if(-1L == ((P) = _ftelli64(S))) { res = RES_IO_ERR; goto error; }
-#else
- #error Undefined FTELL macro
-#endif
-
static res_T
load_stream
(struct sstl* sstl,
@@ -645,35 +672,41 @@ load_stream
int allowed)
{
res_T res = RES_OK;
- long long int idx1, idx2;
int log = (allowed == TRY_READ_ALL);
- size_t count;
+ size_t count = 0;
- ASSERT(sstl && stream && stream_name && allowed);
+ ASSERT(sstl && stream && allowed);
/* Try reading as an ASCII file; if the file doesn't start with "solid" the
* file is not read past the first 5 characters, so that we can continue
* reading as a binary file, exploiting the fact that binary files' first 80
* characters are meaningless */
- FTELL(idx1, stream);
if(allowed & TRY_READ_ASCII) {
if(log) {
print_log(sstl, LOG_OUTPUT,
"%s: attempt to read as ASCII file.\n", stream_name);
}
- res = load_ascii_stream(sstl, stream, stream_name, allowed);
+ res = load_ascii_stream(sstl, stream, stream_name, allowed, &count);
if(res == RES_OK) {
if(log) print_log(sstl, LOG_OUTPUT, "Attempt successful.\n");
goto exit;
}
}
+ /* If here the stream could not be read as ASCII */
if(!(allowed & TRY_READ_BINARY)) goto exit;
- FTELL(idx2, stream);
- ASSERT(idx2 >= idx1);
- count = (size_t)(idx2 - idx1);
- if(count > CHECK_SOLID_LEN)
+ if(sstl->solid.read_type & STARTED_ASCII) {
/* "solid" was found: was an ill-formed ASCII file */
return res;
+ }
+ if(count > 80) {
+ /* Don't know if can happen, but further code cannot handle this */
+ print_log(sstl, LOG_ERROR,
+ "%s: cannot attempt to read as binary file"
+ " (too many bytes read while trying ascii read).\n",
+ stream_name);
+ res = RES_BAD_ARG;
+ goto error;
+ }
if(log) {
print_log(sstl, LOG_OUTPUT,
"%s: attempt to read as binary file.\n", stream_name);
@@ -874,7 +907,7 @@ write_stream
res = data->get_triangle_vertices(i, data->data, vtx);
OKP(fprintf(stream, " outer loop\n"));
for(n = 0; n < 3; n++) {
- OKP(fprintf(stream, " vertex %g %g %g\n", SPLIT3(vtx[n])));
+ OKP(fprintf(stream, " vertex %.16g %.16g %.16g\n", SPLIT3(vtx[n])));
}
OKP(fprintf(stream, " endloop\n"));
OKP(fprintf(stream, " endfacet\n"));
@@ -1013,8 +1046,12 @@ sstl_load_stream(struct sstl* sstl, FILE* stream)
res_T
sstl_get_desc(struct sstl* sstl, struct sstl_desc* desc)
{
- if(!sstl || !desc) return RES_BAD_ARG;
+ if(!sstl || !desc
+ /* OK_ASCII xor OK_BIN */
+ || (sstl->solid.read_type & OK_BINARY) == (sstl->solid.read_type & OK_ASCII))
+ return RES_BAD_ARG;
desc->solid_name = sstl->solid.name;
+ desc->read_type = (sstl->solid.read_type & OK_ASCII) ? SSTL_ASCII : SSTL_BINARY;
desc->vertices_count = sa_size(sstl->solid.vertices);
ASSERT(desc->vertices_count % 3 == 0);
desc->vertices_count /= 3/* # coords per vertex */;
diff --git a/src/sstl.h b/src/sstl.h
@@ -71,6 +71,8 @@ struct sstl_write_data {
void (*print_error_log)(const void* data, const char* msg, ...);
unsigned triangles_count;
};
+#define SSTL_WRITE_DATA_NULL__ { NULL, NULL, NULL, NULL, NULL, 0 }
+static const struct sstl_write_data SSTL_WRITE_DATA_NULL = SSTL_WRITE_DATA_NULL__;
/* Forward declaration of external types */
struct logger;
@@ -138,7 +140,7 @@ sstl_load_stream
FILE* stream);
/* Create a sstl_write_data from a sstl.
- * The returned descriptor is valid until a new load process */
+ * The result is valid as long as the input sstl is valid */
SSTL_API res_T
sstl_pack_write_data
(const struct sstl* sstl,
diff --git a/src/test_sstl_load.c b/src/test_sstl_load.c
@@ -175,13 +175,13 @@ test_basic(struct sstl* sstl)
file = tmpfile();
CHK(file != NULL);
fwrite(test1, sizeof(char), strlen(test1), file);
-
+
rewind(file);
CHK(sstl_load_stream_ascii(NULL, NULL) == RES_BAD_ARG);
CHK(sstl_load_stream_ascii(sstl, NULL) == RES_BAD_ARG);
CHK(sstl_load_stream_ascii(NULL, file) == RES_BAD_ARG);
CHK(sstl_load_stream_ascii(sstl, file) == RES_OK);
-
+
rewind(file);
CHK(sstl_load_stream_binary(NULL, NULL) == RES_BAD_ARG);
CHK(sstl_load_stream_binary(sstl, NULL) == RES_BAD_ARG);
@@ -225,7 +225,7 @@ test_basic(struct sstl* sstl)
rewind(file);
CHK(sstl_load_stream_binary(sstl,file) == RES_OK);
fclose(file);
-
+
CHK(sstl_get_desc(sstl, &desc) == RES_OK);
CHK(desc.solid_name == NULL);
CHK(desc.vertices_count == 3);