Browse code

htable: added iterator function to remove current item

Daniel-Constantin Mierla authored on 08/10/2021 07:47:06
Showing 4 changed files
... ...
@@ -1081,6 +1081,41 @@ sht_iterator_end("i1");
1081 1081
     }
1082 1082
     sht_iterator_end("i1");
1083 1083
 ...
1084
+</programlisting>
1085
+		</example>
1086
+	</section>
1087
+	<section id="htable.f.sht_iterator_rm">
1088
+		<title>
1089
+		<function moreinfo="none">sht_iterator_rm(iname)</function>
1090
+		</title>
1091
+		<para>
1092
+			Remove the current item in the iterator and move the iterator to
1093
+			the next one.
1094
+		</para>
1095
+		<para>
1096
+			The return code is 1 (true) if the item was removed and next item
1097
+			exists; -2 (false) if the item was removed and there is no next item
1098
+			(end of items); other negative value (false) can be returned on
1099
+			error (e.g., iterator or item not found).
1100
+		</para>
1101
+		<para>
1102
+			The parameter can be dynamic string with variables.
1103
+		</para>
1104
+		<para>
1105
+			This function can be used from ANY_ROUTE.
1106
+		</para>
1107
+		<example>
1108
+		<title><function>sht_iterator_rm</function> usage</title>
1109
+		<programlisting format="linespecific">
1110
+...
1111
+    sht_iterator_start("i1", "h1");
1112
+    while(sht_iterator_next("i1")) {
1113
+        while($shtitkey(i1) =~ "xyz" and sht_iterator_rm("i1")) {
1114
+            xdbg("item removed\n");
1115
+        }
1116
+    }
1117
+    sht_iterator_end("i1");
1118
+...
1084 1119
 </programlisting>
1085 1120
 		</example>
1086 1121
 	</section>
... ...
@@ -644,6 +644,17 @@ int ht_set_cell(ht_t *ht, str *name, int type, int_str *val, int mode)
644 644
 	return ht_set_cell_ex(ht, name, type, val, mode, 0);
645 645
 }
646 646
 
647
+static void ht_cell_unlink(ht_t *ht, int idx, ht_cell_t *it)
648
+{
649
+	if(it->prev==NULL)
650
+		ht->entries[idx].first = it->next;
651
+	else
652
+		it->prev->next = it->next;
653
+	if(it->next)
654
+		it->next->prev = it->prev;
655
+	ht->entries[idx].esize--;
656
+}
657
+
647 658
 int ht_del_cell(ht_t *ht, str *name)
648 659
 {
649 660
 	unsigned int idx;
... ...
@@ -675,13 +686,7 @@ int ht_del_cell(ht_t *ht, str *name)
675 686
 				&& strncmp(name->s, it->name.s, name->len)==0)
676 687
 		{
677 688
 			/* found */
678
-			if(it->prev==NULL)
679
-				ht->entries[idx].first = it->next;
680
-			else
681
-				it->prev->next = it->next;
682
-			if(it->next)
683
-				it->next->prev = it->prev;
684
-			ht->entries[idx].esize--;
689
+			ht_cell_unlink(ht, idx, it);
685 690
 			ht_slot_unlock(ht, idx);
686 691
 			ht_cell_free(it);
687 692
 			return 0;
... ...
@@ -1829,6 +1834,50 @@ int ht_iterator_end(str *iname)
1829 1834
 	return 0;
1830 1835
 }
1831 1836
 
1837
+int ht_iterator_rm(str *iname)
1838
+{
1839
+	int k;
1840
+	ht_cell_t *itb;
1841
+
1842
+	k = ht_iterator_find(iname);
1843
+	if(k==-1) {
1844
+		LM_ERR("iterator not found [%.*s]\n", iname->len, iname->s);
1845
+		return -1;
1846
+	}
1847
+	if(_ht_iterators[k].ht==NULL) {
1848
+		LM_ERR("iterator not initialized [%.*s]\n", iname->len, iname->s);
1849
+		return -1;
1850
+	}
1851
+	if(_ht_iterators[k].it==NULL) {
1852
+		LM_ERR("iterator not used [%.*s]\n", iname->len, iname->s);
1853
+		return -1;
1854
+	}
1855
+
1856
+	itb = _ht_iterators[k].it;
1857
+	_ht_iterators[k].it = _ht_iterators[k].it->next;
1858
+
1859
+	ht_cell_unlink(_ht_iterators[k].ht, _ht_iterators[k].slot, itb);
1860
+	ht_cell_free(itb);
1861
+
1862
+	if(_ht_iterators[k].it!=NULL) {
1863
+		/* next item is in the same slot */
1864
+		return 0;
1865
+	}
1866
+	/* next is not in the same slot - release and go to next slot */
1867
+	ht_slot_unlock(_ht_iterators[k].ht, _ht_iterators[k].slot);
1868
+	_ht_iterators[k].slot++;
1869
+
1870
+	for( ; _ht_iterators[k].slot<_ht_iterators[k].ht->htsize; _ht_iterators[k].slot++) {
1871
+		ht_slot_lock(_ht_iterators[k].ht, _ht_iterators[k].slot);
1872
+		if(_ht_iterators[k].ht->entries[_ht_iterators[k].slot].first!=NULL) {
1873
+			_ht_iterators[k].it = _ht_iterators[k].ht->entries[_ht_iterators[k].slot].first;
1874
+			return 0;
1875
+		}
1876
+		ht_slot_unlock(_ht_iterators[k].ht, _ht_iterators[k].slot);
1877
+	}
1878
+	return -2;
1879
+}
1880
+
1832 1881
 ht_cell_t* ht_iterator_get_current(str *iname)
