~ubuntu-branches/ubuntu/lucid/cmake/lucid

« back to all changes in this revision

Viewing changes to Utilities/cmxmlrpc/xmlrpc_data.c

  • Committer: Bazaar Package Importer
  • Author(s): Artur Rona
  • Date: 2009-12-16 11:11:54 UTC
  • mfrom: (3.1.9 sid)
  • Revision ID: james.westby@ubuntu.com-20091216111154-6accvv6yq86h2hkc
Tags: 2.8.0-5ubuntu1
* Merge from debian testing (LP: #497349). Remaining changes:
  - Keep the Replaces: on cmake-data to cover the Kubuntu version from
    Jaunty in case someone decides to do an (unsupported) Jaunty->Lucid
    upgrade.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright information is at end of file */
2
 
 
3
 
#include "xmlrpc_config.h"
4
 
 
5
 
#include <stddef.h>
6
 
#include <stdlib.h>
7
 
#include <stdarg.h>
8
 
#include <string.h>
9
 
 
10
 
#include "bool.h"
11
 
#include "xmlrpc.h"
12
 
#include "xmlrpc_int.h"
13
 
 
14
 
/* Borrowed from Python 1.5.2.
15
 
** MPW pushes 'extended' for float and double types with varargs */
16
 
#ifdef MPW
17
 
typedef extended va_double;
18
 
#else
19
 
typedef double va_double;
20
 
#endif
21
 
 
22
 
/* Borrowed from Python 1.5.2.
23
 
** Python copies its va_list objects before using them in certain
24
 
** tricky fashions. We don't why Python does this, but since we're
25
 
** abusing our va_list objects in a similar fashion, we'll copy them
26
 
** too. */
27
 
#ifdef HAS_VA_COPY
28
 
#  define VA_LIST_COPY(dest,src) va_copy((dest), (src))
29
 
#else
30
 
#  if VA_LIST_IS_ARRAY
31
 
#    define VA_LIST_COPY(dest,src) memcpy((dest), (src), sizeof(va_list))
32
 
#  else
33
 
#    define VA_LIST_COPY(dest,src) ((dest) = (src))
34
 
#  endif
35
 
#endif
36
 
 
37
 
 
38
 
static void
39
 
destroyValue(xmlrpc_value * const valueP) {
40
 
 
41
 
    /* First, we need to destroy this value's contents, if any. */
42
 
    switch (valueP->_type) {
43
 
    case XMLRPC_TYPE_INT:
44
 
    case XMLRPC_TYPE_BOOL:
45
 
    case XMLRPC_TYPE_DOUBLE:
46
 
        break;
47
 
        
48
 
    case XMLRPC_TYPE_ARRAY:
49
 
        xmlrpc_destroyArrayContents(valueP);
50
 
        break;
51
 
        
52
 
    case XMLRPC_TYPE_STRING:
53
 
#ifdef HAVE_UNICODE_WCHAR
54
 
        if (valueP->_wcs_block)
55
 
            xmlrpc_mem_block_free(valueP->_wcs_block);
56
 
#endif /* HAVE_UNICODE_WCHAR */
57
 
        /* Fall through. */
58
 
 
59
 
    case XMLRPC_TYPE_DATETIME:
60
 
    case XMLRPC_TYPE_BASE64:
61
 
        xmlrpc_mem_block_clean(&valueP->_block);
62
 
        break;
63
 
 
64
 
    case XMLRPC_TYPE_STRUCT:
65
 
        xmlrpc_destroyStruct(valueP);
66
 
        break;
67
 
 
68
 
    case XMLRPC_TYPE_C_PTR:
69
 
        break;
70
 
 
71
 
    case XMLRPC_TYPE_DEAD:
72
 
        XMLRPC_ASSERT(FALSE); /* Can't happen, per entry conditions */
73
 
 
74
 
    default:
75
 
        XMLRPC_ASSERT(FALSE); /* There are no other possible values */
76
 
    }
77
 
 
78
 
    /* Next, we mark this value as invalid, to help catch refcount
79
 
        ** errors. */
80
 
    valueP->_type = XMLRPC_TYPE_DEAD;
81
 
 
82
 
    /* Finally, we destroy the value itself. */
83
 
    free(valueP);
84
 
}
85
 
 
86
 
 
87
 
 
88
 
/*=========================================================================
89
 
**  Reference Counting
90
 
**=========================================================================
91
 
**  Some simple reference-counting code. The xmlrpc_DECREF routine is in
92
 
**  charge of destroying values when their reference count equals zero.
93
 
*/
94
 
 
95
 
void 
96
 
xmlrpc_INCREF (xmlrpc_value * const valueP) {
97
 
 
98
 
    XMLRPC_ASSERT_VALUE_OK(valueP);
99
 
    XMLRPC_ASSERT(valueP->_refcount > 0);
100
 
 
101
 
    valueP->_refcount++;
102
 
}
103
 
 
104
 
 
105
 
 
106
 
void 
107
 
xmlrpc_DECREF (xmlrpc_value * const valueP) {
108
 
 
109
 
    XMLRPC_ASSERT_VALUE_OK(valueP);
110
 
    XMLRPC_ASSERT(valueP->_refcount > 0);
111
 
    XMLRPC_ASSERT(valueP->_type != XMLRPC_TYPE_DEAD);
112
 
 
113
 
    valueP->_refcount--;
114
 
 
115
 
    /* If we have no more refs, we need to deallocate this value. */
116
 
    if (valueP->_refcount == 0)
117
 
        destroyValue(valueP);
118
 
}
119
 
 
120
 
 
121
 
 
122
 
/*=========================================================================
123
 
    Utiltiies
124
 
=========================================================================*/
125
 
 
126
 
static const char *
127
 
typeName(xmlrpc_type const type) {
128
 
 
129
 
    switch(type) {
130
 
 
131
 
    case XMLRPC_TYPE_INT: return "INT";
132
 
    case XMLRPC_TYPE_BOOL: return "BOOL";
133
 
    case XMLRPC_TYPE_DOUBLE: return "DOUBLE";
134
 
    case XMLRPC_TYPE_DATETIME: return "DATETIME";
135
 
    case XMLRPC_TYPE_STRING: return "STRING";
136
 
    case XMLRPC_TYPE_BASE64: return "BASE64";
137
 
    case XMLRPC_TYPE_ARRAY: return "ARRAY";
138
 
    case XMLRPC_TYPE_STRUCT: return "STRUCT";
139
 
    case XMLRPC_TYPE_C_PTR: return "C_PTR";
140
 
    case XMLRPC_TYPE_DEAD: return "DEAD";
141
 
    default: return "???";
142
 
    }
143
 
}
144
 
 
145
 
 
146
 
 
147
 
static void
148
 
verifyNoNulls(xmlrpc_env * const envP,
149
 
              const char * const contents,
150
 
              unsigned int const len) {
151
 
/*----------------------------------------------------------------------------
152
 
   Verify that the character array 'contents', which is 'len' bytes long,
153
 
   does not contain any NUL characters, which means it can be made into
154
 
   a passable ASCIIZ string just by adding a terminating NUL.
155
 
 
156
 
   Fail if the array contains a NUL.
157
 
-----------------------------------------------------------------------------*/
158
 
    unsigned int i;
159
 
 
160
 
    for (i = 0; i < len && !envP->fault_occurred; i++)
161
 
        if (contents[i] == '\0')
162
 
            xmlrpc_env_set_fault_formatted(
163
 
                envP, XMLRPC_TYPE_ERROR, 
164
 
                "String must not contain NUL characters");
165
 
}
166
 
 
167
 
 
168
 
 
169
 
static void
170
 
verifyNoNullsW(xmlrpc_env *    const envP,
171
 
               const wchar_t * const contents,
172
 
               unsigned int    const len) {
173
 
/*----------------------------------------------------------------------------
174
 
   Same as verifyNoNulls(), but for wide characters.
175
 
-----------------------------------------------------------------------------*/
176
 
    unsigned int i;
177
 
 
178
 
    for (i = 0; i < len && !envP->fault_occurred; i++)
179
 
        if (contents[i] == '\0')
180
 
            xmlrpc_env_set_fault_formatted(
181
 
                envP, XMLRPC_TYPE_ERROR, 
182
 
                "String must not contain NUL characters");
183
 
}
184
 
 
185
 
 
186
 
 
187
 
static void
188
 
validateType(xmlrpc_env *         const envP,
189
 
             const xmlrpc_value * const valueP,
190
 
             xmlrpc_type          const expectedType) {
191
 
 
192
 
    if (valueP->_type != expectedType) {
193
 
        xmlrpc_env_set_fault_formatted(
194
 
            envP, XMLRPC_TYPE_ERROR, "Value of type %s supplied where "
195
 
            "type %s was expected.", 
196
 
            typeName(valueP->_type), typeName(expectedType));
197
 
    }
198
 
}
199
 
 
200
 
 
201
 
 
202
 
/*=========================================================================
203
 
    Extracting XML-RPC value
204
 
===========================================================================
205
 
  These routines extract XML-RPC values into ordinary C data types.
206
 
 
207
 
  For array and struct values, see the separates files xmlrpc_array.c
208
 
  and xmlrpc_struct.c.
209
 
=========================================================================*/
210
 
 
211
 
void 
212
 
xmlrpc_read_int(xmlrpc_env *         const envP,
213
 
                const xmlrpc_value * const valueP,
214
 
                xmlrpc_int32 *       const intValueP) {
215
 
 
216
 
    validateType(envP, valueP, XMLRPC_TYPE_INT);
217
 
    if (!envP->fault_occurred)
218
 
        *intValueP = valueP->_value.i;
219
 
}
220
 
 
221
 
 
222
 
 
223
 
void
224
 
xmlrpc_read_double(xmlrpc_env *         const envP,
225
 
                   const xmlrpc_value * const valueP,
226
 
                   xmlrpc_double *      const doubleValueP) {
227
 
    
228
 
    validateType(envP, valueP, XMLRPC_TYPE_DOUBLE);
229
 
    if (!envP->fault_occurred)
230
 
        *doubleValueP = valueP->_value.d;
231
 
 
232
 
}
233
 
 
234
 
 
235
 
 
236
 
void
237
 
xmlrpc_read_bool(xmlrpc_env *         const envP,
238
 
                 const xmlrpc_value * const valueP,
239
 
                 xmlrpc_bool *        const boolValueP) {
240
 
 
241
 
    validateType(envP, valueP, XMLRPC_TYPE_BOOL);
242
 
    if (!envP->fault_occurred)
243
 
        *boolValueP = valueP->_value.b;
244
 
}
245
 
 
246
 
 
247
 
 
248
 
void
249
 
xmlrpc_read_string(xmlrpc_env *         const envP,
250
 
                   const xmlrpc_value * const valueP,
251
 
                   const char **        const stringValueP) {
252
 
/*----------------------------------------------------------------------------
253
 
   Read the value of an XML-RPC string an ASCIIZ string.
254
 
 
255
 
   Fail if the string contains null characters (which means it wasn't
256
 
   really a string, but XML-RPC doesn't seem to understand what a string
257
 
   is, and such values are possible).
258
 
-----------------------------------------------------------------------------*/
259
 
    validateType(envP, valueP, XMLRPC_TYPE_STRING);
260
 
    if (!envP->fault_occurred) {
261
 
        size_t const size = 
262
 
            XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block);
263
 
        const char * const contents = 
264
 
            XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
265
 
 
266
 
        verifyNoNulls(envP, contents, (unsigned int)size);
267
 
        if (!envP->fault_occurred) {
268
 
            char * stringValue;
269
 
            
270
 
            stringValue = malloc(size+1);
271
 
            if (stringValue == NULL)
272
 
                xmlrpc_env_set_fault_formatted(
273
 
                    envP, XMLRPC_INTERNAL_ERROR, "Unable to allocate space "
274
 
                    "for %u-character string", size);
275
 
            else {
276
 
                memcpy(stringValue,
277
 
                       XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block), size);
278
 
                stringValue[size] = '\0';
279
 
 
280
 
                *stringValueP = stringValue;
281
 
            }
282
 
        }
283
 
    }
