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