belle_sip_object.c 5.05 KB
Newer Older
Simon Morlat's avatar
Simon Morlat committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
	belle-sip - SIP (RFC3261) library.
    Copyright (C) 2010  Belledonne Communications SARL

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "belle_sip_internal.h"

Simon Morlat's avatar
Simon Morlat committed
21 22 23 24 25 26
static int has_type(belle_sip_object_t *obj, belle_sip_type_id_t id){
	belle_sip_object_vptr_t *vptr=obj->vptr;
	
	while(vptr!=NULL){
		if (vptr->id==id) return TRUE;
		vptr=vptr->parent;
Simon Morlat's avatar
Simon Morlat committed
27
	}
Simon Morlat's avatar
Simon Morlat committed
28
	return FALSE;
Simon Morlat's avatar
Simon Morlat committed
29
}
30 31

int belle_sip_object_is_instance_of(belle_sip_object_t * obj,belle_sip_type_id_t id) {
32 33
	return has_type(obj,id);
}
34

Simon Morlat's avatar
Simon Morlat committed
35
belle_sip_object_t * _belle_sip_object_new(size_t objsize, belle_sip_object_vptr_t *vptr, int initially_unowed){
Simon Morlat's avatar
Simon Morlat committed
36 37
	belle_sip_object_t *obj=(belle_sip_object_t *)belle_sip_malloc0(objsize);
	obj->ref=initially_unowed ? 0 : 1;
38
	obj->vptr=vptr;
Simon Morlat's avatar
Simon Morlat committed
39
	obj->size=objsize;
Simon Morlat's avatar
Simon Morlat committed
40 41 42 43 44 45 46
	return obj;
}

int belle_sip_object_is_unowed(const belle_sip_object_t *obj){
	return obj->ref==0;
}

47 48
belle_sip_object_t * belle_sip_object_ref(void *obj){
	BELLE_SIP_OBJECT(obj)->ref++;
jehan's avatar
jehan committed
49
	return obj;
Simon Morlat's avatar
Simon Morlat committed
50 51
}

52 53
void belle_sip_object_unref(void *ptr){
	belle_sip_object_t *obj=BELLE_SIP_OBJECT(ptr);
Simon Morlat's avatar
Simon Morlat committed
54
	if (obj->ref==0){
55
		/*might hide a double unref belle_sip_warning("Destroying unowed object");*/
Simon Morlat's avatar
Simon Morlat committed
56
		belle_sip_object_delete(obj);
Simon Morlat's avatar
Simon Morlat committed
57 58 59 60
		return;
	}
	obj->ref--;
	if (obj->ref==0){
Simon Morlat's avatar
Simon Morlat committed
61
		belle_sip_object_delete(obj);
Simon Morlat's avatar
Simon Morlat committed
62 63 64
	}
}

Simon Morlat's avatar
Simon Morlat committed
65 66 67 68 69 70 71 72 73 74 75 76 77 78
static void _belle_sip_object_uninit(belle_sip_object_t *obj){
	if (obj->name)
		belle_sip_free(obj->name);
}

static void _belle_sip_object_clone(belle_sip_object_t *obj, const belle_sip_object_t *orig){
	if (orig->name!=NULL) obj->name=belle_sip_strdup(obj->name);
}

belle_sip_object_vptr_t belle_sip_object_t_vptr={
	BELLE_SIP_TYPE_ID(belle_sip_object_t),
	NULL, /*no parent, it's god*/
	NULL,
	_belle_sip_object_uninit,
jehan's avatar
jehan committed
79 80
	_belle_sip_object_clone,
	NULL
Simon Morlat's avatar
Simon Morlat committed
81 82 83
};

void belle_sip_object_delete(void *ptr){
84
	belle_sip_object_t *obj=BELLE_SIP_OBJECT(ptr);
Simon Morlat's avatar
Simon Morlat committed
85
	belle_sip_object_vptr_t *vptr;
Simon Morlat's avatar
Simon Morlat committed
86 87
	if (obj->ref!=0){
		belle_sip_error("Destroying referenced object !");
Simon Morlat's avatar
Simon Morlat committed
88 89 90 91 92
		vptr=obj->vptr;
		while(vptr!=NULL){
			if (vptr->destroy) vptr->destroy(obj);
			vptr=vptr->parent;
		}
Simon Morlat's avatar
Simon Morlat committed
93 94 95 96
		belle_sip_free(obj);
	}
}