284
 
}
285
 
 
286
 
 
287
 
 
288
 
void
289
 
xmlrpc_read_string_lp(xmlrpc_env *         const envP,
290
 
                      const xmlrpc_value * const valueP,
291
 
                      unsigned int *       const lengthP,
292
 
                      const char **        const stringValueP) {
293
 
 
294
 
    validateType(envP, valueP, XMLRPC_TYPE_STRING);
295
 
    if (!envP->fault_occurred) {
296
 
        size_t const size = 
297
 
            XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block);
298
 
        const char * const contents = 
299
 
            XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
300
 
 
301
 
        char * stringValue;
302
 
 
303
 
        stringValue = malloc(size);
304
 
        if (stringValue == NULL)
305
 
            xmlrpc_env_set_fault_formatted(
306
 
                envP, XMLRPC_INTERNAL_ERROR, "Unable to allocate %u bytes "
307
 
                "for string.", size);
308
 
        else {
309
 
            memcpy(stringValue, contents, size);
310
 
            *stringValueP = stringValue;
311
 
            *lengthP = (unsigned int)size;
312
 
        }
313
 
    }
314
 
}
315
 
 
316
 
 
317
 
 
318
 
/*=========================================================================
319
 
**  Building XML-RPC values.
320
 
**=========================================================================
321
 
**  Build new XML-RPC values from a format string. This code is heavily
322
 
**  inspired by Py_BuildValue from Python 1.5.2. In particular, our
323
 
**  particular abuse of the va_list data type is copied from the equivalent
324
 
**  Python code in modsupport.c. Since Python is portable, our code should
325
 
**  (in theory) also be portable.
326
 
*/
327
 
 
328
 
 
329
 
