Harlequin RIP SDK
In-memory virtual file system

Files

file  memfs.h
 Simple API for managing an in-memory, virtual file system.
 
file  memfs.c
 Implementation of an input/output device tied to in-memory data.
 

Data Structures

struct  _MFSFILE
 Describes a file. More...
 
struct  _MFSDIR
 Describes a directory. More...
 
struct  _MFSNODE
 Describes a node, which is a named entry within the filesystem, and is either a file or a directory. More...
 
struct  _MFSITERELEMENT
 Helper structure for storing the state of an iteration. More...
 
struct  _MFSITERSTATE
 Encapsulates the current state of an iteration. More...
 

Macros

#define COMPRESS_NEW_FILES   TRUE
 Tune this to decide whether compression should be applied to new files created at run-time. More...
 

Typedefs

typedef struct _MFSFILE MFSFILE
 Describes a file.
 
typedef struct _MFSDIR MFSDIR
 Describes a directory.
 
typedef struct _MFSNODE MFSNODE
 Describes a node, which is a named entry within the filesystem, and is either a file or a directory. More...
 
typedef struct _MFSFILEDESC MFSFILEDESC
 Encapsulates the information required to control access to an open file.
 
typedef struct _MFSITERELEMENT MFSITERELEMENT
 Helper structure for storing the state of an iteration.
 
typedef struct _MFSITERSTATE MFSITERSTATE
 Encapsulates the current state of an iteration. More...
 

Enumerations

enum  { MFS_File , MFS_Directory }
 A node within the filesystem is either a file or a directory, and we use these markers to indicate which. More...
 

Functions

MFSNODEMFSFindRelative (MFSNODE *pRoot, char *pszFilename, MFSNODE **ppParent, uint32 *pIndex, DEVICE_result *err)
 Locate a file node, relative to the given root, according to its pathname. More...
 
HqBool MFSOpen (MFSNODE *pRoot, char *pszFilename, int32 openFlags, MFSFILEDESC **ppDesc, DEVICE_result *err)
 Open or create a file for reading and/or writing. More...
 
HqBool MFSClose (MFSFILEDESC *pDesc)
 Close a file that was previously opened with MFSOpen(). More...
 
MFSFILEMFSGetFile (MFSFILEDESC *pDesc)
 Return the underlying file from its open descriptor. More...
 
int32 MFSRead (MFSFILEDESC *pDesc, uint8 *buffer, int32 cbLen, DEVICE_result *err)
 Read a specified number of bytes from the current location of an open file. More...
 
int32 MFSWrite (MFSFILEDESC *pDesc, uint8 *buffer, int32 cbLen, DEVICE_result *err)
 Write a specified number of bytes to an open file at the current location, expanding the file as necessary. More...
 
int32 MFSWriteString (MFSFILEDESC *pDesc, char *pszString, DEVICE_result *err)
 Write a specified NUL-terminated character string to an open file at the current location, expanding the file as necessary. The terminating NUL character itself is not written. More...
 
HqBool MFSSeek (MFSFILEDESC *pDesc, Hq32x2 *pDestination, int32 flags, DEVICE_result *err)
 Set (or query) the current the position in an open file. More...
 
HqBool MFSAvail (MFSFILEDESC *pDesc, Hq32x2 *pAvail, int32 reasonFlag)
 Determine the number of bytes that are currently available to be read from an open file. More...
 
HqBool MFSSetCompression (MFSFILEDESC *pDesc, HqBool fCompress)
 Controls whether the file's data buffer will be compressed (or re-compressed) when the file is closed. More...
 
int32 MFSDelete (MFSNODE *pRoot, char *pszFilename, DEVICE_result *err)
 Delete a file or directory, and completely release all of its associated memory resources. More...
 
int32 MFSRename (MFSNODE *pRoot, char *pszFromName, char *pszToName, DEVICE_result *err)
 Rename a file, preserving all of its contents and other properties. More...
 
MFSITERSTATEMFSIterBegin (MFSNODE *pRoot, void *pPrivate)
 Begin an iteration over all or part of the file system. More...
 
HqBool MFSIterNext (MFSITERSTATE *pState)
 Proceed to the first (or next) file in an iteration sequence. More...
 
void MFSIterEnd (MFSITERSTATE *pState)
 Close an iteration sequence. More...
 
