Some string parsing functions



Hi!
When I was developing The Garp (garp.sourceforge.net), I encountered a 
problem.
There are no functions in Glib or Glibc to find, delete, insert and replace 
substrings.
I asked the people at gtk-app-devel-list@gnome.org, but they say there isn't 
such thing in Glib yet.
Havoc told me this would be nice to add to the TODO list of Glib 1.4.

But here's the good news: no need to add that to TODO :-)
I implemented all those functions and tested them.
I attached the file in this email. Please take a look at it.

I hope my functions will be included in Glib.
/* String parsing library. Copyright (c) 2000 by Hongli Lai
   LGPL of course ;-)
   I sure hope this will be included in Glib 1.4. The Garp will need this. */

/* Status: all functions are 100% working.

   I think there are no memory leaks (though I didn't test it with Memprof).

   As far as I know (I tested all functions) all function have no bugs.

   All functions except the g_str_replace_* ones are documented.
   However, English is not my primary language, so there might be some bugs in the documentation :-(
   Feel free to fix them. */


#include <glib.h>
#include <string.h>

/* String searching and copying functions */
gint g_str_get_length (const gchar *str);
gchar *g_str_find_substr (const gchar *str, const gchar *str_to_find);
gchar *g_str_find_substr_right (const gchar *str, const gchar *str_to_find);
gint g_str_find_substr_index (const gchar *str, const gchar *str_to_find);
gint g_str_find_substr_index_start_from (const gchar *str, guint startpos, const gchar *str_to_find);
gint g_str_find_substr_index_right (const gchar *str, const gchar *str_to_find);
gchar *g_str_copy_substr (const gchar *str, guint index, guint count);
gchar *g_str_copy_substr_index (const gchar *str, guint startpos, guint endpos);

/* String manipulation functions */
gchar *g_str_delete_substr (const gchar *str, guint index, guint count);
gchar *g_str_insert_substr (const gchar *str, guint index, const gchar *substr_to_insert);
gchar *g_str_replace_substr (const gchar *str, const gchar *substr_to_replace, const gchar *replace_with);
gchar *g_str_replace_substr_start_from (const gchar *str, guint startpos, const gchar *substr_to_replace, const gchar *replace_with);
gchar *g_str_replace_substr_right (const gchar *str, const gchar *substr_to_replace, const gchar *replace_with);
gchar *g_str_replace_substr_all (const gchar *str, const gchar *substr_to_replace, const gchar *replace_with);



/*  g_str_get_length(const gchar *str)
    1 parameter

    str: The string to calculate.

    Description:
    Calculates the length of a string.

    Return value:
    The length of str. If str is NULL, it will return 0.

    Examples:
    g_str_get_length ("Hello World!");  // => 12
    g_str_get_length (NULL);            // => 0
*/
gint
g_str_get_length (const gchar *str)
{
    if (str == NULL) return 0;
    else return strlen (str);
}


/*  g_str_find_substr(const gchar *str, const gchar *str_to_find)
    2 parameters

    str: The string that contains the substring.
    str_to_find: The substring to find in str.

    Description:
    Find a substring in a string. This function is case insensitive.

    Return value:
    A newly allocated string. The string has the contents of str, beginning
    from the begin of str and ends with the place where str_to_find is.
    (How do I explain this in English? Maybe the examples will enlighten it.)
    If str or str_to_find are NULL, or if the substring is not found, it will return NULL.
    The return value should be freed when no longer needed.

    Examples:
    g_str_find_substr ("Hello World!", "lo Wo");          // => "Hello Wo"
    g_str_find_substr ("Hi there. What's up?", "What");   // => "Hi there. What"
    g_str_find_substr ("Yet another string", "hello");    // => NULL, because string is not found
    g_str_find_substr ("Hello. Hello World.", "Hello");   // => "Hello" and not "Hello. Hello"
                                                          //    because this function start seeking
                                                          //    from left instead of right.
*/
gchar*
g_str_find_substr (const gchar *str, const gchar *str_to_find)
{
    gchar *result;
    gint i;

    if (str == NULL || str_to_find == NULL) return NULL;
    i = g_str_find_substr_index (str, str_to_find);
    if (i == -1) return NULL;

    result = g_new0 (gchar, g_str_get_length (str_to_find) + 1);
    result = g_str_copy_substr (str, 0, i + g_str_get_length (str_to_find));

    return result;
}


