mirror of
https://github.com/felt/tippecanoe.git
synced 2026-10-02 16:35:40 +02:00
Throw instead of exiting from the tile clipping and overzooming code
The code reachable from overzooming a tile no longer calls exit(). It reports errors by throwing tippecanoe_error, and owns its FILE * and json_pull * handles through RAII wrappers so that nothing leaks when an error unwinds the stack. New files: * errors.hpp/errors.cpp: the tippecanoe_error exception class, plus throw_tippecanoe_error() and throw_perror() helpers. * raii.hpp: unique_file and unique_json_pull, both std::unique_ptr aliases, for FILE * and json_pull *. exit() becomes throw in clip.cpp, mvt.cpp, mvt.hpp, read_json.cpp, evaluator.cpp, text.cpp, geometry.cpp, attribute.cpp, and write_json.hpp. Each tool's main() is now a try/catch around an inner_main(), so the command-line tools exit with the status they always did. Along the way this fixes a z_stream leaked when compress() failed, an exit() that could run from json_writer's destructor during unwinding, and an exit() in mvt_value's hash function. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DuCSVGssWNUCpVEE8Yp5HT
This commit is contained in:
+26
-20
@@ -12,6 +12,7 @@
|
||||
#include "read_json.hpp"
|
||||
#include "projection.hpp"
|
||||
#include "usage.hpp"
|
||||
#include "raii.hpp"
|
||||
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
@@ -91,24 +92,21 @@ void usage(char **argv) {
|
||||
std::string read_json_file(const char *fname) {
|
||||
std::string out;
|
||||
|
||||
FILE *f = fopen(fname, "r");
|
||||
if (f == NULL) {
|
||||
perror(optarg);
|
||||
exit(EXIT_OPEN);
|
||||
unique_file f(fopen(fname, "r"));
|
||||
if (!f) {
|
||||
throw_perror(EXIT_OPEN, fname);
|
||||
}
|
||||
|
||||
char buf[2000];
|
||||
size_t nread;
|
||||
while ((nread = fread(buf, sizeof(char), 2000, f)) != 0) {
|
||||
while ((nread = fread(buf, sizeof(char), 2000, f.get())) != 0) {
|
||||
out += std::string(buf, nread);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int inner_main(int argc, char **argv) {
|
||||
int i;
|
||||
const char *outtile = NULL;
|
||||
const char *outfile = NULL;
|
||||
@@ -273,16 +271,14 @@ int main(int argc, char **argv) {
|
||||
char buf[1000];
|
||||
int len;
|
||||
|
||||
FILE *f = fopen(s.tile.c_str(), "rb");
|
||||
if (f == NULL) {
|
||||
perror(s.tile.c_str());
|
||||
exit(EXIT_FAILURE);
|
||||
unique_file f(fopen(s.tile.c_str(), "rb"));
|
||||
if (!f) {
|
||||
throw_perror(EXIT_OPEN, s.tile.c_str());
|
||||
}
|
||||
|
||||
while ((len = fread(buf, sizeof(char), 1000, f)) > 0) {
|
||||
while ((len = fread(buf, sizeof(char), 1000, f.get())) > 0) {
|
||||
tile.append(std::string(buf, len));
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
input_tile t = s;
|
||||
t.tile = std::move(tile);
|
||||
@@ -292,14 +288,24 @@ int main(int argc, char **argv) {
|
||||
out = overzoom(its, nz, nx, ny, detail, buffer, keep, exclude, exclude_prefix, do_compress, NULL, demultiply, json_filter, preserve_input_order, attribute_accum, unidecode_data, simplification, tiny_polygon_size, std::vector<mvt_layer>(), "", "", SIZE_MAX, std::vector<clipbbox>(), deduplicate_by_id);
|
||||
}
|
||||
|
||||
FILE *f = fopen(outfile, "wb");
|
||||
if (f == NULL) {
|
||||
perror(outfile);
|
||||
exit(EXIT_FAILURE);
|
||||
unique_file f(fopen(outfile, "wb"));
|
||||
if (!f) {
|
||||
throw_perror(EXIT_OPEN, outfile);
|
||||
}
|
||||
|
||||
fwrite(out.c_str(), sizeof(char), out.size(), f);
|
||||
fclose(f);
|
||||
fwrite(out.c_str(), sizeof(char), out.size(), f.get());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
try {
|
||||
return inner_main(argc, argv);
|
||||
} catch (tippecanoe_error &e) {
|
||||
fprintf(stderr, "%s\n", e.what());
|
||||
return e.exit_code;
|
||||
} catch (std::exception &e) {
|
||||
fprintf(stderr, "Error: %s\n", e.what());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user