tree.c

Go to the documentation of this file.
00001 /*
00002  * $Id: tree.c 4518 2008-07-28 15:39:28Z henningw $
00003  *
00004  * Copyright (C) 2006 Voice Sistem SRL
00005  *
00006  * This file is part of Kamailio, a free SIP server.
00007  *
00008  * Kamailio is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * Kamailio is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00021  *
00022  *
00023  * History:
00024  * ---------
00025  *  2006-09-08  first version (bogdan)
00026  */
00027 
00028 /*!
00029  * \file 
00030  * \brief MI :: Tree 
00031  * \ingroup mi
00032  */
00033 
00034 #include <string.h>
00035 #include <stdio.h>
00036 #include <errno.h>
00037 #include "../mem/mem.h"
00038 #include "../mem/shm_mem.h"
00039 #include "../dprint.h"
00040 #include "tree.h"
00041 #include "fmt.h"
00042 
00043 
00044 static int use_shm = 0;
00045 
00046 struct mi_root *init_mi_tree(unsigned int code, char *reason, int reason_len)
00047 {
00048    struct mi_root *root;
00049 
00050    if (use_shm)
00051       root = (struct mi_root *)shm_malloc(sizeof(struct mi_root));
00052    else
00053       root = (struct mi_root *)pkg_malloc(sizeof(struct mi_root));
00054    if (!root) {
00055       LM_ERR("no more pkg mem\n");
00056       return NULL;
00057    }
00058 
00059    memset(root,0,sizeof(struct mi_root));
00060    root->node.next = root->node.last = &root->node;
00061 
00062    if (reason && reason_len) {
00063       root->reason.s = reason;
00064       root->reason.len = reason_len;
00065    }
00066    root->code = code;
00067 
00068    return root;
00069 }
00070 
00071 
00072 static void free_mi_node(struct mi_node *parent)
00073 {
00074    struct mi_node *p, *q;
00075 
00076    for(p = parent->kids ; p ; ){
00077       q = p;
00078       p = p->next;
00079       free_mi_node(q);
00080    }
00081 
00082    if (use_shm) {
00083       shm_free(parent);
00084    } else {
00085       del_mi_attr_list(parent);
00086       pkg_free(parent);
00087    }
00088 }
00089 
00090 void free_mi_tree(struct mi_root *parent)
00091 {
00092    struct mi_node *p, *q;
00093 
00094    for(p = parent->node.kids ; p ; ){
00095       q = p;
00096       p = p->next;
00097       free_mi_node(q);
00098    }
00099 
00100    if (use_shm)
00101       shm_free(parent);
00102    else
00103       pkg_free(parent);
00104 }
00105 
00106 
00107 static inline struct mi_node *create_mi_node(char *name, int name_len,
00108                            char *value, int value_len, int flags)
00109 {
00110    struct mi_node *new;
00111    int size_mem;
00112    int name_pos;
00113    int value_pos;
00114 
00115    if (!name) name_len=0;
00116    if (!name_len) name=0;
00117    if (!value) value_len=0;
00118    if (!value_len) value=0;
00119 
00120    if (!name && !value)
00121       return NULL;
00122 
00123    size_mem = sizeof(struct mi_node);
00124    value_pos = name_pos = 0;
00125 
00126    if (name && (flags & MI_DUP_NAME)){
00127       name_pos = size_mem;
00128       size_mem += name_len;
00129    }
00130    if (value && (flags & MI_DUP_VALUE)){
00131       value_pos = size_mem;
00132       size_mem += value_len;
00133    }
00134 
00135    if (use_shm)
00136       new = (struct mi_node *)shm_malloc(size_mem);
00137    else
00138       new = (struct mi_node *)pkg_malloc(size_mem);
00139    if(!new) {
00140       LM_ERR("no more pkg mem\n");
00141       return NULL;
00142    }
00143    memset(new,0,size_mem);
00144 
00145    if (name) {
00146       new->name.len = name_len;
00147       if(flags & MI_DUP_NAME){
00148          new->name.s = ((char *)new) + name_pos;
00149          strncpy(new->name.s, name, name_len);
00150       } else{
00151          new->name.s = name;
00152       }
00153    }
00154 
00155    if (value) {
00156       new->value.len = value_len;
00157       if(flags & MI_DUP_VALUE){
00158          new->value.s = ((char *)new) + value_pos;
00159          strncpy(new->value.s, value, value_len);
00160       }else{
00161          new->value.s = value;
00162       }
00163    }
00164    new->last = new;
00165 
00166    return new;
00167 }
00168 
00169 
00170 static inline struct mi_node *add_next(struct mi_node *brother,
00171          char *name, int name_len, char *value, int value_len, int flags)
00172 {
00173    struct mi_node *new;
00174 
00175    if(!brother)
00176       return NULL;
00177    
00178    new = create_mi_node(name, name_len, value, value_len, flags);
00179    if(!new)
00180       return NULL;
00181 
00182    brother->last->next = new;
00183    brother->last = new;
00184 
00185    return new;
00186 }
00187 
00188 
00189 struct mi_node *add_mi_node_sibling( struct mi_node *brother, int flags,
00190                   char *name, int name_len, char *value, int value_len)
00191 {
00192    return add_next(brother, name, name_len, value, value_len, flags);
00193 }
00194 
00195 
00196 struct mi_node *addf_mi_node_sibling(struct mi_node *brother, int flags,
00197                      char *name, int name_len, char *fmt_val, ...)
00198 {
00199    va_list ap;
00200    char *p;
00201    int  len;
00202 
00203    va_start(ap, fmt_val);
00204    p = mi_print_fmt( fmt_val, ap, &len);
00205    va_end(ap);
00206    if (p==NULL)
00207       return 0;
00208    return add_mi_node_sibling( brother, flags|MI_DUP_VALUE,
00209       name, name_len, p, len);
00210 }
00211 
00212 
00213 struct mi_node *add_mi_node_child( struct mi_node *parent, int flags,
00214                   char *name, int name_len, char *value, int value_len)
00215 {
00216    if(parent->kids){
00217       return add_next(parent->kids, name, name_len, value, value_len, flags);
00218    }else{
00219       parent->kids = create_mi_node(name, name_len, value, value_len, flags);
00220       return parent->kids;
00221    }
00222 }
00223 
00224 
00225 struct mi_node *addf_mi_node_child(struct mi_node *parent, int flags,
00226                      char *name, int name_len, char *fmt_val, ...)
00227 {
00228    va_list ap;
00229    char *p;
00230    int  len;
00231 
00232    va_start(ap, fmt_val);
00233    p = mi_print_fmt( fmt_val, ap, &len);
00234    va_end(ap);
00235    if (p==NULL)
00236       return 0;
00237    return add_mi_node_child( parent, flags|MI_DUP_VALUE,
00238       name, name_len, p, len);
00239 }
00240 
00241 
00242 static int clone_mi_node(struct mi_node *org, struct mi_node *parent)
00243 {
00244    struct mi_node *p, *q;
00245 
00246    for(p = org->kids ; p ; p=p->next){
00247       q = add_mi_node_child( parent, MI_DUP_VALUE|MI_DUP_NAME,
00248          p->name.s, p->name.len, p->value.s, p->value.len);
00249       if (q==NULL)
00250          return -1;
00251       if (clone_mi_node( p, q)!=0)
00252          return -1;
00253    }
00254    return 0;
00255 }
00256 
00257 
00258 struct mi_root* clone_mi_tree(struct mi_root *org, int shm)
00259 {
00260    struct mi_root *root;
00261 
00262    use_shm = shm?1:0;
00263 
00264    root = init_mi_tree( org->code, org->reason.s, org->reason.len);
00265    if (root==NULL)
00266       goto done;
00267 
00268    if (clone_mi_node( &(org->node), &(root->node) )!=0 ) {
00269       free_mi_tree(root);
00270       root = NULL;
00271       goto done;
00272    }
00273 
00274 done:
00275    use_shm=0;
00276    return root;
00277 }
00278 
00279 
00280 
00281 void free_shm_mi_tree(struct mi_root *parent)
00282 {
00283    use_shm = 1;
00284    free_mi_tree(parent);
00285    use_shm = 0;
00286 }

Generated on Thu May 24 20:00:33 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6