/*  g_str_find_substr_right(const gchar *str, const gchar *str_to_find)
    2 parameters

    str: The string that contains the substring.
    str_to_find: The substring to find in str.

    Description:
    Find a substring in a string. This function is case insensitive.
    This function is the same as g_str_find_substr, but starts seeking from the right instead of left.

    Return value:
    A newly allocated string. The string has the contents of str, beginning
    from the place where str_to_find is found and ends where str ends.
    (How do I explain this in English? Maybe the example will enlighten it.)
    If str or str_to_find are NULL, or if the substring is not found, it will return NULL.
    The return value should be freed when no longer needed.

    Examples:
    g_str_find_substr_right ("Hello World!", "lo Wo");          // => "lo World!"
    g_str_find_substr_right ("Hi there. What's up?", "What");   // => "What's up?"
    g_str_find_substr_right ("Yet another string", "hello");    // => NULL, because string is not found
    g_str_find_substr_right ("Hello. Hello World.", "Hello");   // => "Hello World." and not "Hello"
                                                                //    because this function start seeking
                                                                //    from right instead of left.
*/
gchar*
g_str_find_substr_right (const gchar *str, const gchar *str_to_find)
{
    gchar *result;
    gint i;

    if (str == NULL || str_to_find == NULL) return NULL;
    i = g_str_find_substr_index_right (str, str_to_find);
    if (i == -1) return NULL;

    result = g_new0 (gchar, g_str_get_length (str_to_find) + 1);
    result = g_str_copy_substr (str, i, g_str_get_length (str) - i);

    return result;
}


/*  g_str_find_substr_index(const gchar *str, const gchar *str_to_find)
    2 parameters

    str: The string that contains the substring.
    str_to_find: The substring to find in str.

    Description:
    Find a substring in a string. This function is case insensitive.

    Return value:
    The index where str_to_find starts. If str or str_to_find are NULL, the length
    of str_to_find is higher than the length of str, or if the substring is
    not found, it will return -1.
    This function starts seeking from the left.

    Examples:
    g_str_find_substr_index ("Hello World!", "lo Wo");          // => 3
    g_str_find_substr_index ("Hi there. What's up?", "What");   // => 11
    g_str_find_substr_index ("Yet another string", "hello");    // => -1, because string is not found
    g_str_find_substr_index ("Hello. Hello World.", "Hello");   // => 0, not 7, because this function
                                                                //    starts seeking from the left.
*/
gint
g_str_find_substr_index (const gchar *str, const gchar *str_to_find)
{
    guint i = 0;
    gint result = -1;

    if (str == NULL || str_to_find == NULL) return -1;
    if (g_str_get_length (str_to_find) > g_str_get_length (str)) return -1;

    for (i = 0; i < g_str_get_length (str) - g_str_get_length (str_to_find) + 1; i++)
    {
        gchar *s = g_str_copy_substr (str, i, g_str_get_length (str_to_find));
        if (g_strcasecmp (s, str_to_find) == 0) {
            result = i;
            g_free (s);
            break;
        }
        g_free (s);
    }

    return result;
}


/*  g_str_find_substr_index_start_from(const gchar *str, guint startpos, const gchar *str_to_find)
    2 parameters

    str: The string that contains the substring.
    startpos: The position to start seeking.
    str_to_find: The substring to find in str.

    Description:
    Find a substring in a string. This function is case insensitive.

    Return value:
    The index where str_to_find starts. If str or str_to_find are NULL, the length
    of str_to_find is higher than the length of str, or if the substring is
    not found, it will return -1.
    This function starts seeking from the right.

    Examples:
    g_str_find_substr_index_right ("Hello World!", 0, "lo Wo");          // => 3
    g_str_find_substr_index_right ("Hi there. What's up?", 3, "What");   // => 11
    g_str_find_substr_index_right ("Yet another string", 2, "hello");    // => -1, because string is not found
    g_str_find_substr_index_right ("Hello. Hello World.", 13, "Hello");  // => -1, because it starts seeking
                                                                         //    from position 13 in str.
*/
gint
g_str_find_substr_index_start_from (const gchar *str, guint startpos, const gchar *str_to_find)
{
    guint i = 0;
    gint result = -1;

    if (str == NULL || str_to_find == NULL) return -1;
    if (g_str_get_length (str_to_find) > g_str_get_length (str)) return -1;

    for (i = startpos; i < g_str_get_length (str) - g_str_get_length (str_to_find) + 1; i++)
    {
        gchar *s = g_str_copy_substr (str, i, g_str_get_length (str_to_find));
        if (g_strcasecmp (s, str_to_find) == 0) {
            result = i;
            g_free (s);
            break;
        }
        g_free (s);
    }

    return result;
}


