This annex contains some examples of how to apply the mapping rules specified in this part of ISO 10303. The examples were produced using the HDF5 API developed by the HDF5 Group.
The examples make use of the functions and types declared in the following code excerpt.
#ifndef EXAMPLES
#define EXAMPLES
#include "hdf5.h"
#define NUMBER_OF_ENTITIES 4
#define NO_OF_PPOINTS 4
#define NO_OF_MANY_POINTS 25
hid_t file_id;
hid_t instance_reference_tid;
long instance_reference_tid_size;
char *defined_entity_names[NUMBER_OF_ENTITIES];
char *entity_names[NUMBER_OF_ENTITIES];
herr_t define_instance_reference(hid_t group_id);
herr_t define_compound_point(hid_t group_id, hid_t *pp_tid);
herr_t define_compound_line(hid_t group_id, hid_t col_tid, hid_t *ll_tid);
herr_t define_colour_enumeration(hid_t group_id, hid_t *eenum_col_tid);
herr_t define_compound_colour(hid_t group_id, hid_t eenum_col_tid, hid_t *cc_tid);
herr_t define_aggr_reference(hid_t group_id, hid_t aggr_tid, char *aggr_id, hid_t *aggr_ref_tid);
herr_t create_schema_group(hid_t file_id, char *group_name, char *schema_name, hid_t *ggroup_id);
herr_t create_pop_group(hid_t file_id, char *group_name, char *schema_name, hid_t *ggroup_id);
herr_t create_ppoints(hid_t group_id, hid_t p_tid);
herr_t create_llines(hid_t group_id, hid_t l_tid);
hid_t define_nested_real_aggr(void);
herr_t create_nested_real_aggr(hid_t group_id, hid_t vlen_of_vlen_double_tid, char **buffer);
hid_t define_nested_point_aggr(hid_t p_tid);
herr_t create_nested_point_aggr(hid_t group_id, hid_t vlen_of_vlen_p_tid);
hid_t define_nested_ref_aggr(void);
herr_t create_many_points(hid_t group_id, hid_t p_tid);
herr_t define_compound_land_survey(hid_t group_id, hid_t *lls_tid);
herr_t create_survey(hid_t pop_id, hid_t ls_tid,hid_t p_tid);
herr_t create_nested_real_array(hid_t group_id);
long get_dataset_index(char *entity_name);
enum colors_t {vvoid,red, green, blue, white, black};
typedef struct inst_ref_t {
long dataset_index;
long instance_index;
} inst_ref_t;
typedef struct point_t {
long set_unset_bitmap;
long id;
double x;
double y;
} point_t;
typedef struct colour_t {
long set_unset_bitmap;
char *s_colour;
enum colors_t e_colour;
} colour_t;
typedef struct lline_t {
long set_unset_bitmap;
long id;
struct inst_ref_t startp;
struct inst_ref_t endp;
colour_t colour;
} lline_t;
#endif /* EXAMPLES */
The following EXPRESS schema is used as context schema for all examples provided in Annex C:
SCHEMA geometry;
TYPE Colour = ENUMERATION OF
(
VVOID,
RED,
GREEN,
BLUE,
WHITE,
BLACK
);
END_TYPE;
TYPE SSTRING = STRING;
END_TYPE;
TYPE CColour = SELECT(Colour,SSTRING);
END_TYPE;
ENTITY Line;
colour : CColour;
startp : POINT;
endp : POINT;
END_ENTITY;
ENTITY Point;
x : REAL;
y : REAL;
END_ENTITY;
ENTITY Land_survey;
country : STRING;
properties : LIST OF LIST OF POLYGON;
altitudes : LIST OF LIST OF LIST OF ALTITUDE;
END_ENTITY;
END_SCHEMA;
The following function exemplifies how to map an EXPRESS schema to an HDF5 Group. The input parameters are: HDF5 file identifier; name of the HDF5 Group that will be created; the name of EXPRESS schema. The last parameter, "ggroup_id", is an output parameter that will hold the identifier of the new HDF5 Group that will be created. The rules applied to perform the mapping are described in 6.5.
#include <string.h>
#include "hdf5.h"
#include "examples.h"
herr_t create_schema_group(hid_t file_id, char *group_name, char *schema_name, hid_t *ggroup_id)
{
herr_t rstat;
hid_t group_id;
hid_t attr_id;
hid_t string_tid;
hid_t scalar_tid;
rstat = -1;
*ggroup_id = -1;
group_id = H5Gcreate(file_id, group_name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
if(group_id > 0) {
*ggroup_id = group_id;
string_tid = H5Tcopy(H5T_C_S1);
H5Tset_size(string_tid, strlen(schema_name)+1);
scalar_tid = H5Screate(H5S_SCALAR);
attr_id = H5Acreate (group_id, "iso_10303_26_schema", string_tid, scalar_tid, H5P_DEFAULT, H5P_DEFAULT);
rstat = H5Awrite(attr_id,string_tid,schema_name);
}
return(rstat);
}
The following text fragment represents a dump of an HDF5 file resultant from the execution of the function shown above. The resultant text file is created by the HDF5 dump utility (H5dump) and it is structured according to the HDF5 Data Definition Language (DDL) syntax.
HDF5 "example.h5" {
GROUP "/" {
GROUP "Geometry_encoding" {
ATTRIBUTE "iso_10303_26_schema" {
DATATYPE H5T_STRING {
STRSIZE 16;
STRPAD H5T_STR_NULLTERM;
CSET H5T_CSET_ASCII;
CTYPE H5T_C_S1;
}
DATASPACE SCALAR
DATA {
(0): "Geometry_schema"
}
}
}
}
}
The following function shows how to create an HDF5 Group to hold an EXPRESS-driven data population of a given schema. The rules applied to perform the mapping are described in 6.3.3.
Please observe that the global "defined_entity_names" variable is initalized in the main program (see Annex C.10)
#include <string.h>
#include "hdf5.h"
#include "examples.h"
herr_t create_pop_group(hid_t file_id, char *group_name, char *schema_name, hid_t *ggroup_id)
{
herr_t rstat;
hid_t group_id;
hid_t attr_id;
hid_t string_tid;
hid_t scalar_tid;
hid_t string_array_tid;
hsize_t array_dim[1];
rstat = -1;
*ggroup_id = -1;
group_id = H5Gcreate(file_id, group_name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
if(group_id > 0) {
*ggroup_id = group_id;
string_tid = H5Tcopy(H5T_C_S1);
H5Tset_size(string_tid, strlen(schema_name)+1);
scalar_tid = H5Screate(H5S_SCALAR);
attr_id = H5Acreate (group_id, "iso_10303_26_data", string_tid, scalar_tid, H5P_DEFAULT, H5P_DEFAULT);
rstat = H5Awrite(attr_id,string_tid,schema_name);
array_dim[0] = 4;
rstat = H5Tset_size(string_tid, H5T_VARIABLE);
string_array_tid = H5Tarray_create2(string_tid, 1, array_dim);
attr_id = H5Acreate(group_id, "_10303_26_data_set_names", string_array_tid, scalar_tid, H5P_DEFAULT, H5P_DEFAULT);
rstat = H5Awrite(attr_id,string_array_tid,defined_entity_names);
}
return(rstat);
}
The following text fragment represents a dump of an HDF5 file resultant from the execution of the function above.
HDF5 "example.h5" {
GROUP "/" {
GROUP "Geometry_population" {
ATTRIBUTE "_10303_26_data_set_names" {
DATATYPE H5T_ARRAY { [4] H5T_STRING {
STRSIZE H5T_VARIABLE;
STRPAD H5T_STR_NULLTERM;
CSET H5T_CSET_ASCII;
CTYPE H5T_C_S1;
} }
DATASPACE SCALAR
DATA {
(0): [ "Point", "Many_Point", "Line", "Land_survey" ]
}
}
ATTRIBUTE "iso_10303_26_data" {
DATATYPE H5T_STRING {
STRSIZE 16;
STRPAD H5T_STR_NULLTERM;
CSET H5T_CSET_ASCII;
CTYPE H5T_C_S1;
}
DATASPACE SCALAR
DATA {
(0): "Geometry_schema"
}
}
}
}
}
The following function exemplifies how to map an EXPRESS entity type to an HDF5 Compound Type using the HDF5 API. It shows how the EXPRESS entity Point defined in the context schema is mapped to HDF5. The rules applied to perform the mapping are described in 6.6.
//------------------------------------------------------------------
// Define Point:
//
// Only simple types are encoded is this case
//------------------------------------------------------------------
herr_t define_compound_point(hid_t group_id, hid_t *pp_tid)
{
herr_t rstat;
hid_t p_tid;
*pp_tid = -1;
//
// Create named compound type for POINT
//
p_tid = H5Tcreate (H5T_COMPOUND, sizeof(point_t));
if(rstat = H5Tinsert(p_tid, "set_unset_bitmap", HOFFSET(point_t, set_unset_bitmap), H5T_NATIVE_LONG)) goto err;
if(rstat = H5Tinsert(p_tid, "Entity-Instance-Identifier", HOFFSET(point_t, id), H5T_NATIVE_LONG)) goto err;
if(rstat = H5Tinsert(p_tid, "x", HOFFSET(point_t, x), H5T_NATIVE_DOUBLE)) goto err;
if(rstat = H5Tinsert(p_tid, "y", HOFFSET(point_t, y), H5T_NATIVE_DOUBLE)) goto err;
if(rstat = H5Tcommit2(group_id, "Point", p_tid,H5P_DEFAULT,H5P_DEFAULT,H5P_DEFAULT)) goto err;
*pp_tid = p_tid;
err:
return(rstat);
}
The following code excerpt is used to populate the HDF5 file by creating instances of the HDF5 Compound Type that represents the Point entity as defined by the function "define_compound_point".
#include "hdf5.h"
#include "examples.h"
#define NO_OF_PPOINTS 4
//------------------------------------------------------------------
// Create Points:
//
// Exemplifies how the Point Compound type, defined by means of the define_compound_point function, is used to populate Points on an HDF5 dataset.
// Geometrically the Points make up corners of a square(0,0),(100,0),(100,100),(0,100)
//------------------------------------------------------------------
herr_t create_ppoints(hid_t group_id, hid_t p_tid)
{
herr_t rstat;
hid_t point_dataset;
hid_t myspace;
hid_t obj_group;
hsize_t mydim[1];
point_t ppoints[NO_OF_PPOINTS];
//
// Populate the points in a memory buffer
//
ppoints[0].set_unset_bitmap = 7;
ppoints[0].id = 0;
ppoints[0].x = 0.;
ppoints[0].y = 0.;
ppoints[1].set_unset_bitmap = 7;
ppoints[1].id = 1;
ppoints[1].x = 100.;
ppoints[1].y = 0.;
ppoints[2].set_unset_bitmap = 7;
ppoints[2].id = 2;
ppoints[2].x = 100.;
ppoints[2].y = 100.;
ppoints[3].set_unset_bitmap = 7;
ppoints[3].id = 3;
ppoints[3].x = 0.;
ppoints[3].y = 100.;
//
// Create the group that shall contain the dataset
//
obj_group = H5Gcreate(group_id, "Point_objects", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
//
// Create the dataset that shall contain the Points
//
mydim[0] = NO_OF_PPOINTS;
myspace = H5Screate_simple(1, mydim, NULL);
point_dataset = H5Dcreate1(obj_group, "Point_instances", p_tid, myspace, H5P_DEFAULT);
//
// Write the Points to the dataset
//
rstat = H5Dwrite(point_dataset, p_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, ppoints);
return(rstat);
}
The following text fragment represents a dump of an HDF5 file resultant from the execution of the two functions shown above. The HDF5 definition of the EXPRESS entity Point, created with the function "define_compound_point" is represented by the Point Compound type. The "Point_instances" dataset contains the instance population created using the function "create_ppoints".
HDF5 "example.h5" {
GROUP "/" {
GROUP "Geometry_encoding" {
ATTRIBUTE "iso_10303_26_schema" {
DATATYPE H5T_STRING {
STRSIZE 16;
STRPAD H5T_STR_NULLTERM;
CSET H5T_CSET_ASCII;
CTYPE H5T_C_S1;
}
DATASPACE SCALAR
DATA {
(0): "Geometry_schema"
}
}
DATATYPE "Point" H5T_COMPOUND {
H5T_STD_I32LE "set_unset_bitmap";
H5T_STD_I32LE "Entity-Instance-Identifier";
H5T_IEEE_F64LE "x";
H5T_IEEE_F64LE "y";
}
}
GROUP "Geometry_population" {
ATTRIBUTE "_10303_26_data_set_names" {
DATATYPE H5T_ARRAY { [4] H5T_STRING {
STRSIZE H5T_VARIABLE;
STRPAD H5T_STR_NULLTERM;
CSET H5T_CSET_ASCII;
CTYPE H5T_C_S1;
} }
DATASPACE SCALAR
DATA {
(0): [ "Point", "Many_Point", "Line", "Land_survey" ]
}
}
ATTRIBUTE "iso_10303_26_data" {
DATATYPE H5T_STRING {
STRSIZE 16;
STRPAD H5T_STR_NULLTERM;
CSET H5T_CSET_ASCII;
CTYPE H5T_C_S1;
}
DATASPACE SCALAR
DATA {
(0): "Geometry_schema"
}
}
GROUP "Point_objects" {
DATASET "Point_instances" {
DATATYPE "/Geometry_encoding/Point"
DATASPACE SIMPLE { ( 4 ) / ( 4 ) }
DATA {
(0): {
7,
0,
0,
0
},
(1): {
7,
1,
100,
0
},
(2): {
7,
2,
100,
100
},
(3): {
7,
3,
0,
100
}
}
}
}
}
}
}
The following function exemplifies how to map an EXPRESS enumeration type to an HDF5 enumeration type using the HDF5 API. It shows how the EXPRESS enumeration Colour, defined in the context schema, is mapped to HDF5. The rules applied to perform the mapping are described in section 5.8.1.
//------------------------------------------------------------------
// Define enumeration:
//
// Exemplifies how enumeration types are encoded
//------------------------------------------------------------------
herr_t define_colour_enumeration(hid_t group_id, hid_t *eenum_col_tid)
{
herr_t rstat;
short enum_val;
hid_t enum_col_tid;
*eenum_col_tid = -1;
enum_col_tid = H5Tcreate (H5T_ENUM, sizeof(short));
if(rstat = H5Tenum_insert(enum_col_tid, "VVOID",(enum_val=0,&enum_val))) goto err;
if(rstat = H5Tenum_insert(enum_col_tid, "RED" ,(enum_val=1,&enum_val))) goto err;
if(rstat = H5Tenum_insert(enum_col_tid, "GREEN",(enum_val=2,&enum_val))) goto err;
if(rstat = H5Tenum_insert(enum_col_tid, "BLUE" ,(enum_val=3,&enum_val))) goto err;
if(rstat = H5Tenum_insert(enum_col_tid, "WHITE",(enum_val=4,&enum_val))) goto err;
if(rstat = H5Tenum_insert(enum_col_tid, "BLACK",(enum_val=5,&enum_val))) goto err;
if(rstat = H5Tcommit2(group_id, "Colour", enum_col_tid,H5P_DEFAULT,H5P_DEFAULT,H5P_DEFAULT)) goto err;
*eenum_col_tid = enum_col_tid;
err:
return(rstat);
}
The following text fragment represents a dump of an HDF5 file resultant from the execution of the function "define_colour_enumeration". The HDF5 definition of the EXPRESS enumeration Colour is represented by the Colour HDF5 Enumeration Type. In this example it was not created any instance population, hence the corresponding HDF5 construct that represents the population is empty.
HDF5 "example.h5" {
GROUP "/" {
GROUP "Geometry_encoding" {
ATTRIBUTE "iso_10303_26_schema" {
DATATYPE H5T_STRING {
STRSIZE 16;
STRPAD H5T_STR_NULLTERM;
CSET H5T_CSET_ASCII;
CTYPE H5T_C_S1;
}
DATASPACE SCALAR
DATA {
(0): "Geometry_schema"
}
}
DATATYPE "Colour" H5T_ENUM {
H5T_STD_I16LE;
"VVOID" 0;
"RED" 1;
"GREEN" 2;
"BLUE" 3;
"WHITE" 4;
"BLACK" 5;
};
}
GROUP "Geometry_population" {
ATTRIBUTE "_10303_26_data_set_names" {
DATATYPE H5T_ARRAY { [4] H5T_STRING {
STRSIZE H5T_VARIABLE;
STRPAD H5T_STR_NULLTERM;
CSET H5T_CSET_ASCII;
CTYPE H5T_C_S1;
} }
DATASPACE SCALAR
DATA {
(0): [ "Point", "Many_Point", "Line", "Land_survey" ]
}
}
ATTRIBUTE "iso_10303_26_data" {
DATATYPE H5T_STRING {
STRSIZE 16;
STRPAD H5T_STR_NULLTERM;
CSET H5T_CSET_ASCII;
CTYPE H5T_C_S1;
}
DATASPACE SCALAR
DATA {
(0): "Geometry_schema"
}
}
}
}
}
The following function exemplifies how to map an EXPRESS select type to an HDF5 Compound Type using the HDF5 API. It shows how the EXPRESS select type "CColour" defined in the context schema is mapped to HDF5. The rules applied to perform the mapping are described in section 5.8.2.3.
//------------------------------------------------------------------
// Define Colour:
//
// Exemplifies how select types are encoded
//------------------------------------------------------------------
herr_t define_compound_colour(hid_t group_id, hid_t eenum_col_tid, hid_t *cc_tid)
{
herr_t rstat;
hid_t c_tid;
hid_t string_tid;
*cc_tid = -1;
string_tid = H5Tcopy(H5T_C_S1);
if(rstat = H5Tset_size(string_tid, H5T_VARIABLE)) goto err;
//
// Create named compound type for COLOUR
//
c_tid = H5Tcreate (H5T_COMPOUND, sizeof(colour_t));
if(rstat = H5Tinsert(c_tid, "select_bitmap", HOFFSET(colour_t, select_bitmap), H5T_NATIVE_LONG)) goto err;
if(rstat = H5Tinsert(c_tid, "s_colour", HOFFSET(colour_t, s_colour), string_tid)) goto err;
if(rstat = H5Tinsert(c_tid, "e_colour", HOFFSET(colour_t, e_colour), eenum_col_tid)) goto err;
if(rstat = H5Tcommit2(group_id, "CColour", c_tid,H5P_DEFAULT,H5P_DEFAULT,H5P_DEFAULT)) goto err;
*cc_tid = c_tid;
err:
return(rstat);
}
The following text fragment represents a dump of an HDF5 file showing how the EXPRESS select type "CColour" is actually encoded in HDF5.
HDF5 "example.h5" {
GROUP "/" {
GROUP "Geometry_encoding" {
ATTRIBUTE "iso_10303_26_schema" {
DATATYPE H5T_STRING {
STRSIZE 16;
STRPAD H5T_STR_NULLTERM;
CSET H5T_CSET_ASCII;
CTYPE H5T_C_S1;
}
DATASPACE SCALAR
DATA {
(0): "Geometry_schema"
}
}
DATATYPE "CColour" H5T_COMPOUND {
H5T_STD_I32LE "select_bitmap";
H5T_STRING {
STRSIZE H5T_VARIABLE;
STRPAD H5T_STR_NULLTERM;
CSET H5T_CSET_ASCII;
CTYPE H5T_C_S1;
} "s_colour";
H5T_ENUM {
H5T_STD_I16LE;
"VVOID" 0;
"RED" 1;
"GREEN" 2;
"BLUE" 3;
"WHITE" 4;
"BLACK" 5;
} "e_colour";
}
DATATYPE "Colour" H5T_ENUM {
H5T_STD_I16LE;
"VVOID" 0;
"RED" 1;
"GREEN" 2;
"BLUE" 3;
"WHITE" 4;
"BLACK" 5;
};
}
GROUP "Geometry_population" {
ATTRIBUTE "_10303_26_data_set_names" {
DATATYPE H5T_ARRAY { [4] H5T_STRING {
STRSIZE H5T_VARIABLE;
STRPAD H5T_STR_NULLTERM;
CSET H5T_CSET_ASCII;
CTYPE H5T_C_S1;
} }
DATASPACE SCALAR
DATA {
(0): [ "Point", "Many_Point", "Line", "Land_survey" ]
}
}
ATTRIBUTE "iso_10303_26_data" {
DATATYPE H5T_STRING {
STRSIZE 16;
STRPAD H5T_STR_NULLTERM;
CSET H5T_CSET_ASCII;
CTYPE H5T_C_S1;
}
DATASPACE SCALAR
DATA {
(0): "Geometry_schema"
}
}
}
}
}
The following function exemplifies how the EXPRESS entity "Line" defined in the context schema is mapped to the corresponding HDF5 Compound Type using the HDF5 API. In addition, this example shows how instance references and attributes of mixed SELECT types are mapped applying the rules described in section 5.9.3. The EXPRESS entity "Line" referrers to two instances of the entity "Point", namely "startp" and "endp", and contains an attribute of type "CColour", which is the EXPRESS select type defined in the context schema.
//__________________________________________________________________
// Define Line:
//
// In addition to simple type encoding, this functions exemplifies how to encode references to entity instances.
// Moreover it is exemplified how select types , also being defined as Compound types, are embedded.
//__________________________________________________________________
herr_t define_compound_line(hid_t group_id, hid_t col_tid, hid_t *ll_tid)
{
herr_t rstat;
hid_t l_tid;
*ll_tid = _1;
//
// Create named compound type for LINE
//
l_tid = H5Tcreate (H5T_COMPOUND, sizeof(lline_t));
if(rstat = H5Tinsert(l_tid, "set_unset_bitmap", HOFFSET(lline_t, set_unset_bitmap), H5T_NATIVE_LONG)) goto err;
if(rstat = H5Tinsert(l_tid, "Entity_Instance_Identifier", HOFFSET(lline_t, id), H5T_NATIVE_LONG)) goto err;
if(rstat = H5Tinsert(l_tid, "startp", HOFFSET(lline_t, startp), instance_reference_tid )) goto err;
if(rstat = H5Tinsert(l_tid, "endp", HOFFSET(lline_t, endp), instance_reference_tid )) goto err;
if(rstat = H5Tinsert(l_tid, "colour", HOFFSET(lline_t, colour), col_tid )) goto err;
if(rstat = H5Tcommit2(group_id, "Line", l_tid,H5P_DEFAULT,H5P_DEFAULT,H5P_DEFAULT)) goto err;
*ll_tid = l_tid;
err:
return(rstat);
}
The following code excerpt is used to populate an HDF5 file according to the complete context schema.
#include <stdlib.h>
#include <string.h>
#include "hdf5.h"
#include "examples.h"
#define NO_OF_LLINES 4
//------------------------------------------------------------------
// Create Lines:
//
// Lines are created by letting the startp and endp
// attributes (fields) refer to Points in the dataset
// /Geometry_population/Point_objects/Point_instances
//
// (000,100)------------------(100,100)
// . .
// . .
// . .
// . .
// (000,000)-------------------(000,100)
//
//------------------------------------------------------------------
herr_t create_llines(hid_t group_id, hid_t l_tid)
{
herr_t rstat;
hid_t line_dataset;
hid_t myspace;
hid_t obj_group;
hsize_t mydim[1];
inst_ref_t inst_ref;
enum colors_t line_colour;
lline_t lines[NO_OF_LLINES];
//
// Populate the four Lines in a memory buffer
//
mydim[0] = NO_OF_LLINES;
myspace = H5Screate_simple(1, mydim, NULL);
//
// Lower Line (0,0) to (100,0)
//
lines[0].set_unset_bitmap = 7;
lines[0].id = 4;
inst_ref.dataset_index = get_dataset_index("Point");
inst_ref.instance_index = 0;
memcpy(&lines[0].startp,&inst_ref,sizeof(inst_ref_t));
inst_ref.instance_index = 1;
memcpy(&lines[0].endp,&inst_ref,sizeof(inst_ref_t));
lines[0].colour.select_bitmap = 2;
line_colour = red;
lines[0].colour.e_colour = line_colour;
lines[0].colour.s_colour = "";
//
// Rightmost Line (100,0) to (100,100)
//
lines[1].set_unset_bitmap = 7;
lines[1].id = 5;
inst_ref.instance_index = 1;
memcpy(&lines[1].startp,&inst_ref,sizeof(inst_ref_t));
inst_ref.instance_index = 2;
memcpy(&lines[1].endp,&inst_ref,sizeof(inst_ref_t));
lines[1].colour.select_bitmap = 2;
line_colour = blue;
lines[1].colour.e_colour = line_colour;
lines[1].colour.s_colour = "";
//
// Upper Line (100,100) to (0,100)
//
lines[2].set_unset_bitmap = 7;
lines[2].id = 6;
inst_ref.instance_index = 2;
memcpy(&lines[2].startp,&inst_ref,sizeof(inst_ref_t));
inst_ref.instance_index = 3;
memcpy(&lines[2].endp,&inst_ref,sizeof(inst_ref_t));
lines[2].colour.select_bitmap = 1;
line_colour = vvoid;
lines[2].colour.e_colour = line_colour;
lines[2].colour.s_colour = "Red line";
//
// Leftmost Line (0,100) to (0,0)
//
lines[3].set_unset_bitmap = 7;
lines[3].id = 7;
inst_ref.instance_index = 3;
memcpy(&lines[3].startp,&inst_ref,sizeof(inst_ref_t));
inst_ref.instance_index = 0;
memcpy(&lines[3].endp,&inst_ref,sizeof(inst_ref_t));
lines[3].colour.select_bitmap = 1;
line_colour = vvoid;
lines[3].colour.e_colour = line_colour;
lines[3].colour.s_colour = "Blue line";
//
// Create the group that shall containg the Line dataset
//
obj_group = H5Gcreate(group_id, "Line_objects", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
//
// Create the dataset that shall contain the Lines
//
line_dataset = H5Dcreate1(obj_group, "Line_instances", l_tid, myspace, H5P_DEFAULT);
//
// Write the Lines to the dataset
//
if(rstat = H5Dwrite(line_dataset, l_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, lines)) goto err;
err:
return(rstat);
}
See a dump of the resultant HDF5 file in section C.9.
The "Land_survey" EXPRESS entity defined in the context schema contains two nested aggregates.
//---------------------------------------------------------------------
// Define Land Survey:
//
// Exemplifies how references to aggregates are encoded encoded.
// One aggregate is stored on a separate dataset. The other one is embedded.
//---------------------------------------------------------------------
herr_t define_compound_land_survey(hid_t group_id, hid_t *lls_tid)
{
herr_t rstat;
long mysize,offset;
long string_tid_size;
long aggr_ref_tid_size;
hid_t ls_tid;
hid_t string_tid;
hid_t aggr1_ref_tid;
hid_t aggr2_ref_tid;
hid_t vlen_of_vlen_double_tid;
hid_t vlen_of_vlen_ref_tid;
*lls_tid = -1;
string_tid = H5Tcopy(H5T_C_S1);
if(rstat = H5Tset_size(string_tid, H5T_VARIABLE)) goto err;
string_tid_size = H5Tget_size(string_tid);
vlen_of_vlen_ref_tid = define_nested_ref_aggr();
if(rstat = define_aggr_reference(group_id, vlen_of_vlen_ref_tid, "1", &aggr1_ref_tid)) goto err;
vlen_of_vlen_double_tid = define_nested_real_aggr();
if(rstat = define_aggr_reference(group_id, vlen_of_vlen_double_tid, "2", &aggr2_ref_tid)) goto err;
aggr_ref_tid_size = H5Tget_size(aggr1_ref_tid);
//
// Create named compound type for LAND_SURVEY
//
mysize = 2*sizeof(long) + string_tid_size + 2*aggr_ref_tid_size;
offset = 0;
ls_tid = H5Tcreate (H5T_COMPOUND, mysize);
if(rstat = H5Tinsert(ls_tid, "set_unset_bitmap", offset, H5T_NATIVE_LONG)) goto err;
offset += sizeof(long);
if(rstat = H5Tinsert(ls_tid, "Entity-Instance-Identifier", offset, H5T_NATIVE_LONG)) goto err;
offset += sizeof(long);
if(rstat = H5Tinsert(ls_tid, "country", offset, string_tid)) goto err;
offset += string_tid_size;
if(rstat = H5Tinsert(ls_tid, "properties", offset, aggr1_ref_tid)) goto err;
offset += aggr_ref_tid_size;
if(rstat = H5Tinsert(ls_tid, "altitudes", offset, aggr2_ref_tid )) goto err;
if(rstat = H5Tcommit2(group_id, "Land_survey",ls_tid,H5P_DEFAULT,H5P_DEFAULT,H5P_DEFAULT)) goto err;
*lls_tid = ls_tid;
err:
return(rstat);
}
The following code excerpt exemplifies how to create and populate the HDF5 Compund Type corresponding to the "Land_survey" EXPRESS entity, using the HDF5 API.
#include <stdlib.h>
#include <string.h>
#include "hdf5.h"
#include "examples.h"
//------------------------------------------------------------------
// Create Survey
//------------------------------------------------------------------
herr_t create_survey(hid_t group_id, hid_t ls_tid,hid_t p_tid)
{
herr_t rstat;
hid_t ls_dataset;
hid_t myspace;
hid_t obj_group;
hobj_ref_t objref;
hid_t vlen_of_vlen_double_tid;
hid_t vlen_of_vlen_ref_tid;
long mysize;
long myinteger;
char mychar;
hsize_t mydim[1];
char *norway = "Norway";
char *vlen_data;
char *buffer;
char *mybuffer;
mysize = H5Tget_size(ls_tid);
mybuffer = (char*) malloc(mysize);
buffer = mybuffer;
if(rstat = create_many_points(group_id, p_tid)) goto err;
obj_group = H5Gcreate(group_id, "Land_survey_objects", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
vlen_of_vlen_double_tid = define_nested_real_aggr();
vlen_of_vlen_ref_tid = define_nested_ref_aggr();
if(rstat = create_nested_real_aggr(obj_group,vlen_of_vlen_double_tid,&vlen_data)) goto err;
if(rstat = create_nested_point_aggr(obj_group,vlen_of_vlen_ref_tid)) goto err;
memset(mybuffer,0,mysize);
myinteger = 15;
memcpy(mybuffer,&myinteger,sizeof(long));
mybuffer += sizeof(long);
myinteger = 25;
memcpy(mybuffer,&myinteger,sizeof(long));
mybuffer += sizeof(long);
memcpy(mybuffer,&norway,sizeof(char*));
mybuffer += sizeof(char*);
mychar = (char)1;
memcpy(mybuffer,&mychar,sizeof(char));
mybuffer += sizeof(char);
if(rstat = H5Rcreate(&objref, obj_group, "/Geometry_population/Land_survey_objects/Aggr-properties-1", H5R_OBJECT, -1)) goto err;
memcpy(mybuffer,&objref,sizeof(hobj_ref_t));
mybuffer += sizeof(hobj_ref_t);
mybuffer += sizeof(hvl_t);
mychar = (char)0;
memcpy(mybuffer,&mychar,sizeof(char));
mybuffer += sizeof(char);
mybuffer += sizeof(hobj_ref_t);
memcpy(mybuffer,vlen_data,sizeof(hvl_t));
//
// Create the LAND SURVEY dataset
//
mydim[0] = 1;
myspace = H5Screate_simple(1, mydim, NULL);
ls_dataset = H5Dcreate1(obj_group, "Land_survey_instances", ls_tid, myspace, H5P_DEFAULT);
//
// Write lines to file
//
if(rstat = H5Dwrite(ls_dataset, ls_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, buffer)) goto err;
err:
free(mybuffer);
return(rstat);
}
Auxiliary functions are used to define and create the multi-dimensional aggregates that are part of the "Land_survey" Compound type. These functions are called from the "create_survey" function above and they are presented next.
hid_t define_nested_real_aggr(void)
{
hid_t vlen_double_tid;
hid_t vlen_of_vlen_double_tid;
//
// Create variable-length datatype in two levels, double beeing the base type
//
vlen_double_tid = H5Tvlen_create(H5T_NATIVE_DOUBLE);
vlen_of_vlen_double_tid = H5Tvlen_create (vlen_double_tid);
vlen_of_vlen_double_tid = H5Tvlen_create (vlen_of_vlen_double_tid);
return(vlen_of_vlen_double_tid);
}
hid_t define_nested_ref_aggr(void)
{
hid_t vlen_ref_tid;
hid_t vlen_of_vlen_ref_tid;
//
// Create variable-length datatype in two levels, reference type beeing the base type
//
vlen_ref_tid = H5Tvlen_create(instance_reference_tid);
vlen_of_vlen_ref_tid = H5Tvlen_create (vlen_ref_tid);
return(vlen_of_vlen_ref_tid);
}
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include <string.h>
#include "hdf5.h"
#include "examples.h"
#define LEN0 3
#define LEN1 2
//
// NOTE:
// Memory fragments that are allocated in the following two functions are not released.
//
// In a real application a memory management system, where VLEN memory is
// grabbed from a pool of large reausable chunks should be developed.
// (The pool is released upon application exit)
//
// Did not take the time to develop a memory management system for this rather small example,
// so be aware of this small memory leak.
//
//------------------------------------------------------------------
// Create nested REAL aggregate
//
// Exemplifies how a nested aggregate of REAL is encoded in HDF5
// The number of elements on each level are:
// 2-3-6
// -3
// -4
// 2-3
// -6
//------------------------------------------------------------------
herr_t create_nested_real_aggr(hid_t group_id, hid_t vlen_of_vlen_double_tid, char **buffer)
{
hvl_t *wdata;
hvl_t *mybuf;
hvl_t *tA, *tB;
herr_t rstat;
hsize_t dims[1] = {2};
rstat = 0;
/*
* Initialize variable-length data.
*/
wdata = (hvl_t*) malloc(2*sizeof(hvl_t));
mybuf = (hvl_t*) malloc(sizeof(hvl_t));
*buffer = (char*)mybuf;
mybuf->len = 2;
mybuf->p = wdata;
/* Initializing vector C */
wdata[0].len = LEN0;
wdata[0].p = (hvl_t *) malloc ( LEN0 * sizeof (hvl_t));
wdata[1].len = LEN1;
wdata[1].p = (hvl_t *) malloc ( LEN1 * sizeof (hvl_t));
/* Initialize vector A */
tA = wdata[0].p;
tA->len = 5;
tA->p = (double *) malloc (tA->len * sizeof (double));
((double *) tA->p)[0] = 100.0;
((double *) tA->p)[1] = 101.1;
((double *) tA->p)[2] = 102.2;
((double *) tA->p)[3] = 103.3;
((double *) tA->p)[4] = 104.4;
tA++;
tA->len = 3;
tA->p = (double *) malloc (tA->len * sizeof (double));
((double *) tA->p)[0] = 200.0;
((double *) tA->p)[1] = 201.1;
((double *) tA->p)[2] = 202.2;
tA++;
tA->len = 4;
tA->p = (double *) malloc (tA->len * sizeof (double));
((double *)tA->p)[0] = 300.0;
((double *)tA->p)[1] = 301.1;
((double *)tA->p)[2] = 302.2;
((double *)tA->p)[3] = 303.3;
/* Done with A */
/* Initialize vector B */
tB = wdata[1].p;
tB->len =3;
tB->p = (double *) malloc (tB->len * sizeof (double));
((double *)tB->p)[0] = 400.0;
((double *)tB->p)[1] = 401.1;
((double *)tB->p)[2] = 401.2;
tB++;
tB->len = 6;
tB->p = (double *) malloc (tB->len * sizeof (double));
((double *) tB->p)[0] = 500.0;
((double *) tB->p)[1] = 501.1;
((double *) tB->p)[2] = 502.2;
((double *) tB->p)[3] = 503.3;
((double *) tB->p)[4] = 504.4;
((double *) tB->p)[5] = 505.5;
/* Done with B */
return(rstat);
}
//------------------------------------------------------------------
// Create nested aggregate of references to Point instances
//
// The number of elements on each level are:
// 2-3-6
// -3
// -4
// 2-3
// -6
//------------------------------------------------------------------
herr_t create_nested_point_aggr(hid_t group_id, hid_t vlen_of_vlen_ref_tid)
{
long rstat;
hid_t space;
hid_t dset;
inst_ref_t inst_ref;
inst_ref_t *s_p_ref;
inst_ref_t *t_p_ref;
hvl_t wdata[2]; /* Array of vlen structures to write */
hvl_t *tA, *tB;
hsize_t dims[1] = {2};
rstat = -1;
/*
* Initialize variable-length data.
*/
/* Initializing vector C */
wdata[0].len = 3;
wdata[0].p = (hvl_t *) malloc ( 3 * sizeof (hvl_t));
wdata[1].len = 2;
wdata[1].p = (hvl_t *) malloc ( 1 * sizeof (hvl_t));
s_p_ref = &inst_ref;
/* Initialize vector A */
tA = wdata[0].p;
tA->len = 5;
tA->p = (hdset_reg_ref_t *) malloc (tA->len * sizeof (inst_ref_t));
t_p_ref = (inst_ref_t*)tA->p;
inst_ref.dataset_index = get_dataset_index("Many_Point");
inst_ref.instance_index = 0;
memcpy(t_p_ref,s_p_ref,sizeof(inst_ref_t));
++t_p_ref;
inst_ref.instance_index = 1;
memcpy(t_p_ref,s_p_ref,sizeof(inst_ref_t));
++t_p_ref;
inst_ref.instance_index = 7;
memcpy(t_p_ref,s_p_ref,sizeof(inst_ref_t));
++t_p_ref;
inst_ref.instance_index = 11;
memcpy(t_p_ref,s_p_ref,sizeof(inst_ref_t));
++t_p_ref;
inst_ref.instance_index = 5;
memcpy(t_p_ref,s_p_ref,sizeof(inst_ref_t));
tA++;
tA->len = 3;
tA->p = (inst_ref_t *) malloc (tA->len * sizeof (inst_ref_t));
t_p_ref = (inst_ref_t*)tA->p;
inst_ref.instance_index = 1;
memcpy(t_p_ref,s_p_ref,sizeof(inst_ref_t));
++t_p_ref;
inst_ref.instance_index = 2;
memcpy(t_p_ref,s_p_ref,sizeof(inst_ref_t));
++t_p_ref;
inst_ref.instance_index = 7;
memcpy(t_p_ref,s_p_ref,sizeof(inst_ref_t));
tA++;
tA->len = 4;
tA->p = (inst_ref_t *) malloc (tA->len * sizeof (inst_ref_t));
t_p_ref = (inst_ref_t*)tA->p;
inst_ref.instance_index = 2;
memcpy(t_p_ref,s_p_ref,sizeof(inst_ref_t));
++t_p_ref;
inst_ref.instance_index = 9;
memcpy(t_p_ref,s_p_ref,sizeof(inst_ref_t));
++t_p_ref;
inst_ref.instance_index = 13;
memcpy(t_p_ref,s_p_ref,sizeof(inst_ref_t));
++t_p_ref;
inst_ref.instance_index = 7;
memcpy(t_p_ref,s_p_ref,sizeof(inst_ref_t));
/* Initialize vector B */
tB = wdata[1].p;
tB->len = 3;
tB->p = (inst_ref_t *) malloc (tB->len * sizeof (inst_ref_t));
t_p_ref = (inst_ref_t*)tB->p;
inst_ref.instance_index = 2;
memcpy(t_p_ref,s_p_ref,sizeof(inst_ref_t));
++t_p_ref;
inst_ref.instance_index = 4;
memcpy(t_p_ref,s_p_ref,sizeof(inst_ref_t));
++t_p_ref;
inst_ref.instance_index = 9;
memcpy(t_p_ref,s_p_ref,sizeof(inst_ref_t));
tB++;
tB->len = 6;
tB->p = (inst_ref_t *) malloc (tB->len * sizeof (inst_ref_t));
t_p_ref = (inst_ref_t*)tB->p;
inst_ref.instance_index = 5;
memcpy(t_p_ref,s_p_ref,sizeof(inst_ref_t));
++t_p_ref;
inst_ref.instance_index = 11;
memcpy(t_p_ref,s_p_ref,sizeof(inst_ref_t));
++t_p_ref;
inst_ref.instance_index = 7;
memcpy(t_p_ref,s_p_ref,sizeof(inst_ref_t));
++t_p_ref;
inst_ref.instance_index = 13;
memcpy(t_p_ref,s_p_ref,sizeof(inst_ref_t));
++t_p_ref;
inst_ref.instance_index = 16;
memcpy(t_p_ref,s_p_ref,sizeof(inst_ref_t));
++t_p_ref;
inst_ref.instance_index = 10;
memcpy(t_p_ref,s_p_ref,sizeof(inst_ref_t));
/* Done with B */
/*
* Create dataspace. Setting maximum size to NULL sets the maximum
* size to be the current size.
*/
space = H5Screate_simple (1, dims, NULL);
/*
* Create the dataset and write the variable-length data to it.
*/
dset = H5Dcreate (group_id, "Aggr-properties-1", vlen_of_vlen_ref_tid, space, H5P_DEFAULT, H5P_DEFAULT,H5P_DEFAULT);
rstat = H5Dwrite (dset, vlen_of_vlen_ref_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, wdata);
return(rstat);
}
//------------------------------------------------------------------
// Create many Points:
//
// This function is similar to the create_points function.
// The only difference is that more points are created
// for the purpose of refering to them from an aggregate defined in Land_survey Compound type.
// Geometrically the Points make up 25 squares in a mesh.
// (0000,4000),(1000,4000),(2000,4000),(3000,4000),(4000,4000)
// (0000,3000),(1000,3000),(2000,3000),(3000,3000),(4000,3000)
// (0000,2000),(1000,2000),(2000,2000),(3000,2000),(4000,2000)
// (0000,1000),(1000,1000),(2000,1000),(3000,1000),(4000,1000)
// (0000,0000),(1000,0000),(2000,0000),(3000,0000),(4000,0000)
//------------------------------------------------------------------
herr_t create_many_points(hid_t group_id, hid_t p_tid)
{
int i,j,k;
herr_t rstat;
hid_t point_dataset;
hid_t myspace;
hid_t obj_group;
hsize_t mydim[1];
point_t many_points[NO_OF_MANY_POINTS];
//
// Populate the Points in a memory buffer
//
k = 0;
for(i = 0; i<5; ++i){
for(j = 0; j<5; ++j){
many_points[k].set_unset_bitmap = 7;
many_points[k].id = k;
many_points[k].x = j*1000.;
many_points[k].y = i*1000.;
++k;<s
}
}
//
// Create the group that shall contain the dataset
//
obj_group = H5Gcreate(group_id, "Many_Point_objects", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
//
// Create the dataset that shall contain the Points
//
mydim[0] = NO_OF_MANY_POINTS;
myspace = H5Screate_simple(1, mydim, NULL);
point_dataset = H5Dcreate1(obj_group, "Many_Point_instances", p_tid, myspace, H5P_DEFAULT);
//
// Write the Points to the dataset
//
rstat = H5Dwrite(point_dataset, p_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, many_points);
return(rstat);
}
The following text fragment represents a dump of an HDF5 file resultant from encoding the complete context schema into an HDF5 file applying the mapping rules described in this part of ISO 10303. It combines the results of all the examples described in this annex.
HDF5 "example.h5" {
GROUP "/" {
GROUP "Geometry_encoding" {
ATTRIBUTE "iso_10303_26_schema" {
DATATYPE H5T_STRING {
STRSIZE 16;
STRPAD H5T_STR_NULLTERM;
CSET H5T_CSET_ASCII;
CTYPE H5T_C_S1;
}
DATASPACE SCALAR
DATA {
(0): "Geometry_schema"
}
}
DATATYPE "AGGREGATE_REFERENCE_1" H5T_COMPOUND {
H5T_STD_B8LE "obj_ref_or_vlen";
H5T_REFERENCE "object_reference";
H5T_VLEN { H5T_VLEN { H5T_COMPOUND {
H5T_STD_I32LE "_HDF5_dataset_index_";
H5T_STD_I32LE "_HDF5_instance_index_";
}}} "vlen_array";
}
DATATYPE "AGGREGATE_REFERENCE_2" H5T_COMPOUND {
H5T_STD_B8LE "obj_ref_or_vlen";
H5T_REFERENCE "object_reference";
H5T_VLEN { H5T_VLEN { H5T_VLEN { H5T_IEEE_F64LE}}} "vlen_array";
}
DATATYPE "CColour" H5T_COMPOUND {
H5T_STD_I32LE "select_bitmap";
H5T_STRING {
STRSIZE H5T_VARIABLE;
STRPAD H5T_STR_NULLTERM;
CSET H5T_CSET_ASCII;
CTYPE H5T_C_S1;
} "s_colour";
H5T_ENUM {
H5T_STD_I16LE;
"VVOID" 0;
"RED" 1;
"GREEN" 2;
"BLUE" 3;
"WHITE" 4;
"BLACK" 5;
} "e_colour";
}
DATATYPE "Colour" H5T_ENUM {
H5T_STD_I16LE;
"VVOID" 0;
"RED" 1;
"GREEN" 2;
"BLUE" 3;
"WHITE" 4;
"BLACK" 5;
};
DATATYPE "Land_survey" H5T_COMPOUND {
H5T_STD_I32LE "set_unset_bitmap";
H5T_STD_I32LE "Entity-Instance-Identifier";
H5T_STRING {
STRSIZE H5T_VARIABLE;
STRPAD H5T_STR_NULLTERM;
CSET H5T_CSET_ASCII;
CTYPE H5T_C_S1;
} "country";
H5T_COMPOUND {
H5T_STD_B8LE "obj_ref_or_vlen";
H5T_REFERENCE "object_reference";
H5T_VLEN { H5T_VLEN { H5T_COMPOUND {
H5T_STD_I32LE "_HDF5_dataset_index_";
H5T_STD_I32LE "_HDF5_instance_index_";
}}} "vlen_array";
} "properties";
H5T_COMPOUND {
H5T_STD_B8LE "obj_ref_or_vlen";
H5T_REFERENCE "object_reference";
H5T_VLEN { H5T_VLEN { H5T_VLEN { H5T_IEEE_F64LE}}} "vlen_array";
} "altitudes";
}
DATATYPE "Line" H5T_COMPOUND {
H5T_STD_I32LE "set_unset_bitmap";
H5T_STD_I32LE "Entity-Instance-Identifier";
H5T_COMPOUND {
H5T_STD_I32LE "_HDF5_dataset_index_";
H5T_STD_I32LE "_HDF5_instance_index_";
} "startp";
H5T_COMPOUND {
H5T_STD_I32LE "_HDF5_dataset_index_";
H5T_STD_I32LE "_HDF5_instance_index_";
} "endp";
H5T_COMPOUND {
H5T_STD_I32LE "select_bitmap";
H5T_STRING {
STRSIZE H5T_VARIABLE;
STRPAD H5T_STR_NULLTERM;
CSET H5T_CSET_ASCII;
CTYPE H5T_C_S1;
} "s_colour";
H5T_ENUM {
H5T_STD_I16LE;
"VVOID" 0;
"RED" 1;
"GREEN" 2;
"BLUE" 3;
"WHITE" 4;
"BLACK" 5;
} "e_colour";
} "colour";
}
DATATYPE "Point" H5T_COMPOUND {
H5T_STD_I32LE "set_unset_bitmap";
H5T_STD_I32LE "Entity-Instance-Identifier";
H5T_IEEE_F64LE "x";
H5T_IEEE_F64LE "y";
}
DATATYPE "_HDF_INSTANCE_REFERENCE_HANDLE_" H5T_COMPOUND {
H5T_STD_I32LE "_HDF5_dataset_index_";
H5T_STD_I32LE "_HDF5_instance_index_";
}
}
GROUP "Geometry_population" {
ATTRIBUTE "_10303_26_data_set_names" {
DATATYPE H5T_ARRAY { [4] H5T_STRING {
STRSIZE H5T_VARIABLE;
STRPAD H5T_STR_NULLTERM;
CSET H5T_CSET_ASCII;
CTYPE H5T_C_S1;
} }
DATASPACE SCALAR
DATA {
(0): [ "Point", "Many_Point", "Line", "Land_survey" ]
}
}
ATTRIBUTE "iso_10303_26_data" {
DATATYPE H5T_STRING {
STRSIZE 16;
STRPAD H5T_STR_NULLTERM;
CSET H5T_CSET_ASCII;
CTYPE H5T_C_S1;
}
DATASPACE SCALAR
DATA {
(0): "Geometry_schema"
}
}
GROUP "Land_survey_objects" {
DATASET "Aggr-properties-1" {
DATATYPE H5T_VLEN { H5T_VLEN { H5T_COMPOUND {
H5T_STD_I32LE "_HDF5_dataset_index_";
H5T_STD_I32LE "_HDF5_instance_index_";
}}}
DATASPACE SIMPLE { ( 2 ) / ( 2 ) }
DATA {
(0): (({
1,
0
}, {
1,
1
}, {
1,
7
}, {
1,
11
}, {
1,
5
}), ({
1,
1
}, {
1,
2
}, {
1,
7
}), ({
1,
2
}, {
1,
9
}, {
1,
13
}, {
1,
7
})),
(1): (({
1,
2
}, {
1,
4
}, {
1,
9
}), ({
1,
5
}, {
1,
11
}, {
1,
7
}, {
1,
13
}, {
1,
16
}, {
1,
10
}))
}
}
DATASET "Land_survey_instances" {
DATATYPE "/Geometry_encoding/Land_survey"
DATASPACE SIMPLE { ( 1 ) / ( 1 ) }
DATA {
(0): {
15,
25,
"Norway",
{
0x01,
DATASET 17632 /Geometry_population/Land_survey_objects/Aggr-properties-1 ,
()
},
{
0x00,
NULL,
(((100, 101.1, 102.2, 103.3, 104.4), (200, 201.1, 202.2), (300, 301.1, 302.2, 303.3)), ((400, 401.1, 401.2), (500, 501.1, 502.2, 503.3, 504.4, 505.5)))
}
}
}
}
}
GROUP "Line_objects" {
DATASET "Line_instances" {
DATATYPE "/Geometry_encoding/Line"
DATASPACE SIMPLE { ( 4 ) / ( 4 ) }
DATA {
(0): {
7,
4,
{
0,
0
},
{
0,
1
},
{
2,
"",
RED
}
},
(1): {
7,
5,
{
0,
1
},
{
0,
2
},
{
2,
"",
BLUE
}
},
(2): {
7,
6,
{
0,
2
},
{
0,
3
},
{
1,
"Red line",
VVOID
}
},
(3): {
7,
7,
{
0,
3
},
{
0,
0
},
{
1,
"Blue line",
VVOID
}
}
}
}
}
GROUP "Many_Point_objects" {
DATASET "Many_Point_instances" {
DATATYPE "/Geometry_encoding/Point"
DATASPACE SIMPLE { ( 25 ) / ( 25 ) }
DATA {
(0): {
7,
0,
0,
0
},
(1): {
7,
1,
1000,
0
},
(2): {
7,
2,
2000,
0
},
(3): {
7,
3,
3000,
0
},
(4): {
7,
4,
4000,
0
},
(5): {
7,
5,
0,
1000
},
(6): {
7,
6,
1000,
1000
},
(7): {
7,
7,
2000,
1000
},
(8): {
7,
8,
3000,
1000
},
(9): {
7,
9,
4000,
1000
},
(10): {
7,
10,
0,
2000
},
(11): {
7,
11,
1000,
2000
},
(12): {
7,
12,
2000,
2000
},
(13): {
7,
13,
3000,
2000
},
(14): {
7,
14,
4000,
2000
},
(15): {
7,
15,
0,
3000
},
(16): {
7,
16,
1000,
3000
},
(17): {
7,
17,
2000,
3000
},
(18): {
7,
18,
3000,
3000
},
(19): {
7,
19,
4000,
3000
},
(20): {
7,
20,
0,
4000
},
(21): {
7,
21,
1000,
4000
},
(22): {
7,
22,
2000,
4000
},
(23): {
7,
23,
3000,
4000
},
(24): {
7,
24,
4000,
4000
}
}
}
}
GROUP "Point_objects" {
DATASET "Point_instances" {
DATATYPE "/Geometry_encoding/Point"
DATASPACE SIMPLE { ( 4 ) / ( 4 ) }
DATA {
(0): {
7,
0,
0,
0
},
(1): {
7,
1,
100,
0
},
(2): {
7,
2,
100,
100
},
(3): {
7,
3,
0,
100
}
}
}
}
}
}
}
// -------------------------------------------------------------------------------------------------------------------
// Main program that executes the examples found in the ISO-10303-P26 specification.
//
// In addition some dump functions are supplied, but these are not complete in the sense
// that all aspects of HDF5 are covered. Please consult the HDF5 documentation for those aspects that are missing.
// Please make use of the h5dump utility offered by the HDF group for a complete dump.
//
// Note:
// An application should close a datatype, dataspace, or dataset object once it is no longer needed.
// H5Tclose(datatype)
// H5Dclose(dataset)
// H5Sclose(dataspace)
// In this small prototype the closing of such objects has been omitted.
// Reclaim of memory has also been omitted.
// Such a practice is certainly not recommended for a real application
// Please consult the HDF5 documentation for the details.
//----------------------------------------------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hdf5.h"
#include "examples.h"
long dump_dataset(hid_t mydataset);
long dump_compound(hid_t mycompound_type, hsize_t curr_offset, char *mybuffer);
long dump_instance_by_reference(hid_t dataset_tid, long dataset_index, long instance_index);
long dump_aggr_by_reference(hid_t obj_tid, hobj_ref_t myref);
long dump_vlen_data(hid_t datatype, long members, char *vlen_data);
void error_trap(char *file_name, long lineno);
//------------------------------------------------------------------
#define HDF5_FILE "O:/projects/SimDM/HDF5/data/HDF5_files/example.h5"
#define REPORT_FILE "O:/projects/SimDM/HDF5/data/HDF5_files/rep_file.txt"
FILE *rep_file;
extern hid_t file_id;
extern char *defined_entity_names[NUMBER_OF_ENTITIES] = {"Point","Many_Point","Line","Land_survey"};
extern char *entity_names[NUMBER_OF_ENTITIES];
hid_t obj_ref_tid;
long level = 0;
long current_line;
char  *current_file;
long dump_in_aggr_mode = 0;
#define GOTO_ERR\
{\
current_file = __FILE__;\
current_line = __LINE__;\
error_trap(current_file,current_line);\
goto err;\
}
//
//------------------------------------------------------------------
//
void error_trap(char *file_name, long lineno)
{
fprintf(rep_file,"\nERROR trapped in '%s' at line: %lu",file_name,lineno);
}
void indent(void)
{
long ix;
fprintf(rep_file,"\n");
for(ix = 0; ix< level; ix++) {
fprintf(rep_file," ");
}
}
void indent_nlf(void)
{
long ix;
for(ix = 0; ix< level; ix++) {
fprintf(rep_file," ");
}
}
//------------------------------------------------------------------
// MAIN program
//------------------------------------------------------------------
int main(int argc, char* argv[])
{
herr_t mystatus;
hid_t dataset;
hid_t group_id;
hid_t p_tid;
hid_t l_tid;
hid_t lls_tid;
hid_t eenum_col_tid;
hid_t cc_tid;
hid_t pop_id;
hid_t attr_tid;
hid_t attr_type_tid;
hid_t native_type_tid;
obj_ref_tid = H5Tcopy(H5T_STD_REF_OBJ);
rep_file = fopen(REPORT_FILE,"w");
fprintf(rep_file,"\nWriting %s",REPORT_FILE);
//
// Create HDF5 file
//
file_id = H5Fcreate(HDF5_FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
//
// Create group for schemata
//
if(mystatus = create_schema_group(file_id, "Geometry_encoding", "Geometry_schema", &group_id)) GOTO_ERR;
//
// Create group for the population
//
if(mystatus = create_pop_group(file_id, "Geometry_population", "Geometry_schema", &pop_id)) GOTO_ERR;
//
// HDF5 definitions
//
if(mystatus = define_instance_reference(group_id)) GOTO_ERR;
if(mystatus = define_compound_point(group_id,&p_tid)) GOTO_ERR;
if(mystatus = define_colour_enumeration(group_id, &eenum_col_tid)) GOTO_ERR ;
if(mystatus = define_compound_colour(group_id, eenum_col_tid, &cc_tid)) GOTO_ERR;
if(mystatus = define_compound_line(group_id,cc_tid,&l_tid)) GOTO_ERR;
if(mystatus = define_compound_land_survey(group_id, &lls_tid)) GOTO_ERR;
//
// HDF5 population
//
if(mystatus = create_ppoints(pop_id, p_tid)) GOTO_ERR;
if(mystatus = create_llines(pop_id, l_tid)) GOTO_ERR;
if(mystatus = create_survey(pop_id, lls_tid, p_tid)) GOTO_ERR;
//
// Dump HDF5 population
//
attr_tid = H5Aopen_name(pop_id, "_10303_26_data_set_names");
if(attr_tid > 0){
attr_type_tid = H5Aget_type(attr_tid);
native_type_tid = H5Tget_native_type(attr_type_tid,H5T_DIR_ASCEND);
if(mystatus = H5Aread(attr_tid, native_type_tid, entity_names)) goto err;
if(mystatus = H5Aclose(attr_tid)) goto err;
if(mystatus = H5Tclose(attr_type_tid)) goto err;
if(mystatus = H5Tclose(native_type_tid)) goto err;
} else {
mystatus = -1;
goto err;
}
fprintf(rep_file,"\n\n=====================================================================================");
dataset = H5Dopen(file_id, "/Geometry_population/Line_objects/Line_instances", H5P_DEFAULT);
if( mystatus = dump_dataset(dataset)) GOTO_ERR;
if(mystatus = H5Dclose(dataset)) GOTO_ERR;
fprintf(rep_file,"\n\n=====================================================================================");
dataset = H5Dopen(file_id, "/Geometry_population/Land_survey_objects/Land_survey_instances", H5P_DEFAULT);
if(mystatus = dump_dataset(dataset)) GOTO_ERR;
if(mystatus = H5Dclose(dataset)) GOTO_ERR;
if(mystatus = H5Fclose(file_id)) GOTO_ERR;
goto ret;
err:
fprintf(rep_file,"\n\nERROR caught");
mystatus = H5Eprint2(H5E_DEFAULT, rep_file);
ret:
fprintf(rep_file,"\n\nClosing report file");
fclose(rep_file);
return(mystatus);
}
//------------------------------------------------------------------
// Dump dataset
//------------------------------------------------------------------
long dump_dataset(hid_t mydataset)
{
herr_t rstat;
hid_t mydataset_datatype;
H5T_class_t mydataset_datatype_class;
hsize_t mydataset_datatype_size;
hid_t mydataset_filespace;
hssize_t mydataset_noel;
hvl_t myvlen;
long ix;
char *mybuffer;
long myinteger;
double myreal;
//
// Get the datasets datatype, class, space and size
//
mydataset_datatype = H5Dget_type(mydataset);
mydataset_datatype_class = H5Tget_class(mydataset_datatype);
mydataset_datatype_size = H5Tget_size(mydataset_datatype);
mydataset_filespace = H5Dget_space(mydataset);
//
// Read the dataset
//
mydataset_noel = H5Sget_simple_extent_npoints(mydataset_filespace);
mybuffer = (char*) malloc((size_t)(mydataset_datatype_size*mydataset_noel));
if(mydataset_datatype_class == H5T_STRING){
if(rstat = H5Dread(mydataset, mydataset_datatype, mydataset_filespace, mydataset_filespace, H5P_DEFAULT, &mybuffer)) GOTO_ERR;
} else {
if(rstat = H5Dread(mydataset, mydataset_datatype, mydataset_filespace, mydataset_filespace, H5P_DEFAULT, mybuffer)) GOTO_ERR;
}
//
// Handle each element according to its datatype
//
for(ix = 0; ix< mydataset_noel; ix++) {
if(!dump_in_aggr_mode){
fprintf(rep_file,"\n--(%d)",ix);
}
switch(mydataset_datatype_class){
case H5T_INTEGER:
memcpy(&myinteger,mybuffer,sizeof(long));
mybuffer += sizeof(long);
indent();
fprintf(rep_file,"%lu",myinteger);
break;
case H5T_FLOAT:
memcpy(&myreal,mybuffer,sizeof(double));
mybuffer += sizeof(double);
indent();
fprintf(rep_file,"%f",myreal);
break;
case H5T_STRING:
indent();
fprintf(rep_file,"%s",mybuffer);
mybuffer += sizeof(char*);
break;
case H5T_COMPOUND:
++level;
indent();
if(rstat = dump_compound(mydataset_datatype,0,mybuffer)) GOTO_ERR;
mybuffer += mydataset_datatype_size;
--level;
break;
case H5T_VLEN:
memcpy(&myvlen,mybuffer,sizeof(hvl_t));
mybuffer += sizeof(hvl_t);
if(rstat = dump_vlen_data(mydataset_datatype,myvlen.len, myvlen.p)) GOTO_ERR;
break;
default:
indent();
fprintf(rep_file,"OOPS! Unhandled datatype");
}
}
err:
return(rstat);
}
//------------------------------------------------------------------
// Dump Compound type instance
//------------------------------------------------------------------
long dump_compound(hid_t mycompound_type, hsize_t curr_offset, char *mybuffer)
{
hsize_t mycompound_type_size;
int mycompound_type_members;
long dataset_index;
long instance_index;
long obj_ref_or_vlen;
long jx;
long len;
herr_t rstat;
char *mymember_name;
hvl_t myvlen;
hsize_t mymember_offset;
hsize_t myoffset;
hsize_t mymember_type_size;
hid_t mymember_type;
hid_t dataset_tid;
H5T_class_t mymember_class;
long myinteger;
double myreal;
short myenumval;
char *mystring;
char enum_name[10];
hobj_ref_t obj_ref;
enum colors_t mycolor;
char dataset_name[100];
rstat = 0;
mymember_name = H5Tget_member_name(mycompound_type,0);
if(!strcmp(mymember_name,"_HDF5_dataset_index_")){
memcpy(&dataset_index,mybuffer+curr_offset,sizeof(long));
memcpy(&instance_index,mybuffer+curr_offset+(sizeof(long)),sizeof(long));
strcpy(dataset_name,"/Geometry_population/");
strcat(dataset_name,entity_names[dataset_index]);
strcat(dataset_name,"_objects/");
strcat(dataset_name,entity_names[dataset_index]);
strcat(dataset_name,"_instances");
dataset_tid = H5Dopen(file_id, dataset_name, H5P_DEFAULT);
if(rstat = dump_instance_by_reference(dataset_tid,dataset_index,instance_index)) GOTO_ERR;
if(rstat = H5Dclose(dataset_tid)) GOTO_ERR;
return(rstat);
}
if(!strcmp(mymember_name,"obj_ref_or_vlen")){
obj_ref_or_vlen = (long)*(mybuffer +curr_offset);
if(obj_ref_or_vlen == 1){
curr_offset += sizeof(char);
memcpy(&obj_ref,mybuffer + curr_offset,sizeof(hobj_ref_t));
if(rstat = dump_aggr_by_reference(mycompound_type,obj_ref)) GOTO_ERR;
return(rstat);
}
if(obj_ref_or_vlen == 0){
curr_offset += sizeof(char) + sizeof(hobj_ref_t);
memcpy(&myvlen,mybuffer + curr_offset,sizeof(hvl_t));
mymember_type = H5Tget_member_type(mycompound_type,2);
if(rstat = dump_vlen_data(mymember_type,myvlen.len,myvlen.p)) GOTO_ERR;
return(rstat);
}
}
++level;
len = H5Iget_name(mycompound_type, NULL,0);
len = H5Iget_name(mycompound_type, dataset_name,len+1);
fprintf(rep_file,"%s:" ,dataset_name);
mycompound_type_size = H5Tget_size(mycompound_type);
mycompound_type_members = H5Tget_nmembers(mycompound_type);
//
// Handle membmer by member
//
for(jx = 0; jx< mycompound_type_members; jx++) {
indent();indent_nlf();
//
// Get the characteristics of the member
//
mymember_name = H5Tget_member_name(mycompound_type,jx);
mymember_type = H5Tget_member_type(mycompound_type,jx);
mymember_class = H5Tget_member_class(mycompound_type,jx);
mymember_offset = H5Tget_member_offset(mycompound_type,jx);
mymember_type_size = H5Tget_size(mymember_type);
myoffset = curr_offset + mymember_offset;
//
// Branch on datatype.
//
switch(mymember_class){
case H5T_INTEGER:
memcpy(&myinteger,mybuffer + myoffset,sizeof(long));
fprintf(rep_file,"%s: %lu",mymember_name,myinteger);
break;
case H5T_FLOAT:
memcpy(&myreal,mybuffer + myoffset,sizeof(double));
fprintf(rep_file,"%s: %f",mymember_name,myreal);
break;
case H5T_REFERENCE:
if(H5Tequal(obj_ref_tid,mymember_type)){
  fprintf(rep_file,"%s: ",mymember_name);
memcpy(&obj_ref,mybuffer + myoffset,sizeof(hobj_ref_t));
if(rstat = dump_aggr_by_reference(mycompound_type,obj_ref)) GOTO_ERR;
}
break;
case H5T_STRING:
memcpy(&mystring,mybuffer + myoffset,sizeof(char*));
fprintf(rep_file,"%s: %s",mymember_name,mystring);
break;
case H5T_COMPOUND:
fprintf(rep_file,"%s: ",mymember_name);
if(rstat = dump_compound(mymember_type,myoffset,mybuffer)) GOTO_ERR;
break;
case H5T_ENUM:
fprintf(rep_file,"%s: ",mymember_name);
memcpy(&mycolor,mybuffer + myoffset,sizeof(enum colors_t));
if(rstat = H5Tenum_nameof(mymember_type,&mycolor,enum_name,10)) GOTO_ERR;
if(rstat = H5Tenum_valueof(mymember_type,enum_name,&myenumval)) GOTO_ERR;
fprintf(rep_file,"%d : %s",myenumval,enum_name);
break;
case H5T_VLEN:
memcpy(&myvlen,mybuffer + myoffset,sizeof(hvl_t));
if(rstat = dump_vlen_data(mymember_type,myvlen.len,myvlen.p)) GOTO_ERR;
break;
default:
fprintf(rep_file,"\nOOPS! Unhandeled datatype");
}
}
--level;
err:
return(rstat);
}
//------------------------------------------------------------------
// Dump referenced aggregate
//------------------------------------------------------------------
long dump_aggr_by_reference(hid_t obj_tid, hobj_ref_t myref)
{
long mystatus;
hid_t dataset_reg;
mystatus = 0;
dump_in_aggr_mode = 1;
++level;
//
// Get the reference
//
dataset_reg = H5Rdereference(obj_tid, H5R_OBJECT,&myref);
if(dataset_reg < 0){
mystatus = -1;
GOTO_ERR;
}
//
// Dump the refered aggregate
//
mystatus = dump_dataset(dataset_reg);
--level;
err:
dump_in_aggr_mode = 0;
return(mystatus);
}
//------------------------------------------------------------------
// Dump referenced instance
//------------------------------------------------------------------
long dump_instance_by_reference(hid_t dataset_tid, long dataset_index, long instance_index)
{
long rstat;
hid_t mydataset_filespace;
hid_t dataset_datatype;
size_t dataset_datatype_size;
hsize_t mydim[1];
hid_t mymem_space;
hsize_t mycoord[1][1];
char *dataset_buffer;
//
// Read the selected instance
//
mydim[0] = 1;
mymem_space = H5Screate_simple(1, mydim, NULL);
dataset_datatype = H5Dget_type(dataset_tid);
dataset_datatype_size = H5Tget_size(dataset_datatype);
dataset_buffer = (char*) malloc(dataset_datatype_size);
mydataset_filespace = H5Dget_space(dataset_tid);
mycoord[0][0] = instance_index;
if(rstat = H5Sselect_elements(mydataset_filespace, H5S_SELECT_SET, 1, (const hsize_t *)&mycoord)) GOTO_ERR;
if(rstat = H5Dread(dataset_tid, dataset_datatype, mymem_space, mydataset_filespace, H5P_DEFAULT, dataset_buffer)) GOTO_ERR;
//
// Dump the instance from buffer
//
if(rstat = dump_compound(dataset_datatype,0,dataset_buffer)) GOTO_ERR;
free(dataset_buffer);
err:
return(rstat);
}
//------------------------------------------------------------------
// Dump VLEN data
//------------------------------------------------------------------
long dump_vlen_data(hid_t datatype, long members, char *vlen_data)
{
long rstat,i;
long super_size;
hid_t super_tid;
H5T_class_t super_class;
double myreal;
long myinteger;
short myenumval;
enum colors_t mycolor;
hobj_ref_t obj_ref;
char enum_name[10];
hvl_t myvlen;
char *p_myvlen;
rstat = 0;
p_myvlen = vlen_data;
//
// Get type of VLEN data
//
super_tid = H5Tget_super(datatype);
super_class = H5Tget_class(super_tid);
super_size = H5Tget_size(super_tid);
++level;++level;
indent();
fprintf(rep_file,"(");
//
// Branch on type for each element
//
for(i=0; i<members; ++i){
switch(super_class){
case H5T_INTEGER:
memcpy(&myinteger,p_myvlen,sizeof(long));
p_myvlen += sizeof(long);
fprintf(rep_file," %lu ",myinteger);
break;
case H5T_FLOAT:
memcpy(&myreal,p_myvlen,sizeof(double));
p_myvlen += sizeof(double);
fprintf(rep_file," %f ",myreal);
break;
case H5T_VLEN:
memcpy(&myvlen,p_myvlen,sizeof(hvl_t));
if(rstat = dump_vlen_data(super_tid,myvlen.len,myvlen.p)) GOTO_ERR;
p_myvlen += sizeof(hvl_t);
break;
case H5T_COMPOUND:
indent();
if(rstat = dump_compound(super_tid,0,p_myvlen)) GOTO_ERR;
p_myvlen += super_size;
break;
case H5T_REFERENCE:
if(H5Tequal(obj_ref_tid,super_tid)){
indent();
memcpy(&obj_ref,p_myvlen,sizeof(hobj_ref_t));
if(rstat = dump_aggr_by_reference(super_tid,obj_ref)) GOTO_ERR;
p_myvlen += super_size;
}
break;
case H5T_ENUM:
memcpy(&mycolor,p_myvlen,sizeof(enum colors_t));
p_myvlen += sizeof(enum colors_t);
if(rstat = H5Tenum_nameof(super_tid,&mycolor,enum_name,10)) GOTO_ERR;
if(rstat = H5Tenum_valueof(super_tid,enum_name,&myenumval)) GOTO_ERR;
fprintf(rep_file,"%d : %s",myenumval,enum_name);
break;
default:
fprintf(rep_file,"\nOOPS! Unhandeled datatype");
}
}
indent();
fprintf(rep_file,")");
--level;--level;
err:
return(rstat);
}
//
// Get dataset index
//
long get_dataset_index(char *entity_name)
{
long dataset_index,i;
dataset_index = -1;
for(i=0; i<NUMBER_OF_ENTITIES; ++i){
if(!strcmp(defined_entity_names[i],entity_name)){
return(i);
}
}
return(dataset_index);
}