MFSNODEMFSIterNode (MFSITERSTATE *pState)
 Obtain a direct pointer to the MFS_File node of the current iteration step. More...
 
uint32 MFSIterNameLength (MFSITERSTATE *pState, HqBool fLeadingSlash)
 Obtain the pathname length of the file at the current iteration step. More...
 
HqBool MFSIterName (MFSITERSTATE *pState, char *pszFilenameBuf, uint32 bufLen, HqBool fLeadingSlash)
 Obtain the pathname of the file at the current iteration step. More...
 
MFSNODEMFSNewRoot (char *pszRootName)
 Construct and return a completely new root directory node. More...
 
MFSNODEMFSCopyTree (MFSNODE *pMFSRoot, HqBool fCopyFileData)
 Construct and return a completely new filesystem tree by making a recursive copy of the given tree. More...
 
void MFSReleaseRoot (MFSNODE *pMFSRoot)
 Destroy the given root node, and the entire virtual filesystem descended from it. More...
 
void MFSMemUsage (MFSNODE *pNode, uint32 *pROMSize, uint32 *pRAMSize)
 Calculate the amount of memory currently in use by the virtual filesystem descended from the given node. More...
 

Detailed Description

This API specifies a simple tree data structure for representing one or more virtual file systems. Each system is modelled as a tree of MFSNODE objects, where each node represents either a file or a directory. A file is always a leaf node, whereas a directory contains pointers down to child nodes. As with any filesystem, each node is assigned a name, meaning that nodes may be addressed using a path. Currently, only 8-bit ASCII filenames are supported. The tree may be arbitrarily nested. (Pathnames are expressed using a forward-slash / character as the separator).

These data structures are designed to be statically-declarable, but dynamically-growable. A filesystem need not start off as empty, although it can do. It is possible to write (or generate) a series of static C data declarations to describe the initial state of a whole tree. Global Graphics provides an "Import Tool", which can scan an existing directory on disk, and represent it as a virtual filesystem within the application's memory. This can eliminate avoid the need for configuration files on disk.

Whether from an empty initial state, or from a pre-declared static state, it is possible to access and modify files, and to create new ones. Such modifications, of course, persist only for the lifetime of the application, since the entire filesystem is held in process-local memory. Functions are provided to open and create files, and for reading and writing data. There are also functions for managing the tree: such as locating, deleting and renaming files. See the individual function descriptions for further details in each case.

The API supports compression and decompression via the ZLIB interface. This happens transparently, but a file's data stream can only be in a compressed state when the file is closed. In order to keep the code simple, live stream-based compression/decompression of open files is not supported. As soon as a file is opened with MFSOpen(), its data stream will become uncompressed in its entirety, and will remain so until the file is closed, whereupon the data will be re-compressed.

When a file system has a statically-declared initial state (as might be generated by the Import Tool), it is likely that the Import Tool will apply compression to the data buffers where possible. If it does so, it must do so via the ZLIB interface. Statically-declared filesystems are expected to be the typical case for compression. However, a policy of compressing dynamically-created MFS files can also be put in place by tuning the COMPRESS_NEW_FILES macro, defined in this header file. If this macro is set to FALSE, no compression will be applied to fresh files created at runtime.

The implementation of this API is thread-safe, to the extent that there is no undocumented global state within the implementation that might prevent concurrent use. However, the tree structures themselves are not protected by this layer. Broadly, this means that concurrent use of this API should be limited to disjoint filesystem trees, or disjoint portions of a single tree. For convenience, there are some exceptions to this general rule, particularly when read-only access is required to files and directories.

This API is primarily aimed at implementing a device in terms of the Core RIP Device Interface. Some of the flags and return codes used here are deliberately specified to match the contracts of the Device Interface. However, this API can also be used standalone, instead of (or even as well as) just providing the support for a device implementation.

Macro Definition Documentation

◆ COMPRESS_NEW_FILES

#define COMPRESS_NEW_FILES   TRUE

Tune this to decide whether compression should be applied to new files created at run-time.

See also the MFSSetCompression() function, which allows the caller to decide whether to apply compression for individual files.

Typedef Documentation

◆ MFSITERSTATE

typedef struct _MFSITERSTATE MFSITERSTATE

Encapsulates the current state of an iteration.

See also
MFSIterBegin

◆ MFSNODE

typedef struct _MFSNODE MFSNODE

Describes a node, which is a named entry within the filesystem, and is either a file or a directory.

