Io


Int64

Writing block files is pretty simple. There is a stack which represents the levels of block nesting. Each stack entry points to a block header with the position and size of the block for deferred writing. A block does not count the length of any block higher in the stack until those blocks have been closed. Flags bits are used by the save state API.


LXe_IO_ERROR

These are error codes for this subsystem and all other I/O-related subsystems.

  • LXe_REF_BADID

  • LXe_REF_BADPTR

  • LXe_REF_DUPLICATE

  • LXe_IO_SHORTREAD

  • LXe_IO_NEEDGL

  • LXe_IO_TRUNCATED

  • LXe_IO_PARTIALSTRING

LXtBlockHeader

struct st_LXtBlockHeader

Block streams are also style-transparent, reading and writing using the same API for both text and binary streams. As result, blocks have to be identified by both a binary ID code and a text string. Internally, the binary ID code value is always used.

Public Members

LXtID4 id
const char *token

LXfBLKS_FORCE

For string reading, there are two modes - FORCE and RAW. Force will raise an exception if the string is not found. If not set, however, the function will return true if any string is read, including the empty string. RAW causes the stream to be read as a literal string, ignoring quotes and reading to eol.

  • LXfBLKS_RAW

ILxBlockRead

class ILxBlockRead

Block stream interfaces support block-structured I/O with multiple data types. There is an interface for reading and one for writing.

Public Functions

LxResult FindBlock(LXtObjectID self, const LXtBlockHeader *head, int flags, LXtID4 *blkId)

Function descriptions are not provided since these objects are not commonly encountered in nexus file I/O. TODO: fill these in.

void End(LXtObjectID self)
int Depth(LXtObjectID self)
LxResult ReadI1(LXtObjectID self, char *data, int count, int *ocount)
LxResult ReadI2(LXtObjectID self, short *data, int count, int *ocount)
LxResult ReadI4(LXtObjectID self, int *data, int count, int *ocount)
LxResult ReadU1(LXtObjectID self, unsigned char *data, int count, int *ocount)
LxResult ReadU2(LXtObjectID self, unsigned short *data, int count, int *ocount)
LxResult ReadU4(LXtObjectID self, unsigned int *data, int count, int *ocount)
LxResult ReadFP(LXtObjectID self, float *data, int count, int *ocount)
LxResult ReadFP8(LXtObjectID self, double *data, int count, int *ocount)
LxResult ReadString(LXtObjectID self, char *buf, int max, int flags, int *ocount)

Reading a string takes a buffer for the result and its size. If FORCE is true this will return an error if no string is found. If PARTIAL is true then as much string as can be found will be read into the buffer and LXe_IO_PARTIALSTRING will be returned if there is more left to read. Otherwise the entire string will always be read and LXe_IO_TRUNCATED will be returned if some of the string had to be discarded. The returned count is the number of characters read including the terminating null.

LxResult ReadIDCode(LXtObjectID self, const LXtBlockHeader *list, LXtID4 *idCode)
LxResult ReadVX(LXtObjectID self, unsigned *data, int count, int *ocount)
LxResult SetSourceEncoding(LXtObjectID self, unsigned encoding)

ReadString converts a text encoding of string to another text encoding given by the following methods using ILxTextEncoding service. The source encoding is the encoding for strings to read. The target encoding is for a string set to “buf” of ReadString. The text encoding convertion does not work with PARTIAL mode. The returned count is the number of characters read including the terminating null based on the source string.

LxResult SetTargetEncoding(LXtObjectID self, unsigned encoding)
LxResult SetMiniBlockHeight(LXtObjectID self, unsigned mini)
bool Read(short *val, bool force = true)

User Class Only: User class methods are relatively more C++ friendly, using argument types and throwing exceptions on errors. The read count is discarded for these methods because they require reading.

bool Read(unsigned short *val, bool force = true)
bool Read(int *val, bool force = true)
bool Read(unsigned int *val, bool force = true)
bool Read(float *val, bool force = true)
bool Read(double *val, bool force = true)
bool Read(std::string &result, bool force = true)

User Class Only: Reading strings in C++ does partial reads to build up an STL string. If force is true it will raise an exception if the string is not found. Otherwise no string and a valid empty string will both return false. The terminal string has a final null, which we don’t want included in the STL string.

  • LXfREADSTRING_FORCE

  • LXfREADSTRING_RAW

  • LXfREADSTRING_PARTIAL


LXfBLKW_LEAF

The write methods are very similar to the read methods. Function descriptions are not provided since these objects are not commonly encountered in nexus file I/O. TODO: fill these in. LEAF blocks can contain no sub-blocks. PARAM blocks are leaf blocks written at the start of a non-leaf block. In XML they are written into the block header, but otherwise are identical to normal blocks.

  • LXfBLKW_PARAM

ILxBlockWrite

class ILxBlockWrite