xmlrpc_type xmlrpc_value_type (xmlrpc_value* value)
330
 
{
331
 
    XMLRPC_ASSERT_VALUE_OK(value);
332
 
    return value->_type;
333
 
}
334
 
 
335
 
 
336
 
 
337
 
static void
338
 
createXmlrpcValue(xmlrpc_env *    const envP,
339
 
                  xmlrpc_value ** const valPP) {
340
 
/*----------------------------------------------------------------------------
341
 
   Create a blank xmlrpc_value to be filled in.
342
 
 
343
 
   Set the reference count to 1.
344
 
-----------------------------------------------------------------------------*/
345
 
    xmlrpc_value * valP;
346
 
 
347
 
    valP = (xmlrpc_value*) malloc(sizeof(xmlrpc_value));
348
 
    if (!valP)
349
 
        xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR,
350
 
                             "Could not allocate memory for xmlrpc_value");
351
 
    else
352
 
        valP->_refcount = 1;
353
 
 
354
 
    *valPP = valP;
355
 
}
356
 
 
357
 
 
358
 
 
359
 
static void
360
 
mkInt(xmlrpc_env *    const envP, 
361
 
      xmlrpc_int32    const value,
362
 
      xmlrpc_value ** const valPP) {
363
 
 
364
 
    xmlrpc_value * valP;
365
 
 
366
 
    createXmlrpcValue(envP, &valP);
367
 
 
368
 
    if (!envP->fault_occurred) {
369
 
        valP->_type    = XMLRPC_TYPE_INT;
370
 
        valP->_value.i = value;
371
 
    }
372
 
    *valPP = valP;
373
 
}
374
 
 
375
 
 
376
 
 
377
 
static void
378
 
mkBool(xmlrpc_env *    const envP, 
379
 
       xmlrpc_bool     const value,
380
 
       xmlrpc_value ** const valPP) {
381
 
 
382
 
    xmlrpc_value * valP;
383
 
 
384
 
    createXmlrpcValue(envP, &valP);
385
 
 
386
 
    if (!envP->fault_occurred) {
387
 
        valP->_type = XMLRPC_TYPE_BOOL;
388
 
        valP->_value.b = value;
389
 
    }
390
 
    *valPP = valP;
391
 
}
392
 
 
393
 
 
394
 
 
395
 
static void
396
 
mkDouble(xmlrpc_env *    const envP, 
397
 
         double          const value,
398
 
         xmlrpc_value ** const valPP) {
399
 
 
400
 
    xmlrpc_value * valP;
401
 
 
402
 
    createXmlrpcValue(envP, &valP);
403
 
 
404
 
    if (!envP->fault_occurred) {
405
 
        valP->_type = XMLRPC_TYPE_DOUBLE;
406
 
        valP->_value.d = value;
407
 
    }
408
 
    *valPP = valP;
409
 
}
410
 
 
411
 
 
412
 
 
413
 
#ifdef HAVE_UNICODE_WCHAR
414
 
#define MAKE_WCS_BLOCK_NULL(val) ((val)->_wcs_block = NULL)
415
 
#else
416
 
#define MAKE_WCS_BLOCK_NULL(val) do {} while(0)
417
 
#endif
418
 
 
419
 
 
420
 
 
421
 
static void
422
 
mkString(xmlrpc_env *    const envP, 
423
 
         const char *    const value,
424
 
         unsigned int    const length,
425
 
         xmlrpc_value ** const valPP) {
426
 
 
427
 
    xmlrpc_value * valP;
428
 
 
429
 
    createXmlrpcValue(envP, &valP);
430
 
 
431
 
    if (!envP->fault_occurred) {
432
 
        valP->_type = XMLRPC_TYPE_STRING;
433
 
        MAKE_WCS_BLOCK_NULL(valP);
434
 
        XMLRPC_MEMBLOCK_INIT(char, envP, &valP->_block, length + 1);
435
 
        if (!envP->fault_occurred) {
436
 
            char * const contents =
437
 
                XMLRPC_MEMBLOCK_CONTENTS(char, &valP->_block);
438
 
            memcpy(contents, value, length);
439
 
            contents[length] = '\0';
440
 
        }
441
 
        if (envP->fault_occurred)
442
 
            free(valP);
443
 
    }
444
 
    *valPP = valP;
445
 
}
446
 
 
447
 
 
448
 
 
449
 
static void
450
 
getString(xmlrpc_env *    const envP,
451
 
          const char **   const formatP,
452
 
          va_list *       const args,
453
 
          xmlrpc_value ** const valPP) {
454
 
 
455
 
    const char * str;
456
 
    size_t len;
457
 
    
458
 
    str = (const char*) va_arg(*args, char*);
459
 
    if (**formatP == '#') {
460
 
        (*formatP)++;
461
 
        len = (size_t) va_arg(*args, size_t);
462
 
    } else
463
 
        len = strlen(str);
464
 
 
465
 
    mkString(envP, str, (unsigned int)len, valPP);
466
 
}
467
 
 
468
 
 
469
 
 
470
 
#ifdef HAVE_UNICODE_WCHAR
471
 
static void
472
 
mkWideString(xmlrpc_env *    const envP,
473
 
             wchar_t *       const wcs,
474
 
             size_t          const wcs_len,
475
 
             xmlrpc_value ** const valPP) {
476
 
 
477
 
    xmlrpc_value * valP;
478
 
    char *contents;
479
 
    wchar_t *wcs_contents;
480
 
    int block_is_inited;
481
 
    xmlrpc_mem_block *utf8_block;
482
 
    char *utf8_contents;
483
 
    size_t utf8_len;
484
 
 
485
 
    /* Error-handling preconditions. */
486
 
    utf8_block = NULL;
487
 
    block_is_inited = 0;
488
 
 
489
 
    /* Initialize our XML-RPC value. */
490
 
    valP = (xmlrpc_value*) malloc(sizeof(xmlrpc_value));
491
 
    XMLRPC_FAIL_IF_NULL(valP, envP, XMLRPC_INTERNAL_ERROR,
492
 
                        "Could not allocate memory for wide string");
493
 
    valP->_refcount = 1;
494
 
    valP->_type = XMLRPC_TYPE_STRING;
495
 
 
496
 
    /* More error-handling preconditions. */
497
 
    valP->_wcs_block = NULL;
498
 
 
499
 
    /* Build our wchar_t block first. */
500
 
    valP->_wcs_block =
501
 
        XMLRPC_TYPED_MEM_BLOCK_NEW(wchar_t, envP, wcs_len + 1);
502
 
    XMLRPC_FAIL_IF_FAULT(envP);
503
 
    wcs_contents =
504
 
        XMLRPC_TYPED_MEM_BLOCK_CONTENTS(wchar_t, valP->_wcs_block);
505
 
    memcpy(wcs_contents, wcs, wcs_len * sizeof(wchar_t));
506
 
    wcs_contents[wcs_len] = '\0';
507
 
    
508
 
    /* Convert the wcs block to UTF-8. */
509
 
    utf8_block = xmlrpc_wcs_to_utf8(envP, wcs_contents, wcs_len + 1);
510
 
    XMLRPC_FAIL_IF_FAULT(envP);
511
 
    utf8_contents = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, utf8_block);
