aboutsummaryrefslogtreecommitdiffstats
path: root/camel/string-utils.c
blob: 7cfd07e6d8fb0cbaf164bfaedacada28bbc3f818 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* string-util : utilities for gchar* strings  */

/* 
 *
 * Copyright (C) 1999 Bertrand Guiheneuf <Bertrand.Guiheneuf@inria.fr> .
 *
 * This program 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 2 of the
 * License, or (at your option) any later version.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 */



#include <config.h>
#include "string-utils.h"
#include "camel-log.h"



gboolean
string_equal_for_glist (gconstpointer v, gconstpointer v2)
{
  return (!strcmp ( ((const gchar *)v), ((const gchar*)v2))) == 0;
}

/**
 * string_dichotomy:
 * @sep : separator
 * @prefix: pointer to be field by the prefix object
 *   the prefix is not returned when the given pointer is NULL
 * @suffix: pointer to be field by the suffix object
 *   the suffix is not returned when the given pointer is NULL
 *
 * Return the strings before and/or after 
 * the last occurence of the specified separator
 *
 * This routine returns the string before and/or after
 * a character given as an argument. 
 * if the separator is the last character, prefix and/or
 * suffix is set to NULL and result is set to 'l'
 * if the separator is not in the list, prefix and/or
 * suffix is set to NULL and result is set to 'n'
 * When the operation succedeed, the return value is 'o'
 *
 * @Return Value : result of the operation ('o', 'l' or 'n')
 *
 **/
gchar
string_dichotomy (const gchar *string, gchar sep, gchar **prefix, gchar **suffix,
            StringDichotomyOption options)
{
    gchar *tmp_str;
    gint sep_pos, first, last, len;
    
    g_assert (string);
    CAMEL_LOG_FULL_DEBUG (\
          "string_dichotomy:: string=\"%s\"\n\tseparator=\"%c\" \n\tprefix=%p \n\tsuffix=%p \n\toptions=%ld\n",\
          string, sep, prefix, suffix, options);
    len = strlen (string);
    if (!len) {
        if (prefix)
            *prefix=NULL;
        if (suffix)
            *suffix=NULL;
        CAMEL_LOG_FULL_DEBUG ("string_dichotomy:: input string is empty\n");
        return 'n';
    }
    first = 0;
    last = len-1;
    
    if ( (options & STRING_DICHOTOMY_STRIP_LEADING ) && (string[first] == sep) )
        do {first++;} while ( (first<len) && (string[first] == sep) );
    
    if (options & STRING_DICHOTOMY_STRIP_TRAILING )
        while ((string[last] == sep) && (last>first))
            last--;
    
    if (first==last) {
        if (prefix) *prefix=NULL;
        if (suffix) *suffix=NULL;
        CAMEL_LOG_FULL_DEBUG ("string_dichotomy: after stripping, string is empty\n");
        return 'n';
    }
    
    if (options & STRING_DICHOTOMY_RIGHT_DIR) {
        sep_pos = last;
        while ((sep_pos>=first) && (string[sep_pos]!=sep)) {
            sep_pos--;
        }
    } else {
        sep_pos = first;
        while ((sep_pos<=last) && (string[sep_pos]!=sep)) {
            sep_pos++;
        }
        
    }
    
    if ( (sep_pos<first) || (sep_pos>last) ) 
        {
            if (suffix) *suffix=NULL;
            if (prefix) *prefix=NULL;
            CAMEL_LOG_FULL_DEBUG ("string_dichotomy: separator not found\n");
            return 'n';
        }
    
    /* if we have stripped trailing separators, we should */
    /* never enter here */
    if (sep_pos==last) 
        {
            if (suffix) *suffix=NULL;
            if (prefix) *prefix=NULL;
            CAMEL_LOG_FULL_DEBUG ("string_dichotomy: separator is last character\n");
            return 'l';
        }
    /* if we have stripped leading separators, we should */
    /* never enter here */
    if (sep_pos==first)
        {
            if (suffix) *suffix=NULL;
            if (prefix) *prefix=NULL;
            CAMEL_LOG_FULL_DEBUG ("string_dichotomy: separator is first character\n");
            return 'l';
        }
    CAMEL_LOG_FULL_DEBUG ("string_dichotomy: separator found at :%d\n", sep_pos);
    if (prefix) { /* return the prefix */
        *prefix = g_strndup(string+first,sep_pos-first);
        CAMEL_LOG_FULL_DEBUG ( "string_dichotomy:: prefix:\"%s\"\n", *prefix);
    }
    if (suffix) { /* return the suffix */
        *suffix = g_strndup(string+sep_pos+1, last-sep_pos);
        CAMEL_LOG_FULL_DEBUG ( "string_dichotomy:: suffix:\"%s\"\n", *suffix);
    }
     
    return 'o';
}






/* utility func : frees a gchar element in a GList */
static void 
__string_list_free_string (gpointer data, gpointer user_data)
{
    gchar *string = (gchar *)data;
    g_free(string);
}


void 
string_list_free (GList *string_list)
{
    g_list_foreach (string_list, __string_list_free_string, NULL);
    g_list_free (string_list);
}






GList *
string_split (const gchar *string, char sep, const gchar *trim_chars, StringTrimOption trim_options)
{
    GList *result = NULL;
    gint first, last, pos;
    gchar *new_string;

    g_assert (string);
    
    first = 0;
    last = strlen(string) - 1;
    
    /* strip leading and trailing separators */
    while ( (first<=last) && (string[first]==sep) )
        first++;
    while ( (first<=last) && (string[last]==sep) )
        last--;

    
    CAMEL_LOG_FULL_DEBUG ("string_split:: trim options: %d\n", trim_options);

    while (first<=last)  {
        pos = first;
        /* find next separator */
        while ((pos<=last) && (string[pos]!=sep)) pos++;
        if (first != pos) {
            new_string = g_strndup (string+first, pos-first);
            /* could do trimming in line to speed up this code */
            if (trim_chars) string_trim (new_string, trim_chars, trim_options);
            result = g_list_append (result, new_string);
        }   
        first = pos + 1;
    }

    return result;
}


void 
string_trim (gchar *string, const gchar *trim_chars, StringTrimOption options)
{
    gint first_ok;
    gint last_ok;
    guint length;

    CAMEL_LOG_FULL_DEBUG ("string-utils:: Entering string_trim::\n");
    CAMEL_LOG_FULL_DEBUG ("string_trim:: trim_chars:\"%s\"", trim_chars);
    CAMEL_LOG_FULL_DEBUG ("string_trim:: trim_options:%d\n", options);

    g_return_if_fail (string);
    length = strlen (string);
    g_return_if_fail (length > 0);
    
    first_ok = 0;
    last_ok = length - 1;

    if (options & STRING_TRIM_STRIP_LEADING)
        while  ( (first_ok <= last_ok) && (strchr (trim_chars, string[first_ok])!=NULL) )
            first_ok++;
    
    if (options & STRING_TRIM_STRIP_TRAILING)
        while  ( (first_ok <= last_ok) && (strchr (trim_chars, string[last_ok])!=NULL) )
            last_ok--;
    CAMEL_LOG_FULL_DEBUG ("string_trim::\n\t\"%s\":first ok:%d last_ok:%d\n",
           string, first_ok, last_ok);
    
    if (first_ok > 0)
        memmove (string, string+first_ok, last_ok - first_ok +2);
    
}