Block stream interfaces support block-structured I/O with multiple data types. There is an interface for reading and one for writing.

Public Functions

LxResult WriteBlock(LXtObjectID self, const LXtBlockHeader *head, int flags)
void End(LXtObjectID self)
int Depth(LXtObjectID self)
LxResult WriteI1(LXtObjectID self, const char *data, int count)
LxResult WriteI2(LXtObjectID self, const short *data, int count)
LxResult WriteI4(LXtObjectID self, const int *data, int count)
LxResult WriteU1(LXtObjectID self, const unsigned char *data, int count)
LxResult WriteU2(LXtObjectID self, const unsigned short *data, int count)
LxResult WriteU4(LXtObjectID self, const unsigned int *data, int count)
LxResult WriteFP(LXtObjectID self, const float *data, int count)
LxResult WriteFP8(LXtObjectID self, const double *data, int count)
LxResult WriteString(LXtObjectID self, const char *str)
LxResult WriteIDCode(LXtObjectID self, const LXtBlockHeader *ident)
LxResult WriteVX(LXtObjectID self, const unsigned int *data, int count)
LxResult SetSourceEncoding(LXtObjectID self, unsigned encoding)

WriteString converts a text encoding of string to another text encoding given by the following methods using ILxTextEncoding service. The source encoding is for a string set to “buf” of WriteString. The target encoding is the encoding for strings to write.

LxResult SetTargetEncoding(LXtObjectID self, unsigned encoding)
void Write(const short val)

User Class Only: User class methods are relatively more C++ friendly, using argument types and throwing exceptions on errors.

void Write(const unsigned short val)
void Write(const int val)
void Write(const unsigned int val)
void Write(const float val)
void Write(const double val)
void Write(const char *val)
void Write(const std::string &val)

ILxLoader

class ILxLoader

Public Functions

LxResult Recognize(LXtObjectID self, const char *filename, LXtObjectID loadInfo)

An ILxLoader interface is an extensible server for loading objects of many different classes. Methods on the loader interface are called in sequence. Specifically Recognize() is called to open a file, and Cleanup() is called to close it. Recognize() is given the filename and LoadInfo object, and it should return OK if the file can be loaded by this loader.

LxResult LoadInstance(LXtObjectID self, LXtObjectID loadInfo, LXtObjectID monitor, void **ppvObj)

The loader can also set other data by querying for additional interfaces based on object type. This is useful when doing a direct load to specify the attributes of the object to contain the data. For instance to do a direct load of an image the loader would query for ImageLoaderTarget and use its methods to set the pixel format and size of the destination image. The LoadInfo object can also be queried for a monitor. After recognition, the LoadInstance() method may be called to load opaque objects, in which case the new COM object should be returned in the void pointer. For non-opaque loads the (perhaps confusingly named) LoadObject() method may be called to load the data into the destination object.

LxResult LoadObject(LXtObjectID self, LXtObjectID loadInfo, LXtObjectID monitor, LXtObjectID dest)
void Cleanup(LXtObjectID self)

After any attempt at recognition Cleanup() will be called to allow the loader to close the file and reset its state.

LxResult SpawnOptions(LXtObjectID self, void **ppvObj)

This method creates an option object for this loader. This should have a StreamIO interface to allow it to be saved and loaded.

ILxLoaderInfo

class ILxLoaderInfo

Public Functions

LxResult TestClass(LXtObjectID self, const LXtGUID *clsGUID, unsigned *priority)

The LoaderInfo interface can be used to read the context of the load and to set the attributes that apply to this file. For loaders that can load more than one object type, TestClass() returns LXe_TRUE for classes that the client wants to accept. The priority for each type can be used to decide which one to accept, where lower is better.

LxResult SetClass(LXtObjectID self, const LXtGUID *clsGUID)

During recognition the loader can set information about a file that it’s capable of loading. All of this is optional. The class is the object type for loaders that can load more than one type. Flags can suggest opaque versus direct load and if the format has options. The format can be set if a different saver should be used for this object type.

LxResult SetFlags(LXtObjectID self, unsigned flags)
LxResult SetFormat(LXtObjectID self, const char *format)
  • LXfLOAD_OPAQUE

  • LXfLOAD_OPTIONS


LXsLOD_CLASSLIST

Tags define the classes this loader server supports and hints about the files that it might be able to process.

  • CLASSLIST a string of class aliases or GUIDs separated by spaces, such as “image

    animation”. These are the classes which this loader can support.

  • DOSPATTERN a pattern string for filenames in Microsoft Windows (really DOS) format. This is typically something like “*.avi;*.jpg”.

  • MACPATTERN a pattern string for Macintosh filetypes that might be read with this loader. This is typically something like “MooV;TTXT”.

  • THREADSAFE indicates whether the loader is threadsafe (i.e. multiple loaders of the same type can be executed at once). Values other than “Yes” are all interpreted as no.

  • LXsLOD_DOSPATTERN

  • LXsLOD_MACPATTERN

  • LXsLOD_THREADSAFE

