00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
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 }