/*  g_str_find_substr_index_right(const gchar *str, const gchar *str_to_find)
    2 parameters

    str: The string that contains the substring.
    str_to_find: The substring to find in str.

    Description:
    Find a substring in a string. This function is case insensitive.

    Return value:
    The index where str_to_find starts. If str or str_to_find are NULL, the length
    of str_to_find is higher than the length of str, or if the substring is
    not found, it will return -1.
    This function starts seeking from the right.

    Examples:
    g_str_find_substr_index_right ("Hello World!", "lo Wo");          // => 3
    g_str_find_substr_index_right ("Hi there. What's up?", "What");   // => 11
    g_str_find_substr_index_right ("Yet another string", "hello");    // => -1, because string is not found
    g_str_find_substr_index_right ("Hello. Hello World.", "Hello");   // => 7, not 0, because this function
                                                                      //    starts seeking from the right.
*/
gint
g_str_find_substr_index_right (const gchar *str, const gchar *str_to_find)
{
    guint i = 0;
    gint result = -1;

    if (str == NULL || str_to_find == NULL) return -1;
    if (g_str_get_length (str_to_find) > g_str_get_length (str)) return -1;

    for (i = g_str_get_length (str) - g_str_get_length (str_to_find); i > 0; i--)
    {
        gchar *s = g_str_copy_substr (str, i, g_str_get_length (str_to_find));
        if (g_strcasecmp (s, str_to_find) == 0) {
            result = i;
            g_free (s);
            break;
        }
        g_free (s);
    }

    return result;
}


/*  g_str_copy_substr(const gchar *str, guint index, guint count)
    3 parameters

    str: The string to copy
    index: The index to start copying.
    count: The count of characters to copy.

    Description:
    Copy count characters in str, starting from index.

    Return value:
    A newly allocated string. It should be freed when no longer needed.

    Examples:
    g_str_copy_substr ("Hello World!", 1, 3);    // => "ell"
    g_str_copy_substr ("What's up?", 5, 2);      // => "'s"
*/
gchar*
g_str_copy_substr (const gchar *str, guint index, guint count)
{
    gchar *result;
    guint i;

    if (str == NULL || index < 0 || count <= 0) return NULL;

    result = g_new0 (gchar, count + 1);
    for (i = 0; i < count; i++)
        result[i] = str[index + i];
    return result;
}


/*  g_str_copy_substr_index(const gchar *str, guint startpos, guint endpos)
    3 parameters

    str: The string to copy
    startpos: The index to start copying.
    endpos: The index to stop copying.

    Description:
    Copy characters in str, starting from startpos to endpos.

    Return value:
    A newly allocated string. It should be freed when no longer needed.

    Examples:
    g_str_copy_substr ("Hello World!", 1, 4);        // => "ello"
    g_str_copy_substr ("What's up?", 5, 2);          // => NULL
    g_str_copy_substr ("Yet another string", 4, 9);  // => "anothe"
*/
gchar*
g_str_copy_substr_index (const gchar *str, guint startpos, guint endpos)
{
    gchar *result;
    guint i, x = 0;

    if (str == NULL) return NULL;
    if (startpos > endpos) return NULL;

    result = g_new0 (gchar, endpos - startpos + 1);
    for (i = startpos; i <= endpos; i++) {
        result[x] = str[i];
        x++;
    }
    return result;
}


/*  g_str_delete_substr(const gchar *str, guint index, guint count)
    3 parameters

    str: The string to copy
    index: The index to start copying.
    count: The count of characters to copy.

    Description:
    Deletes count characters in str, starting from index.

    Return value:
    A newly allocated string. str remains unmodified. It should be freed when no longer needed.

    Examples:
    g_str_delete_substr ("Hello World!", 3, 2);      // => "Hel World!"
    g_str_delete_substr ("What's up?", 0, 2);        // => "at's up?"
*/
gchar*
g_str_delete_substr (const gchar *str, guint index, guint count)
{
    gchar *result;

    if (str == NULL) return NULL;

    if (index > 0)
    {
        gchar *tmp, *tmp2;
        result = g_str_copy_substr (str, 0, index);
        tmp = g_str_copy_substr (str, index + count, g_str_get_length (str) - (index + count));
        if (tmp != NULL) {
             tmp2 = g_strdup_printf ("%s%s", result, tmp);
             g_free (result);
             g_free (tmp);
             result = g_strdup (tmp2);
             g_free (tmp2);
         } else
             g_free (tmp);
    } else
        result = g_str_copy_substr_index (str, count, g_str_get_length (str));

    return result;
}


