Browse code

core: xavp - helper function to shift xavps to left with rotation

Daniel-Constantin Mierla authored on 10/05/2022 17:35:02
Showing 1 changed files
... ...
@@ -519,6 +519,105 @@ int xavp_count(str *name, sr_xavp_t **start)
519 519
 	return n;
520 520
 }
521 521
 
522
+/**
523
+ * Left shift xavps
524
+ */
525
+int xavp_lshift(str *name, sr_xavp_t **head, int idx)
526
+{
527
+	sr_xavp_t *avp;
528
+	sr_xavp_t *lhead = NULL;
529
+	sr_xavp_t *lhead_last = NULL;
530
+	sr_xavp_t *ltail = NULL;
531
+	sr_xavp_t *ltail_last = NULL;
532
+	sr_xavp_t *crt=0;
533
+	sr_xavp_t *prv=0;
534
+	unsigned int id;
535
+	int n=0;
536
+	int xcnt;
537
+
538
+	if(name==NULL || name->s==NULL || name->len<=0) {
539
+		return 0;
540
+	}
541
+
542
+	if(idx==0) {
543
+		return 1;
544
+	}
545
+	xcnt = xavp_count(name, head);
546
+	if(xcnt <= 0) {
547
+		return -2;
548
+	}
549
+	while(idx < 0) {
550
+		idx = xcnt + idx;
551
+	}
552
+	if(idx==0) {
553
+		return 1;
554
+	}
555
+	idx = idx % xcnt;
556
+	if(idx==0) {
557
+		return 1;
558
+	}
559
+
560
+	id = get_hash1_raw(name->s, name->len);
561
+	if(head!=NULL)
562
+		avp = *head;
563
+	else
564
+		avp = *_xavp_list_crt;
565
+	while(avp)
566
+	{
567
+		crt = avp;
568
+		avp=avp->next;
569
+		if(crt->id==id && crt->name.len==name->len
570
+				&& strncmp(crt->name.s, name->s, name->len)==0)
571
+		{
572
+			if(prv!=NULL)
573
+				prv->next=crt->next;
574
+			else if(head!=NULL)
575
+				*head = crt->next;
576
+			else
577
+				*_xavp_list_crt = crt->next;
578
+			crt->next = NULL;
579
+			if(n < idx) {
580
+				if(ltail==NULL) {
581
+					ltail = crt;
582
+				}
583
+				if(ltail_last!=NULL) {
584
+					ltail_last->next = crt;
585
+				}
586
+				ltail_last = crt;
587
+			} else {
588
+				if(lhead==NULL) {
589
+					lhead = crt;
590
+				}
591
+				if(lhead_last!=NULL) {
592
+					lhead_last->next = crt;
593
+				}
594
+				lhead_last = crt;
595
+			}
596
+			n++;
597
+		} else {
598
+			prv = crt;
599
+		}
600
+	}
601
+
602
+	if(lhead_last) {
603
+		lhead_last->next = ltail;
604
+	}
605
+
606
+	if(head!=NULL) {
607
+		if(ltail_last) {
608
+			ltail_last->next = *head;
609
+		}
610
+		*head = lhead;
611
+	} else {
612
+		if(ltail_last) {
613
+			ltail_last->next = *_xavp_list_crt;
614
+		}
615
+		*_xavp_list_crt = lhead;
616
+	}
617
+
618
+	return 0;
619
+}
620
+
522 621
 void xavp_destroy_list_unsafe(sr_xavp_t **head)
