GRIB-392: grib_dump: provide output in JSON format

This commit is contained in:
Shahram Najm 2013-06-22 16:25:29 +01:00
parent 971eb2a94b
commit 4d6694f88a
8 changed files with 340 additions and 2 deletions

View File

@ -216,6 +216,7 @@ list( APPEND grib_api_srcs
grib_dumper_class_debug.c
grib_dumper_class_default.c
grib_dumper_class_keys.c
grib_dumper_class_json.c
grib_dumper_class_c_code.c
grib_dumper_class_wmo.c
grib_dumper_class.c

View File

@ -229,6 +229,7 @@ libgrib_api_la_prototypes= \
grib_dumper_class_debug.c \
grib_dumper_class_default.c \
grib_dumper_class_keys.c \
grib_dumper_class_json.c \
grib_dumper_class_c_code.c \
grib_dumper_class_wmo.c \
grib_dumper_class.c \

View File

@ -662,6 +662,8 @@ void grib_dump_footer(grib_dumper *d, grib_handle *h);
/* grib_dumper_class_keys.c */
/* grib_dumper_class_json.c */
/* grib_dumper_class_c_code.c */
/* grib_dumper_class_wmo.c */

View File

@ -4,6 +4,7 @@ extern grib_dumper_class* grib_dumper_class_compare;
extern grib_dumper_class* grib_dumper_class_debug;
extern grib_dumper_class* grib_dumper_class_default;
extern grib_dumper_class* grib_dumper_class_file;
extern grib_dumper_class* grib_dumper_class_json;
extern grib_dumper_class* grib_dumper_class_keys;
extern grib_dumper_class* grib_dumper_class_serialize;
extern grib_dumper_class* grib_dumper_class_string;

View File

@ -0,0 +1,319 @@
/*
* Copyright 2005-2012 ECMWF.
*
* This software is licensed under the terms of the Apache Licence Version 2.0
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
*
* In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
* virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
*/
#include "grib_api_internal.h"
#include <ctype.h>
/*
This is used by make_class.pl
START_CLASS_DEF
CLASS = dumper
IMPLEMENTS = dump_long;dump_bits
IMPLEMENTS = dump_double;dump_string
IMPLEMENTS = dump_bytes;dump_values
IMPLEMENTS = dump_label;dump_section
IMPLEMENTS = init;destroy
MEMBERS = long section_offset
MEMBERS = long begin
MEMBERS = long end
END_CLASS_DEF
*/
/* START_CLASS_IMP */
/*
Don't edit anything between START_CLASS_IMP and END_CLASS_IMP
Instead edit values between START_CLASS_DEF and END_CLASS_DEF
or edit "dumper.class" and rerun ./make_class.pl
*/
static void init_class (grib_dumper_class*);
static int init (grib_dumper* d);
static int destroy (grib_dumper*);
static void dump_long (grib_dumper* d, grib_accessor* a,const char* comment);
static void dump_bits (grib_dumper* d, grib_accessor* a,const char* comment);
static void dump_double (grib_dumper* d, grib_accessor* a,const char* comment);
static void dump_string (grib_dumper* d, grib_accessor* a,const char* comment);
static void dump_bytes (grib_dumper* d, grib_accessor* a,const char* comment);
static void dump_values (grib_dumper* d, grib_accessor* a);
static void dump_label (grib_dumper* d, grib_accessor* a,const char* comment);
static void dump_section (grib_dumper* d, grib_accessor* a,grib_block_of_accessors* block);
typedef struct grib_dumper_json {
grib_dumper dumper;
/* Members defined in json */
long section_offset;
long begin;
long end;
} grib_dumper_json;
static grib_dumper_class _grib_dumper_class_json = {
0, /* super */
"json", /* name */
sizeof(grib_dumper_json), /* size */
0, /* inited */
&init_class, /* init_class */
&init, /* init */
&destroy, /* free mem */
&dump_long, /* dump long */
&dump_double, /* dump double */
&dump_string, /* dump string */
&dump_label, /* dump labels */
&dump_bytes, /* dump bytes */
&dump_bits, /* dump bits */
&dump_section, /* dump section */
&dump_values, /* dump values */
0, /* header */
0, /* footer */
};
grib_dumper_class* grib_dumper_class_json = &_grib_dumper_class_json;
/* END_CLASS_IMP */
GRIB_INLINE static int grib_inline_strcmp(const char* a,const char* b) {
if (*a != *b) return 1;
while((*a!=0 && *b!=0) && *(a) == *(b) ) {a++;b++;}
return (*a==0 && *b==0) ? 0 : 1;
}
static int depth=2;
static void init_class (grib_dumper_class* c){}
static int init(grib_dumper* d)
{
grib_dumper_json *self = (grib_dumper_json*)d;
self->section_offset=0;
return GRIB_SUCCESS;
}
static int destroy (grib_dumper* d)
{
return GRIB_SUCCESS;
}
static void dump_values(grib_dumper* d,grib_accessor* a)
{
grib_dumper_json *self = (grib_dumper_json*)d;
double value; size_t size = 1;
double *values=NULL;
int err = 0;
int i,tab;
long more=0;
long count=0;
int mydepth=depth+2;
count=grib_value_count(a);
size=count;
if ( (a->flags & GRIB_ACCESSOR_FLAG_DUMP) == 0)
return;
if (size>1) {
values=grib_context_malloc_clear(a->parent->h->context,sizeof(double)*size);
err=grib_unpack_double(a,values,&size);
} else {
err=grib_unpack_double(a,&value,&size);
}
if(!(d->option_flags & GRIB_DUMP_FLAG_ALL_DATA) && size > 3) {
more = size - 3;
size = 3;
} else more=0;
if (!self->begin) fprintf(self->dumper.out,",\n");
else self->begin=0;
if (size>1) {
int cols=4;
int count=0;
int lens=strlen(a->name);
fprintf(self->dumper.out,"%-*s",mydepth," ");
fprintf(self->dumper.out,"\"%s\" : [ ",a->name);
tab=lens+mydepth+7;
for (i=0;i<size-1;i++) {
if (count>cols || i==0) {fprintf(self->dumper.out,"\n%-*s",tab," ");count=0;}
fprintf(self->dumper.out,"%g, ",values[i]);
count++;
}
if (count>cols) fprintf(self->dumper.out,"\n%-*s",tab," ");
fprintf(self->dumper.out,"%g ",values[i]);
if (more)
fprintf(self->dumper.out,"\n%-*s... %ld more values",tab," ",more);
tab=lens+mydepth+5;
fprintf(self->dumper.out,"\n%-*s] ",tab," ");
grib_context_free(a->parent->h->context,values);
} else {
fprintf(self->dumper.out,"%-*s",mydepth," ");
if( ((a->flags & GRIB_ACCESSOR_FLAG_CAN_BE_MISSING) != 0) && grib_is_missing_internal(a) )
fprintf(self->dumper.out,"\"%s\" : null",a->name);
else
fprintf(self->dumper.out,"\"%s\" : %g",a->name,value);
}
}
static void dump_long(grib_dumper* d,grib_accessor* a,const char* comment)
{
grib_dumper_json *self = (grib_dumper_json*)d;
long value; size_t size = 1;
long *values=NULL;
int err = 0;
int i,tab;
long count=0;
long more=0;
int mydepth=depth+2;
count = grib_value_count(a);
size=count;
if ( (a->flags & GRIB_ACCESSOR_FLAG_DUMP) == 0)
return;
if (size>1) {
values=grib_context_malloc_clear(a->parent->h->context,sizeof(long)*size);
err=grib_unpack_long(a,values,&size);
} else {
err=grib_unpack_long(a,&value,&size);
}
if(!(d->option_flags & GRIB_DUMP_FLAG_ALL_DATA) && size > 3) {
more = size - 3;
size = 3;
} else more=0;
if (!self->begin) fprintf(self->dumper.out,",\n");
else self->begin=0;
if (size>1) {
int cols=9;
int count=0;
int lens=strlen(a->name);
fprintf(self->dumper.out,"%-*s",mydepth," ");
fprintf(self->dumper.out,"\"%s\" : [ ",a->name);
tab=lens+mydepth+7;
for (i=0;i<size-1;i++) {
if (count>cols || i==0) {fprintf(self->dumper.out,"\n%-*s",tab," ");count=0;}
fprintf(self->dumper.out,"%ld, ",values[i]);
count++;
}
if (count>cols) fprintf(self->dumper.out,"\n%-*s",tab," ");
fprintf(self->dumper.out,"%ld ",values[i]);
if (more)
fprintf(self->dumper.out,"\n%-*s... %ld more values",tab," ",more);
tab=lens+mydepth+5;
fprintf(self->dumper.out,"\n%-*s] ",tab," ");
grib_context_free(a->parent->h->context,values);
} else {
fprintf(self->dumper.out,"%-*s",mydepth," ");
if( ((a->flags & GRIB_ACCESSOR_FLAG_CAN_BE_MISSING) != 0) && grib_is_missing_internal(a) )
fprintf(self->dumper.out,"\"%s\" : null",a->name);
else
fprintf(self->dumper.out,"\"%s\" : %ld",a->name,value);
}
}
static void dump_bits(grib_dumper* d,grib_accessor* a,const char* comment)
{
}
static void dump_double(grib_dumper* d,grib_accessor* a,const char* comment)
{
grib_dumper_json *self = (grib_dumper_json*)d;
double value; size_t size = 1;
int mydepth=depth+2;
grib_unpack_double(a,&value,&size);
if ( (a->flags & GRIB_ACCESSOR_FLAG_DUMP) == 0)
return;
if (!self->begin) fprintf(self->dumper.out,",\n");
else self->begin=0;
fprintf(self->dumper.out,"%-*s",mydepth," ");
if( ((a->flags & GRIB_ACCESSOR_FLAG_CAN_BE_MISSING) != 0) && grib_is_missing_internal(a) )
fprintf(self->dumper.out,"\"%s\" : null",a->name);
else
fprintf(self->dumper.out,"\"%s\" : %g",a->name,value);
}
static void dump_string(grib_dumper* d,grib_accessor* a,const char* comment)
{
grib_dumper_json *self = (grib_dumper_json*)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);
int mydepth=depth+2;
c=a->parent->h->context;
if (size==0) return;
if ( (a->flags & GRIB_ACCESSOR_FLAG_DUMP) == 0)
return;
value=grib_context_malloc_clear(c,size);
if (!value) {
grib_context_log(c,GRIB_LOG_FATAL,"unable to allocate %d bytes",(int)size);
return;
}
if (!self->begin) fprintf(self->dumper.out,",\n");
else self->begin=0;
err = grib_unpack_string(a,value,&size);
p=value;
while(*p) { if(!isprint(*p)) *p = '.'; p++; }
fprintf(self->dumper.out,"%-*s",mydepth," ");
if( ((a->flags & GRIB_ACCESSOR_FLAG_CAN_BE_MISSING) != 0) && grib_is_missing_internal(a) )
fprintf(self->dumper.out,"\"%s\" : null",a->name);
else
fprintf(self->dumper.out,"\"%s\" : \"%s\"",a->name,value);
grib_context_free(c,value);
}
static void dump_bytes(grib_dumper* d,grib_accessor* a,const char* comment)
{
}
static void dump_label(grib_dumper* d,grib_accessor* a,const char* comment)
{
}
static void dump_section(grib_dumper* d,grib_accessor* a,grib_block_of_accessors* block)
{
grib_dumper_json *self = (grib_dumper_json*)d;
if ( !grib_inline_strcmp(a->name,"GRIB") ) {
fprintf(self->dumper.out,"{\n");
self->begin=1;
grib_dump_accessors_block(d,block);
fprintf(self->dumper.out,"\n}\n");
}
else {
grib_dump_accessors_block(d,block);
}
}

