From: Michael Tremer Date: Sun, 19 Jul 2026 16:41:11 +0000 (+0000) Subject: database: Implement the match functions as callbacks X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=259af2ec2c6cf3936cfeaa1c1fc7536331b2302c;p=location%2Flibloc.git database: Implement the match functions as callbacks This way, we can change the easier if there is a newer version of the database format. Signed-off-by: Michael Tremer --- diff --git a/src/database.c b/src/database.c index a22feda..35555ac 100644 --- a/src/database.c +++ b/src/database.c @@ -50,6 +50,11 @@ #include #include +typedef int (*loc_database_match_as) + (struct loc_database* db, uint32_t number, off_t i); +typedef int (*loc_database_match_country) + (struct loc_database* db, const char* code, off_t i); + struct loc_database_objects { char* data; size_t length; @@ -97,6 +102,11 @@ struct loc_database { // Countries struct loc_database_objects country_objects; + + struct loc_database_callbacks { + loc_database_match_as match_as; + loc_database_match_country match_country; + } callbacks; }; #define MAX_STACK_DEPTH 256 @@ -424,6 +434,20 @@ static int loc_database_clone_handle(struct loc_database* db, FILE* f) { return 0; } +static int loc_database_match_as_v1(struct loc_database* db, uint32_t number, off_t i) { + struct loc_database_as_v1* as_v1 = (struct loc_database_as_v1*)loc_database_object(db, + &db->as_objects, sizeof(*as_v1), i); + + return htobe32(as_v1->number) - number; +} + +static int loc_database_match_country_v1(struct loc_database* db, const char* code, off_t i) { + struct loc_database_country_v1* country_v1 = \ + (struct loc_database_country_v1*)loc_database_object(db, &db->country_objects, sizeof(*country_v1), i); + + return loc_country_code_cmp(country_v1->code, code); +} + static int loc_database_open(struct loc_database* db, FILE* f) { int r; @@ -439,6 +463,17 @@ static int loc_database_open(struct loc_database* db, FILE* f) { if (r) return r; + // Set the callbacks + switch (db->version) { + case LOC_DATABASE_VERSION_1: + db->callbacks.match_as = loc_database_match_as_v1; + db->callbacks.match_country = loc_database_match_country_v1; + break; + + default: + return -ENOTSUP; + } + // Map the database into memory r = loc_database_mmap(db); if (r) @@ -759,17 +794,14 @@ static int loc_database_fetch_as(struct loc_database* db, struct loc_as** as, of return r; } -static int loc_database_match_as_v1(struct loc_database* db, uint32_t number, off_t i) { - struct loc_database_as_v1* as_v1 = (struct loc_database_as_v1*)loc_database_object(db, - &db->as_objects, sizeof(*as_v1), i); - - return htobe32(as_v1->number) - number; -} - // Performs a binary search to find the AS in the list LOC_EXPORT int loc_database_get_as(struct loc_database* db, struct loc_as** as, uint32_t number) { int r; + // Fail if the callback has not been set + if (!db->callbacks.match_as) + return -ENOTSUP; + off_t lo = 0; off_t hi = db->as_objects.count - 1; @@ -782,7 +814,7 @@ LOC_EXPORT int loc_database_get_as(struct loc_database* db, struct loc_as** as, off_t i = (lo + hi) / 2; // Match the AS number - r = loc_database_match_as_v1(db, number, i); + r = db->callbacks.match_as(db, number, i); if (r < 0) { lo = i + 1; @@ -1037,13 +1069,6 @@ static int loc_database_fetch_country(struct loc_database* db, return r; } -static int loc_database_match_country_v1(struct loc_database* db, const char* code, int i) { - struct loc_database_country_v1* country_v1 = \ - (struct loc_database_country_v1*)loc_database_object(db, &db->country_objects, sizeof(*country_v1), i); - - return loc_country_code_cmp(country_v1->code, code); -} - // Performs a binary search to find the country in the list LOC_EXPORT int loc_database_get_country(struct loc_database* db, struct loc_country** country, const char* code) { @@ -1055,6 +1080,10 @@ LOC_EXPORT int loc_database_get_country(struct loc_database* db, return 1; } + // Fail if the callback has not been set + if (!db->callbacks.match_country) + return -ENOTSUP; + #ifdef ENABLE_DEBUG // Save start time clock_t start = clock(); @@ -1067,7 +1096,7 @@ LOC_EXPORT int loc_database_get_country(struct loc_database* db, off_t i = (lo + hi) / 2; // Match the country code - r = loc_database_match_country_v1(db, code, i); + r = db->callbacks.match_country(db, code, i); if (r < 0) { lo = i + 1;