E57 Foundation API v1.1.312  Aug. 10, 2011
Public Member Functions
ImageFile Class Reference

An ASTM E57 3D format file object. More...

List of all members.

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.

Detailed Description

An ASTM E57 3D format file object.

Class overview

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.

The open/close state

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.

Extensions

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.

Class Invariant

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

 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines