mirror of
https://github.com/Unidata/netcdf-c.git
synced 2024-11-27 07:30:33 +08:00
486 lines
12 KiB
C
486 lines
12 KiB
C
|
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
|
||
|
See the COPYRIGHT file for more information. */
|
||
|
|
||
|
#include <sys/stat.h>
|
||
|
|
||
|
#ifdef NETINET_IN_H
|
||
|
#include <netinet/in.h>
|
||
|
#endif
|
||
|
|
||
|
#include "ocinternal.h"
|
||
|
#include "ocdata.h"
|
||
|
#include "ocdebug.h"
|
||
|
|
||
|
/*Forward*/
|
||
|
static void dumpocnode1(OCnode* node, int depth);
|
||
|
static void dumpdimensions(OCnode* node);
|
||
|
static void dumpattvalue(OCtype nctype, char** aset, int index);
|
||
|
static void ocdumpmemdata1(OCmemdata* memdata, OCbytes* buf, int depth);
|
||
|
|
||
|
static char* sindent = NULL;
|
||
|
|
||
|
static char*
|
||
|
dent(int n)
|
||
|
{
|
||
|
if(sindent == NULL) {
|
||
|
sindent = (char*)ocmalloc(102);
|
||
|
MEMCHECK(sindent,NULL);
|
||
|
memset((void*)sindent,(int)' ',(size_t)101);
|
||
|
sindent[101] = '\0';
|
||
|
}
|
||
|
if(n > 100) n = 100;
|
||
|
return sindent+(100-n);
|
||
|
}
|
||
|
|
||
|
/* support [dd] leader*/
|
||
|
static char*
|
||
|
dent2(int n) {return dent(n+4);}
|
||
|
|
||
|
void
|
||
|
ocdumpnode(OCnode* node)
|
||
|
{
|
||
|
if(node != NULL) {
|
||
|
dumpocnode1(node,0);
|
||
|
} else {
|
||
|
fprintf(stderr,"<NULL>\n");
|
||
|
}
|
||
|
fflush(stderr);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
dumpocnode1(OCnode* node, int depth)
|
||
|
{
|
||
|
unsigned int n;
|
||
|
switch (node->octype) {
|
||
|
case OC_Primitive: {
|
||
|
fprintf(stderr,"[%2d]%s ",depth,dent(depth));
|
||
|
if(node->name == NULL) OCPANIC("prim without name");
|
||
|
fprintf(stderr,"%s %s",octypetostring(node->etype),node->name);
|
||
|
dumpdimensions(node);
|
||
|
fprintf(stderr," @%lx",(unsigned long)node);
|
||
|
fprintf(stderr,"\n");
|
||
|
} break;
|
||
|
|
||
|
case OC_Dataset: {
|
||
|
fprintf(stderr,"[%2d]%s ",depth,dent(depth));
|
||
|
fprintf(stderr,"dataset %s\n",
|
||
|
(node->name?node->name:""));
|
||
|
for(n=0;n<oclistlength(node->subnodes);n++) {
|
||
|
dumpocnode1((OCnode*)oclistget(node->subnodes,n),depth+1);
|
||
|
}
|
||
|
} break;
|
||
|
|
||
|
case OC_Structure: {
|
||
|
fprintf(stderr,"[%2d]%s ",depth,dent(depth));
|
||
|
fprintf(stderr,"struct %s",
|
||
|
(node->name?node->name:""));
|
||
|
dumpdimensions(node);
|
||
|
fprintf(stderr," @%lx",(unsigned long)node);
|
||
|
fprintf(stderr,"\n");
|
||
|
for(n=0;n<oclistlength(node->subnodes);n++) {
|
||
|
dumpocnode1((OCnode*)oclistget(node->subnodes,n),depth+1);
|
||
|
}
|
||
|
} break;
|
||
|
|
||
|
case OC_Sequence: {
|
||
|
fprintf(stderr,"[%2d]%s ",depth,dent(depth));
|
||
|
fprintf(stderr,"sequence %s",
|
||
|
(node->name?node->name:""));
|
||
|
dumpdimensions(node);
|
||
|
fprintf(stderr," @%lx",(unsigned long)node);
|
||
|
fprintf(stderr,"\n");
|
||
|
for(n=0;n<oclistlength(node->subnodes);n++) {
|
||
|
dumpocnode1((OCnode*)oclistget(node->subnodes,n),depth+1);
|
||
|
}
|
||
|
} break;
|
||
|
|
||
|
case OC_Grid: {
|
||
|
unsigned int i;
|
||
|
fprintf(stderr,"[%2d]%s ",depth,dent(depth));
|
||
|
fprintf(stderr,"grid %s",
|
||
|
(node->name?node->name:""));
|
||
|
dumpdimensions(node);
|
||
|
fprintf(stderr," @%lx",(unsigned long)node);
|
||
|
fprintf(stderr,"\n");
|
||
|
fprintf(stderr,"%sarray:\n",dent2(depth+1));
|
||
|
dumpocnode1((OCnode*)oclistget(node->subnodes,0),depth+2);
|
||
|
fprintf(stderr,"%smaps:\n",dent2(depth+1));
|
||
|
for(i=1;i<oclistlength(node->subnodes);i++) {
|
||
|
dumpocnode1((OCnode*)oclistget(node->subnodes,i),depth+2);
|
||
|
}
|
||
|
} break;
|
||
|
|
||
|
case OC_Attribute: {
|
||
|
fprintf(stderr,"[%2d]%s ",depth,dent(depth));
|
||
|
if(node->name == NULL) OCPANIC("Attribute without name");
|
||
|
fprintf(stderr,"%s %s",octypetostring(node->etype),node->name);
|
||
|
for(n=0;n<oclistlength(node->att.values);n++) {
|
||
|
char* value = (char*)oclistget(node->att.values,n);
|
||
|
if(n > 0) fprintf(stderr,",");
|
||
|
fprintf(stderr," %s",value);
|
||
|
}
|
||
|
fprintf(stderr," @%lx",(unsigned long)node);
|
||
|
fprintf(stderr,"\n");
|
||
|
} break;
|
||
|
|
||
|
case OC_Attributeset: {
|
||
|
fprintf(stderr,"[%2d]%s ",depth,dent(depth));
|
||
|
fprintf(stderr,"%s:\n",node->name?node->name:"Attributes");
|
||
|
for(n=0;n<oclistlength(node->subnodes);n++) {
|
||
|
dumpocnode1((OCnode*)oclistget(node->subnodes,n),depth+1);
|
||
|
}
|
||
|
} break;
|
||
|
|
||
|
default:
|
||
|
OCPANIC1("encountered unexpected node type: %x",node->octype);
|
||
|
}
|
||
|
|
||
|
if(node->attributes != NULL) {
|
||
|
unsigned int i;
|
||
|
for(i=0;i<oclistlength(node->attributes);i++) {
|
||
|
OCattribute* att = (OCattribute*)oclistget(node->attributes,i);
|
||
|
fprintf(stderr,"%s[%s=",dent2(depth+2),att->name);
|
||
|
if(att->nvalues == 0)
|
||
|
OCPANIC("Attribute.nvalues == 0");
|
||
|
if(att->nvalues == 1) {
|
||
|
dumpattvalue(att->etype,att->values,0);
|
||
|
} else {
|
||
|
unsigned int j;
|
||
|
fprintf(stderr,"{");
|
||
|
for(j=0;j<att->nvalues;j++) {
|
||
|
if(j>0) fprintf(stderr,", ");
|
||
|
dumpattvalue(att->etype,att->values,j);
|
||
|
}
|
||
|
fprintf(stderr,"}");
|
||
|
}
|
||
|
fprintf(stderr,"]\n");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
dumpdimensions(OCnode* node)
|
||
|
{
|
||
|
unsigned int i;
|
||
|
for(i=0;i<node->array.rank;i++) {
|
||
|
OCnode* dim = (OCnode*)oclistget(node->array.dimensions,i);
|
||
|
fprintf(stderr,"[%s=%lu]",
|
||
|
(dim->name?dim->name:"?"),
|
||
|
(unsigned long)dim->dim.declsize);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
dumpattvalue(OCtype nctype, char** strings, int index)
|
||
|
{
|
||
|
if(nctype == OC_String || nctype == OC_URL) {
|
||
|
fprintf(stderr,"\"%s\"",strings[index]);
|
||
|
} else {
|
||
|
fprintf(stderr,"%s",strings[index]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
ocdumpslice(OCslice* slice)
|
||
|
{
|
||
|
fprintf(stderr,"[");
|
||
|
fprintf(stderr,"%lu",(unsigned long)slice->first);
|
||
|
if(slice->stride > 1) fprintf(stderr,":%lu",(unsigned long)slice->stride);
|
||
|
fprintf(stderr,":%lu",(unsigned long)(slice->first+slice->count)-1);
|
||
|
fprintf(stderr,"]");
|
||
|
}
|
||
|
|
||
|
void
|
||
|
ocdumpclause(OCprojectionclause* ref)
|
||
|
{
|
||
|
unsigned int i;
|
||
|
OClist* path = oclistnew();
|
||
|
collectpathtonode(ref->node,path);
|
||
|
for(i=0;i<oclistlength(path);i++) {
|
||
|
OClist* sliceset;
|
||
|
OCnode* node = (OCnode*)oclistget(path,i);
|
||
|
if(node->tree != NULL) continue; /* leave off the root node*/
|
||
|
fprintf(stderr,"%s%s",(i>0?PATHSEPARATOR:""),node->name);
|
||
|
sliceset = (OClist*)oclistget(ref->indexsets,i);
|
||
|
if(sliceset != NULL) {
|
||
|
unsigned int j;
|
||
|
for(j=0;j<oclistlength(sliceset);j++) {
|
||
|
OCslice* slice = (OCslice*)oclistget(sliceset,j);
|
||
|
ocdumpslice(slice);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
dumpmem2(char* s, char* accum, int align)
|
||
|
{
|
||
|
int len,rem;
|
||
|
strcat(accum,"|");
|
||
|
strcat(accum,s);
|
||
|
len = strlen(s);
|
||
|
rem = (align - len);
|
||
|
while(rem-- > 0) strcat(accum," ");
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
dumpmem1(int index, unsigned int n, unsigned int n1)
|
||
|
{
|
||
|
int i;
|
||
|
char s[1024];
|
||
|
char tmp[32];
|
||
|
union {
|
||
|
unsigned int uv;
|
||
|
int sv;
|
||
|
unsigned char cv[4];
|
||
|
float fv;
|
||
|
} form;
|
||
|
union {
|
||
|
unsigned int uv[2];
|
||
|
double dv;
|
||
|
} dform;
|
||
|
form.uv = n;
|
||
|
s[0] = '\0';
|
||
|
sprintf(tmp,"%6d",index);
|
||
|
dumpmem2(tmp,s,5);
|
||
|
sprintf(tmp,"%08x",form.uv);
|
||
|
dumpmem2(tmp,s,8);
|
||
|
sprintf(tmp,"%12u",form.uv);
|
||
|
dumpmem2(tmp,s,12);
|
||
|
sprintf(tmp,"%12d",form.sv);
|
||
|
dumpmem2(tmp,s,12);
|
||
|
sprintf(tmp,"%#g",form.fv);
|
||
|
dumpmem2(tmp,s,12);
|
||
|
tmp[0] = '\0';
|
||
|
for(i=0;i<4;i++) {
|
||
|
char stmp[64];
|
||
|
if(form.cv[i] < ' ' || form.cv[i] > 126)
|
||
|
sprintf(stmp,"\\%02x",(unsigned int)form.cv[i]);
|
||
|
else
|
||
|
sprintf(stmp,"%c",form.cv[i]);
|
||
|
strcat(tmp,stmp);
|
||
|
}
|
||
|
dumpmem2(tmp,s,16);
|
||
|
dform.uv[1] = n;
|
||
|
dform.uv[0] = n1;
|
||
|
sprintf(tmp,"%#g",dform.dv);
|
||
|
dumpmem2(tmp,s,12);
|
||
|
strcat(s,"\n");
|
||
|
fprintf(stderr,"%s",s);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
dumpmemory0(char* memory, int len, int fromxdr, int bod)
|
||
|
{
|
||
|
unsigned int i,count,rem;
|
||
|
int* imemory;
|
||
|
char hdr[1024];
|
||
|
|
||
|
assert(memory[len] == 0);
|
||
|
|
||
|
/* build the header*/
|
||
|
hdr[0] = '\0';
|
||
|
dumpmem2("offset",hdr,6);
|
||
|
dumpmem2("hex",hdr,8);
|
||
|
dumpmem2("uint",hdr,12);
|
||
|
dumpmem2("int",hdr,12);
|
||
|
dumpmem2("float",hdr,12);
|
||
|
dumpmem2("char[4]",hdr,16);
|
||
|
dumpmem2("double",hdr,12);
|
||
|
strcat(hdr,"\n");
|
||
|
fprintf(stderr,"%s",hdr);
|
||
|
|
||
|
count = (len / sizeof(int));
|
||
|
rem = (len % sizeof(int));
|
||
|
imemory = (int*)memory;
|
||
|
|
||
|
for(i=0;i<count;i++) {
|
||
|
unsigned int tmp0 = (unsigned int)imemory[i];
|
||
|
unsigned int tmp1 = (unsigned int)(i<count?imemory[i+1]:0);
|
||
|
if(fromxdr) {tmp0 = ocntoh(tmp0); tmp1 = ocntoh(tmp1);}
|
||
|
dumpmem1(i*sizeof(unsigned int)+bod,tmp0,tmp1);
|
||
|
}
|
||
|
if(rem > 0) {
|
||
|
unsigned int tmp = 0;
|
||
|
memcpy((void*)&tmp,(void*)(imemory+(sizeof(len)*count)),rem);
|
||
|
if(fromxdr) tmp = ocntoh(tmp);
|
||
|
dumpmem1(count*sizeof(unsigned int)+bod,tmp,0);
|
||
|
}
|
||
|
fflush(stderr);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
ocdumppacket(char* memory, int len, int bod)
|
||
|
{
|
||
|
dumpmemory0(memory,len,1,bod);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
ocdumpmemory(char* memory, int len)
|
||
|
{
|
||
|
dumpmemory0(memory,len,0,0);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
ocdumpfile(FILE* file, int datastart)
|
||
|
{
|
||
|
int i,count,rem,len;
|
||
|
long pos;
|
||
|
char dds[4096];
|
||
|
char hdr[1024];
|
||
|
struct stat stats;
|
||
|
unsigned int imemory;
|
||
|
unsigned int imemory1;
|
||
|
|
||
|
pos = ftell(file);
|
||
|
fseek(file,0,SEEK_SET);
|
||
|
|
||
|
fstat(fileno(file),&stats);
|
||
|
len = stats.st_size;
|
||
|
|
||
|
fprintf(stderr,"\nlength=%d datastart=%d\n",len,datastart);
|
||
|
|
||
|
if(datastart > 0) {
|
||
|
fread(dds,1,datastart,file);
|
||
|
dds[datastart] = '\0';
|
||
|
fprintf(stderr,"DDS:\n");
|
||
|
fprintf(stderr,"====================\n");
|
||
|
fprintf(stderr,"%s\n",dds);
|
||
|
} else {
|
||
|
fprintf(stderr,"DDS: none specified\n");
|
||
|
}
|
||
|
fprintf(stderr,"====================\n");
|
||
|
|
||
|
/* build the header*/
|
||
|
hdr[0] = '\0';
|
||
|
dumpmem2("offset",hdr,5);
|
||
|
dumpmem2("hex",hdr,8);
|
||
|
dumpmem2("uint",hdr,12);
|
||
|
dumpmem2("int",hdr,12);
|
||
|
dumpmem2("float",hdr,12);
|
||
|
dumpmem2("char[4]",hdr,16);
|
||
|
dumpmem2("double",hdr,12);
|
||
|
strcat(hdr,"\n");
|
||
|
fprintf(stderr,"%s",hdr);
|
||
|
|
||
|
len -= datastart;
|
||
|
count = (len / sizeof(unsigned int));
|
||
|
rem = (len % sizeof(unsigned int));
|
||
|
|
||
|
for(i=0;i<count;i++) {
|
||
|
long pos;
|
||
|
fread(&imemory,sizeof(unsigned int),1,file);
|
||
|
pos = ftell(file);
|
||
|
fread(&imemory1,sizeof(unsigned int),1,file);
|
||
|
fseek(file,pos,SEEK_SET);
|
||
|
imemory = ocntoh(imemory);
|
||
|
imemory1 = ocntoh(imemory1);
|
||
|
dumpmem1(i*4+datastart,imemory,imemory1);
|
||
|
}
|
||
|
if(rem > 0) {
|
||
|
fprintf(stderr,">>>>remainder=%d\n",rem);
|
||
|
}
|
||
|
fflush(stderr);
|
||
|
fseek(file,pos,SEEK_SET); /* leave it as we found it*/
|
||
|
}
|
||
|
|
||
|
void
|
||
|
ocdumpmemdata(OCmemdata* memdata, OCbytes* buf)
|
||
|
{
|
||
|
if(memdata == NULL || buf == NULL) return;
|
||
|
ocdumpmemdata1(memdata,buf,0);
|
||
|
}
|
||
|
|
||
|
static char*
|
||
|
ocmodestr(OCmode mode)
|
||
|
{
|
||
|
switch (mode) {
|
||
|
case Emptymode: return "Empty";
|
||
|
case Nullmode: return "Null";
|
||
|
case Dimmode: return "Dim";
|
||
|
case Recordmode: return "Record";
|
||
|
case Fieldmode: return "Field";
|
||
|
case Datamode: return "Data";
|
||
|
}
|
||
|
return "?";
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
ocdumpmemdata1(OCmemdata* md, OCbytes* buf, int depth)
|
||
|
{
|
||
|
OCmemdata** mdp;
|
||
|
unsigned int i;
|
||
|
char tmp[1024];
|
||
|
|
||
|
switch ((OCtype)md->octype) {
|
||
|
|
||
|
case OC_Sequence:
|
||
|
case OC_Grid:
|
||
|
case OC_Structure:
|
||
|
case OC_Dataset:
|
||
|
sprintf(tmp,"%s%s/%s (%lu) {\n",dent(depth),
|
||
|
octypetostring((OCtype)md->octype),
|
||
|
ocmodestr(md->mode),
|
||
|
(unsigned long)md->count);
|
||
|
ocbytescat(buf,tmp);
|
||
|
mdp = (OCmemdata**)md->data.data;
|
||
|
switch ((OCmode)md->mode) {
|
||
|
case Fieldmode:
|
||
|
for(i=0;i<md->count;i++) {
|
||
|
sprintf(tmp,"%s[%u]",dent(depth+1),i);
|
||
|
ocbytescat(buf,tmp);
|
||
|
ocdumpmemdata1(mdp[i],buf,depth+1);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case Dimmode:
|
||
|
for(i=0;i<md->count;i++) {
|
||
|
sprintf(tmp,"%s(%u)",dent(depth+1),i);
|
||
|
ocbytescat(buf,tmp);
|
||
|
ocdumpmemdata1(mdp[i],buf,depth+1);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case Recordmode:
|
||
|
for(i=0;i<md->count;i++) {
|
||
|
sprintf(tmp,"%s{%u}",dent(depth+1),i);
|
||
|
ocbytescat(buf,tmp);
|
||
|
ocdumpmemdata1(mdp[i],buf,depth+1);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default: break;
|
||
|
}
|
||
|
sprintf(tmp,"%s}\n",dent(depth));
|
||
|
break;
|
||
|
|
||
|
case OC_Primitive: {
|
||
|
OCtype etype = (OCtype)md->etype;
|
||
|
char* data = md->data.data;
|
||
|
sprintf(tmp,"%s%s/%s (%lu) {",dent(depth),
|
||
|
octypetostring(etype),ocmodestr(md->mode),(unsigned long)md->count);
|
||
|
ocbytescat(buf,tmp);
|
||
|
for(i=0;i<md->count;i++) {
|
||
|
char* p = data + (octypesize(etype)*i);
|
||
|
ocbytescat(buf," ");
|
||
|
octypeprint(etype,tmp,sizeof(tmp),(void*)p);
|
||
|
ocbytescat(buf,tmp);
|
||
|
}
|
||
|
ocbytescat(buf," }\n");
|
||
|
} break;
|
||
|
|
||
|
default: break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
ocdd(OCstate* state, OCnode* root)
|
||
|
{
|
||
|
#ifdef OC_DISK_STORAGE
|
||
|
ocdumpfile(root->tree->data.file,root->tree->data.bod);
|
||
|
#else
|
||
|
ocdumpmemory(root->tree->data.xdrdata,root->tree->data.bod);
|
||
|
#endif
|
||
|
}
|
||
|
|