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); }
/* Extract data from the xdr packet into a chunk of memory. Normally, it is assumed that we are (at least virtually) "at" a single instance in the xdr packet; which we read. Virtually because for packed data, we need to point to the beginning of the packed data and use the index to indicate which packed element to get. */ int ocxdrread(XDR* xdrs, char* memory, size_t memsize, int packed, OCtype octype, unsigned int start, size_t count) { int stat = OC_NOERR; unsigned int i; size_t elemsize = octypesize(octype); char* localmem = NULL; char* startmem = NULL; size_t totalsize; size_t xdrsize; unsigned int xdrckp = xdr_getpos(xdrs); /* validate memory space*/ totalsize = elemsize*count; if(memsize < totalsize) return THROW(OC_EINVAL); /* Handle packed data specially*/ /* WARNING: assumes that the initial count has been read*/ if(packed) { char tmp[LOCALMEMMAX]; unsigned int readsize = start+count; if(readsize <= LOCALMEMMAX) /* avoid malloc/free for common case*/ localmem = tmp; else { localmem = (char*)ocmalloc(readsize); MEMCHECK(localmem,OC_ENOMEM); } if(!xdr_opaque(xdrs,(char*)localmem,readsize)) return xdrerror(); memcpy((void*)memory,(void*)(localmem+start),count); if(readsize > LOCALMEMMAX) ocfree(localmem); if(!xdr_setpos(xdrs,xdrckp)) return xdrerror(); /* revert to beginning*/ return THROW(OC_NOERR); } /* Not packed: extract count items; use xdr_opaque to speed up*/ if(octype == OC_String || octype == OC_URL) { /* do nothing here; handle below*/ } else if(octype == OC_Float64 || octype == OC_UInt64 || octype == OC_Int64) { unsigned int* p; xdrsize = 2*(start+count)*BYTES_PER_XDR_UNIT; localmem = (char*)ocmalloc(xdrsize); startmem = localmem+(2*start*BYTES_PER_XDR_UNIT); MEMCHECK(localmem,OC_ENOMEM); if(!xdr_opaque(xdrs,(char*)localmem,xdrsize)) return xdrerror(); if(!oc_network_order) { for(p=(unsigned int*)startmem,i=0;i<2*count;i++,p++) { unsigned int swap = *p; swapinline(*p,swap); } } } else { unsigned int* p; xdrsize = (start+count)*BYTES_PER_XDR_UNIT; localmem = (char*)ocmalloc(xdrsize); MEMCHECK(localmem,OC_ENOMEM); startmem = localmem+(start*BYTES_PER_XDR_UNIT); if(!xdr_opaque(xdrs,(char*)localmem,xdrsize)) return xdrerror(); if(!oc_network_order) { for(p=(unsigned int*)startmem,i=0;i<count;i++,p++) { unsigned int swap = *p; swapinline(*p,swap); } } } switch (octype) { case OC_Char: case OC_Byte: case OC_UByte: { char* pmem = (char*)memory; unsigned int* p = (unsigned int*)startmem; for(i=0;i<count;i++) {*pmem++ = (char)(*p++);} } break; case OC_Int16: case OC_UInt16: { unsigned short* pmem = (unsigned short*)memory; unsigned int* p = (unsigned int*)startmem; for(i=0;i<count;i++) {*pmem++ = (unsigned short)(*p++);} } break; case OC_Int32: case OC_UInt32: { memcpy((void*)memory,(void*)startmem,count*sizeof(unsigned int)); } break; case OC_Float32: { memcpy((void*)memory,(void*)startmem,count*sizeof(float)); } break; case OC_Int64: case OC_UInt64: case OC_Float64: { unsigned int* p; unsigned int* pmem = (unsigned int*)memory; /* Sometimes need to invert order*/ for(p=(unsigned int*)startmem,i=0;i<count;i++) { if(oc_invert_xdr_double) { pmem[1] = (unsigned int)(*p++); pmem[0] = (unsigned int)(*p++); } else { pmem[0] = (unsigned int)(*p++); pmem[1] = (unsigned int)(*p++); } pmem += 2; } } break; case OC_String: case OC_URL: { char* s = NULL; char** pmem = (char**)memory; /* First skip to the starting string */ for(i=0;i<start;i++) { s = NULL; /* make xdr_string alloc the space */ if(!xdr_string(xdrs,&s,OC_INT32_MAX)) return xdrerror(); ocfree(s); } /* Read count strings */ for(i=0;i<count;i++) { s = NULL; /* make xdr_string alloc the space */ if(!xdr_string(xdrs,&s,OC_INT32_MAX)) return xdrerror(); pmem[i] = s; } } break; default: return THROW(OC_EINVAL); } ocfree(localmem); if(!xdr_setpos(xdrs,xdrckp)) return xdrerror(); /* revert to beginning*/ return THROW(stat); }