diff options
| author | Murilo Ijanc <[email protected]> | 2026-07-26 12:25:48 -0300 |
|---|---|---|
| committer | Murilo Ijanc <[email protected]> | 2026-07-26 12:25:48 -0300 |
| commit | e2c6ae13af335b311da2429c903032124f926df2 (patch) | |
| tree | 73776fab7f3e52124a217e2768968fc9a8a76c34 /src/cli.c | |
| download | c-e2c6ae13af335b311da2429c903032124f926df2.tar.gz | |
Initial importv0.1.0
Diffstat (limited to 'src/cli.c')
| -rw-r--r-- | src/cli.c | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/src/cli.c b/src/cli.c new file mode 100644 index 0000000..e4c9bd4 --- /dev/null +++ b/src/cli.c @@ -0,0 +1,191 @@ +/** + * @file cli.c + * @brief Minimal command-line front end: `cepis 01001000`. + * + * It exists for one concrete case -- quickly confirming a local instance + * answers before pointing code at it: + * + * cepis --base-url http://localhost:8080 01001000 + * + * A single CEP goes through the unit lookup, which carries `geo`; several go + * through the batch, which is one request instead of N and has no `geo`. + * + * It is not the library's main interface; for that, include `cepis.h`. + */ +#include "cepis.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static void print_escaped(const char *text) +{ + size_t i; + + putchar('"'); + for (i = 0; text[i] != '\0'; i++) { + unsigned char c = (unsigned char)text[i]; + switch (c) { + case '"': + fputs("\\\"", stdout); + break; + case '\\': + fputs("\\\\", stdout); + break; + case '\n': + fputs("\\n", stdout); + break; + case '\r': + fputs("\\r", stdout); + break; + case '\t': + fputs("\\t", stdout); + break; + default: + if (c < 0x20) + printf("\\u%04x", c); + else + putchar((int)c); + } + } + putchar('"'); +} + +static void print_pair(const char *key, const char *value, bool last) +{ + printf(" \"%s\": ", key); + print_escaped(value); + printf("%s\n", last ? "" : ","); +} + +static void print_address(const cepis_address_t *address) +{ + if (address == NULL) { + printf(" null"); + return; + } + printf(" {\n"); + print_pair("cep", address->cep, false); + print_pair("logradouro", address->logradouro, false); + print_pair("complemento", address->complemento, false); + print_pair("unidade", address->unidade, false); + print_pair("bairro", address->bairro, false); + print_pair("localidade", address->localidade, false); + print_pair("uf", address->uf, false); + print_pair("estado", address->estado, false); + print_pair("regiao", address->regiao, false); + print_pair("ibge", address->ibge, false); + print_pair("gia", address->gia, false); + print_pair("ddd", address->ddd, false); + print_pair("siafi", address->siafi, address->geo == NULL); + if (address->geo != NULL) { + printf(" \"geo\": {\"lat\": %.6f, \"lon\": %.6f, " + "\"raio_m\": %ld, \"precisao\": ", + address->geo->lat, address->geo->lon, + address->geo->raio_m); + print_escaped(address->geo->precisao); + printf("}\n"); + } + printf(" }"); +} + +static int usage(int code) +{ + FILE *stream = code == 0 ? stdout : stderr; + + fprintf(stream, + "usage: cepis [--base-url URL] [--timeout SECONDS] CEP...\n" + "\n" + " --base-url URL API URL (default: %s)\n" + " --timeout SECONDS per-socket timeout (default: 10)\n" + " --version print the version and exit\n", + CEPIS_DEFAULT_BASE_URL); + return code; +} + +int main(int argc, char **argv) +{ + cepis_config_t config; + cepis_client_t *client = NULL; + cepis_error_t err; + const char **ceps; + size_t count = 0; + int status = 0; + int i; + + cepis_config_init(&config); + ceps = calloc((size_t)argc, sizeof(*ceps)); + if (ceps == NULL) + return 1; + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "--help") == 0) { + free(ceps); + return usage(0); + } + if (strcmp(argv[i], "--version") == 0) { + printf("cepis %s\n", CEPIS_VERSION); + free(ceps); + return 0; + } + if (strcmp(argv[i], "--base-url") == 0 && i + 1 < argc) { + config.base_url = argv[++i]; + continue; + } + if (strcmp(argv[i], "--timeout") == 0 && i + 1 < argc) { + config.timeout = strtod(argv[++i], NULL); + continue; + } + if (argv[i][0] == '-') { + free(ceps); + return usage(2); + } + ceps[count++] = argv[i]; + } + + if (count == 0) { + free(ceps); + return usage(2); + } + + if (cepis_client_new(&config, &client, &err) != CEPIS_OK) { + fprintf(stderr, "error: %s\n", err.message); + free(ceps); + return 1; + } + + if (count == 1) { + cepis_address_t *address = NULL; + if (cepis_lookup(client, ceps[0], &address, &err) != CEPIS_OK) { + fprintf(stderr, "error: %s: %s\n", + cepis_status_str(err.status), err.message); + status = 1; + } else { + print_address(address); + printf("\n"); + cepis_address_free(address); + } + } else { + cepis_address_list_t list = {NULL, 0}; + if (cepis_lookup_many(client, ceps, count, &list, &err) != + CEPIS_OK) { + fprintf(stderr, "error: %s: %s\n", + cepis_status_str(err.status), err.message); + status = 1; + } else { + size_t index; + printf("[\n"); + for (index = 0; index < list.count; index++) { + print_address(list.items[index]); + printf("%s\n", + index + 1 < list.count ? "," : ""); + } + printf("]\n"); + cepis_address_list_free(&list); + } + } + + cepis_client_free(client); + free(ceps); + return status; +} |