ILxSaver

class ILxSaver

Public Functions

LxResult Verify(LXtObjectID self, LXtObjectID source, LXtObjectID message)

An ILxSaver interface knows how to save objects of a specific type. This is a very much simpler interface and just has a single function to perform the save to the given file using the given monitor. The Verify method allows the plugin to inform the user if parts of his scene will not be saved. The source is the object being saved.

LxResult Save(LXtObjectID self, LXtObjectID source, const char *filename, LXtObjectID monitor)

LXsSAV_OUTCLASS

Tags define the single class and file type.

  • OUTCLASS the class alias or GUID for objects that can be saved. (“image”)

  • DOSTYPE the three-character DOS file extension that should be used by default. (“JPG”)

  • MACTYPE the four-character Macintosh type code that should be applied to the new file. (“PICT”)

  • OVERWRITE indicates that the saver needs to original file in place in order to save changes into it. This disables any safety mechanism that renames the original file to prevent save errors from destroying data. Savers that set this tag to “1” are expected to handle save errors gracefully on their own.

  • SAVEAS indicates that the saver can be used in the Save As dialog. Save As will allow only savers that have appropriate loader to be listed and it’s comparing saver and loader by using server name. If you have named loader and saver for the same file format differently, then you can use this flag in order to get your saver to be displayed in the Save As dialog.

  • LXsSAV_DOSTYPE

  • LXsSAV_MACTYPE

  • LXsSAV_OVERWRITE

  • LXsSAV_SAVEAS

ILxMonitor

class ILxMonitor

These macros support calling the function vectors on monitor objects. If the monitor pointer is null, these do no harm. Init returns zero on failure and incr/step returns zero to continue. The Increment() method can be called directly to determine if it returned a failure code or LXe_ABORT. The most useful macros here are:

  • INIT() Returns true if the monitor was successfully initialized. This may return false to indicate that that the monitor was aborted as soon as it was opened, usually because it wound up being a sub-monitor of another monitor.

  • INCR() Increment a monitor by the given number of steps. Returns true if the user aborted, and false if it is still running.

  • STEP() Increment the monitor by one step. Returns true if the user aborted.

  • TEST() Returns true if the user aborted, and false if it is still running. Under the hood, this is simply calling INCR() with a step of 0, and will check for user input before returning. If you are running a long but unbounded task where you can’t step the monitor, this will allow you to check for aborts without the app appearing to be locked.

  • STATUS() Same as TEST(), but returns an LxResult code of LXe_ABORT if the user aborted, and LXe_OK if the monitor is still running.

Public Functions

LxResult Initialize(LXtObjectID self, unsigned int count)

An ILxMonitor interface allows progress tracking. The monitor is initialized with a max count, and each stage of processing increments the count by something. Initialize() takes the total number of steps the monitor has, and returns a result code. It is possible that the monitor will be immediately aborted, so you should check for LXe_ABORT codes from this call.

LxResult Increment(LXtObjectID self, unsigned int count)

This steps the monitor by the count provided. Care should be taken to keep from exceeding the total number of steps set with Initialize(). Of the user has aborted the operation, this method will return LXe_ABORT and the client should stop the operation. Commands normally set the LXe_ABORT code on their message object so that the caller knows that the command has been aborted by the user.

bool Init(unsigned int count)

User Class Only: The above macros are made more or less obsolete by the user class, which provides simpler methods which do nothing if there is no interface.

bool Step(unsigned int count = 1)
  • LXxMON_CALL

  • LXxMON_OCAL

  • LXxMON_INIT

  • LXxMON_INCR

  • LXxMON_STEP

  • LXxMON_TEST

  • LXxMON_STATUS

ILxStreamIO

class ILxStreamIO

Public Functions

LxResult Write(LXtObjectID self, LXtObjectID stream)

An ILxStreamIO interface allows any object to save or load itself on a block stream. The Write() method writes the underlying object to the block stream, while the Read() method reads the data and sets the state of the object to match the one that was written. The caller will have determined that an object of the right type follows in the stream.

LxResult Read(LXtObjectID self, LXtObjectID stream)

ILxIOService

class ILxIOService

We provide some global IO services.

Public Functions

LxResult ScriptQuery(LXtObjectID self, void **ppvObj)
LxResult SetOptions(LXtObjectID self, LXtObjectID options)

These methods are used to access the global load-options object. This is an object set by the loader’s options command which can then be read by the loader during the actual load. It will also be stored in the case of sub-object loads.

LXtObjectID PeekOptions(LXtObjectID self)
LxResult OpenBlockStore(LXtObjectID self, const char *filename, const char *format, unsigned flags, void **ppvObj)

