Browse code

- Support for regex based search

Jan Janak authored on 12/10/2005 08:12:10
Showing 2 changed files
... ...
@@ -47,17 +47,6 @@
47 47
 #include "usr_avp.h"
48 48
 
49 49
 
50
-/* usr_avp data bodies */
51
-struct str_int_data {
52
-	str  name;
53
-	int  val;
54
-};
55
-
56
-struct str_str_data {
57
-	str  name;
58
-	str  val;
59
-};
60
-
61 50
 /* avp aliases structs*/
62 51
 struct avp_spec {
63 52
 	int type;
... ...
@@ -74,7 +63,7 @@ static struct avp_galias *galiases = 0;
74 74
 static struct usr_avp *global_avps = 0;
75 75
 static struct usr_avp **crt_avps  = &global_avps;
76 76
 
77
-
77
+static regex_t* search_re;  /* Regex for use in subsequent searches */
78 78
 
79 79
 inline static unsigned short compute_ID( str *name )
80 80
 {
... ...
@@ -110,13 +99,17 @@ int add_avp(unsigned short flags, int_str name, int_str val)
110 110
 			LOG(L_ERR,"ERROR:avp:add_avp: EMPTY NAME AVP!");
111 111
 			goto error;
112 112
 		}
113
-		if (flags&AVP_VAL_STR)
114
-			len += sizeof(struct str_str_data)-sizeof(void*) + name.s->len
115
-				+ (val.s->len+1);
116
-		else
117
-			len += sizeof(struct str_int_data)-sizeof(void*) + name.s->len;
118
-	} else if (flags&AVP_VAL_STR)
119
-			len += sizeof(str)-sizeof(void*) + (val.s->len+1);
113
+		if (flags&AVP_VAL_STR) {
114
+			len += sizeof(struct str_str_data)-sizeof(void*) 
115
+				+ name.s->len + 1 /* Terminating zero for regex search */
116
+				+ val.s->len + 1; /* Value is zero terminated */
117
+		} else {
118
+			len += sizeof(struct str_int_data)-sizeof(void*) 
119
+				+ name.s->len + 1; /* Terminating zero for regex search */
120
+		}
121
+	} else if (flags&AVP_VAL_STR) {
122
+		len += sizeof(str)-sizeof(void*) + val.s->len + 1;
123
+	}
120 124
 
121 125
 	avp = (struct usr_avp*)shm_malloc( len );
122 126
 	if (avp==0) {
... ...
@@ -143,6 +136,7 @@ int add_avp(unsigned short flags, int_str name, int_str val)
143 143
 			sid->name.len =name.s->len;
144 144
 			sid->name.s = (char*)sid + sizeof(struct str_int_data);
145 145
 			memcpy( sid->name.s , name.s->s, name.s->len);
146
+			sid->name.s[name.s->len] = '\0'; /* Zero terminator */
146 147
 			break;
147 148
 		case AVP_VAL_STR:
148 149
 			/* avp type ID, str value */
... ...
@@ -158,8 +152,9 @@ int add_avp(unsigned short flags, int_str name, int_str val)
158 158
 			ssd->name.len = name.s->len;
159 159
 			ssd->name.s = (char*)ssd + sizeof(struct str_str_data);
160 160
 			memcpy( ssd->name.s , name.s->s, name.s->len);
161
+			ssd->name.s[name.s->len]='\0'; /* Zero terminator */
161 162
 			ssd->val.len = val.s->len;
162
-			ssd->val.s = ssd->name.s + ssd->name.len;
163
+			ssd->val.s = ssd->name.s + ssd->name.len + 1;
163 164
 			memcpy( ssd->val.s , val.s->s, val.s->len);
164 165
 			ssd->val.s[ssd->val.len] = 0;
165 166
 			break;
... ...
@@ -261,9 +256,36 @@ inline static struct usr_avp *internal_search_name_avp( struct usr_avp *avp,
261 261
 }
262 262
 
263 263
 
264
+/* find an attribute by name match against regular expression */
265
+static struct usr_avp *internal_search_avp_by_re(struct usr_avp *avp, regex_t* re)
266
+{
267
+	str * avp_name;
268
+	regmatch_t pmatch;
269
+	
270
+	     /* validation */
271
+	if (re==0) {
272
+		LOG(L_ERR, "ERROR: internal_search_avp_by_re: No regular expression\n");
273
+		return 0;
274
+	}
275
+	
276
+	for( ; avp ; avp=avp->next ) {
277
+		     /* AVP identifiable by name ? */
278
+		if (!(avp->flags&AVP_NAME_STR)) continue;
279
+		if ((avp_name=get_avp_name(avp))==0) /* valid AVP name ? */
280
+			continue;
281
+		if (!avp_name->s) /* AVP name validation */
282
+			continue;
283
+		if (regexec(re, avp_name->s, 1, &pmatch,0)==0) { /* re match ? */
284
+			avp->search_type|= AVP_NAME_RE;
285
+			return avp;
286
+		}
287
+	}
288
+	return 0;
289
+}
290
+
264 291
 
265 292
 struct usr_avp *search_first_avp( unsigned short name_type,
266
-										int_str name, int_str *val)
293
+				  int_str name, int_str *val)
267 294
 {
268 295
 	struct usr_avp *avp;
269 296
 
... ...
@@ -284,14 +306,20 @@ struct usr_avp *search_first_avp( unsigned short name_type,
284 284
 			return 0;
285 285
 		}
286 286
 		avp = internal_search_name_avp(*crt_avps,compute_ID(name.s),name.s);
287
+	} else if (name_type & AVP_NAME_RE) {
288
+		search_re = name.re;
289
+		avp = internal_search_avp_by_re(*crt_avps, search_re);
287 290
 	} else {
288 291
 		avp = internal_search_ID_avp( *crt_avps, name.n );
289 292
 	}
