The CPC Rapid Deployment API defines a framework for building CPC compression and decompression applications in which the raw CPC data is stored in files. While files serve as a suitable storage framework for many environments, there are certain situations in which the application requires greater control of the storage and retrieval process. For example, in a network environment, there may not exist a file-based abstraction of network I/O, instead requiring the application to use special network-defined functions for the transfer of data. Similarly, a database environment is likely to require that the application use special database-defined functions for storage and retrieval. To provide this level of application control, CPC defines a polymorphic abstraction of a file, known as a Data Stream, and performs all data storage and retrieval by manipulating application-supplied instances of this abstraction. This document describes the Rapid Deployment Data Streams API, which allows a developer to implement application-specific Data Streams, and thereby take complete control of the storage and retrieval of CPC data.
This document assumes that the reader is already familiar with the Rapid Deployment API. Cartesian recommends that developers use that API for situations in which a file-based API is appropriate. It is simpler, and the CPC-specific portions of the application will be smaller.
The CPC library provides a set of functions for the generic manipulation of Data Streams. The following sections describe these manipulation interfaces.
This document describes only those functions that may be needed for interacting with the Rapid Deployment API.
Opaque Type: DataStr | |
The opaque data type used to represent a Data Stream to a Stream user. | |
|
After an error is latched, it is up to the Stream's implementation as to whether or not subsequent I/Os fail.
Function Definition: strGetError | |
Returns 0 if the Stream, str, is not in error. Otherwise, returns a zero-terminated ASCII string describing the nature of the error. The returned string will remain valid even after the Stream is closed. | |
The returned string is owned by the CPC library and should not be modified or deallocated by the application. | |
|
Function Definition: strSetError | |
Put the Data Stream, str, into the error state described by err. If isHard is non-zero, the error is a permanent hard error. Otherwise, the error is a transient soft error. This specific error will be latched if the Stream is not currently in error, or if the Stream is in a soft error state and isHard is non-zero. | |
err must be a valid pointer even after str is closed. Typically, this restriction is met by using string constants. | |
|
Function Definition: strClearError | |
If the Stream, str, is in a soft error state, clears the error state of the Stream. Otherwise, this function is a no-op. | |
|
This is typically done automatically when the application invokes cpcEnc_destroy or cpcDec_destroy.
Function Definition: strClose | |
Close the Data Stream, str, deallocating or detaching all of its resources. If propagateClose is non-zero, any subsidiary resources owned by the Stream are also closed and deallocated. Otherwise, the Stream merely detaches itself from any subsidiary resources. (The definition of subsidiary resources is determined by the implementation of the Stream.) | |
Returns 0 if the Stream was closed without error (and the Stream was not in error at the time of the close). Otherwise, returns a zero-terminated ASCII string describing the nature of the error. | |
On return from this routine, str is no longer valid and should not be used on any subsequent operations. | |
The returned string is owned by the CPC library. It should not be modified or deallocated by the application. | |
|
As described below, some of the methods are allowed to return errors. In addition to returning an error, the Agent can also call strSetError to provide an Agent-specific message describing the error. (If the Agent does not call strSetError, a generic error description is used.)
DataStrAgent Method: GetPos |
Prototype: int (*GetPos)(DataStr *str) |
Example: GetPos_File |
Returns the current position of the seek pointer for str, or a negative value if str is in error and the current position of the seek pointer can not be ascertained. |
DataStrAgent Method: SetPos |
Prototype: unsigned (*SetPos)(DataStr *str, unsigned long pos) |
Example: SetPos_File |
Set the current position of the seek pointer for str to pos. |
Returns non-zero if the operation was successful, zero otherwise. |
The Agent is not required to return an error on a failed seek; it can wait until the I/O is attempted and return an error there. |
DataStrAgent Method: Read |
Prototype: int (*Read)(DataStr *str, void *buf, Ulong cnt) |
Example: Read_File |
Read cnt bytes of data from the Stream, str, into buf. The data should be read from the current position of the Stream's seek pointer. |
Returns the number of bytes of data transferred to buf, or a negative value if an error occurred. On return, the Agent should advance the seek pointer by the number of bytes transferred. |
A CpcEncoder will never attempt to read from its output Data Stream. Hence, an encode-only application need not implement this method. |
If all of the requested data is not yet available, the Agent should block the caller until it is available. The Agent should only return a value less than cnt if an error occurs or the end of the Stream has been reached. |
DataStrAgent Method: Write |
Prototype: int (*Write)(DataStr*str, void *buf, Ulong cnt) |
Example: Write_File |
Write cnt bytes of data from buf into the Stream, str. The data should be written at the current position of the Stream's seek pointer. |
Returns the number of bytes of data transferred to buf, or a negative value if an error occurred. On return, the Agent should advance the seek pointer by the number of bytes transferred. |
A CpcDecoder will never attempt to write to its input Data Stream. Hence, a decode-only application need not implement this method. |
The Agent should only return a value less than cnt if an error occurs. |
The method is passed a parameter indicating whether or not subsidiary resources of the Stream should also be closed. The definition of subidiary resource is up to the Agent. The general idea is that a subsidiary resource is one that could potentially continue to be used after the Stream is closed. For example, an Agent that interacts with an open file might consider the open file to be a subsidiary resource. This would allow the Stream user to close the Stream without closing the open file.
There is no requirement that the Agent consider any of the Stream's resources to be subsidiary.
DataStrAgent Method: Close |
Prototype: char const *(*Close)(DataStr *str, Boolean propagateClose) |
Example: CloseFile |
Close the Data Stream, str, deallocating its resources. If propagateClose is non-zero, any subsidiary resources owned by the Stream are also closed and deallocated. Otherwise, the Stream is merely detached from its subsidiary resources. |
Returns 0 if the Stream was closed without error. Otherwise, returns a pointer to a zero-terminated ASCII string describing the nature of the error. |
On return from this routine, str is assumed to be deallocated and will not be passed to any subsequent method invocations. |
Since on return from this routine the Stream is closed, the returned string must be valid after the Stream is deallocated. Typically, this restriction is met by using string constants. |
DataStrAgent Method: OnErrorChange |
Prototype: void (*OnErrorChange)(DataStr *str) |
Invoked by the CPC Library on any change to the error state of the Stream, str. |
This method is not used in the Rapid Deployment API. There is no reason to implement it.
DataStrAgent Method: GetLen |
Prototype: int (*GetLen)(DataStr *str) |
Returns the total number of bytes of data contained in str, or a negative value if the length of the Stream is not known. |
Type Definition: DataStrAgent | |||||
Defines the Agent implementations of the methods for a Data Stream Class. The semantics of the methods were discussed in the preceding sections. If an Agent does not implement an optional method, it should set the corresponding pointer to zero. | |||||
|
Function Definition: strInit | |
Initialize the newly allocated Data Stream, str, which is controlled by the Data Stream Agent, agent. | |
|
Each of the Agent methods is passed a DataStr pointer identifying the Stream instance on which to perform the method. (This is the same pointer that was passed by the Agent to strInit.) If the Agent maintains any per-Stream data structures, it will need some mechanism for mapping the DataStr pointer to its own per-Stream structure. One simple solution to this problem is to embed the DataStr as the first field of a larger structure which contains the Agent-specific Stream information. This allows the Agent to map the DataStr pointer to its own structure by direct pointer coercion (since both structures always start at the same address).
There is no requirement that an Agent be implemented in this manner.
Type Definition: DataStr | |
The generic structure of a Data Stream. The Agent should never have to directly manipulate the fields of this structure. The structure is exposed to allow Agents to embed it in their own internal structures. | |
The semantics and fields of this structure are not defined by this API. They are subject to change without notice. | |
|
Function Definition: cpcEnc_createFromStream | |
Create a CPC encoder that sends its compressed CPC data to the Data Stream, sink, starting at the Stream's current seek position. If progressive is non-zero, the document is encoded using the CPC-Progressive format. Otherwise, it is encoded using the CPC-Normal format. | |
Returns a pointer to the encoder, or 0 if the encoder could not be created. The only reason for failure is that memory could not be allocated. | |
The CPC encoder never tries to read from sink. | |
|
Function Definition: cpcDec_createFromStream | |
Create a CPC decoder that reads its compressed CPC data from the Data Stream, data, starting at the Stream's current seek position. If sequential is non-zero, the decoder is configured for sequential access to the pages. Otherwise, the decoder is configured for random access. (On large documents, random access uses an additional 750k of memory.) | |
Returns a pointer to the decoder, or 0 if the decoder could not be created. The only reason for failure is that memory could not be allocated. | |
The CPC decoder never tries to write to data. | |
|
Function Definition: cpcDec_checkSignature | |
Returns non-zero if the data at the current seek position of the Data Stream data, appears to be CPC data. Otherwise, returns zero. | |
|
In this section, we develop a full sample application, which compresses and decompresses CPC data using the Rapid Deployment Data Streams API.
The code in this example is taken directly from the CpcStr sample application of the Rapid Deployment SDK.
The File Agent is provided for expository purposes only. It provides no additional functionality over the file-based Rapid Deployment API. (In fact, the File Agent is a simplification of the Agent used to implement the file-based API.)
Type Definition: FileStr | |
Describes an open File Stream. gen contains the generic description of the stream. fp is a pointer to the open file that stands behind the stream. | |
|
Function Definition: SubClass | |
Convert the generic Data Stream, str, to the corresponding FileStr. | |
str must truly be a File Stream. | |
|
Function Definition: SetError | |
Set the error state for str to be the error contained in the underlying stdio file. dfltMsg is used as the error if the underlying file does not contain a known error code (or does not appear to be in error). | |
|
Function Definition: GetPos_File | |
Returns the current position of the seek pointer for str. | |
|
Function Definition: SetPos_File | |
Set the current position of the seek pointer for str to pos. | |
Returns non-zero if the seek was successful, zero otherwise. | |
|
Function Definition: Read_File | |||||
Read cnt bytes of data from str into buf. The data is read from the current position of the Stream's seek pointer. | |||||
Returns the number of bytes of data transferred to buf, or a negative value if an error occurred. On return, the seek pointer is advanced by the number of bytes transferred. | |||||
|
Function Definition: Write_File | |||||
Write cnt bytes of data from buf into the stream, str. The data is written at the current position of the Stream's seek pointer. | |||||
Returns the number of bytes of data transferred to buf, or a negative value if an error occurred. On return, the seek pointer is advanced by the number of bytes transferred. | |||||
|
Function Definition: Close_File | |||||||
Close the Data Stream, str, deallocating its resources. If closeFp is non-zero, the underlying file owned by the Stream is also closed. Otherwise, the Stream merely detaches itself from the underlying file. | |||||||
Returns 0 if the Stream was closed without error. Otherwise, returns a pointer to a zero-terminated ASCII string describing the nature of the error. | |||||||
|
Variable: Agent | |
Defines the interfaces to the File Stream Agent. | |
|
Function Definition: fileStr_open | |||||||||
Create a new instance of a File Stream and attach it to the open file, fp. | |||||||||
Returns a pointer to the newly created Stream, or zero if an error occurred. The Stream's seek pointer is positioned at the same offset as the seek pointer for fp | |||||||||
|
(Regenerative CPC codings typically stabilize after 2-4 generations. Once the coding has stabilized, subsequent generations are bitwise identical.)
Function Definition: OpenDecoder | |||||||
Returns a pointer to a CpcDecoder which reads its raw CPC data from the file named, name, or zero if the CpcDecoder can not be created. | |||||||
|
Function Definition: OpenEncoder | |||||
Returns a pointer to a CpcEncoder that writes its raw CPC data to the file named name, or zero if the CpcEncoder can not be created. | |||||
|
Function Definition: main | |||||||||||||||||
The entry point for the application. | |||||||||||||||||
|