~vcs-imports-ii/gnubg/trunk

5697 by mdpetch
Add GLIB list and string to map functions + macros.
1
/*
2
 * glib-ext.c -- Map/GList extensions and utility functions for GLIB
3
 *
4
 * by Michael Petch <mpetch@gnubg.org>, 2014.
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of version 3 or later of the GNU General Public License as
8
 * published by the Free Software Foundation.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 *
5976 by mdpetch
Fix missing include
19
 * $Id: glib-ext.c,v 1.12 2015/07/31 23:57:55 mdpetch Exp $
5697 by mdpetch
Add GLIB list and string to map functions + macros.
20
 */
21
22
5976 by mdpetch
Fix missing include
23
#include <errno.h>
5697 by mdpetch
Add GLIB list and string to map functions + macros.
24
#include <stdio.h>
25
#include <stdlib.h>
26
#include <string.h>
27
#include "glib-ext.h"
28
5975 by mdpetch
Fix "Invalid argument" problem with g_fopen on Win32.
29
/*  Based on glib's g_fopen to work around issues with WIN32 
30
 *  versions of g_fopen 
31
 */
32
33
FILE *
34
gnubg_g_fopen(const gchar * filename, const gchar * mode)
35
{
36
#if defined(WIN32)
37
    wchar_t *wfilename = g_utf8_to_utf16(filename, -1, NULL, NULL, NULL);
38
    wchar_t *wmode;
39
    FILE *retval;
40
    int save_errno;
41
42
    if (wfilename == NULL) {
43
        errno = EINVAL;
44
        return NULL;
45
    }
46
47
    wmode = g_utf8_to_utf16(mode, -1, NULL, NULL, NULL);
48
49
    if (wmode == NULL) {
50
        g_free(wfilename);
51
        errno = EINVAL;
52
        return NULL;
53
    }
54
55
    retval = _wfopen(wfilename, wmode);
56
    save_errno = errno;
57
58
    g_free(wfilename);
59
    g_free(wmode);
60
61
    errno = save_errno;
62
    return retval;
63
#else
64
    return fopen(filename, mode);
65
#endif
66
}
5731 by mdpetch
Fix glib-ext..* so that it compiles with glib < 2.14.
67
68
#if ! GLIB_CHECK_VERSION(2,14,0)
69
70
/* This code has been backported from the latest GLib
71
 *
72
 * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
73
 *
74
 * gthread.c: MT safety related functions
75
 * Copyright 1998 Sebastian Wilhelmi; University of Karlsruhe
76
 *                Owen Taylor
77
 */
78
79
80
static GMutex *g_once_mutex = NULL;
81
static GCond *g_once_cond = NULL;
82
static GSList *g_once_init_list = NULL;
83
84
gboolean
85
g_once_init_enter_impl(volatile gsize * value_location)
86
{
87
    gboolean need_init = FALSE;
88
    /* mutex and cond creation works without g_threads_got_initialized */
89
90
    g_mutex_lock(g_once_mutex);
91
    if (g_atomic_pointer_get((void **) value_location) == NULL) {
92
        if (!g_slist_find(g_once_init_list, (void *) value_location)) {
93
            need_init = TRUE;
94
            g_once_init_list = g_slist_prepend(g_once_init_list, (void *) value_location);
95
        } else
96
            do
97
                g_cond_wait(g_once_cond, g_once_mutex);
98
            while (g_slist_find(g_once_init_list, (void *) value_location));
99
    }
100
    g_mutex_unlock(g_once_mutex);
101
    return need_init;
102
}
103
104
void
105
g_once_init_leave(volatile gsize * value_location, gsize initialization_value)
106
{
107
    g_return_if_fail(g_atomic_pointer_get((void **) value_location) == NULL);
108
    g_return_if_fail(initialization_value != 0);
109
    g_return_if_fail(g_once_init_list != NULL);
110
111
    g_atomic_pointer_set((void **) value_location, (void *) initialization_value);
112
    g_mutex_lock(g_once_mutex);
113
    g_once_init_list = g_slist_remove(g_once_init_list, (void *) value_location);
114
    g_cond_broadcast(g_once_cond);
115
    g_mutex_unlock(g_once_mutex);
116
}
5975 by mdpetch
Fix "Invalid argument" problem with g_fopen on Win32.
117
118
gboolean
5767 by mdpetch
Modify code to properly compile on systems with GLIB < 2.14. Make sure glib
119
g_once_init_enter(volatile gsize * value_location)
120
{
121
    if G_LIKELY
5975 by mdpetch
Fix "Invalid argument" problem with g_fopen on Win32.
122
        (g_atomic_pointer_get((void *volatile *) value_location) != NULL)
5767 by mdpetch
Modify code to properly compile on systems with GLIB < 2.14. Make sure glib
123
            return FALSE;
124
    else
125
        return g_once_init_enter_impl(value_location);
126
}
5731 by mdpetch
Fix glib-ext..* so that it compiles with glib < 2.14.
127
#endif
128
5975 by mdpetch
Fix "Invalid argument" problem with g_fopen on Win32.
129
void
130
glib_ext_init(void)
5735 by mdpetch
Move glib-ext initialization to glib_ext_init()
131
{
5737 by mdpetch
Make sure the gthreads system is initialized properly for gobject usage
132
#if !GLIB_CHECK_VERSION (2,32,0)
133
    if (!g_thread_supported())
134
        g_thread_init(NULL);
135
    g_assert(g_thread_supported());
136
#endif
137
5735 by mdpetch
Move glib-ext initialization to glib_ext_init()
138
#if ! GLIB_CHECK_VERSION(2,14,0)
139
    if (!g_once_mutex)
140
        g_once_mutex = g_mutex_new();
141
    if (!g_once_cond)
142
        g_once_cond = g_cond_new();
143
#endif
144
    return;
145
}
146
5697 by mdpetch
Add GLIB list and string to map functions + macros.
147
GLIBEXT_DEFINE_BOXED_TYPE(GListBoxed, g_list_boxed, g_list_copy, g_list_gv_boxed_free)
5731 by mdpetch
Fix glib-ext..* so that it compiles with glib < 2.14.
148
    GLIBEXT_DEFINE_BOXED_TYPE(GMapBoxed, g_map_boxed, g_list_copy, g_list_gv_boxed_free)
