aboutsummaryrefslogtreecommitdiff
path: root/doc/html/UsingC++.html
diff options
context:
space:
mode:
Diffstat (limited to 'doc/html/UsingC++.html')
-rw-r--r--doc/html/UsingC++.html442
1 files changed, 442 insertions, 0 deletions
diff --git a/doc/html/UsingC++.html b/doc/html/UsingC++.html
new file mode 100644
index 0000000..15622d0
--- /dev/null
+++ b/doc/html/UsingC++.html
@@ -0,0 +1,442 @@
+<html>
+ <head>
+ <title>IEEE IO C++ Interface</title>
+ </head>
+ <body bgcolor="#F0F0F0">
+ <table><tr>
+ <td><img src="Images/info.gif"></td>
+ <td><h1>C++</h1></td>
+ </tr></table>
+ <hr>
+ <h1>Using the C++ Interface</h1>
+ To use the C++ interface, you must include the
+ headers <b>IO.hh</b> and <b>IEEEIO.hh</b>. If you only require
+ the IEEEIO interface, you link only with <b>libieeeio.a</b> using
+ <code>-L$IEEE_DIRECTORY/lib -lieeeio</code>.<p>
+
+ If you
+ also want HDF support you must also include the header
+ <b>HDFIO.hh</b> and link with <b>libhdfio.a</b> and
+ the usual complement of HDF libraries using
+ <code>-L$HDF_DIRECTORY/lib -L$IEEE_DIRECTORY/lib -lhdfio
+ -lieeeio -lmfhdf -ldf -ljpeg -lz</code>.
+ <hr>
+ <h1>C++ Methods</h1>
+ <UL>
+ <LI><a href="#Opening">Opening and Closing Datafiles</a>
+ <LI><a href="#Writing">Writing Datasets</a>
+ <LI><a href="#Reading">Reading Datasets</a>
+ <LI><a href="#Seeking">Random Access to Datasets <i>(Seeking)</i></a>
+ <LI><a href="#WriteAttribs">Writing Attributes</a>
+ <LI><a href="#ReadAttribs">Reading Attributes</a>
+ <LI><a href="#WriteAnn">Writing Annotations</a>
+ <LI><a href="#ReadAnn">Reading Annotations</a>
+ <LI><a href="#ReadWriteChunk">Writing and Reading in Chunks</a>
+ </UL>
+
+ <hr>
+ <a name="Opening"><h2>Opening</h2></a>
+ To open an IEEEIO file, you simply create a new IEEEIO object.
+ The constructor handles the opening.<p>
+ <b>C++ Prototype</b><br>
+ <code>IEEEIO::IEEEIO(char *filename,IObase::AccessMode accessmode);</code><br>
+ <DL>
+ <DT><i>filename</i>:
+ <DD>The name of the IEEEIO data file to
+ open. The typical extension for these files is <i>.raw</i>
+ <DT><i>accessmode</i>:
+ <DD>The accessmode for the file. This is
+ one of 3 different access modes
+ <!--<DL>
+ <DT><i>IObase::Read</i>:
+ <DD>Opens a file in read-only mode.
+ <DT><i>IObase::Create</i>:
+ <DD>Opens a file in write-only mode. If the file does not exist, it will be created. If it does exist, it will be truncated.
+ <DT><i>IObase::Append</i>:
+ <DD>Opens a file in read/write mode. The file pointer is automatically placed at the end of the file for appending, but random-access read operations are allowed as well.
+ </DL>-->
+ <UL>
+ <LI><b>IObase::Read</b>:
+ Opens a file in read-only mode.
+ <LI><b>IObase::Create</b>:
+ Opens a file in write-only mode. If the file does not exist, it will be created. If it does exist, it will be truncated.
+ <LI><b>IObase::Append</b>:
+ Opens a file in read/write mode. The file pointer is automatically placed at the end of the file for appending, but random-access read operations are allowed as well.
+ </UL>
+ </DL>
+
+ Since this is inherited from the IO base class, you can assign
+ the newly created object to a pointer to the base class and
+ deal with it generically.<br>
+<pre>
+ IO *writer = new IEEEIO("datafileout.raw",IObase::Create);
+ IO *reader = new IEEEIO("datafilein.raw",IObase::Read);
+</pre><br>
+ You can test if the file was opened successfully using the IObase::isValid() method.<br>
+<pre>
+ if(!reader->isValid())
+ puts("The file you specified does not exist or is not in a readable format");
+</pre><br>
+
+ Other IO systems can be inherited from the IO base class. So
+ for instance, to read HDF files you simply link with the the HDFIO
+ and HDF libraries and open using;
+ <pre>
+ IO *writer = new HDFIO("datafileout.raw",IObase::Create);
+ IO *reader = new HDFIO("datafilein.raw",IObase::Read);
+ </pre>
+
+ After the files are opened, you can use the methods in the
+ baseclass IO to do all of your reading and writing in a completely
+ generic manner regardless of the implementation of the underlying
+ IO system so long as the underlying IO system implements the
+ methods of the base class. There are plans, for example, to have
+ a SocketIO system that allows the data to be written out to a TCP
+ socket instead of to a file for real-time simulation-visualization
+ systems. There are also plans to use this interface to drive an
+ existing Parallel IO system.<p>
+
+To close the file, you simply delete the object.
+<pre>
+ delete writer;
+ delete reader;
+</pre>
+ Since virtual destructors are used, you can delete them as
+ objects of the base IO class (no casts required).
+
+ <hr>
+ <a name="Writing"><h2>Writing</h2></a>
+ To write data you simply use the method write().
+ <p><b>C++ Prototype</b><br>
+ <code>IEEEIO::write(IObase::DataType numbertype,int rank,int *dimensions,void *data);</code>
+ <DL>
+ <DT><i>numbertype</i>:
+ <DD>The type of the data being stored
+ (as defined in <a href="DataTypes.html">DataType.html</a>).
+ It can be one of
+ <UL>
+ <LI><b>IObase::Float32</b><br><i>32-bit single-precision IEEE float</i>
+ <LI><b>IObase::Float64</b><br><i>64-bit double-precision IEEE float</i>
+ <LI><b>IObase::Int8</b><br><i>byte</i>
+ <LI><b>IObase::Int16</b><br><i>16-bit short integer</i>
+ <LI><b>IObase::Int32</b><br><i>32-bit standard integer</i>
+ <LI><b>IObase::Int64</b><br><i>64-bit long integer. (note:
+ this is not availible on the Intel/Windows
+ platform)</i>
+ <LI><b>IObase::uInt8</b><br><i>unsigned character</i>
+ <LI><b>IObase::uInt16</b><br><i>unsigned 16-bit short integer</i>
+ <LI><b>IObase::uInt32</b><br><i>unsigned 32-bit standard integer</i>
+ <LI><b>IObase::uInt64</b><br><i>unsigned 64-bit long integer. (note: this is not availible on the Intel/Windows platform)</i>
+ </UL>
+ <DT><i>rank</i>
+ <DD>Number of dimensions of the dataset
+ <DT><i>dimensions</i>:
+ <DD>An array of <i>rank</i> integers that give the dimensions of the dataset
+ <DT><i>data</i>:
+ <DD>Your data array.
+ </DL>
+
+ So to write a sample array of data.
+ <pre>
+ float myarray[40][50][60]; // our bogus data array
+ int rank=3;
+ int dims[3]={60,50,40}; // notice these are reversed.
+ // this is because ieeeio assumes f77 order for data
+ // and c/c++ use exactly the opposite ordering for data in memory.
+ IO *writer=new IEEEIO("datafile.raw",IObase::Create); // create a outfile
+ writer->write(IObase::Float32,rank,dims,myarray); // write a dataset
+ . . . . you can write as many datasets as you want
+ delete writer; // then close the file
+ </pre>
+
+ <hr>
+ <a name="Reading"><h2>Reading Data</h2></a>
+ Reading is a two step process. First you get information on
+ the size and type of the data you intend to read. This allows
+ you to allocate an array of the proper size and type for the
+ reading. Then you actually read the data into a pre-allocated
+ array. The methods for this are readInfo() and read().<p>
+ <b>C++ Prototype</b><br>
+ <code>readInfo(IObase::DataType &numbertype,int &rank,int
+ *dims,int maxdims=3);</code><p>
+ <DL>
+ <DT><i>numbertype</i>:
+ <DD>The type of the data being stored
+ <i>(<a href="DataTypes.html">datatype definition</a>)</i>.
+ It can be one of
+ <UL>
+ <LI><b>IObase::Float32</b><br><i>32-bit single-precision IEEE float</i>
+ <LI><b>IObase::Float64</b><br><i>64-bit double-precision IEEE float</i>
+ <LI><b>IObase::Int8</b><br><i>byte</i>
+ <LI><b>IObase::Int16</b><br><i>16-bit short integer</i>
+ <LI><b>IObase::Int32</b><br><i>32-bit standard integer</i>
+ <LI><b>IObase::Int64</b><br><i>64-bit long integer. (note:
+ this is not availible on the Intel/Windows
+ platform)</i>
+ <LI><b>IObase::uInt8</b><br><i>unsigned character</i>
+ <LI><b>IObase::uInt16</b><br><i>unsigned 16-bit short integer</i>
+ <LI><b>IObase::uInt32</b><br><i>unsigned 32-bit standard integer</i>
+ <LI><b>IObase::uInt64</b><br><i>unsigned 64-bit long integer. (note: this is not availible on the Intel/Windows platform)</i>
+ </UL>
+ <DT><i>rank</i>
+ <DD>Number of dimensions of the dataset
+ <DT><i>dimensions</i>:
+ <DD>An array of <i>rank</i> integers that give the dimensions
+ of the dataset
+ <DT><i>maxdims</i>:
+ <DD>The maximum size of the dimensions array you given it.
+ This prevents array overruns if the dataset has more
+ dimensions than you were anticipating. The default is 3 but
+ it can be any arbitrary positive integer.
+ </DL>
+ This retrieves information about the datatype, rank,
+ and dimensions of the dataset to be retrieved.
+ By default the maximum size of the dimensions array is 3,
+ but you can set it to be larger.<p>
+ <b>C++ Prototype</b><br>
+ <code>
+ IEEEIO::read(void *data);
+ </code><p>
+ This actually reads the dataset into the preallocated array <i>data</i>.<p>
+
+ Another useful utility function is IObase::sizeOf() which returns the number of bytes in a give IObase:: datatype in manner analogous to the standard C sizeof() operator.
+
+ So for instance, to read a simple dataset, you would do
+ <pre>
+ int rank;
+ IObase::DataType numbertype;
+ int dims[3];
+ float *data; // assumes float data
+ IO *infile = new IEEEIO("dataset.raw",IObase::Read);
+ infile-&gtreadInfo(numbertype,rank,dims);
+ // OK, we are assuming a 3D IObase::Float32 array,
+ // but you can be more sophisticated...
+ data = new char[IObase::nBytes(numbertype,rank,dims)];
+ // You can also use
+ // data = new float[IObase::nElements(rank,dims)];
+ infile-&gtread(data); // read in the data
+ </pre><p>
+
+ Since multiple datasets can be stored in a file, you can
+ retrieve them in the order they were written <i>(there is a <a
+href="#Seeking">seek()</a> function that allows random access as well)</i>. The method <b>readInfo()</b> implies reading the next dataset stored in the file. The method <b>nDatasets()</b> tells how many datasets are in a file. So typically if you want to read all datasets in a file in order, you would use code similar to;
+ <pre>
+ IO *infile = new IEEEIO("dataset.raw",IObase::Read);
+ for(int i=0;i&ltinfile-&gtnDatasets();i++){
+ .....lots of code....
+ infile->readInfo(numbertype,rank,dims); // increments to next dataset
+ .....more code....
+ }
+ </pre>
+
+ <hr>
+ <a name="Seeking"><h2>Random Access to Datasets
+ <i>(Seeking)</i></h2></a>
+ You can select specific datasets in a file using the seek()
+ method.<p>
+ <b>C++ Prototype</b>
+ <code>IEEEIO::seek(int index)</code>
+ <DL>
+ <DT><b>index</b>
+ <DD>The index of the dataset you want to read from. This can
+ be any number from 0 to (number_of_datasets - 1).
+ </DL>
+
+ <hr>
+ <a name="WriteAttribs"><h2>Writing Attributes</h2></a>
+ Attributes allow you to attach extra information to each
+ dataset stored in the file. Each attribute has a name and an
+ array of data (of any of the standard IObase:: types) stored with
+ it. These attributes can be retrieved by name or by integer
+ index in the order in which they were stored. A typical
+ attribute would typically be parameters that describe the grid
+ or the data like, "origin" which would be the 3-vector of floats
+ which locates of the origin of a grid in 3-space. The method
+ used to write these attributes is writeAttribute();<p>
+ <b>C++ Prototype</b><br>
+ <code>
+ IEEEIO::writeAttribute(char *name,IObase::DataType numbertype,int length,void *data)
+ </code><p>
+ <DL>
+ <DT><i>name</i>:
+ <DD>Name of the attribute (like "origin" or "coordinates")
+ <DT><i>numbertype</i>:
+ <DD>The type of the data array associated with the attribute
+ <i>(<a href="DataTypes.html">datatype definition</a>)</i>
+ <DT><i>length</i>:
+ <DD>The number of elements in the data array.
+ <DT><i>data</i>:
+ <DD>The attribute data.
+ </DL><p>
+ So to write an attribute named <i>origin</i> along with a 3-vector float for the coordinates of the origin, you would use;
+ <pre>
+ float origin[3]={5.1,0.3,0.5};
+ // and assuming the file is already open for writing
+ // the following attribute will be attached to the last
+ // written dataset. (you must have write data before adding attribs)
+ writer->writeAttribute("origin",IObase::Float32,3,origin);
+ </pre>
+
+ <hr>
+ <a name="ReadAttribs"><h2>Reading Attributes</h2></a>
+ The attributes can be retrieved in the order they were written
+ or they can be retrieved by their name. To retrieve the
+ attributes in order, you would utilize the <b>nAttributes()</b>
+ method to determine how many attributes are attached,
+ <b>readAttributeInfo()</b> to get the size and type of the
+ attribute, and <b>readAttribute()</b> to read the attribute
+ data.<p>
+ <b>C++ Prototype</b><br>
+ <code>int IEEEIO::nAttributes()</code><p>
+ <DL>
+ <DT><i>returnvalue</i>:
+ <DD>Number of attributes in the file
+ </DL><p>
+ <b>C++ Prototype</b><br>
+ <code>IEEEIO::readAttributeInfo(int index,char *name,IObase::DataType &numbertype,int &length,int maxnamelength=128);
+ </code>
+ <DL>
+ <DT><i>index</i>:
+ <DD>The index of the attribute which can be 0 to (nattributes-1)
+ <DT><i>name</i>:
+ <DD>A buffer in which the name of the attribute will be placed.
+ <DT><i>numbertype</i>:
+ <DD>The type of the attribute data
+ <i>(<a href="DataTypes.html">datatype definition</a>)</i>
+ <DT><i>length</i>:
+ <DD>The number of elements in the attribute data.
+ <DT><i>maxnamelength</i>:<DD>The maximum size of a name that can be stored in the <b>name</b> buffer. The default maximum is 128, but can be set to any size.
+ </DL>
+<p>
+ <b>C++ Prototype</b><br>
+ <code>IEEEIO::readAttribute(int index,void *data);</code>
+ <DL>
+ <DT><i>index</i>:
+ <DD>The index of the attribute data to read
+ <DT><i>data</i>:
+ <DD>The array into which the attribute data is copied.
+ </DL>
+ So for example, to read the attributes in order, you can use
+ <pre>
+ for(int i=0;i&ltinfile-&gtnAttributes();i++){
+ char name[128];
+ int length;
+ IObase::DataType datatype;
+ ...
+ infile->readAttributeInfo(i,name,datatype,length);
+ ... // allocate some data for storage
+ infile->readAttribute(i,data);
+ }
+ </pre><p>
+
+ The attributes can also be retrieve by name. In fact,
+ the is the most likely way you will use the attibutes interface.
+ The readAttributeInfo() method is overloaded to allow retrieval
+ by name as well. It returns the index of the attribute if one
+ is found with a matching name: it returns -1 if one is not
+ found.
+ <p><b>C++ Prototype</b><br>
+ <code>
+ int IEEEIO::readAttributeInfo(char *name,IObase::DataType &numbertype,int &length);
+ </code>
+ <DL>
+ <DT><i>returnvalue</i>:
+ <DD>The index of the attribute if found or -1 if no attribute with matching name is found.
+ <DT><i>name</i>:
+ <DD>The name of the attribute to find.
+ <DT><i>numbertype</i>:
+ <DD>Returns the numbertype of the stored attribute data
+ <i>(<a href="DataTypes.html">datatype definition</a>)</i>
+ <DT><i>length</i>:
+ <DD>he length of the stored attribute data.
+ </DL>
+ So a typical use of this interface would be to find an attribute named "origin" and retrieve its data if it exists.
+ <pre>
+ int index = infile->readAttributeInfo("origin",datatype,length);
+ if(index>=0) // the attribute exists
+ infile->readAttribute(index,data);
+ else
+ puts("The attribute origin could not be found");
+ </pre>
+
+ </pre>
+
+ <hr>
+ <a name="WriteAnn"><h2>Writing Annotations</h2></a>
+ An annotation is a text string which can be used to
+ describe a dataset. To write an annotation, you use the
+ writeAnnotation() method.<p>
+ <b>C++ Prototype</b><br>
+ <code>
+ IEEEIO::writeAnnotation(char *annotationtext)
+ </code>
+ <DL>
+ <DT><i>annotationtext</i>:
+ <DD>A null terminated string of the annotation text
+ </DL>
+ The annotation will be attached to the last written dataset.
+ You can store more than one annotation per dataset and the
+ annotations can be of arbitrary length.<p>
+
+ <hr>
+ <a name="ReadAnn"><h2>Reading Annotations</h2></a>
+ The annotations are stored in the order they are written. The
+ method <b>nAnnotations()</b> is used to find out how many
+ attributes are attached to a dataset. The method
+ <b>readAnnotationInfo()</b> is used to find the length of the
+ annotation and <b>readAnnotatin()</b> reads the actual
+ annotation text.<p>
+ <b>C++ Prototype</b><br>
+ <code>
+ int nAnnotations();
+ </code>
+ <DL>
+ <DT><i>returnvalue</i>:
+ <DD>Number of annotations attached to current dataset.
+ </DL><p>
+ <b>C++ Prototype</b><br><code>
+ readAnnotationInfo(int index,int &length)
+ </code>
+ <DL>
+ <DT><i>index</i>:
+ <DD>Index of the annotations which can be 0 to (nannotations-1)
+ <DT><i>length</i>:
+ <DD>Length in characters of the annotation. This includes the null-terminating character.
+ </DL>
+ <hr>
+ <a name="ReadWriteChunk"><h2>Writing and Reading in Chunks</h2></a>
+ For distributed-memory programming paradigms like HPF, MPI, or
+ PVM, it is often not unfeasible to write data to disk in a
+ single operation. For this reason, a <i>chunking</i> interface
+ is provided which allows you to write data in blocks to the
+ disk.<p>
+ To begin a chunk writing operation, you must first reserve a
+ data chunk in the file. This is accomplished using <b>reserveChunk()</b>
+ <b>C++ Prototype</b><br>
+ <code>IObase::reserveChunk(IObase::DataType datatype,int rank,int *dims);
+ </code><p>
+ Once space has been allocated in the datafile, you can write
+ blocks of data specified by their dimensions and origin using
+ <b>writeChunk()</b>
+ <b>C++ Prototype</b><br>
+ <code>
+ int IObase::IOwriteChunk(int *dims,int *origin,void *data);
+ </code><p>
+ Likewise, it is possible to read chunks from the disk as
+ well. No special procedure is required to select a record to
+ read in chunks. Simply use <a href="#Reading">readInfo()</a>
+ to get the dimensions and
+ type of the dataset and then use <b>readChunk()</b> in place
+ of <b>read()</b> in order to read-in the data.
+ <b>C++ Prototype</b><br>
+ <code>
+ int IObase::readChunk(int *dims,int *origin,void *data);
+ </code><p>
+ <hr>
+ <address><a href="mailto:jshalf@suttung.aei-potsdam.mpg.de">John Shalf</a></address>
+ <!-- Created: Mon Apr 7 12:52:52 MDT 1997 -->
+ <!-- hhmts start -->
+Last modified: Thu Feb 4 21:53:13 CST 1999
+<!-- hhmts end -->
+ </body>
+</html>