If this node is a file, then it is a leaf node. If it is a directory, then it contains an array of pointers to the child MFSNODE structures.

Nodes do not contain parent pointers.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum

A node within the filesystem is either a file or a directory, and we use these markers to indicate which.

See also
MFSNODE
Enumerator
MFS_File 

Denotes an ordinary file.

MFS_Directory 

Denotes a directory.

Function Documentation

◆ MFSAvail()

HqBool MFSAvail ( MFSFILEDESC pDesc,
Hq32x2 pAvail,
int32  reasonFlag 
)

Determine the number of bytes that are currently available to be read from an open file.

It is never permissible to call this function concurrently with the same descriptor. It is, however, permissible to call the function concurrently with different descriptors on the same underlying file, provided that there are no open descriptors with write access on the file.

Parameters
[in]pDescA pointer to the file descriptor, obtained from an earlier call to MFSOpen().
[out]pAvailReceives a count of available bytes upon successful return.
[in]reasonFlagOne of SW_BYTES_AVAIL_REL or SW_BYTES_TOTAL_ABS, as per the Core RIP Device Interface. Since files are stored in memory, the maximum extent of the data is always known, so precise information can be returned in both cases.
Returns
TRUE upon success; FALSE upon failure. This return convention is directly compatible with DEVICETYPE::bytes_file() in the Core RIP Device Interface.

◆ MFSClose()

HqBool MFSClose ( MFSFILEDESC pDesc)

Close a file that was previously opened with MFSOpen().

Parameters
[in]pDescA pointer to the file descriptor, obtained from an earlier call to MFSOpen().
Returns
TRUE upon success; FALSE upon failure. Note that the Core RIP Device Interfaces uses a different return convention for the DEVICETYPE::open_file() function. When implementing such a function in terms of MFSOpen(), you must convert TRUE to 0, and FALSE to -1 respectively.

◆ MFSCopyTree()

MFSNODE* MFSCopyTree ( MFSNODE pMFSRoot,
HqBool  fCopyFileData 
)

Construct and return a completely new filesystem tree by making a recursive copy of the given tree.

Use MFSReleaseRoot() to recursively destroy the copy when it is no longer needed.

MFSNewRoot() and MFSCopyTree() are the only two functions that can be used to create a completely fresh virtual filesystem tree. All other functions operate on nodes that are already linked into an existing tree.

The directory node returned by this function is stand-alone, and completely unlinked from any existing virtual filesystems being managed by MFS.

Parameters
[in]pMFSRootPointer to the root of the tree to be copied.
[in]fCopyFileDataControls whether the underlying file data buffers are copied into the new tree. If you pass TRUE, then fresh copies of the file data will be made in the new tree. Otherwise, the underlying file data will be shared by the new tree and the original tree. Sharing the file data will use less memory, but it means that modifications to files in the new tree can potentially have side-effects on the files in the original tree.
Returns
If the function succeeds, the return value is a pointer to a newly-allocated filesystem tree whose shape and contents exactly match the original tree. Every directory and file that exists in the original tree will also exist in the new tree. The files will also contain the same data, which will either be a copy of the original, or a duplicated pointer to memory shared with the original, depending on the value of fCopyFileData. If the function fails, the return value is NULL, which is best interpreted as being due to memory exhaustion.

◆ MFSDelete()

int32 MFSDelete ( MFSNODE pRoot,
char *  pszFilename,
DEVICE_result err 
)

Delete a file or directory, and completely release all of its associated memory resources.

This function can be used to delete a single file, or to recursively delete a directory and all of its descendants, regardless of their contents. If you consider this function as being like the UNIX rm command, then there is an implicit -rf.

This function will fail if the specified file is currently open with any level of access. In the recursive case, the function will similarly fail if any open files are included amongst the directory's descendants.

It is permissible to call this function concurrently, provided that all concurrent calls are given disjoint (sub-)trees as the first argument.

Parameters
[in]pRootRoot of the file system or sub-tree. This can be any directory node, as long as the filename is expressed relative to it.
[in]pszFilenameThe pathname of the required file or directory, expressed relative to pRoot, and with forward-slash characters separating the path elements.
[out]errPointer to an integer error code, specified according to the Core RIP Device Interface. If the function fails, this will receive the appropriate device error code.
Returns
Zero on success, -1 on failure. This return convention is directly compatible with DEVICETYPE::delete_file() in the Core RIP Device Interface.

