fix int_to_string_map bug; allow blank lines and comments in output_spec.cfg
[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
63 gs_retval_t hfta_vstr_length(vstring *str) {
64         return str->length;
65 }
66
67 //              Assume that SRC is either INTERNAL or SHALLOW_COPY
68 void hfta_vstr_assign_with_copy_in_tuple(vstring32 * target, vstring * src,
69         gs_sp_t data_offset,  gs_retval_t int_offset) {
70         target->length = src->length;
71         target->offset = int_offset;
72         target->reserved = PACKED;
73         if ( src->length)
74                 memcpy(data_offset, (gs_sp_t)src->offset, src->length);
75 }
76
77 //              Ted wrote the following function.
78 //              make deep copy of src.  Assume that dst is already empty.
79 //              Assume that SRC is either INTERNAL or SHALLOW_COPY
80 void hfta_vstr_assign_with_copy(vstring *dst, vstring *src){
81         dst->length=src->length;
82         if(src->length){
83                 dst->offset=(gs_p_t)malloc(dst->length);
84                 memcpy((gs_sp_t)(dst->offset),(gs_sp_t)(src->offset),dst->length);
85         }
86         dst->reserved=INTERNAL;
87 }
88
89 //              Ted wrote the following function.
90 //              Make a deep copy of src.  garbage collect dst if needed.
91 //              Assume that SRC is either INTERNAL or SHALLOW_COPY
92 void hfta_vstr_replace(vstring *dst, vstring *src){
93         hfta_vstr_destroy(dst);
94         hfta_vstr_assign_with_copy(dst,src);
95 }
96
97 #define HFTA_VSTR_LHASHFUNC_PRIME 12916008961267169387ull
98 gs_uint64_t hfta_vstr_long_hashfunc(const vstring *s) {
99         gs_uint64_t hash_code;
100         gs_int32_t n_steps;
101         gs_int32_t substr_len;
102         gs_int32_t j, k;
103         gs_uint64_t sub_hash;
104         gs_sp_t sv;
105
106         sv=(gs_sp_t)(s->offset);
107         hash_code = 0;
108         n_steps = s->length / 4;
109         if(4*n_steps < s->length) n_steps++;
110
111         for (j = 0; j <  n_steps; j++) {
112                 if(4*(j+1) < s->length) substr_len = 4;
113                 else                  substr_len = s->length - 4*j;
114
115                 sub_hash = 0;
116                 for(k=0;k<4;k++){
117                   if(k < substr_len)
118                         sub_hash = (sub_hash << 4) + *sv;
119                   else
120                         sub_hash = (sub_hash << 4);
121                   sv++;
122                 }
123
124                 hash_code = (sub_hash + hash_code * HFTA_VSTR_LHASHFUNC_PRIME);
125         }
126
127         return(hash_code);
128 }
129
130 #define HFTA_VSTR_HASHFUNC_PRIME 2995999
131 gs_uint32_t hfta_vstr_hashfunc(const vstring *s) {
132         gs_uint32_t hash_code;
133         gs_int32_t n_steps;
134         gs_int32_t substr_len;
135         gs_int32_t j;
136         gs_uint32_t k, sub_hash;
137         gs_sp_t sv;
138
139         sv=(gs_sp_t)(s->offset);
140         hash_code = 0;
141         n_steps = s->length / 4;
142         if(4*n_steps < s->length) n_steps++;
143
144         for (j = 0; j <  n_steps; j++) {
145                 if(4*(j+1) < s->length) substr_len = 4;
146                 else                  substr_len = s->length - 4*j;
147
148                 sub_hash = 0;
149                 for(k=0;k<4;k++){
150                   if(k < substr_len)
151                         sub_hash = (sub_hash << 4) + *sv;
152                   else
153                         sub_hash = (sub_hash << 4);
154                   sv++;
155                 }
156
157                 hash_code = (sub_hash + hash_code * HFTA_VSTR_HASHFUNC_PRIME);
158         }
159
160         return(hash_code);
161 }
162
163
164 //      return negative if s1 < s2, 0 if s1==s2, positive if s1>s2
165 gs_retval_t hfta_vstr_compare(const vstring * s1, const vstring * s2) {
166         gs_int32_t minlen,cmp_ret;
167         minlen=(s1->length<s2->length?s1->length:s2->length);
168         cmp_ret=memcmp((void *)s1->offset,(void *)s2->offset,minlen);
169
170         if(cmp_ret) return cmp_ret;
171         return(s1->length - s2->length);
172 }
173
174
175
176 gs_param_handle_t register_handle_for_str_regex_match_slot_1(vstring* pattern) {
177     regex_t * reg;
178     gs_int32_t res;
179
180     if ((reg=(regex_t *) malloc(sizeof(regex_t)))==0)  {
181         gslog(LOG_EMERG, "No memory for regular expression %s\n",
182                 (gs_sp_t)(pattern->offset));
183         return 0;
184     }
185
186     if (regcomp(reg,(char*)(pattern->offset), REG_NEWLINE|REG_EXTENDED|REG_NOSUB)!=0) {
187         gslog(LOG_EMERG, "Illegal regular expression %s\n",
188                 (gs_sp_t)(pattern->offset));
189         return 0;
190     }
191     return (gs_param_handle_t) reg;
192 }
193
194 gs_uint32_t str_regex_match(vstring* str, gs_param_handle_t pattern_handle) {
195     regex_t * reg = (regex_t *) pattern_handle ;
196     gs_int32_t res;
197     static gs_sp_t d=0;
198     static gs_uint32_t dlen=0;
199     // grow our static buffer to the longest string we ever see
200     if ((str->length+1) >= dlen) {
201         if (d!=0) free((void*)d);
202         dlen=0;
203         d=0;
204         if ((d=(gs_sp_t)malloc(str->length+1))==0) return 0;
205         dlen=str->length+1;
206     }
207     
208     if (str->length==0) return 0;
209     
210     // copy the string and 0 terminate it
211     memcpy((void *)d,(void *) str->offset, str->length);
212     d[str->length]=0;
213     
214     res = REG_NOMATCH;
215     res = regexec(reg, d, 0, NULL, 0);
216     return (res==REG_NOMATCH)?0:1;
217 }
218
219 gs_retval_t deregister_handle_for_str_regex_match_slot_1(gs_param_handle_t handle) {
220     regex_t * x = (regex_t *) handle;
221     regfree(x);
222     if (x!=0) free(x);
223     return 0;
224 }
225
226 gs_param_handle_t register_handle_for_str_partial_regex_match_slot_1(vstring* pattern) {
227     regex_t * reg;
228     gs_int32_t res;
229
230     if ((reg=(regex_t *) malloc(sizeof(regex_t)))==0)  {
231         gslog(LOG_EMERG, "No memory for regular expression %s\n",
232                 (gs_sp_t)(pattern->offset));
233         return 0;
234     }
235
236     if (regcomp(reg,(gs_sp_t)(pattern->offset), REG_NEWLINE|REG_EXTENDED|REG_NOSUB)!=0) {
237         gslog(LOG_EMERG, "Illegal regular expression %s\n",
238                 (gs_sp_t)(pattern->offset));
239         return 0;
240     }
241     return (gs_param_handle_t) reg;
242 }
243
244 gs_uint32_t str_partial_regex_match(vstring* str, gs_param_handle_t pattern_handle,
245                              uint maxlen) {
246     regex_t * reg = (regex_t *) pattern_handle ;
247     gs_int32_t res;
248     gs_int32_t end;
249     static gs_sp_t d=0;
250     static gs_uint32_t dlen=0;
251     // grow our static buffer to the longest string we ever see
252     if ((str->length+1) >= dlen) {
253         if (d!=0) free((void*)d);
254         dlen=0;
255         d=0;
256         if ((d=(gs_sp_t)malloc(str->length+1))==0) return 0;
257         dlen=str->length+1;
258     }
259     
260     if (str->length==0) return 0;
261     
262     end=(maxlen>(str->length))?(str->length):maxlen;
263     
264     // copy the string and 0 terminate it
265     memcpy((void *)d,(void *) str->offset, end);
266     d[end]=0;
267  
268     res = REG_NOMATCH;
269     res = regexec(reg, d,0, NULL, 0);
270     return (res==REG_NOMATCH)?0:1;
271 }
272
273
274 gs_retval_t deregister_handle_for_str_partial_regex_match_slot_1(
275                                              gs_param_handle_t handle) {
276     regex_t * x = (regex_t *) handle;
277     regfree(x);
278     if (x!=0) free(x);
279     return 0;
280 }
281
282 gs_param_handle_t register_handle_for_str_extract_regex_slot_1(vstring* pattern) {
283     regex_t * reg;
284     
285     if ((reg=(regex_t *) malloc(sizeof(regex_t)))==0)  {
286         gslog(LOG_EMERG, "No memory for regular expression %s\n",
287               (gs_sp_t)(pattern->offset));
288         return 0;
289     }
290     if (regcomp(reg,(gs_sp_t)(pattern->offset), REG_EXTENDED)!=0) {
291         gslog(LOG_EMERG, "Illegal regular expression %s\n",
292               (gs_sp_t)(pattern->offset));
293         return 0;
294     }
295     return (gs_param_handle_t) reg;
296 }
297
298
299 /* partial function return 0 if the value is valid */
300 gs_retval_t str_extract_regex( vstring * result, vstring * str, gs_param_handle_t handle) {
301     regex_t * reg = (regex_t *) handle ;
302     gs_sp_t source = (gs_sp_t)(str->offset);
303     gs_retval_t res;
304     regmatch_t match;
305     static gs_sp_t d=0;
306     static gs_uint32_t dlen=0;
307     // grow our static buffer to the longest string we ever see
308     if ((str->length+1) >= dlen) {
309         if (d!=0) free((void*)d);
310         dlen=0;
311         d=0;
312         if ((d=(gs_sp_t)malloc(str->length+1))==0) return 1;
313         dlen=str->length+1;
314     }
315     
316     if (str->length==0) return 1;
317     
318     // copy the string and 0 terminate it
319     memcpy((void *)d,(void *) str->offset, str->length);
320     d[str->length]=0;
321
322     res = REG_NOMATCH;
323     res = regexec(reg, d, 1, &match, 0);
324     if (res==REG_NOMATCH) return 1;
325     result->offset= (gs_p_t) &source[match.rm_so];
326     result->length=match.rm_eo-match.rm_so;
327     result->reserved = SHALLOW_COPY;
328     return 0;
329 }
330
331 gs_retval_t deregister_handle_for_str_extract_regex_slot_1(gs_param_handle_t handle) {
332     regex_t * x = (regex_t *) handle;
333     regfree(x);
334     if (x!=0) free(x);
335     return 0;
336 }
337
338
339 static gs_uint32_t nextint(struct vstring *str , gs_uint32_t * offset, gs_uint32_t *res) {
340         gs_uint8_t * s = (gs_uint8_t *)(str->offset);
341         int v = 0;
342         *res = 0;
343         while(*offset<str->length) {
344                 if ((s[*offset]>='0') && (s[*offset]<='9')) {
345                         v=1;
346                         *res= (*res*10) + (gs_uint32_t) (s[*offset]-'0');
347                 } else {
348                         if (v!=0) { // got some valid result
349                                 return 1;
350                         } // otherwise skip leading grabage
351                 }
352                 (*offset)++;
353         }
354         return v;
355 }
356
357 gs_uint32_t strtoi(gs_uint32_t * r, struct vstring * s)
358 {
359         gs_uint32_t offset;
360         offset=0;
361         if (nextint(s,&offset,r)==0) return 1;
362         return 0;
363 }
364
365 gs_param_handle_t register_handle_for_strtoi_c_slot_0(vstring* istr) {
366         gs_uint32_t offset,r;
367         offset=0;
368         if (nextint(istr,&offset,&r)!=0)
369                 return (gs_param_handle_t) r;
370         return (gs_param_handle_t) 0;
371 }
372 gs_retval_t deregister_handle_for_strtoi_c_slot_0(gs_param_handle_t h) {
373         return 0;
374 }
375
376
377 gs_uint32_t strtoip(gs_uint32_t * r, struct vstring * s)
378 {
379         gs_uint32_t ip1,ip2,ip3,ip4,offset;
380         offset=0;
381         if (nextint(s,&offset,&ip1)==0) return 1;
382         //fprintf (stderr, "1 %u %u\n",ip1,offset);
383         if (nextint(s,&offset,&ip2)==0) return 1;
384         //fprintf (stderr, "2 %u %u\n",ip2,offset);
385         if (nextint(s,&offset,&ip3)==0) return 1;
386         //fprintf (stderr, "3 %u %u\n",ip3,offset);
387         if (nextint(s,&offset,&ip4)==0) return 1;
388         //fprintf (stderr, "4 %u %u\n",ip4,offset);
389         *r=ip1<<24|ip2<<16|ip3<<8|ip4;
390         return 0;
391 }
392
393 gs_param_handle_t register_handle_for_strtoip_c_slot_0(vstring* istr) {
394         gs_uint32_t ip1,ip2,ip3,ip4,offset,r;
395         offset=0;
396         if (nextint(istr,&offset,&ip1)==0) return (gs_param_handle_t)0;
397         if (nextint(istr,&offset,&ip2)==0) return (gs_param_handle_t)0;
398         if (nextint(istr,&offset,&ip3)==0) return (gs_param_handle_t)0;
399         if (nextint(istr,&offset,&ip4)==0) return (gs_param_handle_t)0;
400         r=ip1<<24|ip2<<16|ip3<<8|ip4;
401                 return (gs_param_handle_t)r;
402 }
403 gs_retval_t deregister_handle_for_strtoip_c_slot_0(gs_param_handle_t h) {
404         return 0;
405 }
406
407 gs_uint32_t partn_hash(  gs_uint32_t ip1, gs_uint32_t ip2) {
408     return (ip1^ip2);
409 }
410
411 gs_uint32_t rand_hash() {
412     return rand();
413 }
414
415 ///////////////////////////////////////
416 //              IPv6 fcns.
417 //      return negative if s1 < s2, 0 if s1==s2, positive if s1>s2
418 gs_retval_t hfta_ipv6_compare(const hfta_ipv6_str &i1, const hfta_ipv6_str &i2) {
419     if(i1.v[0] > i2.v[0])
420         return 1;
421     if(i1.v[0] < i2.v[0])
422         return -1;
423     if(i1.v[1] > i2.v[1])
424         return 1;
425     if(i1.v[1] < i2.v[1])
426         return -1;
427     if(i1.v[2] > i2.v[2])
428         return 1;
429     if(i1.v[2] < i2.v[2])
430         return -1;
431     if(i1.v[3] > i2.v[3])
432         return 1;
433     if(i1.v[3] < i2.v[3])
434         return -1;
435
436     return 0;
437 }
438
439 hfta_ipv6_str And_Ipv6(const hfta_ipv6_str &i1, const hfta_ipv6_str &i2){
440         hfta_ipv6_str ret;
441         ret.v[0] = i1.v[0] & i2.v[0];
442         ret.v[1] = i1.v[1] & i2.v[1];
443         ret.v[2] = i1.v[2] & i2.v[2];
444         ret.v[3] = i1.v[3] & i2.v[3];
445         return ret;
446 }
447
448 hfta_ipv6_str Or_Ipv6(const hfta_ipv6_str &i1, const hfta_ipv6_str &i2){
449         hfta_ipv6_str ret;
450         ret.v[0] = i1.v[0] | i2.v[0];
451         ret.v[1] = i1.v[1] | i2.v[1];
452         ret.v[2] = i1.v[2] | i2.v[2];
453         ret.v[3] = i1.v[3] | i2.v[3];
454         return ret;
455 }
456
457 gs_uint32_t hfta_ipv6_hashfunc(const hfta_ipv6_str *s) {
458         return s->v[0] ^ s->v[1] ^ s->v[2] ^ s->v[3];
459 }
460
461 hfta_ipv6_str hton_ipv6(hfta_ipv6_str s){
462         hfta_ipv6_str ret;
463
464 //      ret.v[0] = htonl(s.v[0]);
465 //      ret.v[1] = htonl(s.v[1]);
466 //      ret.v[2] = htonl(s.v[2]);
467 //      ret.v[3] = htonl(s.v[3]);
468         ret.v[0] = s.v[0];
469         ret.v[1] = s.v[1];
470         ret.v[2] = s.v[2];
471         ret.v[3] = s.v[3];
472         return ret;
473 }
474
475 hfta_ipv6_str ntoh_ipv6(hfta_ipv6_str s){
476         hfta_ipv6_str ret;
477 //      ret.v[0] = ntohl(s.v[0]);
478 //      ret.v[1] = ntohl(s.v[1]);
479 //      ret.v[2] = ntohl(s.v[2]);
480 //      ret.v[3] = ntohl(s.v[3]);
481         ret.v[0] = s.v[0];
482         ret.v[1] = s.v[1];
483         ret.v[2] = s.v[2];
484         ret.v[3] = s.v[3];
485         return ret;
486 }
487
488 int HFTA_Ipv6_Constructor(hfta_ipv6_str *s, gs_csp_t l) {
489         gs_uint32_t i0=0,i1=0,i2=0,i3=0,i4=0,i5=0,i6=0,i7=0;
490         sscanf(l,"%x:%x:%x:%x:%x:%x:%x:%x",&i0,&i1,&i2,&i3,&i4,&i5,&i6,&i7);
491         s->v[0] = ((i0 & 0xffff) << 16) | (i1 & 0xffff);
492         s->v[1] = ((i2 & 0xffff) << 16) | (i3 & 0xffff);
493         s->v[2] = ((i4 & 0xffff) << 16) | (i5 & 0xffff);
494         s->v[3] = ((i6 & 0xffff) << 16) | (i7 & 0xffff);
495     return(0);
496 }
497
498 gs_retval_t str_exists_substr(vstring * s1,vstring * s2)
499 {
500   gs_uint8_t *st1 = (gs_uint8_t *)s1->offset;
501   gs_uint8_t *st2 = (gs_uint8_t *)s2->offset;
502   gs_uint8_t *s2f = (gs_uint8_t *)s2->offset;
503   gs_uint8_t len1 = s1->length-s2->length;
504   gs_uint8_t len2 = s2->length;
505   gs_uint8_t x,y;
506
507   for (x=0; x<len1 ; x++)
508   {
509       if (st1[x]== *s2f)
510         {
511           for (y=0; y<len2 && st1[x+y]==st2[y];y++);
512           if (y==len2)
513               return 1;
514         }
515   }
516   return 0;
517 }
518
519 gs_retval_t str_compare(vstring *s1,vstring *s2)
520 {
521   return hfta_vstr_compare(s1,s2);
522 }
523
524 gs_uint32_t str_match_offset( gs_uint32_t offset, vstring *s1, vstring *s2)
525 {
526   gs_uint8_t *st1 = (gs_uint8_t *)s1->offset;
527   gs_uint8_t *st2 = &(((gs_uint8_t *)s2->offset)[offset]);
528   gs_int32_t x;
529   gs_int32_t len2 = s2->length-offset;
530   gs_int32_t len1 = s1->length;
531
532   if (len2 < len1)
533     return 0;
534
535   for(x = 0; x < len1; x++)
536     {
537       if (st1[x] != st2[x])
538         return 0;
539     }
540   return 1;
541 }
542
543 gs_uint32_t byte_match_offset( gs_uint32_t offset, gs_uint32_t val,vstring *s2)
544 {
545   gs_uint8_t *st2 = (gs_uint8_t *)s2->offset;
546   gs_uint8_t v = (unsigned char) val;
547
548 //  if ((s2->length <= offset)||(offset<0))
549   if (s2->length <= offset)
550       return 0;
551
552   return (st2[offset]==v)?1:0;
553 }
554
555
556 // -------------------------------------------------------
557 //              map_int_to_string and its support functions, structs
558
559 struct int_to_string_map_struct{
560         std::map<gs_int64_t, vstring> i2s_map;
561         std::string fname;
562         vstring empty_string;
563 };
564
565 gs_param_handle_t register_handle_for_int_to_string_map_slot_1(vstring *filename){
566         int_to_string_map_struct *map_struct;
567
568         map_struct = new int_to_string_map_struct();
569         if(map_struct == NULL){
570                 gslog(LOG_EMERG, "int_to_string_map:: Could not allocate handle memory\n");
571                 return 0;
572         }
573
574         map_struct->empty_string.offset = (gs_p_t)malloc(1);
575         map_struct->empty_string.reserved = INTERNAL;
576         map_struct->empty_string.length = 0;
577
578         gs_sp_t filenamec;
579         filenamec = (gs_sp_t)alloca(filename->length+1);
580         if (filenamec==0) {
581                 gslog(LOG_EMERG, "int_to_string_map:: Could not allocate filename memory\n");
582                 return 0;
583         }
584         memcpy(filenamec,(gs_sp_t)filename->offset,filename->length);
585         filenamec[filename->length]=0;  
586         map_struct->fname = filenamec;
587
588         FILE *fl = fopen(filenamec, "r");
589         if(fl==NULL){
590                 gslog(LOG_EMERG, "int_to_string_map:: Could not open regex file %s \n",filename);
591                 return 0;
592         }
593         
594         gs_int32_t buflen = 10000;
595         char buf[buflen], buf_str[buflen];
596         gs_int64_t val;
597         char *fret;
598         fret = fgets(buf, buflen, fl);
599         while(fret != NULL){
600                 int nvals = sscanf(buf, "%lld,%s", &val, buf_str);
601                 if(nvals >= 2){
602                         vstring new_str;
603                         new_str.reserved = SHALLOW_COPY;
604                         new_str.length = strlen(buf_str);
605                         new_str.offset = (gs_p_t)malloc(new_str.length);
606                         memcpy((char *)new_str.offset, buf_str, new_str.length);
607                         map_struct->i2s_map[val] = new_str;
608                 }
609                 fret = fgets(buf, buflen, fl);
610         }
611
612         fclose(fl);
613
614         return (gs_param_handle_t) map_struct;
615 }
616
617 gs_retval_t int_to_string_map(vstring *result, gs_int64_t val, gs_param_handle_t handle){
618         int_to_string_map_struct *map_struct = (int_to_string_map_struct *)handle;
619         if(map_struct->i2s_map.count(val)>0){
620                 vstring ret = map_struct->i2s_map[val];
621                 result->offset = ret.offset;
622                 result->reserved = ret.reserved;
623                 result->length = ret.length;
624         }else{
625                 result->offset = map_struct->empty_string.offset;
626                 result->reserved = map_struct->empty_string.reserved;
627                 result->length = map_struct->empty_string.length;
628         }
629
630         return 0;
631 }
632
633 gs_param_handle_t deregister_handle_for_int_to_string_map_slot_1(gs_param_handle_t handle){
634         int_to_string_map_struct *map_struct = (int_to_string_map_struct *)handle;
635         for(std::map<gs_int64_t, vstring>::iterator i2si = map_struct->i2s_map.begin(); i2si!=map_struct->i2s_map.end(); ++i2si){
636                 free((void *)((*i2si).second.offset));
637         }
638         free((void *)(map_struct->empty_string.offset));
639         delete map_struct;
640 }
641