/*  g_str_insert_substr(const gchar *str, guint index, const gchar *substr_to_insert)
    3 parameters

    str: The string to copy
    index: The index to start insertion.
    substr_to_insert: The string to insert.

    Description:
    Inserts substr_to_insert in str, starting from index.

    Return value:
    A newly allocated string. str remains unmodified. It should be freed when no longer needed.
    It returns NULL if str or substr_to_insert are NULL.

    Examples:
    g_str_insert_substr ("Hello World!", 6, "good old ");   // => "Hello good old World!"
    g_str_insert_substr ("What's up?", 0, "Yo! ");          // => "Yo! What's up?"
*/
gchar*
g_str_insert_substr (const gchar *str, guint index, const gchar *substr_to_insert)
{
    gchar *result;

    if (str == NULL || substr_to_insert == NULL) return NULL;

    if (index > 0)
    {
        gchar *tmp, *tmp2;
        result = g_str_copy_substr (str, 0, index);
        tmp = g_strdup_printf ("%s%s", result, substr_to_insert);
        g_free (result);
        result = g_strdup (tmp);
        g_free (tmp);
        tmp = g_str_copy_substr_index (str, index,
          g_str_get_length (str));
        tmp2 = g_strdup_printf ("%s%s", result, tmp);
        g_free (tmp);
        g_free (result);
        result = g_strdup (tmp2);
        g_free (tmp2);
    } else
        result = g_strdup_printf ("%s%s", substr_to_insert, str);

    return result;
}


gchar*
g_str_replace_substr (const gchar *str, const gchar *substr_to_replace, const gchar *replace_with)
{
    gchar *result, *tmp;
    gint i;

    if (str == NULL || substr_to_replace == NULL || replace_with == NULL) return NULL;
    i = g_str_find_substr_index (str, substr_to_replace);
    if (i == -1) return g_strdup (str);

    i = g_str_find_substr_index (str, substr_to_replace);
    tmp = g_str_delete_substr (str, i, g_str_get_length (substr_to_replace));
    result = g_str_insert_substr (tmp, i, replace_with);
    g_free (tmp);

    return result;
}


gchar*
g_str_replace_substr_start_from (const gchar *str, guint startpos, const gchar *substr_to_replace, const gchar *replace_with)
{
    gchar *result, *tmp;
    gint i;

    if (str == NULL || substr_to_replace == NULL || replace_with == NULL) return NULL;
    i = g_str_find_substr_index (str, substr_to_replace);
    if (i == -1) return g_strdup (str);

    i = g_str_find_substr_index_start_from (str, startpos, substr_to_replace);
    tmp = g_str_delete_substr (str, i, g_str_get_length (substr_to_replace));
    result = g_str_insert_substr (tmp, i, replace_with);
    g_free (tmp);

    return result;
}


gchar*
g_str_replace_substr_right (const gchar *str, const gchar *substr_to_replace, const gchar *replace_with)
{
    gchar *result, *tmp;
    gint i;

    if (str == NULL || substr_to_replace == NULL || replace_with == NULL) return NULL;
    i = g_str_find_substr_index_right (str, substr_to_replace);
    if (i == -1) return g_strdup (str);

    i = g_str_find_substr_index_right (str, substr_to_replace);
    tmp = g_str_delete_substr (str, i, g_str_get_length (substr_to_replace));
    result = g_str_insert_substr (tmp, i, replace_with);
    g_free (tmp);

    return result;
}


gchar*
g_str_replace_substr_all (const gchar *str, const gchar *substr_to_replace, const gchar *replace_with)
{
    gchar *result, *tmp;
    gint i;

    if (str == NULL || substr_to_replace == NULL || replace_with == NULL) return NULL;
    i = g_str_find_substr_index (str, substr_to_replace);
    if (i == -1) return g_strdup (str);

    result = g_strdup (str);
    i = g_str_find_substr_index (result, substr_to_replace);
    while (i > -1)
    {
        tmp = g_str_replace_substr_start_from (result, i, substr_to_replace, replace_with);
        g_free (result);
        result = g_strdup (tmp);
        g_free (tmp);
        i = g_str_find_substr_index_start_from (result, i + g_str_get_length (replace_with), substr_to_replace);
    }
    return result;
}


int main(int argc, char *argv[]) {
    /* Test code goes here */
    return 0;
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]