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 2 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
+ * $xavi(test[0]=>two) = "2"
1986
+ * $xavi(test[0]=>three) = 3
1987
+ * $xavi(test[0]=>four) = $xavp(whatever)
1988
+ * $xavi(test[0]=>two) = "other 2"
1989
+ *
1990
+ * xavi_get_list_keys_names(test[0]) returns
1991
+ * {"one", "two", "three", "four"}
1992
+ *
1993
+ * free the struct str_list afterwards
1994
+ * but do *NOT* free the strings inside
1995
+ */
1996
+struct str_list *xavi_get_list_key_names(sr_xavp_t *xavi)
1997
+{
1998
+	sr_xavp_t *avi = NULL;
1999
+	struct str_list *result = NULL;
2000
+	struct str_list *r = NULL;
2001
+	struct str_list *f = NULL;
2002
+	int total = 0;
2003
+
2004
+	if(xavi==NULL){
2005
+		LM_ERR("xavi is NULL\n");
2006
+		return 0;
2007
+	}
2008
+
2009
+	if(xavi->val.type!=SR_XTYPE_XAVP){
2010
+		LM_ERR("%s not xavp?\n", xavi->name.s);
2011
+		return 0;
2012
+	}
2013
+
2014
+	avi = xavi->val.v.xavp;
2015
+
2016
+	if (avi)
2017
+	{
2018
+		result = (struct str_list*)pkg_malloc(sizeof(struct str_list));
2019
+		if (result==NULL) {
2020
+			PKG_MEM_ERROR;
2021
+			return 0;
2022
+		}
2023
+		r = result;
2024
+		r->s.s = avi->name.s;
2025
+		r->s.len = avi->name.len;
2026
+		r->next = NULL;
2027
+		avi = avi->next;
2028
+	}
2029
+
2030
+	while(avi)
2031
+	{
2032
+		f = result;
2033
+		while(f)
2034
+		{
2035
+			if((avi->name.len==f->s.len)&&
2036
+				(strncasecmp(avi->name.s, f->s.s, f->s.len)==0))
2037
+			{
2038
+				break; /* name already on list */
2039
+			}
2040
+			f = f->next;
2041
+		}
2042
+		if (f==NULL)
2043
+		{
2044
+			r = append_str_list(avi->name.s, avi->name.len, &r, &total);
2045
+			if(r==NULL){
2046
+				while(result){
2047
+					r = result;
2048
+					result = result->next;
2049
+					pkg_free(r);
2050
+				}
2051
+				return 0;
2052
+			}
2053
+		}
2054
+		avi = avi->next;
2055
+	}
2056
+	return result;
2057
+}
2058
+
2059
+sr_xavp_t *xavi_clone_level_nodata(sr_xavp_t *xold)
2060
+{
2061
+	return xavi_clone_level_nodata_with_new_name(xold, &xold->name);
2062
+}
2063
+
2064
+/**
2065
+ * clone the xavi without values that are custom data
2066
+ * - only one list level is cloned, other sublists are ignored
2067
+ */
2068
+sr_xavp_t *xavi_clone_level_nodata_with_new_name(sr_xavp_t *xold, str *dst_name)
2069
+{
2070
+	sr_xavp_t *xnew = NULL;
2071
+	sr_xavp_t *navi = NULL;
2072
+	sr_xavp_t *oavi = NULL;
2073
+	sr_xavp_t *pavi = NULL;
2074
+
2075
+	if(xold == NULL)
2076
+	{
2077
+		return NULL;
2078
+	}
2079
+	if(xold->val.type==SR_XTYPE_DATA || xold->val.type==SR_XTYPE_SPTR)
2080
+	{
2081
+		LM_INFO("xavi value type is 'data' - ignoring in clone\n");
2082
+		return NULL;
2083
+	}
2084
+	xnew = xavi_new_value(dst_name, &xold->val);
2085
+	if(xnew==NULL)
2086
+	{
2087
+		LM_ERR("cannot create cloned root xavi\n");
2088
+		return NULL;
2089
+	}
2090
+	LM_DBG("cloned root xavi [%.*s] >> [%.*s]\n", xold->name.len, xold->name.s, dst_name->len, dst_name->s);
2091
+
2092
+	if(xold->val.type!=SR_XTYPE_XAVP)
2093
+	{
2094
+		return xnew;
2095
+	}
2096
+
2097
+	xnew->val.v.xavp = NULL;
2098
+	oavi = xold->val.v.xavp;
2099
+
2100
+	while(oavi)
2101
+	{
2102
+		if(oavi->val.type!=SR_XTYPE_DATA && oavi->val.type!=SR_XTYPE_XAVP
2103
+				&& oavi->val.type!=SR_XTYPE_SPTR)
2104
+		{
2105
+			navi =  xavi_new_value(&oavi->name, &oavi->val);
2106
+			if(navi==NULL)
2107
+			{
2108
+				LM_ERR("cannot create cloned embedded xavi\n");
2109
+				if(xnew->val.v.xavp != NULL) {
2110
+					xavi_destroy_list(&xnew->val.v.xavp);
2111
+				}
2112
+				shm_free(xnew);
2113
+				return NULL;
2114
+			}
2115
+			LM_DBG("cloned inner xavi [%.*s]\n", oavi->name.len, oavi->name.s);
2116
+			if(xnew->val.v.xavp == NULL)
2117
+			{
2118
+				/* link to val in head xavi */
2119
+				xnew->val.v.xavp = navi;
2120
+			} else {
2121
+				/* link to prev xavi in the list */
2122
+				pavi->next = navi;
2123
+			}
2124
+			pavi = navi;
2125
+		}
2126
+		oavi = oavi->next;
2127
+	}
2128
+
2129
+	if(xnew->val.v.xavp == NULL)
2130
+	{
2131
+		shm_free(xnew);
2132
+		return NULL;
2133
+	}
2134
+
2135
+	return xnew;
2136
+}
2137
+
2138
+int xavi_insert(sr_xavp_t *xavi, int idx, sr_xavp_t **list)
2139
+{
2140
+	sr_xavp_t *crt = 0;
2141
+	sr_xavp_t *lst = 0;
2142
+	sr_xval_t val;
2143
+	int n = 0;
2144
+	int i = 0;
2145
+
2146
+	if(xavi==NULL) {
2147
+		return -1;
2148
+	}
2149
+
2150
+	crt = xavi_get_internal(&xavi->name, list, 0, NULL);
2151
+
2152
+	if (idx == 0 && (!crt || crt->val.type != SR_XTYPE_NULL))
2153
+		return xavi_add(xavi, list);
2154
+
2155
+	while(crt!=NULL && n<idx) {
2156
+		lst = crt;
2157
+		n++;
2158
+		crt = xavi_get_next(lst);
2159
+	}
2160
+
2161
+	if (crt && crt->val.type == SR_XTYPE_NULL) {
2162
+		xavi->next = crt->next;
2163
+		crt->next = xavi;
2164
+
2165
+		xavi_rm(crt, list);
2166
+		return 0;
2167
+	}
2168
+
2169
+	memset(&val, 0, sizeof(sr_xval_t));
2170
+	val.type = SR_XTYPE_NULL;
2171
+	for(i=0; i<idx-n; i++) {
2172
+		crt = xavi_new_value(&xavi->name, &val);
2173
+		if(crt==NULL)
2174
+			return -1;
2175
+		if (lst == NULL) {
2176
+			xavi_add(crt, list);
2177
+		} else {
2178
+			crt->next = lst->next;
2179
+			lst->next = crt;
2180
+		}
2181
+		lst = crt;
2182
+	}
2183
+
2184
+	if(lst==NULL) {
2185
+		LM_ERR("cannot link the xavi\n");
2186
+		return -1;
2187
+	}
2188
+	xavi->next = lst->next;
2189
+	lst->next = xavi;
2190
+
2191
+	return 0;
2192
+}
2193
+
2194
+sr_xavp_t *xavi_extract(str *name, sr_xavp_t **list)
2195
+{
2196
+	sr_xavp_t *avi = 0;
2197
+	sr_xavp_t *foo;
2198
+	sr_xavp_t *prv = 0;
2199
+	unsigned int id;
2200
+
2201
+	if(name==NULL || name->s==NULL) {
2202
+		if(list!=NULL) {
2203
+			avi = *list;
2204
+			if(avi!=NULL) {
2205
+				*list = avi->next;
2206
+				avi->next = NULL;
2207
+			}
2208
+		} else {
2209
+			avi = *_xavi_list_crt;
2210
+			if(avi!=NULL) {
2211
+				*_xavi_list_crt = avi->next;
2212
+				avi->next = NULL;
2213
+			}
2214
+		}
2215
+
2216
+		return avi;
2217
+	}
2218
+
2219
+	id = get_hash1_case_raw(name->s, name->len);
2220
+	if(list!=NULL)
2221
+		avi = *list;
2222
+	else
2223
+		avi = *_xavi_list_crt;
2224
+	while(avi)
2225
+	{
2226
+		foo = avi;
2227
+		avi=avi->next;
2228
+		if(foo->id==id && foo->name.len==name->len
2229
+				&& strncasecmp(foo->name.s, name->s, name->len)==0)
2230
+		{
2231
+			if(prv!=NULL)
2232
+				prv->next=foo->next;
2233
+			else if(list!=NULL)
2234
+				*list = foo->next;
2235
+			else
2236
+				*_xavi_list_crt = foo->next;
2237
+			foo->next = NULL;
2238
+			return foo;
2239
+		} else {
2240
+			prv = foo;
2241
+		}
2242
+	}
2243
+	return NULL;
2244
+}
2245
+
2246
+/**
2247
+ * return child node of an xavi
2248
+ * - $xavi(rname=>cname)
2249
+ */
2250
+sr_xavp_t* xavi_get_child(str *rname, str *cname)
2251
+{
2252
+	sr_xavp_t *ravi=NULL;
2253
+
2254
+	ravi = xavi_get(rname, NULL);
2255
+	if(ravi==NULL || ravi->val.type!=SR_XTYPE_XAVP)
2256
+		return NULL;
2257
+
2258
+	return xavi_get(cname, ravi->val.v.xavp);
2259
+}
2260
+
2261
+
2262
+/**
2263
+ * return child node of an xavi if it has int value
2264
+ * - $xavi(rname=>cname)
2265
+ */
2266
+sr_xavp_t* xavi_get_child_with_ival(str *rname, str *cname)
2267
+{
2268
+	sr_xavp_t *vavi=NULL;
2269
+
2270
+	vavi = xavi_get_child(rname, cname);
2271
+
2272
+	if(vavi==NULL || vavi->val.type!=SR_XTYPE_INT)
2273
+		return NULL;
2274
+
2275
+	return vavi;
2276
+}
2277
+
2278
+
2279
+/**
2280
+ * return child node of an xavi if it has string value
2281
+ * - $xavi(rname=>cname)
2282
+ */
2283
+sr_xavp_t* xavi_get_child_with_sval(str *rname, str *cname)
2284
+{
2285
+	sr_xavp_t *vavi=NULL;
2286
+
2287
+	vavi = xavi_get_child(rname, cname);
2288
+
2289
+	if(vavi==NULL || vavi->val.type!=SR_XTYPE_STR)
2290
+		return NULL;
2291
+
2292
+	return vavi;
2293
+}
2294
+
2295
+/**
2296
+ * Set the value of the first xavi rname with first child xavi cname
2297
+ * - replace if it exits; add if it doesn't exist
2298
+ * - config operations:
2299
+ *   $xavi(rxname=>cname) = xval;
2300
+ *     or:
2301
+ *   $xavi(rxname[0]=>cname[0]) = xval;
2302
+ */
2303
+int xavi_set_child_xval(str *rname, str *cname, sr_xval_t *xval)
2304
+{
2305
+	sr_xavp_t *ravi=NULL;
2306
+	sr_xavp_t *cavi=NULL;
2307
+
2308
+	ravi = xavi_get(rname, NULL);
2309
+	if(ravi) {
2310
+		if(ravi->val.type != SR_XTYPE_XAVP) {
2311
+			/* first root xavi does not have xavi list value - remove it */
2312
+			xavi_rm(ravi, NULL);
2313
+			/* add a new xavi in the root list with a child */
2314
+			if(xavi_add_xavi_value(rname, cname, xval, NULL)==NULL) {
2315
+				return -1;
2316
+			}
2317
+		} else {
2318
+			/* first root xavi has an xavi list value */
2319
+			cavi = xavi_get(cname, ravi->val.v.xavp);
2320
+			if(cavi) {
2321
+				/* child xavi with same name - remove it */
2322
+				/* todo: update in place for int or if allocated size fits */
2323
+				xavi_rm(cavi, &ravi->val.v.xavp);
2324
+			}
2325
+			if(xavi_add_value(cname, xval, &ravi->val.v.xavp)==NULL) {
2326
+				return -1;
2327
+			}
2328
+		}
2329
+	} else {
2330
+		/* no xavi with rname in root list found */
2331
+		if(xavi_add_xavi_value(rname, cname, xval, NULL)==NULL) {
2332
+			return -1;
2333
+		}
2334
+	}
2335
+
2336
+	return 0;
2337
+}
2338
+
2339
+/**
2340
+ *
2341
+ */
2342
+int xavi_set_child_ival(str *rname, str *cname, int ival)
2343
+{
2344
+	sr_xval_t xval;
2345
+
2346
+	memset(&xval, 0, sizeof(sr_xval_t));
2347
+	xval.type = SR_XTYPE_INT;
2348
+	xval.v.i = ival;
2349
+
2350
+	return xavi_set_child_xval(rname, cname, &xval);
2351
+}
2352
+
2353
+/**
2354
+ *
2355
+ */
2356
+int xavi_set_child_sval(str *rname, str *cname, str *sval)
2357
+{
2358
+	sr_xval_t xval;
2359
+
2360
+	memset(&xval, 0, sizeof(sr_xval_t));
2361
+	xval.type = SR_XTYPE_STR;
2362
+	xval.v.s = *sval;
2363
+
2364
+	return xavi_set_child_xval(rname, cname, &xval);
2365
+}
2366
+
2367
+/**
2368
+ * serialize the values in subfields of an xavi in name=value; format
2369
+ * - rname - name of the root list xavi
2370
+ * - obuf - buffer were to write the output
2371
+ * - olen - the size of obuf
2372
+ * return: 0 - not found; -1 - error; >0 - length of output
2373
+ */
2374
+int xavi_serialize_fields(str *rname, char *obuf, int olen)
2375
+{
2376
+	sr_xavp_t *ravi = NULL;
2377
+	sr_xavp_t *avi = NULL;
2378
+	str ostr;
2379
+	int rlen;
2380
+
2381
+	ravi = xavi_get(rname, NULL);
2382
+	if(ravi==NULL || ravi->val.type!=SR_XTYPE_XAVP) {
2383
+		/* not found or not holding subfields */
2384
+		return 0;
2385
+	}
2386
+
2387
+	rlen = 0;
2388
+	ostr.s = obuf;
2389
+	avi = ravi->val.v.xavp;
2390
+	while(avi) {
2391
+		switch(avi->val.type) {
2392
+			case SR_XTYPE_INT:
2393
+				LM_DBG("     XAVP int value: %d\n", avi->val.v.i);
2394
+				ostr.len = snprintf(ostr.s, olen-rlen, "%.*s=%u;",
2395
+						avi->name.len, avi->name.s, (unsigned int)avi->val.v.i);
2396
+				if(ostr.len<=0 || ostr.len>=olen-rlen) {
2397
+					LM_ERR("failed to serialize int value (%d/%d\n",
2398
+							ostr.len, olen-rlen);
2399
+					return -1;
2400
+				}
2401
+			break;
2402
+			case SR_XTYPE_STR:
2403
+				LM_DBG("     XAVP str value: %s\n", avi->val.v.s.s);
2404
+				if(avi->val.v.s.len == 0) {
2405
+					ostr.len = snprintf(ostr.s, olen-rlen, "%.*s;",
2406
+						avi->name.len, avi->name.s);
2407
+				} else {
2408
+					ostr.len = snprintf(ostr.s, olen-rlen, "%.*s=%.*s;",
2409
+						avi->name.len, avi->name.s,
2410
+						avi->val.v.s.len, avi->val.v.s.s);
2411
+				}
2412
+				if(ostr.len<=0 || ostr.len>=olen-rlen) {
2413
+					LM_ERR("failed to serialize int value (%d/%d\n",
2414
+							ostr.len, olen-rlen);
2415
+					return -1;
2416
+				}
2417
+			break;
2418
+			default:
2419
+				LM_DBG("skipping value type: %d\n", avi->val.type);
2420
+				ostr.len = 0;
2421
+		}
2422
+		if(ostr.len>0) {
2423
+			ostr.s += ostr.len;
2424
+			rlen += ostr.len;
2425
+		}
2426
+		avi = avi->next;
2427
+	}
2428
+	return rlen;
2429
+}
... ...
@@ -132,4 +132,47 @@ sr_xavp_t *xavu_set_child_xval(str *rname, str *cname, sr_xval_t *xval);
132 132
 sr_xavp_t *xavu_set_child_ival(str *rname, str *cname, int ival);