512
 
    utf8_len = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, utf8_block);
513
 
 
514
 
    /* XXX - We need an extra memcopy to initialize _block. */
515
 
    XMLRPC_TYPED_MEM_BLOCK_INIT(char, envP, &valP->_block, utf8_len);
516
 
    XMLRPC_FAIL_IF_FAULT(envP);
517
 
    block_is_inited = 1;
518
 
    contents = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, &valP->_block);
519
 
    memcpy(contents, utf8_contents, utf8_len);
520
 
 
521
 
 cleanup:
522
 
    if (utf8_block)
523
 
        xmlrpc_mem_block_free(utf8_block);
524
 
    if (envP->fault_occurred) {
525
 
        if (valP) {
526
 
            if (valP->_wcs_block)
527
 
                xmlrpc_mem_block_free(valP->_wcs_block);
528
 
            if (block_is_inited)
529
 
                xmlrpc_mem_block_clean(&valP->_block);
530
 
            free(valP);
531
 
        }
532
 
    }
533
 
    *valPP = valP;
534
 
}
535
 
#endif /* HAVE_UNICODE_WCHAR */
536
 
 
537
 
 
538
 
 
539
 
static void
540
 
getWideString(xmlrpc_env *    const envP,
541
 
              const char **   const formatP,
542
 
              va_list *       const args,
543
 
              xmlrpc_value ** const valPP) {
544
 
#ifdef HAVE_UNICODE_WCHAR
545
 
 
546
 
    wchar_t *wcs;
547
 
    size_t len;
548
 
    
549
 
    wcs = (wchar_t*) va_arg(*args, wchar_t*);
550
 
    if (**formatP == '#') {
551
 
        (*formatP)++;
552
 
        len = (size_t) va_arg(*args, size_t);
553
 
    } else
554
 
        len = wcslen(wcs);
555
 
 
556
 
    mkWideString(envP, wcs, len, valPP);
557
 
 
558
 
#endif /* HAVE_UNICODE_WCHAR */
559
 
}
560
 
 
561
 
 
562
 
 
563
 
static void
564
 
mkDatetime(xmlrpc_env *    const envP, 
565
 
           const char *    const value,
566
 
           xmlrpc_value ** const valPP) {
567
 
 
568
 
    xmlrpc_value * valP;
569
 
 
570
 
    createXmlrpcValue(envP, &valP);
571
 
 
572
 
    if (!envP->fault_occurred) {
573
 
        valP->_type = XMLRPC_TYPE_DATETIME;
574
 
 
575
 
        XMLRPC_TYPED_MEM_BLOCK_INIT(
576
 
            char, envP, &valP->_block, strlen(value) + 1);
577
 
        if (!envP->fault_occurred) {
578
 
            char * const contents =
579
 
                XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, &valP->_block);
580
 
            strcpy(contents, value);
581
 
        }
582
 
        if (envP->fault_occurred)
583
 
            free(valP);
584
 
    }
585
 
    *valPP = valP;
586
 
}
587
 
 
588
 
 
589
 
 
590
 
static void
591
 
mkBase64(xmlrpc_env *          const envP, 
592
 
         const unsigned char * const value,
593
 
         size_t                const length,
594
 
         xmlrpc_value **       const valPP) {
595
 
 
596
 
    xmlrpc_value * valP;
597
 
 
598
 
    createXmlrpcValue(envP, &valP);
599
 
 
600
 
    if (!envP->fault_occurred) {
601
 
        valP->_type = XMLRPC_TYPE_BASE64;
602
 
 
603
 
        xmlrpc_mem_block_init(envP, &valP->_block, length);
604
 
        if (!envP->fault_occurred) {
605
 
            char * const contents = 
606
 
                xmlrpc_mem_block_contents(&valP->_block);
607
 
            memcpy(contents, value, length);
608
 
        }
609
 
        if (envP->fault_occurred)
610
 
            free(valP);
611
 
    }
612
 
    *valPP = valP;
613
 
}
614
 
 
615
 
 
616
 
 
617
 
static void
618
 
getBase64(xmlrpc_env *    const envP,
619
 
          va_list *       const args,
620
 
          xmlrpc_value ** const valPP) {
621
 
 
622
 
    unsigned char * value;
623
 
    size_t          length;
624
 
    
625
 
    value  = (unsigned char*) va_arg(*args, unsigned char*);
626
 
    length = (size_t)         va_arg(*args, size_t);
627
 
 
628
 
    mkBase64(envP, value, length, valPP);
629
 
}
630
 
 
631
 
 
632
 
 
633
 
static void
634
 
mkCPtr(xmlrpc_env *    const envP, 
635
 
       void *          const value,
636
 
       xmlrpc_value ** const valPP) {
637
 
 
638
 
    xmlrpc_value * valP;
639
 
 
640
 
    createXmlrpcValue(envP, &valP);
641
 
 
642
 
    if (!envP->fault_occurred) {
643
 
        valP->_type = XMLRPC_TYPE_C_PTR;
644
 
        valP->_value.c_ptr = value;
645
 
    }
646
 
    *valPP = valP;
647
 
}
648
 
 
649
 
 
650
 
 
651
 
static void
652
 
mkArrayFromVal(xmlrpc_env *    const envP, 
653
 
               xmlrpc_value *  const value,
654
 
               xmlrpc_value ** const valPP) {
655
 
 
656
 
    if (xmlrpc_value_type(value) != XMLRPC_TYPE_ARRAY)
657
 
        xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR,
658
 
                             "Array format ('A'), non-array xmlrpc_value");
659
 
    else
660
 
        xmlrpc_INCREF(value);
661
 
 
662
 
    *valPP = value;
663
 
}
664
 
 
665
 
 
666
 
 
667
 
static void
668
 
mkStructFromVal(xmlrpc_env *    const envP, 
669
 
                xmlrpc_value *  const value,
670
 
                xmlrpc_value ** const valPP) {
671
 
 
672
 
    if (xmlrpc_value_type(value) != XMLRPC_TYPE_STRUCT)
673
 
        xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR,
674
 
                             "Struct format ('S'), non-struct xmlrpc_value");
675
 
    else
676
 
        xmlrpc_INCREF(value);
