/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* Copyright © 2002 Marco Pesenti Gritti
*
* This file is part of Epiphany.
*
* Epiphany is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Epiphany is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Epiphany. If not, see .
*/
#include "config.h"
#include "ephy-string.h"
#include
#include
#include
#include
#include
#include
#include
gboolean
ephy_string_to_int (const char *string,
gulong *integer)
{
gulong result;
char *parse_end;
/* Check for the case of an empty string. */
if (string == NULL || *string == '\0')
return FALSE;
/* Call the standard library routine to do the conversion. */
errno = 0;
result = strtol (string, &parse_end, 0);
/* Check that the result is in range. */
if (errno == ERANGE)
return FALSE;
/* Check that all the trailing characters are spaces. */
while (*parse_end != '\0') {
if (!g_ascii_isspace (*parse_end++))
return FALSE;
}
/* Return the result. */
*integer = result;
return TRUE;
}
char *
ephy_string_blank_chr (char *source)
{
char *p;
if (source == NULL)
return NULL;
p = source;
while (*p != '\0') {
if ((guchar) * p < 0x20)
*p = ' ';
p++;
}
return source;
}
/**
* ephy_string_shorten: shortens a string
* @str: the string to shorten, in UTF-8
* @target_length: the length of the shortened string (in characters)
*
* If @str is already short enough, it is returned. Otherwise a new string
* is allocated and @str is consumed.
*
* Return value: a newly allocated string, not longer than target_length
* characters.
*/
char *
ephy_string_shorten (char *str,
gsize target_length)
{
char *new_str;
glong actual_length;
gulong bytes;
g_assert (target_length > 0);
if (!str)
return NULL;
/* FIXME: this function is a big mess. While it is utf-8 safe now,
* it can still split a sequence of combining characters.
*/
actual_length = g_utf8_strlen (str, -1);
/* if the string is already short enough, or if it's too short for
* us to shorten it, return a new copy */
if ((gsize)actual_length <= target_length)
return str;
/* create string */
bytes = GPOINTER_TO_UINT (g_utf8_offset_to_pointer (str, target_length - 1) - str);
/* +1 for ellipsis, +1 for trailing NUL */
new_str = g_new (gchar, bytes + 1 + 1);
strncpy (new_str, str, bytes);
strcat (new_str, "…");
g_free (str);
return new_str;
}
/* This is a collation key that is very very likely to sort before any
* collation key that libc strxfrm generates. We use this before any
* special case (dot or number) to make sure that its sorted before
* anything else.
*/
#define COLLATION_SENTINEL "\1\1\1"
/**
* ephy_string_collate_key_for_domain:
* @host:
* @len: the length of @host, or -1 to use the entire null-terminated @host string
*
* Return value: a collation key for @host.
*/
char *
ephy_string_collate_key_for_domain (const char *str,
gssize len)
{
GString *result;
const char *dot;
gssize newlen;
if (len < 0)
len = strlen (str);
result = g_string_sized_new (len + 6 * strlen (COLLATION_SENTINEL));
/* Note that we could do even better by using
* g_utf8_collate_key_for_filename on the dot-separated
* components, but this seems good enough for now.
*/
while ((dot = g_strrstr_len (str, len, ".")) != NULL) {
newlen = dot - str;
g_string_append_len (result, dot + 1, len - newlen - 1);
g_string_append (result, COLLATION_SENTINEL);
len = newlen;
}
if (len > 0)
g_string_append_len (result, str, len);
return g_string_free (result, FALSE);
}
char *
ephy_string_get_host_name (const char *url)
{
SoupURI *uri;
char *ret;
if (url == NULL ||
g_str_has_prefix (url, "file://") ||
g_str_has_prefix (url, "about:") ||
g_str_has_prefix (url, "ephy-about:"))
return NULL;
uri = soup_uri_new (url);
/* If uri is NULL it's very possible that we just got
* something without a scheme, let's try to prepend
* 'http://' */
if (uri == NULL) {
char *effective_url = g_strconcat ("http://", url, NULL);
uri = soup_uri_new (effective_url);
g_free (effective_url);
}
if (uri == NULL) return NULL;
ret = g_strdup (uri->host);
soup_uri_free (uri);
return ret;
}
/**
* ephy_string_commandline_args_to_uris:
* @arguments: a %NULL-terminated array of chars.
*
* Transform commandline arguments to URIs if they are native,
* otherwise simply transform them to UTF-8.
*
* Returns: a newly allocated array with the URIs and
* UTF-8 strings.
**/
char **
ephy_string_commandline_args_to_uris (char **arguments,
GError **error)
{
gchar **args;
GFile *file;
guint i;
if (arguments == NULL)
return NULL;
args = g_malloc0 (sizeof (gchar *) * (g_strv_length (arguments) + 1));
for (i = 0; arguments[i] != NULL; ++i) {
file = g_file_new_for_commandline_arg (arguments [i]);
if (g_file_is_native (file) && g_file_query_exists (file, NULL)) {
args[i] = g_file_get_uri (file);
} else {
args[i] = g_locale_to_utf8 (arguments [i], -1,
NULL, NULL, error);
if (error && *error) {
g_strfreev (args);
return NULL;
}
}
g_object_unref (file);
}
return args;
}
char *
ephy_string_find_and_replace (const char *haystack,
const char *to_find,
const char *to_repl)
{
GString *str;
const char *tmp;
gsize to_find_len;
gsize pos;
g_assert (haystack);
g_assert (to_find);
g_assert (to_repl);
str = g_string_new (haystack);
to_find_len = strlen (to_find);
while ((tmp = strstr (str->str, to_find)) != NULL) {
pos = tmp - str->str;
g_string_erase (str, pos, to_find_len);
g_string_insert (str, pos, to_repl);
}
return g_string_free (str, FALSE);
}
/*
* Adapted from GLib's g_strchug()
*
* This function doesn't allocate or reallocate any memory;
* it modifies @string in place. Therefore, it cannot be used on
* statically allocated strings.
*
* The pointer to @string is returned to allow the nesting of functions.
*/
char *
ephy_string_remove_leading (char *string,
char ch)
{
char *start;
g_assert (string);
for (start = string; *start && *start == ch; start++)
;
memmove (string, start, strlen (start) + 1);
return string;
}
/*
* Adapted from GLib's g_strchomp()
*
* This function doesn't allocate or reallocate any memory;
* it modifies @string in place. Therefore, it cannot be used on
* statically allocated strings.
*
* The pointer to @string is returned to allow the nesting of functions.
*/
char *
ephy_string_remove_trailing (char *string,
char ch)
{
g_assert (string);
for (gssize i = strlen (string) - 1; i >= 0 && string[i] == ch; i--)
string[i] = '\0';
return string;
}
char **
ephy_strv_append (const char * const *strv,
const char *str)
{
char **new_strv;
char **n;
const char * const *s;
guint len;
if (g_strv_contains (strv, str))
return g_strdupv ((char **)strv);
/* Needs room for one more string than before, plus one for trailing NULL. */
len = g_strv_length ((char **)strv);
new_strv = g_malloc ((len + 1 + 1) * sizeof (char *));
n = new_strv;
s = strv;
while (*s != NULL) {
*n = g_strdup (*s);
n++;
s++;
}
new_strv[len] = g_strdup (str);
new_strv[len + 1] = NULL;
return new_strv;
}
char **
ephy_strv_remove (const char * const *strv,
const char *str)
{
char **new_strv;
char **n;
const char * const *s;
guint len;
if (!g_strv_contains (strv, str))
return g_strdupv ((char **)strv);
/* Needs room for one fewer string than before, plus one for trailing NULL. */
len = g_strv_length ((char **)strv);
new_strv = g_malloc ((len - 1 + 1) * sizeof (char *));
n = new_strv;
s = strv;
while (*s != NULL) {
if (strcmp (*s, str) != 0) {
*n = g_strdup (*s);
n++;
}
s++;
}
new_strv[len - 1] = NULL;
return new_strv;
}