int stats3_decompress(unsigned char *in,int inlen,unsigned char *out, int *outlen) { range_coder *c=range_new_coder(inlen); bcopy(in,c->bit_stream,inlen); c->bit_stream_length=inlen*8; c->bits_used=0; c->low=0; c->high=0xffffffff; range_decode_prefetch(c); stats3_decompress_bits(c,out,outlen); range_coder_free(c); return 0; }
int recipe_decode_field(struct recipe *recipe,stats_handle *stats, range_coder *c, int fieldnumber,char *value,int value_size) { int normalised_value; int minimum; int maximum; int precision; int r; precision=recipe->fields[fieldnumber].precision; switch (recipe->fields[fieldnumber].type) { case FIELDTYPE_INTEGER: minimum=recipe->fields[fieldnumber].minimum; maximum=recipe->fields[fieldnumber].maximum; normalised_value=range_decode_equiprobable(c,maximum-minimum+2); if (normalised_value==(maximum-minimum+1)) { // out of range value, so decode it as a string. fprintf(stderr,"FIELDTYPE_INTEGER: Illegal value - decoding string representation.\n"); r=stats3_decompress_bits(c,(unsigned char *)value,&value_size,stats,NULL); } else sprintf(value,"%d",normalised_value+minimum); return 0; case FIELDTYPE_FLOAT: { // Sign int sign = range_decode_equiprobable(c,2); // Exponent int exponent = range_decode_equiprobable(c,256)-128; // Mantissa int mantissa = 0; int b; b=range_decode_equiprobable(c,256); mantissa |= b<<16; b=range_decode_equiprobable(c,256); mantissa |= b<<8; b=range_decode_equiprobable(c,256); mantissa |= b<<0; float f = mantissa*1.0/0xffffff; if (sign) f=-f; f = ldexp( f, exponent); fprintf(stderr,"sign=%d, exp=%d, mantissa=%x, f=%f\n", sign,exponent,mantissa,f); sprintf(value,"%f",f); return 0; } case FIELDTYPE_BOOLEAN: normalised_value=range_decode_equiprobable(c,2); sprintf(value,"%d",normalised_value); return 0; break; case FIELDTYPE_MULTISELECT: { int k; int vlen=0; // Get bitmap of enum fields for(k=0;k<recipe->fields[fieldnumber].enum_count;k++) { if (range_decode_equiprobable(c,2)) { // Field value is present if (vlen) { value[vlen++]='|'; value[vlen]=0; } sprintf(&value[vlen],"%s",recipe->fields[fieldnumber].enum_values[k]); vlen=strlen(value); } } return 0; break; } case FIELDTYPE_ENUM: normalised_value=range_decode_equiprobable(c,recipe->fields[fieldnumber] .enum_count); if (normalised_value<0||normalised_value>=recipe->fields[fieldnumber].enum_count) { printf("enum: range_decode_equiprobable returned illegal value %d for range %d..%d\n", normalised_value,0,recipe->fields[fieldnumber].enum_count-1); return -1; } sprintf(value,"%s",recipe->fields[fieldnumber].enum_values[normalised_value]); printf("enum: decoding %s as %d of %d\n", value,normalised_value,recipe->fields[fieldnumber].enum_count); return 0; break; case FIELDTYPE_TEXT: r=stats3_decompress_bits(c,(unsigned char *)value,&value_size,stats,NULL); return 0; case FIELDTYPE_TIMEDATE: // time is 32-bit seconds since 1970. // Format as yyyy-mm-ddThh:mm:ss+hh:mm { // SMAC has a bug with encoding large ranges, so break into smaller pieces time_t t = 0; t=range_decode_equiprobable(c,0x8000)<<16; t|=range_decode_equiprobable(c,0x10000); printf("TIMEDATE: decoding t=%d\n",(int)t); struct tm tm; // gmtime_r(&t,&tm); localtime_r(&t,&tm); sprintf(value,"%04d-%02d-%02dT%02d:%02d:%02d+00:00", tm.tm_year+1900,tm.tm_mon+1,tm.tm_mday, tm.tm_hour,tm.tm_min,tm.tm_sec); return 0; } case FIELDTYPE_MAGPITIMEDATE: // time encodes each field precisely, allowing years 0 - 9999 // Format as yyyy-mm-dd hh:mm:ss { struct tm tm; bzero(&tm,sizeof(tm)); tm.tm_year=range_decode_equiprobable(c,10000); tm.tm_mon=range_decode_equiprobable(c,12); tm.tm_mday=range_decode_equiprobable(c,31); tm.tm_hour=range_decode_equiprobable(c,25); tm.tm_min=range_decode_equiprobable(c,60); tm.tm_sec=range_decode_equiprobable(c,62); sprintf(value,"%04d-%02d-%02d %02d:%02d:%02d", tm.tm_year,tm.tm_mon+1,tm.tm_mday, tm.tm_hour,tm.tm_min,tm.tm_sec); return 0; } case FIELDTYPE_DATE: // Date encoded using: // normalised_value=y*372+(m-1)*31+(d-1); // So year = value / 372 ... { if (precision==0) precision=22; int minimum=0; int maximum=10000*372; maximum=maximum>> (22-precision); int normalised_value = range_decode_equiprobable(c,maximum-minimum+1); int year = normalised_value / 372; int day_of_year = normalised_value - (year*372); int month = day_of_year/31+1; int day_of_month = day_of_year%31+1; // American date format for Magpi sprintf(value,"%02d-%02d-%04d",month,day_of_month,year); return 0; } case FIELDTYPE_UUID: { int i,j=5; sprintf(value,"uuid:"); for(i=0;i<16;i++) { int b=0; if ((!recipe->fields[fieldnumber].precision) ||(i<recipe->fields[fieldnumber].precision)) b=range_decode_equiprobable(c,256); switch(i) { case 4: case 6: case 8: case 10: value[j++]='-'; } sprintf(&value[j],"%02x",b); j+=2; value[j]=0; } return 0; } case FIELDTYPE_MAGPIUUID: // 64bit hex followed by seconds since UNIX epoch? { int i,j=0; value[0]=0; for(i=0;i<8;i++) { int b=0; b=range_decode_equiprobable(c,256); sprintf(&value[j],"%02x",b); j+=2; value[j]=0; } // 48 bits of milliseconds since unix epoch long long timestamp=0; for(i=0;i<6;i++) { timestamp=timestamp<<8LL; int b=range_decode_equiprobable(c,256); timestamp|=b; } sprintf(&value[j],"-%lld",timestamp); return 0; } case FIELDTYPE_LATLONG: { int ilat,ilon; double lat,lon; switch(recipe->fields[fieldnumber].precision) { case 0: case 34: ilat=range_decode_equiprobable(c,182*112000); ilat-=90*112000; ilon=range_decode_equiprobable(c,361*112000); ilon-=180*112000; lat=ilat/112000.0; lon=ilon/112000.0; break; case 16: ilat=range_decode_equiprobable(c,182); ilat-=90; ilon=range_decode_equiprobable(c,361); ilon-=180; lat=ilat; lon=ilon; break; default: sprintf(recipe_error,"Illegal LATLONG precision of %d bits. Should be 16 or 34.\n",recipe->fields[fieldnumber].precision); return -1; } sprintf(value,"%.5f %.5f",lat,lon); return 0; } default: snprintf(recipe_error,1024,"Attempting decompression of unsupported field type of '%s'.\n",recipe_field_type_name(recipe->fields[fieldnumber].type)); return -1; } return 0; }