◆ MFSFindRelative()

MFSNODE* MFSFindRelative ( MFSNODE pRoot,
char *  pszFilename,
MFSNODE **  ppParent,
uint32 pIndex,
DEVICE_result err 
)

Locate a file node, relative to the given root, according to its pathname.

This function may be called concurrently, even on shared directory trees. However, it should not be called concurrently with MFSOpen(), MFSRename() or MFSDelete(), unless such concurrent calls are operating on disjoint (sub-)trees, otherwise race conditions result.

Parameters
[in]pRootThe root of the search.
[in]pszFilenameThe pathname of the required file, expressed relative to pRoot, and with forward-slash characters separating the path elements.
[out]ppParentIf the function succeeds, this output parameter receives a pointer to the target node's parent node, which will be of type MFS_Directory.
[out]pIndexIf the function succeeds, this output parameter receives the index of the target node within its parent directory's child array.
[out]errPointer to an integer error code, specified according to the Core RIP Device Interface. If the function fails, this will receive the appropriate device error code.
Returns
A pointer to the located node, or NULL if no matching node was found. (This function never creates new nodes - you must use MFSOpen() for that). If a pointer is returned, the node will always be of type MFS_File.

◆ MFSGetFile()

MFSFILE* MFSGetFile ( MFSFILEDESC pDesc)

Return the underlying file from its open descriptor.

Parameters
[in]pDescA pointer to the file descriptor, obtained from an earlier call to MFSOpen().
Returns
The corresponding file within the virtual tree.

◆ MFSIterBegin()

MFSITERSTATE* MFSIterBegin ( MFSNODE pRoot,
void *  pPrivate 
)

Begin an iteration over all or part of the file system.

This function can be used to visit file nodes beneath the given directory. The iteration will recursively enter all nested directories, but the directories themselves are not visited as an explicit iteration step.

The function returns a pointer to an internally-allocated MFSITERSTATE structure, which maintains information about the current iteration state. This structure is initialized at a notional position before the first file. To visit the first file, you must make an initial call to MFSIterNext(), and so on to visit subsequent files.

At each iteration step, you can call MFSIterNameLength() and MFSIterName() to obtain the pathname of the current file, expressed relative to pRoot. You can also call MFSIterNode() to obtain a direct pointer to the current file node.

To avoid resource leaks, all calls to MFSIterBegin() must be matched by a later call to MFSIterEnd().

The following code fragment demonstrates the basic call pattern for iteration.

{
   char filename[ MAXFILENAMELENGTH ];
   MFSITERSTATE *pState = MFSIterBegin( pRoot, NULL );
   while ( MFSIterNext( pState ) )
   {
     if ( MFSIterName( pState, filename, sizeof( filename ), TRUE ) )
       printf( "Visiting %s\n", filename );
     else
       printf( "<Filename too long>\n" );
   }
   MFSIterEnd( pState );
}

Backwards iteration is not supported, and no assumption should be made that files are visited in any particular order, such as alphabetical order.

It is legal to call MFSDelete() on the current file during iteration. It is also legal to call MFSRename(), although it is then undefined whether the destination file will then be visited later in the iteration.

The iteration function can be used to support an implementation of the DEVICETYPE::start_file_list() and DEVICETYPE::next_file() functions in the Core RIP Device Interface.

In general, iteration functions may be called concurrently, provided that they are "separate" iterations - that is, using different MFSITERSTATE structures.

Parameters
[in]pRootRoot of the file system, or directory sub-tree to be traversed.
[in]pPrivateArbitrary pointer to caller-managed memory. This pointer will be installed into the MFSITERSTATE::pPrivate field.
Returns
Pointer to an internally-managed data structure. This pointer remains legal until it is passed into MFSIterEnd().

◆ MFSIterEnd()

void MFSIterEnd ( MFSITERSTATE pState)

Close an iteration sequence.

For more information, see MFSIterBegin().

Parameters
[in]pStateThe current iteration state, as previously obtained from a call to MFSIterBegin(). This pointer becomes invalid upon return.

◆ MFSIterName()

HqBool MFSIterName ( MFSITERSTATE pState,
char *  pszFilenameBuf,
uint32  bufLen,
HqBool  fLeadingSlash 
)

Obtain the pathname of the file at the current iteration step.

