Add new udafs and RMR support to gsprintconsole_ves
[com/gs-lite.git] / src / lib / gscphftaaux / hfta_runtime_library.cc
index ab94a01..65a0a2c 100644 (file)
@@ -31,6 +31,8 @@ extern "C" {
 #include <host_tuple.h>
 #include <fta.h>
 
+#include<map>
+
 // for htonl,ntohl
 #include <netinet/in.h>
 
@@ -57,14 +59,19 @@ void hfta_vstr_destroy(vstring * str) {
        str->length = 0;
 }
 
+//     Make the vstring safe to destroy even if its never initialized
+//     (e.g. stack-allocated groups containing strings)
+void hfta_vstr_init(vstring * str) {
+       str->length = 0;
+}
 
 gs_retval_t hfta_vstr_length(vstring *str) {
        return str->length;
 }
 
 //             Assume that SRC is either INTERNAL or SHALLOW_COPY
-void hfta_vstr_assign_with_copy_in_tuple(vstring32 * target, vstring * src,
-       gs_sp_t data_offset,  gs_retval_t int_offset) {
+void hfta_vstr_assign_with_copy_in_tuple(vstring32 * target,
+               const vstring * src, gs_sp_t data_offset,  gs_retval_t int_offset) {
        target->length = src->length;
        target->offset = int_offset;
        target->reserved = PACKED;
@@ -75,7 +82,7 @@ void hfta_vstr_assign_with_copy_in_tuple(vstring32 * target, vstring * src,
 //             Ted wrote the following function.
 //             make deep copy of src.  Assume that dst is already empty.
 //             Assume that SRC is either INTERNAL or SHALLOW_COPY
-void hfta_vstr_assign_with_copy(vstring *dst, vstring *src){
+void hfta_vstr_assign_with_copy(vstring *dst, const vstring *src){
        dst->length=src->length;
        if(src->length){
                dst->offset=(gs_p_t)malloc(dst->length);
@@ -87,11 +94,44 @@ void hfta_vstr_assign_with_copy(vstring *dst, vstring *src){
 //             Ted wrote the following function.
 //             Make a deep copy of src.  garbage collect dst if needed.
 //             Assume that SRC is either INTERNAL or SHALLOW_COPY
-void hfta_vstr_replace(vstring *dst, vstring *src){
+void hfta_vstr_replace(vstring *dst, const vstring *src){
        hfta_vstr_destroy(dst);
        hfta_vstr_assign_with_copy(dst,src);
 }
 
+#define HFTA_VSTR_LHASHFUNC_PRIME 12916008961267169387ull
+gs_uint64_t hfta_vstr_long_hashfunc(const vstring *s) {
+       gs_uint64_t hash_code;
+       gs_int32_t n_steps;
+       gs_int32_t substr_len;
+       gs_int32_t j, k;
+       gs_uint64_t sub_hash;
+       gs_sp_t sv;
+
+       sv=(gs_sp_t)(s->offset);
+       hash_code = 0;
+       n_steps = s->length / 4;
+       if(4*n_steps < s->length) n_steps++;
+
+       for (j = 0; j <  n_steps; j++) {
+               if(4*(j+1) < s->length) substr_len = 4;
+               else                  substr_len = s->length - 4*j;
+
+               sub_hash = 0;
+               for(k=0;k<4;k++){
+                 if(k < substr_len)
+                       sub_hash = (sub_hash << 4) + *sv;
+                 else
+                       sub_hash = (sub_hash << 4);
+                 sv++;
+               }
+
+               hash_code = (sub_hash + hash_code * HFTA_VSTR_LHASHFUNC_PRIME);
+       }
+
+       return(hash_code);
+}
+
 #define HFTA_VSTR_HASHFUNC_PRIME 2995999
 gs_uint32_t hfta_vstr_hashfunc(const vstring *s) {
        gs_uint32_t hash_code;
@@ -101,7 +141,6 @@ gs_uint32_t hfta_vstr_hashfunc(const vstring *s) {
        gs_uint32_t k, sub_hash;
        gs_sp_t sv;
 
-
        sv=(gs_sp_t)(s->offset);
        hash_code = 0;
        n_steps = s->length / 4;
@@ -126,6 +165,7 @@ gs_uint32_t hfta_vstr_hashfunc(const vstring *s) {
        return(hash_code);
 }
 
+
 //     return negative if s1 < s2, 0 if s1==s2, positive if s1>s2
 gs_retval_t hfta_vstr_compare(const vstring * s1, const vstring * s2) {
        gs_int32_t minlen,cmp_ret;
@@ -136,6 +176,23 @@ gs_retval_t hfta_vstr_compare(const vstring * s1, const vstring * s2) {
        return(s1->length - s2->length);
 }
 
+gs_retval_t hfta_vstr_equal(const vstring * s1, const vstring * s2) {
+       gs_int32_t x;
+
+       if(s1->length != s2->length)
+               return -1;
+
+//     cmp_ret=memcmp((void *)s1->offset,(void *)s2->offset,s1->length);
+    for(x=0;x<s1->length;x++) {
+        if (((char *)(s1->offset))[x]!=((char *)(s2->offset))[x]) {
+            return -1;
+        }
+    }
+
+
+       return 0;
+}
+
 
 
 gs_param_handle_t register_handle_for_str_regex_match_slot_1(vstring* pattern) {
@@ -300,6 +357,54 @@ gs_retval_t deregister_handle_for_str_extract_regex_slot_1(gs_param_handle_t han
     return 0;
 }
 
+// -------------------------------------------------
+//             More substring functions
+
+//      get last n bytes, if available
+//      getting the prefix is done by str_truncate, defined in the include file
+gs_retval_t str_suffix(vstring *result,  vstring *s, gs_uint32_t n){
+  register gs_p_t st = (gs_p_t)s->offset; 
+  int prefix = (n > s->length) ? 0 : s->length-n;  
+  result->offset = st + prefix;
+  result->length = s->length-prefix;
+  result->reserved = SHALLOW_COPY;
+  return 0;
+}
+
+
+//     Split the string on sep, get the i'th substring, if any
+gs_retval_t get_list_entry(vstring *result, vstring *l,  vstring *sep, gs_uint32_t pos){
+       char s;
+       gs_int32_t c;
+
+       result->offset = l->offset;     // empty return string
+       result->reserved = SHALLOW_COPY;
+       result->length = 0;
+
+       if(sep->length > 0){    // get the sep char, ensure the string is nonempty
+               s = ((gs_sp_t)(sep->offset))[0];
+       }else{
+               return 0;
+       }
+
+       for(c=0;c < l->length && pos>0; ++c){
+               if(((gs_sp_t)(l->offset))[c] == s){
+                       pos--;
+               }
+       }
+
+       if(pos>0 || c >= l->length-1){ // not enough seps, or final string is empty
+               return 0;
+       }
+       
+       result->offset = l->offset + c;
+       for(; c<l->length && ((gs_sp_t)(l->offset))[c] != s; ++c, ++result->length);
+       
+       return 0;
+}
+
+
+// -------------------------------------------------
 
 static gs_uint32_t nextint(struct vstring *str , gs_uint32_t * offset, gs_uint32_t *res) {
        gs_uint8_t * s = (gs_uint8_t *)(str->offset);
@@ -319,6 +424,7 @@ static gs_uint32_t nextint(struct vstring *str , gs_uint32_t * offset, gs_uint32
        return v;
 }
 
+
 gs_uint32_t strtoi(gs_uint32_t * r, struct vstring * s)
 {
        gs_uint32_t offset;
@@ -518,3 +624,165 @@ gs_uint32_t byte_match_offset( gs_uint32_t offset, gs_uint32_t val,vstring *s2)
 }
 
 
+// -------------------------------------------------------
+//             map_int_to_string and its support functions, structs
+
+struct int_to_string_map_struct{
+       std::map<gs_int64_t, vstring> i2s_map;
+       std::string fname;
+       vstring empty_string;
+};
+
+gs_param_handle_t register_handle_for_int_to_string_map_slot_1(vstring *filename){
+       int_to_string_map_struct *map_struct;
+
+       map_struct = new int_to_string_map_struct();
+       if(map_struct == NULL){
+               gslog(LOG_EMERG, "int_to_string_map:: Could not allocate handle memory\n");
+               return 0;
+       }
+
+       map_struct->empty_string.offset = (gs_p_t)malloc(1);
+       map_struct->empty_string.reserved = INTERNAL;
+       map_struct->empty_string.length = 0;
+
+       gs_sp_t filenamec;
+       filenamec = (gs_sp_t)alloca(filename->length+1);
+       if (filenamec==0) {
+               gslog(LOG_EMERG, "int_to_string_map:: Could not allocate filename memory\n");
+               return 0;
+       }
+       memcpy(filenamec,(gs_sp_t)filename->offset,filename->length);
+       filenamec[filename->length]=0;  
+       map_struct->fname = filenamec;
+
+       FILE *fl = fopen(filenamec, "r");
+       if(fl==NULL){
+               gslog(LOG_EMERG, "int_to_string_map:: Could not open regex file %s \n",filename);
+               return 0;
+       }
+       
+       gs_int32_t buflen = 10000;
+       char buf[buflen], buf_str[buflen];
+       gs_int64_t val;
+       char *fret;
+       fret = fgets(buf, buflen, fl);
+       while(fret != NULL){
+               int nvals = sscanf(buf, "%lld,%s", &val, buf_str);
+               if(nvals >= 2){
+                       vstring new_str;
+                       new_str.reserved = SHALLOW_COPY;
+                       new_str.length = strlen(buf_str);
+                       new_str.offset = (gs_p_t)malloc(new_str.length);
+                       memcpy((char *)new_str.offset, buf_str, new_str.length);
+                       map_struct->i2s_map[val] = new_str;
+               }
+               fret = fgets(buf, buflen, fl);
+       }
+
+       fclose(fl);
+
+       return (gs_param_handle_t) map_struct;
+}
+
+gs_retval_t int_to_string_map(vstring *result, gs_int64_t val, gs_param_handle_t handle){
+       int_to_string_map_struct *map_struct = (int_to_string_map_struct *)handle;
+       if(map_struct->i2s_map.count(val)>0){
+               vstring ret = map_struct->i2s_map[val];
+               result->offset = ret.offset;
+               result->reserved = ret.reserved;
+               result->length = ret.length;
+       }else{
+               result->offset = map_struct->empty_string.offset;
+               result->reserved = map_struct->empty_string.reserved;
+               result->length = map_struct->empty_string.length;
+       }
+
+       return 0;
+}
+
+gs_param_handle_t deregister_handle_for_int_to_string_map_slot_1(gs_param_handle_t handle){
+       int_to_string_map_struct *map_struct = (int_to_string_map_struct *)handle;
+       for(std::map<gs_int64_t, vstring>::iterator i2si = map_struct->i2s_map.begin(); i2si!=map_struct->i2s_map.end(); ++i2si){
+               free((void *)((*i2si).second.offset));
+       }
+       free((void *)(map_struct->empty_string.offset));
+       delete map_struct;
+}
+
+// ---------------------------------------------------
+//             Return a (binary, non-ascii) string in its hex representation
+
+static char hexmap[16] = {
+  '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'
+};
+
+gs_retval_t to_hex_string(vstring *result, vstring *val){
+       result->length = 2*(val->length);
+       result->offset = (gs_p_t)malloc(result->length);
+       result->reserved = INTERNAL;
+       unsigned char *rs = (unsigned char *)(result->offset);
+       unsigned char *vs = (unsigned char *)(val->offset);
+
+       for(int c=0;c<val->length; ++c){
+               rs[2*c] = hexmap[vs[c] >> 4];
+               rs[2*c+1] = hexmap[vs[c] & 0x0f];
+       }
+
+       return 0;
+}
+
+
+// ---------------------------------------------
+//             sum up unsigned integers expressed as a string with separators,
+//             e.g. on input '34|45|56' and sep '|', return 135.
+//             This kind of thing is common in Nokia PCMD data.
+// gracefully handle empty entries, e.g. '|8|' should return 8
+gs_int64_t sum_uint_in_list(struct vstring *list, struct vstring *sepchar){
+       gs_int64_t ret = 0;
+       gs_int64_t val = 0;
+       char sep;
+       char v;
+       int c;
+
+       if(sepchar->length < 1)
+               return 0;
+       sep = ((char *)(sepchar->offset))[0];
+
+       for(c=0;c<list->length;++c){
+               v = ((char *)(list->offset))[c];
+               if(v==sep){
+                       ret+=val;
+                       val = 0;
+               }else{
+                       val = 10*val + (v>='0' && v<='9')*(v-'0');
+               }
+       }
+       ret += val;
+       return ret;
+}
+
+//     Convert an string to an integer
+gs_int64_t to_llong(vstring *v){
+       gs_int64_t ret=0;
+       gs_uint8_t d;
+       int c;
+       int neg=1;
+
+       if(v->length < 1)
+               return 0;
+       d = ((char *)(v->offset))[0];
+       if(d=='-'){
+               neg=-1;
+       }else{
+               ret = (d>='0' && d<='9')*(d-'0');
+       }
+
+       for(c=1;c<v->length;++c){
+               d = ((char *)(v->offset))[c];
+               ret = 10*ret+(d>='0' && d<='9')*(d-'0');
+       }
+
+       return neg*ret;
+}
+