Open a block store. Each store has a format given by a string up to 8 charaters in length. Depending on the flags the file may be created if it doesn’t exist, in which case this method returns FALSE instead of OK.

ILxBlockStore

class ILxBlockStore

It can be useful to store data in a format that allows blocks to be randomly accessed. The indexed block store is a format where blocks are given by type and name, and the blocks can be read or written in any sequence. The block store object presents the main BlockStore interface, as well as BlockRead and BlockWrite interfaces for access the contents of blocks using a serial block structure. Blocks are hierarchical, so blocks can contain sub-blocks which can also be accessed randomly.

Public Functions

LxResult AllocBookmark(LXtObjectID self, LXtBlockBookmarkID *loc)
LxResult Lookup(LXtObjectID self, LXtID4 type, const char *id, LXtBlockBookmarkID parent)

The main function of the interface is to set the current block. This can be done by finding a block by type and id code. This returns LXe_TRUE for an existing block, and FALSE for a block that doesn’t exist. If the parent is null this will look for root blocks, otherwise it will search for sub-blocks of the parent block. The user class version of the method makes it optional.

LxResult Stack(LXtObjectID self, unsigned operation)

It can be useful when traversing a block store to set the current location as the new root, so that subsequent lookup occur in that context. That can be done by pushing it onto the location stack. The stack can be popped when done or cleared to reset searches back to the root.

LxResult Count(LXtObjectID self, LXtID4 type, unsigned *count, LXtBlockBookmarkID parent)

You can also enumerate blocks by type. The Count() returns the number of blocks of that type, and ByIndex() sets the current block. Parent determines whether these are root or sub-blocks.

LxResult ByIndex(LXtObjectID self, LXtID4 type, unsigned index, LXtBlockBookmarkID parent)
LxResult RestoreBookmark(LXtObjectID self, LXtBlockBookmarkID loc)

Or, of course, the current location can be set using a bookmark.

LxResult SaveBookmark(LXtObjectID self, LXtBlockBookmarkID loc)

Once the current block is set a location can be remembered to bookmark this spot.

LxResult Type(LXtObjectID self, LXtID4 *type)

Properties of the current block can be read.

LxResult Ident(LXtObjectID self, const char **id)
LxResult Size(LXtObjectID self, size_t *size)
LxResult Delete(LXtObjectID self)

The current block can also be deleted. This also deletes any sub-blocks.

LxResult WriteSize(LXtObjectID self, size_t size)

The BlockRead and BlockWrite interfaces on the store object are convenient for writing structured data, but they do use intermediate memory and so may not be as fast or efficient as possible. As an alternative writing and reading can be done directly to and from the block store file. To write a new block or to resize and exisitng block this function can be used. The space will be allocated for the data in the file, but its contents are undefined. To set the contents of the block the next function should be used.

LxResult WriteBlock(LXtObjectID self, const void *buf, size_t offset, size_t size)

If the current block is writable, this function will write a given number of raw bytes from the buffer into the file at a position offset from the start of the block.

LxResult ReadBlock(LXtObjectID self, void *buf, size_t offset, size_t size)

Likewise for a readable block this function will read raw bytes into the buffer from the given position and size in the block.

LxResult Lookup(LXtID4 type, const char *id, LXtBlockBookmarkID parent = 0)

User Class Only:

LxResult Count(LXtID4 type, unsigned *count, LXtBlockBookmarkID parent = 0)

User Class Only:

LxResult ByIndex(LXtID4 type, unsigned index, LXtBlockBookmarkID parent = 0)
  • LXiOBS_PUSH

  • LXiOBS_POP

  • LXiOBS_CLEAR


LXfOBS_WRITE

Files are normally opened for read unless the flags specify otherwise.

  • WRITE Opens the file for write. If the file doesn’t exist it will be created and if it does exist it will be cleared.

  • MODIFY Same as WRITE, except that if the file already exists it won’t be cleared and its existing contents can be altered.

  • MUSTEXIST If this flag is set then the method will raise an error if the file can’t be found.

  • LXfOBS_MODIFY

  • LXfOBS_MUSTEXIST

LXtLoadAccess1

struct st_LXtLoadAccess1

Public Members

const char *filename
const LXtGUID **types
LXtObjectID monitor
const LXtGUID *found
int opaque
void *target
const char *format
int options

ILxLoader1

class ILxLoader1

Public Functions

LxResult Recognize(LXtObjectID self, LXtLoadAccess1 *load)
LxResult LoadInstance(LXtObjectID self, LXtLoadAccess1 *load, void **ppvObj)
LxResult LoadObject(LXtObjectID self, LXtLoadAccess1 *load, LXtObjectID dest)
LxResult Cleanup(LXtObjectID self, LXtLoadAccess1 *load)
LxResult SpawnOptions(LXtObjectID self, void **ppvObj)