Simon Morlat's avatar
Simon Morlat committed
97 98 99 100 101 102 103 104 105 106 107 108 109 110
belle_sip_object_t *belle_sip_object_clone(const belle_sip_object_t *obj){
	belle_sip_object_t *newobj;
	belle_sip_object_vptr_t *vptr;
	
	newobj=belle_sip_malloc0(obj->size);
	newobj->ref=1;
	newobj->vptr=obj->vptr;
	
	vptr=obj->vptr;
	while(vptr!=NULL){
		if (vptr->clone==NULL){
			belle_sip_fatal("Object of type %i cannot be cloned, it does not provide a clone() implementation.",vptr->id);
			return NULL;
		}else vptr->clone(newobj,obj);
jehan's avatar
jehan committed
111
		vptr=vptr->parent;
Simon Morlat's avatar
Simon Morlat committed
112 113 114 115
	}
	return newobj;
}

Simon Morlat's avatar
Simon Morlat committed
116
void *belle_sip_object_cast(belle_sip_object_t *obj, belle_sip_type_id_t id, const char *castname, const char *file, int fileno){
117 118 119 120 121
	if (obj!=NULL){
		if (has_type(obj,id)==0){
			belle_sip_fatal("Bad cast to %s at %s:%i",castname,file,fileno);
			return NULL;
		}
Simon Morlat's avatar
Simon Morlat committed
122 123 124
	}
	return obj;
}
Simon Morlat's avatar
Simon Morlat committed
125

126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
void *belle_sip_object_get_interface_methods(belle_sip_object_t *obj, belle_sip_interface_id_t ifid){
	if (obj!=NULL){
		belle_sip_object_vptr_t *vptr;
		for (vptr=obj->vptr;vptr!=NULL;vptr=vptr->parent){
			belle_sip_interface_id_t **ifaces=vptr->interfaces;
			if (ifaces!=NULL){
				for(;*ifaces!=0;++ifaces){
					if (**ifaces==ifid){
						return *ifaces;
					}
				}
			}
		}
	}
	return NULL;
}

int belle_sip_object_implements(belle_sip_object_t *obj, belle_sip_interface_id_t id){
	return belle_sip_object_get_interface_methods(obj,id)!=NULL;
}

void *belle_sip_object_cast_to_interface(belle_sip_object_t *obj, belle_sip_interface_id_t ifid, const char *castname, const char *file, int fileno){
	if (obj!=NULL){
		if (belle_sip_object_get_interface_methods(obj,ifid)==0){
			belle_sip_fatal("Bad cast to interface %s at %s:%i",castname,file,fileno);
			return NULL;
		}
	}
	return obj;
}
Simon Morlat's avatar
Simon Morlat committed
156

157
void belle_sip_object_set_name(belle_sip_object_t* object,const char* name) {
Simon Morlat's avatar
Simon Morlat committed
158 159 160 161 162 163
	if (object->name) {
		belle_sip_free(object->name);
		object->name=NULL;
	}
	if (name)
		object->name=belle_sip_strdup(name);
164
}
Simon Morlat's avatar
Simon Morlat committed
165

166 167 168
const char* belle_sip_object_get_name(belle_sip_object_t* object) {
	return object->name;
}
jehan's avatar
jehan committed
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187

int belle_sip_object_marshal(belle_sip_object_t* obj, char* buff,unsigned int offset,size_t buff_size) {
	belle_sip_object_vptr_t *vptr=obj->vptr;
	while (vptr != NULL) {
		if (vptr->marshal != NULL) {
			return vptr->marshal(obj,buff,offset,buff_size);
		} else {
			vptr=vptr->parent;
		}
	}
	return -1; /*no implementation found*/
}
char* belle_sip_object_to_string(belle_sip_object_t* obj) {
	char buff[2048]; /*to be optimized*/
	int size = belle_sip_object_marshal(obj,buff,0,sizeof(buff));
	buff[size]='\0';
	return strdup(buff);

}