149
    GLIBEXT_DEFINE_BOXED_TYPE(GMapEntryBoxed, g_mapentry_boxed, g_list_copy, g_list_gv_boxed_free)
5710 by mdpetch
Revise external interface version info. Move location of some GLIB functions
150
#if ! GLIB_CHECK_VERSION(2,28,0)
151
void
5731 by mdpetch
Fix glib-ext..* so that it compiles with glib < 2.14.
152
g_list_free_full(GList * list, GDestroyNotify free_func)
5710 by mdpetch
Revise external interface version info. Move location of some GLIB functions
153
{
154
    g_list_foreach(list, (GFunc) free_func, NULL);
155
    g_list_free(list);
156
}
157
#endif
5697 by mdpetch
Add GLIB list and string to map functions + macros.
158
159
void
160
g_value_unsetfree(GValue * gv)
161
{
162
    g_value_unset(gv);
163
    g_free(gv);
164
}
165
166
GMapEntry *
167
str2gv_map_has_key(GMap * map, GString * key)
168
{
5745 by plm
Fix compiler warning
169
    guint item;
5697 by mdpetch
Add GLIB list and string to map functions + macros.
170
171
    for (item = 0; item < g_list_length(map); item++) {
5707 by mdpetch
Fix bug that incorrectly compares map keys
172
        GString *cmpkey = g_value_get_gstring(g_list_nth_data(g_value_get_boxed(g_list_nth_data(map, item)), 0));
5697 by mdpetch
Add GLIB list and string to map functions + macros.
173
        if (g_string_equal(cmpkey, key))
174
            return g_list_nth(map, item);
175
    }
176
177
    return NULL;
178
}
179
180
GValue *
181
str2gv_map_get_key_value(GMap * map, gchar * key, GValue * defaultgv)
182
{
183
    GString *gstrkey = g_string_new(key);
184
    GMapEntry *entry = str2gv_map_has_key(map, gstrkey);
185
    GValue *gv;
186
187
    if (entry)
188
        gv = g_list_nth_data(g_value_get_boxed(entry->data), 1);
189
    else
190
        gv = defaultgv;
191
192
    g_string_free(gstrkey, TRUE);
193
194
    return gv;
195
}
196
197
void
198
g_list_gv_free_full(gpointer data)
199
{
200
    g_assert(G_IS_VALUE(data));
201
202
    if (G_IS_VALUE(data))
203
        g_value_unsetfree(data);
204
}
205
206
void
207
g_list_gv_boxed_free(GList * list)
208
{
209
    g_list_free_full(list, (GDestroyNotify) g_list_gv_free_full);
210
}
211
212
GList *
213
create_str2int_tuple(char *str, int value)
214
{
215
    GString *tmpstr = g_string_new(str);
216
    GVALUE_CREATE(G_TYPE_INT, int, value, gvint);
217
    GVALUE_CREATE(G_TYPE_GSTRING, boxed, tmpstr, gvstr);
218
    g_string_free(tmpstr, TRUE);
219
    return g_list_prepend(g_list_prepend(NULL, gvint), gvstr);
220
}
221
222
GList *
223
create_str2gvalue_tuple(char *str, GValue * gv)
224
{
225
    GString *tmpstr = g_string_new(str);
226
    GVALUE_CREATE(G_TYPE_GSTRING, boxed, tmpstr, gvstr);
227
    g_string_free(tmpstr, TRUE);
228
    return g_list_prepend(g_list_prepend(NULL, gv), gvstr);
229
}
230
231
GList *
232
create_str2double_tuple(char *str, double value)
233
{
234
    GString *tmpstr = g_string_new(str);
5746 by mdpetch
Fix float/double conversion issue identified by plm
235
    GVALUE_CREATE(G_TYPE_DOUBLE, double, value, gvdouble);
5697 by mdpetch
Add GLIB list and string to map functions + macros.
236
    GVALUE_CREATE(G_TYPE_GSTRING, boxed, tmpstr, gvstr);
237
    g_string_free(tmpstr, TRUE);
238
    return g_list_prepend(g_list_prepend(NULL, gvdouble), gvstr);
239
}
240
241
void
242
free_strmap_tuple(GList * tuple)
243
{
244
    g_string_free(g_list_nth_data(tuple, 0), TRUE);
245
    g_free(g_list_nth_data(tuple, 1));
246
    g_list_free(tuple);
247
}
248
249
void
5731 by mdpetch
Fix glib-ext..* so that it compiles with glib < 2.14.
250
g_value_list_tostring(GString * str, GList * list, int depth)
5697 by mdpetch
Add GLIB list and string to map functions + macros.
251
{
252
    GList *cur = list;
253
    while (cur != NULL) {
5713 by mdpetch
Print routines now output to strings rather than stdout
254
        g_value_tostring(str, cur->data, depth);
5697 by mdpetch
Add GLIB list and string to map functions + macros.
255
        if ((cur = g_list_next(cur)))
5713 by mdpetch
Print routines now output to strings rather than stdout
256
            g_string_append(str, ", ");
5697 by mdpetch
Add GLIB list and string to map functions + macros.
257
    }
258
}
259
260
void
5713 by mdpetch
Print routines now output to strings rather than stdout
261
g_value_tostring(GString * str, GValue * gv, int depth)
5697 by mdpetch
Add GLIB list and string to map functions + macros.
262
{
263
    if (!gv)
264
        return;
265
    g_assert(G_IS_VALUE(gv));
266
267
    if (G_VALUE_HOLDS_INT(gv)) {
5713 by mdpetch
Print routines now output to strings rather than stdout
268
        g_string_append_printf(str, "%d", g_value_get_int(gv));
5697 by mdpetch
Add GLIB list and string to map functions + macros.
269
    } else if (G_VALUE_HOLDS_DOUBLE(gv)) {
5713 by mdpetch
Print routines now output to strings rather than stdout
270
        g_string_append_printf(str, "%lf", g_value_get_double(gv));
5697 by mdpetch
Add GLIB list and string to map functions + macros.
271
    } else if (G_VALUE_HOLDS_GSTRING(gv)) {
5713 by mdpetch
Print routines now output to strings rather than stdout
272
        g_string_append_printf(str, "\"%s\"", g_value_get_gstring_gchar(gv));
5697 by mdpetch
Add GLIB list and string to map functions + macros.
273
    } else if (G_VALUE_HOLDS_BOXED_GLIST_GV(gv)) {
5713 by mdpetch
Print routines now output to strings rather than stdout
274
        g_string_append_c(str, '(');
275
        g_value_list_tostring(str, g_value_get_boxed(gv), depth + 1);
276
        g_string_append_c(str, ')');
5697 by mdpetch
Add GLIB list and string to map functions + macros.
277
    } else if (G_VALUE_HOLDS_BOXED_MAP_GV(gv)) {
5713 by mdpetch
Print routines now output to strings rather than stdout
278
        g_string_append_c(str, '[');
279
        g_value_list_tostring(str, g_value_get_boxed(gv), depth + 1);
280
        g_string_append_c(str, ']');
5697 by mdpetch
Add GLIB list and string to map functions + macros.
281
    } else if (G_VALUE_HOLDS_BOXED_MAPENTRY_GV(gv)) {
5713 by mdpetch
Print routines now output to strings rather than stdout
282
        g_value_tostring(str, g_list_nth_data(g_value_get_boxed(gv), 0), depth + 1);
283
        g_string_append(str, " : ");
284
        g_value_tostring(str, g_list_nth_data(g_value_get_boxed(gv), 1), depth + 1);
5697 by mdpetch
Add GLIB list and string to map functions + macros.
285
    }
286
}