commit a82dcc0640a6b74cdf93eef56552476df40d27cc
parent ce7b081f45c2a94936f9306bcc3c88a99d6b66d1
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Mon, 24 Feb 2025 16:19:27 +0100
Fix stdin compatibility
Code used ftell that is not stdin compatible.
Code is not ftell free.
Diffstat:
| M | src/sstl.c | | | 91 | +++++++++++++++++++++++++++++++++++++++++++++++++------------------------------- |
1 file changed, 56 insertions(+), 35 deletions(-)
diff --git a/src/sstl.c b/src/sstl.c
@@ -45,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 };
@@ -126,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);
@@ -148,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 */
@@ -156,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;
}
@@ -177,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'));
@@ -186,6 +200,7 @@ streamer_read_line
}
}
++streamer->iline;
+ *count += read_count;
return line;
}
@@ -324,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));
@@ -444,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;
@@ -453,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));
@@ -466,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);
@@ -494,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));
}
@@ -514,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));
}
@@ -550,7 +568,7 @@ load_ascii_stream
}
/* Register the solid */
- solid.read_type = SSTL_ASCII;
+ solid.read_type |= OK_ASCII;
sstl->solid = solid;
exit:
@@ -586,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;
@@ -633,7 +654,7 @@ load_binary_stream
}
/* Register the solid */
- solid.read_type = SSTL_BINARY;
+ solid.read_type |= OK_BINARY;
sstl->solid = solid;
exit:
@@ -643,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,
@@ -661,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);
@@ -1029,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 */;