glib-backports: Move flatpak_utils_ascii_string_to_unsigned to here

Currently this is used unconditionally, even if GLib is new enough.
That will be changed in a subsequent commit; no functional change
intended in this one.

Signed-off-by: Simon McVittie <smcv@collabora.com>
This commit is contained in:
Simon McVittie
2023-05-16 12:28:13 +01:00
parent 99878f6356
commit ba556fb98c
4 changed files with 91 additions and 92 deletions

View File

@@ -89,6 +89,14 @@ g_ptr_array_find_with_equal_func (GPtrArray *haystack,
}
#endif
/* From GLib 2.54, currently used unconditionally */
gboolean flatpak_utils_ascii_string_to_unsigned (const gchar *str,
guint base,
guint64 min,
guint64 max,
guint64 *out_num,
GError **error);
#if !GLIB_CHECK_VERSION (2, 56, 0)
typedef void (* GClearHandleFunc) (guint handle_id);

View File

@@ -31,6 +31,89 @@
/* Please sort this file by the GLib version where it originated,
* oldest first. */
/* From GLib 2.54, currently used unconditionally */
#if 1
static gboolean
str_has_sign (const gchar *str)
{
return str[0] == '-' || str[0] == '+';
}
static gboolean
str_has_hex_prefix (const gchar *str)
{
return str[0] == '0' && g_ascii_tolower (str[1]) == 'x';
}
gboolean
flatpak_utils_ascii_string_to_unsigned (const gchar *str,
guint base,
guint64 min,
guint64 max,
guint64 *out_num,
GError **error)
{
guint64 number;
const gchar *end_ptr = NULL;
gint saved_errno = 0;
g_return_val_if_fail (str != NULL, FALSE);
g_return_val_if_fail (base >= 2 && base <= 36, FALSE);
g_return_val_if_fail (min <= max, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
if (str[0] == '\0')
{
g_set_error_literal (error,
G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
_("Empty string is not a number"));
return FALSE;
}
errno = 0;
number = g_ascii_strtoull (str, (gchar **) &end_ptr, base);
saved_errno = errno;
if (/* We do not allow leading whitespace, but g_ascii_strtoull
* accepts it and just skips it, so we need to check for it
* ourselves.
*/
g_ascii_isspace (str[0]) ||
/* Unsigned number should have no sign.
*/
str_has_sign (str) ||
/* We don't support hexadecimal numbers prefixed with 0x or
* 0X.
*/
(base == 16 && str_has_hex_prefix (str)) ||
(saved_errno != 0 && saved_errno != ERANGE) ||
end_ptr == NULL ||
*end_ptr != '\0')
{
g_set_error (error,
G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
_("“%s” is not an unsigned number"), str);
return FALSE;
}
if (saved_errno == ERANGE || number < min || number > max)
{
gchar *min_str = g_strdup_printf ("%" G_GUINT64_FORMAT, min);
gchar *max_str = g_strdup_printf ("%" G_GUINT64_FORMAT, max);
g_set_error (error,
G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
_("Number “%s” is out of bounds [%s, %s]"),
str, min_str, max_str);
g_free (min_str);
g_free (max_str);
return FALSE;
}
if (out_num != NULL)
*out_num = number;
return TRUE;
}
#endif
#if !GLIB_CHECK_VERSION (2, 56, 0)
/* All this code is backported directly from GLib 2.76.2 except where noted */

View File

@@ -241,13 +241,6 @@ gboolean flatpak_remove_dangling_symlinks (GFile *dir,
GCancellable *cancellable,
GError **error);
gboolean flatpak_utils_ascii_string_to_unsigned (const gchar *str,
guint base,
guint64 min,
guint64 max,
guint64 *out_num,
GError **error);
gboolean flatpak_g_ptr_array_contains_string (GPtrArray *array,
const char *str);

View File

@@ -8019,91 +8019,6 @@ flatpak_check_required_version (const char *ref,
return TRUE;
}
static gboolean
str_has_sign (const gchar *str)
{
return str[0] == '-' || str[0] == '+';
}
static gboolean
str_has_hex_prefix (const gchar *str)
{
return str[0] == '0' && g_ascii_tolower (str[1]) == 'x';
}
/* Copied from glib-2.54.0 to avoid the Glib's version bump.
* Function name in glib: g_ascii_string_to_unsigned
* If this is being dropped(migration to g_ascii_string_to_unsigned)
* make sure to remove str_has_hex_prefix and str_has_sign helpers too.
*/
gboolean
flatpak_utils_ascii_string_to_unsigned (const gchar *str,
guint base,
guint64 min,
guint64 max,
guint64 *out_num,
GError **error)
{
guint64 number;
const gchar *end_ptr = NULL;
gint saved_errno = 0;
g_return_val_if_fail (str != NULL, FALSE);
g_return_val_if_fail (base >= 2 && base <= 36, FALSE);
g_return_val_if_fail (min <= max, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
if (str[0] == '\0')
{
g_set_error_literal (error,
G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
_("Empty string is not a number"));
return FALSE;
}
errno = 0;
number = g_ascii_strtoull (str, (gchar **) &end_ptr, base);
saved_errno = errno;
if (/* We do not allow leading whitespace, but g_ascii_strtoull
* accepts it and just skips it, so we need to check for it
* ourselves.
*/
g_ascii_isspace (str[0]) ||
/* Unsigned number should have no sign.
*/
str_has_sign (str) ||
/* We don't support hexadecimal numbers prefixed with 0x or
* 0X.
*/
(base == 16 && str_has_hex_prefix (str)) ||
(saved_errno != 0 && saved_errno != ERANGE) ||
end_ptr == NULL ||
*end_ptr != '\0')
{
g_set_error (error,
G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
_("“%s” is not an unsigned number"), str);
return FALSE;
}
if (saved_errno == ERANGE || number < min || number > max)
{
gchar *min_str = g_strdup_printf ("%" G_GUINT64_FORMAT, min);
gchar *max_str = g_strdup_printf ("%" G_GUINT64_FORMAT, max);
g_set_error (error,
G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
_("Number “%s” is out of bounds [%s, %s]"),
str, min_str, max_str);
g_free (min_str);
g_free (max_str);
return FALSE;
}
if (out_num != NULL)
*out_num = number;
return TRUE;
}
static int
dist (const char *s, int ls, const char *t, int lt, int i, int j, int *d)
{