/** * @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 #include #include 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) { const cepis_faixa_t *faixa = cepis_error_faixa(&err); fprintf(stderr, "error: %s: %s\n", cepis_status_str(err.status), err.message); if (faixa != NULL) fprintf(stderr, "note: it would be in %s/%s, where " "%lld CEP(s) exist between %s and %s\n", faixa->localidade, faixa->uf, faixa->ceps, faixa->cep_ini, faixa->cep_fim); 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; }