65a0a2c399683fa1690409971fee24fd3632999c
[com/gs-lite.git] / src / lib / gscphftaaux / hfta_runtime_library.cc
1 /* ------------------------------------------------
2 Copyright 2014 AT&T Intellectual Property
3    Licensed under the Apache License, Version 2.0 (the "License");
4    you may not use this file except in compliance with the License.
5    You may obtain a copy of the License at
6
7      http://www.apache.org/licenses/LICENSE-2.0
8
9    Unless required by applicable law or agreed to in writing, software
10    distributed under the License is distributed on an "AS IS" BASIS,
11    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12    See the License for the specific language governing permissions and
13    limitations under the License.
14  ------------------------------------------- */
15
16 #include <sys/types.h>
17 #include <iostream>
18 extern "C" {
19 #include "gsconfig.h"
20 #include "gstypes.h"
21 #include <regex.h>
22 #include <rdtsc.h>
23 #include <stringhash.h>
24 #include <errno.h>
25 #include <unistd.h>
26 }
27 #include <stdio.h>
28 #include <string.h>
29
30 #include <vstring.h>
31 #include <host_tuple.h>
32 #include <fta.h>
33
34 #include<map>
35
36 // for htonl,ntohl
37 #include <netinet/in.h>
38
39 #define MAX_PATTERN_LEN 1024
40
41 // Defined here to avoid link errors as this array is auto generated for the lfta and referenced in the clearinghouse library which gets linked against the hfta
42 extern "C" gs_sp_t fta_names[]={0};
43
44
45 //              Only used to construct constant strings ...
46 gs_retval_t Vstring_Constructor(vstring *tmp, gs_csp_t str) {
47         tmp->length = strlen(str);
48         if(tmp->length)
49                 tmp->offset = (gs_p_t)strdup(str);
50         tmp->reserved = SHALLOW_COPY;
51         return 0;
52 }
53
54 //              Assume str is INTERNAL or SHALLOW_COPY.
55 void hfta_vstr_destroy(vstring * str) {
56         if (str->length && str->reserved == INTERNAL) {
57                 free((gs_sp_t)str->offset);
58         }
59         str->length = 0;
60 }
61
62 //      Make the vstring safe to destroy even if its never initialized
63 //      (e.g. stack-allocated groups containing strings)
64 void hfta_vstr_init(vstring * str) {
65         str->length = 0;
66 }
67
68 gs_retval_t hfta_vstr_length(vstring *str) {
69         return str->length;
70 }
71
72 //              Assume that SRC is either INTERNAL or SHALLOW_COPY
73 void hfta_vstr_assign_with_copy_in_tuple(vstring32 * target,
74                 const vstring * src, gs_sp_t data_offset,  gs_retval_t int_offset) {
75         target->length = src->length;
76         target->offset = int_offset;
77         target->reserved = PACKED;
78         if ( src->length)
79                 memcpy(data_offset, (gs_sp_t)src->offset, src->length);
80 }
81
82 //              Ted wrote the following function.
83 //              make deep copy of src.  Assume that dst is already empty.
84 //              Assume that SRC is either INTERNAL or SHALLOW_COPY
85 void hfta_vstr_assign_with_copy(vstring *dst, const vstring *src){
86         dst->length=src->length;
87         if(src->length){
88                 dst->offset=(gs_p_t)malloc(dst->length);
89                 memcpy((gs_sp_t)(dst->offset),(gs_sp_t)(src->offset),dst->length);
90         }
91         dst->reserved=INTERNAL;
92 }
93
94 //              Ted wrote the following function.
95 //              Make a deep copy of src.  garbage collect dst if needed.
96 //              Assume that SRC is either INTERNAL or SHALLOW_COPY
97 void hfta_vstr_replace(vstring *dst, const vstring *src){
98         hfta_vstr_destroy(dst);
99         hfta_vstr_assign_with_copy(dst,src);
100 }
101
102 #define HFTA_VSTR_LHASHFUNC_PRIME 12916008961267169387ull
103 gs_uint64_t hfta_vstr_long_hashfunc(const vstring *s) {
104         gs_uint64_t hash_code;
105         gs_int32_t n_steps;
106         gs_int32_t substr_len;
107         gs_int32_t j, k;
108         gs_uint64_t sub_hash;
109         gs_sp_t sv;
110
111         sv=(gs_sp_t)(s->offset);
112         hash_code = 0;
113         n_steps = s->length / 4;
114         if(4*n_steps < s->length) n_steps++;
115
116         for (j = 0; j <  n_steps; j++) {
117                 if(4*(j+1) < s->length) substr_len = 4;
118                 else                  substr_len = s->length - 4*j;
119
120                 sub_hash = 0;
121                 for(k=0;k<4;k++){
122                   if(k < substr_len)
123                         sub_hash = (sub_hash << 4) + *sv;
124                   else
125                         sub_hash = (sub_hash << 4);
126                   sv++;
127                 }
128
129                 hash_code = (sub_hash + hash_code * HFTA_VSTR_LHASHFUNC_PRIME);
130         }
131
132         return(hash_code);
133 }
134
135 #define HFTA_VSTR_HASHFUNC_PRIME 2995999
136 gs_uint32_t hfta_vstr_hashfunc(const vstring *s) {
137         gs_uint32_t hash_code;
138         gs_int32_t n_steps;
139         gs_int32_t substr_len;
140         gs_int32_t j;
141         gs_uint32_t k, sub_hash;
142         gs_sp_t sv;
143
144         sv=(gs_sp_t)(s->offset);
145         hash_code = 0;
146         n_steps = s->length / 4;
147         if(4*n_steps < s->length) n_steps++;
148
149         for (j = 0; j <  n_steps; j++) {
150                 if(4*(j+1) < s->length) substr_len = 4;
151                 else                  substr_len = s->length - 4*j;
152
153                 sub_hash = 0;
154                 for(k=0;k<4;k++){
155                   if(k < substr_len)
156                         sub_hash = (sub_hash << 4) + *sv;
157                   else
158                         sub_hash = (sub_hash << 4);
159                   sv++;
160                 }
161
162                 hash_code = (sub_hash + hash_code * HFTA_VSTR_HASHFUNC_PRIME);
163         }
164
165         return(hash_code);
166 }
167
168
169 //      return negative if s1 < s2, 0 if s1==s2, positive if s1>s2
170 gs_retval_t hfta_vstr_compare(const vstring * s1, const vstring * s2) {
171         gs_int32_t minlen,cmp_ret;
172         minlen=(s1->length<s2->length?s1->length:s2->length);
173         cmp_ret=memcmp((void *)s1->offset,(void *)s2->offset,minlen);
174
175         if(cmp_ret) return cmp_ret;
176         return(s1->length - s2->length);
177 }
178
179 gs_retval_t hfta_vstr_equal(const vstring * s1, const vstring * s2) {
180         gs_int32_t x;
181
182         if(s1->length != s2->length)
183                 return -1;
184
185 //      cmp_ret=memcmp((void *)s1->offset,(void *)s2->offset,s1->length);
186     for(x=0;x<s1->length;x++) {
187         if (((char *)(s1->offset))[x]!=((char *)(s2->offset))[x]) {
188             return -1;
189         }
190     }
191
192
193         return 0;
194 }
195
196
197
198 gs_param_handle_t register_handle_for_str_regex_match_slot_1(vstring* pattern) {
199     regex_t * reg;
200     gs_int32_t res;
201
202     if ((reg=(regex_t *) malloc(sizeof(regex_t)))==0)  {
203         gslog(LOG_EMERG, "No memory for regular expression %s\n",
204                 (gs_sp_t)(pattern->offset));
205         return 0;
206     }
207
208     if (regcomp(reg,(char*)(pattern->offset), REG_NEWLINE|REG_EXTENDED|REG_NOSUB)!=0) {
209         gslog(LOG_EMERG, "Illegal regular expression %s\n",
210                 (gs_sp_t)(pattern->offset));
211         return 0;
212     }
213     return (gs_param_handle_t) reg;
214 }
215
216 gs_uint32_t str_regex_match(vstring* str, gs_param_handle_t pattern_handle) {
217     regex_t * reg = (regex_t *) pattern_handle ;
218     gs_int32_t res;
219     static gs_sp_t d=0;
220     static gs_uint32_t dlen=0;
221     // grow our static buffer to the longest string we ever see
222     if ((str->length+1) >= dlen) {
223         if (d!=0) free((void*)d);
224         dlen=0;
225         d=0;
226         if ((d=(gs_sp_t)malloc(str->length+1))==0) return 0;
227         dlen=str->length+1;
228     }
229     
230     if (str->length==0) return 0;
231     
232     // copy the string and 0 terminate it
233     memcpy((void *)d,(void *) str->offset, str->length);
234     d[str->length]=0;
235     
236     res = REG_NOMATCH;
237     res = regexec(reg, d, 0, NULL, 0);
238     return (res==REG_NOMATCH)?0:1;
239 }
240
241 gs_retval_t deregister_handle_for_str_regex_match_slot_1(gs_param_handle_t handle) {
242     regex_t * x = (regex_t *) handle;
243     regfree(x);
244     if (x!=0) free(x);
245     return 0;
246 }
247
248 gs_param_handle_t register_handle_for_str_partial_regex_match_slot_1(vstring* pattern) {
249     regex_t * reg;
250     gs_int32_t res;
251
252     if ((reg=(regex_t *) malloc(sizeof(regex_t)))==0)  {
253         gslog(LOG_EMERG, "No memory for regular expression %s\n",
254                 (gs_sp_t)(pattern->offset));
255         return 0;
256     }
257
258     if (regcomp(reg,(gs_sp_t)(pattern->offset), REG_NEWLINE|REG_EXTENDED|REG_NOSUB)!=0) {
259         gslog(LOG_EMERG, "Illegal regular expression %s\n",
260                 (gs_sp_t)(pattern->offset));
261         return 0;
262     }
263     return (gs_param_handle_t) reg;
264 }
265
266 gs_uint32_t str_partial_regex_match(vstring* str, gs_param_handle_t pattern_handle,
267                              uint maxlen) {
268     regex_t * reg = (regex_t *) pattern_handle ;
269     gs_int32_t res;
270     gs_int32_t end;
271     static gs_sp_t d=0;
272     static gs_uint32_t dlen=0;
273     // grow our static buffer to the longest string we ever see
274     if ((str->length+1) >= dlen) {
275         if (d!=0) free((void*)d);
276         dlen=0;
277         d=0;
278         if ((d=(gs_sp_t)malloc(str->length+1))==0) return 0;
279         dlen=str->length+1;
280     }
281     
282     if (str->length==0) return 0;
283     
284     end=(maxlen>(str->length))?(str->length):maxlen;
285     
286     // copy the string and 0 terminate it
287     memcpy((void *)d,(void *) str->offset, end);
288     d[end]=0;
289  
290     res = REG_NOMATCH;
291     res = regexec(reg, d,0, NULL, 0);
292     return (res==REG_NOMATCH)?0:1;
293 }
294
295
296 gs_retval_t deregister_handle_for_str_partial_regex_match_slot_1(
297                                              gs_param_handle_t handle) {
298     regex_t * x = (regex_t *) handle;
299     regfree(x);
300     if (x!=0) free(x);
301     return 0;
302 }
303
304 gs_param_handle_t register_handle_for_str_extract_regex_slot_1(vstring* pattern) {
305     regex_t * reg;
306     
307     if ((reg=(regex_t *) malloc(sizeof(regex_t)))==0)  {
308         gslog(LOG_EMERG, "No memory for regular expression %s\n",
309               (gs_sp_t)(pattern->offset));
310         return 0;
311     }
312     if (regcomp(reg,(gs_sp_t)(pattern->offset), REG_EXTENDED)!=0) {
313         gslog(LOG_EMERG, "Illegal regular expression %s\n",
314               (gs_sp_t)(pattern->offset));
315         return 0;
316     }
317     return (gs_param_handle_t) reg;
318 }
319
320
321 /* partial function return 0 if the value is valid */
322 gs_retval_t str_extract_regex( vstring * result, vstring * str, gs_param_handle_t handle) {
323     regex_t * reg = (regex_t *) handle ;
324     gs_sp_t source = (gs_sp_t)(str->offset);
325     gs_retval_t res;
326     regmatch_t match;
327     static gs_sp_t d=0;
328     static gs_uint32_t dlen=0;
329     // grow our static buffer to the longest string we ever see
330     if ((str->length+1) >= dlen) {
331         if (d!=0) free((void*)d);
332         dlen=0;
333         d=0;
334         if ((d=(gs_sp_t)malloc(str->length+1))==0) return 1;
335         dlen=str->length+1;
336     }
337     
338     if (str->length==0) return 1;
339     
340     // copy the string and 0 terminate it
341     memcpy((void *)d,(void *) str->offset, str->length);
342     d[str->length]=0;
343
344     res = REG_NOMATCH;
345     res = regexec(reg, d, 1, &match, 0);
346     if (res==REG_NOMATCH) return 1;
347     result->offset= (gs_p_t) &source[match.rm_so];
348     result->length=match.rm_eo-match.rm_so;
349     result->reserved = SHALLOW_COPY;
350     return 0;
351 }
352
353 gs_retval_t deregister_handle_for_str_extract_regex_slot_1(gs_param_handle_t handle) {
354     regex_t * x = (regex_t *) handle;
355     regfree(x);
356     if (x!=0) free(x);
357     return 0;
358 }
359
360 // -------------------------------------------------
361 //              More substring functions
362
363 //       get last n bytes, if available
364 //       getting the prefix is done by str_truncate, defined in the include file
365 gs_retval_t str_suffix(vstring *result,  vstring *s, gs_uint32_t n){
366   register gs_p_t st = (gs_p_t)s->offset; 
367   int prefix = (n > s->length) ? 0 : s->length-n;  
368   result->offset = st + prefix;
369   result->length = s->length-prefix;
370   result->reserved = SHALLOW_COPY;
371   return 0;
372 }
373
374
375 //      Split the string on sep, get the i'th substring, if any
376 gs_retval_t get_list_entry(vstring *result, vstring *l,  vstring *sep, gs_uint32_t pos){
377         char s;
378         gs_int32_t c;
379
380         result->offset = l->offset;     // empty return string
381         result->reserved = SHALLOW_COPY;
382         result->length = 0;
383
384         if(sep->length > 0){    // get the sep char, ensure the string is nonempty
385                 s = ((gs_sp_t)(sep->offset))[0];
386         }else{
387                 return 0;
388         }
389
390         for(c=0;c < l->length && pos>0; ++c){
391                 if(((gs_sp_t)(l->offset))[c] == s){
392                         pos--;
393                 }
394         }
395
396         if(pos>0 || c >= l->length-1){ // not enough seps, or final string is empty
397                 return 0;
398         }
399         
400         result->offset = l->offset + c;
401         for(; c<l->length && ((gs_sp_t)(l->offset))[c] != s; ++c, ++result->length);
402         
403         return 0;
404 }
405
406
407 // -------------------------------------------------
408
409 static gs_uint32_t nextint(struct vstring *str , gs_uint32_t * offset, gs_uint32_t *res) {
410         gs_uint8_t * s = (gs_uint8_t *)(str->offset);
411         int v = 0;
412         *res = 0;
413         while(*offset<str->length) {
414                 if ((s[*offset]>='0') && (s[*offset]<='9')) {
415                         v=1;
416                         *res= (*res*10) + (gs_uint32_t) (s[*offset]-'0');
417                 } else {
418                         if (v!=0) { // got some valid result
419                                 return 1;
420                         } // otherwise skip leading grabage
421                 }
422                 (*offset)++;
423         }
424         return v;
425 }
426
427
428 gs_uint32_t strtoi(gs_uint32_t * r, struct vstring * s)
429 {
430         gs_uint32_t offset;
431         offset=0;
432         if (nextint(s,&offset,r)==0) return 1;
433         return 0;
434 }
435
436 gs_param_handle_t register_handle_for_strtoi_c_slot_0(vstring* istr) {
437         gs_uint32_t offset,r;
438         offset=0;
439         if (nextint(istr,&offset,&r)!=0)
440                 return (gs_param_handle_t) r;
441         return (gs_param_handle_t) 0;
442 }
443 gs_retval_t deregister_handle_for_strtoi_c_slot_0(gs_param_handle_t h) {
444         return 0;
445 }
446
447
448 gs_uint32_t strtoip(gs_uint32_t * r, struct vstring * s)
449 {
450         gs_uint32_t ip1,ip2,ip3,ip4,offset;
451         offset=0;
452         if (nextint(s,&offset,&ip1)==0) return 1;
453         //fprintf (stderr, "1 %u %u\n",ip1,offset);
454         if (nextint(s,&offset,&ip2)==0) return 1;
455         //fprintf (stderr, "2 %u %u\n",ip2,offset);
456         if (nextint(s,&offset,&ip3)==0) return 1;
457         //fprintf (stderr, "3 %u %u\n",ip3,offset);
458         if (nextint(s,&offset,&ip4)==0) return 1;
459         //fprintf (stderr, "4 %u %u\n",ip4,offset);
460         *r=ip1<<24|ip2<<16|ip3<<8|ip4;
461         return 0;
462 }
463
464 gs_param_handle_t register_handle_for_strtoip_c_slot_0(vstring* istr) {
465         gs_uint32_t ip1,ip2,ip3,ip4,offset,r;
466         offset=0;
467         if (nextint(istr,&offset,&ip1)==0) return (gs_param_handle_t)0;
468         if (nextint(istr,&offset,&ip2)==0) return (gs_param_handle_t)0;
469         if (nextint(istr,&offset,&ip3)==0) return (gs_param_handle_t)0;
470         if (nextint(istr,&offset,&ip4)==0) return (gs_param_handle_t)0;
471         r=ip1<<24|ip2<<16|ip3<<8|ip4;
472                 return (gs_param_handle_t)r;
473 }
474 gs_retval_t deregister_handle_for_strtoip_c_slot_0(gs_param_handle_t h) {
475         return 0;
476 }
477
478 gs_uint32_t partn_hash(  gs_uint32_t ip1, gs_uint32_t ip2) {
479     return (ip1^ip2);
480 }
481
482 gs_uint32_t rand_hash() {
483     return rand();
484 }
485
486 ///////////////////////////////////////
487 //              IPv6 fcns.
488 //      return negative if s1 < s2, 0 if s1==s2, positive if s1>s2
489 gs_retval_t hfta_ipv6_compare(const hfta_ipv6_str &i1, const hfta_ipv6_str &i2) {
490     if(i1.v[0] > i2.v[0])
491         return 1;
492     if(i1.v[0] < i2.v[0])
493         return -1;
494     if(i1.v[1] > i2.v[1])
495         return 1;
496     if(i1.v[1] < i2.v[1])
497         return -1;
498     if(i1.v[2] > i2.v[2])
499         return 1;
500     if(i1.v[2] < i2.v[2])
501         return -1;
502     if(i1.v[3] > i2.v[3])
503         return 1;
504     if(i1.v[3] < i2.v[3])
505         return -1;
506
507     return 0;
508 }
509
510 hfta_ipv6_str And_Ipv6(const hfta_ipv6_str &i1, const hfta_ipv6_str &i2){
511         hfta_ipv6_str ret;
512         ret.v[0] = i1.v[0] & i2.v[0];
513         ret.v[1] = i1.v[1] & i2.v[1];
514         ret.v[2] = i1.v[2] & i2.v[2];
515         ret.v[3] = i1.v[3] & i2.v[3];
516         return ret;
517 }
518
519 hfta_ipv6_str Or_Ipv6(const hfta_ipv6_str &i1, const hfta_ipv6_str &i2){
520         hfta_ipv6_str ret;
521         ret.v[0] = i1.v[0] | i2.v[0];
522         ret.v[1] = i1.v[1] | i2.v[1];
523         ret.v[2] = i1.v[2] | i2.v[2];
524         ret.v[3] = i1.v[3] | i2.v[3];
525         return ret;
526 }
527
528 gs_uint32_t hfta_ipv6_hashfunc(const hfta_ipv6_str *s) {
529         return s->v[0] ^ s->v[1] ^ s->v[2] ^ s->v[3];
530 }
531
532 hfta_ipv6_str hton_ipv6(hfta_ipv6_str s){
533         hfta_ipv6_str ret;
534
535 //      ret.v[0] = htonl(s.v[0]);
536 //      ret.v[1] = htonl(s.v[1]);
537 //      ret.v[2] = htonl(s.v[2]);
538 //      ret.v[3] = htonl(s.v[3]);
539         ret.v[0] = s.v[0];
540         ret.v[1] = s.v[1];
541         ret.v[2] = s.v[2];
542         ret.v[3] = s.v[3];
543         return ret;
544 }
545
546 hfta_ipv6_str ntoh_ipv6(hfta_ipv6_str s){
547         hfta_ipv6_str ret;
548 //      ret.v[0] = ntohl(s.v[0]);
549 //      ret.v[1] = ntohl(s.v[1]);
550 //      ret.v[2] = ntohl(s.v[2]);
551 //      ret.v[3] = ntohl(s.v[3]);
552         ret.v[0] = s.v[0];
553         ret.v[1] = s.v[1];
554         ret.v[2] = s.v[2];
555         ret.v[3] = s.v[3];
556         return ret;
557 }
558
559 int HFTA_Ipv6_Constructor(hfta_ipv6_str *s, gs_csp_t l) {
560         gs_uint32_t i0=0,i1=0,i2=0,i3=0,i4=0,i5=0,i6=0,i7=0;
561         sscanf(l,"%x:%x:%x:%x:%x:%x:%x:%x",&i0,&i1,&i2,&i3,&i4,&i5,&i6,&i7);
562         s->v[0] = ((i0 & 0xffff) << 16) | (i1 & 0xffff);
563         s->v[1] = ((i2 & 0xffff) << 16) | (i3 & 0xffff);
564         s->v[2] = ((i4 & 0xffff) << 16) | (i5 & 0xffff);
565         s->v[3] = ((i6 & 0xffff) << 16) | (i7 & 0xffff);
566     return(0);
567 }
568
569 gs_retval_t str_exists_substr(vstring * s1,vstring * s2)
570 {
571   gs_uint8_t *st1 = (gs_uint8_t *)s1->offset;
572   gs_uint8_t *st2 = (gs_uint8_t *)s2->offset;
573   gs_uint8_t *s2f = (gs_uint8_t *)s2->offset;
574   gs_uint8_t len1 = s1->length-s2->length;
575   gs_uint8_t len2 = s2->length;
576   gs_uint8_t x,y;
577
578   for (x=0; x<len1 ; x++)
579   {
580       if (st1[x]== *s2f)
581         {
582           for (y=0; y<len2 && st1[x+y]==st2[y];y++);
583           if (y==len2)
584               return 1;
585         }
586   }
587   return 0;
588 }
589
590 gs_retval_t str_compare(vstring *s1,vstring *s2)
591 {
592   return hfta_vstr_compare(s1,s2);
593 }
594
595 gs_uint32_t str_match_offset( gs_uint32_t offset, vstring *s1, vstring *s2)
596 {
597   gs_uint8_t *st1 = (gs_uint8_t *)s1->offset;
598   gs_uint8_t *st2 = &(((gs_uint8_t *)s2->offset)[offset]);
599   gs_int32_t x;
600   gs_int32_t len2 = s2->length-offset;
601   gs_int32_t len1 = s1->length;
602
603   if (len2 < len1)
604     return 0;
605
606   for(x = 0; x < len1; x++)
607     {
608       if (st1[x] != st2[x])
609         return 0;
610     }
611   return 1;
612 }
613
614 gs_uint32_t byte_match_offset( gs_uint32_t offset, gs_uint32_t val,vstring *s2)
615 {
616   gs_uint8_t *st2 = (gs_uint8_t *)s2->offset;
617   gs_uint8_t v = (unsigned char) val;
618
619 //  if ((s2->length <= offset)||(offset<0))
620   if (s2->length <= offset)
621       return 0;
622
623   return (st2[offset]==v)?1:0;
624 }
625
626
627 // -------------------------------------------------------
628 //              map_int_to_string and its support functions, structs
629
630 struct int_to_string_map_struct{
631         std::map<gs_int64_t, vstring> i2s_map;
632         std::string fname;
633         vstring empty_string;
634 };
635
636 gs_param_handle_t register_handle_for_int_to_string_map_slot_1(vstring *filename){
637         int_to_string_map_struct *map_struct;
638
639         map_struct = new int_to_string_map_struct();
640         if(map_struct == NULL){
641                 gslog(LOG_EMERG, "int_to_string_map:: Could not allocate handle memory\n");
642                 return 0;
643         }
644
645         map_struct->empty_string.offset = (gs_p_t)malloc(1);
646         map_struct->empty_string.reserved = INTERNAL;
647         map_struct->empty_string.length = 0;
648
649         gs_sp_t filenamec;
650         filenamec = (gs_sp_t)alloca(filename->length+1);
651         if (filenamec==0) {
652                 gslog(LOG_EMERG, "int_to_string_map:: Could not allocate filename memory\n");
653                 return 0;
654         }
655         memcpy(filenamec,(gs_sp_t)filename->offset,filename->length);
656         filenamec[filename->length]=0;  
657         map_struct->fname = filenamec;
658
659         FILE *fl = fopen(filenamec, "r");
660         if(fl==NULL){
661                 gslog(LOG_EMERG, "int_to_string_map:: Could not open regex file %s \n",filename);
662                 return 0;
663         }
664         
665         gs_int32_t buflen = 10000;
666         char buf[buflen], buf_str[buflen];
667         gs_int64_t val;
668         char *fret;
669         fret = fgets(buf, buflen, fl);
670         while(fret != NULL){
671                 int nvals = sscanf(buf, "%lld,%s", &val, buf_str);
672                 if(nvals >= 2){
673                         vstring new_str;
674                         new_str.reserved = SHALLOW_COPY;
675                         new_str.length = strlen(buf_str);
676                         new_str.offset = (gs_p_t)malloc(new_str.length);
677                         memcpy((char *)new_str.offset, buf_str, new_str.length);
678                         map_struct->i2s_map[val] = new_str;
679                 }
680                 fret = fgets(buf, buflen, fl);
681         }
682
683         fclose(fl);
684
685         return (gs_param_handle_t) map_struct;
686 }
687
688 gs_retval_t int_to_string_map(vstring *result, gs_int64_t val, gs_param_handle_t handle){
689         int_to_string_map_struct *map_struct = (int_to_string_map_struct *)handle;
690         if(map_struct->i2s_map.count(val)>0){
691                 vstring ret = map_struct->i2s_map[val];
692                 result->offset = ret.offset;
693                 result->reserved = ret.reserved;
694                 result->length = ret.length;
695         }else{
696                 result->offset = map_struct->empty_string.offset;
697                 result->reserved = map_struct->empty_string.reserved;
698                 result->length = map_struct->empty_string.length;
699         }
700
701         return 0;
702 }
703
704 gs_param_handle_t deregister_handle_for_int_to_string_map_slot_1(gs_param_handle_t handle){
705         int_to_string_map_struct *map_struct = (int_to_string_map_struct *)handle;
706         for(std::map<gs_int64_t, vstring>::iterator i2si = map_struct->i2s_map.begin(); i2si!=map_struct->i2s_map.end(); ++i2si){
707                 free((void *)((*i2si).second.offset));
708         }
709         free((void *)(map_struct->empty_string.offset));
710         delete map_struct;
711 }
712
713 // ---------------------------------------------------
714 //              Return a (binary, non-ascii) string in its hex representation
715
716 static char hexmap[16] = {
717   '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'
718 };
719
720 gs_retval_t to_hex_string(vstring *result, vstring *val){
721         result->length = 2*(val->length);
722         result->offset = (gs_p_t)malloc(result->length);
723         result->reserved = INTERNAL;
724         unsigned char *rs = (unsigned char *)(result->offset);
725         unsigned char *vs = (unsigned char *)(val->offset);
726
727         for(int c=0;c<val->length; ++c){
728                 rs[2*c] = hexmap[vs[c] >> 4];
729                 rs[2*c+1] = hexmap[vs[c] & 0x0f];
730         }
731
732         return 0;
733 }
734
735
736 // ---------------------------------------------
737 //              sum up unsigned integers expressed as a string with separators,
738 //              e.g. on input '34|45|56' and sep '|', return 135.
739 //              This kind of thing is common in Nokia PCMD data.
740 // gracefully handle empty entries, e.g. '|8|' should return 8
741 gs_int64_t sum_uint_in_list(struct vstring *list, struct vstring *sepchar){
742         gs_int64_t ret = 0;
743         gs_int64_t val = 0;
744         char sep;
745         char v;
746         int c;
747
748         if(sepchar->length < 1)
749                 return 0;
750         sep = ((char *)(sepchar->offset))[0];
751
752         for(c=0;c<list->length;++c){
753                 v = ((char *)(list->offset))[c];
754                 if(v==sep){
755                         ret+=val;
756                         val = 0;
757                 }else{
758                         val = 10*val + (v>='0' && v<='9')*(v-'0');
759                 }
760         }
761         ret += val;
762         return ret;
763 }
764
765 //      Convert an string to an integer
766 gs_int64_t to_llong(vstring *v){
767         gs_int64_t ret=0;
768         gs_uint8_t d;
769         int c;
770         int neg=1;
771
772         if(v->length < 1)
773                 return 0;
774         d = ((char *)(v->offset))[0];
775         if(d=='-'){
776                 neg=-1;
777         }else{
778                 ret = (d>='0' && d<='9')*(d-'0');
779         }
780
781         for(c=1;c<v->length;++c){
782                 d = ((char *)(v->offset))[c];
783                 ret = 10*ret+(d>='0' && d<='9')*(d-'0');
784         }
785
786         return neg*ret;
787 }
788