void gen_chararray(Dimset* dimset, int dimindex, Datalist* data, Bytebuffer* charbuf, Datalist* fillsrc) { int fillchar = getfillchar(fillsrc); int rank = rankfor(dimset); int firstunlim = findunlimited(dimset,0); int nunlim = countunlimited(dimset); int nc3unlim = (nunlim <= 1 && (firstunlim == 0 || firstunlim == rank)); /* netcdf-3 case of at most 1 unlim in 0th dimension */ /* Case: netcdf3 case */ if(nc3unlim) { gen_leafchararray(dimset,0,data,charbuf,fillchar); return; } /* else generate should have done all the hard work */ gen_leafchararray(dimset,dimindex,data,charbuf,fillchar); }
static void generate_array(Symbol* vsym, Bytebuffer* code, Datalist* filler, Generator* generator, Writer writer ) { Dimset* dimset = &vsym->typ.dimset; int rank = dimset->ndims; Symbol* basetype = vsym->typ.basetype; nc_type typecode = basetype->typ.typecode; Odometer* odom; nciter_t iter; ASSERT(rank > 0); /* Start by doing easy cases */ #ifdef CHARBUG if(typecode == NC_CHAR) { /* case: character typed variable, rank > 0 */ Bytebuffer* charbuf = bbNew(); gen_chararray(dimset,vsym->data,charbuf,filler); generator->charconstant(generator,code,charbuf); bbFree(charbuf); odom = newodometer(dimset,NULL,NULL); writer(generator,vsym,code,odom->rank,odom->start,odom->count); } else #else /*!CHARBUG*/ /* Case: char var && dim 1..n are not unlimited */ if(findunlimited(dimset,1) == rank && typecode == NC_CHAR) { Bytebuffer* charbuf = bbNew(); gen_leafchararray(dimset,0,vsym->data,charbuf,filler); generator->charconstant(generator,code,charbuf); bbFree(charbuf); odom = newodometer(dimset,NULL,NULL); writer(generator,vsym,code,odom->rank,odom->start,odom->count); } else #endif /* Case 2: dim 1..n are not unlimited */ if(findunlimited(dimset,1) == rank) { size_t offset = 0; /* where are we in the data list */ size_t nelems = 0; /* # of data list items to read */ /* Create an iterator and odometer and just walk the datalist */ nc_get_iter(vsym,nciterbuffersize,&iter); odom = newodometer(dimset,NULL,NULL); for(;;offset+=nelems) { int i,uid; nelems=nc_next_iter(&iter,odom->start,odom->count); if(nelems == 0) break; bbClear(code); generator->listbegin(generator,LISTDATA,vsym->data->length,code,&uid); for(i=0;i<nelems;i++) { #ifdef ITERBUG Constant* con = datalistith(vsym->data,i); #else NCConstant* con = datalistith(vsym->data,i+offset); #endif generator->list(generator,LISTDATA,uid,i,code); #ifdef USE_NOFILL if(nofill_flag && con == NULL) break; else #endif generate_basetype(basetype,con,code,filler,generator); } generator->listend(generator,LISTDATA,uid,i,code); #ifdef USE_NOFILL writer(generator,vsym,code,rank,odom->start,odom->index); #else writer(generator,vsym,code,rank,odom->start,odom->count); #endif } } else { /* Hard case: multiple unlimited dimensions */ /* Setup iterator and odometer */ #ifdef CHARBUG nc_get_iter(vsym,nciterbuffersize,&iter); #else nc_get_iter(vsym,NC_MAX_UINT,&iter); /* effectively infinite */ #endif odom = newodometer(dimset,NULL,NULL); for(;;) {/* iterate in nelem chunks */ /* get nelems count and modify odometer */ size_t nelems=nc_next_iter(&iter,odom->start,odom->count); if(nelems == 0) break; generate_arrayr(vsym,code,vsym->data, odom, /*dim index=*/0, filler,generator ); #ifdef USE_NOFILL writer(generator,vsym,code,odom->rank,odom->start,odom->index); #else writer(generator,vsym,code,odom->rank,odom->start,odom->count); #endif } } odometerfree(odom); }
static void generate_arrayr(Symbol* vsym, Bytebuffer* code, Datalist* list, Odometer* odom, int dimindex, Datalist* filler, Generator* generator ) { Symbol* basetype = vsym->typ.basetype; Dimset* dimset = &vsym->typ.dimset; int rank = dimset->ndims; int lastunlimited; int typecode = basetype->typ.typecode; lastunlimited = findlastunlimited(dimset); if(lastunlimited == rank) lastunlimited = 0; ASSERT(rank > 0); ASSERT(dimindex >= 0 && dimindex < rank); #ifdef CHARBUG ASSERT(typecode != NC_CHAR); #else /*!CHARBUG*/ if(dimindex == lastunlimited && typecode == NC_CHAR) { Bytebuffer* charbuf = bbNew(); gen_leafchararray(dimset,dimindex,list,charbuf,filler); generator->charconstant(generator,code,charbuf); bbFree(charbuf); } else #endif /*!CHARBUG*/ if(dimindex == lastunlimited) { int uid,i; Odometer* slabodom; /* build a special odometer to walk the last few dimensions (similar to case 2 above) */ slabodom = newsubodometer(odom,dimset,dimindex,rank); /* compute the starting offset in our datalist (Assumes that slabodom->index[i] == slabodom->start[i]) */ generator->listbegin(generator,LISTDATA,list->length,code,&uid); for(i=0;odometermore(slabodom);i++) { size_t offset = odometeroffset(slabodom); NCConstant* con = datalistith(list,offset); #ifdef USE_NOFILL if(nofill_flag && con == NULL) break; #endif generator->list(generator,LISTDATA,uid,i,code); generate_basetype(basetype,con,code,filler,generator); odometerincr(slabodom); } generator->listend(generator,LISTDATA,uid,i,code); odometerfree(slabodom); } else { /* If we are strictly to the left of the next unlimited then our datalist is a list of compounds representing the next unlimited; so walk the subarray from this index upto next unlimited. */ int i; Odometer* slabodom; int nextunlimited = findunlimited(dimset,dimindex+1); ASSERT((dimindex < nextunlimited && (dimset->dimsyms[nextunlimited]->dim.isunlimited))); /* build a sub odometer */ slabodom = newsubodometer(odom,dimset,dimindex,nextunlimited); /* compute the starting offset in our datalist (Assumes that slabodom->index[i] == slabodom->start[i]) */ for(i=0;odometermore(slabodom);i++) { size_t offset = odometeroffset(slabodom); NCConstant* con = datalistith(list,offset); #ifdef USE_NOFILL if(nofill_flag && con == NULL) break; #endif if(con == NULL || con->nctype == NC_FILL) { if(filler == NULL) filler = getfiller(vsym); generate_arrayr(vsym,code,filler,odom,nextunlimited,NULL,generator); } else if(!islistconst(con)) semwarn(constline(con),"Expected {...} representing unlimited list"); else { Datalist* sublist = con->value.compoundv; generate_arrayr(vsym,code,sublist,odom,nextunlimited,filler,generator); } odometerincr(slabodom); } odometerfree(slabodom); } return; }