csg 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Makefile +2 -2
- data/src/reader.c +1 -0
- data/src/stl.c +59 -149
- data/src/stl.h +1 -7
- data/src/stl_mesh.c +54 -0
- data/src/stl_mesh.h +15 -0
- data/src/util.c +149 -0
- data/src/util.h +27 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 032ae67480be4a8091aaceae652d8f7ba608c799
|
4
|
+
data.tar.gz: e9c632170b74ef2bc33a62f4f54f6a39be8176e2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 59540582ac22f6e0beb5158c023e2e492ac470ca52e324c807d14869c1d1d8b00dbb8825d2b52ffdcd271aa553b263e918a4004e7af00a500bdfd75aeea32e00
|
7
|
+
data.tar.gz: e53ca53c28394c684e3647660350725a2db98cc4a232f652aa4d785ae8a0d9c3b23e35e0a3b725f69ee4fb53ccf4024b784aa76f5e25e67af35e25b9af5cf443
|
data/Makefile
CHANGED
@@ -8,7 +8,7 @@ SOURCES = $(wildcard $(ROOT)/src/*.c)
|
|
8
8
|
OBJS = $(patsubst %.c,%.o,$(SOURCES))
|
9
9
|
CPPFLAGS = $(OPTCPPFLAGS)
|
10
10
|
LIBS = -lm $(OPTLIBS)
|
11
|
-
CFLAGS = -g -std=c99 $(INCLUDE) -Wall -Werror $(OPTFLAGS)
|
11
|
+
CFLAGS = -D_POSIX_C_SOURCE=200112L -g -std=c99 $(INCLUDE) -Wall -Werror $(OPTFLAGS)
|
12
12
|
|
13
13
|
ifeq ($(shell uname),Darwin)
|
14
14
|
LIB_TARGET = libcsg.dylib
|
@@ -42,6 +42,6 @@ libcsg: $(LIB_TARGET)
|
|
42
42
|
|
43
43
|
loc:
|
44
44
|
@echo "=> Source:"
|
45
|
-
find src/ -name '*.[ch]' -not -name 'dbg.*' | xargs wc -l csgtool.c
|
45
|
+
find src/ -name '*.[ch]' -not -name 'dbg.*' -not -name 'klist.*' | xargs wc -l csgtool.c
|
46
46
|
@echo "=> Tests:"
|
47
47
|
find tests/ -name '*.[ch]' -not -path '*clar*' | xargs wc -l
|
data/src/reader.c
CHANGED
data/src/stl.c
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#include <ctype.h>
|
2
2
|
#include <fcntl.h>
|
3
|
+
#include <stdbool.h>
|
3
4
|
#include <stdio.h>
|
4
5
|
#include <stdlib.h>
|
5
6
|
#include <math.h>
|
@@ -7,6 +8,7 @@
|
|
7
8
|
#include "dbg.h"
|
8
9
|
|
9
10
|
#include "stl.h"
|
11
|
+
#include "util.h"
|
10
12
|
|
11
13
|
void stl_free(stl_object *obj) {
|
12
14
|
if(obj == NULL) return;
|
@@ -72,61 +74,7 @@ error:
|
|
72
74
|
exit(-1);
|
73
75
|
}
|
74
76
|
|
75
|
-
|
76
|
-
* Allocate, read, and return a anull terminated string from `fd'.
|
77
|
-
* Return NULL in caes of error
|
78
|
-
*/
|
79
|
-
char* read_line(int fd, int downcase, int trim) {
|
80
|
-
const size_t max_line = 100;
|
81
|
-
char *buffer = calloc(max_line + 1, sizeof(char));
|
82
|
-
int rc = -1;
|
83
|
-
check_mem(buffer);
|
84
|
-
|
85
|
-
rc = read(fd, buffer, max_line);
|
86
|
-
check(rc != -1, "Failed to read.");
|
87
|
-
|
88
|
-
char *ret = NULL;
|
89
|
-
while((ret = strchr(buffer, '\r'))) {
|
90
|
-
*ret = ' ';
|
91
|
-
}
|
92
|
-
|
93
|
-
char *newline = strchr(buffer, '\n');
|
94
|
-
if(newline != NULL) *newline = '\0';
|
95
|
-
|
96
|
-
if((strlen(buffer) == 0) && (rc == 0)) goto eof;
|
97
|
-
|
98
|
-
rc = lseek(fd, -(rc - strlen(buffer) - 1), SEEK_CUR);
|
99
|
-
check(rc != -1, "Failed to seek.");
|
100
|
-
|
101
|
-
if(trim) {
|
102
|
-
char *new = NULL;
|
103
|
-
int start = 0;
|
104
|
-
int end = strlen(buffer) ;
|
105
|
-
while(isspace(buffer[start++]));
|
106
|
-
while(isspace(buffer[--end]));
|
107
|
-
if(start > 0) start--;
|
108
|
-
buffer[++end] = '\0';
|
109
|
-
check_mem((new = calloc(strlen(buffer + start) + 1, 1)));
|
110
|
-
memcpy(new, buffer + start, end - start);
|
111
|
-
free(buffer);
|
112
|
-
buffer = new;
|
113
|
-
}
|
114
|
-
|
115
|
-
if(downcase) {
|
116
|
-
for(int i = 0; i < strlen(buffer); i++) {
|
117
|
-
buffer[i] = tolower(buffer[i]);
|
118
|
-
}
|
119
|
-
}
|
120
|
-
|
121
|
-
|
122
|
-
return buffer;
|
123
|
-
eof:
|
124
|
-
error:
|
125
|
-
if(buffer) free(buffer);
|
126
|
-
return NULL;
|
127
|
-
}
|
128
|
-
|
129
|
-
stl_facet *stl_read_text_facet(const char *declaration, int fd) {
|
77
|
+
stl_facet *stl_read_text_facet(const char *declaration, FILE *f) {
|
130
78
|
stl_facet *facet = (stl_facet*)calloc(1, sizeof(stl_facet));
|
131
79
|
int rc = -1;
|
132
80
|
char *line = NULL;
|
@@ -135,11 +83,11 @@ stl_facet *stl_read_text_facet(const char *declaration, int fd) {
|
|
135
83
|
rc = sscanf(declaration, "facet normal %f %f %f", &facet->normal[0], &facet->normal[1], &facet->normal[2]);
|
136
84
|
check(rc == 3, "stl_Read_text_facet(%s): Normal line malformed", declaration);
|
137
85
|
|
138
|
-
check((line =
|
86
|
+
check((line = next_line(f, true, true)), "Malformed facet, no line follows valid normal declaration");
|
139
87
|
check(strcmp(line, "outer loop") == 0, "Malformed facet, no loop declaration following valid normal.");
|
140
88
|
|
141
89
|
for(int i = 0; i < 3; i++) {
|
142
|
-
check((line =
|
90
|
+
check((line = next_line(f, true, true)), "Failed to read vertex %d", i);
|
143
91
|
rc = sscanf(line, "vertex %f %f %f", &facet->vertices[i][0], &facet->vertices[i][1], &facet->vertices[i][2]);
|
144
92
|
check(rc == 3, "Vertex declaration [%s] did not contain (x, y, z) point.", line);
|
145
93
|
|
@@ -147,10 +95,10 @@ stl_facet *stl_read_text_facet(const char *declaration, int fd) {
|
|
147
95
|
line = NULL;
|
148
96
|
}
|
149
97
|
|
150
|
-
check((line =
|
98
|
+
check((line = next_line(f, true, true)), "No line following vertex declarations.");
|
151
99
|
check(strcmp(line, "endloop") == 0, "Vertex declarations not followed by 'endloop'. Got: '%s'", line);
|
152
100
|
free(line);
|
153
|
-
check((line =
|
101
|
+
check((line = next_line(f, true, true)), "No line following endloop.");
|
154
102
|
check(strcmp(line, "endfacet") == 0, "endloop not followed by 'endfacet'");
|
155
103
|
free(line);
|
156
104
|
line = NULL;
|
@@ -163,48 +111,62 @@ error:
|
|
163
111
|
}
|
164
112
|
|
165
113
|
stl_object *stl_read_text_object(int fd) {
|
166
|
-
|
167
|
-
|
168
|
-
|
114
|
+
FILE *f = NULL;
|
115
|
+
stl_object *obj = NULL;
|
116
|
+
char *line = NULL;
|
117
|
+
klist_t(stl_facet) *facets = NULL;
|
118
|
+
|
119
|
+
check((f = fdopen(fd, "r")) != NULL, "Failed to open fd(%d) as FILE", fd);
|
120
|
+
check((facets = kl_init(stl_facet)) != NULL, "Failed to create facel list.");
|
121
|
+
|
122
|
+
// Read first non-blank-line
|
123
|
+
line = next_line(f, false, true);
|
124
|
+
|
125
|
+
check(line != NULL, "Failed to read STL/ASCII header.");
|
126
|
+
check((obj = stl_alloc(NULL, 0)), "Failed to allocated new STL object.");
|
127
|
+
snprintf(obj->header, sizeof(obj->header), "[STL/ASCII]: '%s'", line);
|
128
|
+
// debug("Header: [%s]", obj->header);
|
129
|
+
free(line);
|
130
|
+
|
131
|
+
size_t lines = 0;
|
132
|
+
while((line = read_line(f, true, true))) {
|
133
|
+
lines++;
|
134
|
+
|
135
|
+
// Skip blanks
|
136
|
+
if(strlen(line) == 0) {
|
137
|
+
free(line);
|
138
|
+
continue;
|
139
|
+
}
|
169
140
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
141
|
+
if(strncmp(line, "facet", strlen("facet")) == 0) {
|
142
|
+
stl_facet *facet = stl_read_text_facet(line, f);
|
143
|
+
check(facet != NULL, "Failed to read facet on line %zd", lines);
|
144
|
+
*kl_pushp(stl_facet, facets) = facet;
|
145
|
+
}
|
146
|
+
else if(strncmp(line, "endsolid", strlen("endfacet")) == 0) {
|
147
|
+
check(facets->size > 0, "No facets loaded.");
|
148
|
+
// debug("ASCII solid ended. Loaded %zd facets", facets->size);
|
175
149
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
obj->facet_count = facets->size;
|
189
|
-
obj->facets = calloc(facets->size, sizeof(stl_facet));
|
190
|
-
check_mem(obj->facets);
|
191
|
-
|
192
|
-
stl_facet *facet = NULL;
|
193
|
-
for(int i = 0; kl_shift(stl_facet, facets, &facet) != -1; i++) {
|
194
|
-
obj->facets[i] = *facet;
|
195
|
-
}
|
196
|
-
}
|
197
|
-
else {
|
198
|
-
sentinel("Unexpected line[%zd]: '%s'", lines, line);
|
199
|
-
}
|
200
|
-
free(line);
|
150
|
+
obj->facet_count = facets->size;
|
151
|
+
obj->facets = calloc(facets->size, sizeof(stl_facet));
|
152
|
+
check_mem(obj->facets);
|
153
|
+
|
154
|
+
stl_facet *facet = NULL;
|
155
|
+
for(int i = 0; kl_shift(stl_facet, facets, &facet) != -1; i++) {
|
156
|
+
obj->facets[i] = *facet;
|
157
|
+
}
|
158
|
+
}
|
159
|
+
else {
|
160
|
+
sentinel("Unexpected line[%zd]: '%s'", lines, line);
|
201
161
|
}
|
162
|
+
free(line);
|
163
|
+
}
|
202
164
|
|
203
|
-
|
204
|
-
|
165
|
+
kl_destroy(stl_facet, facets);
|
166
|
+
return obj;
|
205
167
|
error:
|
206
|
-
|
207
|
-
|
168
|
+
kl_destroy(stl_facet, facets);
|
169
|
+
return NULL;
|
208
170
|
}
|
209
171
|
|
210
172
|
stl_object *stl_read_object(int fd) {
|
@@ -244,6 +206,7 @@ stl_object *stl_read_file(char *path, int recompute_normals) {
|
|
244
206
|
check((fd = open(path, O_RDONLY)) != -1, "Unable to open '%s'", path);
|
245
207
|
|
246
208
|
obj = reader(fd);
|
209
|
+
check(obj != NULL, "Failed to read STL from %s", path);
|
247
210
|
|
248
211
|
char buffer[10];
|
249
212
|
int rc = read(fd, buffer, sizeof(buffer));
|
@@ -330,56 +293,3 @@ error:
|
|
330
293
|
if(fd != -1) close(fd);
|
331
294
|
return NULL;
|
332
295
|
}
|
333
|
-
|
334
|
-
// Mesh type prototype methods
|
335
|
-
int stl_mesh_init(void *self, void *data) {
|
336
|
-
stl_mesh_t *mesh = (stl_mesh_t*)self;
|
337
|
-
if(data == NULL) {
|
338
|
-
check_mem(mesh->stl = stl_alloc(NULL, 0));
|
339
|
-
}
|
340
|
-
else {
|
341
|
-
mesh->stl = (stl_object*)data;
|
342
|
-
}
|
343
|
-
return 0;
|
344
|
-
error:
|
345
|
-
return -1;
|
346
|
-
}
|
347
|
-
|
348
|
-
void stl_mesh_destroy(void *self) {
|
349
|
-
stl_mesh_t *mesh = (stl_mesh_t*)self;
|
350
|
-
stl_free(mesh->stl);
|
351
|
-
free(self);
|
352
|
-
}
|
353
|
-
|
354
|
-
int stl_mesh_poly_count(void *self) {
|
355
|
-
stl_mesh_t *mesh = (stl_mesh_t*)self;
|
356
|
-
return mesh->stl->facet_count;
|
357
|
-
}
|
358
|
-
|
359
|
-
klist_t(poly)* stl_mesh_to_polygons(void *self) {
|
360
|
-
stl_mesh_t *mesh = (stl_mesh_t*)self;
|
361
|
-
int count = mesh->_(poly_count)(mesh);
|
362
|
-
klist_t(poly)* polys = kl_init(poly);
|
363
|
-
|
364
|
-
for(int i = 0; i < count; i++) {
|
365
|
-
poly_t *poly = poly_make_triangle(mesh->stl->facets[i].vertices[0],
|
366
|
-
mesh->stl->facets[i].vertices[1],
|
367
|
-
mesh->stl->facets[i].vertices[2]);
|
368
|
-
check_mem(poly);
|
369
|
-
*kl_pushp(poly, polys) = poly;
|
370
|
-
}
|
371
|
-
|
372
|
-
|
373
|
-
return polys;
|
374
|
-
error:
|
375
|
-
if(polys != NULL) kl_destroy(poly, polys);
|
376
|
-
return NULL;
|
377
|
-
}
|
378
|
-
|
379
|
-
// Mesh type definitions
|
380
|
-
mesh_t stl_mesh_t_Proto = {
|
381
|
-
.init = stl_mesh_init,
|
382
|
-
.destroy = stl_mesh_destroy,
|
383
|
-
.poly_count = stl_mesh_poly_count,
|
384
|
-
.to_polygons = stl_mesh_to_polygons
|
385
|
-
};
|
data/src/stl.h
CHANGED
@@ -42,7 +42,7 @@ stl_facet *stl_read_facet(int fd);
|
|
42
42
|
stl_object *stl_read_object(int fd);
|
43
43
|
|
44
44
|
// Text file readers
|
45
|
-
stl_facet *stl_read_text_facet(const char *declaration,
|
45
|
+
stl_facet *stl_read_text_facet(const char *declaration, FILE *f);
|
46
46
|
stl_object *stl_read_text_object(int fd);
|
47
47
|
|
48
48
|
// Binary file writers
|
@@ -56,12 +56,6 @@ KLIST_INIT(stl_object, stl_object*, mp_stl_free)
|
|
56
56
|
#define mp_std_free(x) free(kl_val(x))
|
57
57
|
KLIST_INIT(stl_facet, stl_facet*, mp_std_free)
|
58
58
|
|
59
|
-
// mesh_t type and prototype
|
60
|
-
extern mesh_t stl_mesh_t_Proto;
|
61
59
|
|
62
|
-
typedef struct s_stl_mesh_t {
|
63
|
-
mesh_t proto;
|
64
|
-
stl_object *stl;
|
65
|
-
} stl_mesh_t;
|
66
60
|
|
67
61
|
#endif
|
data/src/stl_mesh.c
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
#include "stl_mesh.h"
|
2
|
+
|
3
|
+
// Mesh type prototype methods
|
4
|
+
int stl_mesh_init(void *self, void *data) {
|
5
|
+
stl_mesh_t *mesh = (stl_mesh_t*)self;
|
6
|
+
if(data == NULL) {
|
7
|
+
check_mem(mesh->stl = stl_alloc(NULL, 0));
|
8
|
+
}
|
9
|
+
else {
|
10
|
+
mesh->stl = (stl_object*)data;
|
11
|
+
}
|
12
|
+
return 0;
|
13
|
+
error:
|
14
|
+
return -1;
|
15
|
+
}
|
16
|
+
|
17
|
+
void stl_mesh_destroy(void *self) {
|
18
|
+
stl_mesh_t *mesh = (stl_mesh_t*)self;
|
19
|
+
stl_free(mesh->stl);
|
20
|
+
free(self);
|
21
|
+
}
|
22
|
+
|
23
|
+
int stl_mesh_poly_count(void *self) {
|
24
|
+
stl_mesh_t *mesh = (stl_mesh_t*)self;
|
25
|
+
return mesh->stl->facet_count;
|
26
|
+
}
|
27
|
+
|
28
|
+
klist_t(poly)* stl_mesh_to_polygons(void *self) {
|
29
|
+
stl_mesh_t *mesh = (stl_mesh_t*)self;
|
30
|
+
int count = mesh->_(poly_count)(mesh);
|
31
|
+
klist_t(poly)* polys = kl_init(poly);
|
32
|
+
|
33
|
+
for(int i = 0; i < count; i++) {
|
34
|
+
poly_t *poly = poly_make_triangle(mesh->stl->facets[i].vertices[0],
|
35
|
+
mesh->stl->facets[i].vertices[1],
|
36
|
+
mesh->stl->facets[i].vertices[2]);
|
37
|
+
check_mem(poly);
|
38
|
+
*kl_pushp(poly, polys) = poly;
|
39
|
+
}
|
40
|
+
|
41
|
+
|
42
|
+
return polys;
|
43
|
+
error:
|
44
|
+
if(polys != NULL) kl_destroy(poly, polys);
|
45
|
+
return NULL;
|
46
|
+
}
|
47
|
+
|
48
|
+
// Mesh type definitions
|
49
|
+
mesh_t stl_mesh_t_Proto = {
|
50
|
+
.init = stl_mesh_init,
|
51
|
+
.destroy = stl_mesh_destroy,
|
52
|
+
.poly_count = stl_mesh_poly_count,
|
53
|
+
.to_polygons = stl_mesh_to_polygons
|
54
|
+
};
|
data/src/stl_mesh.h
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#include "stl.h"
|
2
|
+
#include "mesh.h"
|
3
|
+
|
4
|
+
#ifndef __STL_MESH_H
|
5
|
+
#define __STL_MESH_H
|
6
|
+
|
7
|
+
// mesh_t type and prototype
|
8
|
+
extern mesh_t stl_mesh_t_Proto;
|
9
|
+
|
10
|
+
typedef struct s_stl_mesh_t {
|
11
|
+
mesh_t proto;
|
12
|
+
stl_object *stl;
|
13
|
+
} stl_mesh_t;
|
14
|
+
|
15
|
+
#endif
|
data/src/util.c
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
#include "ctype.h"
|
2
|
+
|
3
|
+
#include "util.h"
|
4
|
+
|
5
|
+
char *str_dup(char *str) {
|
6
|
+
char *copy_str = NULL;
|
7
|
+
check_mem(copy_str = calloc(strlen(str) + 1, sizeof(char)));
|
8
|
+
strncpy(copy_str, str, strlen(str));
|
9
|
+
return copy_str;
|
10
|
+
error:
|
11
|
+
return NULL;
|
12
|
+
}
|
13
|
+
|
14
|
+
char *str_ltrim(char *str, bool copy) {
|
15
|
+
if(!copy) {
|
16
|
+
// Find the first non-space char in the string
|
17
|
+
char *start = str;
|
18
|
+
while(*start && isspace(*start)) {
|
19
|
+
start++;
|
20
|
+
}
|
21
|
+
|
22
|
+
// Do nothing if the string starts on a sane char
|
23
|
+
if(start != str) {
|
24
|
+
// Shift the string and NULL-cap it if we found a subset
|
25
|
+
// otherwise NULL the head of the string
|
26
|
+
if((start - str) != strlen(str)) {
|
27
|
+
memmove(str, start, strlen(start));
|
28
|
+
str[strlen(start)] = '\0';
|
29
|
+
}
|
30
|
+
else {
|
31
|
+
str[0] = '\0';
|
32
|
+
}
|
33
|
+
}
|
34
|
+
return str;
|
35
|
+
}
|
36
|
+
else {
|
37
|
+
char *copy_str = NULL;
|
38
|
+
check_mem(copy_str = str_dup(str));
|
39
|
+
return str_ltrim(copy_str, false);
|
40
|
+
}
|
41
|
+
error:
|
42
|
+
return NULL;
|
43
|
+
}
|
44
|
+
|
45
|
+
char *str_rtrim(char *str, bool copy) {
|
46
|
+
if(!copy) {
|
47
|
+
char *end = str + strlen(str) - 1;
|
48
|
+
while((end > str) && isspace(*end)) {
|
49
|
+
*end-- = '\0';
|
50
|
+
}
|
51
|
+
return str;
|
52
|
+
}
|
53
|
+
else {
|
54
|
+
char *copy_str = NULL;
|
55
|
+
check_mem(copy_str = str_dup(str));
|
56
|
+
return str_ltrim(copy_str, false);
|
57
|
+
}
|
58
|
+
error:
|
59
|
+
return NULL;
|
60
|
+
}
|
61
|
+
|
62
|
+
char *str_trim(char *str, bool copy) {
|
63
|
+
char *trim_str = copy ? str_dup(str) : str;
|
64
|
+
check_mem(trim_str);
|
65
|
+
|
66
|
+
// Since we have already made a copy if we need one,
|
67
|
+
// we can just chain these two together, since non-copy
|
68
|
+
// operations can't throw out a NULL and the pointer itself
|
69
|
+
// cannot change.
|
70
|
+
return str_ltrim(str_rtrim(trim_str, false), false);
|
71
|
+
error:
|
72
|
+
return NULL;
|
73
|
+
}
|
74
|
+
|
75
|
+
char *read_line(FILE *f, bool downcase, bool trim) {
|
76
|
+
char read_buffer[512] = {0};
|
77
|
+
char *line = NULL;
|
78
|
+
char *rc = NULL;
|
79
|
+
|
80
|
+
// Sanity check the stream before we go on,
|
81
|
+
// an EOF here is not fatal, so we'll return early
|
82
|
+
// instead of jumping into the error machinery.
|
83
|
+
if(feof(f) != 0) return NULL;
|
84
|
+
check(ferror(f) == 0, "Error in stream(%p).", f);
|
85
|
+
|
86
|
+
// Try reading, with the hope that we get the entire line at once.
|
87
|
+
// Short circuit EOF, so we don't emit noise if we can avoid it.
|
88
|
+
rc = fgets(read_buffer, sizeof(read_buffer), f);
|
89
|
+
if((rc == NULL) && feof(f)) return NULL;
|
90
|
+
|
91
|
+
check_debug(rc != NULL, "Failed to read line from FILE(%p)", f);
|
92
|
+
check_mem(line = calloc(strlen(read_buffer) + 1, sizeof(char)));
|
93
|
+
strncpy(line, read_buffer, strlen(read_buffer));
|
94
|
+
|
95
|
+
// See if we need to finish reading the line
|
96
|
+
while(line[strlen(line) - 1] != '\n') {
|
97
|
+
rc = fgets(read_buffer, sizeof(read_buffer), f);
|
98
|
+
if((rc == NULL) && feof(f)) {
|
99
|
+
// We got everything that we can get, so we'll
|
100
|
+
// call it a "line"
|
101
|
+
break;
|
102
|
+
}
|
103
|
+
else {
|
104
|
+
// Append the new data to the end of the line
|
105
|
+
char *new_line = NULL;
|
106
|
+
check(rc != NULL, "Error finishing line from FILE(%p)", f);
|
107
|
+
check_mem(new_line = calloc(strlen(line) + strlen(read_buffer) + 1, sizeof(char)));
|
108
|
+
|
109
|
+
strncpy(new_line, line, strlen(line));
|
110
|
+
strncpy(new_line + strlen(new_line), read_buffer, strlen(read_buffer));
|
111
|
+
|
112
|
+
free(line);
|
113
|
+
line = new_line;
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
117
|
+
// Post processing
|
118
|
+
if((line != NULL) && (strlen(line) > 0)) {
|
119
|
+
if(trim == true) {
|
120
|
+
line = str_trim(line, false);
|
121
|
+
}
|
122
|
+
|
123
|
+
if(downcase == true) {
|
124
|
+
for(int i = 0; i < strlen(line); i++) {
|
125
|
+
line[i] = tolower(line[i]);
|
126
|
+
}
|
127
|
+
}
|
128
|
+
}
|
129
|
+
|
130
|
+
return line;
|
131
|
+
error:
|
132
|
+
if(line != NULL) free(line);
|
133
|
+
if(feof(f)) debug("FILE(%p) EOF", f);
|
134
|
+
if(ferror(f)) debug("FILE(%p): ERROR. %s", f, clean_errno());
|
135
|
+
return NULL;
|
136
|
+
}
|
137
|
+
|
138
|
+
char *next_line(FILE *f, bool downcase, bool trim) {
|
139
|
+
char *line = NULL;
|
140
|
+
|
141
|
+
// Read lines until we get one that isn't blank,
|
142
|
+
while(((line = read_line(f, downcase, trim)) != NULL) &&
|
143
|
+
(strlen(line) == 0)) {
|
144
|
+
free(line);
|
145
|
+
line = NULL;
|
146
|
+
}
|
147
|
+
|
148
|
+
return line;
|
149
|
+
}
|
data/src/util.h
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#include <stdbool.h>
|
2
|
+
#include <stdio.h>
|
3
|
+
#include <stdlib.h>
|
4
|
+
|
5
|
+
#include "dbg.h"
|
6
|
+
|
7
|
+
#ifndef __UTIL_H
|
8
|
+
#define __UTIL_H
|
9
|
+
|
10
|
+
|
11
|
+
char *str_dup(char *str);
|
12
|
+
|
13
|
+
char *str_ltrim(char *str, bool copy);
|
14
|
+
char *str_rtrim(char *str, bool copy);
|
15
|
+
char *str_trim(char *str, bool copy);
|
16
|
+
|
17
|
+
/*
|
18
|
+
* Allocate, read, and return a '\0' terminated string from `fd'.
|
19
|
+
* Return NULL in caes of error
|
20
|
+
*/
|
21
|
+
char *read_line(FILE *f, bool downcase, bool trim);
|
22
|
+
|
23
|
+
// Call `read_line` until we don't get blank lines
|
24
|
+
// Gets the "next" non-blank line
|
25
|
+
char *next_line(FILE *f, bool downcase, bool trim);
|
26
|
+
|
27
|
+
#endif
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: csg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yaroslav Shirokov
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2014-04-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ffi
|
@@ -44,6 +44,8 @@ files:
|
|
44
44
|
- src/poly.c
|
45
45
|
- src/reader.c
|
46
46
|
- src/stl.c
|
47
|
+
- src/stl_mesh.c
|
48
|
+
- src/util.c
|
47
49
|
- src/vector.c
|
48
50
|
- src/bsp.h
|
49
51
|
- src/bsp_mesh.h
|
@@ -55,6 +57,8 @@ files:
|
|
55
57
|
- src/poly.h
|
56
58
|
- src/reader.h
|
57
59
|
- src/stl.h
|
60
|
+
- src/stl_mesh.h
|
61
|
+
- src/util.h
|
58
62
|
- src/vector.h
|
59
63
|
- ext/Rakefile
|
60
64
|
homepage: https://github.com/sshirokov/csgtool/
|