Add to_hex_string UDAF
[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 static gs_uint32_t nextint(struct vstring *str , gs_uint32_t * offset, gs_uint32_t *res) {
362         gs_uint8_t * s = (gs_uint8_t *)(str->offset);
363         int v = 0;
364         *res = 0;
365         while(*offset<str->length) {
366                 if ((s[*offset]>='0') && (s[*offset]<='9')) {
367                         v=1;
368                         *res= (*res*10) + (gs_uint32_t) (s[*offset]-'0');
369                 } else {
370                         if (v!=0) { // got some valid result
371                                 return 1;
372                         } // otherwise skip leading grabage
373                 }
374                 (*offset)++;
375         }
376         return v;
377 }
378
379 gs_uint32_t strtoi(gs_uint32_t * r, struct vstring * s)
380 {
381         gs_uint32_t offset;
382         offset=0;
383         if (nextint(s,&offset,r)==0) return 1;
384         return 0;
385 }
386
387 gs_param_handle_t register_handle_for_strtoi_c_slot_0(vstring* istr) {
388         gs_uint32_t offset,r;
389         offset=0;
390         if (nextint(istr,&offset,&r)!=0)
391                 return (gs_param_handle_t) r;
392         return (gs_param_handle_t) 0;
393 }
394 gs_retval_t deregister_handle_for_strtoi_c_slot_0(gs_param_handle_t h) {
395         return 0;
396 }
397
398
399 gs_uint32_t strtoip(gs_uint32_t * r, struct vstring * s)
400 {
401         gs_uint32_t ip1,ip2,ip3,ip4,offset;
402         offset=0;
403         if (nextint(s,&offset,&ip1)==0) return 1;
404         //fprintf (stderr, "1 %u %u\n",ip1,offset);
405         if (nextint(s,&offset,&ip2)==0) return 1;
406         //fprintf (stderr, "2 %u %u\n",ip2,offset);
407         if (nextint(s,&offset,&ip3)==0) return 1;
408         //fprintf (stderr, "3 %u %u\n",ip3,offset);
409         if (nextint(s,&offset,&ip4)==0) return 1;
410         //fprintf (stderr, "4 %u %u\n",ip4,offset);
411         *r=ip1<<24|ip2<<16|ip3<<8|ip4;
412         return 0;
413 }
414
415 gs_param_handle_t register_handle_for_strtoip_c_slot_0(vstring* istr) {
416         gs_uint32_t ip1,ip2,ip3,ip4,offset,r;
417         offset=0;
418         if (nextint(istr,&offset,&ip1)==0) return (gs_param_handle_t)0;
419         if (nextint(istr,&offset,&ip2)==0) return (gs_param_handle_t)0;
420         if (nextint(istr,&offset,&ip3)==0) return (gs_param_handle_t)0;
421         if (nextint(istr,&offset,&ip4)==0) return (gs_param_handle_t)0;
422         r=ip1<<24|ip2<<16|ip3<<8|ip4;
423                 return (gs_param_handle_t)r;
424 }
425 gs_retval_t deregister_handle_for_strtoip_c_slot_0(gs_param_handle_t h) {
426         return 0;
427 }
428
429 gs_uint32_t partn_hash(  gs_uint32_t ip1, gs_uint32_t ip2) {
430     return (ip1^ip2);
431 }
432
433 gs_uint32_t rand_hash() {
434     return rand();
435 }
436
437 ///////////////////////////////////////
438 //              IPv6 fcns.
439 //      return negative if s1 < s2, 0 if s1==s2, positive if s1>s2
440 gs_retval_t hfta_ipv6_compare(const hfta_ipv6_str &i1, const hfta_ipv6_str &i2) {
441     if(i1.v[0] > i2.v[0])
442         return 1;
443     if(i1.v[0] < i2.v[0])
444         return -1;
445     if(i1.v[1] > i2.v[1])
446         return 1;
447     if(i1.v[1] < i2.v[1])
448         return -1;
449     if(i1.v[2] > i2.v[2])
450         return 1;
451     if(i1.v[2] < i2.v[2])
452         return -1;
453     if(i1.v[3] > i2.v[3])
454         return 1;
455     if(i1.v[3] < i2.v[3])
456         return -1;
457
458     return 0;
459 }
460
461 hfta_ipv6_str And_Ipv6(const hfta_ipv6_str &i1, const hfta_ipv6_str &i2){
462         hfta_ipv6_str ret;
463         ret.v[0] = i1.v[0] & i2.v[0];
464         ret.v[1] = i1.v[1] & i2.v[1];
465         ret.v[2] = i1.v[2] & i2.v[2];
466         ret.v[3] = i1.v[3] & i2.v[3];
467         return ret;
468 }
469
470 hfta_ipv6_str Or_Ipv6(const hfta_ipv6_str &i1, const hfta_ipv6_str &i2){
471         hfta_ipv6_str ret;
472         ret.v[0] = i1.v[0] | i2.v[0];
473         ret.v[1] = i1.v[1] | i2.v[1];
474         ret.v[2] = i1.v[2] | i2.v[2];
475         ret.v[3] = i1.v[3] | i2.v[3];
476         return ret;
477 }
478
479 gs_uint32_t hfta_ipv6_hashfunc(const hfta_ipv6_str *s) {
480         return s->v[0] ^ s->v[1] ^ s->v[2] ^ s->v[3];
481 }
482
483 hfta_ipv6_str hton_ipv6(hfta_ipv6_str s){
484         hfta_ipv6_str ret;
485
486 //      ret.v[0] = htonl(s.v[0]);
487 //      ret.v[1] = htonl(s.v[1]);
488 //      ret.v[2] = htonl(s.v[2]);
489 //      ret.v[3] = htonl(s.v[3]);
490         ret.v[0] = s.v[0];
491         ret.v[1] = s.v[1];
492         ret.v[2] = s.v[2];
493         ret.v[3] = s.v[3];
494         return ret;
495 }
496
497 hfta_ipv6_str ntoh_ipv6(hfta_ipv6_str s){
498         hfta_ipv6_str ret;
499 //      ret.v[0] = ntohl(s.v[0]);
500 //      ret.v[1] = ntohl(s.v[1]);
501 //      ret.v[2] = ntohl(s.v[2]);
502 //      ret.v[3] = ntohl(s.v[3]);
503         ret.v[0] = s.v[0];
504         ret.v[1] = s.v[1];
505         ret.v[2] = s.v[2];
506         ret.v[3] = s.v[3];
507         return ret;
508 }
509
510 int HFTA_Ipv6_Constructor(hfta_ipv6_str *s, gs_csp_t l) {
511         gs_uint32_t i0=0,i1=0,i2=0,i3=0,i4=0,i5=0,i6=0,i7=0;
512         sscanf(l,"%x:%x:%x:%x:%x:%x:%x:%x",&i0,&i1,&i2,&i3,&i4,&i5,&i6,&i7);
513         s->v[0] = ((i0 & 0xffff) << 16) | (i1 & 0xffff);
514         s->v[1] = ((i2 & 0xffff) << 16) | (i3 & 0xffff);
515         s->v[2] = ((i4 & 0xffff) << 16) | (i5 & 0xffff);
516         s->v[3] = ((i6 & 0xffff) << 16) | (i7 & 0xffff);
517     return(0);
518 }
519
520 gs_retval_t str_exists_substr(vstring * s1,vstring * s2)
521 {
522   gs_uint8_t *st1 = (gs_uint8_t *)s1->offset;
523   gs_uint8_t *st2 = (gs_uint8_t *)s2->offset;
524   gs_uint8_t *s2f = (gs_uint8_t *)s2->offset;
525   gs_uint8_t len1 = s1->length-s2->length;
526   gs_uint8_t len2 = s2->length;
527   gs_uint8_t x,y;
528
529   for (x=0; x<len1 ; x++)
530   {
531       if (st1[x]== *s2f)
532         {
533           for (y=0; y<len2 && st1[x+y]==st2[y];y++);
534           if (y==len2)
535               return 1;
536         }
537   }
538   return 0;
539 }
540
541 gs_retval_t str_compare(vstring *s1,vstring *s2)
542 {
543   return hfta_vstr_compare(s1,s2);
544 }
545
546 gs_uint32_t str_match_offset( gs_uint32_t offset, vstring *s1, vstring *s2)
547 {
548   gs_uint8_t *st1 = (gs_uint8_t *)s1->offset;
549   gs_uint8_t *st2 = &(((gs_uint8_t *)s2->offset)[offset]);
550   gs_int32_t x;
551   gs_int32_t len2 = s2->length-offset;
552   gs_int32_t len1 = s1->length;
553
554   if (len2 < len1)
555     return 0;
556
557   for(x = 0; x < len1; x++)
558     {
559       if (st1[x] != st2[x])
560         return 0;
561     }
562   return 1;
563 }
564
565 gs_uint32_t byte_match_offset( gs_uint32_t offset, gs_uint32_t val,vstring *s2)
566 {
567   gs_uint8_t *st2 = (gs_uint8_t *)s2->offset;
568   gs_uint8_t v = (unsigned char) val;
569
570 //  if ((s2->length <= offset)||(offset<0))
571   if (s2->length <= offset)
572       return 0;
573
574   return (st2[offset]==v)?1:0;
575 }
576
577
578 // -------------------------------------------------------
579 //              map_int_to_string and its support functions, structs
580
581 struct int_to_string_map_struct{
582         std::map<gs_int64_t, vstring> i2s_map;
583         std::string fname;
584         vstring empty_string;
585 };
586
587 gs_param_handle_t register_handle_for_int_to_string_map_slot_1(vstring *filename){
588         int_to_string_map_struct *map_struct;
589
590         map_struct = new int_to_string_map_struct();
591         if(map_struct == NULL){
592                 gslog(LOG_EMERG, "int_to_string_map:: Could not allocate handle memory\n");
593                 return 0;
594         }
595
596         map_struct->empty_string.offset = (gs_p_t)malloc(1);
597         map_struct->empty_string.reserved = INTERNAL;
598         map_struct->empty_string.length = 0;
599
600         gs_sp_t filenamec;
601         filenamec = (gs_sp_t)alloca(filename->length+1);
602         if (filenamec==0) {
603                 gslog(LOG_EMERG, "int_to_string_map:: Could not allocate filename memory\n");
604                 return 0;
605         }
606         memcpy(filenamec,(gs_sp_t)filename->offset,filename->length);
607         filenamec[filename->length]=0;  
608         map_struct->fname = filenamec;
609
610         FILE *fl = fopen(filenamec, "r");
611         if(fl==NULL){
612                 gslog(LOG_EMERG, "int_to_string_map:: Could not open regex file %s \n",filename);
613                 return 0;
614         }
615         
616         gs_int32_t buflen = 10000;
617         char buf[buflen], buf_str[buflen];
618         gs_int64_t val;
619         char *fret;
620         fret = fgets(buf, buflen, fl);
621         while(fret != NULL){
622                 int nvals = sscanf(buf, "%lld,%s", &val, buf_str);
623                 if(nvals >= 2){
624                         vstring new_str;
625                         new_str.reserved = SHALLOW_COPY;
626                         new_str.length = strlen(buf_str);
627                         new_str.offset = (gs_p_t)malloc(new_str.length);
628                         memcpy((char *)new_str.offset, buf_str, new_str.length);
629                         map_struct->i2s_map[val] = new_str;
630                 }
631                 fret = fgets(buf, buflen, fl);
632         }
633
634         fclose(fl);
635
636         return (gs_param_handle_t) map_struct;
637 }
638
639 gs_retval_t int_to_string_map(vstring *result, gs_int64_t val, gs_param_handle_t handle){
640         int_to_string_map_struct *map_struct = (int_to_string_map_struct *)handle;
641         if(map_struct->i2s_map.count(val)>0){
642                 vstring ret = map_struct->i2s_map[val];
643                 result->offset = ret.offset;
644                 result->reserved = ret.reserved;
645                 result->length = ret.length;
646         }else{
647                 result->offset = map_struct->empty_string.offset;
648                 result->reserved = map_struct->empty_string.reserved;
649                 result->length = map_struct->empty_string.length;
650         }
651
652         return 0;
653 }
654
655 gs_param_handle_t deregister_handle_for_int_to_string_map_slot_1(gs_param_handle_t handle){
656         int_to_string_map_struct *map_struct = (int_to_string_map_struct *)handle;
657         for(std::map<gs_int64_t, vstring>::iterator i2si = map_struct->i2s_map.begin(); i2si!=map_struct->i2s_map.end(); ++i2si){
658                 free((void *)((*i2si).second.offset));
659         }
660         free((void *)(map_struct->empty_string.offset));
661         delete map_struct;
662 }
663
664 // ---------------------------------------------------
665 //              Return a (binary, non-ascii) string in its hex representation
666
667 static char hexmap[16] = {
668   '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'
669 };
670
671 gs_retval_t to_hex_string(vstring *result, vstring *val){
672         result->length = 2*(val->length);
673         result->offset = (gs_p_t)malloc(result->length);
674         result->reserved = INTERNAL;
675         unsigned char *rs = (unsigned char *)(result->offset);
676         unsigned char *vs = (unsigned char *)(val->offset);
677
678         for(int c=0;c<val->length; ++c){
679                 rs[2*c] = hexmap[vs[c] >> 4];
680                 rs[2*c+1] = hexmap[vs[c] & 0x0f];
681         }
682
683         return 0;
684 }
685
686
687