]> git.ipfire.org Git - location/libloc.git/blobdiff - src/writer.c
Make package compile on Mac OS X
[location/libloc.git] / src / writer.c
index 12a2c52ea5636f084483e0bb4fe33bdf8ed8e14f..594df1a0327672ce072e8099a213aa7a70a57d85 100644 (file)
@@ -14,7 +14,6 @@
        Lesser General Public License for more details.
 */
 
-#include <endian.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/queue.h>
 #include <time.h>
 
+#ifdef HAVE_ENDIAN_H
+#  include <endian.h>
+#endif
+
 #include <loc/libloc.h>
 #include <loc/as.h>
+#include <loc/compat.h>
+#include <loc/country.h>
 #include <loc/format.h>
 #include <loc/network.h>
 #include <loc/private.h>
@@ -41,6 +46,9 @@ struct loc_writer {
        struct loc_as** as;
        size_t as_count;
 
+       struct loc_country** countries;
+       size_t countries_count;
+
        struct loc_network_tree* networks;
 };
 
@@ -183,6 +191,32 @@ LOC_EXPORT int loc_writer_add_network(struct loc_writer* writer, struct loc_netw
        return loc_network_tree_add_network(writer->networks, *network);
 }
 
+static int __loc_country_cmp(const void* country1, const void* country2) {
+       return loc_country_cmp(*(struct loc_country**)country1, *(struct loc_country**)country2);
+}
+
+LOC_EXPORT int loc_writer_add_country(struct loc_writer* writer, struct loc_country** country, const char* country_code) {
+       int r = loc_country_new(writer->ctx, country, country_code);
+       if (r)
+               return r;
+
+       // We have a new country to add
+       writer->countries_count++;
+
+       // Make space
+       writer->countries = realloc(writer->countries, sizeof(*writer->countries) * writer->countries_count);
+       if (!writer->countries)
+               return -ENOMEM;
+
+       // Add as last element
+       writer->countries[writer->countries_count - 1] = loc_country_ref(*country);
+
+       // Sort everything
+       qsort(writer->countries, writer->countries_count, sizeof(*writer->countries), __loc_country_cmp);
+
+       return 0;
+}
+
 static void make_magic(struct loc_writer* writer, struct loc_database_magic* magic) {
        // Copy magic bytes
        for (unsigned int i = 0; i < strlen(LOC_DATABASE_MAGIC); i++)
@@ -349,6 +383,9 @@ static int loc_database_write_networks(struct loc_writer* writer,
                }
 
                // Prepare what we are writing to disk
+               db_node.zero = htobe32(node->index_zero);
+               db_node.one  = htobe32(node->index_one);
+
                if (loc_network_tree_node_is_leaf(node->node)) {
                        struct loc_network* network = loc_network_tree_node_get_network(node->node);
 
@@ -356,13 +393,10 @@ static int loc_database_write_networks(struct loc_writer* writer,
                        struct network* nw = make_network(network);
                        TAILQ_INSERT_TAIL(&networks, nw, networks);
 
-                       db_node.zero = htobe32(0xffffffff);
-                       db_node.one  = htobe32(network_index++);
-
+                       db_node.network = htobe32(network_index++);
                        loc_network_unref(network);
                } else {
-                       db_node.zero = htobe32(node->index_zero);
-                       db_node.one  = htobe32(node->index_one);
+                       db_node.network = htobe32(0xffffffff);
                }
 
                // Write the current node
@@ -408,6 +442,31 @@ static int loc_database_write_networks(struct loc_writer* writer,
        return 0;
 }
 
+static int loc_database_write_countries(struct loc_writer* writer,
+               struct loc_database_header_v0* header, off_t* offset, FILE* f) {
+       DEBUG(writer->ctx, "Countries section starts at %jd bytes\n", *offset);
+       header->countries_offset = htobe32(*offset);
+
+       size_t countries_length = 0;
+
+       struct loc_database_country_v0 country;
+       for (unsigned int i = 0; i < writer->countries_count; i++) {
+               // Convert country into database format
+               loc_country_to_database_v0(writer->countries[i], writer->pool, &country);
+
+               // Write to disk
+               *offset += fwrite(&country, 1, sizeof(country), f);
+               countries_length += sizeof(country);
+       }
+
+       DEBUG(writer->ctx, "Countries section has a length of %zu bytes\n", countries_length);
+       header->countries_length = htobe32(countries_length);
+
+       align_page_boundary(offset, f);
+
+       return 0;
+}
+
 LOC_EXPORT int loc_writer_write(struct loc_writer* writer, FILE* f) {
        struct loc_database_magic magic;
        make_magic(writer, &magic);
@@ -452,6 +511,11 @@ LOC_EXPORT int loc_writer_write(struct loc_writer* writer, FILE* f) {
        if (r)
                return r;
 
+       // Write countries
+       r = loc_database_write_countries(writer, &header, &offset, f);
+       if (r)
+               return r;
+
        // Write pool
        r = loc_database_write_pool(writer, &header, &offset, f);
        if (r)