677
 
 
678
 
    *valPP = value;
679
 
}
680
 
 
681
 
 
682
 
 
683
 
static void
684
 
getValue(xmlrpc_env *    const envP, 
685
 
         const char**    const format, 
686
 
         va_list *       const args,
687
 
         xmlrpc_value ** const valPP);
688
 
 
689
 
 
690
 
 
691
 
static void
692
 
createXmlrpcArray(xmlrpc_env *    const envP,
693
 
                  xmlrpc_value ** const arrayPP) {
694
 
/*----------------------------------------------------------------------------
695
 
   Create an empty array xmlrpc_value.
696
 
-----------------------------------------------------------------------------*/
697
 
    xmlrpc_value * arrayP;
698
 
 
699
 
    createXmlrpcValue(envP, &arrayP);
700
 
    if (!envP->fault_occurred) {
701
 
        arrayP->_type = XMLRPC_TYPE_ARRAY;
702
 
        XMLRPC_TYPED_MEM_BLOCK_INIT(xmlrpc_value*, envP, &arrayP->_block, 0);
703
 
        if (envP->fault_occurred)
704
 
            free(arrayP);
705
 
    }
706
 
    *arrayPP = arrayP;
707
 
}
708
 
 
709
 
 
710
 
 
711
 
static void
712
 
getArray(xmlrpc_env *    const envP,
713
 
         const char **   const formatP,
714
 
         char            const delimiter,
715
 
         va_list *       const args,
716
 
         xmlrpc_value ** const arrayPP) {
717
 
 
718
 
    xmlrpc_value * arrayP;
719
 
 
720
 
    createXmlrpcArray(envP, &arrayP);
721
 
 
722
 
    /* Add items to the array until we hit our delimiter. */
723
 
    
724
 
    while (**formatP != delimiter && !envP->fault_occurred) {
725
 
        
726
 
        xmlrpc_value * itemP;
727
 
        
728
 
        if (**formatP == '\0')
729
 
            xmlrpc_env_set_fault(
730
 
                envP, XMLRPC_INTERNAL_ERROR,
731
 
                "format string ended before closing ')'.");
732
 
        else {
733
 
            getValue(envP, formatP, args, &itemP);
734
 
            if (!envP->fault_occurred) {
735
 
                xmlrpc_array_append_item(envP, arrayP, itemP);
736
 
                xmlrpc_DECREF(itemP);
737
 
            }
738
 
        }
739
 
    }
740
 
    if (envP->fault_occurred)
741
 
        xmlrpc_DECREF(arrayP);
742
 
 
743
 
    *arrayPP = arrayP;
744
 
}
745
 
 
746
 
 
747
 
 
748
 
static void
749
 
getStructMember(xmlrpc_env *    const envP,
750
 
                const char **   const formatP,
751
 
                va_list *       const args,
752
 
                xmlrpc_value ** const keyPP,
753
 
                xmlrpc_value ** const valuePP) {
754
 
 
755
 
 
756
 
    /* Get the key */
757
 
    getValue(envP, formatP, args, keyPP);
758
 
    if (!envP->fault_occurred) {
759
 
        if (**formatP != ':')
760
 
            xmlrpc_env_set_fault(
761
 
                envP, XMLRPC_INTERNAL_ERROR,
762
 
                "format string does not have ':' after a "
763
 
                "structure member key.");
764
 
        else {
765
 
            /* Skip over colon that separates key from value */
766
 
            (*formatP)++;
767
 
            
768
 
            /* Get the value */
769
 
            getValue(envP, formatP, args, valuePP);
770
 
        }
771
 
        if (envP->fault_occurred)
772
 
            xmlrpc_DECREF(*keyPP);
773
 
    }
774
 
}
775
 
            
776
 
            
777
 
 
778
 
static void
779
 
getStruct(xmlrpc_env *    const envP,
780
 
          const char **   const formatP,
781
 
          char            const delimiter,
782
 
          va_list *       const args,
783
 
          xmlrpc_value ** const structPP) {
784
 
 
785
 
    xmlrpc_value * structP;
786
 
 
787
 
    structP = xmlrpc_struct_new(envP);
788
 
    if (!envP->fault_occurred) {
789
 
        while (**formatP != delimiter && !envP->fault_occurred) {
790
 
            xmlrpc_value * keyP;
791
 
            xmlrpc_value * valueP;
792
 
            
793
 
            getStructMember(envP, formatP, args, &keyP, &valueP);
794
 
            
795
 
            if (!envP->fault_occurred) {
796
 
                if (**formatP == ',')
797
 
                    (*formatP)++;  /* Skip over the comma */
798
 
                else if (**formatP == delimiter) {
799
 
                    /* End of the line */
800
 
                } else 
801
 
                    xmlrpc_env_set_fault(
802
 
                        envP, XMLRPC_INTERNAL_ERROR,
803
 
                        "format string does not have ',' or ')' after "
804
 
                        "a structure member");
805
 
                
806
 
                if (!envP->fault_occurred)
807
 
                    /* Add the new member to the struct. */
808
 
                    xmlrpc_struct_set_value_v(envP, structP, keyP, valueP);
809
 
                
810
 
                xmlrpc_DECREF(valueP);
811
 
                xmlrpc_DECREF(keyP);
812
 
            }
813
 
        }
814
 
        if (envP->fault_occurred)
815
 
            xmlrpc_DECREF(structP);
816
 
    }
817
 
    *structPP = structP;
818
 
}
819
 
 
820
 
 
821
 
 
822
 
static void
823
 
