blob: 84e03f9a63c6133841df3020de217ea028cd3236 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
#include "cepis/models.hpp"
#include <cerrno>
#include <cmath>
#include <cstdlib>
#include <limits>
#include <optional>
#include <string>
namespace cepis {
namespace {
std::string as_field(const Json* value) {
if (value == nullptr) {
return {};
}
switch (value->kind()) {
case Json::Kind::String:
return value->as_string();
case Json::Kind::Number: {
const double number = value->as_number();
if (number == std::trunc(number) && std::fabs(number) < 9.0e15) {
return std::to_string(static_cast<std::int64_t>(number));
}
return Json::number(number).dump();
}
case Json::Kind::Bool:
return value->as_bool() ? "true" : "false";
default:
return {};
}
}
std::optional<double> as_double(const Json* value) {
if (value == nullptr) {
return std::nullopt;
}
if (value->is_number()) {
return value->as_number();
}
if (!value->is_string()) {
return std::nullopt;
}
const std::string& text = value->as_string();
if (text.empty()) {
return std::nullopt;
}
errno = 0;
char* end = nullptr;
const double parsed = std::strtod(text.c_str(), &end);
if (errno != 0 || end != text.c_str() + text.size() || !std::isfinite(parsed)) {
return std::nullopt;
}
return parsed;
}
std::optional<std::int64_t> as_integer(const Json* value) {
if (value == nullptr) {
return std::nullopt;
}
if (value->is_number()) {
const double number = value->as_number();
if (!std::isfinite(number) || std::fabs(number) >= 9.0e18) {
return std::nullopt;
}
return static_cast<std::int64_t>(std::trunc(number));
}
if (!value->is_string()) {
return std::nullopt;
}
const std::string& text = value->as_string();
if (text.empty()) {
return std::nullopt;
}
errno = 0;
char* end = nullptr;
const long long parsed = std::strtoll(text.c_str(), &end, 10);
if (errno != 0 || end != text.c_str() + text.size()) {
return std::nullopt;
}
return static_cast<std::int64_t>(parsed);
}
std::optional<Geo> geo_from_json(const Json* block) {
if (block == nullptr || !block->is_object()) {
return std::nullopt;
}
const std::optional<double> lat = as_double(block->find("lat"));
const std::optional<double> lon = as_double(block->find("lon"));
const std::optional<std::int64_t> raio_m = as_integer(block->find("raio_m"));
const Json* precisao = block->find("precisao");
if (!lat || !lon || !raio_m || precisao == nullptr || !precisao->is_string()) {
return std::nullopt;
}
return Geo{*lat, *lon, *raio_m, precisao->as_string()};
}
} // namespace
std::string Address::formatted_cep() const {
if (cep.size() != 8) {
return cep;
}
return cep.substr(0, 5) + "-" + cep.substr(5);
}
Address Address::from_json(const Json& data) {
Address address;
address.cep = as_field(data.find("cep"));
address.logradouro = as_field(data.find("logradouro"));
address.complemento = as_field(data.find("complemento"));
address.unidade = as_field(data.find("unidade"));
address.bairro = as_field(data.find("bairro"));
address.localidade = as_field(data.find("localidade"));
address.uf = as_field(data.find("uf"));
address.estado = as_field(data.find("estado"));
address.regiao = as_field(data.find("regiao"));
address.ibge = as_field(data.find("ibge"));
address.gia = as_field(data.find("gia"));
address.ddd = as_field(data.find("ddd"));
address.siafi = as_field(data.find("siafi"));
address.geo = geo_from_json(data.find("geo"));
address.raw = data;
return address;
}
Health Health::from_json(const Json& data) {
Health health;
health.status = as_field(data.find("status"));
health.dne = as_field(data.find("dne"));
health.ceps = as_integer(data.find("ceps")).value_or(0);
health.geo = as_integer(data.find("geo")).value_or(0);
health.base_gerada_em = as_field(data.find("base_gerada_em"));
return health;
}
} // namespace cepis
|