From 32b161599f940f0c7602a8ab5109e8b3d2b0a88c Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Mon, 15 Aug 2022 18:38:02 +0000 Subject: [PATCH] country: Refactor storing country code and continent code Signed-off-by: Michael Tremer --- src/country.c | 74 +++++++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 38 deletions(-) diff --git a/src/country.c b/src/country.c index a871c4c..6226d70 100644 --- a/src/country.c +++ b/src/country.c @@ -35,12 +35,16 @@ static const struct loc_special_country { { "", 0 }, }; +#define CC_LEN 3 + struct loc_country { struct loc_ctx* ctx; int refcount; - char* code; - char* continent_code; + // Store the country code in a 3 byte buffer. Two bytes for the code, and NULL so + // that we can use strcmp() and return a pointer. + char code[3]; + char continent_code[3]; char* name; }; @@ -59,7 +63,8 @@ LOC_EXPORT int loc_country_new(struct loc_ctx* ctx, struct loc_country** country c->ctx = loc_ref(ctx); c->refcount = 1; - c->code = strdup(country_code); + // Set the country code + loc_country_code_copy(c->code, country_code); DEBUG(c->ctx, "Country %s allocated at %p\n", c->code, c); *country = c; @@ -76,12 +81,6 @@ LOC_EXPORT struct loc_country* loc_country_ref(struct loc_country* country) { static void loc_country_free(struct loc_country* country) { DEBUG(country->ctx, "Releasing country %s %p\n", country->code, country); - if (country->code) - free(country->code); - - if (country->continent_code) - free(country->continent_code); - if (country->name) free(country->name); @@ -94,7 +93,6 @@ LOC_EXPORT struct loc_country* loc_country_unref(struct loc_country* country) { return NULL; loc_country_free(country); - return NULL; } @@ -107,13 +105,14 @@ LOC_EXPORT const char* loc_country_get_continent_code(struct loc_country* countr } LOC_EXPORT int loc_country_set_continent_code(struct loc_country* country, const char* continent_code) { - // XXX validate input - - // Free previous value - if (country->continent_code) - free(country->continent_code); + // Check for valid input + if (!continent_code || strlen(continent_code) != 2) { + errno = EINVAL; + return 1; + } - country->continent_code = strdup(continent_code); + // Store the code + loc_country_code_copy(country->continent_code, continent_code); return 0; } @@ -126,37 +125,36 @@ LOC_EXPORT int loc_country_set_name(struct loc_country* country, const char* nam if (country->name) free(country->name); - if (name) + if (name) { country->name = strdup(name); + // Report error if we could not copy the string + if (!country->name) + return 1; + } + return 0; } LOC_EXPORT int loc_country_cmp(struct loc_country* country1, struct loc_country* country2) { - return strcmp(country1->code, country2->code); + return strncmp(country1->code, country2->code, 2); } int loc_country_new_from_database_v1(struct loc_ctx* ctx, struct loc_stringpool* pool, struct loc_country** country, const struct loc_database_country_v1* dbobj) { - char buffer[3]; + char buffer[3] = "XX"; // Read country code loc_country_code_copy(buffer, dbobj->code); - // Terminate buffer - buffer[2] = '\0'; - // Create a new country object int r = loc_country_new(ctx, country, buffer); if (r) return r; - // Continent Code - loc_country_code_copy(buffer, dbobj->continent_code); - - r = loc_country_set_continent_code(*country, buffer); - if (r) - goto FAIL; + // Copy continent code + if (*dbobj->continent_code) + loc_country_code_copy((*country)->continent_code, dbobj->continent_code); // Set name const char* name = loc_stringpool_get(pool, be32toh(dbobj->name)); @@ -175,20 +173,20 @@ FAIL: int loc_country_to_database_v1(struct loc_country* country, struct loc_stringpool* pool, struct loc_database_country_v1* dbobj) { + off_t name = 0; + // Add country code - for (unsigned int i = 0; i < 2; i++) { - dbobj->code[i] = country->code[i] ? country->code[i] : '\0'; - } + if (*country->code) + loc_country_code_copy(dbobj->code, country->code); // Add continent code - if (country->continent_code) { - for (unsigned int i = 0; i < 2; i++) { - dbobj->continent_code[i] = country->continent_code[i] ? country->continent_code[i] : '\0'; - } - } + if (*country->continent_code) + loc_country_code_copy(dbobj->continent_code, country->continent_code); // Save the name string in the string pool - off_t name = loc_stringpool_add(pool, country->name ? country->name : ""); + if (country->name) + name = loc_stringpool_add(pool, country->name); + dbobj->name = htobe32(name); return 0; @@ -227,7 +225,7 @@ LOC_EXPORT int loc_country_special_code_to_flag(const char* cc) { // Return flags for any known special country for (const struct loc_special_country* country = loc_special_countries; country->flags; country++) { - if (strcmp(country->code, cc) == 0) + if (strncmp(country->code, cc, 2) == 0) return country->flags; } -- 2.39.5