h3 3.4.0 → 3.4.4

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.
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
  }