static size_t maxindexfor(OCnode* node, OCmode srcmode) { switch (srcmode) { case Dimmode: if(node->octype == OC_Sequence) return 0; if(node->octype == OC_Primitive) return 1; return oclistlength(node->subnodes); case Recordmode: if(node->array.rank > 0) return totaldimsize(node); if(node->octype == OC_Primitive) return 1; return oclistlength(node->subnodes); case Datamode: return 1; case Nullmode: case Fieldmode: if(node->array.rank > 0) return totaldimsize(node); if(node->octype == OC_Primitive) return 1; if(node->octype == OC_Sequence) return 0; return oclistlength(node->subnodes); case Emptymode: default: OCPANIC1("No defined mode transition: %d",(int)srcmode); break; } return oclistlength(node->subnodes); }
/* Extract the actual element count from the xdr packet*/ size_t ocarraycount(OCstate* state, OCcontent* content) { unsigned int count; unsigned int xdrsave; OCnode* node = content->node; XDR* xdrs; OCASSERT((node != NULL)); OCASSERT((content->mode == Dimmode)); count = totaldimsize(node); /* If we are using memdata; then use that to verify */ if(content->memdata != NULL) { OCASSERT(content->memdata->count == count); return (size_t)count; } /* Otherwise verify against xdr */ xdrs = content->tree->data.xdrs; OCASSERT((xdrs != NULL)); /* checkpoint current location */ xdrsave = xdr_getpos(xdrs); /* move to content location*/ OCASSERT(content->xdrpos.valid); if(!xdr_setpos(xdrs,content->xdrpos.offset)) return 0; /* extract the count*/ if(!xdr_u_int(xdrs,&count)) count = 0; /* return to checkpoint position*/ if(!xdr_setpos(xdrs,xdrsave)) return 0; return (size_t)count; }
static int occompile1(OCstate* state, OCnode* xnode, OCmemdata** memdatap, XDR* xdrs) { unsigned int i,j,xdrcount; int stat = OC_NOERR; size_t nelements; OCmemdata* memdata = NULL; OCmemdata* structdata = NULL; OClist* records = NULL; OCerror ocstat = OC_NOERR; OCmemdata** pmem = NULL; /* Allocate the space for this memdata chunk */ switch (xnode->octype) { case OC_Dataset: case OC_Grid: case OC_Structure: { if(xnode->array.rank == 0) { ocstat = occompilefields(state,xnode,&memdata,xdrs); if(ocstat != OC_NOERR) goto fail; } else { /* rank > 0 */ /* Compute the actual index count after projections */ nelements = totaldimsize(xnode); if(nelements == 0) return THROW(OC_ENODATA); memdata = makememdata(xnode->octype,OC_NAT,nelements); MEMCHECK(memdata,OC_ENOMEM); memdata->mode = Dimmode; pmem = (OCmemdata**)&memdata->data; /* Consume the leading count field */ if(!xdr_u_int(xdrs,&xdrcount)) {stat = OC_EXDR; goto fail;} /* validate the datadds dimensions */ if(xdrcount != nelements) {stat=OC_EINVALCOORDS; goto fail;} for(i=0;i<nelements;i++) { ocstat = occompilefields(state,xnode,&structdata,xdrs); if(ocstat != OC_NOERR) { if(ocstat != OC_ENODATA) goto fail; structdata = NULL; /* Leave a hole for this element */ } pmem[i] = structdata; structdata = NULL; } } } break; case OC_Sequence:{ /* Since we do not know the # records beforehand, use a oclist to collect the record instances. Query: this stores by recor (where e.g. original ocapi stores by column). How hard would it be to make the storage choice conditional on some user defined flag? */ records = oclistnew(); for(;;) { /* pick up the sequence record begin marker*/ char tmp[sizeof(unsigned int)]; /* extract the tag byte*/ if(!xdr_opaque(xdrs,tmp,sizeof(tmp))) {stat = OC_EXDR; goto fail;} if(tmp[0] == StartOfoclist) { /* Walk each member field*/ ocstat = occompilefields(state,xnode,&structdata,xdrs); if(ocstat != OC_NOERR) goto fail; oclistpush(records,(ocelem)structdata); structdata = NULL; } 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; goto fail; } } /* Convert the list to a proper OCmemdata */ nelements = oclistlength(records); memdata = makememdata(xnode->octype,OC_NAT,nelements); MEMCHECK(memdata,OC_ENOMEM); memdata->mode = Recordmode; pmem = (OCmemdata**)&memdata->data; for(j=0;j<nelements;j++) { OCmemdata* record = (OCmemdata*)oclistget(records,j); pmem[j] = record; } oclistfree(records); records = NULL; } break; case OC_Primitive: ocstat = occompileprim(state,xnode,&memdata,xdrs); if(ocstat != OC_NOERR) goto fail; break; default: OCPANIC1("ocmap: encountered unexpected node type: %x",xnode->octype); break; } /*ok:*/ if(memdatap) *memdatap = memdata; return THROW(ocstat); fail: if(records != NULL) for(i=0;i<oclistlength(records);i++) freeocmemdata((OCmemdata*)oclistget(records,i)); freeocmemdata(memdata); freeocmemdata(structdata); return THROW(ocstat); }
static int occompileprim(OCstate* state, OCnode* xnode, OCmemdata** memdatap, XDR* xdrs) { unsigned int xdrcount,i; size_t nelements = 0; OCerror ocstat = OC_NOERR; OCmemdata* memdata = NULL; OCASSERT((xnode->octype == OC_Primitive)); /* Use the count from the datadds */ nelements = totaldimsize(xnode); if(xnode->array.rank > 0) { /* Get first copy of the dimension count */ if(!xdr_u_int(xdrs,&xdrcount)) {ocstat = OC_EXDR; goto fail;} if(xdrcount != nelements) {ocstat=OC_EINVALCOORDS; goto fail;} if(xnode->etype != OC_String && xnode->etype != OC_URL) { /* Get second copy of the dimension count */ if(!xdr_u_int(xdrs,&xdrcount)) {ocstat = OC_EXDR; goto fail;} if(xdrcount != nelements) {ocstat=OC_EINVALCOORDS; goto fail;} } } else { nelements = 1; xdrcount = 1; } memdata = makememdata(xnode->octype,xnode->etype,nelements); MEMCHECK(memdata,OC_ENOMEM); memdata->mode = (xnode->array.rank > 0?Dimmode:Datamode); switch (xnode->etype) { case OC_String: case OC_URL: {/* Get the array of strings and store pointers in buf */ char** dst = (char**)memdata->data.data; for(i=0;i<xdrcount;i++) { char* s = NULL; if(!xdr_string(xdrs,(void*)&s,OC_INT32_MAX)) {ocstat = OC_EXDR; goto fail;} dst[i] = s; } } break; case OC_Byte: case OC_UByte: case OC_Char: { if(xnode->array.rank == 0) { /* Single unpacked character/byte */ union {unsigned int i; char c[BYTES_PER_XDR_UNIT];} u; if(!xdr_opaque(xdrs,u.c,BYTES_PER_XDR_UNIT)) {ocstat = OC_EXDR; goto fail;} u.i = ocntoh(u.i); memdata->data.data[0] = (char)u.i; } else { /* Packed characters; count will have already been read */ char* dst = memdata->data.data; if(!xdr_opaque(xdrs,dst,xdrcount)) {ocstat = OC_EXDR; goto fail;} } } break; case OC_Int16: case OC_UInt16: { unsigned short* dst = (unsigned short*)memdata->data.data; unsigned int* src; size_t xdrsize = xdrcount*BYTES_PER_XDR_UNIT; src = (unsigned int*)ocmalloc(xdrsize); if(!xdr_opaque(xdrs,(char*)src,xdrsize)) {ocfree(src); ocstat = OC_EXDR; goto fail;} if(!oc_network_order) { for(i=0;i<xdrcount;i++) { /* Write in place */ unsigned int hostint = src[i]; swapinline(dst[i],hostint); } } ocfree(src); } break; case OC_Int32: case OC_UInt32: case OC_Float32: { unsigned int* dst = (unsigned int*)memdata->data.data; size_t xdrsize = xdrcount*BYTES_PER_XDR_UNIT; if(!xdr_opaque(xdrs,(char*)dst,xdrsize)) {ocstat = OC_EXDR; goto fail;} if(!oc_network_order) { for(i=0;i<xdrcount;i++) { unsigned int hostint = dst[i]; swapinline(dst[i],hostint); } } } break; case OC_Int64: case OC_UInt64: case OC_Float64: { unsigned int* dst = (unsigned int*)memdata->data.data; size_t xdrsize = 2*xdrcount*BYTES_PER_XDR_UNIT; if(!xdr_opaque(xdrs,(char*)dst,xdrsize)) {ocstat = OC_EXDR; goto fail;} if(!oc_network_order) { for(i=0;i<2*xdrcount;i++) { unsigned int hostint = dst[i]; swapinline(dst[i],hostint); } } if(oc_invert_xdr_double) { /* May need to invert each pair */ for(i=0;i<2*xdrcount;i+=2) { unsigned int tmp = dst[i]; dst[i] = dst[i+1]; dst[i+1] = tmp; } } } break; default: OCPANIC1("unexpected etype: %d",xnode->etype); } /* switch */ /*ok:*/ if(memdatap) *memdatap = memdata; return THROW(ocstat); fail: freeocmemdata(memdata); return THROW(ocstat); }