1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * Copyright (C) 2012,2013 Intel Corporation
4 *
5 * This library is free software: you can redistribute it and/or modify it
6 * under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation.
8 *
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Authors: Mathias Hasselmann <mathias@openismus.com>
18 */
19
20 #include "evolution-data-server-config.h"
21
22 #include "e-phone-number.h"
23
24 #include <glib/gi18n-lib.h>
25
26 #include "e-phone-number-private.h"
27
G_DEFINE_BOXED_TYPE(EPhoneNumber,e_phone_number,e_phone_number_copy,e_phone_number_free)28 G_DEFINE_BOXED_TYPE (
29 EPhoneNumber, e_phone_number,
30 e_phone_number_copy, e_phone_number_free)
31
32 G_DEFINE_QUARK (e-phone-number-error-quark, e_phone_number_error)
33
34 static const gchar *
35 e_phone_number_error_to_string (EPhoneNumberError code)
36 {
37 switch (code) {
38 case E_PHONE_NUMBER_ERROR_NOT_IMPLEMENTED:
39 return _("The library was built without phone number support.");
40 case E_PHONE_NUMBER_ERROR_UNKNOWN:
41 return _("The phone number parser reported a yet unknown error code.");
42 case E_PHONE_NUMBER_ERROR_NOT_A_NUMBER:
43 return _("Not a phone number");
44 case E_PHONE_NUMBER_ERROR_INVALID_COUNTRY_CODE:
45 return _("Invalid country calling code");
46 case E_PHONE_NUMBER_ERROR_TOO_SHORT_AFTER_IDD:
47 return _("Remaining text after the country calling code is too short for a phone number");
48 case E_PHONE_NUMBER_ERROR_TOO_SHORT:
49 return _("Text is too short for a phone number");
50 case E_PHONE_NUMBER_ERROR_TOO_LONG:
51 return _("Text is too long for a phone number");
52 }
53
54 return _("Unknown error");
55 }
56
57 void
_e_phone_number_set_error(GError ** error,EPhoneNumberError code)58 _e_phone_number_set_error (GError **error,
59 EPhoneNumberError code)
60 {
61 const gchar *message = e_phone_number_error_to_string (code);
62 g_set_error_literal (error, E_PHONE_NUMBER_ERROR, code, message);
63 }
64
65 /**
66 * e_phone_number_is_supported:
67 *
68 * Checks if phone number support is available. It is recommended to call this
69 * function before using any of the phone-utils functions to ensure that the
70 * required functionality is available, and to pick alternative mechanisms if
71 * needed.
72 *
73 * Returns: %TRUE if phone number support is available.
74 *
75 * Since: 3.8
76 **/
77 gboolean
e_phone_number_is_supported(void)78 e_phone_number_is_supported (void)
79 {
80 #ifdef ENABLE_PHONENUMBER
81
82 return TRUE;
83
84 #else /* ENABLE_PHONENUMBER */
85
86 return FALSE;
87
88 #endif /* ENABLE_PHONENUMBER */
89 }
90
91 /**
92 * e_phone_number_get_country_code_for_region:
93 * @region_code: (nullable): a two-letter country code, a locale name, or
94 * %NULL
95 * @error: a #GError to set an error, if any
96 *
97 * Retrieves the preferred country calling code for @region_code,
98 * e.g. 358 for "fi" or 1 for "en_US@UTF-8".
99 *
100 * If %NULL is passed for @region_code the default region as returned by
101 * e_phone_number_get_default_region() is used.
102 *
103 * Returns: a valid country calling code, or zero if an unknown region
104 * code was passed.
105 *
106 * Since: 3.8
107 */
108 gint
e_phone_number_get_country_code_for_region(const gchar * region_code,GError ** error)109 e_phone_number_get_country_code_for_region (const gchar *region_code,
110 GError **error)
111 {
112 #ifdef ENABLE_PHONENUMBER
113
114 return _e_phone_number_cxx_get_country_code_for_region (region_code);
115
116 #else /* ENABLE_PHONENUMBER */
117
118 _e_phone_number_set_error (error, E_PHONE_NUMBER_ERROR_NOT_IMPLEMENTED);
119 return 0;
120
121 #endif /* ENABLE_PHONENUMBER */
122 }
123
124 /**
125 * e_phone_number_get_default_region:
126 * @error: a #GError to set an error, if any
127 *
128 * Retrieves the current two-letter country code that's used by default for
129 * parsing phone numbers in e_phone_number_from_string(). It can be useful
130 * to store this number before parsing a bigger number of phone numbers.
131 *
132 * The result of this functions depends on the current setup of the
133 * %LC_ADDRESS category: If that category provides a reasonable value
134 * for %_NL_ADDRESS_COUNTRY_AB2 this value is returned. Otherwise the
135 * locale name configured for %LC_ADDRESS is parsed.
136 *
137 * Returns: a newly allocated string containing the
138 * current locale's two-letter code for phone number parsing.
139 *
140 * Since: 3.8
141 */
142 gchar *
e_phone_number_get_default_region(GError ** error)143 e_phone_number_get_default_region (GError **error)
144 {
145 #ifdef ENABLE_PHONENUMBER
146
147 return _e_phone_number_cxx_get_default_region ();
148
149 #else /* ENABLE_PHONENUMBER */
150
151 _e_phone_number_set_error (error, E_PHONE_NUMBER_ERROR_NOT_IMPLEMENTED);
152 return NULL;
153
154 #endif /* ENABLE_PHONENUMBER */
155 }
156
157 /**
158 * e_phone_number_from_string:
159 * @phone_number: the phone number to parse
160 * @region_code: (nullable): a two-letter country code, or %NULL
161 * @error: a #GError to set an error, if any
162 *
163 * Parses the string passed in @phone_number. Note that no validation is
164 * performed whether the recognized phone number is valid for a particular
165 * region.
166 *
167 * The two-letter country code passed in @region_code only is used if the
168 * @phone_number is not written in international format. The application's
169 * default region as returned by e_phone_number_get_default_region() is used
170 * if @region_code is %NULL.
171 *
172 * If the number is guaranteed to start with a '+' followed by the country
173 * calling code, then "ZZ" can be passed for @region_code.
174 *
175 * Returns: (transfer full): a new EPhoneNumber instance on success,
176 * or %NULL on error. Call e_phone_number_free() to release this instance.
177 *
178 * Since: 3.8
179 **/
180 EPhoneNumber *
e_phone_number_from_string(const gchar * phone_number,const gchar * region_code,GError ** error)181 e_phone_number_from_string (const gchar *phone_number,
182 const gchar *region_code,
183 GError **error)
184 {
185 #ifdef ENABLE_PHONENUMBER
186
187 return _e_phone_number_cxx_from_string (phone_number, region_code, error);
188
189 #else /* ENABLE_PHONENUMBER */
190
191 _e_phone_number_set_error (error, E_PHONE_NUMBER_ERROR_NOT_IMPLEMENTED);
192 return NULL;
193
194 #endif /* ENABLE_PHONENUMBER */
195 }
196
197 /**
198 * e_phone_number_to_string:
199 * @phone_number: the phone number to format
200 * @format: the phone number format to apply
201 *
202 * Describes the @phone_number according to the rules applying to @format.
203 *
204 * Returns: (transfer full): A formatted string for @phone_number.
205 *
206 * Since: 3.8
207 **/
208 gchar *
e_phone_number_to_string(const EPhoneNumber * phone_number,EPhoneNumberFormat format)209 e_phone_number_to_string (const EPhoneNumber *phone_number,
210 EPhoneNumberFormat format)
211 {
212 #ifdef ENABLE_PHONENUMBER
213
214 return _e_phone_number_cxx_to_string (phone_number, format);
215
216 #else /* ENABLE_PHONENUMBER */
217
218 /* The EPhoneNumber instance must be invalid. We'd also bail out with
219 * a warning if phone numbers are supported. Any code triggering this
220 * is broken and should be fixed. */
221 g_warning ("%s: The library was built without phone number support.", G_STRFUNC);
222 return NULL;
223
224 #endif /* ENABLE_PHONENUMBER */
225 }
226
227 /**
228 * e_phone_number_get_country_code:
229 * @phone_number: the phone number to query
230 * @source: (nullable): an optional location for storing the phone number's origin, or %NULL
231 *
232 * Queries the @phone_number's country calling code and optionally stores the country
233 * calling code's origin in @source. For instance when parsing "+1-617-5423789" this
234 * function would return one and assing E_PHONE_NUMBER_COUNTRY_FROM_FQTN to @source.
235 *
236 * Returns: A valid country calling code, or zero if no code is known.
237 *
238 * Since: 3.8
239 **/
240 gint
e_phone_number_get_country_code(const EPhoneNumber * phone_number,EPhoneNumberCountrySource * source)241 e_phone_number_get_country_code (const EPhoneNumber *phone_number,
242 EPhoneNumberCountrySource *source)
243 {
244 #ifdef ENABLE_PHONENUMBER
245
246 return _e_phone_number_cxx_get_country_code (phone_number, source);
247
248 #else /* ENABLE_PHONENUMBER */
249
250 /* The EPhoneNumber instance must be invalid. We'd also bail out with
251 * a warning if phone numbers are supported. Any code triggering this
252 * is broken and should be fixed. */
253 g_warning ("%s: The library was built without phone number support.", G_STRFUNC);
254 return 0;
255
256 #endif /* ENABLE_PHONENUMBER */
257 }
258
259 /**
260 * e_phone_number_get_national_number:
261 * @phone_number: the phone number to query
262 *
263 * Queries the national portion of @phone_number without any call-out
264 * prefixes. For instance when parsing "+1-617-5423789" this function would
265 * return the string "6175423789".
266 *
267 * Returns: (transfer full): The national portion of @phone_number.
268 *
269 * Since: 3.8
270 **/
271 gchar *
e_phone_number_get_national_number(const EPhoneNumber * phone_number)272 e_phone_number_get_national_number (const EPhoneNumber *phone_number)
273 {
274 #ifdef ENABLE_PHONENUMBER
275
276 return _e_phone_number_cxx_get_national_number (phone_number);
277
278 #else /* ENABLE_PHONENUMBER */
279
280 /* The EPhoneNumber instance must be invalid. We'd also bail out with
281 * a warning if phone numbers are supported. Any code triggering this
282 * is broken and should be fixed. */
283 g_warning ("%s: The library was built without phone number support.", G_STRFUNC);
284 return NULL;
285
286 #endif /* ENABLE_PHONENUMBER */
287 }
288
289 /**
290 * e_phone_number_compare:
291 * @first_number: the first EPhoneNumber to compare
292 * @second_number: the second EPhoneNumber to compare
293 *
294 * Compares two phone numbers.
295 *
296 * Returns: The quality of matching for the two phone numbers.
297 *
298 * Since: 3.8
299 **/
300 EPhoneNumberMatch
e_phone_number_compare(const EPhoneNumber * first_number,const EPhoneNumber * second_number)301 e_phone_number_compare (const EPhoneNumber *first_number,
302 const EPhoneNumber *second_number)
303 {
304 #ifdef ENABLE_PHONENUMBER
305
306 return _e_phone_number_cxx_compare (first_number, second_number);
307
308 #else /* ENABLE_PHONENUMBER */
309
310 /* The EPhoneNumber instance must be invalid. We'd also bail out with
311 * a warning if phone numbers are supported. Any code triggering this
312 * is broken and should be fixed. */
313 g_warning ("%s: The library was built without phone number support.", G_STRFUNC);
314 return E_PHONE_NUMBER_MATCH_NONE;
315
316 #endif /* ENABLE_PHONENUMBER */
317 }
318
319 /**
320 * e_phone_number_compare_strings:
321 * @first_number: the first EPhoneNumber to compare
322 * @second_number: the second EPhoneNumber to compare
323 * @error: a #GError to set an error, if any
324 *
325 * Compares two phone numbers.
326 *
327 * Returns: The quality of matching for the two phone numbers.
328 *
329 * Since: 3.8
330 **/
331 EPhoneNumberMatch
e_phone_number_compare_strings(const gchar * first_number,const gchar * second_number,GError ** error)332 e_phone_number_compare_strings (const gchar *first_number,
333 const gchar *second_number,
334 GError **error)
335 {
336 return e_phone_number_compare_strings_with_region (
337 first_number, second_number, NULL, error);
338 }
339
340 /**
341 * e_phone_number_compare_strings_with_region:
342 * @first_number: the first EPhoneNumber to compare
343 * @second_number: the second EPhoneNumber to compare
344 * @region_code: (nullable): a two-letter country code, or %NULL
345 * @error: a #GError to set an error, if any
346 *
347 * Compares two phone numbers within the context of @region_code.
348 *
349 * Returns: The quality of matching for the two phone numbers.
350 *
351 * Since: 3.8
352 **/
353 EPhoneNumberMatch
e_phone_number_compare_strings_with_region(const gchar * first_number,const gchar * second_number,const gchar * region_code,GError ** error)354 e_phone_number_compare_strings_with_region (const gchar *first_number,
355 const gchar *second_number,
356 const gchar *region_code,
357 GError **error)
358 {
359 #ifdef ENABLE_PHONENUMBER
360
361 return _e_phone_number_cxx_compare_strings (
362 first_number, second_number, region_code, error);
363
364 #else /* ENABLE_PHONENUMBER */
365
366 _e_phone_number_set_error (error, E_PHONE_NUMBER_ERROR_NOT_IMPLEMENTED);
367 return E_PHONE_NUMBER_MATCH_NONE;
368
369 #endif /* ENABLE_PHONENUMBER */
370 }
371
372 /**
373 * e_phone_number_copy:
374 * @phone_number: the EPhoneNumber to copy
375 *
376 * Makes a copy of @phone_number.
377 *
378 * Returns: (transfer full): A newly allocated EPhoneNumber instance.
379 * Call e_phone_number_free() to release this instance.
380 *
381 * Since: 3.8
382 **/
383 EPhoneNumber *
e_phone_number_copy(const EPhoneNumber * phone_number)384 e_phone_number_copy (const EPhoneNumber *phone_number)
385 {
386 #ifdef ENABLE_PHONENUMBER
387
388 return _e_phone_number_cxx_copy (phone_number);
389
390 #else /* ENABLE_PHONENUMBER */
391
392 /* Without phonenumber support there are no instances.
393 * Any non-NULL value is a programming error in this setup. */
394 g_warn_if_fail (phone_number == NULL);
395 return NULL;
396
397 #endif /* ENABLE_PHONENUMBER */
398 }
399
400 /**
401 * e_phone_number_free:
402 * @phone_number: the EPhoneNumber to free
403 *
404 * Released the memory occupied by @phone_number.
405 *
406 * Since: 3.8
407 **/
408 void
e_phone_number_free(EPhoneNumber * phone_number)409 e_phone_number_free (EPhoneNumber *phone_number)
410 {
411 #ifdef ENABLE_PHONENUMBER
412
413 _e_phone_number_cxx_free (phone_number);
414
415 #else /* ENABLE_PHONENUMBER */
416
417 /* Without phonenumber support there are no instances.
418 * Any non-NULL value is a programming error in this setup. */
419 g_warn_if_fail (phone_number == NULL);
420
421 #endif /* ENABLE_PHONENUMBER */
422 }
423