csg 0.1.1 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- 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/
|