f9b057a2f70ad4bfc8218f4fa26d6e09a69789ad
[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,
69                 const vstring * src, 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, const 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, const 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 gs_retval_t hfta_vstr_equal(const vstring * s1, const vstring * s2) {
175         gs_int32_t x;
176
177         if(s1->length != s2->length)
178                 return -1;
179
180 //      cmp_ret=memcmp((void *)s1->offset,(void *)s2->offset,s1->length);
181     for(x=0;x<s1->length;x++) {
182         if (((char *)(s1->offset))[x]!=((char *)(s2->offset))[x]) {
183             return -1;
184         }
185     }
186
187
188         return 0;
189 }
190
191
192
193 gs_param_handle_t register_handle_for_str_regex_match_slot_1(vstring* pattern) {
194     regex_t * reg;
195     gs_int32_t res;
196
197     if ((reg=(regex_t *) malloc(sizeof(regex_t)))==0)  {
198         gslog(LOG_EMERG, "No memory for regular expression %s\n",
199                 (gs_sp_t)(pattern->offset));
200         return 0;
201     }
202
203     if (regcomp(reg,(char*)(pattern->offset), REG_NEWLINE|REG_EXTENDED|REG_NOSUB)!=0) {
204         gslog(LOG_EMERG, "Illegal regular expression %s\n",
205                 (gs_sp_t)(pattern->offset));
206         return 0;
207     }
208     return (gs_param_handle_t) reg;
209 }
210
211 gs_uint32_t str_regex_match(vstring* str, gs_param_handle_t pattern_handle) {
212     regex_t * reg = (regex_t *) pattern_handle ;
213     gs_int32_t res;
214     static gs_sp_t d=0;
215     static gs_uint32_t dlen=0;
216     // grow our static buffer to the longest string we ever see
217     if ((str->length+1) >= dlen) {
218         if (d!=0) free((void*)d);
219         dlen=0;
220         d=0;
221         if ((d=(gs_sp_t)malloc(str->length+1))==0) return 0;
222         dlen=str->length+1;
223     }
224     
225     if (str->length==0) return 0;
226     
227     // copy the string and 0 terminate it
228     memcpy((void *)d,(void *) str->offset, str->length);
229     d[str->length]=0;
230     
231     res = REG_NOMATCH;
232     res = regexec(reg, d, 0, NULL, 0);
233     return (res==REG_NOMATCH)?0:1;
234 }
235
236 gs_retval_t deregister_handle_for_str_regex_match_slot_1(gs_param_handle_t handle) {
237     regex_t * x = (regex_t *) handle;
238     regfree(x);
239     if (x!=0) free(x);
240     return 0;
241 }
242
243 gs_param_handle_t register_handle_for_str_partial_regex_match_slot_1(vstring* pattern) {
244     regex_t * reg;
245     gs_int32_t res;
246
247     if ((reg=(regex_t *) malloc(sizeof(regex_t)))==0)  {
248         gslog(LOG_EMERG, "No memory for regular expression %s\n",
249                 (gs_sp_t)(pattern->offset));
250         return 0;
251     }
252
253     if (regcomp(reg,(gs_sp_t)(pattern->offset), REG_NEWLINE|REG_EXTENDED|REG_NOSUB)!=0) {
254         gslog(LOG_EMERG, "Illegal regular expression %s\n",
255                 (gs_sp_t)(pattern->offset));
256         return 0;
257     }
258     return (gs_param_handle_t) reg;
259 }
260
261 gs_uint32_t str_partial_regex_match(vstring* str, gs_param_handle_t pattern_handle,
262                              uint maxlen) {
263     regex_t * reg = (regex_t *) pattern_handle ;
264     gs_int32_t res;
265     gs_int32_t end;
266     static gs_sp_t d=0;
267     static gs_uint32_t dlen=0;
268     // grow our static buffer to the longest string we ever see
269     if ((str->length+1) >= dlen) {
270         if (d!=0) free((void*)d);
271         dlen=0;
272         d=0;
273         if ((d=(gs_sp_t)malloc(str->length+1))==0) return 0;
274         dlen=str->length+1;
275     }
276     
277     if (str->length==0) return 0;
278     
279     end=(maxlen>(str->length))?(str->length):maxlen;
280     
281     // copy the string and 0 terminate it
282     memcpy((void *)d,(void *) str->offset, end);
283     d[end]=0;
284  
285     res = REG_NOMATCH;
286     res = regexec(reg, d,0, NULL, 0);
287     return (res==REG_NOMATCH)?0:1;
288 }
289
290
291 gs_retval_t deregister_handle_for_str_partial_regex_match_slot_1(
292                                              gs_param_handle_t handle) {
293     regex_t * x = (regex_t *) handle;
294     regfree(x);
295     if (x!=0) free(x);
296     return 0;
297 }
298
299 gs_param_handle_t register_handle_for_str_extract_regex_slot_1(vstring* pattern) {
300     regex_t * reg;
301     
302     if ((reg=(regex_t *) malloc(sizeof(regex_t)))==0)  {
303         gslog(LOG_EMERG, "No memory for regular expression %s\n",
304               (gs_sp_t)(pattern->offset));
305         return 0;
306     }
307     if (regcomp(reg,(gs_sp_t)(pattern->offset), REG_EXTENDED)!=0) {
308         gslog(LOG_EMERG, "Illegal regular expression %s\n",
309               (gs_sp_t)(pattern->offset));
310         return 0;
311     }
312     return (gs_param_handle_t) reg;
313 }
314
315
316 /* partial function return 0 if the value is valid */
317 gs_retval_t str_extract_regex( vstring * result, vstring * str, gs_param_handle_t handle) {
318     regex_t * reg = (regex_t *) handle ;
319     gs_sp_t source = (gs_sp_t)(str->offset);
320     gs_retval_t res;
321     regmatch_t match;
322     static gs_sp_t d=0;
323     static gs_uint32_t dlen=0;
324     // grow our static buffer to the longest string we ever see
325     if ((str->length+1) >= dlen) {
326         if (d!=0) free((void*)d);
327         dlen=0;
328         d=0;
329         if ((d=(gs_sp_t)malloc(str->length+1))==0) return 1;
330         dlen=str->length+1;
331     }
332     
333     if (str->length==0) return 1;
334     
335     // copy the string and 0 terminate it
336     memcpy((void *)d,(void *) str->offset, str->length);
337     d[str->length]=0;
338
339     res = REG_NOMATCH;
340     res = regexec(reg, d, 1, &match, 0);
341     if (res==REG_NOMATCH) return 1;
342     result->offset= (gs_p_t) &source[match.rm_so];
343     result->length=match.rm_eo-match.rm_so;
344     result->reserved = SHALLOW_COPY;
345     return 0;
346 }
347
348 gs_retval_t deregister_handle_for_str_extract_regex_slot_1(gs_param_handle_t handle) {
349     regex_t * x = (regex_t *) handle;
350     regfree(x);
351     if (x!=0) free(x);
352     return 0;
353 }
354
355
356 static gs_uint32_t nextint(struct vstring *str , gs_uint32_t * offset, gs_uint32_t *res) {
357         gs_uint8_t * s = (gs_uint8_t *)(str->offset);
358         int v = 0;
359         *res = 0;
360         while(*offset<str->length) {
361                 if ((s[*offset]>='0') && (s[*offset]<='9')) {
362                         v=1;
363                         *res= (*res*10) + (gs_uint32_t) (s[*offset]-'0');
364                 } else {
365                         if (v!=0) { // got some valid result
366                                 return 1;
367                         } // otherwise skip leading grabage
368                 }
369                 (*offset)++;
370         }
371         return v;
372 }
373
374 gs_uint32_t strtoi(gs_uint32_t * r, struct vstring * s)
375 {
376         gs_uint32_t offset;
377         offset=0;
378         if (nextint(s,&offset,r)==0) return 1;
379         return 0;
380 }
381
382 gs_param_handle_t register_handle_for_strtoi_c_slot_0(vstring* istr) {
383         gs_uint32_t offset,r;
384         offset=0;
385         if (nextint(istr,&offset,&r)!=0)
386                 return (gs_param_handle_t) r;
387         return (gs_param_handle_t) 0;
388 }
389 gs_retval_t deregister_handle_for_strtoi_c_slot_0(gs_param_handle_t h) {
390         return 0;
391 }
392
393
394 gs_uint32_t strtoip(gs_uint32_t * r, struct vstring * s)
395 {
396         gs_uint32_t ip1,ip2,ip3,ip4,offset;
397         offset=0;
398         if (nextint(s,&offset,&ip1)==0) return 1;
399         //fprintf (stderr, "1 %u %u\n",ip1,offset);
400         if (nextint(s,&offset,&ip2)==0) return 1;
401         //fprintf (stderr, "2 %u %u\n",ip2,offset);
402         if (nextint(s,&offset,&ip3)==0) return 1;
403         //fprintf (stderr, "3 %u %u\n",ip3,offset);
404         if (nextint(s,&offset,&ip4)==0) return 1;
405         //fprintf (stderr, "4 %u %u\n",ip4,offset);
406         *r=ip1<<24|ip2<<16|ip3<<8|ip4;
407         return 0;
408 }
409
410 gs_param_handle_t register_handle_for_strtoip_c_slot_0(vstring* istr) {
411         gs_uint32_t ip1,ip2,ip3,ip4,offset,r;
412         offset=0;
413         if (nextint(istr,&offset,&ip1)==0) return (gs_param_handle_t)0;
414         if (nextint(istr,&offset,&ip2)==0) return (gs_param_handle_t)0;
415         if (nextint(istr,&offset,&ip3)==0) return (gs_param_handle_t)0;
416         if (nextint(istr,&offset,&ip4)==0) return (gs_param_handle_t)0;
417         r=ip1<<24|ip2<<16|ip3<<8|ip4;
418                 return (gs_param_handle_t)r;
419 }
420 gs_retval_t deregister_handle_for_strtoip_c_slot_0(gs_param_handle_t h) {
421         return 0;
422 }
423
424 gs_uint32_t partn_hash(  gs_uint32_t ip1, gs_uint32_t ip2) {
425     return (ip1^ip2);
426 }
427
428 gs_uint32_t rand_hash() {
429     return rand();
430 }
431
432 ///////////////////////////////////////
433 //              IPv6 fcns.
434 //      return negative if s1 < s2, 0 if s1==s2, positive if s1>s2
435 gs_retval_t hfta_ipv6_compare(const hfta_ipv6_str &i1, const hfta_ipv6_str &i2) {
436     if(i1.v[0] > i2.v[0])
437         return 1;
438     if(i1.v[0] < i2.v[0])
439         return -1;
440     if(i1.v[1] > i2.v[1])
441         return 1;
442     if(i1.v[1] < i2.v[1])
443         return -1;
444     if(i1.v[2] > i2.v[2])
445         return 1;
446     if(i1.v[2] < i2.v[2])
447         return -1;
448     if(i1.v[3] > i2.v[3])
449         return 1;
450     if(i1.v[3] < i2.v[3])
451         return -1;
452
453     return 0;
454 }
455
456 hfta_ipv6_str And_Ipv6(const hfta_ipv6_str &i1, const hfta_ipv6_str &i2){
457         hfta_ipv6_str ret;
458         ret.v[0] = i1.v[0] & i2.v[0];
459         ret.v[1] = i1.v[1] & i2.v[1];
460         ret.v[2] = i1.v[2] & i2.v[2];
461         ret.v[3] = i1.v[3] & i2.v[3];
462         return ret;
463 }
464
465 hfta_ipv6_str Or_Ipv6(const hfta_ipv6_str &i1, const hfta_ipv6_str &i2){
466         hfta_ipv6_str ret;
467         ret.v[0] = i1.v[0] | i2.v[0];
468         ret.v[1] = i1.v[1] | i2.v[1];
469         ret.v[2] = i1.v[2] | i2.v[2];
470         ret.v[3] = i1.v[3] | i2.v[3];
471         return ret;
472 }
473
474 gs_uint32_t hfta_ipv6_hashfunc(const hfta_ipv6_str *s) {
475         return s->v[0] ^ s->v[1] ^ s->v[2] ^ s->v[3];
476 }
477
478 hfta_ipv6_str hton_ipv6(hfta_ipv6_str s){
479         hfta_ipv6_str ret;
480
481 //      ret.v[0] = htonl(s.v[0]);
482 //      ret.v[1] = htonl(s.v[1]);
483 //      ret.v[2] = htonl(s.v[2]);
484 //      ret.v[3] = htonl(s.v[3]);
485         ret.v[0] = s.v[0];
486         ret.v[1] = s.v[1];
487         ret.v[2] = s.v[2];
488         ret.v[3] = s.v[3];
489         return ret;
490 }
491
492 hfta_ipv6_str ntoh_ipv6(hfta_ipv6_str s){
493         hfta_ipv6_str ret;
494 //      ret.v[0] = ntohl(s.v[0]);
495 //      ret.v[1] = ntohl(s.v[1]);
496 //      ret.v[2] = ntohl(s.v[2]);
497 //      ret.v[3] = ntohl(s.v[3]);
498         ret.v[0] = s.v[0];
499         ret.v[1] = s.v[1];
500         ret.v[2] = s.v[2];
501         ret.v[3] = s.v[3];
502         return ret;
503 }
504
505 int HFTA_Ipv6_Constructor(hfta_ipv6_str *s, gs_csp_t l) {
506         gs_uint32_t i0=0,i1=0,i2=0,i3=0,i4=0,i5=0,i6=0,i7=0;
507         sscanf(l,"%x:%x:%x:%x:%x:%x:%x:%x",&i0,&i1,&i2,&i3,&i4,&i5,&i6,&i7);
508         s->v[0] = ((i0 & 0xffff) << 16) | (i1 & 0xffff);
509         s->v[1] = ((i2 & 0xffff) << 16) | (i3 & 0xffff);
510         s->v[2] = ((i4 & 0xffff) << 16) | (i5 & 0xffff);
511         s->v[3] = ((i6 & 0xffff) << 16) | (i7 & 0xffff);
512     return(0);
513 }
514
515 gs_retval_t str_exists_substr(vstring * s1,vstring * s2)
516 {
517   gs_uint8_t *st1 = (gs_uint8_t *)s1->offset;
518   gs_uint8_t *st2 = (gs_uint8_t *)s2->offset;
519   gs_uint8_t *s2f = (gs_uint8_t *)s2->offset;
520   gs_uint8_t len1 = s1->length-s2->length;
521   gs_uint8_t len2 = s2->length;
522   gs_uint8_t x,y;
523
524   for (x=0; x<len1 ; x++)
525   {
526       if (st1[x]== *s2f)
527         {
528           for (y=0; y<len2 && st1[x+y]==st2[y];y++);
529           if (y==len2)
530               return 1;
531         }
532   }
533   return 0;
534 }
535
536 gs_retval_t str_compare(vstring *s1,vstring *s2)
537 {
538   return hfta_vstr_compare(s1,s2);
539 }
540
541 gs_uint32_t str_match_offset( gs_uint32_t offset, vstring *s1, vstring *s2)
542 {
543   gs_uint8_t *st1 = (gs_uint8_t *)s1->offset;
544   gs_uint8_t *st2 = &(((gs_uint8_t *)s2->offset)[offset]);
545   gs_int32_t x;
546   gs_int32_t len2 = s2->length-offset;
547   gs_int32_t len1 = s1->length;
548
549   if (len2 < len1)
550     return 0;
551
552   for(x = 0; x < len1; x++)
553     {
554       if (st1[x] != st2[x])
555         return 0;
556     }
557   return 1;
558 }
559
560 gs_uint32_t byte_match_offset( gs_uint32_t offset, gs_uint32_t val,vstring *s2)
561 {
562   gs_uint8_t *st2 = (gs_uint8_t *)s2->offset;
563   gs_uint8_t v = (unsigned char) val;
564
565 //  if ((s2->length <= offset)||(offset<0))
566   if (s2->length <= offset)
567       return 0;
568
569   return (st2[offset]==v)?1:0;
570 }
571
572
573 // -------------------------------------------------------
574 //              map_int_to_string and its support functions, structs
575
576 struct int_to_string_map_struct{
577         std::map<gs_int64_t, vstring> i2s_map;
578         std::string fname;
579         vstring empty_string;
580 };
581
582 gs_param_handle_t register_handle_for_int_to_string_map_slot_1(vstring *filename){
583         int_to_string_map_struct *map_struct;
584
585         map_struct = new int_to_string_map_struct();
586         if(map_struct == NULL){
587                 gslog(LOG_EMERG, "int_to_string_map:: Could not allocate handle memory\n");
588                 return 0;
589         }
590
591         map_struct->empty_string.offset = (gs_p_t)malloc(1);
592         map_struct->empty_string.reserved = INTERNAL;
593         map_struct->empty_string.length = 0;
594
595         gs_sp_t filenamec;
596         filenamec = (gs_sp_t)alloca(filename->length+1);
597         if (filenamec==0) {
598                 gslog(LOG_EMERG, "int_to_string_map:: Could not allocate filename memory\n");
599                 return 0;
600         }
601         memcpy(filenamec,(gs_sp_t)filename->offset,filename->length);
602         filenamec[filename->length]=0;  
603         map_struct->fname = filenamec;
604
605         FILE *fl = fopen(filenamec, "r");
606         if(fl==NULL){
607                 gslog(LOG_EMERG, "int_to_string_map:: Could not open regex file %s \n",filename);
608                 return 0;
609         }
610         
611         gs_int32_t buflen = 10000;
612         char buf[buflen], buf_str[buflen];
613         gs_int64_t val;
614         char *fret;
615         fret = fgets(buf, buflen, fl);
616         while(fret != NULL){
617                 int nvals = sscanf(buf, "%lld,%s", &val, buf_str);
618                 if(nvals >= 2){
619                         vstring new_str;
620                         new_str.reserved = SHALLOW_COPY;
621                         new_str.length = strlen(buf_str);
622                         new_str.offset = (gs_p_t)malloc(new_str.length);
623                         memcpy((char *)new_str.offset, buf_str, new_str.length);
624                         map_struct->i2s_map[val] = new_str;
625                 }
626                 fret = fgets(buf, buflen, fl);
627         }
628
629         fclose(fl);
630
631         return (gs_param_handle_t) map_struct;
632 }
633
634 gs_retval_t int_to_string_map(vstring *result, gs_int64_t val, gs_param_handle_t handle){
635         int_to_string_map_struct *map_struct = (int_to_string_map_struct *)handle;
636         if(map_struct->i2s_map.count(val)>0){
637                 vstring ret = map_struct->i2s_map[val];
638                 result->offset = ret.offset;
639                 result->reserved = ret.reserved;
640                 result->length = ret.length;
641         }else{
642                 result->offset = map_struct->empty_string.offset;
643                 result->reserved = map_struct->empty_string.reserved;
644                 result->length = map_struct->empty_string.length;
645         }
646
647         return 0;
648 }
649
650 gs_param_handle_t deregister_handle_for_int_to_string_map_slot_1(gs_param_handle_t handle){
651         int_to_string_map_struct *map_struct = (int_to_string_map_struct *)handle;
652         for(std::map<gs_int64_t, vstring>::iterator i2si = map_struct->i2s_map.begin(); i2si!=map_struct->i2s_map.end(); ++i2si){
653                 free((void *)((*i2si).second.offset));
654         }
655         free((void *)(map_struct->empty_string.offset));
656         delete map_struct;
657 }
658