ext/h3/src/src/apps/applib/lib/utility.c in h3-3.4.4 vs ext/h3/src/src/apps/applib/lib/utility.c in h3-3.5.0
- old
+ new
@@ -1,7 +1,7 @@
/*
- * Copyright 2016-2018 Uber Technologies, Inc.
+ * Copyright 2016-2019 Uber Technologies, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
@@ -18,210 +18,18 @@
*/
#include "utility.h"
#include <assert.h>
#include <inttypes.h>
-#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
#include "coordijk.h"
-#include "geoCoord.h"
#include "h3Index.h"
#include "h3api.h"
-/*
- * Return codes from parseArgs.
- */
-
-#define PARSE_ARGS_SUCCESS 0
-#define PARSE_ARGS_HELP 1
-#define PARSE_ARGS_REPEATED_ARGUMENT 2
-#define PARSE_ARGS_MISSING_VALUE 3
-#define PARSE_ARGS_FAILED_PARSE 4
-#define PARSE_ARGS_UNKNOWN_ARGUMENT 5
-#define PARSE_ARGS_MISSING_REQUIRED 6
-
-/**
- * Parse command line arguments and prints help, if needed.
- *
- * Uses the provided arguments to populate argument values and records in the
- * argument if it is found.
- *
- * Returns non-zero if all required arguments are not present, an argument fails
- * to parse, is missing its associated value, or arguments are specified more
- * than once.
- *
- * Help is printed to stdout if a argument with isHelp = true is found, and help
- * is printed to stderr if argument parsing fails.
- *
- * @param argc argc from main
- * @param argv argv from main
- * @param numArgs Number of elements in the args array
- * @param args Pointer to each argument to parse
- * @param helpArg Pointer to the argument for "--help"
- * @param helpText Explanatory text for this program printed with help
- * @return 0 if argument parsing succeeded, otherwise non-0. If help is printed,
- * return value is non-0.
- */
-int parseArgs(int argc, char* argv[], int numArgs, Arg* args[],
- const Arg* helpArg, const char* helpText) {
- const char* errorMessage = NULL;
- const char* errorDetails = NULL;
-
- int failed = _parseArgsList(argc, argv, numArgs, args, helpArg,
- &errorMessage, &errorDetails);
-
- if (failed || helpArg->found) {
- printHelp(helpArg->found ? stdout : stderr, argv[0], helpText, numArgs,
- args, errorMessage, errorDetails);
- return failed != PARSE_ARGS_SUCCESS ? failed : PARSE_ARGS_HELP;
- }
- return PARSE_ARGS_SUCCESS;
-}
-
-/**
- * Parse command line arguments.
- *
- * Uses the provided arguments to populate argument values.
- *
- * Returns non-zero if all required arguments are not present, an argument fails
- * to parse, is missing its associated value, or arguments are specified more
- * than once.
- *
- * @param argc argc from main
- * @param argv argv from main
- * @param numArgs Number of elements in the args array
- * @param args Pointer to each argument to parse.
- * @param helpArg Pointer to the argument for "--help" that suppresses checking
- * for required arguments.
- * @param errorMessage Error message to display, if returning non-zero.
- * @param errorDetail Additional error details, if returning non-zero. May be
- * null, and may be a pointer from `argv` or `args`.
- * @return 0 if argument parsing succeeded, otherwise non-0.
- */
-int _parseArgsList(int argc, char* argv[], int numArgs, Arg* args[],
- const Arg* helpArg, const char** errorMessage,
- const char** errorDetail) {
- // Whether help was found and required arguments do not need to be checked
- bool foundHelp = false;
-
- for (int i = 1; i < argc; i++) {
- bool foundMatch = false;
-
- for (int j = 0; j < numArgs; j++) {
- // Test this argument, which may have multiple names, for whether it
- // matches. argName will be set to the name used for this argument
- // if it matches.
- const char* argName = NULL;
- for (int k = 0; k < NUM_ARG_NAMES; k++) {
- if (args[j]->names[k] == NULL) continue;
-
- if (strcmp(argv[i], args[j]->names[k]) == 0) {
- argName = args[j]->names[k];
- break;
- }
- }
- // argName unchanged from NULL indicates this didn't match, try the
- // next argument.
- if (argName == NULL) continue;
-
- if (args[j]->found) {
- *errorMessage = "Argument specified multiple times";
- *errorDetail = argName;
- return PARSE_ARGS_REPEATED_ARGUMENT;
- }
-
- if (args[j]->scanFormat != NULL) {
- // Argument has a value, need to advance one and read the value.
- i++;
- if (i >= argc) {
- *errorMessage = "Argument value not present";
- *errorDetail = argName;
- return PARSE_ARGS_MISSING_VALUE;
- }
-
- if (!sscanf(argv[i], args[j]->scanFormat, args[j]->value)) {
- *errorMessage = "Failed to parse argument";
- *errorDetail = argName;
- return PARSE_ARGS_FAILED_PARSE;
- }
- }
-
- if (args[j] == helpArg) {
- foundHelp = true;
- }
-
- args[j]->found = true;
- foundMatch = true;
- break;
- }
-
- if (!foundMatch) {
- *errorMessage = "Unknown argument";
- // Don't set errorDetail, since the input could be unprintable.
- return PARSE_ARGS_UNKNOWN_ARGUMENT;
- }
- }
-
- // Check for missing required arguments.
- if (!foundHelp) {
- for (int i = 0; i < numArgs; i++) {
- if (args[i]->required && !args[i]->found) {
- *errorMessage = "Required argument missing";
- *errorDetail = args[i]->names[0];
- return PARSE_ARGS_MISSING_REQUIRED;
- }
- }
- }
-
- return PARSE_ARGS_SUCCESS;
-}
-
-/**
- * Print a help message.
- *
- * @param out Stream to print to, e.g. stdout
- * @param programName Program name, such as from argv[0]
- * @param helpText Explanation of what the program does
- * @param numArgs Number of arguments to print help for
- * @param args Pointer to arguments to print help for
- * @param errorMessage Error message, or null
- * @param errorDetails Additional error detail message, or null
- */
-void printHelp(FILE* out, const char* programName, const char* helpText,
- int numArgs, Arg* args[], const char* errorMessage,
- const char* errorDetails) {
- if (errorMessage != NULL) {
- fprintf(out, "%s: %s", programName, errorMessage);
- if (errorDetails != NULL) {
- fprintf(out, ": %s", errorDetails);
- }
- fprintf(out, "\n");
- }
- fprintf(out, "%s: %s\n", programName, helpText);
- fprintf(out, "H3 %d.%d.%d\n\n", H3_VERSION_MAJOR, H3_VERSION_MINOR,
- H3_VERSION_PATCH);
-
- for (int i = 0; i < numArgs; i++) {
- fprintf(out, "\t");
- for (int j = 0; j < NUM_ARG_NAMES; j++) {
- if (args[i]->names[j] == NULL) continue;
- if (j != 0) fprintf(out, ", ");
- fprintf(out, "%s", args[i]->names[j]);
- }
- if (args[i]->scanFormat != NULL) {
- fprintf(out, " <%s>", args[i]->valueName);
- }
- fprintf(out, "\t");
- if (args[i]->required) {
- fprintf(out, "Required. ");
- }
- fprintf(out, "%s\n", args[i]->helpText);
- }
-}
-
void error(const char* msg) {
fflush(stdout);
fflush(stderr);
fprintf(stderr, "ERROR: %s.\n", msg);
exit(1);
@@ -380,22 +188,48 @@
*/
void iterateAllIndexesAtResPartial(int res, void (*callback)(H3Index),
int baseCells) {
assert(baseCells <= NUM_BASE_CELLS);
for (int i = 0; i < baseCells; i++) {
- H3Index bc;
- setH3Index(&bc, 0, i, 0);
- int childrenSz = H3_EXPORT(maxUncompactSize)(&bc, 1, res);
- H3Index* children = calloc(childrenSz, sizeof(H3Index));
- H3_EXPORT(uncompact)(&bc, 1, children, childrenSz, res);
+ iterateBaseCellIndexesAtRes(res, callback, i);
+ }
+}
- for (int j = 0; j < childrenSz; j++) {
- if (children[j] == 0) {
- continue;
- }
+/**
+ * Call the callback for every index at the given resolution in a
+ * specific base cell
+ */
+void iterateBaseCellIndexesAtRes(int res, void (*callback)(H3Index),
+ int baseCell) {
+ H3Index bc;
+ setH3Index(&bc, 0, baseCell, 0);
+ int childrenSz = H3_EXPORT(maxUncompactSize)(&bc, 1, res);
+ H3Index* children = calloc(childrenSz, sizeof(H3Index));
+ H3_EXPORT(uncompact)(&bc, 1, children, childrenSz, res);
- (*callback)(children[j]);
+ for (int j = 0; j < childrenSz; j++) {
+ if (children[j] == 0) {
+ continue;
}
- free(children);
+ (*callback)(children[j]);
}
+
+ free(children);
+}
+
+/**
+ * Generates a random lat/lon pair.
+ *
+ * @param g Lat/lon will be placed here.
+ */
+void randomGeo(GeoCoord* g) {
+ static int init = 0;
+ if (!init) {
+ srand((unsigned int)time(0));
+ init = 1;
+ }
+
+ g->lat = H3_EXPORT(degsToRads)(
+ (((float)rand() / (float)(RAND_MAX)) * 180.0) - 90.0);
+ g->lon = H3_EXPORT(degsToRads)((float)rand() / (float)(RAND_MAX)) * 360.0;
}