diff --git a/src/apps/filters/h3.c b/src/apps/filters/h3.c index e11c002b3..a21c10f67 100644 --- a/src/apps/filters/h3.c +++ b/src/apps/filters/h3.c @@ -727,6 +727,468 @@ SUBCOMMAND(localIjToCell, return E_SUCCESS; } +/// Hierarchical subcommands + +SUBCOMMAND(cellToParent, + "Returns the H3 index that is the parent (or higher) of the " + "provided cell") { + DEFINE_CELL_ARG(cell, cellArg); + int res = 0; + Arg resArg = {.names = {"-r", "--resolution"}, + .required = true, + .scanFormat = "%d", + .valueName = "res", + .value = &res, + .helpText = + "Resolution, 0-14 inclusive, excluding 15 as it can " + "never be a parent"}; + Arg *args[] = {&cellToParentArg, &helpArg, &cellArg, &resArg}; + PARSE_SUBCOMMAND(argc, argv, args); + H3Index parent; + int valid = H3_EXPORT(isValidCell)(cell); + if (valid == 0) { + return E_CELL_INVALID; + } + H3Error err = H3_EXPORT(cellToParent)(cell, res, &parent); + if (err) { + return err; + } + h3Println(parent); + return E_SUCCESS; +} + +SUBCOMMAND(cellToChildren, + "Returns a JSON array of H3 indexes that are the children (or " + "lower) of the provided cell") { + // TODO: This function contains a lot of code that is very similar to + // `gridDisk`. If this happens again we should DRY them. + DEFINE_CELL_ARG(cell, cellArg); + int res = 0; + Arg resArg = {.names = {"-r", "--resolution"}, + .required = true, + .scanFormat = "%d", + .valueName = "res", + .value = &res, + .helpText = + "Resolution, 1-15 inclusive, excluding 0 as it can " + "never be a child"}; + Arg *args[] = {&cellToChildrenArg, &helpArg, &cellArg, &resArg}; + PARSE_SUBCOMMAND(argc, argv, args); + int64_t len = 0; + H3Error err = H3_EXPORT(cellToChildrenSize)(cell, res, &len); + if (err) { + return err; + } + H3Index *out = calloc(len, sizeof(H3Index)); + if (out == NULL) { + fprintf(stderr, "Failed to allocate memory for the output H3 cells"); + exit(1); + } + err = H3_EXPORT(cellToChildren)(cell, res, out); + if (err) { + free(out); + return err; + } + // Since we don't know *actually* how many cells are in the output (usually + // the max, but sometimes not), we need to do a quick scan to figure out the + // true length in order to properly serialize to a JSON array + int64_t trueLen = 0; + for (int64_t i = 0; i < len; i++) { + if (out[i] != 0) { + trueLen++; + } + } + printf("[ "); + for (int64_t i = 0, j = 0; i < len; i++) { + if (out[i] != 0) { + j++; + printf("\"%" PRIx64 "\"%s", out[i], j == trueLen ? "" : ", "); + } + } + free(out); + printf(" ]\n"); + return E_SUCCESS; +} + +SUBCOMMAND(cellToChildrenSize, + "Returns the maximum number of children for a given cell at the " + "specified child resolution") { + // TODO: Do we want to include this subcommand or no? It can be useful to + // let someone decide for themselves if they really want to run the command + // and get a potentially massive number of cells as the output, but is that + // a concern a CLI user would have? They'd probably just ^C it. + DEFINE_CELL_ARG(cell, cellArg); + int res = 0; + Arg resArg = {.names = {"-r", "--resolution"}, + .required = true, + .scanFormat = "%d", + .valueName = "res", + .value = &res, + .helpText = + "Resolution, 1-15 inclusive, excluding 0 as it can " + "never be a child"}; + Arg *args[] = {&cellToChildrenSizeArg, &helpArg, &cellArg, &resArg}; + PARSE_SUBCOMMAND(argc, argv, args); + int64_t len = 0; + H3Error err = H3_EXPORT(cellToChildrenSize)(cell, res, &len); + if (err) { + return err; + } + printf("%" PRId64, len); + return E_SUCCESS; +} + +SUBCOMMAND( + cellToCenterChild, + "Returns the H3 index that is the centrally-placed child (or lower) of the " + "provided cell") { + DEFINE_CELL_ARG(cell, cellArg); + int res = 0; + Arg resArg = {.names = {"-r", "--resolution"}, + .required = true, + .scanFormat = "%d", + .valueName = "res", + .value = &res, + .helpText = + "Resolution, 1-15 inclusive, excluding 0 as it can " + "never be a child"}; + Arg *args[] = {&cellToCenterChildArg, &helpArg, &cellArg, &resArg}; + PARSE_SUBCOMMAND(argc, argv, args); + H3Index centerChild; + int valid = H3_EXPORT(isValidCell)(cell); + if (valid == 0) { + return E_CELL_INVALID; + } + H3Error err = H3_EXPORT(cellToCenterChild)(cell, res, ¢erChild); + if (err) { + return err; + } + h3Println(centerChild); + return E_SUCCESS; +} + +SUBCOMMAND( + cellToChildPos, + "Returns the position of the child cell within an ordered list of all " + "children of the cell's parent at the specified child resolution") { + DEFINE_CELL_ARG(cell, cellArg); + int res = 0; + Arg resArg = {.names = {"-r", "--resolution"}, + .required = true, + .scanFormat = "%d", + .valueName = "res", + .value = &res, + .helpText = + "Resolution, 1-15 inclusive, excluding 0 as it can " + "never be a child"}; + Arg *args[] = {&cellToChildPosArg, &helpArg, &cellArg, &resArg}; + PARSE_SUBCOMMAND(argc, argv, args); + int64_t len = 0; + H3Error err = H3_EXPORT(cellToChildPos)(cell, res, &len); + if (err) { + return err; + } + printf("%" PRId64, len); + return E_SUCCESS; +} + +SUBCOMMAND(childPosToCell, + "Returns the child cell at a given position and resolution within " + "an ordered list of all children of the parent cell") { + DEFINE_CELL_ARG(cell, cellArg); + int res = 0; + Arg resArg = {.names = {"-r", "--resolution"}, + .required = true, + .scanFormat = "%d", + .valueName = "res", + .value = &res, + .helpText = + "Resolution, 1-15 inclusive, excluding 0 as it can " + "never be a child"}; + int64_t pos; + Arg posArg = { + .names = {"-p", "--position"}, + .required = true, + .scanFormat = "%" PRIi64, + .valueName = "pos", + .value = &pos, + .helpText = + "The child position within the set of children of the parent cell"}; + Arg *args[] = {&childPosToCellArg, &helpArg, &cellArg, &resArg, &posArg}; + PARSE_SUBCOMMAND(argc, argv, args); + H3Index child; + int valid = H3_EXPORT(isValidCell)(cell); + if (valid == 0) { + return E_CELL_INVALID; + } + H3Error err = H3_EXPORT(childPosToCell)(pos, cell, res, &child); + if (err) { + return err; + } + h3Println(child); + return E_SUCCESS; +} + +H3Index *readCellsFromFile(FILE *fp, char *buffer, size_t *totalCells) { + // It's assumed the buffer is a character array of size 1501 to support up + // to 100 cells at a time. If the file pointer is a null pointer, we assume + // the buffer has all of the possible cells already stored in it and go from + // there. Otherwise we continue reading from the file until it's fully + // consumed. On an error, we de-allocate the output buffer and then return + // 0. It's the responsibility of the caller to free the returned buffer and + // the file pointer otherwise. The output array's filled length is set on + // the cellsOffset pointer so it can be used by the caller. + H3Index *cells = calloc(128, sizeof(H3Index)); + int cellsLen = 128; + int bufferOffset = 0; + int cellsOffset = 0; + do { + // Always start from the beginning of the buffer + bufferOffset = 0; + int lastGoodOffset = 0; + H3Index cell = 0; + while (bufferOffset < 1485) { // Keep consuming as much as possible + // A valid H3 cell is exactly 15 hexadecomical characters. + // Determine if we have a match, otherwise increment + int scanlen = 0; + sscanf(buffer + bufferOffset, "%" PRIx64 "%n", &cell, &scanlen); + if (scanlen != 15) { + cell = 0; + bufferOffset += 1; + } else { + bufferOffset += 16; + lastGoodOffset = bufferOffset; + } + // If we still don't have a cell and we've reached the end, we reset + // the offset and `continue` to trigger another read + if (cell == 0 && bufferOffset == 1500) { + bufferOffset = 0; + continue; + } else if (cell != 0) { + // Otherwise, we have a cell to shove into the cells array. + cells[cellsOffset] = cell; + cellsOffset += 1; + // Potentially grow our array + if (cellsOffset == cellsLen) { + cellsLen *= 2; + H3Index *newCells = calloc(cellsLen, sizeof(H3Index)); + for (int i = 0; i < cellsOffset; i++) { + newCells[i] = cells[i]; + } + free(cells); + cells = newCells; + } + } + } + // In case there's a valid H3 index that was unfortunately split between + // buffer reads, we take from the lastGoodOffset and copy the rest to + // the beginning of the buffer so it can be re-assembled on the next + // file read. However, we also know that a valid H3 index is 15 + // characters long, so if the lastGoodOffset is 15 or more characters + // away from 1500, we only need to copy those final 14 bytes from the + // end, so if lastGoodOffset is 1485 or less, we force it to 1485 and + // then move the chunk as specified to the beginning and adjust the + // cellStrsOffset. + if (lastGoodOffset < 1485) { + lastGoodOffset = 1485; + } + for (int i = 0; i < 1500 - lastGoodOffset; i++) { + buffer[i] = buffer[i + lastGoodOffset]; + } + bufferOffset = 1500 - lastGoodOffset; + } while (fp != 0 && + fread(buffer + bufferOffset, 1, 1500 - bufferOffset, fp) != 0); + *totalCells = cellsOffset; + return cells; +} + +SUBCOMMAND(compactCells, + "Compacts the provided set of cells as best as possible. The set of " + "input cells must all share the same resolution. The compacted " + "cells will be printed one per line to stdout.") { + char filename[1024] = {0}; // More than Windows, lol + Arg filenameArg = { + .names = {"-f", "--file"}, + .scanFormat = "%1023c", + .valueName = "FILENAME", + .value = &filename, + .helpText = + "The file to load the cells from. Use -- to read from stdin."}; + char cellStrs[1501] = {0}; // Up to 100 cells with zero padding + Arg cellStrsArg = {.names = {"-c", "--cells"}, + .scanFormat = "%1500c", + .valueName = "CELLS", + .value = &cellStrs, + .helpText = + "The cells to compact. Up to 100 cells if provided " + "as hexadecimals with zero padding."}; + Arg *args[] = {&compactCellsArg, &helpArg, &filenameArg, &cellStrsArg}; + PARSE_SUBCOMMAND(argc, argv, args); + if (!filenameArg.found && !cellStrsArg.found) { + fprintf(stderr, + "You must provide either a file to read from or a set of cells " + "to compact to use compactCells"); + exit(1); + } + FILE *fp = 0; + bool isStdin = false; + if (filenameArg.found) { + if (strcmp(filename, "--") == 0) { + fp = stdin; + isStdin = true; + } else { + fp = fopen(filename, "r"); + } + if (fp == 0) { + fprintf(stderr, "The specified file does not exist."); + exit(1); + } + // Do the initial population of data from the file + if (fread(cellStrs, 1, 1500, fp) == 0) { + fprintf(stderr, "The specified file is empty."); + exit(1); + } + } + size_t cellsOffset = 0; + H3Index *cells = readCellsFromFile(fp, cellStrs, &cellsOffset); + if (fp != 0 && !isStdin) { + fclose(fp); + } + if (cells == NULL) { + return E_FAILED; + } + // Now that we have the cells in a buffer and the actual cell count in + // cellsOffset, we can feed this to the H3 C API + H3Index *compactedSet = calloc(cellsOffset, sizeof(H3Index)); + H3Error err = H3_EXPORT(compactCells)(cells, compactedSet, cellsOffset); + if (err) { + free(cells); + free(compactedSet); + return err; + } + // We have a compacted set! Let's print them out + for (int i = 0; i < cellsOffset; i++) { + if (compactedSet[i] == 0) { + continue; + } + h3Println(compactedSet[i]); + } + free(cells); + free(compactedSet); + return E_SUCCESS; +} + +SUBCOMMAND(uncompactCells, + "Unompacts the provided set of compacted cells." + "The uncompacted " + "cells will be printed one per line to stdout.") { + // TODO: *Most* of this logic is shared with compactCells. See about DRYing + // it. + char filename[1024] = {0}; // More than Windows, lol + Arg filenameArg = { + .names = {"-f", "--file"}, + .scanFormat = "%1023c", + .valueName = "FILENAME", + .value = &filename, + .helpText = + "The file to load the cells from. Use -- to read from stdin."}; + char cellStrs[1501] = { + 0}; // Supports up to 100 cells at a time with zero padding + Arg cellStrsArg = { + .names = {"-c", "--cells"}, + .scanFormat = "%1500c", + .valueName = "CELLS", + .value = &cellStrs, + .helpText = + "The cells to uncompact. Up to 100 cells if provided " + "as hexadecimals with zero padding."}; + int res = 0; + Arg resArg = {.names = {"-r", "--resolution"}, + .required = true, + .scanFormat = "%d", + .valueName = "res", + .value = &res, + .helpText = + "Resolution, 0-15 inclusive, that the compacted set " + "should be uncompacted to. Must be greater than or equal " + "to the highest resolution within the compacted set."}; + Arg *args[] = {&uncompactCellsArg, &helpArg, &filenameArg, &cellStrsArg, + &resArg}; + PARSE_SUBCOMMAND(argc, argv, args); + if (!filenameArg.found && !cellStrsArg.found) { + fprintf(stderr, + "You must provide either a file to read from or a set of cells " + "to compact to use uncompactCells"); + exit(1); + } + // We use the same consumption logic for both kinds of input, and in fact + // use the cellStrs char array as out input buffer for the file path. The + // only difference between the two is when we reach the end of the buffer. + // If there's a non-null file pointer, we start from the last successful + // consumption from the buffer and move the data following it to the + // beginning of the buffer, then we read some of the file after that and + // slap it on after that and continue the consumption loops, while the other + // path just ends at that point. As we have no idea how many cells we're + // going to load, we allocate enough for 128 cells, but if that's not + // enough, we also have to re-allocate double the number of cells, copy them + // over, and free the old buffer of cells. Doing this manually since we want + // to keep the build process for H3 simple and C's stdlib is pretty bare. + FILE *fp = 0; + bool isStdin = false; + if (filenameArg.found) { + if (strcmp(filename, "--") == 0) { + fp = stdin; + isStdin = true; + } else { + fp = fopen(filename, "r"); + } + if (fp == 0) { + fprintf(stderr, "The specified file does not exist."); + exit(1); + } + // Do the initial population of data from the file + if (fread(cellStrs, 1, 1500, fp) == 0) { + fprintf(stderr, "The specified file is empty."); + exit(1); + } + } + size_t cellsOffset = 0; + H3Index *cells = readCellsFromFile(fp, cellStrs, &cellsOffset); + if (fp != 0 && !isStdin) { + fclose(fp); + } + if (cells == NULL) { + return E_FAILED; + } + // Now that we have the cells in a buffer and the actual cell count in + // cellsOffset, we can feed this to the H3 C API + int64_t uncompactedSize = 0; + H3Error err = H3_EXPORT(uncompactCellsSize)(cells, cellsOffset, res, + &uncompactedSize); + if (err) { + free(cells); + return err; + } + H3Index *uncompactedSet = calloc(uncompactedSize, sizeof(H3Index)); + err = H3_EXPORT(uncompactCells)(cells, cellsOffset, uncompactedSet, + uncompactedSize, res); + if (err) { + free(cells); + free(uncompactedSet); + return err; + } + // We have a compacted set! Let's print them out + for (int i = 0; i < uncompactedSize; i++) { + if (uncompactedSet[i] == 0) { + continue; + } + h3Println(uncompactedSet[i]); + } + free(cells); + free(uncompactedSet); + return E_SUCCESS; +} + // TODO: Is there any way to avoid this particular piece of duplication? SUBCOMMANDS_INDEX @@ -754,6 +1216,16 @@ SUBCOMMAND_INDEX(gridDistance) SUBCOMMAND_INDEX(cellToLocalIj) SUBCOMMAND_INDEX(localIjToCell) +/// Hierarchical subcommands +SUBCOMMAND_INDEX(cellToParent) +SUBCOMMAND_INDEX(cellToChildren) +SUBCOMMAND_INDEX(cellToChildrenSize) +SUBCOMMAND_INDEX(cellToCenterChild) +SUBCOMMAND_INDEX(cellToChildPos) +SUBCOMMAND_INDEX(childPosToCell) +SUBCOMMAND_INDEX(compactCells) +SUBCOMMAND_INDEX(uncompactCells) + END_SUBCOMMANDS_INDEX int main(int argc, char *argv[]) { diff --git a/tests/cli/cellToCenterChild.txt b/tests/cli/cellToCenterChild.txt new file mode 100644 index 000000000..a7212b3c3 --- /dev/null +++ b/tests/cli/cellToCenterChild.txt @@ -0,0 +1 @@ +add_h3_cli_test(testCliCellToCenterChild "cellToCenterChild -c 85283473fffffff --resolution 7" "872834700ffffff") diff --git a/tests/cli/cellToChildPos.txt b/tests/cli/cellToChildPos.txt new file mode 100644 index 000000000..05df374c2 --- /dev/null +++ b/tests/cli/cellToChildPos.txt @@ -0,0 +1 @@ +add_h3_cli_test(testCliCellToChildPos "cellToChildPos -c 85283473fffffff -r 3" "25") diff --git a/tests/cli/cellToChildren.txt b/tests/cli/cellToChildren.txt new file mode 100644 index 000000000..d6d8905e7 --- /dev/null +++ b/tests/cli/cellToChildren.txt @@ -0,0 +1 @@ +add_h3_cli_test(testCliCellToChildren "cellToChildren -c 85283473fffffff -r 6" "[ \"862834707ffffff\", \"86283470fffffff\", \"862834717ffffff\", \"86283471fffffff\", \"862834727ffffff\", \"86283472fffffff\", \"862834737ffffff\" ]") diff --git a/tests/cli/cellToChildrenSize.txt b/tests/cli/cellToChildrenSize.txt new file mode 100644 index 000000000..f51b29e5d --- /dev/null +++ b/tests/cli/cellToChildrenSize.txt @@ -0,0 +1 @@ +add_h3_cli_test(testCliCellToChildrenSize "cellToChildrenSize -c 85283473fffffff -r 6" "7") diff --git a/tests/cli/cellToParent.txt b/tests/cli/cellToParent.txt new file mode 100644 index 000000000..8ecd61423 --- /dev/null +++ b/tests/cli/cellToParent.txt @@ -0,0 +1 @@ +add_h3_cli_test(testCliCellToParent "cellToParent -c 8928342e20fffff --resolution 3" "832834fffffffff") diff --git a/tests/cli/childPosToCell.txt b/tests/cli/childPosToCell.txt new file mode 100644 index 000000000..60f1e7398 --- /dev/null +++ b/tests/cli/childPosToCell.txt @@ -0,0 +1 @@ +add_h3_cli_test(testCliChildPosToCell "childPosToCell -c 85283473fffffff -r 7 -p 42" "872834730ffffff") diff --git a/tests/cli/compactCells.txt b/tests/cli/compactCells.txt new file mode 100644 index 000000000..1873e9376 --- /dev/null +++ b/tests/cli/compactCells.txt @@ -0,0 +1,9 @@ +add_h3_cli_test(testCliCompactCellsFile1 "compactCells -f ${PROJECT_SOURCE_DIR}/tests/inputfiles/compact_test1.txt | tr -s '\\\\r\\\\n' ',' | tr -s '\\\\n' ','" "85283447fffffff,8528340ffffffff,8528340bfffffff,85283457fffffff,85283443fffffff,8528344ffffffff,852836b7fffffff,8528342bfffffff,8528343bfffffff,85283407fffffff,85283403fffffff,8528341bfffffff,8428347ffffffff,") +add_h3_cli_test(testCliCompactCellsFile2 "compactCells -f ${PROJECT_SOURCE_DIR}/tests/inputfiles/compact_test2.txt | tr -s '\\\\r\\\\n' ',' | tr -s '\\\\n' ','" "85283447fffffff,8528340ffffffff,8528340bfffffff,85283457fffffff,85283443fffffff,8528344ffffffff,852836b7fffffff,8528342bfffffff,8528343bfffffff,85283407fffffff,85283403fffffff,8528341bfffffff,8428347ffffffff,") +add_h3_cli_test(testCliCompactCellsFile3 "compactCells -f ${PROJECT_SOURCE_DIR}/tests/inputfiles/compact_test3.txt | tr -s '\\\\r\\\\n' ',' | tr -s '\\\\n' ','" "85283447fffffff,8528340ffffffff,8528340bfffffff,85283457fffffff,85283443fffffff,8528344ffffffff,852836b7fffffff,8528342bfffffff,8528343bfffffff,85283407fffffff,85283403fffffff,8528341bfffffff,8428347ffffffff,") +add_h3_cli_test(testCliCompactCellsStdin1 "compactCells -f -- < ${PROJECT_SOURCE_DIR}/tests/inputfiles/compact_test1.txt | tr -s '\\\\r\\\\n' ',' | tr -s '\\\\n' ','" "85283447fffffff,8528340ffffffff,8528340bfffffff,85283457fffffff,85283443fffffff,8528344ffffffff,852836b7fffffff,8528342bfffffff,8528343bfffffff,85283407fffffff,85283403fffffff,8528341bfffffff,8428347ffffffff,") +add_h3_cli_test(testCliCompactCellsStdin2 "compactCells -f -- < ${PROJECT_SOURCE_DIR}/tests/inputfiles/compact_test2.txt | tr -s '\\\\r\\\\n' ',' | tr -s '\\\\n' ','" "85283447fffffff,8528340ffffffff,8528340bfffffff,85283457fffffff,85283443fffffff,8528344ffffffff,852836b7fffffff,8528342bfffffff,8528343bfffffff,85283407fffffff,85283403fffffff,8528341bfffffff,8428347ffffffff,") +add_h3_cli_test(testCliCompactCellsStdin3 "compactCells -f -- < ${PROJECT_SOURCE_DIR}/tests/inputfiles/compact_test3.txt | tr -s '\\\\r\\\\n' ',' | tr -s '\\\\n' ','" "85283447fffffff,8528340ffffffff,8528340bfffffff,85283457fffffff,85283443fffffff,8528344ffffffff,852836b7fffffff,8528342bfffffff,8528343bfffffff,85283407fffffff,85283403fffffff,8528341bfffffff,8428347ffffffff,") +add_h3_cli_test(testCliCompactCellsArg1 "compactCells -c \"\\\\`cat ${PROJECT_SOURCE_DIR}/tests/inputfiles/compact_test1.txt\\\\`\" | tr -s '\\\\r\\\\n' ',' | tr -s '\\\\n' ','" "85283447fffffff,8528340ffffffff,8528340bfffffff,85283457fffffff,85283443fffffff,8528344ffffffff,852836b7fffffff,8528342bfffffff,8528343bfffffff,85283407fffffff,85283403fffffff,8528341bfffffff,8428347ffffffff,") +add_h3_cli_test(testCliCompactCellsArg2 "compactCells -c \\\\`cat ${PROJECT_SOURCE_DIR}/tests/inputfiles/compact_test2.txt\\\\` | tr -s '\\\\r\\\\n' ',' | tr -s '\\\\n' ','" "85283447fffffff,8528340ffffffff,8528340bfffffff,85283457fffffff,85283443fffffff,8528344ffffffff,852836b7fffffff,8528342bfffffff,8528343bfffffff,85283407fffffff,85283403fffffff,8528341bfffffff,8428347ffffffff,") +add_h3_cli_test(testCliCompactCellsArg3 "compactCells -c \\\\`cat ${PROJECT_SOURCE_DIR}/tests/inputfiles/compact_test3.txt\\\\` | tr -s '\\\\r\\\\n' ',' | tr -s '\\\\n' ','" "85283447fffffff,8528340ffffffff,8528340bfffffff,85283457fffffff,85283443fffffff,8528344ffffffff,852836b7fffffff,8528342bfffffff,8528343bfffffff,85283407fffffff,85283403fffffff,8528341bfffffff,8428347ffffffff,") diff --git a/tests/cli/uncompactCells.txt b/tests/cli/uncompactCells.txt new file mode 100644 index 000000000..a75d1513f --- /dev/null +++ b/tests/cli/uncompactCells.txt @@ -0,0 +1,9 @@ +add_h3_cli_test(testCliUncompactCellsFile1 "uncompactCells -r 5 -f ${PROJECT_SOURCE_DIR}/tests/inputfiles/uncompact_test1.txt | tr -s '\\\\r\\\\n' ',' | tr -s '\\\\n' ','" "85283447fffffff,8528340ffffffff,8528340bfffffff,85283457fffffff,85283443fffffff,8528344ffffffff,852836b7fffffff,8528342bfffffff,8528343bfffffff,85283407fffffff,85283403fffffff,8528341bfffffff,85283463fffffff,85283467fffffff,8528346bfffffff,8528346ffffffff,85283473fffffff,85283477fffffff,8528347bfffffff,") +add_h3_cli_test(testCliUncompactCellsFile2 "uncompactCells -r 5 -f ${PROJECT_SOURCE_DIR}/tests/inputfiles/uncompact_test2.txt | tr -s '\\\\r\\\\n' ',' | tr -s '\\\\n' ','" "85283447fffffff,8528340ffffffff,8528340bfffffff,85283457fffffff,85283443fffffff,8528344ffffffff,852836b7fffffff,8528342bfffffff,8528343bfffffff,85283407fffffff,85283403fffffff,8528341bfffffff,85283463fffffff,85283467fffffff,8528346bfffffff,8528346ffffffff,85283473fffffff,85283477fffffff,8528347bfffffff,") +add_h3_cli_test(testCliUncompactCellsFile3 "uncompactCells -r 5 -f ${PROJECT_SOURCE_DIR}/tests/inputfiles/uncompact_test3.txt | tr -s '\\\\r\\\\n' ',' | tr -s '\\\\n' ','" "85283447fffffff,8528340ffffffff,8528340bfffffff,85283457fffffff,85283443fffffff,8528344ffffffff,852836b7fffffff,8528342bfffffff,8528343bfffffff,85283407fffffff,85283403fffffff,8528341bfffffff,85283463fffffff,85283467fffffff,8528346bfffffff,8528346ffffffff,85283473fffffff,85283477fffffff,8528347bfffffff,") +add_h3_cli_test(testCliUncompactCellsStdin1 "uncompactCells -r 5 -f -- < ${PROJECT_SOURCE_DIR}/tests/inputfiles/uncompact_test1.txt | tr -s '\\\\r\\\\n' ',' | tr -s '\\\\n' ','" "85283447fffffff,8528340ffffffff,8528340bfffffff,85283457fffffff,85283443fffffff,8528344ffffffff,852836b7fffffff,8528342bfffffff,8528343bfffffff,85283407fffffff,85283403fffffff,8528341bfffffff,85283463fffffff,85283467fffffff,8528346bfffffff,8528346ffffffff,85283473fffffff,85283477fffffff,8528347bfffffff,") +add_h3_cli_test(testCliUncompactCellsStdin2 "uncompactCells -r 5 -f -- < ${PROJECT_SOURCE_DIR}/tests/inputfiles/uncompact_test2.txt | tr -s '\\\\r\\\\n' ',' | tr -s '\\\\n' ','" "85283447fffffff,8528340ffffffff,8528340bfffffff,85283457fffffff,85283443fffffff,8528344ffffffff,852836b7fffffff,8528342bfffffff,8528343bfffffff,85283407fffffff,85283403fffffff,8528341bfffffff,85283463fffffff,85283467fffffff,8528346bfffffff,8528346ffffffff,85283473fffffff,85283477fffffff,8528347bfffffff,") +add_h3_cli_test(testCliUncompactCellsStdin3 "uncompactCells -r 5 -f -- < ${PROJECT_SOURCE_DIR}/tests/inputfiles/uncompact_test3.txt | tr -s '\\\\r\\\\n' ',' | tr -s '\\\\n' ','" "85283447fffffff,8528340ffffffff,8528340bfffffff,85283457fffffff,85283443fffffff,8528344ffffffff,852836b7fffffff,8528342bfffffff,8528343bfffffff,85283407fffffff,85283403fffffff,8528341bfffffff,85283463fffffff,85283467fffffff,8528346bfffffff,8528346ffffffff,85283473fffffff,85283477fffffff,8528347bfffffff,") +add_h3_cli_test(testCliUncompactCellsArg1 "uncompactCells -r 5 -c \"\\\\`cat ${PROJECT_SOURCE_DIR}/tests/inputfiles/uncompact_test1.txt\\\\`\" | tr -s '\\\\r\\\\n' ',' | tr -s '\\\\n' ','" "85283447fffffff,8528340ffffffff,8528340bfffffff,85283457fffffff,85283443fffffff,8528344ffffffff,852836b7fffffff,8528342bfffffff,8528343bfffffff,85283407fffffff,85283403fffffff,8528341bfffffff,85283463fffffff,85283467fffffff,8528346bfffffff,8528346ffffffff,85283473fffffff,85283477fffffff,8528347bfffffff,") +add_h3_cli_test(testCliUncompactCellsArg2 "uncompactCells -r 5 -c \"\\\\`cat ${PROJECT_SOURCE_DIR}/tests/inputfiles/uncompact_test2.txt\\\\`\" | tr -s '\\\\r\\\\n' ',' | tr -s '\\\\n' ','" "85283447fffffff,8528340ffffffff,8528340bfffffff,85283457fffffff,85283443fffffff,8528344ffffffff,852836b7fffffff,8528342bfffffff,8528343bfffffff,85283407fffffff,85283403fffffff,8528341bfffffff,85283463fffffff,85283467fffffff,8528346bfffffff,8528346ffffffff,85283473fffffff,85283477fffffff,8528347bfffffff,") +add_h3_cli_test(testCliUncompactCellsArg3 "uncompactCells -r 5 -c \\\\`cat ${PROJECT_SOURCE_DIR}/tests/inputfiles/uncompact_test3.txt\\\\` | tr -s '\\\\r\\\\n' ',' | tr -s '\\\\n' ','" "85283447fffffff,8528340ffffffff,8528340bfffffff,85283457fffffff,85283443fffffff,8528344ffffffff,852836b7fffffff,8528342bfffffff,8528343bfffffff,85283407fffffff,85283403fffffff,8528341bfffffff,85283463fffffff,85283467fffffff,8528346bfffffff,8528346ffffffff,85283473fffffff,85283477fffffff,8528347bfffffff,") diff --git a/tests/inputfiles/compact_test1.txt b/tests/inputfiles/compact_test1.txt new file mode 100644 index 000000000..b7c763104 --- /dev/null +++ b/tests/inputfiles/compact_test1.txt @@ -0,0 +1,19 @@ +"85283473fffffff", +"85283447fffffff", +"8528347bfffffff", +"85283463fffffff", +"85283477fffffff", +"8528340ffffffff", +"8528340bfffffff", +"85283457fffffff", +"85283443fffffff", +"8528344ffffffff", +"852836b7fffffff", +"8528346bfffffff", +"8528346ffffffff", +"85283467fffffff", +"8528342bfffffff", +"8528343bfffffff", +"85283407fffffff", +"85283403fffffff", +"8528341bfffffff" diff --git a/tests/inputfiles/compact_test2.txt b/tests/inputfiles/compact_test2.txt new file mode 100644 index 000000000..6200da6f9 --- /dev/null +++ b/tests/inputfiles/compact_test2.txt @@ -0,0 +1 @@ +"85283473fffffff","85283447fffffff","8528347bfffffff","85283463fffffff","85283477fffffff","8528340ffffffff","8528340bfffffff","85283457fffffff","85283443fffffff","8528344ffffffff","852836b7fffffff","8528346bfffffff","8528346ffffffff","85283467fffffff","8528342bfffffff","8528343bfffffff","85283407fffffff","85283403fffffff","8528341bfffffff" diff --git a/tests/inputfiles/compact_test3.txt b/tests/inputfiles/compact_test3.txt new file mode 100644 index 000000000..376a93988 --- /dev/null +++ b/tests/inputfiles/compact_test3.txt @@ -0,0 +1 @@ +85283473fffffff,85283447fffffff,8528347bfffffff,85283463fffffff,85283477fffffff,8528340ffffffff,8528340bfffffff,85283457fffffff,85283443fffffff,8528344ffffffff,852836b7fffffff,8528346bfffffff,8528346ffffffff,85283467fffffff,8528342bfffffff,8528343bfffffff,85283407fffffff,85283403fffffff,8528341bfffffff diff --git a/tests/inputfiles/uncompact_test1.txt b/tests/inputfiles/uncompact_test1.txt new file mode 100644 index 000000000..faecca4cd --- /dev/null +++ b/tests/inputfiles/uncompact_test1.txt @@ -0,0 +1,15 @@ +[ + "85283447fffffff", + "8528340ffffffff", + "8528340bfffffff", + "85283457fffffff", + "85283443fffffff", + "8528344ffffffff", + "852836b7fffffff", + "8528342bfffffff", + "8528343bfffffff", + "85283407fffffff", + "85283403fffffff", + "8528341bfffffff", + "8428347ffffffff" +] diff --git a/tests/inputfiles/uncompact_test2.txt b/tests/inputfiles/uncompact_test2.txt new file mode 100644 index 000000000..f32646773 --- /dev/null +++ b/tests/inputfiles/uncompact_test2.txt @@ -0,0 +1,13 @@ +85283447fffffff +8528340ffffffff +8528340bfffffff +85283457fffffff +85283443fffffff +8528344ffffffff +852836b7fffffff +8528342bfffffff +8528343bfffffff +85283407fffffff +85283403fffffff +8528341bfffffff +8428347ffffffff diff --git a/tests/inputfiles/uncompact_test3.txt b/tests/inputfiles/uncompact_test3.txt new file mode 100644 index 000000000..0be180eed --- /dev/null +++ b/tests/inputfiles/uncompact_test3.txt @@ -0,0 +1 @@ +85283447fffffff,8528340ffffffff,8528340bfffffff,85283457fffffff,85283443fffffff,8528344ffffffff,852836b7fffffff,8528342bfffffff,8528343bfffffff,85283407fffffff,85283403fffffff,8528341bfffffff,8428347ffffffff