h3 3.4.0 → 3.4.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -1
  3. data/ext/h3/src/.travis.yml +5 -0
  4. data/ext/h3/src/CHANGELOG.md +25 -0
  5. data/ext/h3/src/CMakeLists.txt +5 -8
  6. data/ext/h3/src/CONTRIBUTING.md +2 -0
  7. data/ext/h3/src/README.md +6 -2
  8. data/ext/h3/src/VERSION +1 -1
  9. data/ext/h3/src/appveyor.yml +6 -1
  10. data/ext/h3/src/docs/api/misc.md +16 -0
  11. data/ext/h3/src/docs/community/bindings.md +9 -0
  12. data/ext/h3/src/docs/community/tutorials.md +4 -0
  13. data/ext/h3/src/scripts/binding_functions.ps1 +1 -2
  14. data/ext/h3/src/scripts/binding_functions.sh +3 -2
  15. data/ext/h3/src/scripts/coverage.sh.in +3 -3
  16. data/ext/h3/src/src/apps/applib/include/utility.h +60 -0
  17. data/ext/h3/src/src/apps/applib/lib/utility.c +196 -2
  18. data/ext/h3/src/src/apps/benchmarks/benchmarkPolyfill.c +7 -4
  19. data/ext/h3/src/src/apps/filters/geoToH3.c +73 -27
  20. data/ext/h3/src/src/apps/filters/h3ToGeo.c +63 -47
  21. data/ext/h3/src/src/apps/filters/h3ToGeoBoundary.c +64 -48
  22. data/ext/h3/src/src/apps/filters/h3ToLocalIj.c +4 -5
  23. data/ext/h3/src/src/apps/filters/hexRange.c +0 -1
  24. data/ext/h3/src/src/apps/filters/kRing.c +60 -28
  25. data/ext/h3/src/src/apps/filters/localIjToH3.c +75 -0
  26. data/ext/h3/src/src/apps/miscapps/generateBaseCellNeighbors.c +2 -2
  27. data/ext/h3/src/src/apps/testapps/testBBox.c +18 -0
  28. data/ext/h3/src/src/apps/testapps/testCompact.c +41 -0
  29. data/ext/h3/src/src/apps/testapps/testCoordIj.c +0 -1
  30. data/ext/h3/src/src/apps/testapps/testCoordIjk.c +53 -0
  31. data/ext/h3/src/src/apps/testapps/testH3Api.c +20 -0
  32. data/ext/h3/src/src/apps/testapps/testH3Distance.c +5 -3
  33. data/ext/h3/src/src/apps/testapps/testH3Line.c +18 -6
  34. data/ext/h3/src/src/apps/testapps/testH3ToLocalIj.c +75 -3
  35. data/ext/h3/src/src/apps/testapps/testH3UniEdge.c +17 -11
  36. data/ext/h3/src/src/apps/testapps/testHexRanges.c +10 -0
  37. data/ext/h3/src/src/apps/testapps/testKRing.c +11 -7
  38. data/ext/h3/src/src/h3lib/lib/algos.c +2 -1
  39. data/ext/h3/src/src/h3lib/lib/geoCoord.c +10 -10
  40. data/ext/h3/src/src/h3lib/lib/h3Index.c +1 -2
  41. data/ext/h3/src/src/h3lib/lib/localij.c +32 -36
  42. data/lib/h3/version.rb +1 -1
  43. metadata +4 -7
  44. data/ext/h3/src/cmake/CheckAlloca.cmake +0 -33
  45. data/ext/h3/src/cmake/CheckVLA.cmake +0 -33
  46. data/ext/h3/src/cmake/alloca_test.c +0 -29
  47. data/ext/h3/src/cmake/vla_test.c +0 -26
  48. data/ext/h3/src/src/h3lib/include/stackAlloc.h +0 -64
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4b2531121ded47b5f0d9d2b5f5a6a335f7fd2f0fb10b3662a27d53299337742c
4
- data.tar.gz: 3ba64616a8906422668fa9db3f17da9805dcfe7ff57fec8ccc32af750266dd56
3
+ metadata.gz: f9855fbbfa15205895e0467ef2561ec63580395d72c2cacf535c727dfca25e41
4
+ data.tar.gz: 2b92de2e824682fcaee25176007799203afb24180da11cac5d63d463d3649e90
5
5
  SHA512:
6
- metadata.gz: 7a135032876835619d79ebef8160bbb55115058a001dae8e3bcd90091c3ff140cbb2808fa44e98af2761dccd7b2adbb7344c154796732d69ce3bd9365fd3fb84
7
- data.tar.gz: 624c367307b48be1274f5a92ce600fa2f110ace2d1d8ef97285cec9e0f9fe66d08c8bf3f34a09c9968aa566b0f0158601a90127f3aa2ec201bb8923107854205
6
+ metadata.gz: '08630f598e940bd5f28f86292de45c50a84ac8bcd6965fd406b52cba745d825d8c3fcd18bf687831785a087f2a461a63c230b2a8bd599d26e2c9199c6516f4e3'
7
+ data.tar.gz: aa9fb82ed82cda98c56d75d89240cc556ca9568562d791aceaee5df084bb95b050c1d314a157d53a400020b25516ea86cf14f5e2ad18b56a0e74af4b67768aa9
data/CHANGELOG.md CHANGED
@@ -6,6 +6,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
7
  We track the MAJOR and MINOR version levels of Uber's H3 project (https://github.com/uber/h3) but maintain independent patch levels so we can make small fixes and non breaking changes.
8
8
 
9
+ ## [3.4.0] - 2019-1-24
10
+ ### Added
11
+ - `res_0_indexes` and `res_0_index_count` support (#51).
12
+
9
13
  ## [3.3.1] - 2019-1-4
10
14
  ### Added
11
15
  - `h3_line` and `h3_line_size` support (#43).
@@ -19,4 +23,4 @@ We track the MAJOR and MINOR version levels of Uber's H3 project (https://github
19
23
 
20
24
  ## [3.2.0] - 2018-12-21
21
25
 
22
- Initial release.
26
+ Initial release.
@@ -57,6 +57,11 @@ matrix:
57
57
  - coveralls --lcov-file coverage.cleaned.info --verbose
58
58
  - env: NAME="Mac OSX (Xcode 8)"
59
59
  os: osx
60
+ - env: NAME="binding-functions target"
61
+ script:
62
+ - make binding-functions
63
+ # Check that the file exists and has contents
64
+ - test -s binding-functions
60
65
 
61
66
  # Configure the build script, out of source.
62
67
  before_script:
@@ -7,6 +7,31 @@ The public API of this library consists of the functions declared in file
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [3.4.4] - 2019-05-30
11
+ ### Changed
12
+ - Local coordinate spaces cannot cross more than one icosahedron edge. (#234)
13
+ - All dynamic internal memory allocations happen on the heap instead of the stack. (#235)
14
+ - Argument parsing for `h3ToGeo`, `geoToH3`, and `h3ToGeoBoundary` is more flexible. (#227)
15
+
16
+ ## [3.4.3] - 2019-05-02
17
+ ### Added
18
+ - `localIjToH3` filter application (#222)
19
+ - An option to print distances in the `kRing` filter application (#222)
20
+ ### Changed
21
+ - Arguments parsing for `kRing` filter application is more flexible. (#224)
22
+ ### Fixed
23
+ - `benchmarkPolyfill` allocates its memory on the heap (#198)
24
+ - Fixed constraints of vertex longitudes (#213)
25
+ - Zero only input to `uncompact` does not produce an error (#223)
26
+
27
+ ## [3.4.2] - 2019-02-21
28
+ ### Changed
29
+ - `binding-functions` build target generates an ASCII file on Windows (#193)
30
+
31
+ ## [3.4.1] - 2019-02-15
32
+ ### Fixed
33
+ - `binding-functions` build target fixed when running the build out of source (#188)
34
+
10
35
  ## [3.4.0] - 2019-01-23
11
36
  ### Added
12
37
  - `getRes0Indexes` function for getting all base cells, and helper function `res0IndexCount` (#174)
@@ -79,12 +79,6 @@ include(CMakeDependentOption)
79
79
  include(CheckIncludeFile)
80
80
  include(CTest)
81
81
 
82
- include(CheckAlloca)
83
- include(CheckVLA)
84
-
85
- check_alloca(have_alloca)
86
- check_vla(have_vla)
87
-
88
82
  set(LIB_SOURCE_FILES
89
83
  src/h3lib/include/bbox.h
90
84
  src/h3lib/include/polygon.h
@@ -103,7 +97,6 @@ set(LIB_SOURCE_FILES
103
97
  src/h3lib/include/constants.h
104
98
  src/h3lib/include/coordijk.h
105
99
  src/h3lib/include/algos.h
106
- src/h3lib/include/stackAlloc.h
107
100
  src/h3lib/lib/algos.c
108
101
  src/h3lib/lib/coordijk.c
109
102
  src/h3lib/lib/bbox.c
@@ -136,6 +129,7 @@ set(EXAMPLE_SOURCE_FILES
136
129
  set(OTHER_SOURCE_FILES
137
130
  src/apps/filters/h3ToGeo.c
138
131
  src/apps/filters/h3ToLocalIj.c
132
+ src/apps/filters/localIjToH3.c
139
133
  src/apps/filters/h3ToComponents.c
140
134
  src/apps/filters/geoToH3.c
141
135
  src/apps/filters/h3ToGeoBoundary.c
@@ -171,6 +165,7 @@ set(OTHER_SOURCE_FILES
171
165
  src/apps/testapps/testH3Distance.c
172
166
  src/apps/testapps/testH3Line.c
173
167
  src/apps/testapps/testCoordIj.c
168
+ src/apps/testapps/testCoordIjk.c
174
169
  src/apps/miscapps/h3ToGeoBoundaryHier.c
175
170
  src/apps/miscapps/h3ToGeoHier.c
176
171
  src/apps/miscapps/generateBaseCellNeighbors.c
@@ -310,6 +305,7 @@ add_h3_executable(geoToH3 src/apps/filters/geoToH3.c ${APP_SOURCE_FILES})
310
305
  add_h3_executable(h3ToComponents src/apps/filters/h3ToComponents.c ${APP_SOURCE_FILES})
311
306
  add_h3_executable(h3ToGeo src/apps/filters/h3ToGeo.c ${APP_SOURCE_FILES})
312
307
  add_h3_executable(h3ToLocalIj src/apps/filters/h3ToLocalIj.c ${APP_SOURCE_FILES})
308
+ add_h3_executable(localIjToH3 src/apps/filters/localIjToH3.c ${APP_SOURCE_FILES})
313
309
  add_h3_executable(h3ToGeoBoundary src/apps/filters/h3ToGeoBoundary.c ${APP_SOURCE_FILES})
314
310
  add_h3_executable(hexRange src/apps/filters/hexRange.c ${APP_SOURCE_FILES})
315
311
  add_h3_executable(kRing src/apps/filters/kRing.c ${APP_SOURCE_FILES})
@@ -363,7 +359,7 @@ if(BUILD_TESTING)
363
359
  COMMAND bash "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/scripts/coverage.sh" "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}")
364
360
  add_custom_target(clean-coverage
365
361
  # Before running coverage, clear all counters
366
- COMMAND lcov --directory '${CMAKE_CURRENT_BINARY_DIR}' --zerocounters
362
+ COMMAND lcov --rc lcov_branch_coverage=1 --directory '${CMAKE_CURRENT_BINARY_DIR}' --zerocounters
367
363
  COMMENT "Zeroing counters"
368
364
  )
369
365
  endif()
@@ -485,6 +481,7 @@ if(BUILD_TESTING)
485
481
  add_h3_test(testH3Distance src/apps/testapps/testH3Distance.c)
486
482
  add_h3_test(testH3Line src/apps/testapps/testH3Line.c)
487
483
  add_h3_test(testCoordIj src/apps/testapps/testCoordIj.c)
484
+ add_h3_test(testCoordIjk src/apps/testapps/testCoordIjk.c)
488
485
  add_h3_test(testBaseCells src/apps/testapps/testBaseCells.c)
489
486
 
490
487
  add_h3_test_with_arg(testH3NeighborRotations src/apps/testapps/testH3NeighborRotations.c 0)
@@ -2,6 +2,8 @@
2
2
 
3
3
  Pull requests and Github issues are welcome!
4
4
 
5
+ Planned improvements and changes are listed on the [H3 Roadmap](https://github.com/uber/h3/wiki/Roadmap). Roadmap items are currently discussed in Github issues. Feel free to open a discussion about an existing roadmap item or proposing a new one.
6
+
5
7
  ## Pull requests
6
8
 
7
9
  * Please include tests that show the bug is fixed or feature works as intended.
data/ext/h3/src/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # H3: A Hexagonal Hierarchical Geospatial Indexing System
2
2
 
3
- [![Build Status](https://travis-ci.org/uber/h3.svg?branch=master)](https://travis-ci.org/uber/h3)
3
+ [![Build Status](https://travis-ci.com/uber/h3.svg?branch=master)](https://travis-ci.com/uber/h3)
4
4
  [![Build status](https://ci.appveyor.com/api/projects/status/61431y4sc5w0tsuk/branch/master?svg=true)](https://ci.appveyor.com/project/Uber/h3/branch/master)
5
5
  [![Coverage Status](https://coveralls.io/repos/github/uber/h3/badge.svg?branch=master)](https://coveralls.io/github/uber/h3?branch=master)
6
6
  [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)
@@ -16,7 +16,11 @@ Documentation is available at [https://uber.github.io/h3/](https://uber.github.i
16
16
 
17
17
  We recommend using prebuilt bindings if they are available for your programming language. Bindings for [Go](https://github.com/uber/h3-go), [Java](https://github.com/uber/h3-java), [JavaScript](https://github.com/uber/h3-js), [Python](https://github.com/uber/h3-py), and [others](https://uber.github.io/h3/#/documentation/community/bindings) are available.
18
18
 
19
- If no bindings are available, you can only install H3 by building from source.
19
+ On macOS, you can install H3 using brew:
20
+ ```
21
+ brew install h3
22
+ ```
23
+ Otherwise, to build H3 from source, please see the following instructions.
20
24
 
21
25
  ### Building from source
22
26
 
data/ext/h3/src/VERSION CHANGED
@@ -1 +1 @@
1
- 3.4.0
1
+ 3.4.4
@@ -39,7 +39,12 @@ environment:
39
39
  build_script:
40
40
  - cmake "-G%GENERATOR%" -H. -Bbuild
41
41
  - cmake --build build --config "%CONFIG%"
42
+ - cmake --build build --config "%CONFIG%" --target binding-functions
42
43
 
43
44
  test_script:
44
45
  - ps: cd build
45
- - ctest -VV -C "%CONFIG%"
46
+ - ctest -C "%CONFIG%"
47
+ # Check that binding-functions was generated and has content
48
+ - ps: |
49
+ $ErrorActionPreference = "Stop"
50
+ if ((Get-Item "binding-functions").Length -lt 10) { $host.SetShouldExit(1) }
@@ -55,3 +55,19 @@ int64_t numHexagons(int res);
55
55
  ```
56
56
 
57
57
  Number of unique **H3** indexes at the given resolution.
58
+
59
+ ## getRes0Indexes
60
+
61
+ ```
62
+ void getRes0Indexes(H3Index *out);
63
+ ```
64
+
65
+ All the resolution 0 **H3** indexes.
66
+
67
+ ## res0IndexCount
68
+
69
+ ```
70
+ int res0IndexCount();
71
+ ```
72
+
73
+ Number of resolution 0 **H3** indexes.
@@ -6,6 +6,10 @@ As a C library, bindings can be made to call H3 functions from different program
6
6
 
7
7
  - [entrepreneur-interet-general/h3.standard](https://github.com/entrepreneur-interet-general/H3.Standard)
8
8
 
9
+ ## ECL
10
+
11
+ - [hpcc-systems/HPCC-Platform](https://github.com/hpcc-systems/HPCC-Platform/tree/master/plugins/h3)
12
+
9
13
  ## Erlang
10
14
 
11
15
  - [helium/erlang-h3](https://github.com/helium/erlang-h3)
@@ -23,6 +27,10 @@ As a C library, bindings can be made to call H3 functions from different program
23
27
  - [uber/h3-js](https://github.com/uber/h3-js)
24
28
  - [dfellis/h3-node](https://github.com/dfellis/h3-node)
25
29
 
30
+ ## Julia
31
+
32
+ - [wookay/H3.jl](https://github.com/wookay/H3.jl)
33
+
26
34
  ## OCaml
27
35
 
28
36
  - [travisbrady/ocaml-h3](https://github.com/travisbrady/ocaml-h3)
@@ -43,6 +51,7 @@ As a C library, bindings can be made to call H3 functions from different program
43
51
  ## R
44
52
 
45
53
  - [scottmmjackson/h3r](https://github.com/scottmmjackson/h3r)
54
+ - [crazycapivara/h3-r](https://github.com/crazycapivara/h3-r)
46
55
 
47
56
  ## Ruby
48
57
 
@@ -2,6 +2,10 @@
2
2
 
3
3
  This page lists further learning materials and code walkthroughs for the H3 library and bindings. Contributions to this list are welcome, please feel free to open a [pull request](https://github.com/uber/h3/tree/master/docs/community/tutorials.md).
4
4
 
5
+ ## Java
6
+
7
+ - [H3 Measurements](https://github.com/isaacbrodsky/h3measurements): Measurements of average cell area, average cell perimeter length, truncation error, and so on.
8
+
5
9
  ## JavaScript
6
10
 
7
11
  - [H3 Tutorials on Observable](https://beta.observablehq.com/collection/@nrabinowitz/h3-tutorial)
@@ -16,5 +16,4 @@
16
16
  # by bindings of the H3 library. It is invoked by the `binding-functions`
17
17
  # make target and produces a file `binding-functions`.
18
18
 
19
- $scriptDir = Split-Path -parent $PSCommandPath
20
- Get-Content "$scriptDir/../src/h3lib/include/h3api.h" | Where-Object {$_ -match "@defgroup ([A-Za-z0-9_]*)"} | Foreach {$Matches[1]} > binding-functions
19
+ Get-Content "src/h3lib/include/h3api.h" | Where-Object {$_ -match "@defgroup ([A-Za-z0-9_]*)"} | Foreach {$Matches[1]} | Out-File -FilePath binding-functions -Encoding ASCII
@@ -17,5 +17,6 @@
17
17
  # by bindings of the H3 library. It is invoked by the `binding-functions`
18
18
  # make target and produces a file `binding-functions`.
19
19
 
20
- SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")"
21
- cat "$SCRIPT_DIR/../src/h3lib/include/h3api.h" | sed -n '/@defgroup/s/.*@defgroup \([A-Za-z0-9_]*\) .*/\1/gp' > binding-functions
20
+ set -eo pipefail
21
+
22
+ cat "src/h3lib/include/h3api.h" | sed -n '/@defgroup/s/.*@defgroup \([A-Za-z0-9_]*\) .*/\1/gp' > binding-functions
@@ -45,6 +45,6 @@ src_dir=${1:-"Missing source directory"}
45
45
  binary_dir=${2:-"Missing binary directory"}
46
46
 
47
47
  cd "${binary_dir}"
48
- lcov --directory . --capture --output-file coverage.info
49
- lcov --extract coverage.info "${src_dir}/src/h3lib/*" --output-file coverage.cleaned.info
50
- genhtml -o coverage coverage.cleaned.info --title 'h3 coverage'
48
+ lcov --rc lcov_branch_coverage=1 --directory . --capture --output-file coverage.info
49
+ lcov --rc lcov_branch_coverage=1 --extract coverage.info "${src_dir}/src/h3lib/*" --output-file coverage.cleaned.info
50
+ genhtml --branch-coverage -o coverage coverage.cleaned.info --title 'h3 coverage'
@@ -29,7 +29,63 @@
29
29
  /** Macro: Get the size of a fixed-size array */
30
30
  #define ARRAY_SIZE(x) sizeof(x) / sizeof(x[0])
31
31
 
32
+ /** Maximum number of names an argument may have. */
33
+ #define NUM_ARG_NAMES 2
34
+
35
+ /**
36
+ * An argument accepted by on the command line of an H3 application. Specifies
37
+ * how the argument is presented, parsed, and where parsed values are stored.
38
+ */
39
+ typedef struct {
40
+ /**
41
+ * Both short and long names of the argument. A name may be null, but the
42
+ * first name must be non-null.
43
+ */
44
+ const char* const names[NUM_ARG_NAMES];
45
+
46
+ /**
47
+ * If true, this argument must be specified. If the argument is not
48
+ * specified, argument parsing will fail.
49
+ */
50
+ const bool required;
51
+
52
+ /**
53
+ * Scan format for the argument, which will be passed to sscanf. May be null
54
+ * to indicate the argument does not take a value.
55
+ */
56
+ const char* const scanFormat;
57
+
58
+ /**
59
+ * Name to present the value as when printing help.
60
+ */
61
+ const char* const valueName;
62
+
63
+ /**
64
+ * Value will be placed here if the argument is present and scanFormat is
65
+ * not null.
66
+ */
67
+ void* const value;
68
+
69
+ /**
70
+ * Will be set to true if the argument is present. Should be false when
71
+ * passed in to parseArgs.
72
+ */
73
+ bool found;
74
+
75
+ /**
76
+ * Help text for this argument.
77
+ */
78
+ const char* const helpText;
79
+ } Arg;
80
+
32
81
  // prototypes
82
+
83
+ int parseArgs(int argc, char* argv[], int numArgs, Arg* args[],
84
+ const Arg* helpArg, const char* helpText);
85
+ void printHelp(FILE* out, const char* programName, const char* helpText,
86
+ int numArgs, Arg* args[], const char* errorMessage,
87
+ const char* errorDetails);
88
+
33
89
  void error(const char* msg);
34
90
  void h3Print(H3Index h); // prints as integer
35
91
  void h3Println(H3Index h); // prints as integer
@@ -52,4 +108,8 @@ void iterateAllIndexesAtRes(int res, void (*callback)(H3Index));
52
108
  void iterateAllIndexesAtResPartial(int res, void (*callback)(H3Index),
53
109
  int maxBaseCell);
54
110
 
111
+ int _parseArgsList(int argc, char* argv[], int numArgs, Arg* args[],
112
+ const Arg* helpArg, const char** errorMessage,
113
+ const char** errorDetail);
114
+
55
115
  #endif
@@ -20,14 +20,206 @@
20
20
  #include "utility.h"
21
21
  #include <assert.h>
22
22
  #include <inttypes.h>
23
- #include <stackAlloc.h>
23
+ #include <stdbool.h>
24
24
  #include <stdio.h>
25
25
  #include <stdlib.h>
26
+ #include <string.h>
26
27
  #include "coordijk.h"
27
28
  #include "geoCoord.h"
28
29
  #include "h3Index.h"
29
30
  #include "h3api.h"
30
31
 
32
+ /*
33
+ * Return codes from parseArgs.
34
+ */
35
+
36
+ #define PARSE_ARGS_SUCCESS 0
37
+ #define PARSE_ARGS_HELP 1
38
+ #define PARSE_ARGS_REPEATED_ARGUMENT 2
39
+ #define PARSE_ARGS_MISSING_VALUE 3
40
+ #define PARSE_ARGS_FAILED_PARSE 4
41
+ #define PARSE_ARGS_UNKNOWN_ARGUMENT 5
42
+ #define PARSE_ARGS_MISSING_REQUIRED 6
43
+
44
+ /**
45
+ * Parse command line arguments and prints help, if needed.
46
+ *
47
+ * Uses the provided arguments to populate argument values and records in the
48
+ * argument if it is found.
49
+ *
50
+ * Returns non-zero if all required arguments are not present, an argument fails
51
+ * to parse, is missing its associated value, or arguments are specified more
52
+ * than once.
53
+ *
54
+ * Help is printed to stdout if a argument with isHelp = true is found, and help
55
+ * is printed to stderr if argument parsing fails.
56
+ *
57
+ * @param argc argc from main
58
+ * @param argv argv from main
59
+ * @param numArgs Number of elements in the args array
60
+ * @param args Pointer to each argument to parse
61
+ * @param helpArg Pointer to the argument for "--help"
62
+ * @param helpText Explanatory text for this program printed with help
63
+ * @return 0 if argument parsing succeeded, otherwise non-0. If help is printed,
64
+ * return value is non-0.
65
+ */
66
+ int parseArgs(int argc, char* argv[], int numArgs, Arg* args[],
67
+ const Arg* helpArg, const char* helpText) {
68
+ const char* errorMessage = NULL;
69
+ const char* errorDetails = NULL;
70
+
71
+ int failed = _parseArgsList(argc, argv, numArgs, args, helpArg,
72
+ &errorMessage, &errorDetails);
73
+
74
+ if (failed || helpArg->found) {
75
+ printHelp(helpArg->found ? stdout : stderr, argv[0], helpText, numArgs,
76
+ args, errorMessage, errorDetails);
77
+ return failed != PARSE_ARGS_SUCCESS ? failed : PARSE_ARGS_HELP;
78
+ }
79
+ return PARSE_ARGS_SUCCESS;
80
+ }
81
+
82
+ /**
83
+ * Parse command line arguments.
84
+ *
85
+ * Uses the provided arguments to populate argument values.
86
+ *
87
+ * Returns non-zero if all required arguments are not present, an argument fails
88
+ * to parse, is missing its associated value, or arguments are specified more
89
+ * than once.
90
+ *
91
+ * @param argc argc from main
92
+ * @param argv argv from main
93
+ * @param numArgs Number of elements in the args array
94
+ * @param args Pointer to each argument to parse.
95
+ * @param helpArg Pointer to the argument for "--help" that suppresses checking
96
+ * for required arguments.
97
+ * @param errorMessage Error message to display, if returning non-zero.
98
+ * @param errorDetail Additional error details, if returning non-zero. May be
99
+ * null, and may be a pointer from `argv` or `args`.
100
+ * @return 0 if argument parsing succeeded, otherwise non-0.
101
+ */
102
+ int _parseArgsList(int argc, char* argv[], int numArgs, Arg* args[],
103
+ const Arg* helpArg, const char** errorMessage,
104
+ const char** errorDetail) {
105
+ // Whether help was found and required arguments do not need to be checked
106
+ bool foundHelp = false;
107
+
108
+ for (int i = 1; i < argc; i++) {
109
+ bool foundMatch = false;
110
+
111
+ for (int j = 0; j < numArgs; j++) {
112
+ // Test this argument, which may have multiple names, for whether it
113
+ // matches. argName will be set to the name used for this argument
114
+ // if it matches.
115
+ const char* argName = NULL;
116
+ for (int k = 0; k < NUM_ARG_NAMES; k++) {
117
+ if (args[j]->names[k] == NULL) continue;
118
+
119
+ if (strcmp(argv[i], args[j]->names[k]) == 0) {
120
+ argName = args[j]->names[k];
121
+ break;
122
+ }
123
+ }
124
+ // argName unchanged from NULL indicates this didn't match, try the
125
+ // next argument.
126
+ if (argName == NULL) continue;
127
+
128
+ if (args[j]->found) {
129
+ *errorMessage = "Argument specified multiple times";
130
+ *errorDetail = argName;
131
+ return PARSE_ARGS_REPEATED_ARGUMENT;
132
+ }
133
+
134
+ if (args[j]->scanFormat != NULL) {
135
+ // Argument has a value, need to advance one and read the value.
136
+ i++;
137
+ if (i >= argc) {
138
+ *errorMessage = "Argument value not present";
139
+ *errorDetail = argName;
140
+ return PARSE_ARGS_MISSING_VALUE;
141
+ }
142
+
143
+ if (!sscanf(argv[i], args[j]->scanFormat, args[j]->value)) {
144
+ *errorMessage = "Failed to parse argument";
145
+ *errorDetail = argName;
146
+ return PARSE_ARGS_FAILED_PARSE;
147
+ }
148
+ }
149
+
150
+ if (args[j] == helpArg) {
151
+ foundHelp = true;
152
+ }
153
+
154
+ args[j]->found = true;
155
+ foundMatch = true;
156
+ break;
157
+ }
158
+
159
+ if (!foundMatch) {
160
+ *errorMessage = "Unknown argument";
161
+ // Don't set errorDetail, since the input could be unprintable.
162
+ return PARSE_ARGS_UNKNOWN_ARGUMENT;
163
+ }
164
+ }
165
+
166
+ // Check for missing required arguments.
167
+ if (!foundHelp) {
168
+ for (int i = 0; i < numArgs; i++) {
169
+ if (args[i]->required && !args[i]->found) {
170
+ *errorMessage = "Required argument missing";
171
+ *errorDetail = args[i]->names[0];
172
+ return PARSE_ARGS_MISSING_REQUIRED;
173
+ }
174
+ }
175
+ }
176
+
177
+ return PARSE_ARGS_SUCCESS;
178
+ }
179
+
180
+ /**
181
+ * Print a help message.
182
+ *
183
+ * @param out Stream to print to, e.g. stdout
184
+ * @param programName Program name, such as from argv[0]
185
+ * @param helpText Explanation of what the program does
186
+ * @param numArgs Number of arguments to print help for
187
+ * @param args Pointer to arguments to print help for
188
+ * @param errorMessage Error message, or null
189
+ * @param errorDetails Additional error detail message, or null
190
+ */
191
+ void printHelp(FILE* out, const char* programName, const char* helpText,
192
+ int numArgs, Arg* args[], const char* errorMessage,
193
+ const char* errorDetails) {
194
+ if (errorMessage != NULL) {
195
+ fprintf(out, "%s: %s", programName, errorMessage);
196
+ if (errorDetails != NULL) {
197
+ fprintf(out, ": %s", errorDetails);
198
+ }
199
+ fprintf(out, "\n");
200
+ }
201
+ fprintf(out, "%s: %s\n", programName, helpText);
202
+ fprintf(out, "H3 %d.%d.%d\n\n", H3_VERSION_MAJOR, H3_VERSION_MINOR,
203
+ H3_VERSION_PATCH);
204
+
205
+ for (int i = 0; i < numArgs; i++) {
206
+ fprintf(out, "\t");
207
+ for (int j = 0; j < NUM_ARG_NAMES; j++) {
208
+ if (args[i]->names[j] == NULL) continue;
209
+ if (j != 0) fprintf(out, ", ");
210
+ fprintf(out, "%s", args[i]->names[j]);
211
+ }
212
+ if (args[i]->scanFormat != NULL) {
213
+ fprintf(out, " <%s>", args[i]->valueName);
214
+ }
215
+ fprintf(out, "\t");
216
+ if (args[i]->required) {
217
+ fprintf(out, "Required. ");
218
+ }
219
+ fprintf(out, "%s\n", args[i]->helpText);
220
+ }
221
+ }
222
+
31
223
  void error(const char* msg) {
32
224
  fflush(stdout);
33
225
  fflush(stderr);
@@ -193,7 +385,7 @@ void iterateAllIndexesAtResPartial(int res, void (*callback)(H3Index),
193
385
  H3Index bc;
194
386
  setH3Index(&bc, 0, i, 0);
195
387
  int childrenSz = H3_EXPORT(maxUncompactSize)(&bc, 1, res);
196
- STACK_ARRAY_CALLOC(H3Index, children, childrenSz);
388
+ H3Index* children = calloc(childrenSz, sizeof(H3Index));
197
389
  H3_EXPORT(uncompact)(&bc, 1, children, childrenSz, res);
198
390
 
199
391
  for (int j = 0; j < childrenSz; j++) {
@@ -203,5 +395,7 @@ void iterateAllIndexesAtResPartial(int res, void (*callback)(H3Index),
203
395
 
204
396
  (*callback)(children[j]);
205
397
  }
398
+
399
+ free(children);
206
400
  }
207
401
  }