static int compare(grib_accessor* a,grib_accessor* b)
{
    int retval=0;
    char *aval=0;
    char *bval=0;

    size_t alen = 0;
    size_t blen = 0;
    int err=0;
    long count=0;

    err=grib_value_count(a,&count);
    if (err) return err;
    alen=count;

    err=grib_value_count(b,&count);
    if (err) return err;
    blen=count;

    if (alen != blen) return GRIB_COUNT_MISMATCH;

    aval=(char*)grib_context_malloc(a->parent->h->context,alen*sizeof(char));
    bval=(char*)grib_context_malloc(b->parent->h->context,blen*sizeof(char));

    grib_unpack_string(a,aval,&alen);
    grib_unpack_string(b,bval,&blen);

    retval = GRIB_SUCCESS;
    if (!aval || !bval || grib_inline_strcmp(aval,bval)) retval = GRIB_STRING_VALUE_MISMATCH;

    grib_context_free(a->parent->h->context,aval);
    grib_context_free(b->parent->h->context,bval);

    return retval;
}
static void dump_string(grib_dumper* d,grib_accessor* a,const char* comment)
{
  grib_dumper_debug *self = (grib_dumper_debug*)d;
  char value[1024]; size_t size = sizeof(value);
  int err = grib_unpack_string(a,value,&size);
  int i;
  char *p = value;

  if(err) strcpy(value,"<error>");


  if( a->length == 0  &&
      (d->option_flags & GRIB_DUMP_FLAG_CODED) != 0)
    return;

  set_begin_end(d,a);

  while(*p) { if(!isprint(*p)) *p = '.'; p++; }

  for(i = 0; i < d->depth ; i++) fprintf(self->dumper.out," ");
  fprintf(self->dumper.out,"%ld-%ld %s %s = %s",self->begin,self->end,a->creator->op, a->name,value);

  if(comment) fprintf(self->dumper.out," [%s]",comment);
  if(err)
    fprintf(self->dumper.out," *** ERR=%d (%s)",err,grib_get_error_message(err));
  aliases(d,a);
  fprintf(self->dumper.out,"\n");
}
static void dump_string(grib_dumper* d,grib_accessor* a,const char* comment)
{
  grib_dumper_serialize *self = (grib_dumper_serialize*)d;
  char value[1024]; size_t size = sizeof(value);
  int err = grib_unpack_string(a,value,&size);
  int i;

  char *p = value;

  if(  (a->flags & GRIB_ACCESSOR_FLAG_HIDDEN) != 0 )
    return;

  if( (a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY) != 0 &&
      (d->option_flags & GRIB_DUMP_FLAG_READ_ONLY) == 0)
    return;

  while(*p) { if(!isprint(*p)) *p = '.'; p++; }

  for(i = 0; i < d->depth ; i++) fprintf(self->dumper.out," ");



  fprintf(self->dumper.out,"%s = %s", a->name,value);
  if ( (a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY) != 0 )  fprintf(self->dumper.out," (read_only)");

#if 0
  if(comment) fprintf(self->dumper.out," [%s]",comment);
#endif
  if(err)
    fprintf(self->dumper.out," *** ERR=%d (%s) [grib_dumper_serialize::dump_string]",err,grib_get_error_message(err));
  fprintf(self->dumper.out,"\n");

}
static void dump_string(grib_dumper* d,grib_accessor* a,const char* comment)
{
  grib_dumper_default *self = (grib_dumper_default*)d;
  char *value=NULL;
  char *p = NULL;
  size_t size = 0;
  grib_context* c=NULL;
  int err = grib_get_string_length(a->parent->h,a->name,&size);

  c=a->parent->h->context;
  if (size==0) return;

  value=(char*)grib_context_malloc_clear(c,size);
  if (!value) {
  	grib_context_log(c,GRIB_LOG_FATAL,"unable to allocate %d bytes",(int)size);
	return;
  }

  err = grib_unpack_string(a,value,&size);
  p=value;

  if ( (a->flags & GRIB_ACCESSOR_FLAG_DUMP) == 0)
    return;

  while(*p) { if(!isprint(*p)) *p = '.'; p++; }

  print_offset(self->dumper.out,d,a);

  if ((d->option_flags & GRIB_DUMP_FLAG_TYPE) != 0) {
    fprintf(self->dumper.out,"  ");
    fprintf(self->dumper.out,"# type %s \n",a->creator->op);
  }

  aliases(d,a);
  if(comment) {
    fprintf(self->dumper.out,"  ");
    fprintf(self->dumper.out,"# %s \n",comment);
  }

  if (a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY) {
    fprintf(self->dumper.out,"  ");
    fprintf(self->dumper.out,"#-READ ONLY- ");
  } else
    fprintf(self->dumper.out,"  ");

  if( ((a->flags & GRIB_ACCESSOR_FLAG_CAN_BE_MISSING) != 0) && grib_is_missing_internal(a) )
    fprintf(self->dumper.out,"%s = MISSING;",a->name);
  else
    fprintf(self->dumper.out,"%s = %s;",a->name,value);


  if(err) {
    fprintf(self->dumper.out,"  ");
    fprintf(self->dumper.out,"# *** ERR=%d (%s) [grib_dumper_default::dump_string]",err,grib_get_error_message(err));
  }

  fprintf(self->dumper.out,"\n");
  grib_context_free(c,value);
}
static void dump_string(grib_dumper* d,grib_accessor* a,const char* comment)
{
  grib_dumper_wmo *self = (grib_dumper_wmo*)d;
  size_t size=0;
  char *value=NULL;
  char *p=NULL;
  int err = grib_get_string_length(a->parent->h,a->name,&size);

  value=(char *)grib_context_malloc_clear(a->parent->h->context,size);
  if (!value) {
  	grib_context_log(a->parent->h->context,GRIB_LOG_FATAL,"unable to allocate %d bytes",(int)size);
	return;
  }
  err=grib_unpack_string(a,value,&size);
  p=value;

  if( a->length == 0  &&
      (d->option_flags & GRIB_DUMP_FLAG_CODED) != 0) {
	grib_context_free(a->parent->h->context,value);
    return;
  }

  set_begin_end(d,a);

  while(*p) { if(!isprint(*p)) *p = '.'; p++; }

  /*for(i = 0; i < d->depth ; i++) fprintf(self->dumper.out," ");*/
  print_offset(self->dumper.out,self->begin,self->theEnd);
  if ((d->option_flags & GRIB_DUMP_FLAG_TYPE) != 0)
        fprintf(self->dumper.out,"%s ",a->creator->op);

  fprintf(self->dumper.out,"%s = %s",a->name,value);

  if (err==0) print_hexadecimal(self->dumper.out,d->option_flags,a);

  /*if(comment) fprintf(self->dumper.out," [%s]",comment);*/
  if(err)
    fprintf(self->dumper.out," *** ERR=%d (%s) [grib_dumper_wmo::dump_string]",err,grib_get_error_message(err));
  aliases(d,a);
  fprintf(self->dumper.out,"\n");
  if (value) grib_context_free(a->parent->h->context,value);
}
static int unpack_long(grib_accessor* a, long* val, size_t *len)
{

  long value = 0;
  long pos = a->offset*8;
  char *intc = NULL;
  char  expver[5];
  char  refexpver[5];
  size_t llen = a->length+1;
  Assert(a->length == 4);

  if(*len < 1)
  {
    grib_context_log(a->parent->h->context, GRIB_LOG_ERROR, "Wrong size for %s it contains %d values ", a->name , 1 );
    *len = 0;
    return GRIB_ARRAY_TOO_SMALL;
  }
  value = grib_decode_unsigned_long(a->parent->h->buffer->data , &pos, a->length*8);

  grib_unpack_string(a, refexpver , &llen);

  /* test for endiannes */
  intc = (char*)&value;

  expver[0] = intc[0];
  expver[1] = intc[1];
  expver[2] = intc[2];
  expver[3] = intc[3];
  expver[4] = 0;

  /* if there is a difference, have to reverse*/
  if(strcmp(refexpver, expver)){
    intc[0] = expver[3];
    intc[1] = expver[2];
    intc[2] = expver[1];
    intc[3] = expver[0];
  }

  *val = value;
  *len = 1;
  return GRIB_SUCCESS;
}
static void dump_string(grib_dumper* d,grib_accessor* a,const char* comment)
{
    grib_dumper_debug *self = (grib_dumper_debug*)d;
    int err=0;
    int i;
    size_t size=0;
    char *value=NULL;
    char *p=NULL ;

    err = grib_get_string_length(a->parent->h, a->name, &size);
    if ( (size < 2) && grib_is_missing_internal(a) ) {
        /* GRIB-302: transients and missing keys. Need to re-adjust the size */
        size = 10; /* big enough to hold the string "missing" */
    }

    value=(char*)grib_context_malloc_clear(a->parent->h->context,size);
    if (!value) return;
    err=grib_unpack_string(a,value,&size);

    if(err) strcpy(value,"<error>");

    p=value;

    if( a->length == 0  && (d->option_flags & GRIB_DUMP_FLAG_CODED) != 0)
        return;

    set_begin_end(d,a);

    while(*p) { if(!isprint(*p)) *p = '.'; p++; }

    for(i = 0; i < d->depth ; i++) fprintf(self->dumper.out," ");
    fprintf(self->dumper.out,"%ld-%ld %s %s = %s",self->begin,self->theEnd,a->creator->op, a->name,value);

    if(comment) fprintf(self->dumper.out," [%s]",comment);
    if(err)
        fprintf(self->dumper.out," *** ERR=%d (%s) [grib_dumper_debug::dump_string]",err,grib_get_error_message(err));
    aliases(d,a);
    fprintf(self->dumper.out,"\n");

    if (value) grib_context_free(a->parent->h->context,value);
}
static void dump_string(grib_dumper* d,grib_accessor* a,const char* comment)
{
  grib_dumper_c_code *self = (grib_dumper_c_code*)d;
  char value[1024]; size_t size = sizeof(value);
  int err = grib_unpack_string(a,value,&size);

  if (a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY)
    return;

  if(a->length == 0)
    return;

#if 1
  if(comment) fprintf(self->dumper.out,"/* %s */\n",comment);
#endif

  fprintf(self->dumper.out,"    p    = \"%s\";\n",value);
  fprintf(self->dumper.out,"    size = strlen(p)+1;\n");
  fprintf(self->dumper.out,"    GRIB_CHECK(grib_set_string(h,\"%s\",p,&size),%d);\n",a->name,0);

  if(err)
    fprintf(self->dumper.out," /*  Error accessing %s (%s) */",a->name,grib_get_error_message(err));
}