h3 3.4.4 → 3.5.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/Gemfile.lock +1 -1
- data/README.md +2 -1
- data/ext/h3/Makefile +1 -1
- data/ext/h3/src/.gitignore +2 -1
- data/ext/h3/src/CHANGELOG.md +9 -0
- data/ext/h3/src/CMakeLists.txt +72 -45
- data/ext/h3/src/RELEASE.md +2 -1
- data/ext/h3/src/VERSION +1 -1
- data/ext/h3/src/docs/api/hierarchy.md +2 -0
- data/ext/h3/src/docs/api/indexing.md +3 -1
- data/ext/h3/src/docs/api/inspection.md +20 -0
- data/ext/h3/src/docs/api/misc.md +2 -0
- data/ext/h3/src/docs/api/regions.md +2 -0
- data/ext/h3/src/docs/api/traversal.md +2 -0
- data/ext/h3/src/docs/api/uniedge.md +2 -0
- data/ext/h3/src/docs/community/bindings.md +4 -0
- data/ext/h3/src/docs/community/tutorials.md +12 -0
- data/ext/h3/src/scripts/update_version.sh +50 -0
- data/ext/h3/src/src/apps/applib/include/args.h +122 -0
- data/ext/h3/src/src/apps/applib/include/utility.h +5 -62
- data/ext/h3/src/src/apps/applib/lib/args.c +216 -0
- data/ext/h3/src/src/apps/applib/lib/utility.c +40 -206
- data/ext/h3/src/src/apps/filters/geoToH3.c +7 -9
- data/ext/h3/src/src/apps/filters/h3ToComponents.c +50 -47
- data/ext/h3/src/src/apps/filters/h3ToGeo.c +7 -30
- data/ext/h3/src/src/apps/filters/h3ToGeoBoundary.c +7 -27
- data/ext/h3/src/src/apps/filters/h3ToLocalIj.c +42 -25
- data/ext/h3/src/src/apps/filters/hexRange.c +43 -24
- data/ext/h3/src/src/apps/filters/kRing.c +4 -4
- data/ext/h3/src/src/apps/filters/localIjToH3.c +63 -21
- data/ext/h3/src/src/apps/miscapps/h3ToGeoBoundaryHier.c +68 -44
- data/ext/h3/src/src/apps/miscapps/h3ToGeoHier.c +68 -43
- data/ext/h3/src/src/apps/miscapps/h3ToHier.c +48 -37
- data/ext/h3/src/src/apps/testapps/mkRandGeo.c +32 -27
- data/ext/h3/src/src/apps/testapps/mkRandGeoBoundary.c +33 -28
- data/ext/h3/src/src/apps/testapps/testH3GetFaces.c +136 -0
- data/ext/h3/src/src/h3lib/include/faceijk.h +19 -7
- data/ext/h3/src/src/h3lib/include/h3api.h.in +12 -1
- data/ext/h3/src/src/h3lib/lib/algos.c +7 -2
- data/ext/h3/src/src/h3lib/lib/faceijk.c +135 -103
- data/ext/h3/src/src/h3lib/lib/h3Index.c +86 -5
- data/lib/h3/bindings/private.rb +1 -0
- data/lib/h3/inspection.rb +34 -0
- data/lib/h3/version.rb +1 -1
- data/spec/inspection_spec.rb +33 -1
- metadata +6 -2
@@ -0,0 +1,122 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright 2019 Uber Technologies, Inc.
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
* you may not use this file except in compliance with the License.
|
6
|
+
* You may obtain a copy of the License at
|
7
|
+
*
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
*
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
* See the License for the specific language governing permissions and
|
14
|
+
* limitations under the License.
|
15
|
+
*/
|
16
|
+
/** @file args.h
|
17
|
+
* @brief Miscellaneous functions and constants.
|
18
|
+
*/
|
19
|
+
|
20
|
+
#ifndef ARGS_H
|
21
|
+
#define ARGS_H
|
22
|
+
|
23
|
+
#include <inttypes.h>
|
24
|
+
#include <stdbool.h>
|
25
|
+
#include <stdio.h>
|
26
|
+
#include "utility.h"
|
27
|
+
|
28
|
+
/** Maximum number of names an argument may have. */
|
29
|
+
#define NUM_ARG_NAMES 2
|
30
|
+
|
31
|
+
/**
|
32
|
+
* An argument accepted by on the command line of an H3 application. Specifies
|
33
|
+
* how the argument is presented, parsed, and where parsed values are stored.
|
34
|
+
*/
|
35
|
+
typedef struct {
|
36
|
+
/**
|
37
|
+
* Both short and long names of the argument. A name may be null, but the
|
38
|
+
* first name must be non-null.
|
39
|
+
*/
|
40
|
+
const char* const names[NUM_ARG_NAMES];
|
41
|
+
|
42
|
+
/**
|
43
|
+
* If true, this argument must be specified. If the argument is not
|
44
|
+
* specified, argument parsing will fail.
|
45
|
+
*/
|
46
|
+
const bool required;
|
47
|
+
|
48
|
+
/**
|
49
|
+
* Scan format for the argument, which will be passed to sscanf. May be null
|
50
|
+
* to indicate the argument does not take a value.
|
51
|
+
*/
|
52
|
+
const char* const scanFormat;
|
53
|
+
|
54
|
+
/**
|
55
|
+
* Name to present the value as when printing help.
|
56
|
+
*/
|
57
|
+
const char* const valueName;
|
58
|
+
|
59
|
+
/**
|
60
|
+
* Value will be placed here if the argument is present and scanFormat is
|
61
|
+
* not null.
|
62
|
+
*/
|
63
|
+
void* const value;
|
64
|
+
|
65
|
+
/**
|
66
|
+
* Will be set to true if the argument is present. Should be false when
|
67
|
+
* passed in to parseArgs.
|
68
|
+
*/
|
69
|
+
bool found;
|
70
|
+
|
71
|
+
/**
|
72
|
+
* Help text for this argument.
|
73
|
+
*/
|
74
|
+
const char* const helpText;
|
75
|
+
} Arg;
|
76
|
+
|
77
|
+
// prototypes
|
78
|
+
|
79
|
+
int parseArgs(int argc, char* argv[], int numArgs, Arg* args[],
|
80
|
+
const Arg* helpArg, const char* helpText);
|
81
|
+
void printHelp(FILE* out, const char* programName, const char* helpText,
|
82
|
+
int numArgs, Arg* args[], const char* errorMessage,
|
83
|
+
const char* errorDetails);
|
84
|
+
|
85
|
+
int _parseArgsList(int argc, char* argv[], int numArgs, Arg* args[],
|
86
|
+
const Arg* helpArg, const char** errorMessage,
|
87
|
+
const char** errorDetail);
|
88
|
+
|
89
|
+
// common arguments
|
90
|
+
|
91
|
+
#define ARG_HELP \
|
92
|
+
{ .names = {"-h", "--help"}, .helpText = "Show this help message." }
|
93
|
+
#define DEFINE_INDEX_ARG(varName, argName) \
|
94
|
+
H3Index varName = 0; \
|
95
|
+
Arg argName = { \
|
96
|
+
.names = {"-i", "--index"}, \
|
97
|
+
.scanFormat = "%" PRIx64, \
|
98
|
+
.valueName = "index", \
|
99
|
+
.value = &varName, \
|
100
|
+
.helpText = \
|
101
|
+
"Index, or not specified to read indexes from standard input."}
|
102
|
+
#define ARG_KML \
|
103
|
+
{ .names = {"-k", "--kml"}, .helpText = "Print output in KML format." }
|
104
|
+
#define DEFINE_KML_NAME_ARG(varName, argName) \
|
105
|
+
char varName[BUFF_SIZE] = {0}; \
|
106
|
+
Arg argName = { \
|
107
|
+
.names = {"--kn", "--kml-name"}, \
|
108
|
+
.scanFormat = "%255c", /* BUFF_SIZE - 1 */ \
|
109
|
+
.valueName = "name", \
|
110
|
+
.value = &varName, \
|
111
|
+
.helpText = "Text for the KML name tag, if --kml is specified."}
|
112
|
+
#define DEFINE_KML_DESC_ARG(varName, argName) \
|
113
|
+
char varName[BUFF_SIZE] = {0}; \
|
114
|
+
Arg argName = { \
|
115
|
+
.names = {"--kd", "--kml-description"}, \
|
116
|
+
.scanFormat = "%255c", /* BUFF_SIZE - 1 */ \
|
117
|
+
.valueName = "description", \
|
118
|
+
.value = &varName, \
|
119
|
+
.helpText = \
|
120
|
+
"Text for the KML description tag, if --kml is specified."}
|
121
|
+
|
122
|
+
#endif
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/*
|
2
|
-
* Copyright 2016-
|
2
|
+
* Copyright 2016-2019 Uber Technologies, Inc.
|
3
3
|
*
|
4
4
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
5
|
* you may not use this file except in compliance with the License.
|
@@ -29,63 +29,6 @@
|
|
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
|
-
|
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
|
-
|
89
32
|
void error(const char* msg);
|
90
33
|
void h3Print(H3Index h); // prints as integer
|
91
34
|
void h3Println(H3Index h); // prints as integer
|
@@ -104,12 +47,12 @@ void geoBoundaryPrint(const GeoBoundary* b);
|
|
104
47
|
void geoBoundaryPrintln(const GeoBoundary* b);
|
105
48
|
int readBoundary(FILE* f, GeoBoundary* b);
|
106
49
|
|
50
|
+
void randomGeo(GeoCoord* p);
|
51
|
+
|
107
52
|
void iterateAllIndexesAtRes(int res, void (*callback)(H3Index));
|
108
53
|
void iterateAllIndexesAtResPartial(int res, void (*callback)(H3Index),
|
109
54
|
int maxBaseCell);
|
110
|
-
|
111
|
-
int
|
112
|
-
const Arg* helpArg, const char** errorMessage,
|
113
|
-
const char** errorDetail);
|
55
|
+
void iterateBaseCellIndexesAtRes(int res, void (*callback)(H3Index),
|
56
|
+
int baseCell);
|
114
57
|
|
115
58
|
#endif
|
@@ -0,0 +1,216 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright 2019 Uber Technologies, Inc.
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
* you may not use this file except in compliance with the License.
|
6
|
+
* You may obtain a copy of the License at
|
7
|
+
*
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
*
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
* See the License for the specific language governing permissions and
|
14
|
+
* limitations under the License.
|
15
|
+
*/
|
16
|
+
/** @file args.c
|
17
|
+
* @brief Miscellaneous useful functions.
|
18
|
+
*/
|
19
|
+
|
20
|
+
#include "args.h"
|
21
|
+
#include <stdbool.h>
|
22
|
+
#include <stdio.h>
|
23
|
+
#include <stdlib.h>
|
24
|
+
#include <string.h>
|
25
|
+
#include "h3api.h"
|
26
|
+
|
27
|
+
/*
|
28
|
+
* Return codes from parseArgs.
|
29
|
+
*/
|
30
|
+
|
31
|
+
#define PARSE_ARGS_SUCCESS 0
|
32
|
+
#define PARSE_ARGS_HELP 1
|
33
|
+
#define PARSE_ARGS_REPEATED_ARGUMENT 2
|
34
|
+
#define PARSE_ARGS_MISSING_VALUE 3
|
35
|
+
#define PARSE_ARGS_FAILED_PARSE 4
|
36
|
+
#define PARSE_ARGS_UNKNOWN_ARGUMENT 5
|
37
|
+
#define PARSE_ARGS_MISSING_REQUIRED 6
|
38
|
+
|
39
|
+
/**
|
40
|
+
* Parse command line arguments and prints help, if needed.
|
41
|
+
*
|
42
|
+
* Uses the provided arguments to populate argument values and records in the
|
43
|
+
* argument if it is found.
|
44
|
+
*
|
45
|
+
* Returns non-zero if all required arguments are not present, an argument fails
|
46
|
+
* to parse, is missing its associated value, or arguments are specified more
|
47
|
+
* than once.
|
48
|
+
*
|
49
|
+
* Help is printed to stdout if a argument with isHelp = true is found, and help
|
50
|
+
* is printed to stderr if argument parsing fails.
|
51
|
+
*
|
52
|
+
* @param argc argc from main
|
53
|
+
* @param argv argv from main
|
54
|
+
* @param numArgs Number of elements in the args array
|
55
|
+
* @param args Pointer to each argument to parse
|
56
|
+
* @param helpArg Pointer to the argument for "--help"
|
57
|
+
* @param helpText Explanatory text for this program printed with help
|
58
|
+
* @return 0 if argument parsing succeeded, otherwise non-0. If help is printed,
|
59
|
+
* return value is non-0.
|
60
|
+
*/
|
61
|
+
int parseArgs(int argc, char* argv[], int numArgs, Arg* args[],
|
62
|
+
const Arg* helpArg, const char* helpText) {
|
63
|
+
const char* errorMessage = NULL;
|
64
|
+
const char* errorDetails = NULL;
|
65
|
+
|
66
|
+
int failed = _parseArgsList(argc, argv, numArgs, args, helpArg,
|
67
|
+
&errorMessage, &errorDetails);
|
68
|
+
|
69
|
+
if (failed || helpArg->found) {
|
70
|
+
printHelp(helpArg->found ? stdout : stderr, argv[0], helpText, numArgs,
|
71
|
+
args, errorMessage, errorDetails);
|
72
|
+
return failed != PARSE_ARGS_SUCCESS ? failed : PARSE_ARGS_HELP;
|
73
|
+
}
|
74
|
+
return PARSE_ARGS_SUCCESS;
|
75
|
+
}
|
76
|
+
|
77
|
+
/**
|
78
|
+
* Parse command line arguments.
|
79
|
+
*
|
80
|
+
* Uses the provided arguments to populate argument values.
|
81
|
+
*
|
82
|
+
* Returns non-zero if all required arguments are not present, an argument fails
|
83
|
+
* to parse, is missing its associated value, or arguments are specified more
|
84
|
+
* than once.
|
85
|
+
*
|
86
|
+
* @param argc argc from main
|
87
|
+
* @param argv argv from main
|
88
|
+
* @param numArgs Number of elements in the args array
|
89
|
+
* @param args Pointer to each argument to parse.
|
90
|
+
* @param helpArg Pointer to the argument for "--help" that suppresses checking
|
91
|
+
* for required arguments.
|
92
|
+
* @param errorMessage Error message to display, if returning non-zero.
|
93
|
+
* @param errorDetail Additional error details, if returning non-zero. May be
|
94
|
+
* null, and may be a pointer from `argv` or `args`.
|
95
|
+
* @return 0 if argument parsing succeeded, otherwise non-0.
|
96
|
+
*/
|
97
|
+
int _parseArgsList(int argc, char* argv[], int numArgs, Arg* args[],
|
98
|
+
const Arg* helpArg, const char** errorMessage,
|
99
|
+
const char** errorDetail) {
|
100
|
+
// Whether help was found and required arguments do not need to be checked
|
101
|
+
bool foundHelp = false;
|
102
|
+
|
103
|
+
for (int i = 1; i < argc; i++) {
|
104
|
+
bool foundMatch = false;
|
105
|
+
|
106
|
+
for (int j = 0; j < numArgs; j++) {
|
107
|
+
// Test this argument, which may have multiple names, for whether it
|
108
|
+
// matches. argName will be set to the name used for this argument
|
109
|
+
// if it matches.
|
110
|
+
const char* argName = NULL;
|
111
|
+
for (int k = 0; k < NUM_ARG_NAMES; k++) {
|
112
|
+
if (args[j]->names[k] == NULL) continue;
|
113
|
+
|
114
|
+
if (strcmp(argv[i], args[j]->names[k]) == 0) {
|
115
|
+
argName = args[j]->names[k];
|
116
|
+
break;
|
117
|
+
}
|
118
|
+
}
|
119
|
+
// argName unchanged from NULL indicates this didn't match, try the
|
120
|
+
// next argument.
|
121
|
+
if (argName == NULL) continue;
|
122
|
+
|
123
|
+
if (args[j]->found) {
|
124
|
+
*errorMessage = "Argument specified multiple times";
|
125
|
+
*errorDetail = argName;
|
126
|
+
return PARSE_ARGS_REPEATED_ARGUMENT;
|
127
|
+
}
|
128
|
+
|
129
|
+
if (args[j]->scanFormat != NULL) {
|
130
|
+
// Argument has a value, need to advance one and read the value.
|
131
|
+
i++;
|
132
|
+
if (i >= argc) {
|
133
|
+
*errorMessage = "Argument value not present";
|
134
|
+
*errorDetail = argName;
|
135
|
+
return PARSE_ARGS_MISSING_VALUE;
|
136
|
+
}
|
137
|
+
|
138
|
+
if (!sscanf(argv[i], args[j]->scanFormat, args[j]->value)) {
|
139
|
+
*errorMessage = "Failed to parse argument";
|
140
|
+
*errorDetail = argName;
|
141
|
+
return PARSE_ARGS_FAILED_PARSE;
|
142
|
+
}
|
143
|
+
}
|
144
|
+
|
145
|
+
if (args[j] == helpArg) {
|
146
|
+
foundHelp = true;
|
147
|
+
}
|
148
|
+
|
149
|
+
args[j]->found = true;
|
150
|
+
foundMatch = true;
|
151
|
+
break;
|
152
|
+
}
|
153
|
+
|
154
|
+
if (!foundMatch) {
|
155
|
+
*errorMessage = "Unknown argument";
|
156
|
+
// Don't set errorDetail, since the input could be unprintable.
|
157
|
+
return PARSE_ARGS_UNKNOWN_ARGUMENT;
|
158
|
+
}
|
159
|
+
}
|
160
|
+
|
161
|
+
// Check for missing required arguments.
|
162
|
+
if (!foundHelp) {
|
163
|
+
for (int i = 0; i < numArgs; i++) {
|
164
|
+
if (args[i]->required && !args[i]->found) {
|
165
|
+
*errorMessage = "Required argument missing";
|
166
|
+
*errorDetail = args[i]->names[0];
|
167
|
+
return PARSE_ARGS_MISSING_REQUIRED;
|
168
|
+
}
|
169
|
+
}
|
170
|
+
}
|
171
|
+
|
172
|
+
return PARSE_ARGS_SUCCESS;
|
173
|
+
}
|
174
|
+
|
175
|
+
/**
|
176
|
+
* Print a help message.
|
177
|
+
*
|
178
|
+
* @param out Stream to print to, e.g. stdout
|
179
|
+
* @param programName Program name, such as from argv[0]
|
180
|
+
* @param helpText Explanation of what the program does
|
181
|
+
* @param numArgs Number of arguments to print help for
|
182
|
+
* @param args Pointer to arguments to print help for
|
183
|
+
* @param errorMessage Error message, or null
|
184
|
+
* @param errorDetails Additional error detail message, or null
|
185
|
+
*/
|
186
|
+
void printHelp(FILE* out, const char* programName, const char* helpText,
|
187
|
+
int numArgs, Arg* args[], const char* errorMessage,
|
188
|
+
const char* errorDetails) {
|
189
|
+
if (errorMessage != NULL) {
|
190
|
+
fprintf(out, "%s: %s", programName, errorMessage);
|
191
|
+
if (errorDetails != NULL) {
|
192
|
+
fprintf(out, ": %s", errorDetails);
|
193
|
+
}
|
194
|
+
fprintf(out, "\n");
|
195
|
+
}
|
196
|
+
fprintf(out, "%s: %s\n", programName, helpText);
|
197
|
+
fprintf(out, "H3 %d.%d.%d\n\n", H3_VERSION_MAJOR, H3_VERSION_MINOR,
|
198
|
+
H3_VERSION_PATCH);
|
199
|
+
|
200
|
+
for (int i = 0; i < numArgs; i++) {
|
201
|
+
fprintf(out, "\t");
|
202
|
+
for (int j = 0; j < NUM_ARG_NAMES; j++) {
|
203
|
+
if (args[i]->names[j] == NULL) continue;
|
204
|
+
if (j != 0) fprintf(out, ", ");
|
205
|
+
fprintf(out, "%s", args[i]->names[j]);
|
206
|
+
}
|
207
|
+
if (args[i]->scanFormat != NULL) {
|
208
|
+
fprintf(out, " <%s>", args[i]->valueName);
|
209
|
+
}
|
210
|
+
fprintf(out, "\t");
|
211
|
+
if (args[i]->required) {
|
212
|
+
fprintf(out, "Required. ");
|
213
|
+
}
|
214
|
+
fprintf(out, "%s\n", args[i]->helpText);
|
215
|
+
}
|
216
|
+
}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/*
|
2
|
-
* Copyright 2016-
|
2
|
+
* Copyright 2016-2019 Uber Technologies, Inc.
|
3
3
|
*
|
4
4
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
5
|
* you may not use this file except in compliance with the License.
|
@@ -20,206 +20,14 @@
|
|
20
20
|
#include "utility.h"
|
21
21
|
#include <assert.h>
|
22
22
|
#include <inttypes.h>
|
23
|
-
#include <stdbool.h>
|
24
23
|
#include <stdio.h>
|
25
24
|
#include <stdlib.h>
|
26
25
|
#include <string.h>
|
26
|
+
#include <time.h>
|
27
27
|
#include "coordijk.h"
|
28
|
-
#include "geoCoord.h"
|
29
28
|
#include "h3Index.h"
|
30
29
|
#include "h3api.h"
|
31
30
|
|
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
|
-
|
223
31
|
void error(const char* msg) {
|
224
32
|
fflush(stdout);
|
225
33
|
fflush(stderr);
|
@@ -382,20 +190,46 @@ void iterateAllIndexesAtResPartial(int res, void (*callback)(H3Index),
|
|
382
190
|
int baseCells) {
|
383
191
|
assert(baseCells <= NUM_BASE_CELLS);
|
384
192
|
for (int i = 0; i < baseCells; i++) {
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
H3Index* children = calloc(childrenSz, sizeof(H3Index));
|
389
|
-
H3_EXPORT(uncompact)(&bc, 1, children, childrenSz, res);
|
390
|
-
|
391
|
-
for (int j = 0; j < childrenSz; j++) {
|
392
|
-
if (children[j] == 0) {
|
393
|
-
continue;
|
394
|
-
}
|
193
|
+
iterateBaseCellIndexesAtRes(res, callback, i);
|
194
|
+
}
|
195
|
+
}
|
395
196
|
|
396
|
-
|
197
|
+
/**
|
198
|
+
* Call the callback for every index at the given resolution in a
|
199
|
+
* specific base cell
|
200
|
+
*/
|
201
|
+
void iterateBaseCellIndexesAtRes(int res, void (*callback)(H3Index),
|
202
|
+
int baseCell) {
|
203
|
+
H3Index bc;
|
204
|
+
setH3Index(&bc, 0, baseCell, 0);
|
205
|
+
int childrenSz = H3_EXPORT(maxUncompactSize)(&bc, 1, res);
|
206
|
+
H3Index* children = calloc(childrenSz, sizeof(H3Index));
|
207
|
+
H3_EXPORT(uncompact)(&bc, 1, children, childrenSz, res);
|
208
|
+
|
209
|
+
for (int j = 0; j < childrenSz; j++) {
|
210
|
+
if (children[j] == 0) {
|
211
|
+
continue;
|
397
212
|
}
|
398
213
|
|
399
|
-
|
214
|
+
(*callback)(children[j]);
|
400
215
|
}
|
216
|
+
|
217
|
+
free(children);
|
218
|
+
}
|
219
|
+
|
220
|
+
/**
|
221
|
+
* Generates a random lat/lon pair.
|
222
|
+
*
|
223
|
+
* @param g Lat/lon will be placed here.
|
224
|
+
*/
|
225
|
+
void randomGeo(GeoCoord* g) {
|
226
|
+
static int init = 0;
|
227
|
+
if (!init) {
|
228
|
+
srand((unsigned int)time(0));
|
229
|
+
init = 1;
|
230
|
+
}
|
231
|
+
|
232
|
+
g->lat = H3_EXPORT(degsToRads)(
|
233
|
+
(((float)rand() / (float)(RAND_MAX)) * 180.0) - 90.0);
|
234
|
+
g->lon = H3_EXPORT(degsToRads)((float)rand() / (float)(RAND_MAX)) * 360.0;
|
401
235
|
}
|