static int walkAtomicVar(NCD4meta* compiler, NCD4node* topvar, NCD4node* var, void** offsetp) { int ret = NC_NOERR; void* offset; d4size_t i; nc_type subsort; d4size_t dimproduct; NCD4node* basetype; basetype = (var->sort == NCD4_TYPE ? var : var->basetype); subsort = basetype->subsort; dimproduct = (var->sort == NCD4_TYPE ? 1 : NCD4_dimproduct(var)); offset = *offsetp; if(subsort == NC_ENUM) subsort = var->basetype->basetype->subsort; /* Only need to swap multi-byte integers and floats */ if(subsort != NC_STRING) { int typesize = NCD4_typesize(subsort); d4size_t totalsize = typesize*dimproduct; if(typesize == 1) { offset = INCR(offset,totalsize); } else { /*(typesize > 1)*/ for(i=0;i<dimproduct;i++) { char* sp = (char*)offset; if(compiler->swap) { switch (typesize) { case 2: swapinline16(sp); break; case 4: swapinline32(sp); break; case 8: swapinline64(sp); break; default: break; } } offset = INCR(offset,typesize); } } } else if(subsort == NC_STRING) { /* remaining case; just convert the counts */ COUNTERTYPE count; for(i=0;i<dimproduct;i++) { /* Get string count */ if(compiler->swap) swapinline64(offset); count = GETCOUNTER(offset); SKIPCOUNTER(offset); /* skip count bytes */ offset = INCR(offset,count); } } *offsetp = offset; return THROW(ret); }
/* Remember that the base type of var is a vlen. */ static int walkSeq(NCD4meta* compiler, NCD4node* topvar, NCD4node* vlentype, void** offsetp) { int ret = NC_NOERR; int i; void* offset; d4size_t recordcount; NCD4node* basetype; offset = *offsetp; /* process the record count */ recordcount = GETCOUNTER(offset); SKIPCOUNTER(offset); if(compiler->swap) swapinline64(&recordcount); basetype = vlentype->basetype; /* This may be of any type potentially */ assert(basetype->sort == NCD4_TYPE); for(i=0;i<recordcount;i++) { switch(basetype->subsort) { default: /* atomic basetype */ if((ret=walkAtomicVar(compiler,topvar,basetype,&offset))) goto done; break; case NC_OPAQUE: if((ret=walkOpaqueVar(compiler,topvar,basetype,&offset))) goto done; break; case NC_STRUCT: /* We can treat each record like a structure instance */ if((ret=walkStruct(compiler,topvar,basetype,&offset))) goto done; break; case NC_SEQ: if((ret=walkSeq(compiler,topvar,basetype,&offset))) goto done; break; } } *offsetp = offset; done: return THROW(ret); }
static int walkOpaqueVar(NCD4meta* compiler, NCD4node* topvar, NCD4node* var, void** offsetp) { int ret = NC_NOERR; void* offset; d4size_t i; unsigned long long count; d4size_t dimproduct = NCD4_dimproduct(var); dimproduct = (var->sort == NCD4_TYPE ? 1 : NCD4_dimproduct(var)); offset = *offsetp; for(i=0;i<dimproduct;i++) { /* Get and swap opaque count */ if(compiler->swap) swapinline64(offset); count = GETCOUNTER(offset); SKIPCOUNTER(offset); offset = INCR(offset,count); } *offsetp = offset; return THROW(ret); }
static OCerror ocread(OCdata* data, XXDR* xdrs, char* memory, size_t memsize, size_t start, size_t count) { int i; OCnode* pattern; OCtype etype; off_t elemsize, totalsize, xdrtotal, xdrstart; int scalar; OCASSERT(data != NULL); OCASSERT(memory != NULL); OCASSERT(memsize > 0); OCASSERT(count > 0); OCASSERT((start+count) <= data->ninstances); pattern = data->pattern; etype = pattern->etype; scalar = (pattern->array.rank == 0); /* Note that for strings, xdrsize == 0 */ xdrtotal = count*data->xdrsize; /* amount (in xdr sizes) to read */ xdrstart = start*data->xdrsize; /* offset from the start of the data */ elemsize = octypesize(etype); /* wrt memory, not xdrsize */ totalsize = elemsize*count; /* validate memory space*/ if(memsize < totalsize) return OCTHROW(OC_EINVAL); /* copy out with appropriate byte-order conversions */ switch (etype) { case OC_Int32: case OC_UInt32: case OC_Float32: xxdr_setpos(xdrs,data->xdroffset+xdrstart); if(!xxdr_getbytes(xdrs,memory,xdrtotal)) {OCTHROW(OC_EDATADDS); goto xdrfail;} if(!xxdr_network_order) { unsigned int* p; for(p=(unsigned int*)memory,i=0;i<count;i++,p++) { swapinline32(p); } } break; case OC_Int64: case OC_UInt64: xxdr_setpos(xdrs,data->xdroffset+xdrstart); if(!xxdr_getbytes(xdrs,memory,xdrtotal)) {OCTHROW(OC_EDATADDS); goto xdrfail;} if(!xxdr_network_order) { unsigned long long* llp; for(llp=(unsigned long long*)memory,i=0;i<count;i++,llp++) { swapinline64(llp); } } break; case OC_Float64: xxdr_setpos(xdrs,data->xdroffset+xdrstart); if(!xxdr_getbytes(xdrs,memory,xdrtotal)) {OCTHROW(OC_EDATADDS); goto xdrfail;} { double* dp; for(dp=(double*)memory,i=0;i<count;i++,dp++) { double swap; xxdrntohdouble((char*)dp,&swap); *dp = swap; } } break; /* non-packed fixed length, but memory size < xdrsize */ case OC_Int16: case OC_UInt16: { /* In order to avoid allocating a lot of space, we do this one int at a time */ /* Remember also that the short is not packed, so its xdr size is twice its memory size */ xxdr_setpos(xdrs,data->xdroffset+xdrstart); if(scalar) { if(!xxdr_ushort(xdrs,(unsigned short*)memory)) {OCTHROW(OC_EDATADDS); goto xdrfail;} } else { unsigned short* sp = (unsigned short*)memory; for(i=0;i<count;i++,sp++) { unsigned int tmp; if(!xxdr_getbytes(xdrs,(char*)&tmp,(off_t)XDRUNIT)) {OCTHROW(OC_EDATADDS); goto xdrfail;} /* convert from network order if necessary */ if(!xxdr_network_order) swapinline32(&tmp); /* store as unsigned short */ *sp = (unsigned short)tmp; } } } break; /* Do the byte types, packed/unpacked */ case OC_Byte: case OC_UByte: case OC_Char: if(scalar) { /* scalar bytes are stored in xdr as int */ xxdr_setpos(xdrs,data->xdroffset+xdrstart); if(!xxdr_uchar(xdrs,(unsigned char*)memory)) {OCTHROW(OC_EDATADDS); goto xdrfail;} } else { /* the xdroffset will always be at the start of the packed data, so we need to add the start count to it */ xxdr_setpos(xdrs,data->xdroffset+xdrstart); if(!xxdr_getbytes(xdrs,memory,xdrtotal)) {OCTHROW(OC_EDATADDS); goto xdrfail;} } break; /* Hard case, because strings are variable length */ case OC_String: case OC_URL: { /* use the data->nstrings data->string fields */ char** sp = (char**)memory; if(count > data->nstrings) return OCTHROW(OC_EDATADDS); for(i=0;i<count;i++,sp++) { off_t len; off_t offset = data->strings[start+i]; xxdr_setpos(xdrs,offset); /* get the string */ if(!xxdr_string(xdrs,sp,&len)) {OCTHROW(OC_EDATADDS); goto xdrfail;} } } break; default: OCPANIC("unexpected etype"); break; } return OC_NOERR; xdrfail: oclog(OCLOGERR,"DAP DATADDS packet is apparently too short"); return OCTHROW(OC_EDATADDS); }