View File

@ -2,6 +2,7 @@
{ "c_code", &grib_dumper_class_c_code, },
{ "debug", &grib_dumper_class_debug, },
{ "default", &grib_dumper_class_default, },
{ "json", &grib_dumper_class_json, },
{ "keys", &grib_dumper_class_keys, },
{ "serialize", &grib_dumper_class_serialize, },
{ "wmo", &grib_dumper_class_wmo, },

View File

@ -21,6 +21,7 @@ grib_option grib_options[]={
{"O",0,"Octet mode. WMO documentation style dump.\n",0,1,0},
{"D",0,0,0,1,0},
{"d",0,"Print all data values.\n",0,1,0},
{"j",0,0,0,1,0},
{"C",0,0,0,1,0},
{"t",0,0,0,1,0},
{"H",0,0,0,1,0},
@ -39,6 +40,7 @@ grib_option grib_options[]={
char* grib_tool_description="Dump the content of a grib file in different formats.";
char* grib_tool_name="grib_dump";
char* grib_tool_usage="[options] grib_file grib_file ...";
static int json=0;
int grib_options_count=sizeof(grib_options)/sizeof(grib_option);
@ -55,15 +57,20 @@ int grib_tool_before_getopt(grib_runtime_options* options) {
int grib_tool_init(grib_runtime_options* options) {
int opt=grib_options_on("C")+grib_options_on("O")+grib_options_on("D");
int opt=grib_options_on("C")+grib_options_on("O")+grib_options_on("D")+grib_options_on("j");
options->dump_mode = "default";
if (opt > 1) {
printf("%s: simultaneous C/O/D options not allowed\n",grib_tool_name);
printf("%s: simultaneous j/C/O/D options not allowed\n",grib_tool_name);
exit(1);
}
if (grib_options_on("j")) {
options->dump_mode = "json";
json=1;
}
if (grib_options_on("C")) {
options->dump_mode = "c_code";
if (grib_options_on("d"))
@ -108,6 +115,7 @@ int grib_tool_new_filename_action(grib_runtime_options* options,const char* file
int grib_tool_new_file_action(grib_runtime_options* options,grib_tools_file* file) {
char tmp[1024];
if (!options->current_infile->name) return 0;
if (json) return 0;
sprintf(tmp,"FILE: %s ",options->current_infile->name);
if (!grib_options_on("C"))
fprintf(stdout,"***** %s\n",tmp);
@ -132,12 +140,16 @@ int grib_tool_new_handle_action(grib_runtime_options* options, grib_handle* h) {
for (i=0;i<options->print_keys_count;i++)
grib_set_flag(h,options->print_keys[i].name,GRIB_ACCESSOR_FLAG_DUMP);
if(json) {
}
else {
sprintf(tmp,"MESSAGE %d ( length=%ld )",options->handle_count,length);
if (!grib_options_on("C"))
fprintf(stdout,"#============== %-38s ==============\n",tmp);
if (!strcmp(options->dump_mode,"default")) {
GRIB_CHECK_NOLINE(grib_get_string(h,"identifier",identifier,&idlen),0);
printf("%s {\n",identifier);
}
}
grib_dump_content(h,stdout,options->dump_mode,options->dump_flags,0);

View File

@ -43,6 +43,7 @@ grib_options_help grib_options_help_list[] ={
{"G",0,"GRIBEX compatibility mode.\n"},
{"i:","index",
"\n\t\tData value corresponding to the given index is printed.\n"},
{"j",0,"JSON mode (JavaScript Object Notation).\n"},
{"l:","Latitude,Longitude[,MODE,file]",
"\n\t\tValue close to the point of a Latitude/Longitude."
"\n\t\tAllowed values for MODE are:"