~ubuntu-branches/ubuntu/quantal/gconf/quantal

« back to all changes in this revision

Viewing changes to backends/val-encode.c

  • Committer: Bazaar Package Importer
  • Author(s): Takuo KITAME
  • Date: 2002-03-17 01:51:39 UTC
  • Revision ID: james.westby@ubuntu.com-20020317015139-z4f8fdg1hoe049g0
Tags: upstream-1.0.9
ImportĀ upstreamĀ versionĀ 1.0.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * GConf BerkeleyDB back-end
 
3
 * 
 
4
 * Copyright (C) 2000 Sun Microsystems Inc Contributed to the GConf project.
 
5
 * 
 
6
 * This library is free software; you can redistribute it and/or modify it under
 
7
 * the terms of the GNU Library General Public License as published by the
 
8
 * Free Software Foundation; either version 2 of the License, or (at your
 
9
 * option) any later version.
 
10
 * 
 
11
 * This library is distributed in the hope that it will be useful, but WITHOUT
 
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
 
14
 * License for more details.
 
15
 * 
 
16
 * You should have received a copy of the GNU Library General Public License
 
17
 * along with this library; if not, write to the Free Software Foundation,
 
18
 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
19
 */
 
20
 
 
21
#include <string.h>
 
22
#include <stdlib.h>
 
23
#include <stdio.h>
 
24
 
 
25
#include <gconf/gconf.h>
 
26
 
 
27
/* required for gconf_value_new_from_string() */
 
28
#include <gconf/gconf-internals.h>
 
29
 
 
30
/* required for _gconf_slist_free_all */
 
31
#include "dir-utils.h"
 
32
 
 
33
/* GConf Value type character identifiers */
 
34
static const char bdb_string = 's';
 
35
static const char bdb_int = 'i';
 
36
static const char bdb_float = 'f';
 
37
static const char bdb_bool = 'b';
 
38
static const char bdb_schema = 'x';
 
39
static const char bdb_list = 'l';
 
40
static const char bdb_pair = 'p';
 
41
 
 
42
/* Map each character value type id to the corresponding GConfValueType
 
43
   and vice-versa */
 
44
static struct s_TypeMap
 
45
{
 
46
  char type;
 
47
  GConfValueType valuetype;
 
48
}
 
49
bdb_value_types[] =
 
50
{
 
51
  {
 
52
  's', GCONF_VALUE_STRING}
 
53
  ,
 
54
  {
 
55
  'i', GCONF_VALUE_INT}
 
56
  ,
 
57
  {
 
58
  'f', GCONF_VALUE_FLOAT}
 
59
  ,
 
60
  {
 
61
  'b', GCONF_VALUE_BOOL}
 
62
  ,
 
63
  {
 
64
  'x', GCONF_VALUE_SCHEMA}
 
65
  ,
 
66
  {
 
67
  'l', GCONF_VALUE_LIST}
 
68
  ,
 
69
  {
 
70
  'p', GCONF_VALUE_PAIR}
 
71
  ,
 
72
  {
 
73
  '\0', GCONF_VALUE_INVALID}
 
74
};
 
75
 
 
76
/* { Conversion functions using bdb_value_types to map between GConfValueType
 
77
 * and the corresponding character-based value type identifiers
 
78
 */
 
79
static GConfValueType
 
80
get_value_type (char type)
 
81
{
 
82
  int i = 0;
 
83
 
 
84
  while (bdb_value_types[i].type && (bdb_value_types[i].type != type))
 
85
    i++;
 
86
  return bdb_value_types[i].valuetype;
 
87
}
 
88
 
 
89
static char
 
90
get_type_for_value_type (GConfValueType valuetype)
 
91
{
 
92
  int i = 0;
 
93
 
 
94
  while (bdb_value_types[i].type
 
95
         && (bdb_value_types[i].valuetype != valuetype))
 
96
    i++;
 
97
  return bdb_value_types[i].type;
 
98
}
 
99
 
 
100
/* } */
 
101
 
 
102
static char *
 
103
append_string (char *buf, const char *string)
 
104
{
 
105
  if (string)
 
106
    {
 
107
      strcpy (buf, string);
 
108
      return buf + strlen (string) + 1;
 
109
    }
 
110
  *buf++ = '\0';
 
111
  return buf;
 
112
}
 
