xavp.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com)
  5. *
  6. * Permission to use, copy, modify, and distribute this software for any
  7. * purpose with or without fee is hereby granted, provided that the above
  8. * copyright notice and this permission notice appear in all copies.
  9. *
  10. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. /*
  19. * History:
  20. * --------
  21. * 2009-05-20 created by daniel
  22. */
  23. #ifdef WITH_XAVP
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include "mem/mem.h"
  27. #include "mem/shm_mem.h"
  28. #include "dprint.h"
  29. #include "hashes.h"
  30. #include "xavp.h"
  31. /*! XAVP list head */
  32. static sr_xavp_t *_xavp_list_head = 0;
  33. /*! Pointer to XAVP current list */
  34. static sr_xavp_t **_xavp_list_crt = &_xavp_list_head;
  35. /*! Helper functions */
  36. static sr_xavp_t *xavp_get_internal(str *name, sr_xavp_t **list, int idx, sr_xavp_t **prv);
  37. static int xavp_rm_internal(str *name, sr_xavp_t **head, int idx);
  38. void xavp_shm_free(void *p)
  39. {
  40. shm_free(p);
  41. }
  42. void xavp_shm_free_unsafe(void *p)
  43. {
  44. shm_free_unsafe(p);
  45. }
  46. void xavp_free(sr_xavp_t *xa)
  47. {
  48. if(xa->val.type == SR_XTYPE_DATA) {
  49. if(xa->val.v.data!=NULL && xa->val.v.data->pfree!=NULL) {
  50. xa->val.v.data->pfree(xa->val.v.data->p, xavp_shm_free);
  51. shm_free(xa->val.v.data);
  52. }
  53. } else if(xa->val.type == SR_XTYPE_XAVP) {
  54. xavp_destroy_list(&xa->val.v.xavp);
  55. }
  56. shm_free(xa);
  57. }
  58. void xavp_free_unsafe(sr_xavp_t *xa)
  59. {
  60. if(xa->val.type == SR_XTYPE_DATA) {
  61. if(xa->val.v.data!=NULL && xa->val.v.data->pfree!=NULL) {
  62. xa->val.v.data->pfree(xa->val.v.data->p, xavp_shm_free_unsafe);
  63. shm_free_unsafe(xa->val.v.data);
  64. }
  65. } else if(xa->val.type == SR_XTYPE_XAVP) {
  66. xavp_destroy_list_unsafe(&xa->val.v.xavp);
  67. }
  68. shm_free_unsafe(xa);
  69. }
  70. static sr_xavp_t *xavp_new_value(str *name, sr_xval_t *val)
  71. {
  72. sr_xavp_t *avp;
  73. int size;
  74. unsigned int id;
  75. if(name==NULL || name->s==NULL || val==NULL)
  76. return NULL;
  77. id = get_hash1_raw(name->s, name->len);
  78. size = sizeof(sr_xavp_t) + name->len + 1;
  79. if(val->type == SR_XTYPE_STR)
  80. size += val->v.s.len + 1;
  81. avp = (sr_xavp_t*)shm_malloc(size);
  82. if(avp==NULL)
  83. return NULL;
  84. memset(avp, 0, size);
  85. avp->id = id;
  86. avp->name.s = (char*)avp + sizeof(sr_xavp_t);
  87. memcpy(avp->name.s, name->s, name->len);
  88. avp->name.s[name->len] = '\0';
  89. avp->name.len = name->len;
  90. memcpy(&avp->val, val, sizeof(sr_xval_t));
  91. if(val->type == SR_XTYPE_STR)
  92. {
  93. avp->val.v.s.s = avp->name.s + avp->name.len + 1;
  94. memcpy(avp->val.v.s.s, val->v.s.s, val->v.s.len);
  95. avp->val.v.s.s[val->v.s.len] = '\0';
  96. avp->val.v.s.len = val->v.s.len;
  97. }
  98. return avp;
  99. }
  100. int xavp_add(sr_xavp_t *xavp, sr_xavp_t **list)
  101. {
  102. if (xavp==NULL)
  103. return -1;
  104. /* Prepend new xavp to the list */
  105. if(list) {
  106. xavp->next = *list;
  107. *list = xavp;
  108. } else {
  109. xavp->next = *_xavp_list_crt;
  110. *_xavp_list_crt = xavp;
  111. }
  112. return 0;
  113. }
  114. int xavp_add_last(sr_xavp_t *xavp, sr_xavp_t **list)
  115. {
  116. sr_xavp_t *prev;
  117. sr_xavp_t *crt;
  118. if (xavp==NULL)
  119. return -1;
  120. crt = xavp_get_internal(&xavp->name, list, 0, 0);
  121. prev = NULL;
  122. while(crt) {
  123. prev = crt;
  124. crt = xavp_get_next(prev);
  125. }
  126. if(prev==NULL) {
  127. /* Prepend new xavp to the list */
  128. if(list) {
  129. xavp->next = *list;
  130. *list = xavp;
  131. } else {
  132. xavp->next = *_xavp_list_crt;
  133. *_xavp_list_crt = xavp;
  134. }
  135. } else {
  136. xavp->next = prev->next;
  137. prev->next = xavp;
  138. }
  139. return 0;
  140. }
  141. sr_xavp_t *xavp_add_value(str *name, sr_xval_t *val, sr_xavp_t **list)
  142. {
  143. sr_xavp_t *avp=0;
  144. avp = xavp_new_value(name, val);
  145. if (avp==NULL)
  146. return NULL;
  147. /* Prepend new value to the list */
  148. if(list) {
  149. avp->next = *list;
  150. *list = avp;
  151. } else {
  152. avp->next = *_xavp_list_crt;
  153. *_xavp_list_crt = avp;
  154. }
  155. return avp;
  156. }
  157. sr_xavp_t *xavp_add_xavp_value(str *rname, str *name, sr_xval_t *val, sr_xavp_t **list)
  158. {
  159. sr_xavp_t *ravp=0;
  160. sr_xavp_t *cavp=0;
  161. sr_xval_t rval;
  162. cavp = xavp_new_value(name, val);
  163. if (cavp==NULL)
  164. return NULL;
  165. memset(&rval, 0, sizeof(sr_xval_t));
  166. rval.type = SR_XTYPE_XAVP;
  167. rval.v.xavp = cavp;
  168. ravp = xavp_new_value(rname, &rval);
  169. if (ravp==NULL) {
  170. xavp_destroy_list(&cavp);
  171. return NULL;
  172. }
  173. /* Prepend new value to the list */
  174. if(list) {
  175. ravp->next = *list;
  176. *list = ravp;
  177. } else {
  178. ravp->next = *_xavp_list_crt;
  179. *_xavp_list_crt = ravp;
  180. }
  181. return ravp;
  182. }
  183. sr_xavp_t *xavp_set_value(str *name, int idx, sr_xval_t *val, sr_xavp_t **list)
  184. {
  185. sr_xavp_t *avp;
  186. sr_xavp_t *cur;
  187. sr_xavp_t *prv=0;
  188. if(val==NULL)
  189. return NULL;
  190. /* Find the current value */
  191. cur = xavp_get_internal(name, list, idx, &prv);
  192. if(cur==NULL)
  193. return NULL;
  194. avp = xavp_new_value(name, val);
  195. if (avp==NULL)
  196. return NULL;
  197. /* Replace the current value with the new */
  198. avp->next = cur->next;
  199. if(prv)
  200. prv->next = avp;
  201. else if(list)
  202. *list = avp;
  203. else
  204. *_xavp_list_crt = avp;
  205. xavp_free(cur);
  206. return avp;
  207. }
  208. static sr_xavp_t *xavp_get_internal(str *name, sr_xavp_t **list, int idx, sr_xavp_t **prv)
  209. {
  210. sr_xavp_t *avp;
  211. unsigned int id;
  212. int n = 0;
  213. if(name==NULL || name->s==NULL)
  214. return NULL;
  215. id = get_hash1_raw(name->s, name->len);
  216. if(list && *list)
  217. avp = *list;
  218. else
  219. avp = *_xavp_list_crt;
  220. while(avp)
  221. {
  222. if(avp->id==id && avp->name.len==name->len
  223. && strncmp(avp->name.s, name->s, name->len)==0)
  224. {
  225. if(idx==n)
  226. return avp;
  227. n++;
  228. }
  229. if(prv)
  230. *prv = avp;
  231. avp = avp->next;
  232. }
  233. return NULL;
  234. }
  235. sr_xavp_t *xavp_get(str *name, sr_xavp_t *start)
  236. {
  237. return xavp_get_internal(name, (start)?&start:NULL, 0, NULL);
  238. }
  239. sr_xavp_t *xavp_get_by_index(str *name, int idx, sr_xavp_t **start)
  240. {
  241. return xavp_get_internal(name, start, idx, NULL);
  242. }
  243. sr_xavp_t *xavp_get_next(sr_xavp_t *start)
  244. {
  245. sr_xavp_t *avp;
  246. if(start==NULL)
  247. return NULL;
  248. avp = start->next;
  249. while(avp)
  250. {
  251. if(avp->id==start->id && avp->name.len==start->name.len
  252. && strncmp(avp->name.s, start->name.s, start->name.len)==0)
  253. return avp;
  254. avp=avp->next;
  255. }
  256. return NULL;
  257. }
  258. int xavp_rm(sr_xavp_t *xa, sr_xavp_t **head)
  259. {
  260. sr_xavp_t *avp;
  261. sr_xavp_t *prv=0;
  262. if(head!=NULL)
  263. avp = *head;
  264. else
  265. avp=*_xavp_list_crt;
  266. while(avp)
  267. {
  268. if(avp==xa)
  269. {
  270. if(prv)
  271. prv->next=avp->next;
  272. else if(head!=NULL)
  273. *head = avp->next;
  274. else
  275. *_xavp_list_crt = avp->next;
  276. xavp_free(avp);
  277. return 1;
  278. }
  279. prv=avp; avp=avp->next;
  280. }
  281. return 0;
  282. }
  283. /* Remove xavps
  284. * idx: <0 remove all xavps with the same name
  285. * >=0 remove only the specified index xavp
  286. * Returns number of xavps that were deleted
  287. */
  288. static int xavp_rm_internal(str *name, sr_xavp_t **head, int idx)
  289. {
  290. sr_xavp_t *avp;
  291. sr_xavp_t *foo;
  292. sr_xavp_t *prv=0;
  293. unsigned int id;
  294. int n=0;
  295. int count=0;
  296. if(name==NULL || name->s==NULL)
  297. return 0;
  298. id = get_hash1_raw(name->s, name->len);
  299. if(head!=NULL)
  300. avp = *head;
  301. else
  302. avp = *_xavp_list_crt;
  303. while(avp)
  304. {
  305. foo = avp;
  306. avp=avp->next;
  307. if(foo->id==id && foo->name.len==name->len
  308. && strncmp(foo->name.s, name->s, name->len)==0)
  309. {
  310. if(idx<0 || idx==n)
  311. {
  312. if(prv!=NULL)
  313. prv->next=foo->next;
  314. else if(head!=NULL)
  315. *head = foo->next;
  316. else
  317. *_xavp_list_crt = foo->next;
  318. xavp_free(foo);
  319. if(idx>=0)
  320. return 1;
  321. count++;
  322. }
  323. n++;
  324. } else {
  325. prv = foo;
  326. }
  327. }
  328. return count;
  329. }
  330. int xavp_rm_by_name(str *name, int all, sr_xavp_t **head)
  331. {
  332. return xavp_rm_internal(name, head, -1*all);
  333. }
  334. int xavp_rm_by_index(str *name, int idx, sr_xavp_t **head)
  335. {
  336. if (idx<0)
  337. return 0;
  338. return xavp_rm_internal(name, head, idx);
  339. }
  340. int xavp_count(str *name, sr_xavp_t **start)
  341. {
  342. sr_xavp_t *avp;
  343. unsigned int id;
  344. int n = 0;
  345. if(name==NULL || name->s==NULL)
  346. return -1;
  347. id = get_hash1_raw(name->s, name->len);
  348. if(start)
  349. avp = *start;
  350. else
  351. avp=*_xavp_list_crt;
  352. while(avp)
  353. {
  354. if(avp->id==id && avp->name.len==name->len
  355. && strncmp(avp->name.s, name->s, name->len)==0)
  356. {
  357. n++;
  358. }
  359. avp=avp->next;
  360. }
  361. return n;
  362. }
  363. void xavp_destroy_list_unsafe(sr_xavp_t **head)
  364. {
  365. sr_xavp_t *avp, *foo;
  366. avp = *head;
  367. while(avp)
  368. {
  369. foo = avp;
  370. avp = avp->next;
  371. xavp_free_unsafe(foo);
  372. }
  373. *head = 0;
  374. }
  375. void xavp_destroy_list(sr_xavp_t **head)
  376. {
  377. sr_xavp_t *avp, *foo;
  378. LM_DBG("destroying xavp list %p\n", *head);
  379. avp = *head;
  380. while(avp)
  381. {
  382. foo = avp;
  383. avp = avp->next;
  384. xavp_free(foo);
  385. }
  386. *head = 0;
  387. }
  388. void xavp_reset_list(void)
  389. {
  390. assert(_xavp_list_crt!=0 );
  391. if (_xavp_list_crt!=&_xavp_list_head)
  392. _xavp_list_crt=&_xavp_list_head;
  393. xavp_destroy_list(_xavp_list_crt);
  394. }
  395. sr_xavp_t **xavp_set_list(sr_xavp_t **head)
  396. {
  397. sr_xavp_t **avp;
  398. assert(_xavp_list_crt!=0);
  399. avp = _xavp_list_crt;
  400. _xavp_list_crt = head;
  401. return avp;
  402. }
  403. sr_xavp_t **xavp_get_crt_list(void)
  404. {
  405. assert(_xavp_list_crt!=0);
  406. return _xavp_list_crt;
  407. }
  408. void xavp_print_list_content(sr_xavp_t **head, int level)
  409. {
  410. sr_xavp_t *avp=0;
  411. sr_xavp_t *start=0;
  412. if(head!=NULL)
  413. start = *head;
  414. else
  415. start=*_xavp_list_crt;
  416. LM_INFO("+++++ start XAVP list: %p (level=%d)\n", start, level);
  417. avp = start;
  418. while(avp)
  419. {
  420. LM_INFO(" *** XAVP name: %s\n", avp->name.s);
  421. LM_INFO(" XAVP id: %u\n", avp->id);
  422. LM_INFO(" XAVP value type: %d\n", avp->val.type);
  423. switch(avp->val.type) {
  424. case SR_XTYPE_NULL:
  425. LM_INFO(" XAVP value: <null>\n");
  426. break;
  427. case SR_XTYPE_INT:
  428. LM_INFO(" XAVP value: %d\n", avp->val.v.i);
  429. break;
  430. case SR_XTYPE_STR:
  431. LM_INFO(" XAVP value: %s\n", avp->val.v.s.s);
  432. break;
  433. case SR_XTYPE_TIME:
  434. LM_INFO(" XAVP value: %lu\n",
  435. (long unsigned int)avp->val.v.t);
  436. break;
  437. case SR_XTYPE_LONG:
  438. LM_INFO(" XAVP value: %ld\n", avp->val.v.l);
  439. break;
  440. case SR_XTYPE_LLONG:
  441. LM_INFO(" XAVP value: %lld\n", avp->val.v.ll);
  442. break;
  443. case SR_XTYPE_XAVP:
  444. LM_INFO(" XAVP value: <xavp:%p>\n", avp->val.v.xavp);
  445. xavp_print_list_content(&avp->val.v.xavp, level+1);
  446. break;
  447. case SR_XTYPE_DATA:
  448. LM_INFO(" XAVP value: <data:%p>\n", avp->val.v.data);
  449. break;
  450. }
  451. avp = avp->next;
  452. }
  453. LM_INFO("----- end XAVP list: %p (level=%d)\n", start, level);
  454. }
  455. void xavp_print_list(sr_xavp_t **head)
  456. {
  457. xavp_print_list_content(head, 0);
  458. }
  459. /**
  460. * returns a list of str with key names.
  461. * Example:
  462. * If we have this structure
  463. * $xavp(test=>one) = 1
  464. * $xavp(test[0]=>two) = "2"
  465. * $xavp(test[0]=>three) = 3
  466. * $xavp(test[0]=>four) = $xavp(whatever)
  467. * $xavp(test[0]=>two) = "other 2"
  468. *
  469. * xavp_get_list_keys_names(test[0]) returns
  470. * {"one", "two", "three", "four"}
  471. *
  472. * free the struct str_list afterwards
  473. * but do *NO* free the strings inside
  474. */
  475. struct str_list *xavp_get_list_key_names(sr_xavp_t *xavp)
  476. {
  477. sr_xavp_t *avp = NULL;
  478. struct str_list *result = NULL;
  479. struct str_list *r = NULL;
  480. struct str_list *f = NULL;
  481. int total = 0;
  482. if(xavp==NULL){
  483. LM_ERR("xavp is NULL\n");
  484. return 0;
  485. }
  486. if(xavp->val.type!=SR_XTYPE_XAVP){
  487. LM_ERR("%s not xavp?\n", xavp->name.s);
  488. return 0;
  489. }
  490. avp = xavp->val.v.xavp;
  491. if (avp)
  492. {
  493. result = (struct str_list*)pkg_malloc(sizeof(struct str_list));
  494. if (result==NULL) {
  495. PKG_MEM_ERROR;
  496. return 0;
  497. }
  498. r = result;
  499. r->s.s = avp->name.s;
  500. r->s.len = avp->name.len;
  501. r->next = NULL;
  502. avp = avp->next;
  503. }
  504. while(avp)
  505. {
  506. f = result;
  507. while(f)
  508. {
  509. if((avp->name.len==f->s.len)&&
  510. (strncmp(avp->name.s, f->s.s, f->s.len)==0))
  511. {
  512. break; /* name already on list */
  513. }
  514. f = f->next;
  515. }
  516. if (f==NULL)
  517. {
  518. r = append_str_list(avp->name.s, avp->name.len, &r, &total);
  519. if(r==NULL){
  520. while(result){
  521. r = result;
  522. result = result->next;
  523. pkg_free(r);
  524. }
  525. return 0;
  526. }
  527. }
  528. avp = avp->next;
  529. }
  530. return result;
  531. }
  532. /**
  533. * clone the xavp without values that are custom data
  534. * - only one list level is cloned, other sublists are ignored
  535. */
  536. sr_xavp_t *xavp_clone_level_nodata(sr_xavp_t *xold)
  537. {
  538. sr_xavp_t *xnew = NULL;
  539. sr_xavp_t *navp = NULL;
  540. sr_xavp_t *oavp = NULL;
  541. sr_xavp_t *pavp = NULL;
  542. if(xold == NULL)
  543. {
  544. return NULL;
  545. }
  546. if(xold->val.type==SR_XTYPE_DATA)
  547. {
  548. LM_INFO("xavp value type is 'data' - ignoring in clone\n");
  549. return NULL;
  550. }
  551. xnew = xavp_new_value(&xold->name, &xold->val);
  552. if(xnew==NULL)
  553. {
  554. LM_ERR("cannot create cloned root xavp\n");
  555. return NULL;
  556. }
  557. if(xold->val.type!=SR_XTYPE_XAVP)
  558. {
  559. return xnew;
  560. }
  561. xnew->val.v.xavp = NULL;
  562. oavp = xold->val.v.xavp;
  563. while(oavp)
  564. {
  565. if(oavp->val.type!=SR_XTYPE_DATA && oavp->val.type!=SR_XTYPE_XAVP)
  566. {
  567. navp = xavp_new_value(&oavp->name, &oavp->val);
  568. if(navp==NULL)
  569. {
  570. LM_ERR("cannot create cloned embedded xavp\n");
  571. if(xnew->val.v.xavp == NULL)
  572. {
  573. shm_free(xnew);
  574. return NULL;
  575. } else {
  576. xavp_destroy_list(&navp);
  577. return NULL;
  578. }
  579. }
  580. if(xnew->val.v.xavp == NULL)
  581. {
  582. /* link to val in head xavp */
  583. xnew->val.v.xavp = navp;
  584. pavp = navp;
  585. } else {
  586. /* link to prev xavp in the list */
  587. pavp->next = navp;
  588. }
  589. }
  590. oavp = oavp->next;
  591. }
  592. if(xnew->val.v.xavp == NULL)
  593. {
  594. shm_free(xnew);
  595. return NULL;
  596. }
  597. return xnew;
  598. }
  599. int xavp_insert(sr_xavp_t *xavp, int idx, sr_xavp_t **list)
  600. {
  601. sr_xavp_t *crt = 0;
  602. sr_xavp_t *lst = 0;
  603. sr_xval_t val;
  604. int n = 0;
  605. int i = 0;
  606. crt = xavp_get_internal(&xavp->name, list, 0, NULL);
  607. if (idx == 0 && (!crt || crt->val.type != SR_XTYPE_NULL))
  608. return xavp_add(xavp, list);
  609. while(crt!=NULL && n<idx) {
  610. lst = crt;
  611. n++;
  612. crt = xavp_get_next(lst);
  613. }
  614. if (crt && crt->val.type == SR_XTYPE_NULL) {
  615. xavp->next = crt->next;
  616. crt->next = xavp;
  617. xavp_rm(crt, list);
  618. return 0;
  619. }
  620. memset(&val, 0, sizeof(sr_xval_t));
  621. val.type = SR_XTYPE_NULL;
  622. for(i=0; i<idx-n; i++) {
  623. crt = xavp_new_value(&xavp->name, &val);
  624. if(crt==NULL)
  625. return -1;
  626. if (lst == NULL) {
  627. xavp_add(crt, list);
  628. } else {
  629. crt->next = lst->next;
  630. lst->next = crt;
  631. }
  632. lst = crt;
  633. }
  634. if(lst==NULL) {
  635. LM_ERR("cannot link the xavp\n");
  636. return -1;
  637. }
  638. xavp->next = lst->next;
  639. lst->next = xavp;
  640. return 0;
  641. }
  642. sr_xavp_t *xavp_extract(str *name, sr_xavp_t **list)
  643. {
  644. sr_xavp_t *avp = 0;
  645. sr_xavp_t *foo;
  646. sr_xavp_t *prv = 0;
  647. unsigned int id;
  648. if(name==NULL || name->s==NULL) {
  649. if(list!=NULL) {
  650. avp = *list;
  651. if(avp!=NULL) {
  652. *list = avp->next;
  653. avp->next = NULL;
  654. }
  655. } else {
  656. avp = *_xavp_list_crt;
  657. if(avp!=NULL) {
  658. *_xavp_list_crt = avp->next;
  659. avp->next = NULL;
  660. }
  661. }
  662. return avp;
  663. }
  664. id = get_hash1_raw(name->s, name->len);
  665. if(list!=NULL)
  666. avp = *list;
  667. else
  668. avp = *_xavp_list_crt;
  669. while(avp)
  670. {
  671. foo = avp;
  672. avp=avp->next;
  673. if(foo->id==id && foo->name.len==name->len
  674. && strncmp(foo->name.s, name->s, name->len)==0)
  675. {
  676. if(prv!=NULL)
  677. prv->next=foo->next;
  678. else if(list!=NULL)
  679. *list = foo->next;
  680. else
  681. *_xavp_list_crt = foo->next;
  682. foo->next = NULL;
  683. return foo;
  684. } else {
  685. prv = foo;
  686. }
  687. }
  688. return NULL;
  689. }
  690. /**
  691. * return child node of an xavp
  692. * - $xavp(rname=>cname)
  693. */
  694. sr_xavp_t* xavp_get_child(str *rname, str *cname)
  695. {
  696. sr_xavp_t *ravp=NULL;
  697. ravp = xavp_get(rname, NULL);
  698. if(ravp==NULL || ravp->val.type!=SR_XTYPE_XAVP)
  699. return NULL;
  700. return xavp_get(cname, ravp->val.v.xavp);
  701. }
  702. /**
  703. * return child node of an xavp if it has int value
  704. * - $xavp(rname=>cname)
  705. */
  706. sr_xavp_t* xavp_get_child_with_ival(str *rname, str *cname)
  707. {
  708. sr_xavp_t *vavp=NULL;
  709. vavp = xavp_get_child(rname, cname);
  710. if(vavp==NULL || vavp->val.type!=SR_XTYPE_INT)
  711. return NULL;
  712. return vavp;
  713. }
  714. /**
  715. * return child node of an xavp if it has string value
  716. * - $xavp(rname=>cname)
  717. */
  718. sr_xavp_t* xavp_get_child_with_sval(str *rname, str *cname)
  719. {
  720. sr_xavp_t *vavp=NULL;
  721. vavp = xavp_get_child(rname, cname);
  722. if(vavp==NULL || vavp->val.type!=SR_XTYPE_STR)
  723. return NULL;
  724. return vavp;
  725. }
  726. #endif