For more information, see MFSIterBegin().

Parameters
[in]pStateThe current iteration state, as previously obtained from a call to MFSIterBegin().
[out]pszFilenameBufA pointer to caller-managed memory, which will receive the pathname. The pathname will be expressed relative to the directory that was specified to MFSIterBegin(), and will use forward-slash characters as path separators. A leading foward-slash and a terminating NUL character are included.
[in]bufLenThe number of bytes available in the buffer. If this does not accommodate the pathname (including its NUL terminator), the function will fail, and no bytes will be written into the buffer. Use MFSIterNameLength() to obtain the required buffer length, and remember to use the same value for fLeadingSlash.
[in]fLeadingSlashFlag indicating whether a leading slash should be included in the name.
Returns
TRUE upon success; FALSE upon failure.

◆ MFSIterNameLength()

uint32 MFSIterNameLength ( MFSITERSTATE pState,
HqBool  fLeadingSlash 
)

Obtain the pathname length of the file at the current iteration step.

For more information, see MFSIterBegin().

Parameters
[in]pStateThe current iteration state, as previously obtained from a call to MFSIterBegin().
[in]fLeadingSlashFlag indicating whether a leading slash should be taken into account when computing the filename. This will just increase the returned value by 1 character, but the parameterization is in order to be consistent with MFSIterName().
Returns
The number of 8-bit characters, including a NUL terminator and all separating characters, required to store the pathname of the current file.

◆ MFSIterNext()

HqBool MFSIterNext ( MFSITERSTATE pState)

Proceed to the first (or next) file in an iteration sequence.

For more information, see MFSIterBegin().

Parameters
[in]pStateThe current iteration state, as previously obtained from a call to MFSIterBegin().
Returns
TRUE if the iteration has proceeded; FALSE if the iteration has been exhausted.

◆ MFSIterNode()

MFSNODE* MFSIterNode ( MFSITERSTATE pState)

Obtain a direct pointer to the MFS_File node of the current iteration step.

For more information, see MFSIterBegin().

Parameters
[in]pStateThe current iteration state, as previously obtained from a call to MFSIterBegin().

◆ MFSMemUsage()

void MFSMemUsage ( MFSNODE pNode,
uint32 pROMSize,
uint32 pRAMSize 
)

Calculate the amount of memory currently in use by the virtual filesystem descended from the given node.

This function recursively walks over the tree, and totals up the file data buffer space being used. The result is approximate, since the memory consumption of MFS internal data structures is not included, but this is generally small in comparison with the actual file data.

The function produces separate totals for ROM consumption and RAM consumption. ROM consumption extends to initial file data that was imported from an external source and embedded in the compiled binaries. RAM consumption extends to all further space that was allocated at runtime. RAM consumption will tend to fluctuate with usage of the filesystem, whereas ROM consumption is fixed (effectively at application link time).

Parameters
[in]pNodeRoot node of the virtual filesystem to be examined. This is allowed to be NULL, in which case the function does nothing.
[out]pROMSizeThis number is increased by the number of bytes of ROM being consumed by the filesystem. The caller should initialize this to zero to obtain a total for just the given node. There is no handling for overflow. If files have been deleted from the tree, their ROM consumption is no longer included by this function, although the memory is effectively "leaked" and cannot be recovered. (RAM space, by comparison, is never leaked).
[out]pRAMSizeThis number is increased by the number of bytes of dynamic heap memory being consumed by the filesystem. The caller should initialize this to zero to obtain a total for just the given node. There is no handling for overflow.

◆ MFSNewRoot()

MFSNODE* MFSNewRoot ( char *  pszRootName)

Construct and return a completely new root directory node.

Use MFSReleaseRoot() to destroy this root and the entire virtual filesystem descended from it.

MFSNewRoot() and MFSCopyTree() are the only two functions that can be used to create a completely fresh virtual filesystem tree. All other functions operate on nodes that are already linked into an existing tree.

The directory node returned by this function is stand-alone, and completely unlinked from any existing virtual filesystems being managed by MFS.

Parameters
[in]pszRootNameThe identifier to use for the root node, since all nodes must have a name. Note that this name does not form a part of any path relative to this root.
Returns
A new node, whose type will be MFS_Directory, or NULL if there has been a failure to allocate the necessary memory.

◆ MFSOpen()