113
 
 
114
static char tbuf[259];          /* 256 + 3 bytes for "<type>:" and end zero byte */
 
115
 
 
116
void
 
117
_gconf_check_free (char *buf)
 
118
{
 
119
  if (buf && buf != tbuf)
 
120
    free (buf);
 
121
}
 
122
 
 
123
/* { Functions to size, serialize and de-serialize a GConfValue, which
 
124
 *   is stored in the database as an encoded string.
 
125
 */
 
126
 
 
127
/* bdb_size_value returns the encoded size of a value, which is 2 bytes
 
128
 * for leading type info, plus enough room for the value as a string
 
129
 * (excluding terminal NULL byte)
 
130
 */
 
131
static size_t
 
132
bdb_size_value (const GConfValue * val)
 
133
{
 
134
  size_t len = 0;
 
135
  char *buf = tbuf;
 
136
  if (!val)
 
137
    return 3;                   /* empty values are encoded as a type and a
 
138
                                 * null string */
 
139
  switch (val->type)
 
140
    {
 
141
    case GCONF_VALUE_STRING:
 
142
      {
 
143
        char *t = gconf_value_get_string (val) == 0 ? "" : val->d.string_data;
 
144
        len = strlen (t) + 2;
 
145
      }
 
146
      break;
 
147
    case GCONF_VALUE_INT:
 
148
      sprintf (buf, "%d", val->d.int_data);
 
149
      len = strlen (buf) + 2;
 
150
      break;
 
151
    case GCONF_VALUE_FLOAT:
 
152
      sprintf (buf, "%f", (double) gconf_value_get_float (val));
 
153
      len = strlen (buf) + 2;
 
154
      break;
 
155
    case GCONF_VALUE_BOOL:
 
156
      len = 3;
 
157
      break;
 
158
    case GCONF_VALUE_SCHEMA:
 
159
      {
 
160
        GConfSchema *schema = gconf_value_get_schema (val);
 
161
        len = 3;
 
162
        if (schema == NULL)
 
163
          {
 
164
            return len;
 
165
          }
 
166
        if (schema->locale)
 
167
          len += strlen (schema->locale);       /* Schema locale */
 
168
        len++;
 
169
        if (schema->owner)
 
170
          len += strlen (schema->owner);        /* Name of creating application */
 
171
        len++;
 
172
        if (schema->short_desc)
 
173
          len += strlen (schema->short_desc);   /* 40 char or less
 
174
                                                 * description, no newlines */
 
175
        len++;
 
176
        if (schema->long_desc)
 
177
          len += strlen (schema->long_desc);    /* could be a paragraph or so */
 
178
        len++;
 
179
        len += bdb_size_value (schema->default_value);  /* includes type
 
180
                                                         * information */
 
181
        if (!schema->default_value)
 
182
          {
 
183
            if (schema->type == GCONF_VALUE_LIST)
 
184
              len++;            /* even an empty list will include the type
 
185
                                 * character */
 
186
          }
 
187
      }
 
188
      break;
 
189
    case GCONF_VALUE_LIST:
 
190
      {
 
191
        GSList *list;
 
192
        len = 4;
 
193
        list = gconf_value_get_list (val);
 
194
        while (list != NULL)
 
195
          {
 
196
            len += bdb_size_value ((GConfValue *) list->data) + 1;
 
197
            list = g_slist_next (list);
 
198
          }
 
199
        return len;
 
200
      }
 
201
    case GCONF_VALUE_PAIR:
 
202
      len = 2 + bdb_size_value (gconf_value_get_car (val)) +
 
203
        bdb_size_value (gconf_value_get_cdr (val));
 
204
    case GCONF_VALUE_INVALID:
 
205
    default:
 
206
      len = 0;
 
207
      break;
 
208
    }
 
209
  return len;
 
210
}
 
211
 
 
212
/* All values are stored in the database as strings; bdb_serialize_value()
 
213
 * encodes a GConfValue as a string, bdb_restore_value() decodes a
 
214
 * serialized string back to a value
 
215
 */
 
216
char *
 
217
bdb_serialize_value (GConfValue * val, size_t * lenp)
 
