1 /* GSequencer - Advanced GTK Sequencer
2  * Copyright (C) 2005-2021 Joël Krähemann
3  *
4  * This file is part of GSequencer.
5  *
6  * GSequencer is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GSequencer is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with GSequencer.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <ags/lib/ags_string_util.h>
21 
22 #include <stdlib.h>
23 #include <string.h>
24 #include <strings.h>
25 
26 gpointer ags_string_util_copy(gpointer ptr);
27 void ags_string_util_free(gpointer ptr);
28 
29 /**
30  * SECTION:ags_string_util
31  * @short_description: string util
32  * @title: AgsStringUtil
33  * @section_id:
34  * @include: ags/lib/ags_string_util.h
35  *
36  * Common string utility functions.
37  */
38 
39 GType
ags_string_util_get_type(void)40 ags_string_util_get_type(void)
41 {
42   static volatile gsize g_define_type_id__volatile = 0;
43 
44   if(g_once_init_enter (&g_define_type_id__volatile)){
45     GType ags_type_string_util = 0;
46 
47     ags_type_string_util =
48       g_boxed_type_register_static("AgsStringUtil",
49 				   (GBoxedCopyFunc) ags_string_util_copy,
50 				   (GBoxedFreeFunc) ags_string_util_free);
51 
52     g_once_init_leave(&g_define_type_id__volatile, ags_type_string_util);
53   }
54 
55   return g_define_type_id__volatile;
56 }
57 
58 gpointer
ags_string_util_copy(gpointer ptr)59 ags_string_util_copy(gpointer ptr)
60 {
61   gpointer retval;
62 
63   retval = g_memdup(ptr, sizeof(AgsStringUtil));
64 
65   return(retval);
66 }
67 
68 void
ags_string_util_free(gpointer ptr)69 ags_string_util_free(gpointer ptr)
70 {
71   g_free(ptr);
72 }
73 
74 /**
75  * ags_string_util_escape_single_quote:
76  * @str: the string to escape
77  *
78  * Escape all occurence of single quotes.
79  *
80  * Returns: (transfer full): the newly allocated string
81  *
82  * Since: 3.0.0
83  */
84 gchar*
ags_string_util_escape_single_quote(gchar * str)85 ags_string_util_escape_single_quote(gchar *str)
86 {
87   gchar *retval;
88   gchar *iter, *prev;
89   guint count;
90   guint n_chars;
91   guint offset;
92 
93   iter = str;
94   count = 0;
95 
96   while((iter = strchr(iter, '\'')) != NULL){
97     count++;
98     iter++;
99   }
100 
101   if(count > 0){
102     n_chars = strlen(str);
103 
104     retval = (gchar *) malloc((n_chars + (5 * count) + 1) * sizeof(gchar));
105     retval[n_chars + (5 * count)] = '\0';
106 
107     iter = str;
108     prev = str;
109     offset = 0;
110 
111     while((iter = strchr(iter, '\'')) != NULL){
112       memcpy(&(retval[offset]), prev, (iter - prev) * sizeof(char));
113       retval[offset + (iter - prev)] = '&';
114       retval[offset + (iter - prev + 1)] = 'a';
115       retval[offset + (iter - prev + 2)] = 'p';
116       retval[offset + (iter - prev + 3)] = 'o';
117       retval[offset + (iter - prev + 4)] = 's';
118       retval[offset + (iter - prev + 5)] = ';';
119 
120       offset += (iter - prev + 6);
121       iter++;
122       prev = iter;
123     }
124 
125     memcpy(&(retval[offset]), prev, (strchr(str, '\0') - prev) * sizeof(char));
126   }else{
127     retval = g_strdup(str);
128   }
129 
130   return(retval);
131 }
132 
133 /**
134  * ags_strv_length:
135  * @str_array: (element-type utf8) (array zero-terminated=1) (transfer none): the string vector
136  *
137  * Count the number of non-%NULL entries in the array.
138  *
139  * Returns: the length of the vector
140  *
141  * Since: 3.0.0
142  */
143 guint
ags_strv_length(gchar ** str_array)144 ags_strv_length(gchar **str_array)
145 {
146   guint i;
147 
148   if(str_array == NULL){
149     return(0);
150   }
151 
152   for(i = 0; *str_array != NULL; i++, str_array++);
153 
154   return(i);
155 }
156 
157 /**
158  * ags_strv_contains:
159  * @str_array: (element-type utf8) (array zero-terminated=1) (transfer none): the string vector
160  * @str: the string to match
161  *
162  * Check occurence of @str within @str_array
163  *
164  * Returns: %TRUE if found, else %FALSE
165  *
166  * Since: 3.0.0
167  */
168 gboolean
ags_strv_contains(gchar ** str_array,gchar * str)169 ags_strv_contains(gchar **str_array,
170 		  gchar *str)
171 {
172   guint i;
173 
174   if(str_array == NULL){
175     return(FALSE);
176   }
177 
178   for(i = 0; str_array[0] != NULL; i++, str_array++){
179     if(str_array[0] == str ||
180        !g_strcmp0(str_array[0],
181 		  str)){
182       return(TRUE);
183     }
184   }
185 
186   return(FALSE);
187 }
188 
189 /**
190  * ags_strv_index:
191  * @str_array: (element-type utf8) (array zero-terminated=1) (transfer none): the string vector
192  * @str: the string to match
193  *
194  * Check by comparing @str against @str_array items.
195  *
196  * Returns: the first matching position or -1, if not found
197  *
198  * Since: 3.0.0
199  */
200 gint
ags_strv_index(gchar ** str_array,gchar * str)201 ags_strv_index(gchar **str_array,
202 	       gchar *str)
203 {
204   gint i;
205 
206   if(str_array == NULL){
207     return(-1);
208   }
209 
210   for(i = 0; str_array[0] != NULL; i++, str_array++){
211     if(!g_strcmp0(str_array[0], str)){
212       return(i);
213     }
214   }
215 
216   return(-1);
217 }
218 
219 /**
220  * ags_strv_equal:
221  * @strv1: the string vector
222  * @strv2: an other string vector
223  *
224  * Check @strv1 and @strv2 to be equal. The arrays don't have to be
225  * sorted.
226  *
227  * Returns: %TRUE on success, otherwise %FALSE
228  *
229  * Since: 3.2.1
230  */
231 gboolean
ags_strv_equal(gchar ** strv1,gchar ** strv2)232 ags_strv_equal(gchar **strv1,
233 	       gchar **strv2)
234 {
235   gchar **iter;
236 
237   gboolean success;
238 
239   if(strv1 == NULL &&
240      strv2 == NULL){
241     return(TRUE);
242   }
243 
244   if((strv1 == NULL &&
245       strv2 != NULL) ||
246      (strv1 != NULL &&
247       strv2 == NULL)){
248     return(FALSE);
249   }
250 
251   if(g_strv_length(strv1) != g_strv_length(strv2)){
252     return(FALSE);
253   }
254 
255   success = TRUE;
256 
257   for(iter = strv2; success && iter[0] != NULL; iter++){
258     if(!ags_strv_contains(strv1, iter[0])){
259       success = FALSE;
260     }
261   }
262 
263   return(success);
264 }
265