changeset 1883:37e5bfa0b3a7

Minor changes for windows compatibility, add emulation of vector_dimension for compound data types
author bert <bert>
date Tue, 19 Oct 2004 16:13:19 +0000
parents 4f060d43902e
children 3bb11fc01e67
files libsrc/hdf_convenience.c
diffstat 1 files changed, 118 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/libsrc/hdf_convenience.c
+++ b/libsrc/hdf_convenience.c
@@ -19,6 +19,7 @@
     char path[NC_MAX_NAME];
     int id;
     int ndims;
+    int is_cmpd;                /* Is compound? */
     hsize_t *dims;
     hid_t dset_id;
     hid_t ftyp_id;              /* File type */
@@ -30,12 +31,14 @@
     struct m2_dim *link;
     int id;
     long length;
+    int is_fake;                /* TRUE if "emulated" vector dimension. */
     char name[NC_MAX_NAME];
 };
 
 struct m2_file {
     struct m2_file *link;
     hid_t fd;
+    int wr_ok;                  /* non-zero if write OK */
     int resolution;		/* Resolution setting. */
     int nvars;
     int ndims;
@@ -175,6 +178,7 @@
         new->id = file->nvars++;
 	strncpy(new->name, name, NC_MAX_NAME - 1);
 	strncpy(new->path, path, NC_MAX_NAME - 1);
+        new->is_cmpd = 0;
         new->dset_id = H5Dopen(file->fd, path);
         new->ftyp_id = H5Dget_type(new->dset_id);
         new->mtyp_id = H5Tget_native_type(new->ftyp_id, H5T_DIR_ASCEND);
@@ -243,6 +247,7 @@
     if (new != NULL) {
         new->id = file->ndims++;
 	new->length = length;
+        new->is_fake = 0;
 	strncpy(new->name, name, NC_MAX_NAME - 1);
 	file->dims[new->id] = new;
     }
@@ -326,10 +331,11 @@
     return (-1);
 }
 
-private void
+static void
 hdf_get_diminfo(hid_t dst_id, int *ndims, hsize_t dims[])
 {
     hid_t spc_id;
+
     spc_id = H5Dget_space(dst_id);
     if (spc_id < 0) {
         milog_message(MI_MSG_SNH);
@@ -340,9 +346,10 @@
 	    H5Sget_simple_extent_dims(spc_id, dims, NULL);
 	}
     }
+
 }
 
