Module: sip-router Branch: master Commit: 6f31c603d1e540b1cd7ca7e81648e024acbd1388 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=6f31c603...
Author: Daniel-Constantin Mierla miconda@gmail.com Committer: Daniel-Constantin Mierla miconda@gmail.com Date: Mon Dec 24 10:02:01 2012 +0100
core: extended xavp api
- functions to add an avp last in a list or inserted at a specific position, to extract an avp from top of the list
---
xavp.c | 216 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ xavp.h | 7 ++ 2 files changed, 223 insertions(+), 0 deletions(-)
diff --git a/xavp.c b/xavp.c index 97b545d..f04ac90 100644 --- a/xavp.c +++ b/xavp.c @@ -113,6 +113,56 @@ static sr_xavp_t *xavp_new_value(str *name, sr_xval_t *val) return avp; }
+int xavp_add(sr_xavp_t *xavp, sr_xavp_t **list) +{ + if (xavp==NULL) + return -1; + /* Prepend new xavp to the list */ + if(list) { + xavp->next = *list; + *list = xavp; + } else { + xavp->next = *_xavp_list_crt; + *_xavp_list_crt = xavp; + } + + return 0; +} + +int xavp_add_last(sr_xavp_t *xavp, sr_xavp_t **list) +{ + sr_xavp_t *prev; + sr_xavp_t *crt; + + if (xavp==NULL) + return -1; + + crt = xavp_get_internal(&xavp->name, list, 0, 0); + + prev = NULL; + + while(crt) { + prev = crt; + crt = xavp_get_next(prev); + } + + if(prev==NULL) { + /* Prepend new xavp to the list */ + if(list) { + xavp->next = *list; + *list = xavp; + } else { + xavp->next = *_xavp_list_crt; + *_xavp_list_crt = xavp; + } + } else { + xavp->next = prev->next; + prev->next = xavp; + } + + return 0; +} + sr_xavp_t *xavp_add_value(str *name, sr_xval_t *val, sr_xavp_t **list) { sr_xavp_t *avp=0; @@ -454,4 +504,170 @@ void xavp_print_list(sr_xavp_t **head) { xavp_print_list_content(head, 0); } + +/** + * clone the xavp without values that are custom data + * - only one list level is cloned, other sublists are ignored + */ +sr_xavp_t *xavp_clone_level_nodata(sr_xavp_t *xold) +{ + sr_xavp_t *xnew = NULL; + sr_xavp_t *navp = NULL; + sr_xavp_t *oavp = NULL; + sr_xavp_t *pavp = NULL; + + if(xold == NULL) + return NULL; + if(xold->val.type==SR_XTYPE_DATA) + { + LM_INFO("xavp value type is 'data' - ignoring in clone\n"); + return NULL; + } + xnew = xavp_new_value(&xold->name, &xold->val); + if(xnew==NULL) + { + LM_ERR("cannot create cloned root xavp\n"); + return NULL; + } + + if(xold->val.type!=SR_XTYPE_XAVP) + return xnew; + + xnew->val.v.xavp = NULL; + oavp = xold->val.v.xavp; + + while(oavp) + { + if(xold->val.type!=SR_XTYPE_DATA && xold->val.type!=SR_XTYPE_XAVP) + { + navp = xavp_new_value(&oavp->name, &oavp->val); + if(navp==NULL) + { + if(xnew->val.v.xavp == NULL) + { + shm_free(xnew); + return NULL; + } else { + xavp_destroy_list(&navp); + return NULL; + } + } + if(xnew->val.v.xavp == NULL) + { + /* link to val in head xavp */ + xnew->val.v.xavp = navp; + pavp = navp; + } else { + /* link to prev xavp in the list */ + pavp->next = navp; + } + } + oavp = oavp->next; + } + + if(xnew->val.v.xavp == NULL) + { + shm_free(xnew); + return NULL; + } + + return xnew; +} + +int xavp_insert(sr_xavp_t *xavp, int idx, sr_xavp_t **list) +{ + sr_xavp_t *crt = 0; + sr_xavp_t *fst = 0; + sr_xavp_t *lst = 0; + sr_xval_t val; + int n = 0; + int i = 0; + + if(idx==0) + return xavp_add(xavp, list); + + crt = xavp_get_internal(&xavp->name, list, 0, 0); + while(crt!=NULL && n<idx) { + lst = crt; + n++; + crt = xavp_get_next(lst); + } + memset(&val, 0, sizeof(sr_xval_t)); + val.type = SR_XTYPE_NULL; + for(i=0; i<idx-n; i++) { + crt = xavp_add_value(&xavp->name, &val, list); + if(crt==NULL) + return -1; + if(fst==NULL) + fst = crt; + if(lst==NULL) { + if(xavp_add(crt, list)<0) + return -1; + } else { + crt->next = lst->next; + lst->next = crt; + } + } + + if(fst==NULL) { + return xavp_add(xavp, list); + } else { + xavp->next = fst->next; + fst->next = xavp; + } + + return 0; +} + +sr_xavp_t *xavp_extract(str *name, sr_xavp_t **list) +{ + sr_xavp_t *avp = 0; + sr_xavp_t *foo; + sr_xavp_t *prv = 0; + unsigned int id; + + if(name==NULL || name->s==NULL) { + if(list!=NULL) { + avp = *list; + if(avp!=NULL) { + *list = avp->next; + avp->next = NULL; + } + } else { + avp = *_xavp_list_crt; + if(avp!=NULL) { + *_xavp_list_crt = avp->next; + avp->next = NULL; + } + } + + return avp; + } + + id = get_hash1_raw(name->s, name->len); + if(list!=NULL) + avp = *list; + else + avp = *_xavp_list_crt; + while(avp) + { + foo = avp; + avp=avp->next; + if(foo->id==id && foo->name.len==name->len + && strncmp(foo->name.s, name->s, name->len)==0) + { + if(prv!=NULL) + prv->next=foo->next; + else if(list!=NULL) + *list = foo->next; + else + *_xavp_list_crt = foo->next; + foo->next = NULL; + return foo; + } else { + prv = foo; + } + } + return NULL; +} #endif diff --git a/xavp.h b/xavp.h index 979bee4..0ffce2a 100644 --- a/xavp.h +++ b/xavp.h @@ -78,6 +78,8 @@ typedef struct _sr_xavp { int xavp_init_head(void); void avpx_free(sr_xavp_t *xa);
+int xavp_add(sr_xavp_t *xavp, sr_xavp_t **list); +int xavp_add_last(sr_xavp_t *xavp, sr_xavp_t **list); sr_xavp_t *xavp_add_value(str *name, sr_xval_t *val, sr_xavp_t **list); sr_xavp_t *xavp_set_value(str *name, int idx, sr_xval_t *val, sr_xavp_t **list); sr_xavp_t *xavp_get(str *name, sr_xavp_t *start); @@ -93,7 +95,12 @@ void xavp_reset_list(void); sr_xavp_t **xavp_set_list(sr_xavp_t **head); sr_xavp_t **xavp_get_crt_list(void);
+int xavp_insert(sr_xavp_t *xavp, int idx, sr_xavp_t **list); +sr_xavp_t *xavp_extract(str *name, sr_xavp_t **list); + void xavp_print_list(sr_xavp_t **head); + +sr_xavp_t *xavp_clone_level_nodata(sr_xavp_t *xold); #endif
#endif
Daniel-Constantin Mierla writes:
- functions to add an avp last in a list or inserted at a specific position, to extract an avp from top of the list
in t_serial.c, i'm currently adding branches to contacts_avp like this:
while (there are contacts left) { record = NULL; several xavp_add_value(&name, &val, &record) calls; val.type = SR_XTYPE_XAVP; val.v.xavp = record; xavp_add_value(&contacts_avp, &val, NULL); }
i'm wondering, if it would be faster to do this instead:
list = NULL; while (there are contacts left) { record = NULL; several xavp_add_value(&name, &val, &record) calls; val.type = SR_XTYPE_XAVP; val.v.xavp = record; xavp_add(&val, &list); } val.type = SR_XTYPE_XAVP; val.v.xavp = list; xavp_add_value(&contacts_avp, &val, NULL);
but after that xavp_get(&contacts_avp, NULL) returns a list of xavps that contains only one element although i added three to the list.
obviously, i do not understand the semantics of the new xavp api functions.
what is the best way to achieve what i'm trying to do, i.e., add several xavps to contacts_avp?
-- juha