290
-
291
-	/* get the value - if required */
292
-	if (avp && val)
293
-		get_avp_val(avp, val);
294
-
293
+	
294
+	if (avp) {
295
+		     /* remember type of search for next searches */
296
+		avp->search_type=name_type;
297
+		if (val) /* get the value - if required */
298
+			get_avp_val(avp, val);
299
+	}
300
+	
295 301
 	return avp;
296 302
 }
297 303
 
... ...
@@ -299,18 +327,30 @@ struct usr_avp *search_first_avp( unsigned short name_type,
299 299
 
300 300
 struct usr_avp *search_next_avp( struct usr_avp *avp,  int_str *val )
301 301
 {
302
-	if (avp==0 || avp->next==0)
302
+	struct usr_avp* next;
303
+
304
+	if (avp == 0) {
303 305
 		return 0;
306
+	}
304 307
 
305
-	if (avp->flags&AVP_NAME_STR)
306
-		avp = internal_search_name_avp( avp->next, avp->id, get_avp_name(avp));
307
-	else
308
-		avp = internal_search_ID_avp( avp->next, avp->id );
308
+	next = avp->next;
309
+	if (next == 0) {
310
+		return 0;
311
+	}
309 312
 
310
-	if (avp && val)
311
-		get_avp_val(avp, val);
313
+	if (avp->search_type & AVP_NAME_RE) {
314
+		next = internal_search_avp_by_re(next, search_re);
315
+	} else if (avp->flags & AVP_NAME_STR) {
316
+		next = internal_search_name_avp(next, avp->id, get_avp_name(avp));
317
+	} else {
318
+		next = internal_search_ID_avp(next, avp->id);
319
+	}
312 320
 
313
-	return avp;
321
+	if (next && val) {
322
+		get_avp_val(next, val);
323
+	}
324
+	
325
+	return next;
314 326
 }
315 327
 
316 328
 
... ...
@@ -34,6 +34,10 @@
34 34
 #ifndef _SER_URS_AVP_H_
35 35
 #define _SER_URS_AVP_H_
36 36
 
37
+#include <sys/types.h>
38
+#include <regex.h>
39
+
40
+
37 41
 /*
38 42
  *   LIST with the allocated flags, their meaning and owner
39 43
  *   flag no.    owner            description
... ...
@@ -47,15 +51,29 @@
47 47
 
48 48
 #include "str.h"
49 49
 
50
+struct str_int_data {
51
+	str name;
52
+	int val;
53
+};
54
+
55
+struct str_str_data {
56
+	str name;
57
+	str val;
58
+};
59
+
50 60
 typedef union {
51 61
 	int  n;
52 62
 	str *s;
63
+	regex_t* re;
53 64
 } int_str;
54 65
 
55 66
 
56 67
 struct usr_avp {
57 68
 	unsigned short id;
69
+	     /* Flags that are kept for the AVP lifetime */
58 70
 	unsigned short flags;
71
+	     /* Type of search in progress */
72
+	unsigned short search_type;
59 73
 	struct usr_avp *next;
60 74
 	void *data;
61 75
 };
... ...
@@ -63,6 +81,7 @@ struct usr_avp {
63 63
 
64 64
 #define AVP_NAME_STR     (1<<0)
65 65
 #define AVP_VAL_STR      (1<<1)
66
+#define AVP_NAME_RE      (1<<2)
66 67
 
67 68
 #define GALIAS_CHAR_MARKER  '$'
68 69
 
... ...
@@ -94,4 +113,3 @@ int parse_avp_name( str *name, int *type, int_str *avp_name);
94 94
 int parse_avp_spec( str *name, int *type, int_str *avp_name);
95 95
 
96 96
 #endif
97
-