static void
createDecompTreeNext(xmlrpc_env * const envP,
const char ** const formatP,
va_listx * const argsP,
struct decompTreeNode ** const decompNodePP) {
/*----------------------------------------------------------------------------
Create a branch of a decomposition tree that applies to the first
value described by '*formatP', and advance *formatP past the description
of that first value. E.g.:
- If *formatP is "isb", we create a branch consisting of one
node -- for an integer. We advance *formatP by one character, so
it points to the "s".
- If *formatP is "(isb)s", we create a branch that represents the
array (isb) and advance *formatP past the closing parenthesis to
point to the final "s". We return as *decompNodePP a pointer to
a node for the array, and that array in turn points to nodes for
each of the 3 array items: one for an integer, one for a string,
and one for a boolean.
The locations at which the components of that value are to be
stored (which is the main contents of the branch we create) are
given by 'argsP'.
Return as *decompNodeP a pointer to the root node of the branch we
generate.
-----------------------------------------------------------------------------*/
struct decompTreeNode * decompNodeP;
MALLOCVAR(decompNodeP);
if (decompNodeP == NULL)
xmlrpc_faultf(envP, "Could not allocate space for a decomposition "
"tree node");
else {
decompNodeP->formatSpecChar = *(*formatP)++;
switch (decompNodeP->formatSpecChar) {
case '-':
/* There's nothing to store */
break;
case 'i':
decompNodeP->store.Tinteger.valueP =
(xmlrpc_int32*) va_arg(argsP->v, xmlrpc_int32*);
break;
case 'b':
decompNodeP->store.Tbool.valueP =
(xmlrpc_bool*) va_arg(argsP->v, xmlrpc_bool*);
break;
case 'd':
decompNodeP->store.Tdouble.valueP =
(double*) va_arg(argsP->v, double*);
break;
case 't':
decompNodeP->store.TdatetimeT.valueP =
va_arg(argsP->v, time_t*);
break;
case '8':
decompNodeP->store.Tdatetime8.valueP =
(const char**) va_arg(argsP->v, char**);
break;
case 's':
decompNodeP->store.Tstring.valueP =
(const char**) va_arg(argsP->v, char**);
if (**formatP == '#') {
decompNodeP->store.Tstring.sizeP =
(size_t*) va_arg(argsP->v, size_t**);
++*formatP;
} else
decompNodeP->store.Tstring.sizeP = NULL;
break;
case 'w':
buildWideStringNode(envP, formatP, argsP, decompNodeP);
break;
case '6':
decompNodeP->store.TbitString.valueP =
(const unsigned char**) va_arg(argsP->v, unsigned char**);
decompNodeP->store.TbitString.sizeP =
(size_t*) va_arg(argsP->v, size_t**);
break;
case 'n':
/* There's no value to store */
break;
case 'I':
decompNodeP->store.Ti8.valueP =
(xmlrpc_int64 *) va_arg(argsP->v, xmlrpc_int64 *);
break;
case 'p':
decompNodeP->store.Tcptr.valueP =
(void**) va_arg(argsP->v, void**);
break;
case 'V':
decompNodeP->store.Tvalue.valueP =
(xmlrpc_value**) va_arg(argsP->v, xmlrpc_value**);
break;
case 'A':
decompNodeP->store.TarrayVal.valueP =
(xmlrpc_value**) va_arg(argsP->v, xmlrpc_value**);
break;
case 'S':
decompNodeP->store.TstructVal.valueP =
(xmlrpc_value**) va_arg(argsP->v, xmlrpc_value**);
break;
case '(':
buildArrayDecompBranch(envP, formatP, ')', argsP, decompNodeP);
++(*formatP); /* skip past closing ')' */
break;
case '{':
buildStructDecompBranch(envP, formatP, '}', argsP, decompNodeP);
++(*formatP); /* skip past closing '}' */
break;
default:
xmlrpc_faultf(envP, "Invalid format character '%c'",
decompNodeP->formatSpecChar);
}
if (envP->fault_occurred)
free(decompNodeP);
else
*decompNodePP = decompNodeP;
}
}