g message for the release.Ettore Perazzoli2000-12-142-2/+7 * Update the splash animation to fit with the new splash design.Ettore Perazzoli2000-12-142-1/+5 * Return TRUE as we have handled the event.Jeffrey Stedfast2000-12-132-0/+7 * Pass path+1 rather than path to get_type_for_storage, to match theDan Winship2000-12-132-1/+7 * Connect a button-press-event signal on the splash screen so users canJeffrey Stedfast2000-12-122-1/+18 * return NULL if no {folder,storage} is found. (get_control_for_uri): returnDan Winship2000-12-122-1/+13 * Complete the code to associate a URI and a folder type to the toplevelEttore Perazzoli2000-12-0916-106/+288 * update to GNOME_Evolution_Shell.oafinfoMichael Meeks2000-12-085-4/+10 * Start implementing a physical URI property for the toplevel nodes inEttore Perazzoli2000-12-0516-43/+187 * Handle a NIL return value from `oaf_activate_from_id' withoutEttore Perazzoli2000-12-052-1/+8 * return NULL if we can't create a view.Michael Meeks2000-12-052-1/+12 * New `createNewView' method in `Evolution::Shell'. Register the shellEttore Perazzoli2000-12-0512-81/+296 * removed #ifdef ENABLE_NLS/#endif on Miguel's request.Gediminas Paulauskas2000-11-301-2/+0 * Update - hopefully I assigned blame correctly :-)JP Rosevear2000-11-282-0/+7 * de-register a component's UI if it dies.Michael Meeks2000-11-282-0/+10 * Install Evolution IDL's into datadir/idl.Peter Williams2000-11-262-0/+10 * Plug leaks of the fullname and fulldefaultname.Federico Mena Quintero2000-11-255-33/+57 * Plug leak; mark the CORBA sequence so that it will be released.Federico Mena Quintero2000-11-252-0/+7 * add (e_shell_view_construct): hook up to system_exception on ui_container.Michael Meeks2000-11-142-0/+22 * Update the remaining "IDL:Evolution*" to "IDL:GNOME/Evolution*" to sync upMatt Bissiri2000-11-113-3/+10 * A very, long, very tedious IDL API rename and re-scoping;Michael Meeks2000-11-1138-466/+475 * Make the panes of the EPaned not shrinkable beyond their minimum size.Christopher James Lahey2000-11-092-4/+9 * Fix typo in a comment.Matt Bissiri2000-11-082-1/+5 * Pass full_name, not folder_name to callback.Dan Winship2000-11-082-1/+6 * Fixed a couple of warnings.Ettore Perazzoli2000-11-072-5/+11 * Make the shell pop-up a warning dialog per component when a componentEttore Perazzoli2000-11-074-5/+81 * Fixed a missing `CORBA_Object_duplicate()' problem. This should fixEttore Perazzoli2000-11-072-1/+6 * Added #include <config.h>Kjartan Maraas2000-11-072-0/+8 * Added a `--no-splash' option to the shell.Ettore Perazzoli2000-11-044-20/+60 * Fix the name of the signal passed to gtk_signal_new so that this actuallyDan Winship2000-11-042-1/+6 * The big api rename ...Michael Meeks2000-11-025-13/+13 * Make this take "highlighted" as well.Dan Winship2000-11-026-4/+20 * Moving the executive summarys now :)Iain Holmes2000-11-025-0/+100 * Add "highligted" field to Folder. Add update_folder method toDan Winship2000-11-0218-61/+373 * modified or added a bunch of .cvsignore to ignore generated files, whichGediminas Paulauskas2000-11-011-0/+2 * No longer include <db.h>52000-10-262-1/+6 * AM_GNOME_GETTEXT doesn't use $(datadir)/locale as the locale dir. (ItDan Winship2000-10-242-1/+5 * update to new UI handlerMichael Meeks2000-10-217-20/+28 * If there is no view save the default uri instead. (socket_destroy_cb):Iain Holmes2000-10-202-1/+10 * update for new UI handler.Michael Meeks2000-10-193-6/+11 * If the widget is not realized don't do anything, to prevent BadGC's atIain Holmes2000-10-193-2/+40 * Save the settings before the view is destroyed. (e_shell_quit): Don't saveIain Holmes2000-10-184-31/+57 * Add a typecast.Dan Winship2000-10-177-6/+25 * Check if there are any files in default_user that are not in ~/evolutionIain Holmes2000-10-165-3/+162 * Use an EScrollFrame instead of a GtkScrolledWindow for the folderEttore Perazzoli2000-10-152-41/+39 * if we are in LDAP mode then merge in the extra few items, otherwise justMichael Meeks2000-10-151-1/+1 * 31337 splash screen for the shell's startup sequence.Ettore Perazzoli2000-10-155-5/+549 * *e-shell-folder-creation-dialog.glade: Added focus to the folder-name textAnna Marie Dirks2000-10-143-0/+6 * Fixed the spec on this.Christopher James Lahey2000-10-112-2/+6 * Changed this to use the built in cells.Christopher James Lahey2000-10-112-17/+7 * Adapted this for the new ETable system.Christopher James Lahey2000-10-112-14/+16 * Change paths in such a way as to require HEAD bonobo.Michael Meeks2000-10-092-2/+15 * initialize priv->sockets to NULL, fixes startup crash on non-ia32Matt Wilson2000-10-082-0/+6 * Backported (from EVOLUTION_0_5_1) the code that allowed the shell toEttore Perazzoli2000-10-072-3/+109 * call _set_compare_function after inserting the storage.Chris Toshok2000-10-072-0/+6 * add a freeze / thaw pair to reduce flicker on switching controls.Michael Meeks2000-10-063-11/+15 * #include <gal/widgets/e-gui-utils.h>Chris Toshok2000-10-063-3/+8 * add #include for libgnomeui/gnome-messagebox.hChris Toshok2000-10-062-0/+6 * Disable summary stuff, it appears to be badly broken.Michael Meeks2000-10-055-75/+83 * ui/evolution-addressbook-ldap.xml, ui/evolution-addressbook.xml,Matt Bissiri2000-10-042-3/+15 * remove evil usize set.Michael Meeks2000-10-042-1/+4 * Fixed a bug that caused the "Create new shortcut group" dialog not toEttore Perazzoli2000-10-032-0/+7 * if we're not displaying folders, the current folder is NULL. (class_init):Chris Toshok2000-10-033-3/+16 * add storage_selected behavior - loop over the listeners callingChris Toshok2000-10-037-6/+96 * `EvolutionStorageSetViewListener', wrapper for the CORBAEttore Perazzoli2000-10-034-0/+353 * fix typo. (impl_StorageSetView_remove_listener): same.Chris Toshok2000-10-035-29/+143 * pass storage_set_view_interface as second argument toChris Toshok2000-10-032-1/+10 * kill.Michael Meeks2000-10-033-66/+77 * set the new node's compare function. (insert_folders): same.Chris Toshok2000-10-032-2/+11 * track e-tree sort api change. (treepath_compare): same. (new_folder_cb):Chris Toshok2000-10-032-10/+13 * pass NULL for the open/closed pixbuf of the tree renderer. we'll let itChris Toshok2000-10-032-21/+21 * Added the ability for the shell to export the storage set view as aEttore Perazzoli2000-10-0210-5/+583 * Add a `::remove_listener' method to Evolution::Storage.Ettore Perazzoli2000-10-023-7/+101 * Get the title bar for the folder view to use TigerT's pin icon for theEttore Perazzoli2000-09-292-10/+26 * Minor stylistical fixup.Ettore Perazzoli2000-09-291-2/+4 * Don't print "Folder registered successfully" if it didn't. (Duh. :)Dan Winship2000-09-292-3/+7 * If the startup folder cannot be open, default to the local Inbox.Ettore Perazzoli2000-09-282-5/+12 * Fix a bunch of EShortcutView problems. It's still buggy, but at leastEttore Perazzoli2000-09-274-19/+147 * Update the shortcut bar in the shell view to match the changes in theEttore Perazzoli2000-09-267-158/+431 * Fix a refcounting problem with the local storage. ("Somebody" added aEttore Perazzoli2000-09-252-2/+4 * Updates for the Bonobo changes from Michael who is having someEttore Perazzoli2000-09-233-19/+14 * Dear native speakers,Federico Mena Quintero2000-09-222-1/+5 * s/Bonobo_UIHandler/Bonobo_UIContainer/Michael Meeks2000-09-218-7/+35 * Added check for gnome-app-lib. Removed directories that have been moved toChristopher James Lahey2000-09-1829-42/+59 * Everywhere add a -DEVOLUTION_DATADIR=${datadir} in the Makefile.amMichael Meeks2000-09-172-1/+6 * #include <bonobo-win.h>, not <bonobo-app.h>, which doesn't existEttore Perazzoli2000-09-162-1/+5 * foreach_data should be set to the caller-supplied data, not the tree itemDan Winship2000-09-152-4/+9 * Fixed bug #536 Popup folder tree button doesn't expandIain Holmes2000-09-152-4/+6 * add bonobo_ui_handler_unset_container to stop menus screwing up.Michael Meeks2000-09-142-2/+6 * Move a couple of helpers into Bonobo before more people start the re-buildMichael Meeks2000-09-142-18/+4 * Added $(GNOME_PRINT_LIBS) to evolution_LDADD.Christopher James Lahey2000-09-142-0/+5 * Get the status bar playing ball.Michael Meeks2000-09-142-31/+50 * re-order to suit and add freeze / thaw, update paths to toggles, removeMichael Meeks2000-09-142-16/+23 * The Commit from hell that breaks all UI related stuff;Michael Meeks2000-09-148-288/+213 * Make the pop-up folder bar pop down after a folder is selected.Ettore Perazzoli2000-09-132-5/+24 * Thou shalt add a space after `-I' when invoking `orbit-idl'.Ettore Perazzoli2000-09-132-1/+6 * Little UTF-8 fixLauris Kaplinski2000-09-132-2/+10 * Remove ui.xml stuff which was breaking distcheck.Ettore Perazzoli2000-09-132-4/+5 * Tidy some xml.Michael Meeks2000-09-131-105/+0 * Initialize libunicodeDan Winship2000-09-122-1/+6 * Fixed some warnings.Christopher James Lahey2000-09-122-2/+6 * Fix some annoying warnings in the folder selection dialog.Ettore Perazzoli2000-09-122-2/+12 * Remove debugging message.Ettore Perazzoli2000-09-122-2/+4 * Make `EvolutionStorage' and `ELocalstorage' actually update the CORBAEttore Perazzoli2000-09-127-14/+103 * Grmpf.Ettore Perazzoli2000-09-111-1/+1 * Unset the `GTK_FLOATING' flag when constructing anEttore Perazzoli2000-09-112-0/+8 * Fully support setting the display name in the tree. It seems to work.Ettore Perazzoli2000-09-115-81/+155