1833 1882
 {
1834 1883
 	int k;
... ...
@@ -129,6 +129,7 @@ void ht_iterator_init(void);
129 129
 int ht_iterator_start(str *iname, str *hname);
130 130
 int ht_iterator_next(str *iname);
131 131
 int ht_iterator_end(str *iname);
132
+int ht_iterator_rm(str *iname);
132 133
 ht_cell_t* ht_iterator_get_current(str *iname);
133 134
 
134 135
 void ht_slot_lock(ht_t *ht, int idx);
... ...
@@ -80,6 +80,7 @@ static int ht_reset(struct sip_msg* msg, char* htname, char* foo);
80 80
 static int w_ht_iterator_start(struct sip_msg* msg, char* iname, char* hname);
81 81
 static int w_ht_iterator_next(struct sip_msg* msg, char* iname, char* foo);
82 82
 static int w_ht_iterator_end(struct sip_msg* msg, char* iname, char* foo);
83
+static int w_ht_iterator_rm(struct sip_msg* msg, char* iname, char* foo);
83 84
 
84 85
 int ht_param(modparam_t type, void* val);
85 86
 
... ...
@@ -140,6 +141,8 @@ static cmd_export_t cmds[]={
140 141
 		ANY_ROUTE},
141 142
 	{"sht_iterator_end",	(cmd_function)w_ht_iterator_end,	1, fixup_spve_null, 0,
142 143
 		ANY_ROUTE},
144
+	{"sht_iterator_rm",	(cmd_function)w_ht_iterator_rm,	1, fixup_spve_null, 0,
145
+		ANY_ROUTE},
143 146
 	{"bind_htable",     (cmd_function)bind_htable,     0, 0, 0,
144 147
 		ANY_ROUTE},
145 148
 	{0,0,0,0,0,0}
... ...
@@ -790,6 +793,32 @@ static int ki_ht_iterator_end(sip_msg_t *msg, str *iname)
790 793
 	return 1;
791 794
 }
792 795
 
796
+static int w_ht_iterator_rm(struct sip_msg* msg, char* iname, char* foo)
797
+{
798
+	str siname;
799
+	int ret;
800
+
801
+	if(fixup_get_svalue(msg, (gparam_t*)iname, &siname)<0 || siname.len<=0)
802
+	{
803
+		LM_ERR("cannot get iterator name\n");
804
+		return -1;
805
+	}
806
+	ret = ht_iterator_rm(&siname);
807
+	return (ret==0)?1:ret;
808
+}
809
+
810
+static int ki_ht_iterator_rm(sip_msg_t *msg, str *iname)
811
+{
812
+	int ret;
813
+
814
+	if(iname==NULL || iname->s==NULL || iname->len<=0) {
815
+		LM_ERR("invalid parameters\n");
816
+		return -1;
817
+	}
818
+	ret = ht_iterator_rm(iname);
819
+	return (ret==0)?1:ret;
820
+}
821
+
793 822
 static int ki_ht_slot_xlock(sip_msg_t *msg, str *htname, str *skey, int lmode)
794 823
 {
795 824
 	ht_t *ht;
... ...
@@ -1873,6 +1902,11 @@ static sr_kemi_t sr_kemi_htable_exports[] = {
1873 1902
 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
1874 1903
 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1875 1904
 	},
1905
+	{ str_init("htable"), str_init("sht_iterator_rm"),
1906
+		SR_KEMIP_INT, ki_ht_iterator_rm,
1907
+		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
1908
+			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1909
+	},
1876 1910
 	{ str_init("htable"), str_init("sht_rm"),
1877 1911
 		SR_KEMIP_INT, ki_ht_rm,
1878 1912
 		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,