1 #ifndef GEONAMES_H
2 #define GEONAMES_H
3 
4 
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <stdint.h>
9 #include <stdbool.h>
10 #include <string.h>
11 
12 #include "collections.h"
13 #include "features.h"
14 #include "string_utils.h"
15 
16 typedef enum {
17     GEONAMES_COUNTRY = 0,
18     GEONAMES_ADMIN1 = 1,
19     GEONAMES_ADMIN2 = 2,
20     GEONAMES_ADMIN3 = 3,
21     GEONAMES_ADMIN4 = 4,
22     GEONAMES_ADMIN_OTHER = 5,
23     GEONAMES_LOCALITY = 6,
24     GEONAMES_NEIGHBORHOOD = 7,
25     NUM_BOUNDARY_TYPES
26 } boundary_type_t;
27 
28 #define GEONAMES_ADDRESS_COMPONENT_COUNTRY (1 << 0)
29 #define GEONAMES_ADDRESS_COMPONENT_ADMIN1 (1 << 1)
30 #define GEONAMES_ADDRESS_COMPONENT_ADMIN2 (1 << 2)
31 #define GEONAMES_ADDRESS_COMPONENT_ADMIN3 (1 << 3)
32 #define GEONAMES_ADDRESS_COMPONENT_ADMIN4 (1 << 4)
33 #define GEONAMES_ADDRESS_COMPONENT_ADMIN_OTHER (1 << 5)
34 #define GEONAMES_ADDRESS_COMPONENT_LOCALITY (1 << 6)
35 #define GEONAMES_ADDRESS_COMPONENT_NEIGHBORHOOD (1 << 7)
36 #define GEONAMES_ADDRESS_COMPONENT_POSTCODE (1 << 8)
37 
38 typedef struct geoname {
39     uint32_t geonames_id;
40     char_array *name;
41     char_array *canonical;
42     boundary_type_t type;
43     char_array *iso_language;
44     bool has_wikipedia_entry;
45     bool is_preferred_name;
46     bool is_short_name;
47     bool is_colloquial;
48     bool is_historical;
49     uint32_t population;
50     double latitude;
51     double longitude;
52     char_array *feature_code;
53     char_array *country_code;
54     uint32_t country_geonames_id;
55     char_array *admin1_code;
56     uint32_t admin1_geonames_id;
57     char_array *admin2_code;
58     uint32_t admin2_geonames_id;
59     char_array *admin3_code;
60     uint32_t admin3_geonames_id;
61     char_array *admin4_code;
62     uint32_t admin4_geonames_id;
63 } geoname_t;
64 
65 /* We want to reuse objects here, so only call
66  * geoname_create once or twice and populate the same
67  * object repeatedly with geoname_deserialize.
68  * This helps avoid making too many malloc/free calls
69 */
70 geoname_t *geoname_new(void);
71 bool geoname_deserialize(geoname_t *self, char_array *str);
72 bool geoname_serialize(geoname_t *self, char_array *str);
73 void geoname_print(geoname_t *self);
74 void geoname_clear(geoname_t *self);
75 void geoname_destroy(geoname_t *self);
76 
77 typedef struct gn_postal_code {
78     char_array *postal_code;
79     char_array *country_code;
80     uint32_t country_geonames_id;
81     bool have_lat_lon;
82     double latitude;
83     double longitude;
84     uint8_t accuracy;
85     bool have_containing_geoname;
86     char_array *containing_geoname;
87     uint32_t containing_geonames_id;
88     uint32_array *admin1_ids;
89     uint32_array *admin2_ids;
90     uint32_array *admin3_ids;
91 } gn_postal_code_t;
92 
93 gn_postal_code_t *gn_postal_code_new(void);
94 bool gn_postal_code_deserialize(gn_postal_code_t *self, char_array *str);
95 bool gn_postal_code_serialize(gn_postal_code_t *self, char_array *str);
96 void gn_postal_code_print(gn_postal_code_t *self);
97 void gn_postal_code_clear(gn_postal_code_t *self);
98 void gn_postal_code_destroy(gn_postal_code_t *self);
99 
100 typedef enum {
101     GEONAMES_PLACE,
102     GEONAMES_POSTAL_CODE
103 } gn_type;
104 
105 typedef struct geonames_generic {
106     gn_type type;
107     union {
108         geoname_t *geoname;
109         gn_postal_code_t *postal_code;
110     };
111 } geonames_generic_t;
112 
113 VECTOR_INIT(gn_generic_array, geonames_generic_t);
114 
115 bool geonames_generic_serialize(geonames_generic_t *gn, char_array *str);
116 bool geonames_generic_deserialize(gn_type *type, geoname_t *geoname, gn_postal_code_t *postal_code, char_array *str);
117 
118 
119 
120 #endif
121