HqBool MFSOpen ( MFSNODE pRoot,
char *  pszFilename,
int32  openFlags,
MFSFILEDESC **  ppDesc,
DEVICE_result err 
)

Open or create a file for reading and/or writing.

This function can be called concurrently, provided that all concurrent calls are given disjoint (sub-)trees as the first argument. Similar caveats apply with concurrent calls to MFSDelete() and MFSRename().

Parameters
[in]pRootRoot of the file system or sub-tree. This may be any directory node within the tree, as long as the filename is expressed relative to it.
[in]pszFilenameThe pathname of the required file, expressed relative to pRoot, and with forward-slash characters separating the path elements.
[in]openFlagsSpecified as per the Core RIP Device Interface, indicating the required level of access to the file. The Memory File System allows concurrent read access, but write access is always exclusive. This parameter can also indicate whether to create a new file.
[out]ppDescIf the function succeeds, receives a pointer to the file descriptor. This pointer must subsequently be passed into all functions used to access the file while it is open. Ultimately, the pointer must be passed to MFSClose() in order to close the file.
[out]errPointer to an integer error code, specified according to the Core RIP Device Interface. If the function fails, this will receive the appropriate device error code.
Returns
TRUE upon success; FALSE upon failure. Note that the Core RIP Device Interfaces uses a different return convention for the DEVICETYPE::open_file() function. When implementing such a function in terms of MFSOpen(), you must convert TRUE to 0, and FALSE to -1 respectively.

◆ MFSRead()

int32 MFSRead ( MFSFILEDESC pDesc,
uint8 buffer,
int32  cbLen,
DEVICE_result err 
)

Read a specified number of bytes from the current location of an open file.

This function has no side-effects on the underlying file. Therefore, it is permissible to call this function concurrently for different descriptors on the same file, but not with identical descriptors.

Parameters
[in]pDescA pointer to the file descriptor, obtained from an earlier call to MFSOpen(). The file must have been opened with read access: SW_RDONLY or SW_RDWR.
[out]bufferPointer to caller-managed data buffer, which will receive the bytes.
[in]cbLenThe maximum number of bytes to read.
[out]errPointer to an integer error code, specified according to the Core RIP Device Interface. If the function fails, this will receive the appropriate device error code.
Returns
The number of bytes actually read, which will not be greater than cbLen, but which might be less. Returns zero if the end of file has been reached. Returns -1 upon failure. This return convention is directly compatible with DEVICETYPE::read_file() in the Core RIP Device interface.

◆ MFSReleaseRoot()

void MFSReleaseRoot ( MFSNODE pMFSRoot)

Destroy the given root node, and the entire virtual filesystem descended from it.

Parameters
[in]pMFSRootThe root node, which must have previously been allocated with either MFSNewRoot() or MFSCopyTree(). Never call MFSReleaseRoot() with a non-root node from within another virtual filesystem. Use MFSDelete() instead.

◆ MFSRename()

int32 MFSRename ( MFSNODE pRoot,
char *  pszFromName,
char *  pszToName,
DEVICE_result err 
)

Rename a file, preserving all of its contents and other properties.

It is permissible to call this function concurrently, provided that all concurrent calls are given disjoint (sub-)trees as the first argument.

Parameters
[in]pRootRoot of the file system or sub-tree. This can be any directory node, as long as the filenames are expressed relative to it.
[in]pszFromNameThe pathname of the source file, expressed relative to pRoot, and with forward-slash characters separating the path elements. The function will fail if this pathname designates a file that is currently open with any level of access. The function will also fail if this pathname does not exist, or if it designates a directory.
[in]pszToNameThe pathname of the destination file, expressed relative to pRoot, and with forward-slash characters separating the path elements. If this pathname denotes any file or directory that already exists, the function will fail.
[out]errPointer to an integer error code, specified according to the Core RIP Device Interface. If the function fails, this will receive the appropriate device error code.
Returns
Zero on success, -1 on failure. This return convention is directly compatible with DEVICETYPE::delete_file() in the Core RIP Device Interface.

◆ MFSSeek()

HqBool MFSSeek ( MFSFILEDESC pDesc,
Hq32x2 pDestination,
int32  flags,
DEVICE_result err 
)

Set (or query) the current the position in an open file.

It is never permissible to call this function concurrently with the same file descriptor. It is, however, permissible to call the function concurrently with different descriptors on the same underlying file, provided that there are no open descriptors with write access on the file.

