diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 62fa07e5..a24c3300 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -36,3 +36,22 @@ jobs: echo "::error::man/tippecanoe.1 is out of date. Run 'make docs' and commit the result." exit 1 } + + indent: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + # Pinned, because different clang-format versions format the same input + # differently, which would make this check fail spuriously. + - name: Install clang-format + run: | + python3 -m venv /tmp/clang-format + /tmp/clang-format/bin/pip install clang-format==18.1.8 + - name: Reformat the sources + run: PATH="/tmp/clang-format/bin:$PATH" make indent + - name: Check that the sources are correctly formatted + run: | + git diff --exit-code || { + echo "::error::Sources are not correctly formatted. Run 'make indent' and commit the result." + exit 1 + } diff --git a/Makefile b/Makefile index 84ad090c..4de7a66b 100644 --- a/Makefile +++ b/Makefile @@ -127,8 +127,13 @@ tippecanoe-overzoom: overzoom.o mvt.o clip.o evaluator.o jsonpull/jsonpull.o tex clean: rm -f ./tippecanoe ./tippecanoe-* ./tile-join ./unit *.o *.d */*.o */*.d tests/**/*.mbtiles tests/**/*.check +# CI checks that the committed sources match what this produces, so run it before +# sending a pull request. Different clang-format versions format the same input +# differently, so the CI job pins one (see .github/workflows/test.yml); if your +# local version disagrees with it, let the job tell you what to fix rather than +# committing its idea of the formatting. indent: - clang-format -i -style="{BasedOnStyle: Google, IndentWidth: 8, UseTab: Always, AllowShortIfStatementsOnASingleLine: false, ColumnLimit: 0, ContinuationIndentWidth: 8, SpaceAfterCStyleCast: true, IndentCaseLabels: false, AllowShortBlocksOnASingleLine: false, AllowShortFunctionsOnASingleLine: false, SortIncludes: false}" $(filter-out flatgeobuf.cpp,$(C)) $(H) jsonpull/*.[ch] + clang-format -i -style="{BasedOnStyle: Google, IndentWidth: 8, UseTab: Always, AllowShortIfStatementsOnASingleLine: false, ColumnLimit: 0, ContinuationIndentWidth: 8, SpaceAfterCStyleCast: true, IndentCaseLabels: false, AllowShortBlocksOnASingleLine: false, AllowShortFunctionsOnASingleLine: false, SortIncludes: false, PointerAlignment: Right, DerivePointerAlignment: false}" $(C) $(H) jsonpull/*.[ch] TESTS = $(wildcard tests/*/out/*.json) SPACE = $(NULL) $(NULL) diff --git a/flatgeobuf.cpp b/flatgeobuf.cpp index c081128f..aca9d194 100644 --- a/flatgeobuf.cpp +++ b/flatgeobuf.cpp @@ -9,43 +9,42 @@ #include "errors.hpp" #include "thread.hpp" -static constexpr uint8_t magicbytes[8] = { 0x66, 0x67, 0x62, 0x03, 0x66, 0x67, 0x62, 0x01 }; +static constexpr uint8_t magicbytes[8] = {0x66, 0x67, 0x62, 0x03, 0x66, 0x67, 0x62, 0x01}; struct NodeItem { - double minX; - double minY; - double maxX; - double maxY; - uint64_t offset; + double minX; + double minY; + double maxX; + double maxY; + uint64_t offset; }; // copied from https://github.com/flatgeobuf/flatgeobuf/blob/master/src/cpp/packedrtree.cpp#L365 -uint64_t PackedRTreeSize(const uint64_t numItems, const uint16_t nodeSize) -{ - if (nodeSize < 2) - throw std::invalid_argument("Node size must be at least 2"); - if (numItems == 0) - throw std::invalid_argument("Number of items must be greater than 0"); - const uint16_t nodeSizeMin = std::min(std::max(nodeSize, static_cast(2)), static_cast(65535)); - // limit so that resulting size in bytes can be represented by uint64_t - if (numItems > static_cast(1) << 56) - throw std::overflow_error("Number of items must be less than 2^56"); - uint64_t n = numItems; - uint64_t numNodes = n; - do { - n = (n + nodeSizeMin - 1) / nodeSizeMin; - numNodes += n; - } while (n != 1); - return numNodes * sizeof(NodeItem); +uint64_t PackedRTreeSize(const uint64_t numItems, const uint16_t nodeSize) { + if (nodeSize < 2) + throw std::invalid_argument("Node size must be at least 2"); + if (numItems == 0) + throw std::invalid_argument("Number of items must be greater than 0"); + const uint16_t nodeSizeMin = std::min(std::max(nodeSize, static_cast(2)), static_cast(65535)); + // limit so that resulting size in bytes can be represented by uint64_t + if (numItems > static_cast(1) << 56) + throw std::overflow_error("Number of items must be less than 2^56"); + uint64_t n = numItems; + uint64_t numNodes = n; + do { + n = (n + nodeSizeMin - 1) / nodeSizeMin; + numNodes += n; + } while (n != 1); + return numNodes * sizeof(NodeItem); } drawvec readPoints(const FlatGeobuf::Geometry *geometry) { auto xy = geometry->xy(); drawvec dv; - for (unsigned int i = 0; i < xy->size(); i+=2) { + for (unsigned int i = 0; i < xy->size(); i += 2) { long long x, y; - projection->project(xy->Get(i), xy->Get(i+1), 32, &x, &y); + projection->project(xy->Get(i), xy->Get(i + 1), 32, &x, &y); dv.push_back(draw(VT_MOVETO, x, y)); } return dv; @@ -57,12 +56,13 @@ drawvec readLinePart(const FlatGeobuf::Geometry *geometry) { size_t current_end = 0; drawvec dv; - for (unsigned int i = 0; i < xy->size(); i+=2) { + for (unsigned int i = 0; i < xy->size(); i += 2) { long long x, y; - projection->project(xy->Get(i), xy->Get(i+1), 32, &x, &y); - if (i == 0 || (ends != NULL && current_end < ends->size() && i == ends->Get(current_end)*2)) { + projection->project(xy->Get(i), xy->Get(i + 1), 32, &x, &y); + if (i == 0 || (ends != NULL && current_end < ends->size() && i == ends->Get(current_end) * 2)) { dv.push_back(draw(VT_MOVETO, x, y)); - if (i > 0) current_end++; + if (i > 0) + current_end++; } else { dv.push_back(draw(VT_LINETO, x, y)); } @@ -72,12 +72,13 @@ drawvec readLinePart(const FlatGeobuf::Geometry *geometry) { drawvec readGeometry(const FlatGeobuf::Geometry *geometry, FlatGeobuf::GeometryType h_geometry_type) { FlatGeobuf::GeometryType geometry_type = h_geometry_type; - if (h_geometry_type == FlatGeobuf::GeometryType_Unknown) geometry_type = geometry->type(); + if (h_geometry_type == FlatGeobuf::GeometryType_Unknown) + geometry_type = geometry->type(); if (geometry_type == FlatGeobuf::GeometryType_Point) { return readPoints(geometry); } else if (geometry_type == FlatGeobuf::GeometryType_MultiPoint) { - return readPoints(geometry); + return readPoints(geometry); } else if (geometry_type == FlatGeobuf::GeometryType_LineString) { return readLinePart(geometry); } else if (geometry_type == FlatGeobuf::GeometryType_MultiLineString) { @@ -85,7 +86,7 @@ drawvec readGeometry(const FlatGeobuf::Geometry *geometry, FlatGeobuf::GeometryT } else if (geometry_type == FlatGeobuf::GeometryType_Polygon) { return readLinePart(geometry); } else if (geometry_type == FlatGeobuf::GeometryType_MultiPolygon) { - // if it is a GeometryCollection, parse Parts, ignore XY + // if it is a GeometryCollection, parse Parts, ignore XY drawvec dv; for (size_t part = 0; part < geometry->parts()->size(); part++) { drawvec dv2 = readLinePart(geometry->parts()->Get(part)); @@ -96,7 +97,7 @@ drawvec readGeometry(const FlatGeobuf::Geometry *geometry, FlatGeobuf::GeometryT } return dv; } else { - fprintf(stderr, "flatgeobuf has unsupported geometry type %u\n", (unsigned int)h_geometry_type); + fprintf(stderr, "flatgeobuf has unsupported geometry type %u\n", (unsigned int) h_geometry_type); exit(EXIT_IMPOSSIBLE); } } @@ -107,26 +108,27 @@ void readFeature(const FlatGeobuf::Feature *feature, long long feature_sequence_ int drawvec_type = -1; FlatGeobuf::GeometryType geometry_type = h_geometry_type; - if (h_geometry_type == FlatGeobuf::GeometryType_Unknown) geometry_type = feature->geometry()->type(); + if (h_geometry_type == FlatGeobuf::GeometryType_Unknown) + geometry_type = feature->geometry()->type(); switch (geometry_type) { - case FlatGeobuf::GeometryType_Point : - case FlatGeobuf::GeometryType_MultiPoint : - drawvec_type = 1; - break; - case FlatGeobuf::GeometryType_LineString : - case FlatGeobuf::GeometryType_MultiLineString : - drawvec_type = 2; - break; - case FlatGeobuf::GeometryType_Polygon : - case FlatGeobuf::GeometryType_MultiPolygon : - drawvec_type = 3; - break; - case FlatGeobuf::GeometryType_Unknown : - case FlatGeobuf::GeometryType_GeometryCollection : - default: - fprintf(stderr, "flatgeobuf has unsupported geometry type %u\n", (unsigned int)h_geometry_type); - exit(EXIT_IMPOSSIBLE); + case FlatGeobuf::GeometryType_Point: + case FlatGeobuf::GeometryType_MultiPoint: + drawvec_type = 1; + break; + case FlatGeobuf::GeometryType_LineString: + case FlatGeobuf::GeometryType_MultiLineString: + drawvec_type = 2; + break; + case FlatGeobuf::GeometryType_Polygon: + case FlatGeobuf::GeometryType_MultiPolygon: + drawvec_type = 3; + break; + case FlatGeobuf::GeometryType_Unknown: + case FlatGeobuf::GeometryType_GeometryCollection: + default: + fprintf(stderr, "flatgeobuf has unsupported geometry type %u\n", (unsigned int) h_geometry_type); + exit(EXIT_IMPOSSIBLE); } serial_feature sf; @@ -148,7 +150,7 @@ void readFeature(const FlatGeobuf::Feature *feature, long long feature_sequence_ std::vector> full_keys; std::vector full_values; - key_pool key_pool; + key_pool key_pool; // assume tabular schema with columns in header size_t p_pos = 0; @@ -236,12 +238,12 @@ void readFeature(const FlatGeobuf::Feature *feature, long long feature_sequence_ sv.type = mvt_string; uint32_t val_len; memcpy(&val_len, feature->properties()->data() + p_pos + sizeof(uint16_t), sizeof(val_len)); - std::string s{reinterpret_cast(feature->properties()->data() + p_pos + sizeof(uint16_t) + sizeof(uint32_t)), val_len}; + std::string s{reinterpret_cast(feature->properties()->data() + p_pos + sizeof(uint16_t) + sizeof(uint32_t)), val_len}; sv.s = s; p_pos += sizeof(uint16_t) + sizeof(uint32_t) + val_len; } else { // Binary is not representable in MVT - fprintf(stderr, "flatgeobuf has unsupported column type %u\n", (unsigned int)col_type); + fprintf(stderr, "flatgeobuf has unsupported column type %u\n", (unsigned int) col_type); exit(EXIT_IMPOSSIBLE); } full_keys.push_back(key_pool.pool(h_column_names[col_idx])); @@ -347,9 +349,9 @@ void queueFeature(const FlatGeobuf::Feature *feature, long long feature_sequence } void parse_flatgeobuf(std::vector *sst, const char *src, size_t len, int layer, std::string layername) { - auto header_size = flatbuffers::GetPrefixedSize((const uint8_t *)src + sizeof(magicbytes)); + auto header_size = flatbuffers::GetPrefixedSize((const uint8_t *) src + sizeof(magicbytes)); - flatbuffers::Verifier v((const uint8_t *)src+sizeof(magicbytes),header_size+sizeof(uint32_t)); + flatbuffers::Verifier v((const uint8_t *) src + sizeof(magicbytes), header_size + sizeof(uint32_t)); const auto ok = FlatGeobuf::VerifySizePrefixedHeaderBuffer(v); if (!ok) { fprintf(stderr, "flatgeobuf header verification failed\n"); @@ -378,15 +380,15 @@ void parse_flatgeobuf(std::vector *sst, const char * if (!quiet) { fprintf(stderr, "detected indexed FlatGeobuf: assigning feature IDs by sequence\n"); } - index_size = PackedRTreeSize(features_count,node_size); + index_size = PackedRTreeSize(features_count, node_size); feature_sequence_id = 0; } - const char* start = src + sizeof(magicbytes) + sizeof(uint32_t) + header_size + index_size; + const char *start = src + sizeof(magicbytes) + sizeof(uint32_t) + header_size + index_size; while (start < src + len) { - auto feature_size = flatbuffers::GetPrefixedSize((const uint8_t *)start); + auto feature_size = flatbuffers::GetPrefixedSize((const uint8_t *) start); - flatbuffers::Verifier v2((const uint8_t *)start,feature_size+sizeof(uint32_t)); + flatbuffers::Verifier v2((const uint8_t *) start, feature_size + sizeof(uint32_t)); const auto ok2 = FlatGeobuf::VerifySizePrefixedFeatureBuffer(v2); if (!ok2) { fprintf(stderr, "flatgeobuf feature buffer verification failed\n"); @@ -397,7 +399,8 @@ void parse_flatgeobuf(std::vector *sst, const char * queueFeature(feature, feature_sequence_id, h_geometry_type, h_column_names, h_column_types, sst, layer, layername); - if (feature_sequence_id >= 0) feature_sequence_id ++; + if (feature_sequence_id >= 0) + feature_sequence_id++; start += sizeof(uint32_t) + feature_size; } diff --git a/geometry.cpp b/geometry.cpp index 58d4f163..92544ad1 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -693,7 +693,7 @@ struct sorty { struct sorty_sorter { int kind; sorty_sorter(int k) - : kind(k){}; + : kind(k) {}; bool operator()(const sorty &a, const sorty &b) const { long long xa, ya, xb, yb; diff --git a/mvt.cpp b/mvt.cpp index 18f239d2..8042db7c 100644 --- a/mvt.cpp +++ b/mvt.cpp @@ -407,7 +407,7 @@ std::string mvt_tile::encode() { std::string feature_string; protozero::pbf_writer feature_writer(feature_string); - if (layers[i].features[f].type >= 0) + if (layers[i].features[f].type >= 0) feature_writer.add_enum(3, layers[i].features[f].type); std::vector sorted_tags = layers[i].features[f].tags; diff --git a/serial.cpp b/serial.cpp index 73868194..e2e91c29 100644 --- a/serial.cpp +++ b/serial.cpp @@ -676,7 +676,7 @@ int serialize_feature(struct serialization_state *sst, serial_feature &sf, std:: } else if (extent < 0) { sf.extent = LLONG_MIN; } else { - sf.extent = LLONG_MAX; // also the NaN case + sf.extent = LLONG_MAX; // also the NaN case } if (sst->want_dist && sf.t == VT_POLYGON) { diff --git a/tile-join.cpp b/tile-join.cpp index 017e04b8..7e594e66 100644 --- a/tile-join.cpp +++ b/tile-join.cpp @@ -336,7 +336,7 @@ void append_tile(std::string message, int z, unsigned x, unsigned y, std::map &attribute_values, double if (descending) { // For descending: drop features > threshold, keep features <= threshold // ix points at the last value to keep - size_t ix = (size_t)((attribute_values.size() - 1) * f); + size_t ix = (size_t) ((attribute_values.size() - 1) * f); while (ix > 0 && attribute_values[ix] >= existing_attribute) { ix--; } @@ -845,7 +845,7 @@ static double choose_minattribute(std::vector &attribute_values, double } else { // For ascending: drop features < threshold, keep features >= threshold // ix points at the first value to keep - size_t ix = (size_t)ceil((double)(attribute_values.size() - 1) * (1 - f)); + size_t ix = (size_t) ceil((double) (attribute_values.size() - 1) * (1 - f)); if (ix >= attribute_values.size()) { ix = attribute_values.size() - 1; } @@ -1744,7 +1744,7 @@ long long write_tile(decompressor *geoms, std::atomic *geompos_in, ch key_pool key_pool; - std::vector > within(child_shards); + std::vector> within(child_shards); std::vector start_geompos(child_shards); for (size_t i = 0; i < (size_t) child_shards; i++) { within[i] = false; @@ -2113,8 +2113,8 @@ long long write_tile(decompressor *geoms, std::atomic *geompos_in, ch if (attr_valid) { add_sample_to(attribute_values, attr_numeric, attribute_values_increment, seq); bool should_drop = arg->drop_by_attribute_descending - ? (minattribute != HUGE_VAL && attr_numeric > minattribute) - : (minattribute != -HUGE_VAL && attr_numeric < minattribute); + ? (minattribute != HUGE_VAL && attr_numeric > minattribute) + : (minattribute != -HUGE_VAL && attr_numeric < minattribute); if (should_drop) { can_stop_early = false; if (drop_feature_unless_it_can_be_added_to_a_multiplier_cluster(layer, sf, layer_unmaps, strategy, drop_rest, arg->attribute_accum, key_pool)) { @@ -2777,7 +2777,7 @@ long long write_tile(decompressor *geoms, std::atomic *geompos_in, ch } } else if (additional[A_DROP_BY_ATTRIBUTE_AS_NEEDED]) { minattribute_fraction = minattribute_fraction * - adjusted_max_tile_features / adjusted_feature_count * 0.75; + adjusted_max_tile_features / adjusted_feature_count * 0.75; if (minattribute_fraction > 0.80) { if (!quiet) { fprintf(stderr, @@ -3251,7 +3251,7 @@ int traverse_zooms(int *geomfd, off_t *geom_size, char *global_stringpool, std:: std::vector compressors(TEMP_FILES); std::vector sub(TEMP_FILES); - std::vector > subpos(TEMP_FILES); + std::vector> subpos(TEMP_FILES); std::vector subfd(TEMP_FILES); for (size_t j = 0; j < TEMP_FILES; j++) { std::string geomname = std::string(tmpdir) + "/geom" + std::to_string(j) + ".XXXXXXXX"; @@ -3459,8 +3459,8 @@ int traverse_zooms(int *geomfd, off_t *geom_size, char *global_stringpool, std:: again = true; } bool attr_propagate = drop_by_attribute_descending - ? args[thread].minattribute_out < zoom_minattribute - : args[thread].minattribute_out > zoom_minattribute; + ? args[thread].minattribute_out < zoom_minattribute + : args[thread].minattribute_out > zoom_minattribute; if (attr_propagate) { zoom_minattribute = args[thread].minattribute_out; again = true; diff --git a/unit.cpp b/unit.cpp index dc752152..aacfabcf 100644 --- a/unit.cpp +++ b/unit.cpp @@ -145,8 +145,8 @@ TEST_CASE("Polygon cleaning drops a hole that no ring can parent", "[wagyu]") { // through the "Could not properly place hole to a parent." handler in // clean_or_clip_poly instead of returning. static const std::vector>> rings = { - {{0, 5}, {5, 4}, {5, 1}, {4, 4}, {4, 2}, {7, 1}, {0, 5}}, - {{0, 5}, {7, 1}, {4, 2}, {4, 4}, {5, 1}, {5, 4}, {0, 0}, {0, 5}}, + {{0, 5}, {5, 4}, {5, 1}, {4, 4}, {4, 2}, {7, 1}, {0, 5}}, + {{0, 5}, {7, 1}, {4, 2}, {4, 4}, {5, 1}, {5, 4}, {0, 0}, {0, 5}}, }; drawvec geom;