1 /* 2 GLIB - Library of useful routines for C programming 3 4 Copyright (C) 2009-2024 5 Free Software Foundation, Inc. 6 7 Written by: 8 Slava Zanko <slavazanko@gmail.com>, 2009, 2013. 9 10 This file is part of the Midnight Commander. 11 12 The Midnight Commander is free software: you can redistribute it 13 and/or modify it under the terms of the GNU General Public License as 14 published by the Free Software Foundation, either version 3 of the License, 15 or (at your option) any later version. 16 17 The Midnight Commander is distributed in the hope that it will be useful, 18 but WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 GNU General Public License for more details. 21 22 You should have received a copy of the GNU General Public License 23 along with this program. If not, see <http://www.gnu.org/licenses/>. 24 */ 25 26 /** \file glibcompat.c 27 * \brief Source: compatibility with older versions of glib 28 * 29 * Following code was copied from glib to GNU Midnight Commander to 30 * provide compatibility with older versions of glib. 31 */ 32 33 #include <config.h> 34 #include <string.h> 35 36 #include "global.h" 37 #include "glibcompat.h" 38 39 /*** global variables ****************************************************************************/ 40 41 /*** file scope macro definitions ****************************************************************/ 42 43 /*** file scope type declarations ****************************************************************/ 44 45 /*** file scope variables ************************************************************************/ 46 47 /* --------------------------------------------------------------------------------------------- */ 48 /*** file scope functions ************************************************************************/ 49 /* --------------------------------------------------------------------------------------------- */ 50 51 /* --------------------------------------------------------------------------------------------- */ 52 /*** public functions ****************************************************************************/ 53 /* --------------------------------------------------------------------------------------------- */ 54 55 #if ! GLIB_CHECK_VERSION (2, 54, 0) 56 /** 57 * g_ptr_array_find_with_equal_func: (skip) 58 * @haystack: pointer array to be searched 59 * @needle: pointer to look for 60 * @equal_func: (nullable): the function to call for each element, which should 61 * return %TRUE when the desired element is found; or %NULL to use pointer 62 * equality 63 * @index_: (optional) (out): return location for the index of 64 * the element, if found 65 * 66 * Checks whether @needle exists in @haystack, using the given @equal_func. 67 * If the element is found, %TRUE is returned and the element^A^A^As index is 68 * returned in @index_ (if non-%NULL). Otherwise, %FALSE is returned and @index_ 69 * is undefined. If @needle exists multiple times in @haystack, the index of 70 * the first instance is returned. 71 * 72 * @equal_func is called with the element from the array as its first parameter, 73 * and @needle as its second parameter. If @equal_func is %NULL, pointer 74 * equality is used. 75 * 76 * Returns: %TRUE if @needle is one of the elements of @haystack 77 * Since: 2.54 78 */ 79 gboolean 80 g_ptr_array_find_with_equal_func (GPtrArray *haystack, gconstpointer needle, GEqualFunc equal_func, /* */ 81 guint *index_) 82 { 83 guint i; 84 85 g_return_val_if_fail (haystack != NULL, FALSE); 86 87 if (equal_func == NULL) 88 equal_func = g_direct_equal; 89 90 for (i = 0; i < haystack->len; i++) 91 if (equal_func (g_ptr_array_index (haystack, i), needle)) 92 { 93 if (index_ != NULL) 94 *index_ = i; 95 return TRUE; 96 } 97 98 return FALSE; 99 } 100 #endif /* ! GLIB_CHECK_VERSION (2, 54, 0) */ 101 102 /* --------------------------------------------------------------------------------------------- */ 103 104 #if ! GLIB_CHECK_VERSION (2, 63, 3) 105 /** 106 * g_clear_slist: (skip) 107 * @slist_ptr: (not nullable): a #GSList return location 108 * @destroy: (nullable): the function to pass to g_slist_free_full() or NULL to not free elements 109 * 110 * Clears a pointer to a #GSList, freeing it and, optionally, freeing its elements using @destroy. 111 * 112 * @slist_ptr must be a valid pointer. If @slist_ptr points to a null #GSList, this does nothing. 113 * 114 * Since: 2.64 115 */ 116 void 117 g_clear_slist (GSList **slist_ptr, GDestroyNotify destroy) /* */ 118 { 119 GSList *slist; 120 121 slist = *slist_ptr; 122 123 if (slist != NULL) 124 { 125 *slist_ptr = NULL; 126 127 if (destroy != NULL) 128 g_slist_free_full (slist, destroy); 129 else 130 g_slist_free (slist); 131 } 132 } 133 134 /* --------------------------------------------------------------------------------------------- */ 135 136 /** 137 * g_clear_list: 138 * @list_ptr: (not nullable): a #GList return location 139 * @destroy: (nullable): the function to pass to g_list_free_full() or NULL to not free elements 140 * 141 * Clears a pointer to a #GList, freeing it and, optionally, freeing its elements using @destroy. 142 * 143 * @list_ptr must be a valid pointer. If @list_ptr points to a null #GList, this does nothing. 144 * 145 * Since: 2.64 146 */ 147 void 148 g_clear_list (GList **list_ptr, GDestroyNotify destroy) /* */ 149 { 150 GList *list; 151 152 list = *list_ptr; 153 154 if (list != NULL) 155 { 156 *list_ptr = NULL; 157 158 if (destroy != NULL) 159 g_list_free_full (list, destroy); 160 else 161 g_list_free (list); 162 } 163 } 164 165 #endif /* ! GLIB_CHECK_VERSION (2, 63, 3) */ 166 167 /* --------------------------------------------------------------------------------------------- */ 168 169 #if ! GLIB_CHECK_VERSION (2, 60, 0) 170 /** 171 * g_queue_clear_full: 172 * @queue: a pointer to a #GQueue 173 * @free_func: (nullable): the function to be called to free memory allocated 174 * 175 * Convenience method, which frees all the memory used by a #GQueue, 176 * and calls the provided @free_func on each item in the #GQueue. 177 * 178 * Since: 2.60 179 */ 180 void 181 g_queue_clear_full (GQueue *queue, GDestroyNotify free_func) /* */ 182 { 183 g_return_if_fail (queue != NULL); 184 185 if (free_func != NULL) 186 g_queue_foreach (queue, (GFunc) free_func, NULL); 187 188 g_queue_clear (queue); 189 } 190 #endif /* ! GLIB_CHECK_VERSION (2, 60, 0) */ 191 192 /* --------------------------------------------------------------------------------------------- */ 193 194 #if ! GLIB_CHECK_VERSION (2, 77, 0) 195 /** 196 * g_string_new_take: 197 * @init: (nullable): initial text used as the string. 198 * Ownership of the string is transferred to the #GString. 199 * Passing NULL creates an empty string. 200 * 201 * Creates a new #GString, initialized with the given string. 202 * 203 * After this call, @init belongs to the #GString and may no longer be 204 * modified by the caller. The memory of @data has to be dynamically 205 * allocated and will eventually be freed with g_free(). 206 * 207 * Returns: the new #GString 208 */ 209 GString * 210 g_string_new_take (char *init) /* */ 211 { 212 GString *string; 213 214 if (init == NULL) 215 return g_string_new (NULL); 216 217 string = g_slice_new (GString); 218 219 string->str = init; 220 string->len = strlen (string->str); 221 string->allocated_len = string->len + 1; 222 223 return string; 224 } 225 #endif /* ! GLIB_CHECK_VERSION (2, 77, 0) */ 226 227 /* --------------------------------------------------------------------------------------------- */ 228 229 /** 230 * mc_g_string_copy: 231 * @dest: (not nullable): the destination #GString. Its current contents are destroyed 232 * @src: (not nullable): the source #GString 233 * @return: @dest 234 * 235 * Copies the bytes from a #GString into a #GString, destroying any previous contents. 236 * It is rather like the standard strcpy() function, except that you do not have to worry about 237 * having enough space to copy the string. 238 * 239 * There is no such API in GLib2. 240 */ 241 GString * 242 mc_g_string_copy (GString *dest, const GString *src) /* */ 243 { 244 g_return_val_if_fail (src != NULL, NULL); 245 g_return_val_if_fail (dest != NULL, NULL); 246 247 g_string_set_size (dest, 0); 248 g_string_append_len (dest, src->str, src->len); 249 250 return dest; 251 } 252 253 /* --------------------------------------------------------------------------------------------- */ 254 255 /** 256 * mc_g_string_dup: 257 * @s: (nullable): the source #GString 258 * @return: @copy of @s 259 * 260 * Copies the bytes from one #GString to another. 261 * 262 * There is no such API in GLib2. 263 */ 264 GString * 265 mc_g_string_dup (const GString *s) /* */ 266 { 267 GString *ret = NULL; 268 269 if (s != NULL) 270 ret = g_string_new_len (s->str, s->len); 271 272 return ret; 273 } 274 275 /* --------------------------------------------------------------------------------------------- */ 276 277 /** 278 * mc_g_string_append_c_len: 279 * @s: (not nullable): the destination #GString. 280 * @c: the byte to append onto the end of @s 281 * @len: the number of bytes @c to append onto the end of @s 282 * @return: @s 283 * 284 * Adds @len bytes @c onto the end of @s. 285 * 286 * There is no such API in GLib2. 287 */ 288 GString * 289 mc_g_string_append_c_len (GString *s, gchar c, guint len) /* */ 290 { 291 g_return_val_if_fail (s != NULL, NULL); 292 293 if (len != 0) 294 { 295 guint s_len = s->len; 296 297 g_string_set_size (s, s->len + len); 298 memset (s->str + s_len, (unsigned char) c, len); 299 } 300 301 return s; 302 } 303 304 /* --------------------------------------------------------------------------------------------- */