1
0
Fork 0
mirror of https://gitlab.gnome.org/GNOME/calls.git synced 2024-06-08 12:59:36 +00:00
Purism-Calls/src/calls-emergency-call-types.c
Guido Günther aaefc0443a emergency-call-types: Allow to lookup emergency numbers by country code
We build a hash as cache to speed up lookups. As this is a one time
thing we just do it once and don't bother to free it up.

We currently assume that all numbers can be used for the location based
lookups. Should that change we want to add a flag indicating that.
2024-02-10 17:09:37 +01:00

159 lines
3.9 KiB
C

/*
* Copyright (C) 2021 Purism SPC
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Author: Guido Günther <agx@sigxcpu.org>
*/
#define G_LOG_DOMAIN "CallsEmergencyCallType"
#include "calls-emergency-call-types.h"
#include <glib/gi18n.h>
/**
* SECTION:calls-emergency-call-type
* @short_description: Emergency call types per country
*
* Exerpt from https://source.android.com/docs/core/connect/emergency-number-db
* TODO: parse the actual database for dynamic updates and broader coverage
*/
typedef struct {
char *number;
CallsEmergencyCallTypeFlags flags;
} CallsEmergencyNumber;
typedef struct {
char *country_code;
CallsEmergencyNumber numbers[3];
} CallsEmergencyNumberTypes;
GHashTable *by_mcc;
CallsEmergencyNumberTypes emergency_number_types[] = {
{ "CH",
{
{ "117", CALLS_EMERGENCY_CALL_TYPE_POLICE },
{ "144", CALLS_EMERGENCY_CALL_TYPE_AMBULANCE },
{ "118", CALLS_EMERGENCY_CALL_TYPE_FIRE_BRIGADE }
}
},
{ "DE",
{
{ "112", (CALLS_EMERGENCY_CALL_TYPE_POLICE |
CALLS_EMERGENCY_CALL_TYPE_AMBULANCE |
CALLS_EMERGENCY_CALL_TYPE_FIRE_BRIGADE) }
}
},
{ "US",
{
{ "911", (CALLS_EMERGENCY_CALL_TYPE_POLICE |
CALLS_EMERGENCY_CALL_TYPE_AMBULANCE |
CALLS_EMERGENCY_CALL_TYPE_FIRE_BRIGADE) }
}
}
};
static void
init_hash (void)
{
if (g_once_init_enter (&by_mcc)) {
GHashTable *table = g_hash_table_new (g_str_hash, g_str_equal);
for (int i = 0; i < G_N_ELEMENTS (emergency_number_types); i++) {
CallsEmergencyNumberTypes *numbers = &emergency_number_types[i];
g_hash_table_insert (table, numbers->country_code, numbers);
}
g_once_init_leave (&by_mcc, table);
}
}
static char *
flags_to_string (CallsEmergencyCallTypeFlags flags)
{
g_autoptr (GPtrArray) types = g_ptr_array_new ();
if (flags & CALLS_EMERGENCY_CALL_TYPE_POLICE) {
g_ptr_array_add (types, _("Police"));
}
if (flags & CALLS_EMERGENCY_CALL_TYPE_AMBULANCE) {
g_ptr_array_add (types, _("Ambulance"));
}
if (flags & CALLS_EMERGENCY_CALL_TYPE_FIRE_BRIGADE) {
g_ptr_array_add (types, _("Fire Brigade"));
}
if (flags & CALLS_EMERGENCY_CALL_TYPE_MOUNTAIN_RESCUE) {
g_ptr_array_add (types, _("Mountain Rescue"));
}
if (types->len == 0)
return NULL;
g_ptr_array_add (types, NULL);
/* TODO: join in RTL and locale aware way */
return g_strjoinv (", ", (GStrv)types->pdata);
}
char *
calls_emergency_call_type_get_name (const char *lookup, const char *country_code)
{
g_return_val_if_fail (lookup, NULL);
if (country_code == NULL)
return NULL;
for (int i = 0; i < G_N_ELEMENTS (emergency_number_types); i++){
CallsEmergencyNumberTypes *numbers = &emergency_number_types[i];
if (g_str_equal (numbers->country_code, country_code) == FALSE)
continue;
for (int n = 0; n < G_N_ELEMENTS (numbers->numbers); n++) {
CallsEmergencyNumber *number = &numbers->numbers[n];
if (g_strcmp0 (lookup, number->number) == 0)
return flags_to_string (number->flags);
}
}
return NULL;
}
/**
* calls_emergency_call_types_get_numbers_by_country_code:
* @mcc: The country code
*
* Get the valid emergency numbers for this country code
*
* Returns:(transfer full): A string array of emergency numbers
*/
GStrv
calls_emergency_call_types_get_numbers_by_country_code (const char *country_code)
{
g_autoptr (GPtrArray) ret = g_ptr_array_new_with_free_func (g_free);
CallsEmergencyNumberTypes *match;
if (country_code == NULL)
return NULL;
init_hash ();
match = g_hash_table_lookup (by_mcc, country_code);
if (!match)
return NULL;
/* Can use g_strv_builder with glib > 2.68 */
for (int i = 0; i < G_N_ELEMENTS (match->numbers); i++) {
char *number = g_strdup (match->numbers[i].number);
g_ptr_array_add (ret, number);
}
g_ptr_array_add (ret, NULL);
return (GStrv) g_ptr_array_steal (ret, NULL);
}