getValue(xmlrpc_env *    const envP, 
824
 
         const char**    const formatP,
825
 
         va_list *       const args,
826
 
         xmlrpc_value ** const valPP) {
827
 
/*----------------------------------------------------------------------------
828
 
   Get the next value from the list.  *formatP points to the specifier
829
 
   for the next value in the format string (i.e. to the type code
830
 
   character) and we move *formatP past the whole specifier for the
831
 
   next value.  We read the required arguments from 'args'.  We return
832
 
   the value as *valPP with a reference to it.
833
 
 
834
 
   For example, if *formatP points to the "i" in the string "sis",
835
 
   we read one argument from 'args' and return as *valP an integer whose
836
 
   value is the argument we read.  We advance *formatP to point to the
837
 
   last 's' and advance 'args' to point to the argument that belongs to
838
 
   that 's'.
839
 
-----------------------------------------------------------------------------*/
840
 
    char const formatChar = *(*formatP)++;
841
 
 
842
 
    switch (formatChar) {
843
 
    case 'i':
844
 
        mkInt(envP, (xmlrpc_int32) va_arg(*args, xmlrpc_int32), valPP);
845
 
        break;
846
 
 
847
 
    case 'b':
848
 
        mkBool(envP, (xmlrpc_bool) va_arg(*args, xmlrpc_bool), valPP);
849
 
        break;
850
 
 
851
 
    case 'd':
852
 
        mkDouble(envP, (double) va_arg(*args, va_double), valPP);
853
 
        break;
854
 
 
855
 
    case 's':
856
 
        getString(envP, formatP, args, valPP);
857
 
        break;
858
 
 
859
 
    case 'w':
860
 
        getWideString(envP, formatP, args, valPP);
861
 
        break;
862
 
 
863
 
    /* The code 't' is reserved for a better, time_t based
864
 
       implementation of dateTime conversion.  
865
 
    */
866
 
    case '8':
867
 
        mkDatetime(envP, (char*) va_arg(*args, char*), valPP);
868
 
        break;
869
 
 
870
 
    case '6':
871
 
        getBase64(envP, args, valPP);
872
 
        break;
873
 
 
874
 
    case 'p':
875
 
        /* We might someday want to use the code 'p!' to read in a
876
 
           cleanup function for this pointer. 
877
 
        */
878
 
        mkCPtr(envP, (void*) va_arg(*args, void*), valPP);
879
 
        break;      
880
 
 
881
 
    case 'A':
882
 
        mkArrayFromVal(envP, (xmlrpc_value*) va_arg(*args, xmlrpc_value*),
883
 
                       valPP);
884
 
        break;
885
 
 
886
 
    case 'S':
887
 
        mkStructFromVal(envP, (xmlrpc_value*) va_arg(*args, xmlrpc_value*),
888
 
                        valPP);
889
 
        break;
890
 
 
891
 
    case 'V':
892
 
        *valPP = (xmlrpc_value*) va_arg(*args, xmlrpc_value*);
893
 
        xmlrpc_INCREF(*valPP);
894
 
        break;
895
 
 
896
 
    case '(':
897
 
        getArray(envP, formatP, ')', args, valPP);
898
 
        if (!envP->fault_occurred) {
899
 
            XMLRPC_ASSERT(**formatP == ')');
900
 
            (*formatP)++;  /* Skip over closing parenthesis */
901
 
        }
902
 
        break;
903
 
 
904
 
    case '{': 
905
 
        getStruct(envP, formatP, '}', args, valPP);
906
 
        if (!envP->fault_occurred) {
907
 
            XMLRPC_ASSERT(**formatP == '}');
908
 
            (*formatP)++;  /* Skip over closing brace */
909
 
        }
910
 
        break;
911
 
 
912
 
    default: {
913
 
        const char * const badCharacter = xmlrpc_makePrintableChar(formatChar);
914
 
        xmlrpc_env_set_fault_formatted(
915
 
            envP, XMLRPC_INTERNAL_ERROR,
916
 
            "Unexpected character '%s' in format string", badCharacter);
917
 
        xmlrpc_strfree(badCharacter);
918
 
        }
919
 
    }
920
 
}
921
 
 
922
 
 
923
 
 
924
 
void
925
 
xmlrpc_build_value_va(xmlrpc_env *    const envP,
926
 
                      const char *    const format,
927
 
                      va_list               args,
928
 
                      xmlrpc_value ** const valPP,
929
 
                      const char **   const tailP) {
930
 
 
931
 
    const char * formatCursor;
932
 
    va_list args_copy;
933
 
 
934
 
    XMLRPC_ASSERT_ENV_OK(envP);
935
 
    XMLRPC_ASSERT(format != NULL);
936
 
 
937
 
    if (strlen(format) == 0)
938
 
        xmlrpc_env_set_fault_formatted(
939
 
            envP, XMLRPC_INTERNAL_ERROR, "Format string is empty.");
940
 
    else {
941
 
        formatCursor = &format[0];
942
 
        VA_LIST_COPY(args_copy, args);
943
 
        getValue(envP, &formatCursor, &args_copy, valPP);
944
 
        
945
 
        if (!envP->fault_occurred)
946
 
            XMLRPC_ASSERT_VALUE_OK(*valPP);
947
 
        
948
 
        *tailP = formatCursor;
949
 
    }
950
 
}
951
 
 
952
 
 
953
 
 
954
 
xmlrpc_value * 
955
 
xmlrpc_build_value(xmlrpc_env * const envP,
956
 
                   const char * const format, 
957
 
                   ...) {
958
 
 
959
 
    va_list args;
960
 
    xmlrpc_value* retval;
961
 
    const char * suffix;
962
 
 
963
 
    va_start(args, format);
964
 
    xmlrpc_build_value_va(envP, format, args, &retval, &suffix);
965
 
    va_end(args);
966
 
 
967
 
    if (!envP->fault_occurred) {
968
 
        if (*suffix != '\0')
969
 
            xmlrpc_env_set_fault_formatted(
970
 
                envP, XMLRPC_INTERNAL_ERROR, "Junk after the argument "
971
 
                "specifier: '%s'.  There must be exactly one arument.",
972
 
                suffix);
973
 
    
974
 
        if (envP->fault_occurred)
975
 
            xmlrpc_DECREF(retval);
976
 
    }
977
 
    return retval;
978
 
}
979
 
 
980
 
 
981
 
/*=========================================================================
982
 
**  Parsing XML-RPC values.
983
 
**=========================================================================
984
 
**  Parse an XML-RPC value based on a format string. This code is heavily
985
 
**  inspired by Py_BuildValue from Python 1.5.2.
986
 
*/
987
 
 
988
 
/* Prototype for recursive invocation: */
989
 
 
990
 
static void 
991
 
parsevalue(xmlrpc_env *   const env,
992
 
           xmlrpc_value * const val,
993
 
           const char **  const format,
994
 
           va_list *            args);
995
 
 
996
 
static void 
997
 
parsearray(xmlrpc_env *         const env,
998
 
           const xmlrpc_value * const array,
999
 
           const char **        const format,
1000
 
           char                 const delimiter,
1001
 
           va_list *                  args) {
1002
 
 
1003
 
    int size, i;
1004
 
    xmlrpc_value *item;
1005
 
 
1006
 
    /* Fetch the array size. */
1007
 
    size = xmlrpc_array_size(env, array);
1008
 
    XMLRPC_FAIL_IF_FAULT(env);
1009
 
 
1010
 
    /* Loop over the items in the array. */
1011
 
    for (i = 0; i < size; i++) {
1012
 
        /* Bail out if the caller didn't care about the rest of the items. */
1013
 
        if (**format == '*')
1014
 
            break;
1015
 
 
1016
 
        item = xmlrpc_array_get_item(env, array, i);
1017
 
        XMLRPC_FAIL_IF_FAULT(env);
1018
 
 
1019
 
        XMLRPC_ASSERT(**format != '\0');
1020
 
        if (**format == delimiter)
1021
 
            XMLRPC_FAIL(env, XMLRPC_INDEX_ERROR, "Too many items in array");
1022
 
        parsevalue(env, item, format, args);
1023
 
        XMLRPC_FAIL_IF_FAULT(env);
1024
 
    }
1025
 
    if (**format == '*')
1026
 
        (*format)++;
1027
 
    if (**format != delimiter)
1028
 
        XMLRPC_FAIL(env, XMLRPC_INDEX_ERROR, "Not enough items in array");
1029
 
 
1030
 
           cleanup:
1031
 
    return;
1032
 
}
1033
 
 
1034
 
 
1035
 
 
1036
 