-private int
+static int
 hdf_size(hid_t spc_id, hid_t typ_id)
 {
     int typ_size = H5Tget_size(typ_id);
@@ -358,7 +365,7 @@
 /** Given a numeric variable ID, get the text name of a MINC/HDF5 variable.
  * Equivalent of ncvarname()
  */
-public int
+int
 hdf_varname(int fd, int varid, char *varnm)
 {
     struct m2_file *file;
@@ -382,7 +389,7 @@
 /** Given a text name, get the numeric ID of a MINC/HDF5 variable. 
  * Equivalent of ncvarid().
  */
-public int
+int
 hdf_varid(int fd, const char *varnm)
 {
     struct m2_file *file;
@@ -405,7 +412,7 @@
 /** Given a variable ID and attribute number return the attribute's text
  * name.  The variable ID may be NC_GLOBAL.  Equivalent to ncattname().
  */
-public int
+int
 hdf_attname(int fd, int varid, int attnum, char *name)
 {
     hid_t loc_id;
@@ -456,7 +463,7 @@
  * is part of netCDF.  Unlike a number of netCDF functions, this 
  * function is expected to return 1 on success, rather than zero.
  */
-public int 
+int 
 hdf_attinq(int fd, int varid, const char *attnm, nc_type *type_ptr, 
 	   int *length_ptr)
 {
@@ -574,7 +581,7 @@
   return (status);
 }
 
-private int
+static int
 hdf_put_dimorder(struct m2_file *file, int dst_id, int ndims, 
 		 const int *dims_ptr)
 {
@@ -617,7 +624,7 @@
     return (MI_NOERROR);
 }
 
-private int 
+static int 
 hdf_get_dimorder(struct m2_file *file, int dst_id, int ndims, int *dims_ptr)
 {
     char *str_ptr;
@@ -683,10 +690,23 @@
 	str_ptr = tmp_ptr;
     }
 
+#ifndef NO_EMULATE_VECTOR_DIMENSION
+    typ_id = H5Dget_type(dst_id);
+    if (typ_id >= 0) {
+        if (H5Tget_class(typ_id) == H5T_COMPOUND) {
+            dim = hdf_dim_byname(file, MIvector_dimension);
+            if (dim != NULL) {
+                dims_ptr[n++] = dim->id;
+            }
+        }
+        H5Tclose(typ_id);
+    }
+#endif /* NO_EMULATE_VECTOR_DIMENSION */
+
     return (MI_NOERROR);
 }
 
-public int
+int
 hdf_inquire(int fd, int *ndims_ptr, int *nvars_ptr, int *natts_ptr,
 	    int *unlimdim_ptr)
 {
@@ -716,7 +736,7 @@
     return (MI_NOERROR);
 }
 
-public int 
+int 
 hdf_varinq(int fd, int varid, char *varnm_ptr, nc_type *type_ptr, 
 	   int *ndims_ptr, int *dims_ptr, int *natts_ptr)
 {
@@ -759,6 +779,14 @@
     size = H5Tget_size(typ_id);
 
     if (type_ptr != NULL) {
+#ifndef NO_EMULATE_VECTOR_DIMENSION
+        if (class == H5T_COMPOUND) {
+            hid_t subtype_id = H5Tget_member_type(typ_id, 0);
+            class = H5Tget_class(subtype_id);
+            size = H5Tget_size(subtype_id);
+            H5Tclose(subtype_id);
+        }
+#endif /* NO_EMULATE_VECTOR_DIMENSION */
 	if (class == H5T_INTEGER) {
 	    if (size == 1)
 		*type_ptr = NC_BYTE;
@@ -812,7 +840,8 @@
 
         /* Emulate the signtype attribute for the image variable.
          */
-        if (!strcmp(var->name, MIimage)) {
+        if (!strcmp(var->name, MIimage) &&
+            H5Tget_class(var->ftyp_id) == H5T_INTEGER) {
             natts++;
         }
 
@@ -826,14 +855,14 @@
     return (MI_NOERROR);
 }
 
-public int
+int
 hdf_dimrename(int fd, int dimid, const char *new_name)
 {
     milog_message(MI_MSG_NOTIMPL, "dimrename");
     return (MI_NOERROR);
 }
 
-public int
+int
 hdf_dimid(int fd, const char *dimnm)
 {
     struct m2_file *file;
@@ -850,7 +879,7 @@
 }
 
 	
-public int
+int
 hdf_diminq(int fd, int dimid, char *dimnm_ptr, long *len_ptr)
 {
     struct m2_file *file;
@@ -877,7 +906,7 @@
     return (MI_NOERROR);
 }
 
-private void
+static void
 hdf_set_length(hid_t dst_id, const char *dimnm, unsigned long length)
 {
     hid_t att_id;
@@ -895,7 +924,7 @@
     }
 }
 
-public int
+int
 hdf_dimdef(int fd, const char *dimnm, long length)
 {
     int status = MI_ERROR;
@@ -916,7 +945,7 @@
 /** Like hdf_attinq, this function must return one for success, not
  * zero!
  */
-public int
+int
 hdf_attget(int fd, int varid, const char *attnm, void *value)
 {
     hid_t att_id;
@@ -985,7 +1014,7 @@
     return (status);
 }
 
-public int
+int
 hdf_attput(int fd, int varid, const char *attnm, nc_type val_typ, 
 	   int val_len, void *val_ptr)
 {
@@ -1177,16 +1206,17 @@
  * in a file, and if a dimension variable has not yet been saved to the 
  * file, it creates one here.
  */
-private void
+static void
 hdf_dim_commit(int fd)
 {
     struct m2_file *file;
     struct m2_dim *dim;
     int i;
 
-    if ((file = hdf_id_check(fd)) != NULL) {
+    if ((file = hdf_id_check(fd)) != NULL && file->wr_ok) {
         for (i = 0; i < file->ndims; i++) {
-            if ((dim = hdf_dim_byid(file, i)) != NULL) {
+            if ((dim = hdf_dim_byid(file, i)) != NULL &&
+                !dim->is_fake) {
                 if (hdf_var_byname(file, dim->name) == NULL) {
                     hdf_vardef(fd, dim->name, NC_INT, 0, NULL);
                 }
@@ -1201,7 +1231,7 @@
  * time to make certain all of the dimension variables have actually
  * been defined.
  */
-public void
+void
 hdf_enddef(int fd)
 {
     hdf_dim_commit(fd);         /* Make sure all dimensions were saved. */
@@ -1210,7 +1240,7 @@
 
 /** This function provides the HDF5 emulation of the function ncvardef
  */
-public int
+int
 hdf_vardef(int fd, const char *varnm, nc_type vartype, int ndims, 
            const int *dimids)
 {
@@ -1361,7 +1391,7 @@
 
 /**
  */
-public int
+int
 hdf_var_declare(int fd, char *varnm, char *varpath, int ndims, hsize_t *sizes)
 {
     struct m2_file *file;
@@ -1374,7 +1404,7 @@
     return (MI_NOERROR);
 }
 
-public int
+int
 hdf_varget(int fd, int varid, const long *start_ptr, const long *length_ptr,
 	   void *val_ptr)
 {
@@ -1411,6 +1441,22 @@
 
   ndims = var->ndims;
 
+#ifndef NO_EMULATE_VECTOR_DIMENSION
+  /* If it is a compound variable, we cannot actually pick and choose the
+   * length of the hyperslab along the emulated vector_dimension, so we
+   * just reduce the dimensionality by 1
+   */
+  if (var->is_cmpd) {
+      struct m2_dim *dim = hdf_dim_byname(file, MIvector_dimension);
+      if (dim != NULL && length_ptr[ndims - 1] != dim->length) {
+          fprintf(stderr, 
+                  "ERROR: can't read subset of emulated vector dimension\n");
+          return (MI_ERROR);
+      }
+      ndims--;
+  }
+#endif /* NO_EMULATE_VECTOR_DIMENSION */
+
   if (ndims == 0) {
       mspc_id = H5Screate(H5S_SCALAR);
   }
@@ -1446,7 +1492,7 @@
   return (status);
 }
 
-public int 
+int 
 hdf_varputg(int fd, int varid, const long *start, 
             const long *edges, const long *stride, 
             const long *map, const void *value)
@@ -1633,7 +1679,7 @@
     return (status);
 }
 
-public int 
+int 
 hdf_vargetg(int fd, int varid, const long *start, 
             const long *edges, const long *stride, 
             const long *map, void *value)
@@ -1792,7 +1838,7 @@
     return (status);
 }
 
-public int
+int
 hdf_varput(int fd, int varid, const long *start_ptr, const long *length_ptr,
 	   const void *val_ptr)
 {
@@ -1862,7 +1908,7 @@
   return (status);
 }
 
-public int
+int
 hdf_varput1(int fd, int varid, const long *mindex_ptr, const void *val_ptr)
 {
   long length[MAX_VAR_DIMS];
@@ -1881,7 +1927,7 @@
 /** Emulates ncattdel().  Like many of the netCDF attribute functions,
  * success here is indicated by a return value of one.
  */
-public int
+int
 hdf_attdel(int fd, int varid, const char *attnm)
 {
     hid_t loc_id;
@@ -1911,7 +1957,7 @@
  * and can be independent, rather than set by a file-wide "dimension"
  * object.
  */
-public int
+int
 hdf_varsize(int fd, int varid, long *size_ptr)
 {
     int i;
@@ -1945,7 +1991,7 @@
     return (MI_NOERROR);
 }
 
-public herr_t
+herr_t
 hdf_copy_attr(hid_t in_id, const char *attr_name, void *op_data)
 {
    hid_t out_id = (hid_t) op_data;
@@ -2084,9 +2130,20 @@
     struct m2_file *file;
     hsize_t dims[MAX_NC_DIMS];
     int ndims;
+    struct m2_var *var;
 
     H5E_BEGIN_TRY {
-        fd = H5Fopen(path, mode, H5P_DEFAULT);
+        if (mode & 0x8000) {
+            hid_t prp_id;
+
+            prp_id = H5Pcreate(H5P_FILE_ACCESS);
+            H5Pset_fapl_mmap(prp_id, 8192, 1);
+            fd = H5Fopen(path, mode & 0x7FFF, prp_id);
+            H5Pclose(prp_id);
+        }
+        else {
+            fd = H5Fopen(path, mode, H5P_DEFAULT);
+        }
     } H5E_END_TRY;
 
     if (fd < 0) {
@@ -2094,15 +2151,39 @@
     }
 
     file = hdf_id_add(fd);	/* Add it to the list */
+    file->wr_ok = (mode & H5F_ACC_RDWR) != 0;
 
     /* Open the image variables.
      */
     H5E_BEGIN_TRY {
         dset_id = H5Dopen(fd, "/minc-2.0/image/0/image");
         if (dset_id >= 0) {
+            hid_t type_id;
+            int is_compound = 0;
+
             hdf_get_diminfo(dset_id, &ndims, dims);
-            hdf_var_add(file, MIimage, "/minc-2.0/image/0/image", 
-                        ndims, dims);
+
+#ifndef NO_EMULATE_VECTOR_DIMENSION
+            /* See if a vector_dimension needs to be emulated.
+             */
+            type_id = H5Dget_type(dset_id);
+            if (type_id >= 0) {
+                if (H5Tget_class(type_id) == H5T_COMPOUND) {
+                    /* OK, it's compound type. */
+                    struct m2_dim *dim = hdf_dim_add(file, MIvector_dimension, 
+                                                     H5Tget_nmembers(type_id));
+                    dim->is_fake = 1;
+                    dims[ndims++] = H5Tget_nmembers(type_id);
+                    is_compound = 1;
+                }
+                H5Tclose(type_id);
+            }
+#endif /* NO_EMULATE_VECTOR_DIMENSION */
+
+            var = hdf_var_add(file, MIimage, "/minc-2.0/image/0/image", 
+                              ndims, dims);
+            var->is_cmpd = is_compound;
+
             H5Dclose(dset_id);
         }
     
@@ -2196,6 +2277,8 @@
         return (MI_ERROR);      /* Should not happen?? */
     }
 
+    file->wr_ok = 1;
+
     if (opts_ptr != NULL && opts_ptr->struct_version == MI2_OPTS_V1) {
         file->comp_type = opts_ptr->comp_type;
         file->comp_param = opts_ptr->comp_param;