/*
* Copyright (c) 2001, 2002, 2003, 2004, 2005 Netli, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ncnf_constr.c,v 1.1 2005/05/26 12:08:19 vlm Exp $
*/
/*
* Implementation of construction, cloning and destruction.
*/
#include "headers.h"
#include "ncnf_int.h"
/*
* Basic constructor for the configuration object.
* Takes optional type and name/value, and inserts their copies into
* the newly created structure.
*/
struct ncnf_obj_s *
_ncnf_obj_new(void *mr, enum obj_class obj_class, const bstr_t type, const bstr_t value, int config_line) {
struct ncnf_obj_s *nobj;
nobj = calloc(1, sizeof(struct ncnf_obj_s));
if(nobj == NULL)
return NULL;
/*
* Initializing basic header data.
*/
nobj->obj_class = obj_class;
if(type) nobj->type = bstr_ref(type);
if(value) nobj->value = bstr_ref(value);
nobj->config_line = config_line;
nobj->mr = mr;
return nobj;
}
/*
* Kill everything alive within the configuration object structure.
*/
void
_ncnf_obj_destroy(struct ncnf_obj_s *obj) {
assert(obj->obj_class != NOBJ_INVALID);
/*
* Clear the common object header.
*/
bstr_free(obj->type);
bstr_free(obj->value);
/*
* Class-dependent destruction.
*/
switch(obj->obj_class) {
case NOBJ_ROOT:
case NOBJ_COMPLEX:
{
enum collections_e c;
for(c = 0; c < MAX_COLLECTIONS; c++)
_ncnf_coll_clear(obj->mr,
&obj->m_collection[c], 1);
}
break;
case NOBJ_REFERENCE:
assert(obj->m_ref_type);
assert(obj->m_ref_value);
bstr_free(obj->m_ref_type);
bstr_free(obj->m_ref_value);
obj->m_ref_type = 0;
obj->m_ref_value = NULL;
bstr_free(obj->m_new_ref_type);
obj->m_new_ref_type = NULL;
bstr_free(obj->m_new_ref_value);
obj->m_new_ref_value = NULL;
break;
case NOBJ_ITERATOR:
/* Do not destroy contained objects */
_ncnf_coll_clear(obj->mr, &obj->m_iterator_collection, 0);
break;
case NOBJ_LAZY_NOTIF:
case NOBJ_ATTRIBUTE:
case NOBJ_INSERTION:
/* Do nothing */
break;
case NOBJ_INVALID: /* Mostly for switch()/enum integration */
/* Do nothing */
break;
}
obj->obj_class = NOBJ_INVALID; /* Post invalidity */
free(obj);
}
/*
* Insert an object into an object.
*/
int
_ncnf_attach_obj(struct ncnf_obj_s *to, struct ncnf_obj_s *what, int relaxed_ns) {
collection_t *coll;
switch(to->obj_class) {
case NOBJ_ROOT:
case NOBJ_COMPLEX:
coll = NULL;
switch(what->obj_class) {
case NOBJ_COMPLEX:
case NOBJ_REFERENCE:
coll = &to->m_collection[COLLECTION_OBJECTS];
goto insert;
case NOBJ_ATTRIBUTE:
coll = &to->m_collection[COLLECTION_ATTRIBUTES];
goto insert;
case NOBJ_INSERTION:
coll = &to->m_collection[COLLECTION_INSERTS];
goto insert;
case NOBJ_LAZY_NOTIF:
coll = &to->m_collection[COLLECTION_LAZY_NOTIF];
goto insert;
insert:
what->parent = to;
return _ncnf_coll_insert(to->mr, coll, what,
(relaxed_ns ? MERGE_NOFLAGS : MERGE_DUPCHECK)
| MERGE_EMPTYSRC);
case NOBJ_ROOT:
{
enum collections_e c;
for(c = 0; c < MAX_COLLECTIONS; c++) {
if(_ncnf_coll_join(to->mr,
&to->m_collection[c],
&what->m_collection[c],
to,
(relaxed_ns ? MERGE_NOFLAGS : MERGE_DUPCHECK)
| MERGE_EMPTYSRC
)) {
_ncnf_obj_destroy(what);
return -1;
}
}
}
return 0;
case NOBJ_ITERATOR:
case NOBJ_INVALID:
/* Never happens */
assert(0);
}
/* Fall through */
default:
/* Cant attach object to the non-complex class */
errno = EINVAL;
return -1;
}
}
/*
* Create a full copy of the given object.
*/
struct ncnf_obj_s *
_ncnf_obj_clone(void *mr, struct ncnf_obj_s *root) {
struct ncnf_obj_s *obj;
enum collections_e c;
/*
* Create wireframe of the new object.
*/
obj = _ncnf_obj_new(mr, root->obj_class,
root->type, root->value, root->config_line);
if(obj == NULL)
return NULL;
switch(obj->obj_class) {
case NOBJ_ROOT:
case NOBJ_COMPLEX:
for(c = 0; c < MAX_COLLECTIONS; c++) {
collection_t *coll = &root->m_collection[c];
int i;
for(i = 0; i < coll->entries; i++) {
struct ncnf_obj_s *clone;
clone = _ncnf_obj_clone(mr,
coll->entry[i].object);
if(clone == NULL) {
_ncnf_obj_destroy(obj);
return NULL;
}
if(_ncnf_coll_insert(mr, &obj->m_collection[c],
clone,
/* Cloning does not have
* to do DUPCHECK */
MERGE_NOFLAGS)
) {
_ncnf_obj_destroy(clone);
_ncnf_obj_destroy(obj);
return NULL;
} else {
clone->parent = obj;
}
}
}
break;
case NOBJ_ATTRIBUTE:
obj->m_attr_flags = root->m_attr_flags;
break;
case NOBJ_REFERENCE:
obj->m_ref_type = bstr_ref(root->m_ref_type);
obj->m_ref_value = bstr_ref(root->m_ref_value);
obj->m_ref_flags = root->m_ref_flags;
obj->m_direct_reference = root->m_direct_reference;
break;
case NOBJ_INSERTION:
default:
/* Do nothing */
break;
}
/* Object copied. */
return obj;
}
syntax highlighted by Code2HTML, v. 0.9.1