static void 
1037
 
parsestruct(xmlrpc_env *   const env,
1038
 
            xmlrpc_value * const strct,
1039
 
            const char **  const format,
1040
 
            char           const delimiter,
1041
 
            va_list *            args) {
1042
 
 
1043
 
    xmlrpc_value *key, *value;
1044
 
    char *keystr;
1045
 
    size_t keylen;
1046
 
 
1047
 
    /* Set up error handling preconditions. */
1048
 
    key = NULL;
1049
 
 
1050
 
    /* Build the members of our struct. */
1051
 
    while (**format != '*' && **format != delimiter && **format != '\0') {
1052
 
 
1053
 
        /* Get our key, and skip over the ':' character. Notice the
1054
 
        ** sudden call to getValue--we're going in the opposite direction. */
1055
 
        getValue(env, format, args, &key);
1056
 
        XMLRPC_FAIL_IF_FAULT(env);
1057
 
        XMLRPC_ASSERT(**format == ':');
1058
 
        (*format)++;
1059
 
 
1060
 
        /* Look up the value for our key. */
1061
 
        xmlrpc_parse_value(env, key, "s#", &keystr, &keylen);
1062
 
        XMLRPC_FAIL_IF_FAULT(env);
1063
 
        value = xmlrpc_struct_get_value_n(env, strct, keystr, keylen);
1064
 
        XMLRPC_FAIL_IF_FAULT(env);
1065
 
 
1066
 
        /* Get our value, and skip over the ',' character (if present). */
1067
 
        parsevalue(env, value, format, args);
1068
 
        XMLRPC_FAIL_IF_FAULT(env);
1069
 
        XMLRPC_ASSERT(**format == ',' || **format == delimiter);
1070
 
        if (**format == ',')
1071
 
            (*format)++;
1072
 
 
1073
 
        /* Release our reference, and restore our invariant. */
1074
 
        xmlrpc_DECREF(key);
1075
 
        key = NULL;
1076
 
    }
1077
 
    if (**format == '*') {
1078
 
        (*format)++;
1079
 
        if (**format != delimiter && **format != '\0')
1080
 
            XMLRPC_FAIL(env, XMLRPC_INTERNAL_ERROR, 
1081
 
                        "* can appear only at the end "
1082
 
                        "of a structure format specifier");
1083
 
    } else {
1084
 
        /* Here we're supposed to fail if he didn't extract all the
1085
 
           members.  But we don't know how to determine whether he
1086
 
           specified all the members, so we always fail.
1087
 
        */
1088
 
        XMLRPC_FAIL(env, XMLRPC_INTERNAL_ERROR, "You must specify '*' as the "
1089
 
                    "last member of a structure in a format specifier "
1090
 
                    "used for parsing an xmlrpc_value"); 
1091
 
    }
1092
 
    XMLRPC_ASSERT(**format == delimiter || **format == '\0');
1093
 
 
1094
 
cleanup:
1095
 
    if (key)
1096
 
        xmlrpc_DECREF(key);
1097
 
}
1098
 
 
1099
 
 
1100
 
static void 
1101
 
parsevalue(xmlrpc_env *   const envP,
1102
 
           xmlrpc_value * const valueP,
1103
 
           const char **  const format,
1104
 
           va_list *            args) {
1105
 
 
1106
 
    char formatSpecChar;
1107
 
 
1108
 
    formatSpecChar = *(*format)++;
1109
 
 
1110
 
    switch (formatSpecChar) {
1111
 
    case 'i':
1112
 
        validateType(envP, valueP, XMLRPC_TYPE_INT);
1113
 
        if (!envP->fault_occurred) {
1114
 
            xmlrpc_int32 * const int32ptr = 
1115
 
                (xmlrpc_int32*) va_arg(*args, xmlrpc_int32*);
1116
 
            *int32ptr = valueP->_value.i;
1117
 
        }
1118
 
        break;
1119
 
 
1120
 
    case 'b':
1121
 
        validateType(envP, valueP, XMLRPC_TYPE_BOOL);
1122
 
        if (!envP->fault_occurred) {
1123
 
            xmlrpc_bool * const boolptr =
1124
 
                (xmlrpc_bool*) va_arg(*args, xmlrpc_bool*);
1125
 
            *boolptr = valueP->_value.b;       
1126
 
        }
1127
 
        break;
1128
 
 
1129
 
    case 'd':
1130
 
        validateType(envP, valueP, XMLRPC_TYPE_DOUBLE);
1131
 
        if (!envP->fault_occurred) {
1132
 
            double * const doubleptr = (double*) va_arg(*args, double*);
1133
 
            *doubleptr = valueP->_value.d;     
1134
 
        }
1135
 
        break;
1136
 
 
1137
 
    case 's':
1138
 
        validateType(envP, valueP, XMLRPC_TYPE_STRING);
1139
 
        if (!envP->fault_occurred) {
1140
 
            char * const contents =
1141
 
                XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
1142
 
            size_t const len = XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block) - 1;
1143
 
            
1144
 
            char ** const strptr = (char**) va_arg(*args, char**);
1145
 
            if (**format == '#') {
1146
 
                size_t * const sizeptr = (size_t*) va_arg(*args, size_t**);
1147
 
                (*format)++;
1148
 
                *sizeptr = len;
1149
 
            } else
1150
 
                verifyNoNulls(envP, contents, (unsigned int)len);
1151
 
            *strptr = contents;
1152
 
        }
1153
 
        break;
1154
 
 
1155
 
#ifdef HAVE_UNICODE_WCHAR
1156
 
    case 'w':
1157
 
        validateType(envP, valueP, XMLRPC_TYPE_STRING);
1158
 
        if (!envP->fault_occurred) {
1159
 
            if (!valueP->_wcs_block) {
1160
 
                /* Allocate a wchar_t string if we don't have one. */
1161
 
                char * const contents = 
1162
 
                    XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
1163
 
                size_t const len = 
1164
 
                    XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block) - 1;
1165
 
                valueP->_wcs_block = 
1166
 
                    xmlrpc_utf8_to_wcs(envP, contents, len + 1);
1167
 
            }
1168
 
            if (!envP->fault_occurred) {
1169
 
                wchar_t * const wcontents = 
1170
 
                    XMLRPC_MEMBLOCK_CONTENTS(wchar_t, valueP->_wcs_block);
1171
 
                size_t const len = 
1172
 
                    XMLRPC_MEMBLOCK_SIZE(wchar_t, valueP->_wcs_block) - 1;
1173
 
 
1174
 
                wchar_t ** const wcsptr = (wchar_t**) va_arg(*args, wchar_t**);
1175
 
                if (**format == '#') {
1176
 
                    size_t * const sizeptr = (size_t*) va_arg(*args, size_t**);
1177
 
                    (*format)++;
1178
 
                    *sizeptr = len;
1179
 
                } else
1180
 
                    verifyNoNullsW(envP, wcontents, (unsigned int)len);
1181
 
                *wcsptr = wcontents;
1182
 
            }
1183
 
        }
