void xml_element_free(xml_element * const elemP) { /*---------------------------------------------------------------------------- Blow away an existing element & all of its child elements. -----------------------------------------------------------------------------*/ xmlrpc_mem_block * children; unsigned int size; unsigned int i; xml_element ** contents; XMLRPC_ASSERT_ELEM_OK(elemP); xmlrpc_strfree(elemP->name); elemP->name = XMLRPC_BAD_POINTER; xmlrpc_mem_block_clean(&elemP->cdata); /* Deallocate all of our children recursively. */ children = &elemP->children; contents = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(xml_element *, children); size = XMLRPC_TYPED_MEM_BLOCK_SIZE(xml_element *, children); for (i = 0; i < size; ++i) xml_element_free(contents[i]); xmlrpc_mem_block_clean(&elemP->children); free(elemP); }
static xml_element * xmlElementNew(xmlrpc_env * const envP, const char * const name) { /*---------------------------------------------------------------------------- Create a new xml_element. This routine isn't exported, because the arguments are implementation-dependent. -----------------------------------------------------------------------------*/ xml_element * retval; bool nameIsValid; bool cdataIsValid; bool childrenAreValid; XMLRPC_ASSERT_ENV_OK(envP); assert(name != NULL); /* Set up our error-handling preconditions. */ retval = NULL; nameIsValid = cdataIsValid = childrenAreValid = false; MALLOCVAR(retval); XMLRPC_FAIL_IF_NULL(retval, envP, XMLRPC_INTERNAL_ERROR, "Couldn't allocate memory for XML element"); retval->parentP = NULL; /* Copy over the element name. */ retval->name = strdup(name); XMLRPC_FAIL_IF_NULL(retval->name, envP, XMLRPC_INTERNAL_ERROR, "Couldn't allocate memory for XML element"); nameIsValid = true; /* Initialize a block to hold our CDATA. */ XMLRPC_TYPED_MEM_BLOCK_INIT(char, envP, &retval->cdata, 0); XMLRPC_FAIL_IF_FAULT(envP); cdataIsValid = true; /* Initialize a block to hold our child elements. */ XMLRPC_TYPED_MEM_BLOCK_INIT(xml_element *, envP, &retval->children, 0); XMLRPC_FAIL_IF_FAULT(envP); childrenAreValid = true; cleanup: if (envP->fault_occurred) { if (retval) { if (nameIsValid) xmlrpc_strfree(retval->name); if (cdataIsValid) xmlrpc_mem_block_clean(&retval->cdata); if (childrenAreValid) xmlrpc_mem_block_clean(&retval->children); free(retval); } retval = NULL; } return retval; }
static void destroyValue(xmlrpc_value * const valueP) { /* First, we need to destroy this value's contents, if any. */ switch (valueP->_type) { case XMLRPC_TYPE_INT: break; case XMLRPC_TYPE_BOOL: break; case XMLRPC_TYPE_DOUBLE: break; case XMLRPC_TYPE_DATETIME: xmlrpc_mem_block_clean(&valueP->_block); break; case XMLRPC_TYPE_STRING: xmlrpc_destroyString(valueP); break; case XMLRPC_TYPE_BASE64: xmlrpc_mem_block_clean(&valueP->_block); break; case XMLRPC_TYPE_ARRAY: xmlrpc_destroyArrayContents(valueP); break; case XMLRPC_TYPE_STRUCT: xmlrpc_destroyStruct(valueP); break; case XMLRPC_TYPE_C_PTR: break; case XMLRPC_TYPE_NIL: break; case XMLRPC_TYPE_I8: break; case XMLRPC_TYPE_DEAD: XMLRPC_ASSERT(false); /* Can't happen, per entry conditions */ default: XMLRPC_ASSERT(false); /* There are no other possible values */ } /* Next, we mark this value as invalid, to help catch refcount ** errors. */ valueP->_type = XMLRPC_TYPE_DEAD; /* Finally, we destroy the value itself. */ free(valueP); }
void xmlrpc_destroyString(xmlrpc_value * const valueP) { if (valueP->_wcs_block) xmlrpc_mem_block_free(valueP->_wcs_block); xmlrpc_mem_block_clean(&valueP->_block); }
/* Destroy an existing xmlrpc_mem_block, and everything it contains. */ void xmlrpc_mem_block_free(xmlrpc_mem_block * const blockP) { XMLRPC_ASSERT(blockP != NULL); XMLRPC_ASSERT(blockP->_block != NULL); xmlrpc_mem_block_clean(blockP); free(blockP); }