Parameters
[in]pDescA pointer to the file descriptor, obtained from an earlier call to MFSOpen() (with any level of access).
[in]pDestinationSpecifies the file pointer adjustment, and receives the absolute file position if the function returns successfully.
[in]flagsOne of SW_SET, SW_INCR or SW_XTND, as per the Core RIP Device Interface. This determines how the pDestination argument is treated on entry. However, the updated pDestination is always an absolute file pointer on exit. To query the current file pointer without modifying it, use SW_INCR and supply a pointer to a zero-valued Hq32x2 (note that this does not mean a NULL pointer).
[out]errPointer to an integer error code, specified according to the Core RIP Device Interface. If the function fails, this will receive the appropriate device error code.
Returns
TRUE upon success, in which case pDestination is updated with the current file pointer. FALSE upon failure, in which case pDestination is not updated. This return convention is directly compatible with DEVICETYPE::seek_file() in the Core RIP Device Interface

◆ MFSSetCompression()

HqBool MFSSetCompression ( MFSFILEDESC pDesc,
HqBool  fCompress 
)

Controls whether the file's data buffer will be compressed (or re-compressed) when the file is closed.

This function can only be called when the file's data buffer is currently in an uncompressed state. This will be the case if the file was opened for writing, or for random-access reading. In other cases, it is less certain.

Normally, when a file is closed, its data buffer is retained in a compressed state to save on memory usage. There might be cases where this is undesirable. For instance, if a large file is opened and closed many times in rapid succession, a runtime expense will be incurred in decompression (and re-compression) of the data. The caller might use this function to de-activate the compression for periods of such activity. The caller might also use this function when storing data that has already been compressed, in which case there is little point in trying to compress it again.

The most typical use of this function is immediately after creation of a new file with MFSOpen().

Parameters
[in]pDescA pointer to the file descriptor, obtained from an earlier call to MFSOpen().
[in]fCompressSupply TRUE to indicate that the file buffer should be compressed when the file is closed, or FALSE to indicate that it shouldn't.
Returns
TRUE if the function succeeds, otherwise FALSE.

◆ MFSWrite()

int32 MFSWrite ( MFSFILEDESC pDesc,
uint8 buffer,
int32  cbLen,
DEVICE_result err 
)

Write a specified number of bytes to an open file at the current location, expanding the file as necessary.

This function has side-effects on the underlying file. Therefore, it is never permissible to call this function concurrently with descriptors on the same file. It is also never permissible to call MFSRead() concurrently with MFSWrite() with descriptors on the same underlying file.

Parameters
[in]pDescA pointer to the file descriptor, obtained from an earlier call to MFSOpen(). The file must have been opened with write access: SW_WRONLY or SW_RDWR.
[in]bufferPointer to caller-managed data buffer, from which bytes will be copied into the file.
[in]cbLenThe maximum number of bytes to write.
[out]errPointer to an integer error code, specified according to the Core RIP Device Interface. If the function fails, this will receive the appropriate device error code.
Returns
The number of bytes actually written, which will not be greater than cbLen, but which might be less. Returns -1 upon failure. This return convention is directly compatible with DEVICETYPE::write_file() in the Core RIP Device interface.

◆ MFSWriteString()

int32 MFSWriteString ( MFSFILEDESC pDesc,
char *  pszString,
DEVICE_result err 
)

Write a specified NUL-terminated character string to an open file at the current location, expanding the file as necessary. The terminating NUL character itself is not written.

This function has side-effects on the underlying file. Therefore, it is never permissible to call this function concurrently with descriptors on the same file. It is also never permissible to call MFSRead() or MFSWrite() concurrently with MFSWriteString(), with descriptors on the same underlying file.

Parameters
[in]pDescA pointer to the file descriptor, obtained from an earlier call to MFSOpen(). The file must have been opened with write access: SW_WRONLY or SW_RDWR.
[in]pszStringA pointer to caller-managed string memory. The string should be NUL-terminated, and should be an ANSI or multi-byte encoded character string.
[out]errPointer to an integer error code, specified according to the Core RIP Device Interface. If the function fails, this will receive the appropriate device error code.
Returns
The number of bytes actually written, which will not be greater than the length of the string in bytes, but which might be less. Returns -1 upon failure. This return convention is directly compatible with DEVICETYPE::write_file() in the Core RIP Device interface.