nc4hdf.c 129 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041
  1. /*
  2. This file is part of netcdf-4, a netCDF-like interface for HDF5, or a
  3. HDF5 backend for netCDF, depending on your point of view.
  4. This file contains functions internal to the netcdf4 library. None of
  5. the functions in this file are exposed in the exetnal API. These
  6. functions handle the HDF interface.
  7. Copyright 2003, University Corporation for Atmospheric
  8. Research. See the COPYRIGHT file for copying and redistribution
  9. conditions.
  10. $Id: nc4hdf.c,v 1.273 2010/05/27 21:34:14 dmh Exp $
  11. */
  12. #include "config.h"
  13. #include "nc4internal.h"
  14. #include <H5DSpublic.h>
  15. #include <math.h>
  16. #ifdef IGNORE
  17. extern NC_FILE_INFO_T *nc_file;
  18. #endif
  19. #define NC3_STRICT_ATT_NAME "_nc3_strict"
  20. /* This is to track opened HDF5 objects to make sure they are
  21. * closed. */
  22. #ifdef EXTRA_TESTS
  23. int num_plists;
  24. int num_spaces;
  25. #endif /* EXTRA_TESTS */
  26. /* This function is needed to handle one special case: what if the
  27. * user defines a dim, writes metadata, then goes back into define
  28. * mode and adds a coordinate var for the already existing dim. In
  29. * that case, I need to recreate the dim's dimension scale dataset,
  30. * and then I need to go to every var in the file which uses that
  31. * dimension, and attach the new dimension scale. */
  32. static int
  33. rec_reattach_scales(NC_GRP_INFO_T *grp, int dimid, hid_t dimscaleid)
  34. {
  35. NC_VAR_INFO_T *var;
  36. NC_GRP_INFO_T *child_grp;
  37. int d;
  38. int retval;
  39. assert(grp && grp->name && dimid >= 0 && dimscaleid >= 0);
  40. LOG((3, "rec_reattach_scales: grp->name %s", grp->name));
  41. /* If there are any child groups, attach dimscale there, if needed. */
  42. for (child_grp = grp->children; child_grp; child_grp = child_grp->next)
  43. if ((retval = rec_reattach_scales(child_grp, dimid, dimscaleid)))
  44. return retval;
  45. /* Find any vars that use this dimension id. */
  46. for (var = grp->var; var; var = var->next)
  47. for (d = 0; d < var->ndims; d++)
  48. if (var->dimids[d] == dimid && !var->dimscale)
  49. {
  50. LOG((2, "rec_reattach_scaled: attaching scale for dimid %d to var %s",
  51. var->dimids[d], var->name));
  52. if (var->created)
  53. {
  54. if (H5DSattach_scale(var->hdf_datasetid, dimscaleid, d) < 0)
  55. return NC_EHDFERR;
  56. var->dimscale_attached[d]++;
  57. }
  58. }
  59. return NC_NOERR;
  60. }
  61. /* This function is needed to handle one special case: what if the
  62. * user defines a dim, writes metadata, then goes back into define
  63. * mode and adds a coordinate var for the already existing dim. In
  64. * that case, I need to recreate the dim's dimension scale dataset,
  65. * and then I need to go to every var in the file which uses that
  66. * dimension, and attach the new dimension scale. */
  67. static int
  68. rec_detach_scales(NC_GRP_INFO_T *grp, int dimid, hid_t dimscaleid)
  69. {
  70. NC_VAR_INFO_T *var;
  71. NC_GRP_INFO_T *child_grp;
  72. int d;
  73. int retval;
  74. assert(grp && grp->name && dimid >= 0 && dimscaleid >= 0);
  75. LOG((3, "rec_detach_scales: grp->name %s", grp->name));
  76. /* If there are any child groups, attach dimscale there, if needed. */
  77. for (child_grp = grp->children; child_grp; child_grp = child_grp->next)
  78. if ((retval = rec_detach_scales(child_grp, dimid, dimscaleid)))
  79. return retval;
  80. /* If there are no vars, we are done. */
  81. if (!grp->var)
  82. return NC_NOERR;
  83. /* Find any (already created) vars that use this dimension id. Go
  84. * through the list backwards to accomdate a HDF5 bug. */
  85. for (var = grp->var; var->next; var = var->next)
  86. ;
  87. for ( ; var; var = var->prev)
  88. for (d = 0; d < var->ndims; d++)
  89. if (var->dimids[d] == dimid && !var->dimscale)
  90. {
  91. LOG((2, "rec_detach_scales: detaching scale for dimid %d to var %s",
  92. var->dimids[d], var->name));
  93. if (var->created)
  94. {
  95. if (var->dimscale_attached[d])
  96. {
  97. if (H5DSdetach_scale(var->hdf_datasetid, dimscaleid, d) < 0)
  98. return NC_EHDFERR;
  99. var->dimscale_attached[d] = 0;
  100. }
  101. }
  102. }
  103. return NC_NOERR;
  104. }
  105. /* Open the dataset and leave it open. */
  106. int
  107. nc4_open_var_grp2(NC_GRP_INFO_T *grp, int varid, hid_t *dataset)
  108. {
  109. NC_VAR_INFO_T *var;
  110. /* Find the requested varid. */
  111. for (var = grp->var; var; var = var->next)
  112. if (var->varid == varid)
  113. break;
  114. if (!var)
  115. return NC_ENOTVAR;
  116. /* Open this dataset if necessary. */
  117. if (!var->hdf_datasetid)
  118. if ((var->hdf_datasetid = H5Dopen2(grp->hdf_grpid, var->name,
  119. H5P_DEFAULT)) < 0)
  120. return NC_ENOTVAR;
  121. *dataset = var->hdf_datasetid;
  122. return NC_NOERR;
  123. }
  124. /* Write or read one element of data.
  125. Oh, better far to live and die
  126. Under the brave black flag I fly,
  127. Than play a sanctimonious part,
  128. With a pirate head and a pirate heart.
  129. Away to the cheating world go you,
  130. Where pirates all are well-to-do.
  131. But I'll be true to the song I sing,
  132. And live and die a Pirate king.
  133. */
  134. int
  135. nc4_pg_var1(NC_PG_T pg, NC_FILE_INFO_T *nc, int ncid, int varid,
  136. const size_t *indexp, nc_type xtype, int is_long, void *ip)
  137. {
  138. NC_GRP_INFO_T *grp;
  139. NC_VAR_INFO_T *var;
  140. int i;
  141. size_t start[NC_MAX_VAR_DIMS], count[NC_MAX_VAR_DIMS];
  142. int retval;
  143. /* Find file and var, cause I need the number of dims. */
  144. assert(nc);
  145. if ((retval = nc4_find_g_var_nc(nc, ncid, varid, &grp, &var)))
  146. return retval;
  147. assert(grp && var && var->name);
  148. /* Set up the count and start arrays. */
  149. for (i=0; i<var->ndims; i++)
  150. {
  151. start[i] = indexp[i];
  152. count[i] = 1;
  153. }
  154. /* Get or put this data. */
  155. if (pg == GET)
  156. return nc4_get_vara(nc, ncid, varid, start, count, xtype,
  157. is_long, ip);
  158. else
  159. return nc4_put_vara(nc, ncid, varid, start, count, xtype,
  160. is_long, ip);
  161. }
  162. /* Get the default fill value for an atomic type. Memory for
  163. * fill_value must already be allocated, or you are DOOMED!!!*/
  164. int
  165. nc4_get_default_fill_value(NC_TYPE_INFO_T *type_info, void *fill_value)
  166. {
  167. switch (type_info->nc_typeid)
  168. {
  169. case NC_BYTE:
  170. *(signed char *)fill_value = NC_FILL_BYTE;
  171. break;
  172. case NC_CHAR:
  173. *(char *)fill_value = NC_FILL_CHAR;
  174. break;
  175. case NC_SHORT:
  176. *(short *)fill_value = NC_FILL_SHORT;
  177. break;
  178. case NC_INT:
  179. *(int *)fill_value = NC_FILL_INT;
  180. break;
  181. case NC_FLOAT:
  182. *(float *)fill_value = NC_FILL_FLOAT;
  183. break;
  184. case NC_DOUBLE:
  185. *(double *)fill_value = NC_FILL_DOUBLE;
  186. break;
  187. case NC_UBYTE:
  188. *(unsigned char *)fill_value = NC_FILL_UBYTE;
  189. break;
  190. case NC_USHORT:
  191. *(unsigned short *)fill_value = NC_FILL_USHORT;
  192. break;
  193. case NC_UINT:
  194. *(unsigned int *)fill_value = NC_FILL_UINT;
  195. break;
  196. case NC_INT64:
  197. *(long long *)fill_value = NC_FILL_INT64;
  198. break;
  199. case NC_UINT64:
  200. *(unsigned long long *)fill_value = NC_FILL_UINT64;
  201. break;
  202. case NC_STRING:
  203. strcpy((char *)fill_value, "");
  204. break;
  205. default:
  206. return NC_EINVAL;
  207. }
  208. return NC_NOERR;
  209. }
  210. /* What fill value should be used for a variable? */
  211. static int
  212. get_fill_value(NC_HDF5_FILE_INFO_T *h5, NC_VAR_INFO_T *var, void **fillp)
  213. {
  214. size_t size;
  215. int retval;
  216. /* Find out how much space we need for this type's fill value. */
  217. if ((retval = nc4_get_typelen_mem(h5, var->xtype, 0, &size)))
  218. return retval;
  219. /* Strings have a size of one for the empty sting (to hold the
  220. * null), otherwise the length of the users fill_value string, plus
  221. * one. */
  222. if (var->xtype == NC_STRING)
  223. {
  224. size = 1;
  225. }
  226. /* Allocate the space. VLENS are different, of course. */
  227. if (var->type_info->class == NC_VLEN)
  228. {
  229. if (!((*fillp) = malloc(sizeof(nc_vlen_t))))
  230. return NC_ENOMEM;
  231. }
  232. else
  233. {
  234. if (!((*fillp) = malloc(size)))
  235. return NC_ENOMEM;
  236. }
  237. /* If the user has set a fill_value for this var, use, otherwise
  238. * find the default fill value. */
  239. if (var->fill_value)
  240. {
  241. LOG((4, "Found a fill value for var %s", var->name));
  242. if (var->type_info->class == NC_VLEN)
  243. {
  244. nc_vlen_t *in_vlen = (nc_vlen_t *)(var->fill_value), *fv_vlen = (nc_vlen_t *)(*fillp);
  245. fv_vlen->len = in_vlen->len;
  246. if (!(fv_vlen->p = malloc(size * in_vlen->len)))
  247. return NC_ENOMEM;
  248. memcpy(fv_vlen->p, in_vlen->p, in_vlen->len * size);
  249. }
  250. else if (var->xtype == NC_STRING)
  251. {
  252. if (!(*(char **)fillp = malloc((strlen((char *)var->fill_value) + 1) *
  253. sizeof(char))))
  254. return NC_ENOMEM;
  255. strcpy(*(char **)fillp, (char *)var->fill_value);
  256. }
  257. else
  258. memcpy((*fillp), var->fill_value, size);
  259. }
  260. else
  261. {
  262. if ((nc4_get_default_fill_value(var->type_info, *fillp)))
  263. {
  264. free(*fillp);
  265. *fillp = NULL;
  266. }
  267. }
  268. return NC_NOERR;
  269. }
  270. /* Given a netcdf type, return appropriate HDF typeid. */
  271. int
  272. nc4_get_hdf_typeid(NC_HDF5_FILE_INFO_T *h5, nc_type xtype,
  273. hid_t *hdf_typeid, int endianness)
  274. {
  275. NC_TYPE_INFO_T *type;
  276. hid_t typeid = 0;
  277. int retval = NC_NOERR;
  278. assert(hdf_typeid && h5);
  279. *hdf_typeid = -1;
  280. switch (xtype)
  281. {
  282. case NC_NAT: /* NAT = 'Not A Type' (c.f. NaN) */
  283. return NC_EBADTYPE;
  284. case NC_BYTE: /* signed 1 byte integer */
  285. if (endianness == NC_ENDIAN_LITTLE)
  286. *hdf_typeid = H5T_STD_I8LE;
  287. else if (endianness == NC_ENDIAN_BIG)
  288. *hdf_typeid = H5T_STD_I8BE;
  289. else
  290. *hdf_typeid = H5T_NATIVE_SCHAR;
  291. break;
  292. case NC_CHAR: /* ISO/ASCII character */
  293. if ((typeid = H5Tcopy(H5T_C_S1)) < 0)
  294. return NC_EHDFERR;
  295. if (H5Tset_strpad(typeid, H5T_STR_NULLTERM) < 0)
  296. BAIL(NC_EVARMETA);
  297. *hdf_typeid = typeid;
  298. break;
  299. case NC_SHORT: /* signed 2 byte integer */
  300. if (endianness == NC_ENDIAN_LITTLE)
  301. *hdf_typeid = H5T_STD_I16LE;
  302. else if (endianness == NC_ENDIAN_BIG)
  303. *hdf_typeid = H5T_STD_I16BE;
  304. else
  305. *hdf_typeid = H5T_NATIVE_SHORT;
  306. break;
  307. case NC_INT:
  308. if (endianness == NC_ENDIAN_LITTLE)
  309. *hdf_typeid = H5T_STD_I32LE;
  310. else if (endianness == NC_ENDIAN_BIG)
  311. *hdf_typeid = H5T_STD_I32BE;
  312. else
  313. *hdf_typeid = H5T_NATIVE_INT;
  314. break;
  315. case NC_FLOAT:
  316. if (endianness == NC_ENDIAN_LITTLE)
  317. *hdf_typeid = H5T_IEEE_F32LE;
  318. else if (endianness == NC_ENDIAN_BIG)
  319. *hdf_typeid = H5T_IEEE_F32BE;
  320. else
  321. *hdf_typeid = H5T_NATIVE_FLOAT;
  322. break;
  323. case NC_DOUBLE:
  324. if (endianness == NC_ENDIAN_LITTLE)
  325. *hdf_typeid = H5T_IEEE_F64LE;
  326. else if (endianness == NC_ENDIAN_BIG)
  327. *hdf_typeid = H5T_IEEE_F64BE;
  328. else
  329. *hdf_typeid = H5T_NATIVE_DOUBLE;
  330. break;
  331. case NC_UBYTE:
  332. if (endianness == NC_ENDIAN_LITTLE)
  333. *hdf_typeid = H5T_STD_U8LE;
  334. else if (endianness == NC_ENDIAN_BIG)
  335. *hdf_typeid = H5T_STD_U8BE;
  336. else
  337. *hdf_typeid = H5T_NATIVE_UCHAR;
  338. break;
  339. case NC_USHORT:
  340. if (endianness == NC_ENDIAN_LITTLE)
  341. *hdf_typeid = H5T_STD_U16LE;
  342. else if (endianness == NC_ENDIAN_BIG)
  343. *hdf_typeid = H5T_STD_U16BE;
  344. else
  345. *hdf_typeid = H5T_NATIVE_USHORT;
  346. break;
  347. case NC_UINT:
  348. if (endianness == NC_ENDIAN_LITTLE)
  349. *hdf_typeid = H5T_STD_U32LE;
  350. else if (endianness == NC_ENDIAN_BIG)
  351. *hdf_typeid = H5T_STD_U32BE;
  352. else
  353. *hdf_typeid = H5T_NATIVE_UINT;
  354. break;
  355. case NC_INT64:
  356. if (endianness == NC_ENDIAN_LITTLE)
  357. *hdf_typeid = H5T_STD_I64LE;
  358. else if (endianness == NC_ENDIAN_BIG)
  359. *hdf_typeid = H5T_STD_I64BE;
  360. else
  361. *hdf_typeid = H5T_NATIVE_LLONG;
  362. break;
  363. case NC_UINT64:
  364. if (endianness == NC_ENDIAN_LITTLE)
  365. *hdf_typeid = H5T_STD_U64LE;
  366. else if (endianness == NC_ENDIAN_BIG)
  367. *hdf_typeid = H5T_STD_U64BE;
  368. else
  369. *hdf_typeid = H5T_NATIVE_ULLONG;
  370. break;
  371. case NC_STRING:
  372. if ((typeid = H5Tcopy(H5T_C_S1)) < 0)
  373. return NC_EHDFERR;
  374. if (H5Tset_size(typeid, H5T_VARIABLE) < 0)
  375. return NC_EHDFERR;
  376. *hdf_typeid = typeid;
  377. break;
  378. default:
  379. /* Maybe this is a user defined type? */
  380. if (!nc4_find_type(h5, xtype, &type))
  381. {
  382. if (!type)
  383. return NC_EBADTYPE;
  384. *hdf_typeid = type->hdf_typeid;
  385. }
  386. }
  387. if (*hdf_typeid == -1)
  388. return NC_EBADTYPE;
  389. return NC_NOERR;
  390. exit:
  391. if (xtype == NC_CHAR && typeid > 0 && H5Tclose(typeid) < 0)
  392. BAIL2(NC_EHDFERR);
  393. return retval;
  394. }
  395. /* Do some common check for nc4_put_vara and nc4_get_vara. These
  396. * checks have to be done when both reading and writing data. */
  397. static int
  398. check_for_vara(nc_type *mem_nc_type, NC_VAR_INFO_T *var, NC_HDF5_FILE_INFO_T *h5)
  399. {
  400. int retval;
  401. /* If mem_nc_type is NC_NAT, it means we want to use the file type
  402. * as the mem type as well. */
  403. assert(mem_nc_type);
  404. if (*mem_nc_type == NC_NAT)
  405. *mem_nc_type = var->xtype;
  406. assert(*mem_nc_type);
  407. /* No NC_CHAR conversions, you pervert! */
  408. if (var->xtype != *mem_nc_type &&
  409. (var->xtype == NC_CHAR || *mem_nc_type == NC_CHAR))
  410. return NC_ECHAR;
  411. /* If we're in define mode, we can't read or write data. */
  412. if (h5->flags & NC_INDEF)
  413. {
  414. if (h5->cmode & NC_CLASSIC_MODEL)
  415. return NC_EINDEFINE;
  416. if ((retval = nc4_enddef_netcdf4_file(h5)))
  417. return retval;
  418. }
  419. return NC_NOERR;
  420. }
  421. #ifdef LOGGING
  422. /* Print some debug info about dimensions to the log. */
  423. static void
  424. log_dim_info(NC_VAR_INFO_T *var, hsize_t *fdims, hsize_t *fmaxdims,
  425. hsize_t *start, hsize_t *count)
  426. {
  427. int d2;
  428. /* Print some debugging info... */
  429. LOG((4, "nc4_put_vara: var name %s ndims %d", var->name, var->ndims));
  430. LOG((4, "File space, and requested:"));
  431. for (d2 = 0; d2 < var->ndims; d2++)
  432. {
  433. LOG((4, "fdims[%d]=%Ld fmaxdims[%d]=%Ld", d2, fdims[d2], d2,
  434. fmaxdims[d2]));
  435. LOG((4, "start[%d]=%Ld count[%d]=%Ld", d2, start[d2], d2, count[d2]));
  436. }
  437. }
  438. #endif /* LOGGING */
  439. #ifdef USE_PARALLEL
  440. static int
  441. set_par_access(NC_HDF5_FILE_INFO_T *h5, NC_VAR_INFO_T *var, hid_t xfer_plistid)
  442. {
  443. H5FD_mpio_xfer_t hdf5_xfer_mode;
  444. /* If netcdf is built with parallel I/O, then parallel access can
  445. * be used, and, if this file was opened or created for parallel
  446. * access, we need to set the transfer mode. */
  447. if (h5->parallel)
  448. {
  449. /* Decide on collective or independent. */
  450. hdf5_xfer_mode = (var->parallel_access != NC_INDEPENDENT) ?
  451. H5FD_MPIO_COLLECTIVE : H5FD_MPIO_INDEPENDENT;
  452. /* Set the mode in the transfer property list. */
  453. if (H5Pset_dxpl_mpio(xfer_plistid, hdf5_xfer_mode) < 0)
  454. return NC_EPARINIT;
  455. LOG((4, "hdf5_xfer_mode: %d H5FD_MPIO_COLLECTIVE: %d H5FD_MPIO_INDEPENDENT: %d",
  456. (int)hdf5_xfer_mode, H5FD_MPIO_COLLECTIVE, H5FD_MPIO_INDEPENDENT));
  457. }
  458. return NC_NOERR;
  459. }
  460. #endif
  461. /* Write an array of data to a variable. When it comes right down to
  462. * it, this is what netCDF-4 is all about, this is *the* function, the
  463. * big enchilda, the grand poo-bah, the alpha dog, the head honcho,
  464. * the big cheese, the mighty kahuna, the top bananna, the high
  465. * muckity-muck, numero uno. Well, you get the idea. */
  466. int
  467. nc4_put_vara(NC_FILE_INFO_T *nc, int ncid, int varid, const size_t *startp,
  468. const size_t *countp, nc_type mem_nc_type, int is_long, void *data)
  469. {
  470. NC_GRP_INFO_T *grp;
  471. NC_HDF5_FILE_INFO_T *h5;
  472. NC_VAR_INFO_T *var;
  473. NC_DIM_INFO_T *dim;
  474. hid_t file_spaceid = 0, mem_spaceid = 0, xfer_plistid = 0;
  475. size_t file_type_size;
  476. hsize_t *xtend_size = NULL, count[NC_MAX_VAR_DIMS];
  477. hsize_t fdims[NC_MAX_VAR_DIMS], fmaxdims[NC_MAX_VAR_DIMS];
  478. hsize_t start[NC_MAX_VAR_DIMS];
  479. int need_to_extend = 0;
  480. int scalar = 0, retval = NC_NOERR, range_error = 0, i, d2;
  481. void *bufr = NULL;
  482. #ifndef HDF5_CONVERT
  483. int need_to_convert = 0;
  484. size_t len = 1;
  485. #endif
  486. #ifdef HDF5_CONVERT
  487. hid_t mem_typeid = 0;
  488. #endif
  489. int no_data=0 ;
  490. /* Find our metadata for this file, group, and var. */
  491. assert(nc);
  492. if ((retval = nc4_find_g_var_nc(nc, ncid, varid, &grp, &var)))
  493. return retval;
  494. h5 = nc->nc4_info;
  495. assert(grp && h5 && var && var->name);
  496. LOG((3, "nc4_put_vara: var->name %s mem_nc_type %d is_long %d",
  497. var->name, mem_nc_type, is_long));
  498. /* Check some stuff about the type and the file. If the file must
  499. * be switched from define mode, it happens here. */
  500. if ((retval = check_for_vara(&mem_nc_type, var, h5)))
  501. return retval;
  502. /* Convert from size_t and ptrdiff_t to hssize_t, and hsize_t. */
  503. for (i = 0; i < var->ndims; i++)
  504. {
  505. start[i] = startp[i];
  506. count[i] = countp[i];
  507. }
  508. /* Open this dataset if necessary, also checking for a weird case:
  509. * a non-coordinate (and non-scalar) variable that has the same
  510. * name as a dimension. */
  511. if (var->hdf5_name && strlen(var->hdf5_name) >= strlen(NON_COORD_PREPEND) &&
  512. strncmp(var->hdf5_name, NON_COORD_PREPEND, strlen(NON_COORD_PREPEND)) == 0 &&
  513. var->ndims)
  514. if ((var->hdf_datasetid = H5Dopen2(grp->hdf_grpid, var->hdf5_name,
  515. H5P_DEFAULT)) < 0)
  516. return NC_ENOTVAR;
  517. if (!var->hdf_datasetid)
  518. if ((var->hdf_datasetid = H5Dopen2(grp->hdf_grpid, var->name,
  519. H5P_DEFAULT)) < 0)
  520. return NC_ENOTVAR;
  521. /* Get file space of data. */
  522. if ((file_spaceid = H5Dget_space(var->hdf_datasetid)) < 0)
  523. BAIL(NC_EHDFERR);
  524. #ifdef EXTRA_TESTS
  525. num_spaces++;
  526. #endif
  527. /* Check to ensure the user selection is
  528. * valid. H5Sget_simple_extent_dims gets the sizes of all the dims
  529. * and put them in fdims. */
  530. if (H5Sget_simple_extent_dims(file_spaceid, fdims, fmaxdims) < 0)
  531. BAIL(NC_EHDFERR);
  532. #ifdef LOGGING
  533. log_dim_info(var, fdims, fmaxdims, start, count);
  534. #endif
  535. /* Check dimension bounds. Remember that unlimited dimnsions can
  536. * put data beyond their current length. */
  537. for (d2 = 0; d2 < var->ndims; d2++)
  538. {
  539. for (dim = grp->dim; dim; dim = dim->next)
  540. {
  541. if (dim->dimid == var->dimids[d2])
  542. {
  543. if (!dim->unlimited)
  544. {
  545. if (start[d2] >= (hssize_t)fdims[d2])
  546. BAIL_QUIET(NC_EINVALCOORDS);
  547. if (start[d2] + count[d2] > fdims[d2])
  548. BAIL_QUIET(NC_EEDGE);
  549. }
  550. }
  551. }
  552. }
  553. /* A little quirk: if any of the count values are zero, then
  554. return success and forget about it. */
  555. for (d2 = 0; d2 < var->ndims; d2++)
  556. if (count[d2] != 0) no_data++ ;
  557. /* goto exit; */
  558. /* Now you would think that no one would be crazy enough to write
  559. a scalar dataspace with one of the array function calls, but you
  560. would be wrong. So let's check to see if the dataset is
  561. scalar. If it is, we won't try to set up a hyperslab. */
  562. if (H5Sget_simple_extent_type(file_spaceid) == H5S_SCALAR)
  563. {
  564. if ((mem_spaceid = H5Screate(H5S_SCALAR)) < 0)
  565. BAIL(NC_EHDFERR);
  566. #ifdef EXTRA_TESTS
  567. num_spaces++;
  568. #endif
  569. scalar++;
  570. }
  571. else
  572. {
  573. if (H5Sselect_hyperslab(file_spaceid, H5S_SELECT_SET, start, NULL,
  574. count, NULL) < 0)
  575. BAIL(NC_EHDFERR);
  576. /* Create a space for the memory, just big enough to hold the slab
  577. we want. */
  578. if ((mem_spaceid = H5Screate_simple(var->ndims, count, NULL)) < 0)
  579. BAIL(NC_EHDFERR);
  580. #ifdef EXTRA_TESTS
  581. num_spaces++;
  582. #endif
  583. }
  584. /* Later on, we will need to know the size of this type in the
  585. * file. */
  586. if ((retval = nc4_get_typelen_mem(h5, var->xtype, 0, &file_type_size)))
  587. return retval;
  588. #ifndef HDF5_CONVERT
  589. /* Are we going to convert any data? (No converting of compound or
  590. * opaque types.) */
  591. if ((mem_nc_type != var->xtype || (var->xtype == NC_INT && is_long)) &&
  592. mem_nc_type != NC_COMPOUND && mem_nc_type != NC_OPAQUE)
  593. {
  594. /* We must convert - allocate a buffer. */
  595. need_to_convert++;
  596. if (var->ndims)
  597. for (d2=0; d2<var->ndims; d2++)
  598. len *= countp[d2];
  599. LOG((4, "converting data for var %s type=%d len=%d", var->name,
  600. var->xtype, len));
  601. /* If we're reading, we need bufr to have enough memory to store
  602. * the data in the file. If we're writing, we need bufr to be
  603. * big enough to hold all the data in the file's type. */
  604. if (!(bufr = malloc(len * file_type_size)))
  605. BAIL(NC_ENOMEM);
  606. }
  607. else
  608. #endif /* ifndef HDF5_CONVERT */
  609. bufr = data;
  610. #ifdef HDF5_CONVERT
  611. /* Get the HDF type of the data in memory. */
  612. if ((retval = nc4_get_hdf_typeid(h5, mem_nc_type, &mem_typeid,
  613. var->type_info->endianness)))
  614. BAIL(retval);
  615. #endif
  616. /* Create the data transfer property list. */
  617. if ((xfer_plistid = H5Pcreate(H5P_DATASET_XFER)) < 0)
  618. BAIL(NC_EHDFERR);
  619. #ifdef EXTRA_TESTS
  620. num_plists++;
  621. #endif
  622. /* Apply the callback function which will detect range
  623. * errors. Which one to call depends on the length of the
  624. * destination buffer type. */
  625. #ifdef HDF5_CONVERT
  626. if (H5Pset_type_conv_cb(xfer_plistid, except_func, &range_error) < 0)
  627. BAIL(NC_EHDFERR);
  628. #endif
  629. #ifdef USE_PARALLEL
  630. /* Set up parallel I/O, if needed. */
  631. if ((retval = set_par_access(h5, var, xfer_plistid)))
  632. BAIL(retval);
  633. #endif
  634. /* Read/write this hyperslab into memory. */
  635. /* Does the dataset have to be extended? If it's already
  636. extended to the required size, it will do no harm to reextend
  637. it to that size. */
  638. if (var->ndims)
  639. {
  640. if (!(xtend_size = malloc(var->ndims * sizeof(hsize_t))))
  641. BAIL(NC_ENOMEM);
  642. for (d2 = 0; d2 < var->ndims; d2++)
  643. {
  644. if ((retval = nc4_find_dim(grp, var->dimids[d2], &dim, NULL)))
  645. BAIL(retval);
  646. if (dim->unlimited)
  647. {
  648. if (start[d2] + count[d2] > fdims[d2])
  649. {
  650. xtend_size[d2] = start[d2] + count[d2];
  651. need_to_extend++;
  652. }
  653. else
  654. xtend_size[d2] = fdims[d2];
  655. if (start[d2] + count[d2] > dim->len)
  656. {
  657. dim->len = start[d2] + count[d2];
  658. dim->extended++;
  659. }
  660. }
  661. else
  662. {
  663. xtend_size[d2] = dim->len;
  664. }
  665. }
  666. /* If we need to extend it, we also need a new file_spaceid
  667. to reflect the new size of the space. */
  668. if (need_to_extend)
  669. {
  670. LOG((4, "extending dataset"));
  671. if (H5Dextend(var->hdf_datasetid, xtend_size) < 0)
  672. BAIL(NC_EHDFERR);
  673. if (file_spaceid > 0 && H5Sclose(file_spaceid) < 0)
  674. BAIL2(NC_EHDFERR);
  675. if ((file_spaceid = H5Dget_space(var->hdf_datasetid)) < 0)
  676. BAIL(NC_EHDFERR);
  677. #ifdef EXTRA_TESTS
  678. num_spaces++;
  679. #endif
  680. if (H5Sselect_hyperslab(file_spaceid, H5S_SELECT_SET,
  681. start, NULL, count, NULL) < 0)
  682. BAIL(NC_EHDFERR);
  683. }
  684. }
  685. #ifndef HDF5_CONVERT
  686. /* Do we need to convert the data? */
  687. if (need_to_convert)
  688. {
  689. if ((retval = nc4_convert_type(data, bufr, mem_nc_type, var->xtype,
  690. len, &range_error, var->fill_value,
  691. (h5->cmode & NC_CLASSIC_MODEL), is_long, 0)))
  692. BAIL(retval);
  693. }
  694. #endif
  695. /* Write the data. At last! */
  696. LOG((4, "about to H5Dwrite datasetid 0x%x mem_spaceid 0x%x "
  697. "file_spaceid 0x%x", var->hdf_datasetid, mem_spaceid, file_spaceid));
  698. /*
  699. if (no_data==0)
  700. {
  701. H5Sselect_none(mem_spaceid);
  702. H5Sselect_none(file_spaceid);
  703. bufr=NULL ;
  704. }
  705. */
  706. /* if (no_data!=0) */
  707. if (H5Dwrite(var->hdf_datasetid, var->type_info->hdf_typeid,
  708. mem_spaceid, file_spaceid, xfer_plistid, bufr) < 0)
  709. BAIL(NC_EHDFERR);
  710. /* Remember that we have written to this var so that Fill Value
  711. * can't be set for it. */
  712. if (!var->written_to)
  713. var->written_to++;
  714. /* For strict netcdf-3 rules, ignore erange errors between UBYTE
  715. * and BYTE types. */
  716. if ((h5->cmode & NC_CLASSIC_MODEL) &&
  717. (var->xtype == NC_UBYTE || var->xtype == NC_BYTE) &&
  718. (mem_nc_type == NC_UBYTE || mem_nc_type == NC_BYTE) &&
  719. range_error)
  720. range_error = 0;
  721. exit:
  722. if (file_spaceid > 0 && H5Sclose(file_spaceid) < 0)
  723. BAIL2(NC_EHDFERR);
  724. #ifdef EXTRA_TESTS
  725. num_spaces--;
  726. #endif
  727. if (mem_spaceid > 0 && H5Sclose(mem_spaceid) < 0)
  728. BAIL2(NC_EHDFERR);
  729. #ifdef EXTRA_TESTS
  730. num_spaces--;
  731. #endif
  732. if (xfer_plistid && (H5Pclose(xfer_plistid) < 0))
  733. BAIL2(NC_EPARINIT);
  734. #ifdef EXTRA_TESTS
  735. num_plists--;
  736. #endif
  737. #ifndef HDF5_CONVERT
  738. if (need_to_convert) free(bufr);
  739. #endif
  740. if (xtend_size) free(xtend_size);
  741. /* If there was an error return it, otherwise return any potential
  742. range error value. If none, return NC_NOERR as usual.*/
  743. if (retval)
  744. return retval;
  745. if (range_error)
  746. return NC_ERANGE;
  747. return NC_NOERR;
  748. }
  749. int
  750. nc4_get_vara(NC_FILE_INFO_T *nc, int ncid, int varid, const size_t *startp,
  751. const size_t *countp, nc_type mem_nc_type, int is_long, void *data)
  752. {
  753. NC_GRP_INFO_T *grp, *g;
  754. NC_HDF5_FILE_INFO_T *h5;
  755. NC_VAR_INFO_T *var;
  756. NC_DIM_INFO_T *dim;
  757. hid_t file_spaceid = 0, mem_spaceid = 0;
  758. hid_t xfer_plistid = 0;
  759. hid_t hdf_datasetid;
  760. size_t file_type_size;
  761. hsize_t *xtend_size = NULL, count[NC_MAX_VAR_DIMS];
  762. hsize_t fdims[NC_MAX_VAR_DIMS], fmaxdims[NC_MAX_VAR_DIMS];
  763. hsize_t start[NC_MAX_VAR_DIMS];
  764. void *fillvalue = NULL;
  765. int no_read = 0, provide_fill = 0;
  766. int fill_value_size[NC_MAX_VAR_DIMS];
  767. int scalar = 0, retval = NC_NOERR, range_error = 0, i, d2;
  768. void *bufr = NULL;
  769. int break_it;
  770. #ifndef HDF5_CONVERT
  771. int need_to_convert = 0;
  772. size_t len = 1;
  773. #endif
  774. /* Find our metadata for this file, group, and var. */
  775. assert(nc);
  776. if ((retval = nc4_find_g_var_nc(nc, ncid, varid, &grp, &var)))
  777. return retval;
  778. h5 = nc->nc4_info;
  779. assert(grp && h5 && var && var->name);
  780. LOG((3, "nc4_get_vara: var->name %s mem_nc_type %d is_long %d",
  781. var->name, mem_nc_type, is_long));
  782. /* Check some stuff about the type and the file. */
  783. if ((retval = check_for_vara(&mem_nc_type, var, h5)))
  784. return retval;
  785. /* Convert from size_t and ptrdiff_t to hssize_t, and hsize_t. */
  786. for (i = 0; i < var->ndims; i++)
  787. {
  788. start[i] = startp[i];
  789. count[i] = countp[i];
  790. }
  791. /* Open this dataset if necessary, also checking for a weird case:
  792. * a non-coordinate (and non-scalar) variable that has the same
  793. * name as a dimension. */
  794. if (var->hdf5_name && strlen(var->hdf5_name) >= strlen(NON_COORD_PREPEND) &&
  795. strncmp(var->hdf5_name, NON_COORD_PREPEND, strlen(NON_COORD_PREPEND)) == 0 &&
  796. var->ndims)
  797. if ((var->hdf_datasetid = H5Dopen2(grp->hdf_grpid, var->hdf5_name,
  798. H5P_DEFAULT)) < 0)
  799. return NC_ENOTVAR;
  800. if (!var->hdf_datasetid)
  801. if ((var->hdf_datasetid = H5Dopen2(grp->hdf_grpid, var->name,
  802. H5P_DEFAULT)) < 0)
  803. return NC_ENOTVAR;
  804. /* Get file space of data. */
  805. if ((file_spaceid = H5Dget_space(var->hdf_datasetid)) < 0)
  806. BAIL(NC_EHDFERR);
  807. #ifdef EXTRA_TESTS
  808. num_spaces++;
  809. #endif
  810. /* Check to ensure the user selection is
  811. * valid. H5Sget_simple_extent_dims gets the sizes of all the dims
  812. * and put them in fdims. */
  813. if (H5Sget_simple_extent_dims(file_spaceid, fdims, fmaxdims) < 0)
  814. BAIL(NC_EHDFERR);
  815. #ifdef LOGGING
  816. log_dim_info(var, fdims, fmaxdims, start, count);
  817. #endif
  818. /* Check dimension bounds. Remember that unlimited dimnsions can
  819. * put data beyond their current length. */
  820. for (d2 = 0, break_it = 0; d2 < var->ndims; d2++)
  821. {
  822. for (g = grp; g && !break_it; g = g->parent)
  823. for (dim = g->dim; dim; dim = dim->next)
  824. {
  825. if (dim->dimid == var->dimids[d2])
  826. {
  827. if (!dim->unlimited)
  828. {
  829. if (start[d2] >= (hssize_t)fdims[d2])
  830. BAIL_QUIET(NC_EINVALCOORDS);
  831. if (start[d2] + count[d2] > fdims[d2])
  832. BAIL_QUIET(NC_EEDGE);
  833. }
  834. if (dim->unlimited)
  835. {
  836. size_t ulen;
  837. /* We can't go beyond the latgest current extent of
  838. the unlimited dim. */
  839. if ((retval = nc_inq_dimlen(ncid, dim->dimid, &ulen)))
  840. BAIL(retval);
  841. /* Check for out of bound requests. */
  842. if (start[d2] >= (hssize_t)ulen && count[d2])
  843. BAIL_QUIET(NC_EINVALCOORDS);
  844. if (start[d2] + count[d2] > ulen)
  845. BAIL_QUIET(NC_EEDGE);
  846. /* THings get a little tricky here. If we're getting
  847. a GET request beyond the end of this var's
  848. current length in an unlimited dimension, we'll
  849. later need to return the fill value for the
  850. variable. */
  851. if (start[d2] >= (hssize_t)fdims[d2])
  852. fill_value_size[d2] = count[d2];
  853. else if (start[d2] + count[d2] > fdims[d2])
  854. fill_value_size[d2] = count[d2] - (fdims[d2] - start[d2]);
  855. else
  856. fill_value_size[d2] = 0;
  857. count[d2] -= fill_value_size[d2];
  858. if (fill_value_size[d2])
  859. provide_fill++;
  860. }
  861. else
  862. fill_value_size[d2] = count[d2];
  863. }
  864. }
  865. }
  866. /* A little quirk: if any of the count values are zero, don't
  867. * read. */
  868. for (d2 = 0; d2 < var->ndims; d2++)
  869. if (count[d2] == 0)
  870. no_read++;
  871. /* Later on, we will need to know the size of this type in the
  872. * file. */
  873. if ((retval = nc4_get_typelen_mem(h5, var->xtype, 0, &file_type_size)))
  874. return retval;
  875. if (!no_read)
  876. {
  877. /* Now you would think that no one would be crazy enough to write
  878. a scalar dataspace with one of the array function calls, but you
  879. would be wrong. So let's check to see if the dataset is
  880. scalar. If it is, we won't try to set up a hyperslab. */
  881. if (H5Sget_simple_extent_type(file_spaceid) == H5S_SCALAR)
  882. {
  883. if ((mem_spaceid = H5Screate(H5S_SCALAR)) < 0)
  884. BAIL(NC_EHDFERR);
  885. scalar++;
  886. #ifdef EXTRA_TESTS
  887. num_spaces++;
  888. #endif
  889. }
  890. else
  891. {
  892. if (H5Sselect_hyperslab(file_spaceid, H5S_SELECT_SET,
  893. start, NULL, count, NULL) < 0)
  894. BAIL(NC_EHDFERR);
  895. /* Create a space for the memory, just big enough to hold the slab
  896. we want. */
  897. if ((mem_spaceid = H5Screate_simple(var->ndims, count, NULL)) < 0)
  898. BAIL(NC_EHDFERR);
  899. #ifdef EXTRA_TESTS
  900. num_spaces++;
  901. #endif
  902. }
  903. /* Fix bug when reading HDF5 files with variable of type
  904. * fixed-length string. We need to make it look like a
  905. * variable-length string, because that's all netCDF-4 data
  906. * model supports, lacking anonymous dimensions. So
  907. * variable-length strings are in allocated memory that user has
  908. * to free, which we allocate here. */
  909. if(var->type_info->class == H5T_STRING &&
  910. H5Tget_size(var->type_info->hdf_typeid) > 1 &&
  911. !H5Tis_variable_str(var->type_info->hdf_typeid)) {
  912. hsize_t fstring_len;
  913. if ((fstring_len = H5Tget_size(var->type_info->hdf_typeid)) < 0)
  914. BAIL(NC_EHDFERR);
  915. if (!(*(char **)data = malloc(1 + fstring_len)))
  916. BAIL(NC_ENOMEM);
  917. bufr = *(char **)data;
  918. }
  919. #ifndef HDF5_CONVERT
  920. /* Are we going to convert any data? (No converting of compound or
  921. * opaque types.) */
  922. if ((mem_nc_type != var->xtype || (var->xtype == NC_INT && is_long)) &&
  923. mem_nc_type != NC_COMPOUND && mem_nc_type != NC_OPAQUE)
  924. {
  925. /* We must convert - allocate a buffer. */
  926. need_to_convert++;
  927. if (var->ndims)
  928. for (d2 = 0; d2 < var->ndims; d2++)
  929. len *= countp[d2];
  930. LOG((4, "converting data for var %s type=%d len=%d", var->name,
  931. var->xtype, len));
  932. /* If we're reading, we need bufr to have enough memory to store
  933. * the data in the file. If we're writing, we need bufr to be
  934. * big enough to hold all the data in the file's type. */
  935. if (!(bufr = malloc(len * file_type_size)))
  936. BAIL(NC_ENOMEM);
  937. }
  938. else
  939. #endif /* ifndef HDF5_CONVERT */
  940. if(!bufr)
  941. bufr = data;
  942. /* Get the HDF type of the data in memory. */
  943. #ifdef HDF5_CONVERT
  944. if ((retval = nc4_get_hdf_typeid(h5, mem_nc_type, &mem_typeid,
  945. var->type_info->endianness)))
  946. BAIL(retval);
  947. #endif
  948. /* Create the data transfer property list. */
  949. if ((xfer_plistid = H5Pcreate(H5P_DATASET_XFER)) < 0)
  950. BAIL(NC_EHDFERR);
  951. #ifdef EXTRA_TESTS
  952. num_plists++;
  953. #endif
  954. #ifdef HDF5_CONVERT
  955. /* Apply the callback function which will detect range
  956. * errors. Which one to call depends on the length of the
  957. * destination buffer type. */
  958. if (H5Pset_type_conv_cb(xfer_plistid, except_func, &range_error) < 0)
  959. BAIL(NC_EHDFERR);
  960. #endif
  961. #ifdef USE_PARALLEL
  962. /* Set up parallel I/O, if needed. */
  963. if ((retval = set_par_access(h5, var, xfer_plistid)))
  964. BAIL(retval);
  965. #endif
  966. /* Read this hyperslab into memory. */
  967. LOG((5, "About to H5Dread some data..."));
  968. if (H5Dread(var->hdf_datasetid, var->type_info->native_typeid,
  969. mem_spaceid, file_spaceid, xfer_plistid, bufr) < 0)
  970. BAIL(NC_EHDFERR);
  971. #ifndef HDF5_CONVERT
  972. /* Eventually the block below will go away. Right now it's
  973. needed to support conversions between int/float, and range
  974. checking converted data in the netcdf way. These features are
  975. being added to HDF5 at the HDF5 World Hall of Coding right
  976. now, by a staff of thousands of programming gnomes. */
  977. if (need_to_convert)
  978. {
  979. if ((retval = nc4_convert_type(bufr, data, var->xtype, mem_nc_type,
  980. len, &range_error, var->fill_value,
  981. (h5->cmode & NC_CLASSIC_MODEL), 0, is_long)))
  982. BAIL(retval);
  983. /* For strict netcdf-3 rules, ignore erange errors between UBYTE
  984. * and BYTE types. */
  985. if ((h5->cmode & NC_CLASSIC_MODEL) &&
  986. (var->xtype == NC_UBYTE || var->xtype == NC_BYTE) &&
  987. (mem_nc_type == NC_UBYTE || mem_nc_type == NC_BYTE) &&
  988. range_error)
  989. range_error = 0;
  990. }
  991. #endif
  992. /* For strict netcdf-3 rules, ignore erange errors between UBYTE
  993. * and BYTE types. */
  994. if ((h5->cmode & NC_CLASSIC_MODEL) &&
  995. (var->xtype == NC_UBYTE || var->xtype == NC_BYTE) &&
  996. (mem_nc_type == NC_UBYTE || mem_nc_type == NC_BYTE) &&
  997. range_error)
  998. range_error = 0;
  999. } /* endif ! no_read */
  1000. /* Now we need to fake up any further data that was asked for,
  1001. using the fill values instead. First skip past the data we
  1002. just read, if any. */
  1003. if (!scalar && provide_fill)
  1004. {
  1005. void *filldata;
  1006. size_t real_data_size = 0;
  1007. size_t fill_len;
  1008. /* Skip past the real data we've already read. */
  1009. if (!no_read)
  1010. for (real_data_size = file_type_size, d2 = 0; d2 < var->ndims; d2++)
  1011. real_data_size *= (count[d2] - start[d2]);
  1012. /* Get the fill value from the HDF5 variable. Memory will be
  1013. * allocated. */
  1014. if (get_fill_value(h5, var, &fillvalue) < 0)
  1015. BAIL(NC_EHDFERR);
  1016. /* How many fill values do we need? */
  1017. for (fill_len = 1, d2 = 0; d2 < var->ndims; d2++)
  1018. fill_len *= (fill_value_size[d2] ? fill_value_size[d2] : 1);
  1019. /* Copy the fill value into the rest of the data buffer. */
  1020. filldata = (char *)data + real_data_size;
  1021. for (i = 0; i < fill_len; i++)
  1022. {
  1023. if (var->xtype == NC_STRING)
  1024. {
  1025. if (!(*(char **)filldata = malloc(sizeof(*(char **)fillvalue))))
  1026. return NC_ENOMEM;
  1027. strcpy(*(char **)filldata, *(char **)fillvalue);
  1028. }
  1029. else
  1030. {
  1031. memcpy(filldata, fillvalue, file_type_size);
  1032. filldata = (char *)filldata + file_type_size;
  1033. }
  1034. }
  1035. }
  1036. exit:
  1037. /** if (var->xtype == NC_CHAR && mem_typeid > 0 && H5Tclose(mem_typeid) < 0)
  1038. BAIL2(NC_EHDFERR);*/
  1039. if (file_spaceid > 0)
  1040. {
  1041. if (H5Sclose(file_spaceid) < 0)
  1042. BAIL2(NC_EHDFERR);
  1043. #ifdef EXTRA_TESTS
  1044. num_spaces--;
  1045. #endif
  1046. }
  1047. if (mem_spaceid > 0)
  1048. {
  1049. if (H5Sclose(mem_spaceid) < 0)
  1050. BAIL2(NC_EHDFERR);
  1051. #ifdef EXTRA_TESTS
  1052. num_spaces--;
  1053. #endif
  1054. }
  1055. if (xfer_plistid > 0)
  1056. {
  1057. if (H5Pclose(xfer_plistid) < 0)
  1058. BAIL2(NC_EHDFERR);
  1059. #ifdef EXTRA_TESTS
  1060. num_plists--;
  1061. #endif
  1062. }
  1063. #ifndef HDF5_CONVERT
  1064. if (need_to_convert)
  1065. free(bufr);
  1066. #endif
  1067. if (xtend_size)
  1068. free(xtend_size);
  1069. if (fillvalue)
  1070. {
  1071. if (var->xtype == NC_STRING)
  1072. {
  1073. if (nc_free_string(1, (char **)fillvalue))
  1074. return NC_ENOMEM;
  1075. }
  1076. else
  1077. free(fillvalue);
  1078. }
  1079. /* If there was an error return it, otherwise return any potential
  1080. range error value. If none, return NC_NOERR as usual.*/
  1081. if (retval)
  1082. return retval;
  1083. if (range_error)
  1084. return NC_ERANGE;
  1085. return NC_NOERR;
  1086. }
  1087. /* This function is a bit of a hack. Turns out that HDF5 dimension
  1088. * scales cannot themselves have scales attached. This leaves
  1089. * multidimensional coordinate variables hosed. So this function
  1090. * writes a special attribute for such a variable, which has the ids
  1091. * of all the dimensions for that coordinate variable. This sucks,
  1092. * really. But that's the way the cookie crumbles. Better luck next
  1093. * time. This function also contains a new way of dealing with HDF5
  1094. * error handling, abandoning the BAIL macros for a more organic and
  1095. * natural approach, made with whole grains, and locally-grown
  1096. * vegetables. */
  1097. static int
  1098. write_coord_dimids(NC_VAR_INFO_T *var)
  1099. {
  1100. hsize_t coords_len[1];
  1101. hid_t c_spaceid = -1, c_attid = -1;
  1102. int ret = 0;
  1103. /* Write our attribute. */
  1104. coords_len[0] = var->ndims;
  1105. if ((c_spaceid = H5Screate_simple(1, coords_len, coords_len)) < 0) ret++;
  1106. #ifdef EXTRA_TESTS
  1107. num_spaces++;
  1108. #endif
  1109. if (!ret && (c_attid = H5Acreate(var->hdf_datasetid, COORDINATES, H5T_NATIVE_INT,
  1110. c_spaceid, H5P_DEFAULT)) < 0) ret++;
  1111. if (!ret && H5Awrite(c_attid, H5T_NATIVE_INT, var->dimids) < 0) ret++;
  1112. /* Close up shop. */
  1113. if (c_spaceid > 0 && H5Sclose(c_spaceid) < 0) ret++;
  1114. #ifdef EXTRA_TESTS
  1115. num_spaces--;
  1116. #endif
  1117. if (c_attid > 0 && H5Aclose(c_attid) < 0) ret++;
  1118. return ret ? NC_EHDFERR : 0;
  1119. }
  1120. /* Write a special attribute for the netCDF-4 dimension ID. */
  1121. static int
  1122. write_netcdf4_dimid(hid_t datasetid, int dimid)
  1123. {
  1124. hid_t dimid_spaceid, dimid_attid;
  1125. /* Create the space. */
  1126. if ((dimid_spaceid = H5Screate(H5S_SCALAR)) < 0)
  1127. return NC_EHDFERR;
  1128. #ifdef EXTRA_TESTS
  1129. num_spaces++;
  1130. #endif
  1131. /* Does the attribute already exist? If so, don't try to create it. */
  1132. H5E_BEGIN_TRY {
  1133. dimid_attid = H5Aopen_by_name(datasetid, ".", NC_DIMID_ATT_NAME,
  1134. H5P_DEFAULT, H5P_DEFAULT);
  1135. } H5E_END_TRY;
  1136. /* Create the attribute if needed. */
  1137. if (dimid_attid < 0)
  1138. if ((dimid_attid = H5Acreate(datasetid, NC_DIMID_ATT_NAME,
  1139. H5T_NATIVE_INT, dimid_spaceid, H5P_DEFAULT)) < 0)
  1140. return NC_EHDFERR;
  1141. /* Write it. */
  1142. LOG((4, "write_netcdf4_dimid: writting secret dimid %d", dimid));
  1143. if (H5Awrite(dimid_attid, H5T_NATIVE_INT, &dimid) < 0)
  1144. return NC_EHDFERR;
  1145. /* Close stuff*/
  1146. if (H5Sclose(dimid_spaceid) < 0)
  1147. return NC_EHDFERR;
  1148. #ifdef EXTRA_TESTS
  1149. num_spaces--;
  1150. #endif
  1151. if (H5Aclose(dimid_attid) < 0)
  1152. return NC_EHDFERR;
  1153. return NC_NOERR;
  1154. }
  1155. /* This function creates the HDF5 dataset for a variabale. */
  1156. static int
  1157. var_create_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, int write_dimid)
  1158. {
  1159. NC_GRP_INFO_T *g;
  1160. hid_t plistid = 0, access_plistid = 0, typeid = 0, spaceid = 0;
  1161. hsize_t *chunksize = NULL, *dimsize = NULL, *maxdimsize = NULL;
  1162. int d;
  1163. NC_DIM_INFO_T *dim = NULL;
  1164. void *fillp = NULL;
  1165. int dims_found = 0;
  1166. int set_chunksizes = 0;
  1167. char *name_to_use;
  1168. int retval = NC_NOERR;
  1169. LOG((3, "var_create_dataset: name %s", var->name));
  1170. /* Scalar or not, we need a creation property list. */
  1171. if ((plistid = H5Pcreate(H5P_DATASET_CREATE)) < 0)
  1172. BAIL(NC_EHDFERR);
  1173. #ifdef EXTRA_TESTS
  1174. num_plists++;
  1175. #endif
  1176. if ((access_plistid = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
  1177. BAIL(NC_EHDFERR);
  1178. #ifdef EXTRA_TESTS
  1179. num_plists++;
  1180. #endif
  1181. /* Find the HDF5 type of the dataset. */
  1182. if ((retval = nc4_get_hdf_typeid(grp->file->nc4_info, var->xtype, &typeid,
  1183. var->type_info->endianness)))
  1184. BAIL(retval);
  1185. /* Figure out what fill value to set, if any. */
  1186. if (!var->no_fill)
  1187. {
  1188. if ((retval = get_fill_value(grp->file->nc4_info, var, &fillp)))
  1189. BAIL(retval);
  1190. /* If there is a fill value, set it. */
  1191. if (fillp)
  1192. {
  1193. if (var->xtype == NC_STRING)
  1194. {
  1195. if (H5Pset_fill_value(plistid, typeid, &fillp) < 0)
  1196. BAIL(NC_EHDFERR);
  1197. free((char *)fillp);
  1198. }
  1199. else
  1200. {
  1201. /* The fill value set in HDF5 must always be presented as
  1202. * a native type, even if the endianness for this dataset
  1203. * is non-native. HDF5 will translate the fill value to
  1204. * the target endiannesss. */
  1205. hid_t fill_typeid;
  1206. if ((retval = nc4_get_hdf_typeid(grp->file->nc4_info, var->xtype, &fill_typeid,
  1207. NC_ENDIAN_NATIVE)))
  1208. BAIL(retval);
  1209. if (H5Pset_fill_value(plistid, fill_typeid, fillp) < 0)
  1210. BAIL(NC_EHDFERR);
  1211. if (var->type_info->class == NC_VLEN)
  1212. nc_free_vlen((nc_vlen_t *)fillp);
  1213. else
  1214. free(fillp);
  1215. if (var->type_info->nc_typeid == NC_STRING || var->type_info->nc_typeid == NC_CHAR)
  1216. if (H5Tclose(fill_typeid) < 0)
  1217. BAIL(NC_EHDFERR);
  1218. }
  1219. }
  1220. } else {
  1221. /* Required to truly turn HDF5 fill values off */
  1222. if(H5Pset_fill_time(plistid,H5D_FILL_TIME_NEVER) < 0)
  1223. BAIL(NC_EHDFERR);
  1224. }
  1225. /* If the user wants to shuffle the data, set that up now. */
  1226. if (var->shuffle)
  1227. if (H5Pset_shuffle(plistid) < 0)
  1228. BAIL(NC_EHDFERR);
  1229. /* If the user wants to deflate the data, set that up now. */
  1230. if (var->deflate)
  1231. if (H5Pset_deflate(plistid, var->deflate_level) < 0)
  1232. BAIL(NC_EHDFERR);
  1233. /* Szip? NO! We don't want anyone to produce szipped netCDF files! */
  1234. /* #ifdef USE_SZIP */
  1235. /* if (var->options_mask) */
  1236. /* if (H5Pset_szip(plistid, var->options_mask, var->bits_per_pixel) < 0) */
  1237. /* BAIL(NC_EHDFERR); */
  1238. /* #endif */
  1239. /* If the user wants to fletcher error correcton, set that up now. */
  1240. if (var->fletcher32)
  1241. if (H5Pset_fletcher32(plistid) < 0)
  1242. BAIL(NC_EHDFERR);
  1243. /* If ndims non-zero, get info for all dimensions. We look up the
  1244. dimids and get the len of each dimension. We need this to create
  1245. the space for the dataset. In netCDF a dimension length of zero
  1246. means an unlimited dimension. */
  1247. if (var->ndims)
  1248. {
  1249. int unlimdim = 0;
  1250. /* Check to see if any unlimited dimensions are used in this var. */
  1251. for (d = 0; d < var->ndims; d++)
  1252. if (var->dim[d]->unlimited)
  1253. unlimdim++;
  1254. /* If there are no unlimited dims, and no filters, and the user
  1255. * has not specified chunksizes, use contiguous variable for
  1256. * better performance. */
  1257. if (!unlimdim && !var->shuffle && !var->deflate && !var->options_mask &&
  1258. !var->fletcher32 && !var->chunksizes[0])
  1259. var->contiguous = 1;
  1260. if (!(dimsize = malloc(var->ndims * sizeof(hsize_t))))
  1261. BAIL(NC_ENOMEM);
  1262. if (!(maxdimsize = malloc(var->ndims * sizeof(hsize_t))))
  1263. BAIL(NC_ENOMEM);
  1264. if (!(chunksize = malloc(var->ndims * sizeof(hsize_t))))
  1265. BAIL(NC_ENOMEM);
  1266. /* for (d = 0; d < var->ndims; d++)
  1267. dimsize[d] = var->dim[d]->unlimited ? NC_HDF5_UNLIMITED_DIMSIZE : var->dim[d]->len;
  1268. maxdimsize[d] = var->dim[d]->unlimited ? H5S_UNLIMITED : (hsize_t)var->dim[d]->len;
  1269. chunksize[d] = var->chunksizes[d];*/
  1270. for (d = 0; d < var->ndims; d++)
  1271. for (g = grp; g && (dims_found < var->ndims); g = g->parent)
  1272. for (dim = g->dim; dim; dim = dim->next)
  1273. if (dim->dimid == var->dimids[d])
  1274. {
  1275. dimsize[d] = dim->unlimited ? NC_HDF5_UNLIMITED_DIMSIZE : dim->len;
  1276. maxdimsize[d] = dim->unlimited ? H5S_UNLIMITED : (hsize_t)dim->len;
  1277. if (var->chunksizes[d])
  1278. chunksize[d] = var->chunksizes[d];
  1279. else
  1280. {
  1281. size_t type_size;
  1282. if (var->type_info->nc_typeid == NC_STRING)
  1283. type_size = sizeof(char *);
  1284. else
  1285. type_size = var->type_info->size;
  1286. /* Unlimited dim always gets chunksize of 1. */
  1287. if (dim->unlimited)
  1288. chunksize[d] = 1;
  1289. else
  1290. chunksize[d] = pow((double)DEFAULT_CHUNK_SIZE/type_size,
  1291. 1/(double)(var->ndims - unlimdim));
  1292. /* If the chunksize is greater than the dim
  1293. * length, make it the dim length. */
  1294. if (!dim->unlimited && chunksize[d] > dim->len)
  1295. chunksize[d] = dim->len;
  1296. set_chunksizes++;
  1297. }
  1298. if (!var->contiguous && !var->chunksizes[d])
  1299. var->chunksizes[d] = chunksize[d];
  1300. dims_found++;
  1301. break;
  1302. }
  1303. if (var->contiguous)
  1304. {
  1305. if (H5Pset_layout(plistid, H5D_CONTIGUOUS) < 0)
  1306. BAIL(NC_EHDFERR);
  1307. }
  1308. else
  1309. {
  1310. if (H5Pset_chunk(plistid, var->ndims, chunksize) < 0)
  1311. BAIL(NC_EHDFERR);
  1312. }
  1313. /* Create the dataspace. */
  1314. if ((spaceid = H5Screate_simple(var->ndims, dimsize, maxdimsize)) < 0)
  1315. BAIL(NC_EHDFERR);
  1316. #ifdef EXTRA_TESTS
  1317. num_spaces++;
  1318. #endif
  1319. }
  1320. else
  1321. {
  1322. if ((spaceid = H5Screate(H5S_SCALAR)) < 0)
  1323. BAIL(NC_EHDFERR);
  1324. #ifdef EXTRA_TESTS
  1325. num_spaces++;
  1326. #endif
  1327. }
  1328. /* Turn on creation order tracking. */
  1329. if (H5Pset_attr_creation_order(plistid, H5P_CRT_ORDER_TRACKED|
  1330. H5P_CRT_ORDER_INDEXED) < 0)
  1331. BAIL(NC_EHDFERR);
  1332. /* Set per-var chunk cache. */
  1333. if (var->chunk_cache_size)
  1334. if (H5Pset_chunk_cache(access_plistid, var->chunk_cache_nelems,
  1335. var->chunk_cache_size, var->chunk_cache_preemption) < 0)
  1336. BAIL(NC_EHDFERR);
  1337. /* At long last, create the dataset. */
  1338. name_to_use = var->hdf5_name ? var->hdf5_name : var->name;
  1339. LOG((4, "var_create_dataset: about to H5Dcreate dataset %s of type 0x%x",
  1340. name_to_use, typeid));
  1341. if ((var->hdf_datasetid = H5Dcreate2(grp->hdf_grpid, name_to_use, typeid,
  1342. spaceid, H5P_DEFAULT, plistid, access_plistid)) < 0)
  1343. BAIL(NC_EHDFERR);
  1344. var->created++;
  1345. var->dirty = 0;
  1346. /* If this is a dimscale, mark it as such in the HDF5 file. Also
  1347. * find the dimension info and store the dataset id of the dimscale
  1348. * dataset. */
  1349. if (var->dimscale)
  1350. {
  1351. if (H5DSset_scale(var->hdf_datasetid, var->name) < 0)
  1352. BAIL(NC_EHDFERR);
  1353. for (dim = grp->dim; dim; dim = dim->next)
  1354. if (strcmp(dim->name, var->name) == 0)
  1355. {
  1356. dim->hdf_dimscaleid = var->hdf_datasetid;
  1357. break;
  1358. }
  1359. /* Make sure we found a dimension, and gave it a dimscale id. */
  1360. if (!dim || !dim->hdf_dimscaleid)
  1361. BAIL(NC_EDIMMETA);
  1362. /* If this is a multidimensional coordinate variable, write a
  1363. * coordinates attribute. */
  1364. if (var->ndims > 1)
  1365. if ((retval = write_coord_dimids(var)))
  1366. BAIL(retval);
  1367. /* If desired, write the netCDF dimid. */
  1368. if (write_dimid)
  1369. if ((retval = write_netcdf4_dimid(var->hdf_datasetid,
  1370. var->dimids[0])))
  1371. BAIL(retval);
  1372. }
  1373. exit:
  1374. if (var->type_info->nc_typeid == NC_STRING || var->type_info->nc_typeid == NC_CHAR)
  1375. if (typeid > 0 && H5Tclose(typeid) < 0)
  1376. BAIL2(NC_EHDFERR);
  1377. if (plistid > 0 && H5Pclose(plistid) < 0)
  1378. BAIL2(NC_EHDFERR);
  1379. #ifdef EXTRA_TESTS
  1380. num_plists--;
  1381. #endif
  1382. if (access_plistid > 0 && H5Pclose(access_plistid) < 0)
  1383. BAIL2(NC_EHDFERR);
  1384. #ifdef EXTRA_TESTS
  1385. num_plists--;
  1386. #endif
  1387. if (spaceid > 0 && H5Sclose(spaceid) < 0)
  1388. BAIL2(NC_EHDFERR);
  1389. #ifdef EXTRA_TESTS
  1390. num_spaces--;
  1391. #endif
  1392. if (maxdimsize) free(maxdimsize);
  1393. if (dimsize) free(dimsize);
  1394. if (chunksize) free(chunksize);
  1395. return retval;
  1396. }
  1397. /* Adjust the chunk cache of a var for better performance. */
  1398. int
  1399. nc4_adjust_var_cache(NC_GRP_INFO_T *grp, NC_VAR_INFO_T * var)
  1400. {
  1401. size_t chunk_size_bytes = 1;
  1402. int d;
  1403. int retval;
  1404. /* Nothing to be done. */
  1405. if (var->contiguous)
  1406. return NC_NOERR;
  1407. #ifdef USE_PARALLEL
  1408. return NC_NOERR;
  1409. #endif
  1410. /* How many bytes in the chunk? */
  1411. for (d = 0; d < var->ndims; d++)
  1412. chunk_size_bytes *= var->chunksizes[d];
  1413. if (var->type_info->size)
  1414. chunk_size_bytes *= var->type_info->size;
  1415. else
  1416. chunk_size_bytes *= sizeof(char *);
  1417. /* If the chunk cache is too small, and the user has not changed
  1418. * the default value of the chunk cache size, then increase the
  1419. * size of the cache. */
  1420. if (var->chunk_cache_size == CHUNK_CACHE_SIZE)
  1421. if (chunk_size_bytes > var->chunk_cache_size)
  1422. {
  1423. var->chunk_cache_size = chunk_size_bytes * DEFAULT_CHUNKS_IN_CACHE;
  1424. if (var->chunk_cache_size > MAX_DEFAULT_CACHE_SIZE)
  1425. var->chunk_cache_size = MAX_DEFAULT_CACHE_SIZE;
  1426. if ((retval = nc4_reopen_dataset(grp, var)))
  1427. return retval;
  1428. }
  1429. return NC_NOERR;
  1430. }
  1431. /* Read or write an attribute. */
  1432. static int
  1433. put_att_grpa(NC_GRP_INFO_T *grp, int varid, NC_ATT_INFO_T *att)
  1434. {
  1435. hid_t datasetid = 0, locid;
  1436. hid_t attid = 0, spaceid = 0, file_typeid = 0;
  1437. hsize_t dims[1]; /* netcdf attributes always 1-D. */
  1438. int retval = NC_NOERR;
  1439. void *data;
  1440. int phoney_data = 99;
  1441. assert(att->name);
  1442. LOG((3, "put_att_grpa: varid %d att->attnum %d att->name %s "
  1443. "att->xtype %d att->len %d", varid, att->attnum, att->name,
  1444. att->xtype, att->len));
  1445. /* If the file is read-only, return an error. */
  1446. if (grp->file->nc4_info->no_write)
  1447. return NC_EPERM;
  1448. /* Get the hid to attach the attribute to, or read it from. */
  1449. if (varid == NC_GLOBAL)
  1450. locid = grp->hdf_grpid;
  1451. else
  1452. {
  1453. if ((retval = nc4_open_var_grp2(grp, varid, &datasetid)))
  1454. BAIL(retval);
  1455. locid = datasetid;
  1456. }
  1457. /* Delete the att if it exists already. */
  1458. H5E_BEGIN_TRY {
  1459. H5Adelete(locid, att->name);
  1460. } H5E_END_TRY;
  1461. /* Get the length ready, and find the HDF type we'll be
  1462. * writing. */
  1463. dims[0] = att->len;
  1464. if ((retval = nc4_get_hdf_typeid(grp->file->nc4_info, att->xtype,
  1465. &file_typeid, 0)))
  1466. BAIL(retval);
  1467. /* Even if the length is zero, HDF5 won't let me write with a
  1468. * NULL pointer. So if the length of the att is zero, point to
  1469. * some phoney data (which won't be written anyway.)*/
  1470. if (!dims[0])
  1471. data = &phoney_data;
  1472. else if (att->data)
  1473. data = att->data;
  1474. else if (att->stdata)
  1475. data = att->stdata;
  1476. else
  1477. data = att->vldata;
  1478. /* NC_CHAR types require some extra work. The space ID is set to
  1479. * scalar, and the type is told how long the string is. If it's
  1480. * really zero length, set the size to 1. (The fact that it's
  1481. * really zero will be marked by the NULL dataspace, but HDF5
  1482. * doesn't allow me to set the size of the type to zero.)*/
  1483. if (att->xtype == NC_CHAR)
  1484. {
  1485. size_t string_size = dims[0];
  1486. if (!string_size)
  1487. {
  1488. string_size = 1;
  1489. if ((spaceid = H5Screate(H5S_NULL)) < 0)
  1490. BAIL(NC_EATTMETA);
  1491. #ifdef EXTRA_TESTS
  1492. num_spaces++;
  1493. #endif
  1494. }
  1495. else
  1496. {
  1497. if ((spaceid = H5Screate(H5S_SCALAR)) < 0)
  1498. BAIL(NC_EATTMETA);
  1499. #ifdef EXTRA_TESTS
  1500. num_spaces++;
  1501. #endif
  1502. }
  1503. if (H5Tset_size(file_typeid, string_size) < 0)
  1504. BAIL(NC_EATTMETA);
  1505. if (H5Tset_strpad(file_typeid, H5T_STR_NULLTERM) < 0)
  1506. BAIL(NC_EATTMETA);
  1507. }
  1508. else
  1509. {
  1510. if (!att->len)
  1511. {
  1512. if ((spaceid = H5Screate(H5S_NULL)) < 0)
  1513. BAIL(NC_EATTMETA);
  1514. #ifdef EXTRA_TESTS
  1515. num_spaces++;
  1516. #endif
  1517. }
  1518. else
  1519. {
  1520. if ((spaceid = H5Screate_simple(1, dims, NULL)) < 0)
  1521. BAIL(NC_EATTMETA);
  1522. #ifdef EXTRA_TESTS
  1523. num_spaces++;
  1524. #endif
  1525. }
  1526. }
  1527. if ((attid = H5Acreate(locid, att->name, file_typeid, spaceid,
  1528. H5P_DEFAULT)) < 0)
  1529. BAIL(NC_EATTMETA);
  1530. /* Write the values, (even if length is zero). */
  1531. if (H5Awrite(attid, file_typeid, data) < 0)
  1532. BAIL(NC_EATTMETA);
  1533. exit:
  1534. if (att->xtype == NC_CHAR || att->xtype == NC_STRING)
  1535. if (file_typeid && H5Tclose(file_typeid))
  1536. BAIL2(NC_EHDFERR);
  1537. if (attid > 0 && H5Aclose(attid) < 0)
  1538. BAIL2(NC_EHDFERR);
  1539. if (spaceid > 0 && H5Sclose(spaceid) < 0)
  1540. BAIL2(NC_EHDFERR);
  1541. #ifdef EXTRA_TESTS
  1542. num_spaces--;
  1543. #endif
  1544. return retval;
  1545. }
  1546. /* Create a HDF5 defined type from a NC_TYPE_INFO_T struct, and commit
  1547. * it to the file. */
  1548. static int
  1549. commit_type(NC_GRP_INFO_T *grp, NC_TYPE_INFO_T *type)
  1550. {
  1551. NC_FIELD_INFO_T *field;
  1552. NC_ENUM_MEMBER_INFO_T *enum_m;
  1553. hid_t hdf_base_typeid, hdf_typeid;
  1554. int retval;
  1555. assert(grp && type);
  1556. /* Did we already record this type? */
  1557. if (type->committed)
  1558. return NC_NOERR;
  1559. /* Is this a compound type? */
  1560. if (type->class == NC_COMPOUND)
  1561. {
  1562. if ((type->hdf_typeid = H5Tcreate(H5T_COMPOUND, type->size)) < 0)
  1563. return NC_EHDFERR;
  1564. LOG((4, "creating compound type %s hdf_typeid 0x%x", type->name,
  1565. type->hdf_typeid));
  1566. for (field = type->field; field; field = field->next)
  1567. {
  1568. if ((retval = nc4_get_hdf_typeid(grp->file->nc4_info, field->nctype,
  1569. &hdf_base_typeid, type->endianness)))
  1570. return retval;
  1571. /* If this is an array, create a special array type. */
  1572. if (field->ndims)
  1573. {
  1574. int d;
  1575. hsize_t dims[NC_MAX_DIMS];
  1576. for (d = 0; d < field->ndims; d++)
  1577. dims[d] = field->dim_size[d];
  1578. if ((hdf_typeid = H5Tarray_create(hdf_base_typeid, field->ndims,
  1579. dims, NULL)) < 0)
  1580. return NC_EHDFERR;
  1581. }
  1582. else
  1583. hdf_typeid = hdf_base_typeid;
  1584. LOG((4, "inserting field %s offset %d hdf_typeid 0x%x", field->name,
  1585. field->offset, hdf_typeid));
  1586. if (H5Tinsert(type->hdf_typeid, field->name, field->offset,
  1587. hdf_typeid) < 0)
  1588. return NC_EHDFERR;
  1589. if (field->ndims && H5Tclose(hdf_typeid) < 0)
  1590. return NC_EHDFERR;
  1591. }
  1592. }
  1593. else if (type->class == NC_VLEN)
  1594. {
  1595. /* Find the HDF typeid of the base type of this vlen. */
  1596. if ((retval = nc4_get_hdf_typeid(grp->file->nc4_info, type->base_nc_type,
  1597. &type->base_hdf_typeid, type->endianness)))
  1598. return retval;
  1599. /* Create a vlen type. */
  1600. if ((type->hdf_typeid = H5Tvlen_create(type->base_hdf_typeid)) < 0)
  1601. return NC_EHDFERR;
  1602. }
  1603. else if (type->class == NC_OPAQUE)
  1604. {
  1605. /* Create the opaque type. */
  1606. if ((type->hdf_typeid = H5Tcreate(H5T_OPAQUE, type->size)) < 0)
  1607. return NC_EHDFERR;
  1608. }
  1609. else if (type->class == NC_ENUM)
  1610. {
  1611. if (!type->enum_member)
  1612. return NC_EINVAL;
  1613. /* Find the HDF typeid of the base type of this enum. */
  1614. if ((retval = nc4_get_hdf_typeid(grp->file->nc4_info, type->base_nc_type,
  1615. &type->base_hdf_typeid, type->endianness)))
  1616. return retval;
  1617. /* Create an enum type. */
  1618. if ((type->hdf_typeid = H5Tenum_create(type->base_hdf_typeid)) < 0)
  1619. return NC_EHDFERR;
  1620. /* Add all the members to the HDF5 type. */
  1621. for (enum_m = type->enum_member; enum_m; enum_m = enum_m->next)
  1622. if (H5Tenum_insert(type->hdf_typeid, enum_m->name,
  1623. enum_m->value) < 0)
  1624. return NC_EHDFERR;
  1625. }
  1626. else
  1627. {
  1628. LOG((0, "Unknown class: %d", type->class));
  1629. return NC_EBADTYPE;
  1630. }
  1631. /* Commit the type. */
  1632. if (H5Tcommit(grp->hdf_grpid, type->name, type->hdf_typeid) < 0)
  1633. return NC_EHDFERR;
  1634. type->committed++;
  1635. LOG((4, "just committed type %s, HDF typeid: 0x%x", type->name,
  1636. type->hdf_typeid));
  1637. /* Later we will always use the native typeid. In this case, it is
  1638. * a copy of the same type pointed to by hdf_typeid, but it's
  1639. * easier to maintain a copy. */
  1640. if ((type->native_typeid = H5Tget_native_type(type->hdf_typeid,
  1641. H5T_DIR_DEFAULT)) < 0)
  1642. return NC_EHDFERR;
  1643. return NC_NOERR;
  1644. }
  1645. /* Write an attribute, with value 1, to indicate that strict NC3 rules
  1646. * apply to this file. */
  1647. static int
  1648. write_nc3_strict_att(hid_t hdf_grpid)
  1649. {
  1650. hid_t attid = 0, spaceid = 0;
  1651. int one = 1, num, a;
  1652. char att_name[NC_MAX_NAME + 1];
  1653. int retval = NC_NOERR;
  1654. /* If the attribute already exists, call that a success and return
  1655. * NC_NOERR. */
  1656. if ((num = H5Aget_num_attrs(hdf_grpid)) < 0)
  1657. return NC_EHDFERR;
  1658. for (a = 0; a < num; a++)
  1659. {
  1660. if ((attid = H5Aopen_idx(hdf_grpid, (unsigned int)a)) < 0)
  1661. BAIL(NC_EHDFERR);
  1662. if (H5Aget_name(attid, NC_MAX_HDF5_NAME, att_name) < 0)
  1663. BAIL(NC_EHDFERR);
  1664. if (!strcmp(att_name, NC3_STRICT_ATT_NAME))
  1665. {
  1666. if (H5Aclose(attid) < 0)
  1667. return NC_EFILEMETA;
  1668. return NC_NOERR;
  1669. }
  1670. }
  1671. /* Create the attribute to mark this as a file that needs to obey
  1672. * strict netcdf-3 rules. */
  1673. if ((spaceid = H5Screate(H5S_SCALAR)) < 0)
  1674. BAIL(NC_EFILEMETA);
  1675. #ifdef EXTRA_TESTS
  1676. num_spaces++;
  1677. #endif
  1678. if ((attid = H5Acreate(hdf_grpid, NC3_STRICT_ATT_NAME,
  1679. H5T_NATIVE_INT, spaceid, H5P_DEFAULT)) < 0)
  1680. BAIL(NC_EFILEMETA);
  1681. if (H5Awrite(attid, H5T_NATIVE_INT, &one) < 0)
  1682. BAIL(NC_EFILEMETA);
  1683. exit:
  1684. if (spaceid && (H5Sclose(spaceid) < 0))
  1685. BAIL2(NC_EFILEMETA);
  1686. #ifdef EXTRA_TESTS
  1687. num_spaces--;
  1688. #endif
  1689. if (attid && (H5Aclose(attid) < 0))
  1690. BAIL2(NC_EFILEMETA);
  1691. return retval;
  1692. }
  1693. static int
  1694. create_group(NC_GRP_INFO_T *grp)
  1695. {
  1696. hid_t gcpl_id = 0;
  1697. int retval = NC_NOERR;;
  1698. assert(grp);
  1699. /* If this is not the root group, create it in the HDF5 file. */
  1700. if (grp->parent)
  1701. {
  1702. /* Create group, with link_creation_order set in the group
  1703. * creation property list. */
  1704. if ((gcpl_id = H5Pcreate(H5P_GROUP_CREATE)) < 0)
  1705. return NC_EHDFERR;
  1706. #ifdef EXTRA_TESTS
  1707. num_plists++;
  1708. #endif
  1709. if (H5Pset_link_creation_order(gcpl_id, H5P_CRT_ORDER_TRACKED|H5P_CRT_ORDER_INDEXED) < 0)
  1710. BAIL(NC_EHDFERR);
  1711. if (H5Pset_attr_creation_order(gcpl_id, H5P_CRT_ORDER_TRACKED|H5P_CRT_ORDER_INDEXED) < 0)
  1712. BAIL(NC_EHDFERR);
  1713. if ((grp->hdf_grpid = H5Gcreate2(grp->parent->hdf_grpid, grp->name,
  1714. H5P_DEFAULT, gcpl_id, H5P_DEFAULT)) < 0)
  1715. BAIL(NC_EHDFERR);
  1716. if (H5Pclose(gcpl_id) < 0)
  1717. BAIL(NC_EHDFERR);
  1718. #ifdef EXTRA_TESTS
  1719. num_plists--;
  1720. #endif
  1721. }
  1722. else
  1723. {
  1724. /* Since this is the root group, we have to open it. */
  1725. if ((grp->hdf_grpid = H5Gopen2(grp->file->nc4_info->hdfid, "/", H5P_DEFAULT)) < 0)
  1726. BAIL(NC_EFILEMETA);
  1727. }
  1728. return NC_NOERR;
  1729. exit:
  1730. if (gcpl_id > 0 && H5Pclose(gcpl_id) < 0)
  1731. BAIL2(NC_EHDFERR);
  1732. #ifdef EXTRA_TESTS
  1733. num_plists--;
  1734. #endif
  1735. if (grp->hdf_grpid > 0 && H5Gclose(grp->hdf_grpid) < 0)
  1736. BAIL2(NC_EHDFERR);
  1737. return retval;
  1738. }
  1739. /* After all the datasets of the file have been read, it's time to
  1740. * sort the wheat from the chaff. Which of the datasets are netCDF
  1741. * dimensions, and which are coordinate variables, and which are
  1742. * non-coordinate variables. */
  1743. static int
  1744. attach_dimscales(NC_GRP_INFO_T *grp)
  1745. {
  1746. NC_VAR_INFO_T *var;
  1747. NC_DIM_INFO_T *dim1;
  1748. NC_GRP_INFO_T *g;
  1749. int d;
  1750. int retval = NC_NOERR;
  1751. /* Attach dimension scales. */
  1752. for (var = grp->var; var; var = var->next)
  1753. {
  1754. /* Scales themselves do not attach. But I really wish they
  1755. * would. */
  1756. if (var->dimscale)
  1757. {
  1758. /* If this is a multidimensional coordinate variable, it will
  1759. * have a special coords attribute (read earlier) with a list
  1760. * of the dimensions for this variable. */
  1761. }
  1762. else /* not a dimscale... */
  1763. {
  1764. /* Find the scale for each dimension and attach it. */
  1765. for (d = 0; d < var->ndims; d++)
  1766. {
  1767. /* Is there a dimscale for this dimension? */
  1768. if (var->dimscale_attached)
  1769. {
  1770. if (!var->dimscale_attached[d])
  1771. {
  1772. for (g = grp; g && !var->dimscale_attached[d]; g = g->parent)
  1773. for (dim1 = g->dim; dim1; dim1 = dim1->next)
  1774. if (var->dimids[d] == dim1->dimid)
  1775. {
  1776. LOG((2, "attach_dimscales: attaching scale for dimid %d to var %s",
  1777. var->dimids[d], var->name));
  1778. if (H5DSattach_scale(var->hdf_datasetid, dim1->hdf_dimscaleid, d) < 0)
  1779. BAIL(NC_EHDFERR);
  1780. var->dimscale_attached[d]++;
  1781. break;
  1782. }
  1783. }
  1784. /* If we didn't find a dimscale to attach, that's a problem! */
  1785. if (!var->dimscale_attached[d])
  1786. {
  1787. LOG((0, "no dimscale found!"));
  1788. return NC_EDIMSCALE;
  1789. }
  1790. }
  1791. else
  1792. {
  1793. /* Create a phoney dimension! */
  1794. }
  1795. }
  1796. } /* next d */
  1797. }
  1798. exit:
  1799. return retval;
  1800. }
  1801. /* Write all the dirty atts in an attlist. */
  1802. static int
  1803. write_attlist(NC_ATT_INFO_T *attlist, int varid, NC_GRP_INFO_T *grp)
  1804. {
  1805. NC_ATT_INFO_T *att;
  1806. int retval;
  1807. for (att = attlist; att; att = att->next)
  1808. {
  1809. if (att->dirty)
  1810. {
  1811. LOG((4, "write_attlist: writing att %s to varid %d", att->name, varid));
  1812. if ((retval = put_att_grpa(grp, varid, att)))
  1813. return retval;
  1814. att->dirty = 0;
  1815. att->created++;
  1816. }
  1817. }
  1818. return NC_NOERR;
  1819. }
  1820. /* Using the HDF5 group iterator is more efficient than the original
  1821. * code (O(n) vs O(n**2) for n variables in the group) */
  1822. #define USE_ITERATE_CODE
  1823. #ifdef USE_ITERATE_CODE
  1824. typedef struct {
  1825. char *name; /* The name of the object to searched*/
  1826. int *exists; /* 1 if the object exists, 0 otherswise */
  1827. } var_exists_iter_info;
  1828. /*-------------------------------------------------------------------------
  1829. * Function: var_exists_cb
  1830. *
  1831. * Purpose: Callback routine for checking an object by its name
  1832. *
  1833. * Return: Exist: 1
  1834. * Not exist: 0
  1835. * Failure: -1
  1836. *
  1837. * Programmer: Peter Cao
  1838. * 1/25/2012
  1839. *
  1840. *-------------------------------------------------------------------------
  1841. */
  1842. static int
  1843. var_exists_cb(hid_t grpid, const char *name, const H5L_info_t *info,
  1844. void *_op_data)
  1845. {
  1846. var_exists_iter_info *iter_info = (var_exists_iter_info *)_op_data;
  1847. H5I_type_t otype;
  1848. hid_t oid;
  1849. if ((oid = H5Oopen(grpid, name, H5P_DEFAULT)) < 0)
  1850. return H5_ITER_STOP;
  1851. if ((otype = H5Iget_type( oid ))<0) {
  1852. H5Oclose(oid);
  1853. return H5_ITER_STOP;
  1854. }
  1855. H5Oclose(oid);
  1856. if (otype == H5I_DATASET) {
  1857. if (!strcmp(iter_info->name, name)) {
  1858. *(iter_info->exists) = 1;
  1859. return (H5_ITER_STOP);
  1860. }
  1861. }
  1862. return (H5_ITER_CONT);
  1863. } /* end var_exists_cb() */
  1864. static int
  1865. var_exists(hid_t grpid, char *name, int *exists)
  1866. {
  1867. hsize_t num_obj;
  1868. var_exists_iter_info iter_info;
  1869. iter_info.name = name;
  1870. iter_info.exists = exists;
  1871. if (H5Gget_num_objs(grpid, &num_obj) < 0)
  1872. return NC_EVARMETA;
  1873. if (!name)
  1874. return NC_NOERR;
  1875. *exists = 0;
  1876. if (H5Literate(grpid, H5_INDEX_CRT_ORDER, H5_ITER_INC, NULL, var_exists_cb, &iter_info) < 0)
  1877. return NC_EHDFERR;
  1878. return NC_NOERR;
  1879. }
  1880. #else
  1881. static int
  1882. var_exists(hid_t grpid, char *name, int *exists)
  1883. {
  1884. hsize_t num_obj, i;
  1885. H5O_info_t obj_info;
  1886. int obj_class;
  1887. char obj_name[NC_MAX_NAME + 1];
  1888. ssize_t size;
  1889. int retval = NC_NOERR;
  1890. *exists = 0;
  1891. if (H5Gget_num_objs(grpid, &num_obj) < 0)
  1892. return NC_EVARMETA;
  1893. for (i = 0; i < num_obj; i++)
  1894. {
  1895. if (H5Oget_info_by_idx(grpid, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, i, &obj_info, H5P_DEFAULT) < 0)
  1896. return NC_EHDFERR;
  1897. obj_class = obj_info.type;
  1898. if ((size = H5Lget_name_by_idx(grpid, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, i, NULL, 0, H5P_DEFAULT)) < 0)
  1899. return NC_EHDFERR;
  1900. if (size > NC_MAX_NAME)
  1901. return NC_EMAXNAME;
  1902. if (H5Lget_name_by_idx(grpid, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, i, obj_name, size+1, H5P_DEFAULT) < 0)
  1903. return NC_EHDFERR;
  1904. if (obj_class == H5O_TYPE_DATASET)
  1905. {
  1906. if (!strncmp(name, obj_name, NC_MAX_NAME))
  1907. {
  1908. *exists = 1;
  1909. return NC_NOERR;
  1910. }
  1911. }
  1912. }
  1913. return retval;
  1914. }
  1915. #endif /* USE_ITERATE_CODE */
  1916. /* This function writes a variable. The principle difficulty comes
  1917. * from the possibility that this is a coordinate variable, and was
  1918. * already written to the file as a dimension-only dimscale. If this
  1919. * occurs, then it must be deleted and recreated. */
  1920. static int
  1921. write_var(NC_VAR_INFO_T *var, NC_GRP_INFO_T *grp, int write_dimid)
  1922. {
  1923. NC_DIM_INFO_T *d1 = NULL;
  1924. int replace_existing_var = 0;
  1925. int exists;
  1926. int retval;
  1927. if (!var->dirty)
  1928. {
  1929. if (write_dimid && var->ndims)
  1930. if ((retval = write_netcdf4_dimid(var->hdf_datasetid,
  1931. var->dimids[0])))
  1932. BAIL(retval);
  1933. }
  1934. else
  1935. {
  1936. LOG((4, "write_var: writing var %s", var->name));
  1937. if (var->created)
  1938. replace_existing_var = 1;
  1939. /* If this is a coordinate var, and a dataset has already
  1940. * been created for it, then delete that dataset and recreate
  1941. * it (because its type may be wrong anyway.) But then we
  1942. * have to reattach dimension scales for all vars! Oh well,
  1943. * this all only happens when the user defines a var, writes
  1944. * metadata, reenters define mode, and adds a coordinate
  1945. * var. Presumably this will happen rarely. */
  1946. /* Is this a coordinate var that has already been created in
  1947. * the HDF5 as a dimscale dataset? Check for dims with the
  1948. * same name in this group. If there is one, check to see if
  1949. * this object exists in the HDF group. */
  1950. if (var->dimscale)
  1951. for (d1 = grp->dim; d1; d1 = d1->next)
  1952. if (!strcmp(d1->name, var->name))
  1953. {
  1954. if ((retval = var_exists(grp->hdf_grpid, var->name, &exists)))
  1955. return retval;
  1956. if (exists)
  1957. {
  1958. replace_existing_var++;
  1959. /* If we're replacing an existing dimscale dataset, go to
  1960. * every var in the file and detatch this dimension scale,
  1961. * because we have to delete it. */
  1962. if ((retval = rec_detach_scales(grp->file->nc4_info->root_grp,
  1963. var->dimids[0], d1->hdf_dimscaleid)))
  1964. return retval;
  1965. break;
  1966. }
  1967. }
  1968. /* Delete the HDF5 dataset that is to be replaced. */
  1969. if (replace_existing_var)
  1970. {
  1971. /* If this is a dimension scale, do this stuff. */
  1972. if (d1)
  1973. {
  1974. assert(d1 && d1->hdf_dimscaleid);
  1975. if (H5Dclose(d1->hdf_dimscaleid) < 0)
  1976. return NC_EDIMMETA;
  1977. }
  1978. else
  1979. {
  1980. int dims_detached = 0;
  1981. int finished = 0;
  1982. int d;
  1983. NC_DIM_INFO_T *dim1;
  1984. NC_GRP_INFO_T *g;
  1985. /* If this is a regular var, detach all its dim scales. */
  1986. for (d = 0; d < var->ndims; d++)
  1987. for (g = grp; g && !finished; g = g->parent)
  1988. for (dim1 = g->dim; dim1; dim1 = dim1->next)
  1989. if (var->dimids[d] == dim1->dimid)
  1990. {
  1991. if (H5DSdetach_scale(var->hdf_datasetid, dim1->hdf_dimscaleid, d) < 0)
  1992. BAIL(NC_EHDFERR);
  1993. var->dimscale_attached[d] = 0;
  1994. if (dims_detached++ == var->ndims)
  1995. finished++;
  1996. }
  1997. }
  1998. /* Free the HDF5 dataset id. */
  1999. if (var->hdf_datasetid && H5Dclose(var->hdf_datasetid))
  2000. BAIL(NC_EHDFERR);
  2001. /* Now delete the variable. */
  2002. if (H5Gunlink(grp->hdf_grpid, var->name) < 0)
  2003. return NC_EDIMMETA;
  2004. }
  2005. /* Create the dataset. */
  2006. if ((retval = var_create_dataset(grp, var, write_dimid)))
  2007. return retval;
  2008. /* Reattach this scale everywhere it is used. (Recall that
  2009. * netCDF dimscales are always 1-D). */
  2010. if (d1 && replace_existing_var)
  2011. {
  2012. d1->hdf_dimscaleid = var->hdf_datasetid;
  2013. if ((retval = rec_reattach_scales(grp->file->nc4_info->root_grp,
  2014. var->dimids[0], d1->hdf_dimscaleid)))
  2015. return retval;
  2016. }
  2017. }
  2018. /* Now check the atributes for this var. */
  2019. /* Write attributes for this var. */
  2020. if ((retval = write_attlist(var->att, var->varid, grp)))
  2021. BAIL(retval);
  2022. return NC_NOERR;
  2023. exit:
  2024. return retval;
  2025. }
  2026. static int
  2027. write_dim(NC_DIM_INFO_T *dim, NC_GRP_INFO_T *grp, int write_dimid)
  2028. {
  2029. hid_t spaceid, create_propid;
  2030. hsize_t dims[1], max_dims[1], chunk_dims[1] = {1};
  2031. int dimscale_exists = 0;
  2032. char dimscale_wo_var[NC_MAX_NAME];
  2033. int retval;
  2034. if (dim->dirty)
  2035. {
  2036. /* If there's no dimscale dataset for this dim, create one,
  2037. * and mark that it should be hidden from netCDF as a
  2038. * variable. (That is, it should appear as a dimension
  2039. * without an associated variable.) */
  2040. if (!dimscale_exists)
  2041. {
  2042. LOG((4, "write_dim: creating dim %s", dim->name));
  2043. /* Create a property list. If this dimension scale is
  2044. * unlimited (i.e. it's an unlimited dimension), then set
  2045. * up chunking, with a chunksize of 1. */
  2046. if ((create_propid = H5Pcreate(H5P_DATASET_CREATE)) < 0)
  2047. BAIL(NC_EHDFERR);
  2048. #ifdef EXTRA_TESTS
  2049. num_plists++;
  2050. #endif
  2051. dims[0] = dim->len;
  2052. max_dims[0] = dim->len;
  2053. if (dim->unlimited)
  2054. {
  2055. max_dims[0] = H5S_UNLIMITED;
  2056. if (H5Pset_chunk(create_propid, 1, chunk_dims) < 0)
  2057. BAIL(NC_EHDFERR);
  2058. }
  2059. /* Set up space. */
  2060. if ((spaceid = H5Screate_simple(1, dims, max_dims)) < 0)
  2061. BAIL(NC_EHDFERR);
  2062. #ifdef EXTRA_TESTS
  2063. num_spaces++;
  2064. #endif
  2065. /* If we define, and then rename this dimension before
  2066. * creation of the dimscale dataset, then we can throw
  2067. * away the old_name of the dimension. */
  2068. if (dim->old_name && strlen(dim->old_name))
  2069. strcpy(dim->old_name, "");
  2070. if (H5Pset_attr_creation_order(create_propid, H5P_CRT_ORDER_TRACKED|
  2071. H5P_CRT_ORDER_INDEXED) < 0)
  2072. BAIL(NC_EHDFERR);
  2073. /* Create the dataset that will be the dimension scale. */
  2074. LOG((4, "write_dim: about to H5Dcreate a dimscale dataset %s", dim->name));
  2075. if ((dim->hdf_dimscaleid = H5Dcreate1(grp->hdf_grpid, dim->name, H5T_IEEE_F32BE,
  2076. spaceid, create_propid)) < 0)
  2077. BAIL(NC_EHDFERR);
  2078. /* Close the spaceid and create_propid. */
  2079. if (H5Sclose(spaceid) < 0)
  2080. BAIL(NC_EHDFERR);
  2081. #ifdef EXTRA_TESTS
  2082. num_spaces--;
  2083. #endif
  2084. if (H5Pclose(create_propid) < 0)
  2085. BAIL(NC_EHDFERR);
  2086. #ifdef EXTRA_TESTS
  2087. num_plists--;
  2088. #endif
  2089. /* Indicate that this is a scale. Also indicate that not
  2090. * be shown to the user as a variable. It is hidden. It is
  2091. * a DIM WITHOUT A VARIABLE! */
  2092. sprintf(dimscale_wo_var, "%s%10d", DIM_WITHOUT_VARIABLE, (int)dim->len);
  2093. if (H5DSset_scale(dim->hdf_dimscaleid, dimscale_wo_var) < 0)
  2094. BAIL(NC_EHDFERR);
  2095. }
  2096. dim->dirty = 0;
  2097. }
  2098. /* Did we extend an unlimited dimension? */
  2099. if (dim->extended)
  2100. {
  2101. NC_VAR_INFO_T *v1;
  2102. assert(dim->unlimited);
  2103. /* If this is a dimension without a variable, then update
  2104. * the secret length information at the end of the NAME
  2105. * attribute. */
  2106. for (v1 = grp->var; v1; v1 = v1->next)
  2107. if (!strcmp(v1->name, dim->name))
  2108. break;
  2109. if (v1)
  2110. {
  2111. hsize_t *new_size;
  2112. NC_GRP_INFO_T *g;
  2113. NC_DIM_INFO_T *dim1;
  2114. int d1;
  2115. /* Extend the dimension scale dataset to reflect the new
  2116. * length of the dimension. */
  2117. if (!(new_size = malloc(v1->ndims * sizeof(hsize_t))))
  2118. BAIL(NC_ENOMEM);
  2119. for (d1 = 0; d1 < v1->ndims; d1++)
  2120. {
  2121. if (v1->dimids[d1] == dim->dimid)
  2122. new_size[d1] = dim->len;
  2123. else
  2124. {
  2125. int break_it = 0;
  2126. for (g = grp; g && !break_it; g = g->parent)
  2127. for (dim1 = g->dim; dim1; dim1 = dim1->next)
  2128. if (dim1->dimid == v1->dimids[d1])
  2129. {
  2130. new_size[d1] = dim1->len;
  2131. break_it++;
  2132. break;
  2133. }
  2134. }
  2135. }
  2136. if (H5Dextend(v1->hdf_datasetid, new_size) < 0)
  2137. BAIL(NC_EHDFERR);
  2138. free(new_size);
  2139. }
  2140. }
  2141. /* Did we rename this dimension? */
  2142. if (dim->old_name && strlen(dim->old_name))
  2143. {
  2144. /* Rename the dimension's dataset in the HDF5 file. */
  2145. if (H5Gmove2(grp->hdf_grpid, dim->old_name, grp->hdf_grpid, dim->name) < 0)
  2146. return NC_EHDFERR;
  2147. /* Reset old_name. */
  2148. strcpy(dim->old_name, "");
  2149. }
  2150. /* If desired, write the secret dimid. This will be used instead of
  2151. * the dimid that the dimension would otherwise receive based on
  2152. * creation order. This can be necessary when dims and their
  2153. * coordinate variables were created in different order. */
  2154. if (write_dimid && dim->hdf_dimscaleid)
  2155. if ((retval = write_netcdf4_dimid(dim->hdf_dimscaleid,
  2156. dim->dimid)))
  2157. BAIL(retval);
  2158. return NC_NOERR;
  2159. exit:
  2160. return retval;
  2161. }
  2162. /* Recursively write all the metadata in a group. Groups and types
  2163. * have all already been written. */
  2164. int
  2165. nc4_rec_write_metadata(NC_GRP_INFO_T *grp)
  2166. {
  2167. NC_DIM_INFO_T *dim;
  2168. NC_VAR_INFO_T *var;
  2169. NC_GRP_INFO_T *child_grp;
  2170. int found_coord, coord_varid = -1, wrote_coord;
  2171. int bad_coord_order = 0;
  2172. int last_dimid = -1;
  2173. int retval;
  2174. assert(grp && grp->name && grp->hdf_grpid);
  2175. LOG((3, "nc4_rec_write_metadata: grp->name %s", grp->name));
  2176. /* Write global attributes for this group. */
  2177. if ((retval = write_attlist(grp->att, NC_GLOBAL, grp)))
  2178. return retval;
  2179. /* If the user writes coord vars in a different order then he
  2180. * defined their dimensions, then, when the file is reopened, the
  2181. * order of the dimids will change to match the order of the coord
  2182. * vars. Detect if this is about to happen. */
  2183. for (var = grp->var; var; var = var->next)
  2184. {
  2185. LOG((5, "checking %s for out of order coord var", var->name));
  2186. if (var->ndims && var->dimscale)
  2187. {
  2188. if (var->dimids[0] < last_dimid)
  2189. {
  2190. bad_coord_order++;
  2191. break;
  2192. }
  2193. last_dimid = var->dimids[0];
  2194. }
  2195. }
  2196. /* Did the user define a dimension, end define mode, reenter define
  2197. * mode, and then define a coordinate variable for that dimension?
  2198. * If so, dimensions will be out of order. */
  2199. for (var = grp->var; var; var = var->next)
  2200. if (var->dirty && !var->created && var->ndims)
  2201. for (dim = grp->dim; dim && dim->next; dim = dim->next)
  2202. if (strcmp(dim->name, var->name) && !dim->dirty)
  2203. {
  2204. LOG((5, "coord var defined after enddef/redef"));
  2205. bad_coord_order++;
  2206. }
  2207. /* For some stupid reason, the dim list is stored backwards! Get to
  2208. * the back of the list. */
  2209. for (dim = grp->dim; dim && dim->next; dim = dim->next)
  2210. ;
  2211. /* Set the pointer to the beginning of the list of vars in this
  2212. * group. */
  2213. var = grp->var;
  2214. /* Because of HDF5 ordering the dims and vars have to be stored in
  2215. * this way to ensure that the dims and coordinate vars come out in
  2216. * the correct order. */
  2217. while (dim || var)
  2218. {
  2219. /* Write non-coord dims in order, stopping at the first one that
  2220. * has an associated coord var. */
  2221. for (found_coord = 0; dim && !found_coord; dim = dim->prev)
  2222. {
  2223. if (!dim->coord_var_in_grp)
  2224. {
  2225. if ((retval = write_dim(dim, grp, bad_coord_order)))
  2226. return retval;
  2227. }
  2228. else
  2229. {
  2230. found_coord++;
  2231. coord_varid = dim->coord_var->varid;
  2232. }
  2233. }
  2234. /* Write each var. When we get to the coord var we are waiting
  2235. * for (if any), then we break after writing it. */
  2236. for (wrote_coord = 0; var && !wrote_coord; var = var->next)
  2237. {
  2238. if ((retval = write_var(var, grp, bad_coord_order)))
  2239. return retval;
  2240. if (found_coord && var->varid == coord_varid)
  2241. wrote_coord++;
  2242. }
  2243. } /* end while */
  2244. if ((retval = attach_dimscales(grp)))
  2245. return retval;
  2246. /* If there are any child groups, write their metadata. */
  2247. for (child_grp = grp->children; child_grp; child_grp = child_grp->next)
  2248. if ((retval = nc4_rec_write_metadata(child_grp)))
  2249. return retval;
  2250. return NC_NOERR;
  2251. }
  2252. /* Recursively write all groups and types. */
  2253. int
  2254. nc4_rec_write_types(NC_GRP_INFO_T *grp)
  2255. {
  2256. NC_GRP_INFO_T *child_grp;
  2257. NC_TYPE_INFO_T *type;
  2258. int retval;
  2259. assert(grp && grp->name);
  2260. LOG((3, "nc4_rec_write_types: grp->name %s", grp->name));
  2261. /* Create the group in the HDF5 file if it doesn't exist. */
  2262. if (!grp->hdf_grpid)
  2263. if ((retval = create_group(grp)))
  2264. return retval;
  2265. /* If this is the root group of a file with strict NC3 rules, write
  2266. * an attribute. But don't leave the attribute open. */
  2267. if (!grp->parent && (grp->file->nc4_info->cmode & NC_CLASSIC_MODEL))
  2268. if ((retval = write_nc3_strict_att(grp->hdf_grpid)))
  2269. return retval;
  2270. /* If there are any user-defined types, write them now. */
  2271. for (type = grp->type; type; type = type->next)
  2272. if ((retval = commit_type(grp, type)))
  2273. return retval;
  2274. /* If there are any child groups, write their groups and types. */
  2275. for (child_grp = grp->children; child_grp; child_grp = child_grp->next)
  2276. if ((retval = nc4_rec_write_types(child_grp)))
  2277. return retval;
  2278. return NC_NOERR;
  2279. }
  2280. /* This reads/writes a whole var at a time. If the file has an
  2281. unlimited dimension, then we will look at the number of records
  2282. currently existing for this var, and read/write that many. This
  2283. this is not what the user intended, particularly with writing, then
  2284. that is there look-out! So we will not be extending datasets
  2285. here. */
  2286. int
  2287. pg_var(NC_PG_T pg, NC_FILE_INFO_T *nc, int ncid, int varid, nc_type xtype,
  2288. int is_long, void *ip)
  2289. {
  2290. NC_GRP_INFO_T *grp;
  2291. NC_VAR_INFO_T *var;
  2292. size_t start[NC_MAX_VAR_DIMS], count[NC_MAX_VAR_DIMS];
  2293. int i;
  2294. int retval;
  2295. assert(nc);
  2296. if ((retval = nc4_find_g_var_nc(nc, ncid, varid, &grp, &var)))
  2297. return retval;
  2298. assert(grp && var && var->name);
  2299. /* For each dimension, the start will be 0, and the count will be
  2300. * the length of the dimension. */
  2301. for (i = 0; i < var->ndims; i++)
  2302. {
  2303. start[i] = 0;
  2304. if ((retval = nc_inq_dimlen(ncid, var->dimids[i], &(count[i]))))
  2305. return retval;
  2306. }
  2307. /* Read or write the data. */
  2308. if (pg == GET)
  2309. return nc4_get_vara(nc, ncid, varid, start, count, xtype,
  2310. is_long, ip);
  2311. else
  2312. return nc4_put_vara(nc, ncid, varid, start, count, xtype,
  2313. is_long, ip);
  2314. }
  2315. /* Write or read some mapped data. Yea, like I even understand what it
  2316. is!
  2317. I stole this code, lock, stock, and semicolons, from the netcdf
  2318. 3.5.1 beta release. It walks through the stride and map arrays, and
  2319. converts them to a series of calles to the varm function.
  2320. I had to modify the code a little to fit it in, and generalize it
  2321. for all data types, and for both puts and gets.
  2322. Ed Hartnett, 9/43/03
  2323. */
  2324. int
  2325. nc4_pg_varm(NC_PG_T pg, NC_FILE_INFO_T *nc, int ncid, int varid, const size_t *start,
  2326. const size_t *edges, const ptrdiff_t *stride,
  2327. const ptrdiff_t *map, nc_type xtype, int is_long, void *data)
  2328. {
  2329. NC_GRP_INFO_T *grp;
  2330. NC_HDF5_FILE_INFO_T *h5;
  2331. NC_VAR_INFO_T *var;
  2332. int maxidim; /* maximum dimensional index */
  2333. size_t mem_type_size;
  2334. int convert_map = 0;
  2335. ptrdiff_t new_map[NC_MAX_VAR_DIMS];
  2336. int i;
  2337. int retval = NC_NOERR;
  2338. LOG((3, "nc4_pg_varm: ncid 0x%x varid %d xtype %d", ncid, varid,
  2339. xtype));
  2340. /* Find metadata for this file and var. */
  2341. assert(nc && nc->nc4_info);
  2342. h5 = nc->nc4_info;
  2343. if ((retval = nc4_find_g_var_nc(nc, ncid, varid, &grp, &var)))
  2344. return retval;
  2345. assert(grp && var && var->name);
  2346. /* If mem_nc_type is NC_NAT, it means we were called by
  2347. * nc_get|put_varm, the old V2 API call! In this case we want to
  2348. * use the file type as the mem type as well. Also, for these two
  2349. * functions only, we interpret the map array as referring to
  2350. * numbers of bytes rather than number of elements. (This is
  2351. * something that changed between V2 and V3.) Also we do not allow
  2352. * mapped access to user-defined vars in nc4. */
  2353. if (xtype == NC_NAT)
  2354. {
  2355. if (var->xtype > NC_STRING)
  2356. return NC_EMAPTYPE;
  2357. xtype = var->xtype;
  2358. convert_map++;
  2359. }
  2360. assert(xtype);
  2361. /* What is the size of this type? */
  2362. if ((retval = nc4_get_typelen_mem(h5, xtype, is_long, &mem_type_size)))
  2363. return retval;
  2364. if(map != NULL && var->ndims && convert_map)
  2365. {
  2366. /* convert map units from bytes to units of sizeof(type) */
  2367. for(i = 0; i < var->ndims; i++)
  2368. {
  2369. if(map[i] % mem_type_size != 0)
  2370. return NC_EINVAL;
  2371. new_map[i] = map[i] / mem_type_size;
  2372. }
  2373. map = new_map;
  2374. }
  2375. /* No text to number hanky-panky is allowed for those observing
  2376. * strict netcdf-3 rules! It's sick. */
  2377. if ((h5->cmode & NC_CLASSIC_MODEL) && (xtype == NC_CHAR || var->xtype == NC_CHAR) &&
  2378. (xtype != var->xtype))
  2379. return NC_ECHAR;
  2380. /* If the file is read-only, return an error. */
  2381. if (pg == PUT && h5->no_write)
  2382. return NC_EPERM;
  2383. /* If we're in define mode, we can't read or write data. If strict
  2384. * nc3 rules are in effect, return an error, otherwise leave define
  2385. * mode. */
  2386. if (h5->flags & NC_INDEF)
  2387. {
  2388. if (h5->cmode & NC_CLASSIC_MODEL)
  2389. return NC_EINDEFINE;
  2390. if ((retval = nc_enddef(ncid)))
  2391. BAIL(retval);
  2392. }
  2393. #ifdef LOGGING
  2394. {
  2395. int i;
  2396. if (start)
  2397. for (i=0; i<var->ndims; i++)
  2398. LOG((4, "start[%d] %d", i, start[i]));
  2399. if (edges)
  2400. for (i=0; i<var->ndims; i++)
  2401. LOG((4, "edges[%d] %d", i, edges[i]));
  2402. if (stride)
  2403. for (i=0; i<var->ndims; i++)
  2404. LOG((4, "stride[%d] %d", i, stride[i]));
  2405. if (map)
  2406. for (i=0; i<var->ndims; i++)
  2407. LOG((4, "map[%d] %d", i, map[i]));
  2408. }
  2409. #endif /* LOGGING */
  2410. /* The code below was stolen from netcdf-3. Some comments by Ed. */
  2411. maxidim = (int) var->ndims - 1;
  2412. if (maxidim < 0)
  2413. {
  2414. /* The variable is a scalar; consequently, there is only one
  2415. thing to get and only one place to put it. (Why was I
  2416. called?) */
  2417. return pg_var(pg, nc, ncid, varid, xtype, is_long, data);
  2418. }
  2419. /* The variable is an array. */
  2420. {
  2421. int idim;
  2422. size_t *mystart = NULL;
  2423. size_t *myedges;
  2424. size_t *iocount; /* count vector */
  2425. size_t *stop; /* stop indexes */
  2426. size_t *length; /* edge lengths in bytes */
  2427. ptrdiff_t *mystride;
  2428. ptrdiff_t *mymap;
  2429. /* Verify stride argument. */
  2430. for (idim = 0; idim <= maxidim; ++idim)
  2431. {
  2432. if (stride != NULL
  2433. && (stride[idim] == 0
  2434. /* cast needed for braindead systems with signed size_t */
  2435. || (unsigned long) stride[idim] >= X_INT_MAX))
  2436. {
  2437. return NC_ESTRIDE;
  2438. }
  2439. }
  2440. /* The mystart array of pointer info is needed to walk our way
  2441. through the dimensions as specified by the start, edges,
  2442. stride and (gulp!) map parameters. */
  2443. if (!(mystart = (size_t *)calloc((size_t)var->ndims * 7, sizeof(ptrdiff_t))))
  2444. return NC_ENOMEM;
  2445. myedges = mystart + var->ndims;
  2446. iocount = myedges + var->ndims;
  2447. stop = iocount + var->ndims;
  2448. length = stop + var->ndims;
  2449. mystride = (ptrdiff_t *)(length + var->ndims);
  2450. mymap = mystride + var->ndims;
  2451. /* Initialize I/O parameters. */
  2452. for (idim = maxidim; idim >= 0; --idim)
  2453. {
  2454. /* Get start value, use 0 if non provided. */
  2455. mystart[idim] = start != NULL ? start[idim] : 0;
  2456. /* If any edges are 0, return NC_NOERR and forget it. */
  2457. if (edges[idim] == 0)
  2458. {
  2459. retval = NC_NOERR;
  2460. goto done;
  2461. }
  2462. /* If edges not provided, use the current dimlen. */
  2463. if (edges)
  2464. myedges[idim] = edges[idim];
  2465. else
  2466. {
  2467. size_t len;
  2468. if ((retval = nc_inq_dimlen(ncid, var->dimids[idim], &len)))
  2469. goto done;
  2470. myedges[idim] = len - mystart[idim];
  2471. }
  2472. /* If stride not provided, use 1. */
  2473. mystride[idim] = stride != NULL ? stride[idim] : 1;
  2474. /* If map is not provided, do something dark and
  2475. mysterious. */
  2476. if (map)
  2477. mymap[idim] = map[idim];
  2478. else
  2479. mymap[idim] = idim == maxidim ? 1 :
  2480. mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
  2481. iocount[idim] = 1;
  2482. length[idim] = mymap[idim] * myedges[idim];
  2483. stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
  2484. }
  2485. /* Check start, edges */
  2486. for (idim = maxidim; idim >= 0; --idim)
  2487. {
  2488. size_t dimlen;
  2489. if ((retval = nc_inq_dimlen(ncid, var->dimids[idim], &dimlen)))
  2490. goto done;
  2491. /* Don't check unlimited dimension on PUTs. */
  2492. if (pg == PUT)
  2493. {
  2494. int stop = 0, d, num_unlim_dim, unlim_dimids[NC_MAX_DIMS];
  2495. if ((retval = nc_inq_unlimdims(ncid, &num_unlim_dim, unlim_dimids)))
  2496. goto done;
  2497. for (d = 0; d < num_unlim_dim; d++)
  2498. if (var->dimids[idim] == unlim_dimids[d])
  2499. stop++;
  2500. if (stop)
  2501. break;
  2502. }
  2503. LOG((4, "idim=%d mystart[idim]=%d myedge[idim]=%d dimlen=%d",
  2504. idim, mystart[idim], myedges[idim], dimlen));
  2505. if (mystart[idim] >= dimlen)
  2506. {
  2507. retval = NC_EINVALCOORDS;
  2508. goto done;
  2509. }
  2510. if (mystart[idim] + myedges[idim] > dimlen)
  2511. {
  2512. retval = NC_EEDGE;
  2513. goto done;
  2514. }
  2515. }
  2516. /* OK, now we're just getting too fancy... As an optimization,
  2517. adjust I/O parameters when the fastest dimension has unity
  2518. stride both externally and internally. In this case, the user
  2519. could have called a simpler routine
  2520. (i.e. ncvarnc_get_vara_text).*/
  2521. if (mystride[maxidim] == 1
  2522. && mymap[maxidim] == 1)
  2523. {
  2524. iocount[maxidim] = myedges[maxidim];
  2525. mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
  2526. mymap[maxidim] = (ptrdiff_t) length[maxidim];
  2527. }
  2528. /* Perform I/O. Exit when done. */
  2529. for (;;)
  2530. {
  2531. int lretval;
  2532. if (pg == GET)
  2533. lretval = nc4_get_vara(nc, ncid, varid, mystart, iocount, xtype,
  2534. is_long, data);
  2535. else
  2536. lretval = nc4_put_vara(nc, ncid, varid, mystart, iocount, xtype,
  2537. is_long, data);
  2538. if (lretval != NC_NOERR
  2539. && (retval == NC_NOERR || lretval != NC_ERANGE))
  2540. retval = lretval;
  2541. /*
  2542. * The following code permutes through the variable s
  2543. * external start-index space and it s internal address
  2544. * space. At the UPC, this algorithm is commonly
  2545. * called "odometer code".
  2546. */
  2547. idim = maxidim;
  2548. carry:
  2549. data = (char *)data + (mymap[idim] * mem_type_size);
  2550. LOG((4, "data=0x%x mymap[%d]=%d", data, idim, (int)mymap[idim]));
  2551. mystart[idim] += mystride[idim];
  2552. LOG((4, "mystart[%d]=%d length[%d]=%d", idim, (int)mystart[idim],
  2553. idim, (int)length[idim]));
  2554. if (mystart[idim] == stop[idim])
  2555. {
  2556. mystart[idim] = start[idim];
  2557. data = (char *)data - (length[idim] * mem_type_size);
  2558. if (--idim < 0)
  2559. break; /* normal return */
  2560. goto carry;
  2561. }
  2562. } /* I/O loop */
  2563. done:
  2564. free(mystart);
  2565. } /* variable is array */
  2566. exit:
  2567. return retval;
  2568. }
  2569. /* This function will copy data from one buffer to another, in
  2570. accordance with the types. Range errors will be noted, and the fill
  2571. value used (or the default fill value if none is supplied) for
  2572. values that overflow the type.
  2573. I should be able to take this out when HDF5 does the right thing
  2574. with data type conversion.
  2575. Ed Hartnett, 11/15/3
  2576. */
  2577. int
  2578. nc4_convert_type(const void *src, void *dest,
  2579. const nc_type src_type, const nc_type dest_type,
  2580. const size_t len, int *range_error,
  2581. const void *fill_value, int strict_nc3, int src_long,
  2582. int dest_long)
  2583. {
  2584. char *cp, *cp1;
  2585. float *fp, *fp1;
  2586. double *dp, *dp1;
  2587. int *ip, *ip1;
  2588. signed long *lp, *lp1;
  2589. short *sp, *sp1;
  2590. signed char *bp, *bp1;
  2591. unsigned char *ubp, *ubp1;
  2592. unsigned short *usp, *usp1;
  2593. unsigned int *uip, *uip1;
  2594. long long *lip, *lip1;
  2595. unsigned long long *ulip, *ulip1;
  2596. size_t count = 0;
  2597. *range_error = 0;
  2598. LOG((3, "nc4_convert_type: len %d src_type %d dest_type %d src_long %d"
  2599. " dest_long %d", len, src_type, dest_type, src_long, dest_long));
  2600. /* OK, this is ugly. If you can think of anything better, I'm open
  2601. to suggestions!
  2602. Note that we don't use a default fill value for type
  2603. NC_BYTE. This is because Lord Voldemort cast a nofilleramous spell
  2604. at Harry Potter, but it bounced off his scar and hit the netcdf-4
  2605. code.
  2606. */
  2607. switch (src_type)
  2608. {
  2609. case NC_CHAR:
  2610. switch (dest_type)
  2611. {
  2612. case NC_CHAR:
  2613. for (cp = (char *)src, cp1 = dest; count < len; count++)
  2614. *cp1++ = *cp++;
  2615. break;
  2616. default:
  2617. LOG((0, "nc4_convert_type: Uknown destination type."));
  2618. }
  2619. break;
  2620. case NC_BYTE:
  2621. switch (dest_type)
  2622. {
  2623. case NC_BYTE:
  2624. for (bp = (signed char *)src, bp1 = dest; count < len; count++)
  2625. *bp1++ = *bp++;
  2626. break;
  2627. case NC_UBYTE:
  2628. for (bp = (signed char *)src, ubp = dest; count < len; count++)
  2629. {
  2630. if (*bp < 0)
  2631. (*range_error)++;
  2632. *ubp++ = *bp++;
  2633. }
  2634. break;
  2635. case NC_SHORT:
  2636. for (bp = (signed char *)src, sp = dest; count < len; count++)
  2637. *sp++ = *bp++;
  2638. break;
  2639. case NC_USHORT:
  2640. for (bp = (signed char *)src, usp = dest; count < len; count++)
  2641. {
  2642. if (*bp < 0)
  2643. (*range_error)++;
  2644. *usp++ = *bp++;
  2645. }
  2646. break;
  2647. case NC_INT:
  2648. if (dest_long)
  2649. {
  2650. for (bp = (signed char *)src, lp = dest; count < len; count++)
  2651. *lp++ = *bp++;
  2652. break;
  2653. }
  2654. else
  2655. {
  2656. for (bp = (signed char *)src, ip = dest; count < len; count++)
  2657. *ip++ = *bp++;
  2658. break;
  2659. }
  2660. case NC_UINT:
  2661. for (bp = (signed char *)src, uip = dest; count < len; count++)
  2662. {
  2663. if (*bp < 0)
  2664. (*range_error)++;
  2665. *uip++ = *bp++;
  2666. }
  2667. break;
  2668. case NC_INT64:
  2669. for (bp = (signed char *)src, lip = dest; count < len; count++)
  2670. *lip++ = *bp++;
  2671. break;
  2672. case NC_UINT64:
  2673. for (bp = (signed char *)src, ulip = dest; count < len; count++)
  2674. {
  2675. if (*bp < 0)
  2676. (*range_error)++;
  2677. *ulip++ = *bp++;
  2678. }
  2679. break;
  2680. case NC_FLOAT:
  2681. for (bp = (signed char *)src, fp = dest; count < len; count++)
  2682. *fp++ = *bp++;
  2683. break;
  2684. case NC_DOUBLE:
  2685. for (bp = (signed char *)src, dp = dest; count < len; count++)
  2686. *dp++ = *bp++;
  2687. break;
  2688. default:
  2689. LOG((0, "nc4_convert_type: unexpected dest type. "
  2690. "src_type %d, dest_type %d", src_type, dest_type));
  2691. return NC_EBADTYPE;
  2692. }
  2693. break;
  2694. case NC_UBYTE:
  2695. switch (dest_type)
  2696. {
  2697. case NC_BYTE:
  2698. for (ubp = (unsigned char *)src, bp = dest; count < len; count++)
  2699. {
  2700. if (!strict_nc3 && *ubp > X_SCHAR_MAX)
  2701. (*range_error)++;
  2702. *bp++ = *ubp++;
  2703. }
  2704. break;
  2705. case NC_SHORT:
  2706. for (ubp = (unsigned char *)src, sp = dest; count < len; count++)
  2707. *sp++ = *ubp++;
  2708. break;
  2709. case NC_UBYTE:
  2710. for (ubp = (unsigned char *)src, ubp1 = dest; count < len; count++)
  2711. *ubp1++ = *ubp++;
  2712. break;
  2713. case NC_USHORT:
  2714. for (ubp = (unsigned char *)src, usp = dest; count < len; count++)
  2715. *usp++ = *ubp++;
  2716. break;
  2717. case NC_INT:
  2718. if (dest_long)
  2719. {
  2720. for (ubp = (unsigned char *)src, lp = dest; count < len; count++)
  2721. *lp++ = *ubp++;
  2722. break;
  2723. }
  2724. else
  2725. {
  2726. for (ubp = (unsigned char *)src, ip = dest; count < len; count++)
  2727. *ip++ = *ubp++;
  2728. break;
  2729. }
  2730. case NC_UINT:
  2731. for (ubp = (unsigned char *)src, uip = dest; count < len; count++)
  2732. *uip++ = *ubp++;
  2733. break;
  2734. case NC_INT64:
  2735. for (ubp = (unsigned char *)src, lip = dest; count < len; count++)
  2736. *lip++ = *ubp++;
  2737. break;
  2738. case NC_UINT64:
  2739. for (ubp = (unsigned char *)src, ulip = dest; count < len; count++)
  2740. *ulip++ = *ubp++;
  2741. break;
  2742. case NC_FLOAT:
  2743. for (ubp = (unsigned char *)src, fp = dest; count < len; count++)
  2744. *fp++ = *ubp++;
  2745. break;
  2746. case NC_DOUBLE:
  2747. for (ubp = (unsigned char *)src, dp = dest; count < len; count++)
  2748. *dp++ = *ubp++;
  2749. break;
  2750. default:
  2751. LOG((0, "nc4_convert_type: unexpected dest type. "
  2752. "src_type %d, dest_type %d", src_type, dest_type));
  2753. return NC_EBADTYPE;
  2754. }
  2755. break;
  2756. case NC_SHORT:
  2757. switch (dest_type)
  2758. {
  2759. case NC_UBYTE:
  2760. for (sp = (short *)src, ubp = dest; count < len; count++)
  2761. {
  2762. if (*sp > X_UCHAR_MAX || *sp < 0)
  2763. (*range_error)++;
  2764. *ubp++ = *sp++;
  2765. }
  2766. break;
  2767. case NC_BYTE:
  2768. for (sp = (short *)src, bp = dest; count < len; count++)
  2769. {
  2770. if (*sp > X_SCHAR_MAX || *sp < X_SCHAR_MIN)
  2771. (*range_error)++;
  2772. *bp++ = *sp++;
  2773. }
  2774. break;
  2775. case NC_SHORT:
  2776. for (sp = (short *)src, sp1 = dest; count < len; count++)
  2777. *sp1++ = *sp++;
  2778. break;
  2779. case NC_USHORT:
  2780. for (sp = (short *)src, usp = dest; count < len; count++)
  2781. {
  2782. if (*sp < 0)
  2783. (*range_error)++;
  2784. *usp++ = *sp++;
  2785. }
  2786. break;
  2787. case NC_INT:
  2788. if (dest_long)
  2789. for (sp = (short *)src, lp = dest; count < len; count++)
  2790. *lp++ = *sp++;
  2791. else
  2792. for (sp = (short *)src, ip = dest; count < len; count++)
  2793. *ip++ = *sp++;
  2794. break;
  2795. case NC_UINT:
  2796. for (sp = (short *)src, uip = dest; count < len; count++)
  2797. {
  2798. if (*sp < 0)
  2799. (*range_error)++;
  2800. *uip++ = *sp++;
  2801. }
  2802. break;
  2803. case NC_INT64:
  2804. for (sp = (short *)src, lip = dest; count < len; count++)
  2805. *lip++ = *sp++;
  2806. break;
  2807. case NC_UINT64:
  2808. for (sp = (short *)src, ulip = dest; count < len; count++)
  2809. {
  2810. if (*sp < 0)
  2811. (*range_error)++;
  2812. *ulip++ = *sp++;
  2813. }
  2814. break;
  2815. case NC_FLOAT:
  2816. for (sp = (short *)src, fp = dest; count < len; count++)
  2817. *fp++ = *sp++;
  2818. break;
  2819. case NC_DOUBLE:
  2820. for (sp = (short *)src, dp = dest; count < len; count++)
  2821. *dp++ = *sp++;
  2822. break;
  2823. default:
  2824. LOG((0, "nc4_convert_type: unexpected dest type. "
  2825. "src_type %d, dest_type %d", src_type, dest_type));
  2826. return NC_EBADTYPE;
  2827. }
  2828. break;
  2829. case NC_USHORT:
  2830. switch (dest_type)
  2831. {
  2832. case NC_UBYTE:
  2833. for (usp = (unsigned short *)src, ubp = dest; count < len; count++)
  2834. {
  2835. if (*usp > X_UCHAR_MAX)
  2836. (*range_error)++;
  2837. *ubp++ = *usp++;
  2838. }
  2839. break;
  2840. case NC_BYTE:
  2841. for (usp = (unsigned short *)src, bp = dest; count < len; count++)
  2842. {
  2843. if (*usp > X_SCHAR_MAX)
  2844. (*range_error)++;
  2845. *bp++ = *usp++;
  2846. }
  2847. break;
  2848. case NC_SHORT:
  2849. for (usp = (unsigned short *)src, sp = dest; count < len; count++)
  2850. {
  2851. if (*usp > X_SHORT_MAX)
  2852. (*range_error)++;
  2853. *sp++ = *usp++;
  2854. }
  2855. break;
  2856. case NC_USHORT:
  2857. for (usp = (unsigned short *)src, usp1 = dest; count < len; count++)
  2858. *usp1++ = *usp++;
  2859. break;
  2860. case NC_INT:
  2861. if (dest_long)
  2862. for (usp = (unsigned short *)src, lp = dest; count < len; count++)
  2863. *lp++ = *usp++;
  2864. else
  2865. for (usp = (unsigned short *)src, ip = dest; count < len; count++)
  2866. *ip++ = *usp++;
  2867. break;
  2868. case NC_UINT:
  2869. for (usp = (unsigned short *)src, uip = dest; count < len; count++)
  2870. *uip++ = *usp++;
  2871. break;
  2872. case NC_INT64:
  2873. for (usp = (unsigned short *)src, lip = dest; count < len; count++)
  2874. *lip++ = *usp++;
  2875. break;
  2876. case NC_UINT64:
  2877. for (usp = (unsigned short *)src, ulip = dest; count < len; count++)
  2878. *ulip++ = *usp++;
  2879. break;
  2880. case NC_FLOAT:
  2881. for (usp = (unsigned short *)src, fp = dest; count < len; count++)
  2882. *fp++ = *usp++;
  2883. break;
  2884. case NC_DOUBLE:
  2885. for (usp = (unsigned short *)src, dp = dest; count < len; count++)
  2886. *dp++ = *usp++;
  2887. break;
  2888. default:
  2889. LOG((0, "nc4_convert_type: unexpected dest type. "
  2890. "src_type %d, dest_type %d", src_type, dest_type));
  2891. return NC_EBADTYPE;
  2892. }
  2893. break;
  2894. case NC_INT:
  2895. if (src_long)
  2896. {
  2897. switch (dest_type)
  2898. {
  2899. case NC_UBYTE:
  2900. for (lp = (long *)src, ubp = dest; count < len; count++)
  2901. {
  2902. if (*lp > X_UCHAR_MAX || *lp < 0)
  2903. (*range_error)++;
  2904. *ubp++ = *lp++;
  2905. }
  2906. break;
  2907. case NC_BYTE:
  2908. for (lp = (long *)src, bp = dest; count < len; count++)
  2909. {
  2910. if (*lp > X_SCHAR_MAX || *lp < X_SCHAR_MIN)
  2911. (*range_error)++;
  2912. *bp++ = *lp++;
  2913. }
  2914. break;
  2915. case NC_SHORT:
  2916. for (lp = (long *)src, sp = dest; count < len; count++)
  2917. {
  2918. if (*lp > X_SHORT_MAX || *lp < X_SHORT_MIN)
  2919. (*range_error)++;
  2920. *sp++ = *lp++;
  2921. }
  2922. break;
  2923. case NC_USHORT:
  2924. for (lp = (long *)src, usp = dest; count < len; count++)
  2925. {
  2926. if (*lp > X_USHORT_MAX || *lp < 0)
  2927. (*range_error)++;
  2928. *usp++ = *lp++;
  2929. }
  2930. break;
  2931. case NC_INT: /* src is long */
  2932. if (dest_long)
  2933. {
  2934. for (lp = (long *)src, lp1 = dest; count < len; count++)
  2935. {
  2936. if (*lp > X_LONG_MAX || *lp < X_LONG_MIN)
  2937. (*range_error)++;
  2938. *lp1++ = *lp++;
  2939. }
  2940. }
  2941. else /* dest is int */
  2942. {
  2943. for (lp = (long *)src, ip = dest; count < len; count++)
  2944. {
  2945. if (*lp > X_INT_MAX || *lp < X_INT_MIN)
  2946. (*range_error)++;
  2947. *ip++ = *lp++;
  2948. }
  2949. }
  2950. break;
  2951. case NC_UINT:
  2952. for (lp = (long *)src, uip = dest; count < len; count++)
  2953. {
  2954. if (*lp > X_UINT_MAX || *lp < 0)
  2955. (*range_error)++;
  2956. *uip++ = *lp++;
  2957. }
  2958. break;
  2959. case NC_INT64:
  2960. for (lp = (long *)src, lip = dest; count < len; count++)
  2961. *lip++ = *lp++;
  2962. break;
  2963. case NC_UINT64:
  2964. for (lp = (long *)src, ulip = dest; count < len; count++)
  2965. {
  2966. if (*lp < 0)
  2967. (*range_error)++;
  2968. *ulip++ = *lp++;
  2969. }
  2970. break;
  2971. case NC_FLOAT:
  2972. for (lp = (long *)src, fp = dest; count < len; count++)
  2973. *fp++ = *lp++;
  2974. break;
  2975. case NC_DOUBLE:
  2976. for (lp = (long *)src, dp = dest; count < len; count++)
  2977. *dp++ = *lp++;
  2978. break;
  2979. default:
  2980. LOG((0, "nc4_convert_type: unexpected dest type. "
  2981. "src_type %d, dest_type %d", src_type, dest_type));
  2982. return NC_EBADTYPE;
  2983. }
  2984. }
  2985. else
  2986. {
  2987. switch (dest_type)
  2988. {
  2989. case NC_UBYTE:
  2990. for (ip = (int *)src, ubp = dest; count < len; count++)
  2991. {
  2992. if (*ip > X_UCHAR_MAX || *ip < 0)
  2993. (*range_error)++;
  2994. *ubp++ = *ip++;
  2995. }
  2996. break;
  2997. case NC_BYTE:
  2998. for (ip = (int *)src, bp = dest; count < len; count++)
  2999. {
  3000. if (*ip > X_SCHAR_MAX || *ip < X_SCHAR_MIN)
  3001. (*range_error)++;
  3002. *bp++ = *ip++;
  3003. }
  3004. break;
  3005. case NC_SHORT:
  3006. for (ip = (int *)src, sp = dest; count < len; count++)
  3007. {
  3008. if (*ip > X_SHORT_MAX || *ip < X_SHORT_MIN)
  3009. (*range_error)++;
  3010. *sp++ = *ip++;
  3011. }
  3012. break;
  3013. case NC_USHORT:
  3014. for (ip = (int *)src, usp = dest; count < len; count++)
  3015. {
  3016. if (*ip > X_USHORT_MAX || *ip < 0)
  3017. (*range_error)++;
  3018. *usp++ = *ip++;
  3019. }
  3020. break;
  3021. case NC_INT: /* src is int */
  3022. if (dest_long)
  3023. {
  3024. for (ip = (int *)src, lp1 = dest; count < len; count++)
  3025. {
  3026. if (*ip > X_LONG_MAX || *ip < X_LONG_MIN)
  3027. (*range_error)++;
  3028. *lp1++ = *ip++;
  3029. }
  3030. }
  3031. else /* dest is int */
  3032. {
  3033. for (ip = (int *)src, ip1 = dest; count < len; count++)
  3034. {
  3035. if (*ip > X_INT_MAX || *ip < X_INT_MIN)
  3036. (*range_error)++;
  3037. *ip1++ = *ip++;
  3038. }
  3039. }
  3040. break;
  3041. case NC_UINT:
  3042. for (ip = (int *)src, uip = dest; count < len; count++)
  3043. {
  3044. if (*ip > X_UINT_MAX || *ip < 0)
  3045. (*range_error)++;
  3046. *uip++ = *ip++;
  3047. }
  3048. break;
  3049. case NC_INT64:
  3050. for (ip = (int *)src, lip = dest; count < len; count++)
  3051. *lip++ = *ip++;
  3052. break;
  3053. case NC_UINT64:
  3054. for (ip = (int *)src, ulip = dest; count < len; count++)
  3055. {
  3056. if (*ip < 0)
  3057. (*range_error)++;
  3058. *ulip++ = *ip++;
  3059. }
  3060. break;
  3061. case NC_FLOAT:
  3062. for (ip = (int *)src, fp = dest; count < len; count++)
  3063. *fp++ = *ip++;
  3064. break;
  3065. case NC_DOUBLE:
  3066. for (ip = (int *)src, dp = dest; count < len; count++)
  3067. *dp++ = *ip++;
  3068. break;
  3069. default:
  3070. LOG((0, "nc4_convert_type: unexpected dest type. "
  3071. "src_type %d, dest_type %d", src_type, dest_type));
  3072. return NC_EBADTYPE;
  3073. }
  3074. }
  3075. break;
  3076. case NC_UINT:
  3077. switch (dest_type)
  3078. {
  3079. case NC_UBYTE:
  3080. for (uip = (unsigned int *)src, ubp = dest; count < len; count++)
  3081. {
  3082. if (*uip > X_UCHAR_MAX)
  3083. (*range_error)++;
  3084. *ubp++ = *uip++;
  3085. }
  3086. break;
  3087. case NC_BYTE:
  3088. for (uip = (unsigned int *)src, bp = dest; count < len; count++)
  3089. {
  3090. if (*uip > X_SCHAR_MAX)
  3091. (*range_error)++;
  3092. *bp++ = *uip++;
  3093. }
  3094. break;
  3095. case NC_SHORT:
  3096. for (uip = (unsigned int *)src, sp = dest; count < len; count++)
  3097. {
  3098. if (*uip > X_SHORT_MAX)
  3099. (*range_error)++;
  3100. *sp++ = *uip++;
  3101. }
  3102. break;
  3103. case NC_USHORT:
  3104. for (uip = (unsigned int *)src, usp = dest; count < len; count++)
  3105. {
  3106. if (*uip > X_USHORT_MAX)
  3107. (*range_error)++;
  3108. *usp++ = *uip++;
  3109. }
  3110. break;
  3111. case NC_INT:
  3112. if (dest_long)
  3113. for (uip = (unsigned int *)src, lp = dest; count < len; count++)
  3114. {
  3115. if (*uip > X_LONG_MAX)
  3116. (*range_error)++;
  3117. *lp++ = *uip++;
  3118. }
  3119. else
  3120. for (uip = (unsigned int *)src, ip = dest; count < len; count++)
  3121. {
  3122. if (*uip > X_INT_MAX)
  3123. (*range_error)++;
  3124. *ip++ = *uip++;
  3125. }
  3126. break;
  3127. case NC_UINT:
  3128. for (uip = (unsigned int *)src, uip1 = dest; count < len; count++)
  3129. {
  3130. if (*uip > X_UINT_MAX)
  3131. (*range_error)++;
  3132. *uip1++ = *uip++;
  3133. }
  3134. break;
  3135. case NC_INT64:
  3136. for (uip = (unsigned int *)src, lip = dest; count < len; count++)
  3137. *lip++ = *uip++;
  3138. break;
  3139. case NC_UINT64:
  3140. for (uip = (unsigned int *)src, ulip = dest; count < len; count++)
  3141. *ulip++ = *uip++;
  3142. break;
  3143. case NC_FLOAT:
  3144. for (uip = (unsigned int *)src, fp = dest; count < len; count++)
  3145. *fp++ = *uip++;
  3146. break;
  3147. case NC_DOUBLE:
  3148. for (uip = (unsigned int *)src, dp = dest; count < len; count++)
  3149. *dp++ = *uip++;
  3150. break;
  3151. default:
  3152. LOG((0, "nc4_convert_type: unexpected dest type. "
  3153. "src_type %d, dest_type %d", src_type, dest_type));
  3154. return NC_EBADTYPE;
  3155. }
  3156. break;
  3157. case NC_INT64:
  3158. switch (dest_type)
  3159. {
  3160. case NC_UBYTE:
  3161. for (lip = (long long *)src, ubp = dest; count < len; count++)
  3162. {
  3163. if (*lip > X_UCHAR_MAX || *lip < 0)
  3164. (*range_error)++;
  3165. *ubp++ = *lip++;
  3166. }
  3167. break;
  3168. case NC_BYTE:
  3169. for (lip = (long long *)src, bp = dest; count < len; count++)
  3170. {
  3171. if (*lip > X_SCHAR_MAX || *lip < X_SCHAR_MIN)
  3172. (*range_error)++;
  3173. *bp++ = *lip++;
  3174. }
  3175. break;
  3176. case NC_SHORT:
  3177. for (lip = (long long *)src, sp = dest; count < len; count++)
  3178. {
  3179. if (*lip > X_SHORT_MAX || *lip < X_SHORT_MIN)
  3180. (*range_error)++;
  3181. *sp++ = *lip++;
  3182. }
  3183. break;
  3184. case NC_USHORT:
  3185. for (lip = (long long *)src, usp = dest; count < len; count++)
  3186. {
  3187. if (*lip > X_USHORT_MAX || *lip < 0)
  3188. (*range_error)++;
  3189. *usp++ = *lip++;
  3190. }
  3191. break;
  3192. case NC_UINT:
  3193. for (lip = (long long *)src, uip = dest; count < len; count++)
  3194. {
  3195. if (*lip > X_UINT_MAX || *lip < 0)
  3196. (*range_error)++;
  3197. *uip++ = *lip++;
  3198. }
  3199. break;
  3200. case NC_INT:
  3201. if (dest_long)
  3202. for (lip = (long long *)src, lp = dest; count < len; count++)
  3203. {
  3204. if (*lip > X_LONG_MAX || *lip < X_LONG_MIN)
  3205. (*range_error)++;
  3206. *lp++ = *lip++;
  3207. }
  3208. else
  3209. for (lip = (long long *)src, ip = dest; count < len; count++)
  3210. {
  3211. if (*lip > X_INT_MAX || *lip < X_INT_MIN)
  3212. (*range_error)++;
  3213. *ip++ = *lip++;
  3214. }
  3215. break;
  3216. case NC_INT64:
  3217. for (lip = (long long *)src, lip1 = dest; count < len; count++)
  3218. *lip1++ = *lip++;
  3219. break;
  3220. case NC_UINT64:
  3221. for (lip = (long long *)src, ulip = dest; count < len; count++)
  3222. {
  3223. if (*lip < 0)
  3224. (*range_error)++;
  3225. *ulip++ = *lip++;
  3226. }
  3227. break;
  3228. case NC_FLOAT:
  3229. for (lip = (long long *)src, fp = dest; count < len; count++)
  3230. *fp++ = *lip++;
  3231. break;
  3232. case NC_DOUBLE:
  3233. for (lip = (long long *)src, dp = dest; count < len; count++)
  3234. *dp++ = *lip++;
  3235. break;
  3236. default:
  3237. LOG((0, "nc4_convert_type: unexpected dest type. "
  3238. "src_type %d, dest_type %d", src_type, dest_type));
  3239. return NC_EBADTYPE;
  3240. }
  3241. break;
  3242. case NC_UINT64:
  3243. switch (dest_type)
  3244. {
  3245. case NC_UBYTE:
  3246. for (ulip = (unsigned long long *)src, ubp = dest; count < len; count++)
  3247. {
  3248. if (*ulip > X_UCHAR_MAX)
  3249. (*range_error)++;
  3250. *ubp++ = *ulip++;
  3251. }
  3252. break;
  3253. case NC_BYTE:
  3254. for (ulip = (unsigned long long *)src, bp = dest; count < len; count++)
  3255. {
  3256. if (*ulip > X_SCHAR_MAX)
  3257. (*range_error)++;
  3258. *bp++ = *ulip++;
  3259. }
  3260. break;
  3261. case NC_SHORT:
  3262. for (ulip = (unsigned long long *)src, sp = dest; count < len; count++)
  3263. {
  3264. if (*ulip > X_SHORT_MAX)
  3265. (*range_error)++;
  3266. *sp++ = *ulip++;
  3267. }
  3268. break;
  3269. case NC_USHORT:
  3270. for (ulip = (unsigned long long *)src, usp = dest; count < len; count++)
  3271. {
  3272. if (*ulip > X_USHORT_MAX)
  3273. (*range_error)++;
  3274. *usp++ = *ulip++;
  3275. }
  3276. break;
  3277. case NC_UINT:
  3278. for (ulip = (unsigned long long *)src, uip = dest; count < len; count++)
  3279. {
  3280. if (*ulip > X_UINT_MAX)
  3281. (*range_error)++;
  3282. *uip++ = *ulip++;
  3283. }
  3284. break;
  3285. case NC_INT:
  3286. if (dest_long)
  3287. for (ulip = (unsigned long long *)src, lp = dest; count < len; count++)
  3288. {
  3289. if (*ulip > X_LONG_MAX)
  3290. (*range_error)++;
  3291. *lp++ = *ulip++;
  3292. }
  3293. else
  3294. for (ulip = (unsigned long long *)src, ip = dest; count < len; count++)
  3295. {
  3296. if (*ulip > X_INT_MAX)
  3297. (*range_error)++;
  3298. *ip++ = *ulip++;
  3299. }
  3300. break;
  3301. case NC_INT64:
  3302. for (ulip = (unsigned long long *)src, lip = dest; count < len; count++)
  3303. {
  3304. if (*ulip > X_INT64_MAX)
  3305. (*range_error)++;
  3306. *lip++ = *ulip++;
  3307. }
  3308. break;
  3309. case NC_UINT64:
  3310. for (ulip = (unsigned long long *)src, ulip1 = dest; count < len; count++)
  3311. *ulip1++ = *ulip++;
  3312. break;
  3313. case NC_FLOAT:
  3314. for (ulip = (unsigned long long *)src, fp = dest; count < len; count++)
  3315. *fp++ = *ulip++;
  3316. break;
  3317. case NC_DOUBLE:
  3318. for (ulip = (unsigned long long *)src, dp = dest; count < len; count++)
  3319. *dp++ = *ulip++;
  3320. break;
  3321. default:
  3322. LOG((0, "nc4_convert_type: unexpected dest type. "
  3323. "src_type %d, dest_type %d", src_type, dest_type));
  3324. return NC_EBADTYPE;
  3325. }
  3326. break;
  3327. case NC_FLOAT:
  3328. switch (dest_type)
  3329. {
  3330. case NC_UBYTE:
  3331. for (fp = (float *)src, ubp = dest; count < len; count++)
  3332. {
  3333. if (*fp > X_UCHAR_MAX || *fp < 0)
  3334. (*range_error)++;
  3335. *ubp++ = *fp++;
  3336. }
  3337. break;
  3338. case NC_BYTE:
  3339. for (fp = (float *)src, bp = dest; count < len; count++)
  3340. {
  3341. if (*fp > (double)X_SCHAR_MAX || *fp < (double)X_SCHAR_MIN)
  3342. (*range_error)++;
  3343. *bp++ = *fp++;
  3344. }
  3345. break;
  3346. case NC_SHORT:
  3347. for (fp = (float *)src, sp = dest; count < len; count++)
  3348. {
  3349. if (*fp > (double)X_SHORT_MAX || *fp < (double)X_SHORT_MIN)
  3350. (*range_error)++;
  3351. *sp++ = *fp++;
  3352. }
  3353. break;
  3354. case NC_USHORT:
  3355. for (fp = (float *)src, usp = dest; count < len; count++)
  3356. {
  3357. if (*fp > X_USHORT_MAX || *fp < 0)
  3358. (*range_error)++;
  3359. *usp++ = *fp++;
  3360. }
  3361. break;
  3362. case NC_UINT:
  3363. for (fp = (float *)src, uip = dest; count < len; count++)
  3364. {
  3365. if (*fp > X_UINT_MAX || *fp < 0)
  3366. (*range_error)++;
  3367. *uip++ = *fp++;
  3368. }
  3369. break;
  3370. case NC_INT:
  3371. if (dest_long)
  3372. for (fp = (float *)src, lp = dest; count < len; count++)
  3373. {
  3374. if (*fp > (double)X_LONG_MAX || *fp < (double)X_LONG_MIN)
  3375. (*range_error)++;
  3376. *lp++ = *fp++;
  3377. }
  3378. else
  3379. for (fp = (float *)src, ip = dest; count < len; count++)
  3380. {
  3381. if (*fp > (double)X_INT_MAX || *fp < (double)X_INT_MIN)
  3382. (*range_error)++;
  3383. *ip++ = *fp++;
  3384. }
  3385. break;
  3386. case NC_INT64:
  3387. for (fp = (float *)src, lip = dest; count < len; count++)
  3388. {
  3389. if (*fp > X_INT64_MAX || *fp <X_INT64_MIN)
  3390. (*range_error)++;
  3391. *lip++ = *fp++;
  3392. }
  3393. break;
  3394. case NC_UINT64:
  3395. for (fp = (float *)src, lip = dest; count < len; count++)
  3396. {
  3397. if (*fp > X_UINT64_MAX || *fp < 0)
  3398. (*range_error)++;
  3399. *lip++ = *fp++;
  3400. }
  3401. break;
  3402. case NC_FLOAT:
  3403. for (fp = (float *)src, fp1 = dest; count < len; count++)
  3404. {
  3405. /* if (*fp > X_FLOAT_MAX || *fp < X_FLOAT_MIN)
  3406. (*range_error)++;*/
  3407. *fp1++ = *fp++;
  3408. }
  3409. break;
  3410. case NC_DOUBLE:
  3411. for (fp = (float *)src, dp = dest; count < len; count++)
  3412. *dp++ = *fp++;
  3413. break;
  3414. default:
  3415. LOG((0, "nc4_convert_type: unexpected dest type. "
  3416. "src_type %d, dest_type %d", src_type, dest_type));
  3417. return NC_EBADTYPE;
  3418. }
  3419. break;
  3420. case NC_DOUBLE:
  3421. switch (dest_type)
  3422. {
  3423. case NC_UBYTE:
  3424. for (dp = (double *)src, ubp = dest; count < len; count++)
  3425. {
  3426. if (*dp > X_UCHAR_MAX || *dp < 0)
  3427. (*range_error)++;
  3428. *ubp++ = *dp++;
  3429. }
  3430. break;
  3431. case NC_BYTE:
  3432. for (dp = (double *)src, bp = dest; count < len; count++)
  3433. {
  3434. if (*dp > X_SCHAR_MAX || *dp < X_SCHAR_MIN)
  3435. (*range_error)++;
  3436. *bp++ = *dp++;
  3437. }
  3438. break;
  3439. case NC_SHORT:
  3440. for (dp = (double *)src, sp = dest; count < len; count++)
  3441. {
  3442. if (*dp > X_SHORT_MAX || *dp < X_SHORT_MIN)
  3443. (*range_error)++;
  3444. *sp++ = *dp++;
  3445. }
  3446. break;
  3447. case NC_USHORT:
  3448. for (dp = (double *)src, usp = dest; count < len; count++)
  3449. {
  3450. if (*dp > X_USHORT_MAX || *dp < 0)
  3451. (*range_error)++;
  3452. *usp++ = *dp++;
  3453. }
  3454. break;
  3455. case NC_UINT:
  3456. for (dp = (double *)src, uip = dest; count < len; count++)
  3457. {
  3458. if (*dp > X_UINT_MAX || *dp < 0)
  3459. (*range_error)++;
  3460. *uip++ = *dp++;
  3461. }
  3462. break;
  3463. case NC_INT:
  3464. if (dest_long)
  3465. for (dp = (double *)src, lp = dest; count < len; count++)
  3466. {
  3467. if (*dp > X_LONG_MAX || *dp < X_LONG_MIN)
  3468. (*range_error)++;
  3469. *lp++ = *dp++;
  3470. }
  3471. else
  3472. for (dp = (double *)src, ip = dest; count < len; count++)
  3473. {
  3474. if (*dp > X_INT_MAX || *dp < X_INT_MIN)
  3475. (*range_error)++;
  3476. *ip++ = *dp++;
  3477. }
  3478. break;
  3479. case NC_INT64:
  3480. for (dp = (double *)src, lip = dest; count < len; count++)
  3481. {
  3482. if (*dp > X_INT64_MAX || *dp < X_INT64_MIN)
  3483. (*range_error)++;
  3484. *lip++ = *dp++;
  3485. }
  3486. break;
  3487. case NC_UINT64:
  3488. for (dp = (double *)src, lip = dest; count < len; count++)
  3489. {
  3490. if (*dp > X_UINT64_MAX || *dp < 0)
  3491. (*range_error)++;
  3492. *lip++ = *dp++;
  3493. }
  3494. break;
  3495. case NC_FLOAT:
  3496. for (dp = (double *)src, fp = dest; count < len; count++)
  3497. {
  3498. if (*dp > X_FLOAT_MAX || *dp < X_FLOAT_MIN)
  3499. (*range_error)++;
  3500. *fp++ = *dp++;
  3501. }
  3502. break;
  3503. case NC_DOUBLE:
  3504. for (dp = (double *)src, dp1 = dest; count < len; count++)
  3505. {
  3506. /* if (*dp > X_DOUBLE_MAX || *dp < X_DOUBLE_MIN) */
  3507. /* (*range_error)++; */
  3508. *dp1++ = *dp++;
  3509. }
  3510. break;
  3511. default:
  3512. LOG((0, "nc4_convert_type: unexpected dest type. "
  3513. "src_type %d, dest_type %d", src_type, dest_type));
  3514. return NC_EBADTYPE;
  3515. }
  3516. break;
  3517. default:
  3518. LOG((0, "nc4_convert_type: unexpected src type. "
  3519. "src_type %d, dest_type %d", src_type, dest_type));
  3520. return NC_EBADTYPE;
  3521. }
  3522. return NC_NOERR;
  3523. }
  3524. /* In our first pass through the data, we may have encountered
  3525. * variables before encountering their dimscales, so go through the
  3526. * vars in this file and make sure we've got a dimid for each. */
  3527. int
  3528. nc4_rec_match_dimscales(NC_GRP_INFO_T *grp)
  3529. {
  3530. NC_GRP_INFO_T *g;
  3531. NC_VAR_INFO_T *var;
  3532. NC_DIM_INFO_T *dim;
  3533. H5G_stat_t statbuf;
  3534. int d, finished;
  3535. int retval = NC_NOERR;
  3536. assert(grp && grp->name);
  3537. LOG((4, "nc4_rec_match_dimscales: grp->name %s", grp->name));
  3538. /* Perform var dimscale match for child groups. */
  3539. for (g = grp->children; g; g = g->next)
  3540. if ((retval = nc4_rec_match_dimscales(g)))
  3541. return retval;
  3542. /* Check all the vars in this group. If they have dimscale info,
  3543. * try and find a dimension for them. */
  3544. for (var = grp->var; var; var = var->next)
  3545. {
  3546. /* Are there dimscales for this variable? */
  3547. if (var->dimscale_hdf5_objids)
  3548. {
  3549. for (d = 0; d < var->ndims; d++)
  3550. {
  3551. LOG((5, "nc4_rec_match_dimscales: var %s has dimscale info...", var->name));
  3552. /* Look at all the dims in this group to see if they
  3553. * match. */
  3554. finished = 0;
  3555. for (g = grp; g && !finished; g = g->parent)
  3556. {
  3557. for (dim = g->dim; dim; dim = dim->next)
  3558. {
  3559. if (!dim->hdf_dimscaleid)
  3560. return NC_EDIMMETA;
  3561. if (H5Gget_objinfo(dim->hdf_dimscaleid, ".", 1, &statbuf) < 0)
  3562. return NC_EHDFERR;
  3563. if (var->dimscale_hdf5_objids[d].fileno[0] == statbuf.fileno[0] &&
  3564. var->dimscale_hdf5_objids[d].objno[0] == statbuf.objno[0] &&
  3565. var->dimscale_hdf5_objids[d].fileno[1] == statbuf.fileno[1] &&
  3566. var->dimscale_hdf5_objids[d].objno[1] == statbuf.objno[1])
  3567. {
  3568. LOG((4, "nc4_rec_match_dimscales: for dimension %d, found dim %s",
  3569. d, dim->name));
  3570. var->dimids[d] = dim->dimid;
  3571. finished++;
  3572. break;
  3573. }
  3574. } /* next dim */
  3575. } /* next grp */
  3576. LOG((5, "nc4_rec_match_dimscales: dimid for this dimscale is %d", var->xtype));
  3577. } /* next var->dim */
  3578. }
  3579. else
  3580. {
  3581. if (!var->dimscale)
  3582. {
  3583. hid_t spaceid = 0;
  3584. hsize_t *h5dimlen = NULL, *h5dimlenmax = NULL;
  3585. int dataset_ndims;
  3586. /* No dimscales for this var! Invent phony dimensions. */
  3587. /* Find the space information for this dimension. */
  3588. if ((spaceid = H5Dget_space(var->hdf_datasetid)) < 0)
  3589. return NC_EHDFERR;
  3590. #ifdef EXTRA_TESTS
  3591. num_spaces++;
  3592. #endif
  3593. /* Get the len of each dim in the space. */
  3594. if (var->ndims)
  3595. {
  3596. if (!(h5dimlen = malloc(var->ndims * sizeof(hsize_t))))
  3597. return NC_ENOMEM;
  3598. if (!(h5dimlenmax = malloc(var->ndims * sizeof(hsize_t))))
  3599. return NC_ENOMEM;
  3600. if ((dataset_ndims = H5Sget_simple_extent_dims(spaceid, h5dimlen,
  3601. h5dimlenmax)) < 0)
  3602. return NC_EHDFERR;
  3603. if (dataset_ndims != var->ndims)
  3604. return NC_EHDFERR;
  3605. }
  3606. else
  3607. {
  3608. /* Make sure it's scalar. */
  3609. if (H5Sget_simple_extent_type(spaceid) != H5S_SCALAR)
  3610. return NC_EHDFERR;
  3611. }
  3612. /* Release the space object. */
  3613. if (H5Sclose(spaceid) < 0)
  3614. return NC_EHDFERR;
  3615. #ifdef EXTRA_TESTS
  3616. num_spaces--;
  3617. #endif
  3618. /* Create a phony dimension for each dimension in the
  3619. * dataset, unless there already is one the correct
  3620. * size. */
  3621. for (d = 0; d < var->ndims; d++)
  3622. {
  3623. NC_DIM_INFO_T *dim = NULL;
  3624. char phony_dim_name[NC_MAX_NAME + 1];
  3625. /* Is there already a phony dimension of the correct size? */
  3626. for (dim = grp->dim; dim; dim = dim->next)
  3627. if ((dim->len == h5dimlen[d]) &&
  3628. ((h5dimlenmax[d] == H5S_UNLIMITED && dim->unlimited) ||
  3629. (h5dimlenmax[d] != H5S_UNLIMITED && !dim->unlimited)))
  3630. break;
  3631. /* Didn't find a phony dim? Then create one. */
  3632. if (!dim)
  3633. {
  3634. LOG((3, "nc4_rec_match_dimscales: creating phony dim for var %s", var->name));
  3635. if ((retval = nc4_dim_list_add(&grp->dim)))
  3636. return retval;
  3637. grp->ndims++;
  3638. dim = grp->dim;
  3639. dim->dimid = grp->file->nc4_info->next_dimid++;
  3640. sprintf(phony_dim_name, "phony_dim_%d", dim->dimid);
  3641. if (!(dim->name = malloc((strlen(phony_dim_name) + 1) * sizeof(char))))
  3642. return NC_ENOMEM;
  3643. strcpy(dim->name, phony_dim_name);
  3644. dim->len = h5dimlen[d];
  3645. if (h5dimlenmax[d] == H5S_UNLIMITED)
  3646. dim->unlimited = 1;
  3647. }
  3648. /* The variable must remember the dimid. */
  3649. var->dimids[d] = dim->dimid;
  3650. } /* next dim */
  3651. /* Free the memory we malloced. */
  3652. free(h5dimlen);
  3653. free(h5dimlenmax);
  3654. }
  3655. }
  3656. }
  3657. return retval;
  3658. }
  3659. /* Get the length, in bytes, of one element of a type in memory. */
  3660. int
  3661. nc4_get_typelen_mem(NC_HDF5_FILE_INFO_T *h5, nc_type xtype, int is_long,
  3662. size_t *len)
  3663. {
  3664. NC_TYPE_INFO_T *type;
  3665. int retval;
  3666. LOG((4, "nc4_get_typelen_mem xtype: %d", xtype));
  3667. assert(len);
  3668. /* If this is an atomic type, the answer is easy. */
  3669. switch (xtype)
  3670. {
  3671. case NC_BYTE:
  3672. case NC_CHAR:
  3673. case NC_UBYTE:
  3674. *len = sizeof(char);
  3675. return NC_NOERR;
  3676. case NC_SHORT:
  3677. case NC_USHORT:
  3678. *len = sizeof(short);
  3679. return NC_NOERR;
  3680. case NC_INT:
  3681. case NC_UINT:
  3682. if (is_long)
  3683. *len = sizeof(long);
  3684. else
  3685. *len = sizeof(int);
  3686. return NC_NOERR;
  3687. case NC_FLOAT:
  3688. *len = sizeof(float);
  3689. return NC_NOERR;
  3690. case NC_DOUBLE:
  3691. *len = sizeof(double);
  3692. return NC_NOERR;
  3693. case NC_INT64:
  3694. case NC_UINT64:
  3695. *len = sizeof(long long);
  3696. return NC_NOERR;
  3697. case NC_STRING:
  3698. *len = 0; /* can't even guess! */
  3699. return NC_NOERR;
  3700. }
  3701. /* See if var is compound type. */
  3702. if ((retval = nc4_find_type(h5, xtype, &type)))
  3703. return retval;
  3704. if (!type)
  3705. return NC_EBADTYPE;
  3706. *len = type->size;
  3707. LOG((5, "type->size ", type->size));
  3708. return NC_NOERR;
  3709. }