1184
 
        break;
1185
 
#endif /* HAVE_UNICODE_WCHAR */
1186
 
        
1187
 
    case '8':
1188
 
        /* The code 't' is reserved for a better, time_t based
1189
 
        ** implementation of dateTime conversion. */
1190
 
        validateType(envP, valueP, XMLRPC_TYPE_DATETIME);
1191
 
        if (!envP->fault_occurred) {
1192
 
            char * const contents = 
1193
 
                XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
1194
 
            char ** const strptr = (char**) va_arg(*args, char**);
1195
 
            *strptr = contents;
1196
 
        }
1197
 
        break;
1198
 
 
1199
 
    case '6':
1200
 
        validateType(envP, valueP, XMLRPC_TYPE_BASE64);
1201
 
        if (!envP->fault_occurred) {
1202
 
            unsigned char * const bin_data =
1203
 
                XMLRPC_MEMBLOCK_CONTENTS(unsigned char,
1204
 
                                         &valueP->_block);
1205
 
            size_t const len = XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block);
1206
 
            unsigned char ** const binptr =
1207
 
                (unsigned char**) va_arg(*args, unsigned char**);
1208
 
            size_t * const sizeptr = (size_t*) va_arg(*args, size_t**);        
1209
 
            *binptr = bin_data;
1210
 
            *sizeptr = len;
1211
 
        }
1212
 
        break;
1213
 
 
1214
 
    case 'p':
1215
 
        validateType(envP, valueP, XMLRPC_TYPE_C_PTR);
1216
 
        if (!envP->fault_occurred) {
1217
 
            void ** const voidptrptr = (void**) va_arg(*args, void**);
1218
 
            *voidptrptr = valueP->_value.c_ptr;
1219
 
        }
1220
 
        break;
1221
 
 
1222
 
    case 'V': {
1223
 
        xmlrpc_value ** const valptr =
1224
 
            (xmlrpc_value**) va_arg(*args, xmlrpc_value**);
1225
 
        *valptr = valueP;
1226
 
    }
1227
 
        break;
1228
 
 
1229
 
    case 'A':
1230
 
        validateType(envP, valueP, XMLRPC_TYPE_ARRAY);
1231
 
        if (!envP->fault_occurred) {
1232
 
            xmlrpc_value ** const valptr =
1233
 
                (xmlrpc_value**) va_arg(*args, xmlrpc_value**);
1234
 
            *valptr = valueP;
1235
 
        }
1236
 
        break;
1237
 
 
1238
 
    case 'S':
1239
 
        validateType(envP, valueP, XMLRPC_TYPE_STRUCT);
1240
 
        if (!envP->fault_occurred) {
1241
 
            xmlrpc_value ** const valptr =
1242
 
                (xmlrpc_value**) va_arg(*args, xmlrpc_value**);
1243
 
            *valptr = valueP;
1244
 
        }
1245
 
        break;
1246
 
 
1247
 
    case '(':
1248
 
        validateType(envP, valueP, XMLRPC_TYPE_ARRAY);
1249
 
        if (!envP->fault_occurred) {
1250
 
            parsearray(envP, valueP, format, ')', args);
1251
 
            (*format)++;
1252
 
        }
1253
 
        break;
1254
 
 
1255
 
    case '{':
1256
 
        validateType(envP, valueP, XMLRPC_TYPE_STRUCT);
1257
 
        if (!envP->fault_occurred) {
1258
 
            parsestruct(envP, valueP, format, '}', args);
1259
 
            (*format)++;
1260
 
        }
1261
 
        break;
1262
 
 
1263
 
    default:
1264
 
        xmlrpc_env_set_fault_formatted(
1265
 
            envP, XMLRPC_INTERNAL_ERROR, "Invalid format character '%c'",
1266
 
            formatSpecChar);
1267
 
    }
1268
 
}
1269
 
 
1270
 
 
1271
 
 
1272
 
void 
1273
 
xmlrpc_parse_value_va(xmlrpc_env *   const envP,
1274
 
                      xmlrpc_value * const value,
1275
 
                      const char *   const format,
1276
 
                      va_list              args) {
1277
 
 
1278
 
    const char *format_copy;
1279
 
    va_list args_copy;
1280
 
 
1281
 
    XMLRPC_ASSERT_ENV_OK(envP);
1282
 
    XMLRPC_ASSERT_VALUE_OK(value);
1283
 
    XMLRPC_ASSERT(format != NULL);
1284
 
 
1285
 
    format_copy = format;
1286
 
    VA_LIST_COPY(args_copy, args);
1287
 
    parsevalue(envP, value, &format_copy, &args_copy);
1288
 
    if (!envP->fault_occurred) {
1289
 
        XMLRPC_ASSERT(*format_copy == '\0');
1290
 
    }
1291
 
}
1292
 
 
1293
 
 
1294
 
 
1295
 
void 
1296
 
xmlrpc_parse_value(xmlrpc_env *   const envP,
1297
 
                   xmlrpc_value * const value,
1298
 
                   const char *   const format, 
1299
 
                   ...) {
1300
 
 
1301
 
    va_list args;
1302
 
 
1303
 
    va_start(args, format);
1304
 
    xmlrpc_parse_value_va(envP, value, format, args);
1305
 
    va_end(args);
1306
 
}
1307
 
 
1308
 
 
1309
 
 
1310
 
/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
1311
 
** Copyright (C) 2001 by Eric Kidd. All rights reserved.
1312
 
**
1313
 
** Redistribution and use in source and binary forms, with or without
1314
 
** modification, are permitted provided that the following conditions
1315
 
** are met:
1316
 
** 1. Redistributions of source code must retain the above copyright
1317
 
**    notice, this list of conditions and the following disclaimer.
1318
 
** 2. Redistributions in binary form must reproduce the above copyright
1319
 
**    notice, this list of conditions and the following disclaimer in the
1320
 
**    documentation and/or other materials provided with the distribution.
1321
 
** 3. The name of the author may not be used to endorse or promote products
1322
 
**    derived from this software without specific prior written permission. 
1323
 
**  
1324
 
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1325
 
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1326
 
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1327
 
** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1328
 
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1329
 
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1330
 
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1331
 
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1332
 
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1333
 
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1334
 
** SUCH DAMAGE. */