218
{
 
219
  char *buf = tbuf;
 
220
  char *t;
 
221
  size_t len = 0;
 
222
  g_assert (val != 0);
 
223
  switch (val->type)
 
224
    {
 
225
    case GCONF_VALUE_STRING:
 
226
      t = gconf_value_get_string (val) == 0 ? "" : val->d.string_data;
 
227
      len = strlen (t) + 3;
 
228
      if (len > 256)
 
229
        {
 
230
          buf = (char *) malloc (len);
 
231
        }
 
232
      buf[0] = bdb_string;
 
233
      buf[1] = ':';
 
234
      strcpy (buf + 2, t);
 
235
      break;
 
236
    case GCONF_VALUE_INT:
 
237
      sprintf (buf, "%c:%d", bdb_int, gconf_value_get_int (val));
 
238
      len = strlen (buf) + 1;
 
239
      break;
 
240
    case GCONF_VALUE_FLOAT:
 
241
      sprintf (buf, "%c:%f", bdb_float, (double) gconf_value_get_float (val));
 
242
      len = strlen (buf) + 1;
 
243
      break;
 
244
    case GCONF_VALUE_BOOL:
 
245
      sprintf (buf, "%c:%d", bdb_bool, gconf_value_get_bool (val) ? 1 : 0);
 
246
      len = strlen (buf) + 1;
 
247
      break;
 
248
    case GCONF_VALUE_SCHEMA:
 
249
      {
 
250
        GConfSchema *schema = gconf_value_get_schema (val);
 
251
        size_t sublen;
 
252
        char *end;
 
253
        len = bdb_size_value (val);
 
254
        buf = (char *) malloc (len);
 
255
        buf[0] = bdb_schema;
 
256
        buf[1] = ':';
 
257
        if (schema == NULL)
 
258
          {
 
259
            buf[2] = '\0';
 
260
            return buf;
 
261
          }
 
262
        end = &buf[2];
 
263
        end = append_string (end, schema->locale);
 
264
        end = append_string (end, schema->owner);
 
265
        end = append_string (end, schema->short_desc);
 
266
        end = append_string (end, schema->long_desc);
 
267
        if (!schema->default_value)
 
268
          {
 
269
            *end++ = get_type_for_value_type (schema->type);
 
270
            *end++ = ':';
 
271
            *end++ = '\0';
 
272
          }
 
273
        else
 
274
          {
 
275
            t = bdb_serialize_value (schema->default_value, &sublen);
 
276
            memcpy (end, t, sublen);
 
277
            end += sublen;
 
278
          }
 
279
      }
 
280
      break;
 
281
    case GCONF_VALUE_LIST:
 
282
      {
 
283
        GSList *list;
 
284
        char *end;
 
285
        size_t sublen;
 
286
        len = bdb_size_value (val);
 
287
        buf = (char *) malloc (len);
 
288
        list = val->d.list_data.list;
 
289
        buf[0] = bdb_list;
 
290
        buf[1] = ':';
 
291
        buf[2] = get_type_for_value_type (gconf_value_get_list_type (val));
 
292
        end = buf + 3;
 
293
        while (list != NULL)
 
294
          {
 
295
            t = bdb_serialize_value ((GConfValue *) list->data, &sublen);
 
296
            memcpy (end, t, sublen);
 
297
            end += sublen;
 
298
            _gconf_check_free (t);
 
299
            list = g_slist_next (list);
 
300
          }
 
301
        *end = '\0';
 
302
      }
 
303
      break;
 
304
    case GCONF_VALUE_PAIR:
 
305
      {
 
306
        size_t sublen;
 
307
        len = bdb_size_value (val);
 
308
        buf = (char *) malloc (len);
 
309
        buf[0] = bdb_pair;
 
310
        buf[1] = ':';
 
311
        len = 2;
 
312
        t = bdb_serialize_value (gconf_value_get_car (val), &sublen);
 
313
        if (t)
 
314
          {
 
315
            memcpy (buf + len, t, sublen);
 
316
            len += sublen;
 
317
            _gconf_check_free (t);
 
318
          }
 
319
        else
 
320
          {
 
321
            buf[len++] = '\0';
 
322
          }
 
323
        t = bdb_serialize_value (gconf_value_get_cdr (val), &sublen);
 
324
        if (t)
 
325
          {
 
326
            memcpy (buf + len, t, sublen);
 
327
            len += sublen;
 
328
            _gconf_check_free (t);
 
329
          }
 
330
        else
 
331
          {
 
332
            buf[len++] = '\0';
 
333
          }
 
334
      }
 
335
      break;
 
336
    case GCONF_VALUE_INVALID:
 
337
    default:
 
338
      *lenp = 0;
 
339
      return NULL;
 
340
      break;
 
341
    }
 
342
  *lenp = len;
 
343
  return buf;
 
344
}
 
