int countrecords(OCnode* node, XDR* xdrs, size_t* nrecordsp) { int stat = OC_NOERR; size_t nrecords = 0; unsigned int xdroffset; if(node->octype != OC_Sequence) return THROW(OC_EINVAL); /* checkpoint the xdr position*/ xdroffset = xdr_getpos(xdrs); for(;;) { unsigned int i; /* pick up the sequence record begin marker*/ char tmp[sizeof(unsigned int)]; /* extract the tag byte*/ if(!xdr_opaque(xdrs,tmp,sizeof(tmp))) return xdrerror(); if(tmp[0] == StartOfoclist) { /* Walk each member field*/ for(i=0;i<oclistlength(node->subnodes);i++) { OCnode* member = (OCnode*)oclistget(node->subnodes,i); stat = ocskip(member,xdrs); if(stat != OC_NOERR) break; } nrecords++; } else if(tmp[0] == EndOfoclist) { break; /* we are done with the this sequence instance*/ } else { oc_log(LOGERR,"missing/invalid begin/end record marker\n"); stat = OC_EINVALCOORDS; break; } if(stat != OC_NOERR) break; } /* move to checkpoint position*/ if(!xdr_setpos(xdrs,xdroffset)) return xdrerror(); if(nrecordsp != NULL) *nrecordsp = nrecords; return THROW(stat); }
/* Skip arbitrary single instance; except for primitives Assumes that parent will handle arrays of compound instances or records of compound instances of this node type Specifically, all array counts have been absorbed by some parent caller.*/ int ocskipinstance(OCnode* node, XDR* xdrs) { unsigned int i; int stat = OC_NOERR; unsigned int xdrcount; #if 0 unsigned int j,rank; switch (node->octype) { case OC_Dataset: case OC_Grid: OCASSERT((node->array.rank == 0)); stat = ocskip(node,xdrs); break; case OC_Sequence: /* instance is essentially same a structure */ case OC_Structure: if(node->dap.instancesize > 0) { /* do a direct skip*/ if(!xdr_skip(xdrs,node->dap.instancesize)) return xdrerror(); } else { /* Non-uniform size, we have to skip field by field*/ /* Walk each structure/sequence field*/ for(j=0;j<oclistlength(node->subnodes);j++) { OCnode* field = (OCnode*)oclistget(node->subnodes,j); stat = ocskip(field,xdrs); if(stat != OC_NOERR) break; } if(stat != OC_NOERR) break; } break; case OC_Primitive: if(node->etype == OC_String || node->etype == OC_URL) { if(!xdr_u_int(xdrs,&xdrcount)) return xdrerror(); if(!xdr_skip(xdrs,xdrcount)) return xdrerror(); } else { OCASSERT((node->dap.instancesize > 0)); if(!xdr_skip(xdrs,node->dap.instancesize)) return xdrerror(); } break; default: OCPANIC1("oc_move: encountered unexpected node type: %x",node->octype); break; } #else if(node->dap.instancesize > 0) { /* do a direct skip*/ if(!xdr_skip(xdrs,node->dap.instancesize)) return xdrerror(); } else if(node->octype == OC_Primitive) { OCASSERT((node->etype == OC_String || node->etype == OC_URL)); if(!xdr_u_int(xdrs,&xdrcount)) return xdrerror(); if(!xdr_skip(xdrs,xdrcount)) return xdrerror(); } else { /* Non-uniform size Grid/Sequence/Structure/Dataset;*/ /* we have to skip field by field*/ for(i=0;i<oclistlength(node->subnodes);i++) { OCnode* field = (OCnode*)oclistget(node->subnodes,i); stat = ocskip(field,xdrs); if(stat != OC_NOERR) break; } } #endif return THROW(stat); }
/* Skip arbitrary dimensioned instance; handles dimensioning.*/ int ocskip(OCnode* node, XDR* xdrs) { unsigned int i,j,rank; int stat = OC_NOERR; unsigned int xdrcount; unsigned int len; switch (node->octype) { case OC_Primitive: /* handle non-uniform types separately*/ if(node->etype == OC_String || node->etype == OC_URL) { rank = node->array.rank; xdrcount = 1; if(rank > 0 && !xdr_u_int(xdrs,&xdrcount)) return xdrerror(); len = xdrcount; for(i=0;i<xdrcount;i++) { if(!xdr_u_int(xdrs,&len)) return xdrerror(); if(!xdr_skip(xdrs,len)) return xdrerror(); } } else { /* uniform => do a direct skip*/ OCASSERT((node->dap.arraysize > 0 && node->dap.instancesize > 0)); if(node->array.rank > 0) { if(!xdr_skip(xdrs,node->dap.arraysize)) return xdrerror(); } else { if(!xdr_skip(xdrs,node->dap.instancesize)) return xdrerror(); } } break; case OC_Grid: OCASSERT((node->array.rank == 0)); if(node->dap.instancesize > 0) { /* do a direct skip*/ if(!xdr_skip(xdrs,node->dap.arraysize)) return xdrerror(); break; } else { /* Non-uniform size*/ /* Walk array and maps*/ for(j=0;j<oclistlength(node->subnodes);j++) { OCnode* field = (OCnode*)oclistget(node->subnodes,j); stat = ocskip(field,xdrs); if(stat != OC_NOERR) {THROWCHK(stat); break;} } if(stat != OC_NOERR) {THROWCHK(stat); break;} } break; case OC_Dataset: OCASSERT((node->array.rank == 0)); /* fall-thru*/ case OC_Structure: if(node->dap.instancesize > 0) { /* do a direct skip*/ if(!xdr_skip(xdrs,node->dap.arraysize)) return xdrerror(); } else { /* Non-uniform size, we have to skip element by element*/ rank = node->array.rank; xdrcount = 1; if(rank > 0 && !xdr_u_int(xdrs,&xdrcount)) return xdrerror(); for(i=0;i<xdrcount;i++) { /* skip element by element*/ /* Walk each structure field*/ for(j=0;j<oclistlength(node->subnodes);j++) { OCnode* field = (OCnode*)oclistget(node->subnodes,j); stat = ocskip(field,xdrs); if(stat != OC_NOERR) {THROWCHK(stat); break;} } if(stat != OC_NOERR) {THROWCHK(stat); break;} } } break; case OC_Sequence: /* not uniform, so walk record by record*/ OCASSERT((node->array.rank == 0)); for(;;) { /* pick up the sequence record begin marker*/ char tmp[sizeof(unsigned int)]; /* extract the tag byte*/ if(!xdr_opaque(xdrs,tmp,sizeof(tmp))) return xdrerror(); if(tmp[0] == StartOfoclist) { /* Walk each member field*/ for(j=0;j<oclistlength(node->subnodes);j++) { OCnode* member = (OCnode*)oclistget(node->subnodes,j); stat = ocskip(member,xdrs); if(stat != OC_NOERR) {THROWCHK(stat); break;} } } else if(tmp[0] == EndOfoclist) { break; /* we are done with the this sequence instance*/ } else { oc_log(LOGERR,"missing/invalid begin/end record marker\n"); stat = OC_EINVALCOORDS; {THROWCHK(stat); break;} } if(stat != OC_NOERR) {THROWCHK(stat); break;} } break; default: OCPANIC1("oc_move: encountered unexpected node type: %x",node->octype); break; } return THROW(stat); }
/* The ocfieldcontent procedure has to deal with the fact that the dap constraints may have removed some fields from the datadds and hence some fields may have no representation in the xdr data (or compiled data). */ int ocfieldcontent(OCstate* state, OCcontent* content, OCcontent* fieldcontent, size_t index) { unsigned int i; int stat = OC_NOERR; XDR* xdrs; OCtype octype,etype; int packed; if(state == NULL || content == NULL) return OCTHROW(OC_EINVAL); if(content->mode != Fieldmode) return OCTHROW(OC_EINVAL); if(content->maxindex > 0 && content->maxindex <= index) return OCTHROW(OC_EINVALCOORDS); content->index = index; /* Track our location in parent content */ octype = content->node->octype; etype = content->node->etype; /* check if the data is packed*/ packed = (octype == OC_Primitive && (etype == OC_Byte || etype == OC_UByte || etype == OC_Char)); ocresetcontent(state,fieldcontent); /* Set the state of the new content*/ fieldcontent->state = state; /* make sure*/ fieldcontent->tree = content->tree; fieldcontent->node = (OCnode*)oclistget(content->node->subnodes,index); fieldcontent->packed = packed; fieldcontent->mode = modetransition(fieldcontent->node, content->mode); fieldcontent->index = 0; /* record where we want to be */ fieldcontent->maxindex = maxindexfor(fieldcontent->node,content->mode); if(content->memdata != NULL) { /* Get data from the compiled version */ OCmemdata* md = content->memdata; OCmemdata* next; OCASSERT((md->mode == Fieldmode)); if(md->count <= index) {OCTHROWCHK(stat=OC_ENODATA); goto done;} next = ((OCmemdata**)md->data.data)[index]; if(next == NULL) {OCTHROWCHK(stat=OC_ENODATA); goto done;} fieldcontent->memdata = next; goto done; } xdrs = content->tree->data.xdrs; if(xdrs == NULL) return OCTHROW(OC_EXDR); /* checkpoint the beginning of this instance*/ if(!content->xdrpos.valid) { content->xdrpos.offset = xdr_getpos(xdrs); content->xdrpos.valid = 1; } /* move to checkpoint position*/ if(!xdr_setpos(xdrs,content->xdrpos.offset)) return xdrerror(); switch (content->node->octype) { case OC_Grid: /* Note that the Grid array is field 0 and the maps are 1..nsubnodes*/ case OC_Sequence: case OC_Dataset: case OC_Structure: if(index >= oclistlength(content->node->subnodes)) return OCTHROW(OC_EINVALCOORDS); for(i=0;i<index;i++) { OCnode* field = (OCnode*)oclistget(content->node->subnodes,i); stat = ocskip(field,xdrs); if(stat != OC_NOERR) return OCTHROW(stat); } fieldcontent->xdrpos.offset = xdr_getpos(xdrs); fieldcontent->xdrpos.valid = 1; break; case OC_Primitive: default: return OCTHROW(OC_EINVAL); } /* move back to checkpoint position*/ if(!xdr_setpos(xdrs,content->xdrpos.offset)) return xdrerror(); done: return OCTHROW(stat); }