523 622
 {
524 623
 	sr_xavp_t *avp, *foo;
Browse code

core: xavp - safety checks for name len

Daniel-Constantin Mierla authored on 13/05/2021 15:41:40
Showing 1 changed files
... ...
@@ -106,7 +106,7 @@ static sr_xavp_t *xavp_new_value(str *name, sr_xval_t *val)
106 106
 	int size;
107 107
 	unsigned int id;
108 108
 
109
-	if(name==NULL || name->s==NULL || val==NULL)
109
+	if(name==NULL || name->s==NULL || name->len<=0 || val==NULL)
110 110
 		return NULL;
111 111
 	id = get_hash1_raw(name->s, name->len);
112 112
 
... ...
@@ -427,7 +427,7 @@ static int xavp_rm_internal(str *name, sr_xavp_t **head, int idx)
427 427
 	int n=0;
428 428
 	int count=0;
429 429
 
430
-	if(name==NULL || name->s==NULL)
430
+	if(name==NULL || name->s==NULL || name->len<=0)
431 431
 		return 0;
432 432
 
433 433
 	id = get_hash1_raw(name->s, name->len);
... ...
@@ -498,7 +498,7 @@ int xavp_count(str *name, sr_xavp_t **start)
498 498
 	unsigned int id;
499 499
 	int n = 0;
500 500
 
501
-	if(name==NULL || name->s==NULL)
501
+	if(name==NULL || name->s==NULL || name->len<=0)
502 502
 		return -1;
503 503
 	id = get_hash1_raw(name->s, name->len);
504 504
 
... ...
@@ -865,7 +865,7 @@ sr_xavp_t *xavp_extract(str *name, sr_xavp_t **list)
865 865
 	sr_xavp_t *prv = 0;
866 866
 	unsigned int id;
867 867
 
868
-	if(name==NULL || name->s==NULL) {
868
+	if(name==NULL || name->s==NULL || name->len<=0) {
869 869
 		if(list!=NULL) {
870 870
 			avp = *list;
871 871
 			if(avp!=NULL) {
... ...
@@ -1157,7 +1157,7 @@ static sr_xavp_t *xavu_get_internal(str *name, sr_xavp_t **list, sr_xavp_t **prv
1157 1157
 	sr_xavp_t *avu;
1158 1158
 	unsigned int id;
1159 1159
 
1160
-	if(name==NULL || name->s==NULL) {
1160
+	if(name==NULL || name->s==NULL || name->len<=0) {
1161 1161
 		return NULL;
1162 1162
 	}
1163 1163
 
... ...
@@ -1235,7 +1235,7 @@ int xavu_rm_by_name(str *name, sr_xavp_t **head)
1235 1235
 	unsigned int id;
1236 1236
 
1237 1237
 
1238
-	if(name==NULL || name->s==NULL) {
1238
+	if(name==NULL || name->s==NULL || name->len<=0) {
1239 1239
 		return -1;
1240 1240
 	}
1241 1241
 
... ...
@@ -1579,7 +1579,7 @@ static sr_xavp_t *xavi_new_value(str *name, sr_xval_t *val)
1579 1579
 	int size;
1580 1580
 	unsigned int id;
1581 1581
 
1582
-	if(name==NULL || name->s==NULL || val==NULL)
1582
+	if(name==NULL || name->s==NULL || name->len<=0 || val==NULL)
1583 1583
 		return NULL;
1584 1584
 	id = get_hash1_case_raw(name->s, name->len);
1585 1585
 
... ...
@@ -1812,7 +1812,7 @@ static sr_xavp_t *xavi_get_internal(str *name, sr_xavp_t **list, int idx, sr_xav
1812 1812
 	unsigned int id;
1813 1813
 	int n = 0;
1814 1814
 
1815
-	if(name==NULL || name->s==NULL)
1815
+	if(name==NULL || name->s==NULL || name->len<=0)
1816 1816
 		return NULL;
1817 1817
 	id = get_hash1_case_raw(name->s, name->len);
1818 1818
 
... ...
@@ -1939,7 +1939,7 @@ static int xavi_rm_internal(str *name, sr_xavp_t **head, int idx)
1939 1939
 	int n=0;
1940 1940
 	int count=0;
1941 1941
 
1942
-	if(name==NULL || name->s==NULL)
1942
+	if(name==NULL || name->s==NULL || name->len<=0)
1943 1943
 		return 0;
1944 1944
 
1945 1945
 	id = get_hash1_case_raw(name->s, name->len);
... ...
@@ -2022,7 +2022,7 @@ int xavi_count(str *name, sr_xavp_t **start)
2022 2022
 	unsigned int id;
2023 2023
 	int n = 0;
2024 2024
 
2025
-	if(name==NULL || name->s==NULL)
2025
+	if(name==NULL || name->s==NULL || name->len<=0)
2026 2026
 		return -1;
2027 2027
 	id = get_hash1_case_raw(name->s, name->len);
2028 2028
 
... ...
@@ -2315,7 +2315,7 @@ sr_xavp_t *xavi_extract(str *name, sr_xavp_t **list)
2315 2315
 	sr_xavp_t *prv = 0;
2316 2316
 	unsigned int id;
2317 2317
 
2318
-	if(name==NULL || name->s==NULL) {
2318
+	if(name==NULL || name->s==NULL || name->len<=0) {
2319 2319
 		if(list!=NULL) {
2320 2320
 			avi = *list;
2321 2321
 			if(avi!=NULL) {
Browse code

core: $xavu() helper functions to get child values

- like for xavp and xavi

Daniel-Constantin Mierla authored on 01/04/2021 05:56:30
Showing 1 changed files
... ...
@@ -1448,6 +1448,56 @@ sr_xavp_t *xavu_set_child_sval(str *rname, str *cname, str *sval)
1448 1448
 	return xavu_set_child_xval(rname, cname, &xval);
1449 1449
 }
1450 1450
 
1451
+/**
1452
+ * return child node of an xavp
1453
+ * - $xavu(rname=>cname)
1454
+ */
1455
+sr_xavp_t* xavu_get_child(str *rname, str *cname)
1456
+{
1457
+	sr_xavp_t *ravp=NULL;
1458
+
1459
+	ravp = xavu_get(rname, NULL);
1460
+	if(ravp==NULL || ravp->val.type!=SR_XTYPE_XAVP)
1461
+		return NULL;
1462
+
1463
+	return xavu_get(cname, ravp->val.v.xavp);
1464
+}
1465
+
1466
+
1467
+/**
1468
+ * return child node of an xavp if it has int value
1469
+ * - $xavu(rname=>cname)
1470
+ */
1471
+sr_xavp_t* xavu_get_child_with_ival(str *rname, str *cname)
1472
+{
1473
+	sr_xavp_t *vavp=NULL;
1474
+
1475
+	vavp = xavu_get_child(rname, cname);
1476
+
1477
+	if(vavp==NULL || vavp->val.type!=SR_XTYPE_INT)
1478
+		return NULL;
1479
+
1480
+	return vavp;
1481
+}
1482
+
1483
+
1484
+/**
1485
+ * return child node of an xavp if it has string value
1486
+ * - $xavu(rname=>cname)
1487
+ */
1488
+sr_xavp_t* xavu_get_child_with_sval(str *rname, str *cname)
1489
+{
1490
+	sr_xavp_t *vavp=NULL;
1491
+
1492
+	vavp = xavu_get_child(rname, cname);
1493
+
1494
+	if(vavp==NULL || vavp->val.type!=SR_XTYPE_STR)
1495
+		return NULL;
1496
+
1497
+	return vavp;
1498
+}
1499
+
1500
+
1451 1501
 /**
1452 1502
  * serialize the values in subfields of an xavu in name=value; format
1453 1503
  * - rname - name of the root list xavu
Browse code

core: fix to xavp_rm_internal (#2604)

This fixes the following issue:
https://github.com/kamailio/kamailio/issues/2604

Description of the issue:

When called to remove a specific index from a given xavp, function xavp_rm_by_index removes the index (as expected) but also all others before it.

E.g :
If called with idx = 1, it removes indexes 0 and 1.
Likewise if invoked with idx = 2 => the first 3 elements are removed.

This bug is located in function xavp_rm_internal. An assignment was missing when looping over the xavp list.
Same for xavi_rm_internal.

Nicolas C authored on 22/01/2021 14:16:56
Showing 1 changed files
... ...
@@ -454,6 +454,8 @@ static int xavp_rm_internal(str *name, sr_xavp_t **head, int idx)
454 454
 				if(idx>=0)
455 455
 					return 1;
456 456
 				count++;
457
+			} else {
458
+				prv = foo;
457 459
 			}
458 460
 			n++;
459 461
 		} else {
... ...
@@ -1914,6 +1916,8 @@ static int xavi_rm_internal(str *name, sr_xavp_t **head, int idx)
1914 1916
 				if(idx>=0)
1915 1917
 					return 1;
1916 1918
 				count++;
1919
+			} else {
1920
+				prv = foo;
1917 1921
 			}
1918 1922
 			n++;
1919 1923
 		} else {
Browse code

core: added xavu_serialize_fields function (#2603)

* core: added xavu_serialize_fields function

Also added a function called by the three "*_serialize_fields" to reduce code duplication.

The interface is not modified.

* Revert refactoring

We can add xavu_serialize_fields, but do not change the other functions.

Nicolas C authored on 18/01/2021 16:36:12 • GitHub committed on 18/01/2021 16:36:12
Showing 1 changed files
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com) 
2
+ * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com)
3 3
  *
4 4
  * Permission to use, copy, modify, and distribute this software for any
5 5
  * purpose with or without fee is hereby granted, provided that the above
... ...
@@ -1446,6 +1446,69 @@ sr_xavp_t *xavu_set_child_sval(str *rname, str *cname, str *sval)
1446 1446
 	return xavu_set_child_xval(rname, cname, &xval);
1447 1447
 }
1448 1448
 
1449
+/**
1450
+ * serialize the values in subfields of an xavu in name=value; format
1451
+ * - rname - name of the root list xavu
1452
+ * - obuf - buffer were to write the output
1453
+ * - olen - the size of obuf
1454
+ * return: 0 - not found; -1 - error; >0 - length of output
1455
+ */
1456
+int xavu_serialize_fields(str *rname, char *obuf, int olen)
1457
+{
1458
+	sr_xavp_t *ravu = NULL;
1459
+	sr_xavp_t *avu = NULL;
1460
+	str ostr;
1461
+	int rlen;
1462
+
1463
+	ravu = xavu_get(rname, NULL);
1464
+	if(ravu==NULL || ravu->val.type!=SR_XTYPE_XAVP) {
1465
+		/* not found or not holding subfields */
1466
+		return 0;
1467
+	}
1468
+
1469
+	rlen = 0;
1470
+	ostr.s = obuf;
1471
+	avu = ravu->val.v.xavp;
1472
+	while(avu) {
1473
+		switch(avu->val.type) {
1474
+			case SR_XTYPE_INT:
1475
+				LM_DBG("     XAVP int value: %d\n", avu->val.v.i);
1476
+				ostr.len = snprintf(ostr.s, olen-rlen, "%.*s=%u;",
1477
+						avu->name.len, avu->name.s, (unsigned int)avu->val.v.i);
1478
+				if(ostr.len<=0 || ostr.len>=olen-rlen) {
1479
+					LM_ERR("failed to serialize int value (%d/%d\n",
1480
+							ostr.len, olen-rlen);
1481
+					return -1;
1482
+				}
1483
+			break;
1484
+			case SR_XTYPE_STR:
1485
+				LM_DBG("     XAVP str value: %s\n", avu->val.v.s.s);
1486
+				if(avu->val.v.s.len == 0) {
1487
+					ostr.len = snprintf(ostr.s, olen-rlen, "%.*s;",
1488
+						avu->name.len, avu->name.s);
1489
+				} else {
1490
+					ostr.len = snprintf(ostr.s, olen-rlen, "%.*s=%.*s;",
1491
+						avu->name.len, avu->name.s,
1492
+						avu->val.v.s.len, avu->val.v.s.s);
1493
+				}
1494
+				if(ostr.len<=0 || ostr.len>=olen-rlen) {
1495
+					LM_ERR("failed to serialize int value (%d/%d\n",
1496
+							ostr.len, olen-rlen);
1497
+					return -1;
1498
+				}
1499
+			break;
1500
+			default:
1501
+				LM_DBG("skipping value type: %d\n", avu->val.type);
1502
+				ostr.len = 0;
1503
+		}
1504
+		if(ostr.len>0) {
1505
+			ostr.s += ostr.len;
1506
+			rlen += ostr.len;
1507
+		}
1508
+		avu = avu->next;
1509
+	}
1510
+	return rlen;
1511
+}
1449 1512
 
1450 1513
 /**
1451 1514
  *
Browse code

core: xavi api - like xavp but with insensitive case names

$xavi(WhatEver=>FOo) == $xavi(whatever=>foO)

Victor Seva authored on 26/05/2020 09:24:53
Showing 1 changed files
... ...
@@ -39,6 +39,11 @@ static sr_xavp_t *_xavu_list_head = 0;
39 39
 /*! Pointer to XAVP current list */
40 40
 static sr_xavp_t **_xavu_list_crt = &_xavu_list_head;
41 41
 
42
+/*! XAVI list head */
43
+static sr_xavp_t *_xavi_list_head = 0;
44
+/*! Pointer to XAVI current list */
45
+static sr_xavp_t **_xavi_list_crt = &_xavi_list_head;
46
+
42 47
 /*! Helper functions */
43 48
 static sr_xavp_t *xavp_get_internal(str *name, sr_xavp_t **list, int idx, sr_xavp_t **prv);
44 49
 static int xavp_rm_internal(str *name, sr_xavp_t **head, int idx);
... ...
@@ -1440,3 +1445,985 @@ sr_xavp_t *xavu_set_child_sval(str *rname, str *cname, str *sval)
1440 1445
 
1441 1446
 	return xavu_set_child_xval(rname, cname, &xval);
1442 1447
 }
1448
+
1449
+
1450
+/**
1451
+ *
1452
+ */
1453
+/*** XAVI - eXtended Attribute Value Insensitive case - implementation ***/
1454
+/*! Helper functions */
1455
+static sr_xavp_t *xavi_get_internal(str *name, sr_xavp_t **list, int idx, sr_xavp_t **prv);
1456
+static int xavi_rm_internal(str *name, sr_xavp_t **head, int idx);
1457
+
1458
+/**
1459
+ *
1460
+ */
1461
+static sr_xavp_t *xavi_new_value(str *name, sr_xval_t *val)
1462
+{
1463
+	sr_xavp_t *avi;
1464
+	int size;
1465
+	unsigned int id;
1466
+
1467
+	if(name==NULL || name->s==NULL || val==NULL)
1468
+		return NULL;
1469
+	id = get_hash1_case_raw(name->s, name->len);
1470
+
1471
+	size = sizeof(sr_xavp_t) + name->len + 1;
1472
+	if(val->type == SR_XTYPE_STR)
1473
+		size += val->v.s.len + 1;
1474
+	avi = (sr_xavp_t*)shm_malloc(size);
1475
+	if(avi==NULL) {
1476
+		SHM_MEM_ERROR;
1477
+		return NULL;
1478
+	}
1479
+	memset(avi, 0, size);
1480
+	avi->id = id;
1481
+	avi->name.s = (char*)avi + sizeof(sr_xavp_t);
1482
+	memcpy(avi->name.s, name->s, name->len);
1483
+	avi->name.s[name->len] = '\0';
1484
+	avi->name.len = name->len;
1485
+	memcpy(&avi->val, val, sizeof(sr_xval_t));
1486
+	if(val->type == SR_XTYPE_STR)
1487
+	{
1488
+		avi->val.v.s.s = avi->name.s + avi->name.len + 1;
1489
+		memcpy(avi->val.v.s.s, val->v.s.s, val->v.s.len);
1490
+		avi->val.v.s.s[val->v.s.len] = '\0';
1491
+		avi->val.v.s.len = val->v.s.len;
1492
+	}
1493
+
1494
+	return avi;
1495
+}
1496
+
1497
+/**
1498
+ *
1499
+ */
1500
+int xavi_add(sr_xavp_t *xavi, sr_xavp_t **list)
1501
+{
1502
+	if (xavi==NULL) {
1503
+		return -1;
1504
+	}
1505
+	/* Prepend new xavi to the list */
1506
+	if(list) {
1507
+		xavi->next = *list;
1508
+		*list = xavi;
1509
+	} else {
1510
+		xavi->next = *_xavi_list_crt;
1511
+		*_xavi_list_crt = xavi;
1512
+	}
1513
+
1514
+	return 0;
1515
+}
1516
+
1517
+/**
1518
+ *
1519
+ */
1520
+int xavi_add_last(sr_xavp_t *xavi, sr_xavp_t **list)
1521
+{
1522
+	sr_xavp_t *prev;
1523
+	sr_xavp_t *crt;
1524
+
1525
+	if (xavi==NULL) {
1526
+		return -1;
1527
+	}
1528
+
1529
+	crt = xavi_get_internal(&xavi->name, list, 0, 0);
1530
+
1531
+	prev = NULL;
1532
+
1533
+	while(crt) {
1534
+		prev = crt;
1535
+		crt = xavi_get_next(prev);
1536
+	}
1537
+
1538
+	if(prev==NULL) {
1539
+		/* Prepend new xavi to the list */
1540
+		if(list) {
1541
+			xavi->next = *list;
1542
+			*list = xavi;
1543
+		} else {
1544
+			xavi->next = *_xavi_list_crt;
1545
+			*_xavi_list_crt = xavi;
1546
+		}
1547
+	} else {
1548
+		xavi->next = prev->next;
1549
+		prev->next = xavi;
1550
+	}
1551
+
1552
+	return 0;
1553
+}
1554
+
1555
+/**
1556
+ *
1557
+ */
1558
+int xavi_add_after(sr_xavp_t *nxavi, sr_xavp_t *pxavi)
1559
+{
1560
+	if (nxavi==NULL) {
1561
+		return -1;
1562
+	}
1563
+
1564
+	if(pxavi==NULL) {
1565
+		nxavi->next = *_xavi_list_crt;
1566
+		*_xavi_list_crt = nxavi;
1567
+	} else {
1568
+		nxavi->next = pxavi->next;
1569
+		pxavi->next = nxavi;
1570
+	}
1571
+
1572
+	return 0;
1573
+}
1574
+
1575
+/**
1576
+ *
1577
+ */
1578
+sr_xavp_t *xavi_add_value(str *name, sr_xval_t *val, sr_xavp_t **list)
1579
+{
1580
+	sr_xavp_t *avi=0;
1581
+
1582
+	avi = xavi_new_value(name, val);
1583
+	if (avi==NULL)
1584
+		return NULL;
1585
+
1586
+	/* Prepend new value to the list */
1587
+	if(list) {
1588
+		avi->next = *list;
1589
+		*list = avi;
1590
+	} else {
1591
+		avi->next = *_xavi_list_crt;
1592
+		*_xavi_list_crt = avi;
1593
+	}
1594
+
1595
+	return avi;
1596
+}
1597
+
1598
+/**
1599
+ *
1600
+ */
1601
+sr_xavp_t *xavi_add_value_after(str *name, sr_xval_t *val, sr_xavp_t *pxavi)
1602
+{
1603
+	sr_xavp_t *avi=0;
1604
+
1605
+	avi = xavi_new_value(name, val);
1606
+	if (avi==NULL)
1607
+		return NULL;
1608
+
1609
+	/* link new xavi */
1610
+	if(pxavi) {
1611
+		avi->next = pxavi->next;
1612
+		pxavi->next = avi;
1613
+	} else {
1614
+		avi->next = *_xavi_list_crt;
1615
+		*_xavi_list_crt = avi;
1616
+	}
1617
+
1618
+	return avi;
1619
+}
1620
+
1621
+/**
1622
+ *
1623
+ */
1624
+sr_xavp_t *xavi_add_xavi_value(str *rname, str *name, sr_xval_t *val, sr_xavp_t **list)
1625
+{
1626
+	sr_xavp_t *ravi=0;
1627
+	sr_xavp_t *cavi=0;
1628
+	sr_xval_t rval;
1629
+
1630
+	cavi = xavi_new_value(name, val);
1631
+	if (cavi==NULL)
1632
+		return NULL;
1633
+
1634
+	memset(&rval, 0, sizeof(sr_xval_t));
1635
+	rval.type = SR_XTYPE_XAVP;
1636
+	rval.v.xavp = cavi;
1637
+
1638
+	ravi = xavi_new_value(rname, &rval);
1639
+	if (ravi==NULL) {
1640
+		xavi_destroy_list(&cavi);
1641
+		return NULL;
1642
+	}
1643
+
1644
+	/* Prepend new value to the list */
1645
+	if(list) {
1646
+		ravi->next = *list;
1647
+		*list = ravi;
1648
+	} else {
1649
+		ravi->next = *_xavi_list_crt;
1650
+		*_xavi_list_crt = ravi;
1651
+	}
1652
+
1653
+	return ravi;
1654
+}
1655
+
1656
+/**
1657
+ *
1658
+ */
1659
+sr_xavp_t *xavi_set_value(str *name, int idx, sr_xval_t *val, sr_xavp_t **list)
1660
+{
1661
+	sr_xavp_t *avi;
1662
+	sr_xavp_t *cur;
1663
+	sr_xavp_t *prv=0;
1664
+
1665
+	if(val==NULL)
1666
+		return NULL;
1667
+
1668
+	/* Find the current value */
1669
+	cur = xavi_get_internal(name, list, idx, &prv);
1670
+	if(cur==NULL)
1671
+		return NULL;
1672
+
1673
+	avi = xavi_new_value(name, val);
1674
+	if (avi==NULL)
1675
+		return NULL;
1676
+
1677
+	/* Replace the current value with the new */
1678
+	avi->next = cur->next;
1679
+	if(prv)
1680
+		prv->next = avi;
1681
+	else if(list)
1682
+		*list = avi;
1683
+	else
1684
+		*_xavi_list_crt = avi;
1685
+
1686
+	xavi_free(cur);
1687
+
1688
+	return avi;
1689
+}
1690
+
1691
+/**
1692
+ *
1693
+ */
1694
+static sr_xavp_t *xavi_get_internal(str *name, sr_xavp_t **list, int idx, sr_xavp_t **prv)
1695
+{
1696
+	sr_xavp_t *avi;
1697
+	unsigned int id;
1698
+	int n = 0;
1699
+
1700
+	if(name==NULL || name->s==NULL)
1701
+		return NULL;
1702
+	id = get_hash1_case_raw(name->s, name->len);
1703
+
1704
+	if(list && *list)
1705
+		avi = *list;
1706
+	else
1707
+		avi = *_xavi_list_crt;
1708
+	while(avi)
1709
+	{
1710
+		if(avi->id==id && avi->name.len==name->len
1711
+				&& strncasecmp(avi->name.s, name->s, name->len)==0)
1712
+		{
1713
+			if(idx==n)
1714
+				return avi;
1715
+			n++;
1716
+		}
1717
+		if(prv)
1718
+			*prv = avi;
1719
+		avi = avi->next;
1720
+	}
1721
+	return NULL;
1722
+}
1723
+
1724
+/**
1725
+ *
1726
+ */
1727
+sr_xavp_t *xavi_get(str *name, sr_xavp_t *start)
1728
+{
1729
+	return xavi_get_internal(name, (start)?&start:NULL, 0, NULL);
1730
+}
1731
+
1732
+/**
1733
+ *
1734
+ */
1735
+sr_xavp_t *xavi_get_by_index(str *name, int idx, sr_xavp_t **start)
1736
+{
1737
+	return xavi_get_internal(name, start, idx, NULL);
1738
+}
1739
+
1740
+/**
1741
+ *
1742
+ */
1743
+sr_xavp_t *xavi_get_next(sr_xavp_t *start)
1744
+{
1745
+	sr_xavp_t *avi;
1746
+
1747
+	if(start==NULL)
1748
+		return NULL;
1749
+
1750
+	avi = start->next;
1751
+	while(avi)
1752
+	{
1753
+		if(avi->id==start->id && avi->name.len==start->name.len
1754
+				&& strncasecmp(avi->name.s, start->name.s, start->name.len)==0)
1755
+			return avi;
1756
+		avi=avi->next;
1757
+	}
1758
+
1759
+	return NULL;
1760
+}
1761
+
1762
+/**
1763
+ *
1764
+ */
1765
+sr_xavp_t *xavi_get_last(str *xname, sr_xavp_t **list)
1766
+{
1767
+	sr_xavp_t *prev;
1768
+	sr_xavp_t *crt;
1769
+
1770
+	crt = xavi_get_internal(xname, list, 0, 0);
1771
+
1772
+	prev = NULL;
1773
+
1774
+	while(crt) {
1775
+		prev = crt;
1776
+		crt = xavi_get_next(prev);
1777
+	}
1778
+
1779
+	return prev;
1780
+}
1781
+
1782
+/**
1783
+ *
1784
+ */
1785
+int xavi_rm(sr_xavp_t *xa, sr_xavp_t **head)
1786
+{
1787
+	sr_xavp_t *avi;
1788
+	sr_xavp_t *prv=0;
1789
+
1790
+	if(head!=NULL)
1791
+		avi = *head;
1792
+	else
1793
+		avi=*_xavi_list_crt;
1794
+
1795
+	while(avi)
1796
+	{
1797
+		if(avi==xa)
1798
+		{
1799
+			if(prv)
1800
+				prv->next=avi->next;
1801
+			else if(head!=NULL)
1802
+				*head = avi->next;
1803
+			else
1804
+				*_xavi_list_crt = avi->next;
1805
+			xavi_free(avi);
1806
+			return 1;
1807
+		}
1808
+		prv=avi; avi=avi->next;
1809
+	}
1810
+	return 0;
1811
+}
1812
+
1813
+/* Remove xavis
1814
+ * idx: <0 remove all xavis with the same name
1815
+ *      >=0 remove only the specified index xavi
1816
+ * Returns number of xavis that were deleted
1817
+ */
1818
+static int xavi_rm_internal(str *name, sr_xavp_t **head, int idx)
1819
+{
1820
+	sr_xavp_t *avi;
1821
+	sr_xavp_t *foo;
1822
+	sr_xavp_t *prv=0;
1823
+	unsigned int id;
1824
+	int n=0;
1825
+	int count=0;
1826
+
1827
+	if(name==NULL || name->s==NULL)
1828
+		return 0;
1829
+
1830
+	id = get_hash1_case_raw(name->s, name->len);
1831
+	if(head!=NULL)
1832
+		avi = *head;
1833
+	else
1834
+		avi = *_xavi_list_crt;
1835
+	while(avi)
1836
+	{
1837
+		foo = avi;
1838
+		avi=avi->next;
1839
+		if(foo->id==id && foo->name.len==name->len
1840
+				&& strncasecmp(foo->name.s, name->s, name->len)==0)
1841
+		{
1842
+			if(idx<0 || idx==n)
1843
+			{
1844
+				if(prv!=NULL)
1845
+					prv->next=foo->next;
1846
+				else if(head!=NULL)
1847
+					*head = foo->next;
1848
+				else
1849
+					*_xavi_list_crt = foo->next;
1850
+				xavi_free(foo);
1851
+				if(idx>=0)
1852
+					return 1;
1853
+				count++;
1854
+			}
1855
+			n++;
1856
+		} else {
1857
+			prv = foo;
1858
+		}
1859
+	}
1860
+	return count;
1861
+}
1862
+
1863
+/**
1864
+ *
1865
+ */
1866
+int xavi_rm_by_name(str *name, int all, sr_xavp_t **head)
1867
+{
1868
+	return xavi_rm_internal(name, head, -1*all);
1869
+}
1870
+
1871
+/**
1872
+ *
1873
+ */
1874
+int xavi_rm_by_index(str *name, int idx, sr_xavp_t **head)
1875
+{
1876
+	if (idx<0)
1877
+		return 0;
1878
+	return xavi_rm_internal(name, head, idx);
1879
+}
1880
+
1881
+/**
1882
+ *
1883
+ */
1884
+int xavi_rm_child_by_index(str *rname, str *cname, int idx)
1885
+{
1886
+	sr_xavp_t *avi=NULL;
1887
+
1888
+	if (idx<0) {
1889
+		return 0;
1890
+	}
1891
+	avi = xavi_get(rname, NULL);
1892
+
1893
+	if(avi == NULL || avi->val.type!=SR_XTYPE_XAVP) {
1894
+		return 0;
1895
+	}
1896
+	return xavi_rm_internal(cname, &avi->val.v.xavp, idx);
1897
+}
1898
+
1899
+/**
1900
+ *
1901
+ */
1902
+int xavi_count(str *name, sr_xavp_t **start)
1903
+{
1904
+	sr_xavp_t *avi;
1905
+	unsigned int id;
1906
+	int n = 0;
1907
+
1908
+	if(name==NULL || name->s==NULL)
1909
+		return -1;
1910
+	id = get_hash1_case_raw(name->s, name->len);
1911
+
1912
+	if(start)
1913
+		avi = *start;
1914
+	else
1915
+		avi=*_xavi_list_crt;
1916
+	while(avi)
1917
+	{
1918
+		if(avi->id==id && avi->name.len==name->len
1919
+				&& strncasecmp(avi->name.s, name->s, name->len)==0)
1920
+		{
1921
+			n++;
1922
+		}
1923
+		avi=avi->next;
1924
+	}
1925
+
1926
+	return n;
1927
+}
1928
+
1929
+/**
1930
+ *
1931
+ */
1932
+void xavi_reset_list(void)
1933
+{
1934
+	assert(_xavi_list_crt!=0 );
1935
+
1936
+	if (_xavi_list_crt!=&_xavi_list_head)
1937
+		_xavi_list_crt=&_xavi_list_head;
1938
+	xavi_destroy_list(_xavi_list_crt);
1939
+}
1940
+
1941
+/**
1942
+ *
1943
+ */
1944
+sr_xavp_t **xavi_set_list(sr_xavp_t **head)
1945
+{
1946
+	sr_xavp_t **avi;
1947
+
1948
+	assert(_xavi_list_crt!=0);
1949
+
1950
+	avi = _xavi_list_crt;
1951
+	_xavi_list_crt = head;
1952
+	return avi;
1953
+}
1954
+
1955
+/**
1956
+ *
1957
+ */
1958
+sr_xavp_t **xavi_get_crt_list(void)
1959
+{
1960
+	assert(_xavi_list_crt!=0);
1961
+	return _xavi_list_crt;
1962
+}
1963
+
1964
+/**
1965
+ *
1966
+ */
1967
+void xavi_print_list_content(sr_xavp_t **head, int level)
1968
+{
1969
+	xavx_print_list_content("XAVI", head, _xavi_list_crt, level);
1970
+}
1971
+
1972
+/**
1973
+ *
1974
+ */
1975
+void xavi_print_list(sr_xavp_t **head)
1976
+{
1977
+	xavi_print_list_content(head, 0);
1978
+}
1979
+
1980
+/**
1981
+ * returns a list of str with key names.
1982
+ * Example:
1983
+ * If we have this structure
1984
+ * $xavi(test=>one) = 1
1985