345
 
 
346
GConfValue *
 
347
bdb_restore_value (const char *srz)
 
348
{
 
349
  size_t len;
 
350
  char type;
 
351
  GError *err;
 
352
  g_assert (srz != 0);
 
353
  if ((strlen (srz) < 2) || (srz[1] != ':'))
 
354
    {
 
355
      return NULL;
 
356
    }
 
357
  type = *srz;
 
358
  srz += 2;
 
359
  switch (type)
 
360
    {
 
361
    case 's':
 
362
      return gconf_value_new_from_string (GCONF_VALUE_STRING, srz, &err);
 
363
      break;
 
364
    case 'i':
 
365
      return gconf_value_new_from_string (GCONF_VALUE_INT, srz, &err);
 
366
      break;
 
367
    case 'f':
 
368
      return gconf_value_new_from_string (GCONF_VALUE_FLOAT, srz, &err);
 
369
      break;
 
370
    case 'b':
 
371
      return gconf_value_new_from_string (GCONF_VALUE_BOOL, srz, &err);
 
372
      break;
 
373
    case 'x':
 
374
      {
 
375
        GConfValue *schema_val = gconf_value_new (GCONF_VALUE_SCHEMA);
 
376
        GConfValue *val;
 
377
        GConfSchema *schema = gconf_schema_new ();
 
378
        len = 4;                /* "x:" + (char)type + '\0' */
 
379
        if (*srz)
 
380
          gconf_schema_set_locale (schema, srz);
 
381
        srz += strlen (srz) + 1;
 
382
        if (*srz)
 
383
          gconf_schema_set_owner (schema, srz);
 
384
        srz += strlen (srz) + 1;
 
385
        if (*srz)
 
386
          gconf_schema_set_short_desc (schema, srz);
 
387
        srz += strlen (srz) + 1;
 
388
        if (*srz)
 
389
          gconf_schema_set_long_desc (schema, srz);
 
390
        srz += strlen (srz) + 1;
 
391
        val = bdb_restore_value (srz);
 
392
        gconf_schema_set_type (schema, get_value_type (*srz));
 
393
        gconf_schema_set_default_value_nocopy (schema, val);
 
394
        gconf_value_set_schema (schema_val, schema);
 
395
        return schema_val;
 
396
      }
 
397
      break;
 
398
    case 'l':
 
399
      {
 
400
        GSList *list = NULL;
 
401
        GConfValue *valuep;
 
402
        valuep = gconf_value_new (GCONF_VALUE_LIST);
 
403
        gconf_value_set_list_type (valuep, get_value_type (*srz++));
 
404
        while (*srz)
 
405
          {
 
406
            list = g_slist_append (list, bdb_restore_value (srz));
 
407
            while (*srz)
 
408
              srz++;
 
409
            srz++;
 
410
          }
 
411
        gconf_value_set_list (valuep, list);
 
412
        _gconf_slist_free_all (list);
 
413
        return valuep;
 
414
      }
 
415
      break;
 
416
    case 'p':
 
417
      {
 
418
        GConfValue *valuep = NULL;
 
419
        if (*srz)
 
420
          {
 
421
            valuep = gconf_value_new (GCONF_VALUE_PAIR);
 
422
            gconf_value_set_car (valuep, bdb_restore_value (srz));
 
423
            while (*srz)
 
424
              srz++;
 
425
            srz++;
 
426
            if (*srz)
 
427
              {
 
428
                gconf_value_set_cdr (valuep, bdb_restore_value (srz));
 
429
              }
 
430
            else
 
431
              {
 
432
                gconf_value_free (valuep);
 
433
                valuep = NULL;
 
434
              }
 
435
          }
 
436
        return valuep;
 
437
      }
 
438
    default:
 
439
      break;
 
440
    }
 
441
  return 0;
 
442
}
 
443
 
 
444
/* } */