E57 Foundation API v1.1.312
Aug. 10, 2011
|
An ASTM E57 3D format file object. More...
Public Member Functions | |
ImageFile (const ustring &fname, const ustring &mode, const ustring &configuration="") | |
Open an ASTM E57 imaging data file for reading/writing. | |
StructureNode | root () const |
Get the pre-established root StructureNode of the E57 ImageFile. | |
void | close () |
Complete any write operations on an ImageFile, and close the file on the disk. | |
void | cancel () |
Stop I/O operations and delete a partially written ImageFile on the disk. | |
bool | isOpen () const |
Test whether ImageFile is still open for accessing. | |
bool | isWritable () const |
Test whether ImageFile was opened in write mode. | |
ustring | fileName () const |
Get the file name the ImageFile was created with. | |
int | writerCount () const |
Get current number of open CompressedVectorWriter objects writing to ImageFile. | |
int | readerCount () const |
Get current number of open CompressedVectorReader objects reading from ImageFile. | |
void | extensionsAdd (const ustring &prefix, const ustring &uri) |
Declare the use of an E57 extension in an ImageFile being written. | |
bool | extensionsLookupPrefix (const ustring &prefix, ustring &uri) const |
Get URI associated with an E57 extension prefix in the ImageFile. | |
bool | extensionsLookupUri (const ustring &uri, ustring &prefix) const |
Get an E57 extension prefix associated with a URI in the ImageFile. | |
size_t | extensionsCount () const |
Get number of E57 extensions declared in the ImageFile. | |
ustring | extensionsPrefix (const size_t index) const |
Get an E57 extension prefix declared in an ImageFile by index. | |
ustring | extensionsUri (const size_t index) const |
Get an E57 extension URI declared in an ImageFile by index. | |
bool | isElementNameExtended (const ustring &elementName) const |
Test whether an E57 element name has an extension prefix. | |
void | elementNameParse (const ustring &elementName, ustring &prefix, ustring &localPart) const |
Parse element name into prefix and localPart substrings. | |
void | dump (int indent=0, std::ostream &os=std::cout) const |
Diagnostic function to print internal state of object to output stream in an indented format. | |
void | checkInvariant (bool doRecurse=true) |
Check whether ImageFile class invariant is true. | |
bool | operator== (ImageFile imf2) const |
Test if two ImageFile handles refer to the same underlying ImageFile. | |
bool | operator!= (ImageFile imf2) const |
Test if two ImageFile handles refer to different underlying ImageFile. |
An ASTM E57 3D format file object.
The ImageFile class represents the state of an ASTM E57 format data file. An ImageFile may be created from an E57 file on the disk (read mode). An new ImageFile may be created to write an E57 file to disk (write mode).
E57 files are organized in a tree structure. Each ImageFile object has a predefined root node (of type StructureNode). In a write mode ImageFile, the root node is initially empty. In a read mode ImageFile, the root node is populated by the tree stored in the .e57 file on disk.
An ImageFile object, opened in either mode (read/write), can be in one of two states: open or closed. An ImageFile in the open state is ready to perform transfers of data and to be interrogated. An ImageFile in the closed state cannot perform any further transfers, and has very limited ability to be interrogated. Note entering the closed state is different than destroying the ImageFile object. An ImageFile object can still exist and be in the closed state. When created, the ImageFile is initially open.
The ImageFile state can transition to the closed state in two ways. The programmer can call ImageFile::close after all required processing has completed. The programmer can call ImageFile::cancel if it is determined that the ImageFile is no longer needed.
Basically in an E57 file, "extension = namespace + rules + meaning". The "namespace" ensures that element names don't collide. The "rules" may be written on paper, or partly codified in a computer grammar. The "meaning" is a definition of what was measured, what the numbers in the file mean.
Extensions are identified by URIs. Extensions are not identified by prefixes. Prefixes are a shorthand, used in a particular file, to make the element names more palatable for humans. When thinking about a prefixed element name, in your mind you should immediately substitute the URI for the prefix. For example, think "http://www.example.com/DemoExtension:extra2" rather than "demo:extra2", if the prefix "demo" is declared in the file to be a shorthand for the URI "http://www.example.com/DemoExtension".
The rules are statements of: what is valid, what element names are possible, what values are possible. The rules establish the answer to the following yes/no question: "Is this extended E57 file valid?". The rules divide all possible files into two sets: valid files and invalid files.
The "meanings" part of the above equation defines what the files in the first set, the valid files, actually mean. This definition usually comes in the form of documentation of the content of each new element in the format and how they relate to the other elements.
An element name in an E57 file is a member of exactly one namespace (either the default namespace defined in the ASTM standard, or an extension namespace). Rules about the structure of an E57 extension (what element names can appear where), are implicitly assumed only to govern the element names within the namespace of the extension. Element names in other namespaces are unconstrained. This is because a reader is required to ignore elements in namespaces that are unfamiliar (to treat them as if they didn't exist). This enables a writer to "tack on" new elements into pre-defined structures (e.g. structures defined in the ASTM standard), without fear that it will confuse a reader that is only familiar with the old format. This allows an extension designer to communicate to two sets of readers: the old readers that will understand the information in the old base format, and the new-fangled readers that will be able to read the base format and the extra information stored in element names in the extended namespace.
A class invariant is a list of statements about an object that are always true before and after any operation on the object. An invariant is useful for testing correct operation of an implementation. Statements in an invariant can involve only externally visible state, or can refer to internal implementation-specific state that is not visible to the API user. The following C++ code checks externally visible state for consistency and throws an exception if the invariant is violated:
void ImageFile::checkInvariant(bool doRecurse) { // If this ImageFile is not open, can't test invariant (almost every call would throw) if (!isOpen()) return; // root() node must be a root node if (!root().isRoot()) throw E57_EXCEPTION1(E57_ERROR_INVARIANCE_VIOLATION); // Can't have empty fileName if (fileName() == "") throw E57_EXCEPTION1(E57_ERROR_INVARIANCE_VIOLATION); int wCount = writerCount(); int rCount = readerCount(); // Can't have negative number of readers if (rCount < 0) throw E57_EXCEPTION1(E57_ERROR_INVARIANCE_VIOLATION); // Can't have negative number of writers if (wCount < 0) throw E57_EXCEPTION1(E57_ERROR_INVARIANCE_VIOLATION); // Can't have more than one writer if (1 < wCount) throw E57_EXCEPTION1(E57_ERROR_INVARIANCE_VIOLATION); // If have writer if (wCount > 0) { // Must be in write-mode if (!isWritable()) throw E57_EXCEPTION1(E57_ERROR_INVARIANCE_VIOLATION); // Can't have any readers if (rCount > 0) throw E57_EXCEPTION1(E57_ERROR_INVARIANCE_VIOLATION); } // Extension prefixes and URIs are unique const size_t eCount = extensionsCount(); for (size_t i = 0; i < eCount; i++) { for (size_t j = i+1; j < eCount; j++) { if (extensionsPrefix(i) == extensionsPrefix(j)) throw E57_EXCEPTION1(E57_ERROR_INVARIANCE_VIOLATION); if (extensionsUri(i) == extensionsUri(j)) throw E57_EXCEPTION1(E57_ERROR_INVARIANCE_VIOLATION); } } // Verify lookup functions are correct for (size_t i = 0; i < eCount; i++) { ustring goodPrefix = extensionsPrefix(i); ustring goodUri = extensionsUri(i); ustring prefix, uri; if (!extensionsLookupPrefix(goodPrefix, uri)) throw E57_EXCEPTION1(E57_ERROR_INVARIANCE_VIOLATION); if (uri != goodUri) throw E57_EXCEPTION1(E57_ERROR_INVARIANCE_VIOLATION); if (!extensionsLookupUri(goodUri, prefix)) throw E57_EXCEPTION1(E57_ERROR_INVARIANCE_VIOLATION); if (prefix != goodPrefix) throw E57_EXCEPTION1(E57_ERROR_INVARIANCE_VIOLATION); } // If requested, check all objects "below" this one if (doRecurse) root().checkInvariant(doRecurse); } // end ImageFile::checkInvariant