133 133
 sr_xavp_t *xavu_set_child_sval(str *rname, str *cname, str *sval);
134 134
 
135
+/** xavi api */
136
+int xavi_init_head(void);
137
+#define xavi_free xavp_free
138
+
139
+int xavi_add(sr_xavp_t *xavp, sr_xavp_t **list);
140
+int xavi_add_last(sr_xavp_t *xavp, sr_xavp_t **list);
141
+int xavi_add_after(sr_xavp_t *nxavp, sr_xavp_t *pxavp);
142
+sr_xavp_t *xavi_add_value(str *name, sr_xval_t *val, sr_xavp_t **list);
143
+sr_xavp_t *xavi_add_value_after(str *name, sr_xval_t *val, sr_xavp_t *pxavp);
144
+sr_xavp_t *xavi_add_xavi_value(str *rname, str *name, sr_xval_t *val, sr_xavp_t **list);
145
+sr_xavp_t *xavi_set_value(str *name, int idx, sr_xval_t *val, sr_xavp_t **list);
146
+sr_xavp_t *xavi_get(str *name, sr_xavp_t *start);
147
+sr_xavp_t *xavi_get_by_index(str *name, int idx, sr_xavp_t **start);
148
+sr_xavp_t *xavi_get_next(sr_xavp_t *start);
149
+sr_xavp_t *xavi_get_last(str *xname, sr_xavp_t **list);
150
+int xavi_rm_by_name(str *name, int all, sr_xavp_t **head);
151
+int xavi_rm_by_index(str *name, int idx, sr_xavp_t **head);
152
+int xavi_rm(sr_xavp_t *xa, sr_xavp_t **head);
153
+int xavi_rm_child_by_index(str *rname, str *cname, int idx);
154
+int xavi_count(str *name, sr_xavp_t **start);
155
+#define xavi_destroy_list_unsafe xavp_destroy_list_unsafe
156
+#define xavi_destroy_list xavp_destroy_list
157
+void xavi_reset_list(void);
158
+sr_xavp_t **xavi_set_list(sr_xavp_t **head);
159
+sr_xavp_t **xavi_get_crt_list(void);
160
+struct str_list *xavi_get_list_key_names(sr_xavp_t *xavp);
161
+
162
+int xavi_insert(sr_xavp_t *xavp, int idx, sr_xavp_t **list);
163
+sr_xavp_t *xavi_extract(str *name, sr_xavp_t **list);
164
+
165
+void xavi_print_list(sr_xavp_t **head);
166
+
167
+sr_xavp_t *xavi_clone_level_nodata(sr_xavp_t *xold);
168
+sr_xavp_t *xavi_clone_level_nodata_with_new_name(sr_xavp_t *xold, str *dst_name);
169
+
170
+sr_xavp_t* xavi_get_child(str *rname, str *cname);
171
+sr_xavp_t* xavi_get_child_with_ival(str *rname, str *cname);
172
+sr_xavp_t* xavi_get_child_with_sval(str *rname, str *cname);
173
+int xavi_serialize_fields(str *rname, char *obuf, int olen);
174
+
175
+int xavi_set_child_ival(str *rname, str *cname, int ival);
176
+int xavi_set_child_sval(str *rname, str *cname, str *sval);
177
+
135 178
 #endif