Harlequin RIP SDK
RIP Data Resource (RDR) System

The RIP Data Resource (RDR) API is used to share blocks of data and functional interfaces between the skin and core, or in general, between multiple Providers and Consumers. More...

Files

file  apis.h
 This header file defines Types of RDR_CLASS_API, used to identify APIs exposed through the RDR system.
 
file  rdrapi.h
 Header file defining the RIP Data Resource (RDR) System.
 
file  rdrerrors.h
 Header file defining the RIP Data Resource (RDR) System result translation.
 
file  rdrmetrics.h
 This header file defines how metrics are published through RDR.
 
file  event.c
 This file provides the Events system API.
 
file  rdr.c
 This file implements the RIP Data Resource (RDR) System.
 
file  rdrglue.c
 This file provides interfacing between the core RIP Data Resource API and the skin.
 
file  rdrpriv.h
 This file provides definitions for the core RIP Data Resource API.
 

Data Structures

struct  sw_rdr_api_20110201
 The RDR API structure for version 20110201. More...
 
struct  sw_rdr_api_20191120
 The RDR API structure for version 20191120. More...
 

Macros

#define SwFindRDRs(void)   rdr_api->find_all
 Find all RDRs. More...
 

Typedefs

typedef HqnIdent sw_rdr_class
 A type used to store and communicate RDR classes. More...
 
typedef HqnIdent sw_rdr_type
 RDR Types. More...
 
typedef HqnIdent sw_rdr_namespace
 A type used to store and communicate RDR Namespaces. More...
 
typedef HqnIdent sw_rdr_id
 RDR IDs. More...
 
typedef int32 sw_rdr_priority
 RDR priorities. More...
 
typedef HqnResult sw_rdr_result
 A type used to communicate return values from RDR API calls. More...
 
typedef struct sw_rdr_iterator sw_rdr_iterator
 Iterator for finding multiple RDRs. More...
 

Enumerations

enum  RDR_APIS {
  RDR_API_RDR = 1 , RDR_API_EVENT , RDR_API_PTHREADS , RDR_API_TIMER ,
  RDR_API_HTM , RDR_API_TIMELINE , RDR_API_DATA , RDR_API_JPEG ,
  RDR_API_BARCODE , RDR_API_ZLIB , RDR_API_LIBPNG , RDR_API_EXPAT ,
  RDR_API_LIBJPEG , RDR_API_RASTERSTORE , RDR_API_GUISKIN = 1000 , RDR_API_NAMEDCOLOR ,
  RDR_API_CDF , RDR_API_THROUGHPUT , RDR_API_INPUTQ , RDR_API_RASTERMANAGER_OUTPUT = 2500 ,
  RDR_API_RESERVED1 = 2000 , RDR_API_COLORLOGIC
}
 RDR-discoverable API numbers (RDR Types for RDR_CLASS_API). More...
 
enum  RDR_CLASSES {
  RDR_CLASS_EVENT = -1 , RDR_CLASS_RDR = 1 , RDR_CLASS_FONT , RDR_CLASS_RESERVE1 ,
  RDR_CLASS_API , RDR_CLASS_TIMELINE , RDR_CLASS_LOW_MEM , RDR_CLASS_SOAR ,
  RDR_CLASS_DEVICETYPE
}
 RDR Classes. More...
 
enum  RDR_NAMES {
  RDR_NAMES_RDR = 1 , RDR_NAMES_TILEAPI , RDR_NAMES_CMMAPI , RDR_NAMES_HTMAPI ,
  RDR_NAMES_NAMEDCOLOR_DEVICE , RDR_NAMES_RASTERAPI
}
 RDR Namespaces. More...
 
enum  { SW_RDR_DEFAULT = -10000 , SW_RDR_NORMAL = 0 , SW_RDR_OVERRIDE = 10000 }
 Enumeration of RDR priorities. More...
 
enum  RDR_RESULT {
  SW_RDR_SUCCESS = HQN_RESULT_SUCCESS , SW_RDR_ERROR , SW_RDR_ERROR_UNKNOWN , SW_RDR_ERROR_SYNTAX ,
  SW_RDR_ERROR_IN_USE , SW_RDR_ERROR_MEMORY
}
 Return values from RDR API calls. More...
 

Functions

int rdr_start (void)
 Initialise the RDR system. More...
 
void rdr_end (void)
 Finalise the RDR system. More...
 
HqBool get_skin_api_ptr (sw_rdr_type apitype, sw_rdr_id id, void *papi)
 Get an API pointer to a specified version of an RDR_CLASS_API resource. More...
 
sw_rdr_result SwRegisterRDR (sw_rdr_class rdrclass, sw_rdr_type rdrtype, sw_rdr_id rdrid, void *ptr, size_t length, sw_rdr_priority priority)
 Register an RDR. More...
 
sw_rdr_result SwRegisterRDRandID (sw_rdr_class rdrclass, sw_rdr_type rdrtype, sw_rdr_id *prdrid, void *ptr, size_t length, sw_rdr_priority priority)
 Register an RDR and allocate it a unique ID. More...
 
sw_rdr_result SwDeregisterRDR (sw_rdr_class rdrclass, sw_rdr_type rdrtype, sw_rdr_id rdrid, void *ptr, size_t length)
 Deregister an RDR. More...
 
sw_rdr_result SwFindRDR (sw_rdr_class rdrclass, sw_rdr_type rdrtype, sw_rdr_id rdrid, void **pptr, size_t *plength)
 Find an RDR given the Class, Type and ID. More...
 
sw_rdr_iteratorSwFindRDRbyType (sw_rdr_class rdrclass, sw_rdr_type rdrtype)
 Find all RDRs of a specified Class and Type. More...
 
sw_rdr_iteratorSwFindRDRbyClass (sw_rdr_class rdrclass)
 Find all RDRs of a specified Class. More...
 
sw_rdr_result SwNextRDR (sw_rdr_iterator *iterator, sw_rdr_class *pclass, sw_rdr_type *ptype, sw_rdr_id *pid, void **pptr, size_t *plength)
 Find an RDR by iteration. More...
 
sw_rdr_result SwLockNextRDR (sw_rdr_iterator *iterator, sw_rdr_class *pclass, sw_rdr_type *ptype, sw_rdr_id *pid, void **pptr, size_t *plength)
 Find an RDR by iteration and lock it to prevent deregistration. More...
 
sw_rdr_result SwRestartFindRDR (sw_rdr_iterator *iterator)
 Restart an RDR iterator. More...
 
sw_rdr_result SwFoundRDR (sw_rdr_iterator *iterator)
 Destroy an RDR iterator. More...
 
sw_rdr_result SwRegisterNamedRDR (sw_rdr_namespace rdrspace, const char *name, size_t namelen, sw_rdr_id rdrid, void *ptr, size_t length, sw_rdr_priority priority)
 Register a Named RDR. More...
 
sw_rdr_result SwRegisterNamedRDRandID (sw_rdr_namespace rdrspace, const char *name, size_t namelen, sw_rdr_id *prdrid, void *ptr, size_t length, sw_rdr_priority priority)
 Register a Named RDR and allocate it a unique ID. More...
 
sw_rdr_result SwDeregisterNamedRDR (sw_rdr_namespace rdrspace, const char *name, size_t namelen, sw_rdr_id rdrid, void *ptr, size_t length)
 Deregister a Named RDR. More...
 
sw_rdr_result SwFindNamedRDR (sw_rdr_namespace rdrspace, const char *name, size_t namelen, sw_rdr_id rdrid, void **pptr, size_t *plength)
 Find a named RDR given the Namespace, Name, and ID. More...
 
sw_rdr_iteratorSwFindNamedRDRbyName (sw_rdr_namespace rdrspace, const char *name, size_t namelen)
 Find all Named RDRs of a specified Namespace and Name. More...
 
static HqnResult rdr_result_translate (sw_rdr_result result)
 Translate an RDR-specific error code to a generic HqnResult error code. More...
 

Detailed Description

The RIP Data Resource (RDR) API is used to share blocks of data and functional interfaces between the skin and core, or in general, between multiple Providers and Consumers.

The RDR system is a thread-safe database for entity publishing and discovery built on the concepts of:

The RDR API allows data to be discovered at run time, rather than being statically linked at build time. This allows complete decoupling of skin-supplied, RIP-consumed data, or vice versa; allows the skin to optionally override RIP-embedded data; and even allows data to be selected contextually.

What is an RDR?

An RDR is an entity represented by an address and a size. RDRs are identified by Class, Type and ID, or by Namespace, Name and ID. RDRs usually represent a block of data in memory, but the semantic interpretation of the address and size are (with one exception) specific to the Class and Type, or Namespace, of the RDR. The address and/or size could be used to represent, amongst other things:

The interpretation of the address and length is defined by the owner of the RDR Class and Type or Namespace. The only exception is the null case where both address and length are zero, which has a special meaning: If a null RDR is the highest priority registration of a particular Class, Type and ID (or Namespace, Name and ID), it appears to the consumer as though the RDR has not been registered at all. The RDR iteration functions will fail to find anything for that Class, Type and ID (or Namespace, Name and ID). This allows one provider to suppress an RDR registered by another.

Named and unnamed RDRs

A provider can register an entity (for example an API structure pointer or a block of data in memory) as an RDR identified by Class, Type and ID, with a particular priority; or identified by Namespace, Name and ID, with a particular priority. If multiple RDRs are registered with the same Class, Type and ID (or Namespace, Name and ID), only the highest priority is visible. RDRs can be de-registered and re-prioritized at any time, possibly revealing other registrations. Registrations of the same Class, Type, ID and priority, or Namespace, Name, ID and priority, operate a strict chronological ordering, with the last registration being visible.

A consumer can locate a particular RDR by Class, Type and ID, by Namespace, Name, and ID, or iterate through RDRs by Class and Type, or by Namespace and Name.

Names and Namespaces may be more or less convenient than Classes and Types depending on where the RDR is defined and registered, and how the knowledge of the RDR's existence is identified to the RIP. RDRs are either registered, deregistered and found by Class and Type, or by Namespace and Name. There is no mixing of the concepts; RDRs registered by Class and Type cannot be discovered or deregistered by Namespace and Name, and vice-versa.

RDR Classes

Pre-defined RDR classes are enumerated in the RDR_CLASSES enumeration. Classes are subdivided into Types. The distinction between Class and Type is usually clear from the context: APIs registered as RDRs might have a Class of RDR_CLASS_API, and a Type indicating the use of the particular API (and hence its member functions). Classes are stored and passed through the interface as values of sw_rdr_class, an alias for the generic integer type HqnIdent.

RDR Types

RDR Types are enumerated elsewhere, as they are unique only within a single Class. For example, the RDR_CLASS_API Class uses the value RDR_API_EVENT (value 2) to indicate the entity is the events API pointer, and RDR_API_PTHREADS (value 3) to indicate the entity is the threading API pointer. Within another Class, Type values of 2 and 3 will have different meanings. Types are stored and passed through the interface as values of sw_rdr_type, an alias for the generic integer type HqnIdent.

RDR Namespaces

Named RDRs are typically used for RDRs where there may be multiple instances of the same type of entity with the same ID that must be selected, e.g., multiple implementation instances of an interface using the same API and version. When using named RDRs, Namespaces are used to separate the domains in which names apply. The same name can be used in multiple namespaces. Pre-defined RDR namespaces are enumerated in the RDR_NAMES enumeration.

RDR Names

An RDR name is used to discriminate between different entity registrations in a Namespace. When using named RDR objects, the name is supplied as a string and length. When searching for RDRs, the name is compared for equality using the length supplied: it need not be zero-terminated, and any zeros included in the length supplied will be included in the name comparison. The calling functions retain ownership over the memory for the name in all cases, the name will be copied by the RDR system if necessary.

RDR IDs

Individual RDRs of a particular Class and Type, or Namespace and Name, are discerned by their ID. There can only ever be one RDR with a particular Class, Type, and ID or Namespace, Name, and ID combination. The most recently registered (or highest priority) RDR with that combination is the visible RDR: see Priorities, overriding, hiding, and filtering for prioritisation. IDs are stored and passed through the interface as values of the generic integer type HqnIdent.

The significance of the ID depends on the Class and Type or Namespace and Name. In some combinations the ID is used as a version number for the RDR data; in other combinations the ID is not significant, and may be created automatically on registration by the RDR system.

Previous registrations are remembered in chronological order, and will be restored if the current RDR is deregistered. This allows contextual overriding of a default RDR.

Class, Type, and Namespace ranges

The Class and Namespace identifiers and most Type identifiers follow common conventions in the Harlequin RIP interfaces for the ranges of values that are used:

You may safely define and use RDR classes and namespaces in your own customer range for your own entities.

Using the RDR API

The RDR API is used by the Harlequin MultiRIP and Harlequin Core to communicate with RIP plugins and skins and across modular boundaries. RDR is implemented in the skin code and is general purpose. It can be used by the customers for their own purposes in addition to existing RIP usage. A client can register and deregister RDRs, iterate through available RDRs, filtered by Class and Type or by Namespace and Name if required, or can directly locate a specific RDR.

Class-based RDRs are registered and deregistered using SwRegisterRDR(), SwRegisterRDRandID(), and SwDeregisterRDR(). They are discovered using SwFindRDR(), and iterated using SwFindRDRbyType() followed by SwNextRDR(), SwLockNextRDR(), and/or SwRestartFindRDR(), and finally SwFoundRDR().

Name-based RDRs are registered and deregistered using SwRegisterNamedRDR(), SwRegisterNamedRDRandID(), and SwDeregisterNamedRDR(). They are discovered using SwFindNamedRDR(), and iterated by using SwFindNamedRDRbyName() followed by SwNextRDR(), SwLockNextRDR(), and/or SwRestartFindRDR(), and finally SwFoundRDR(). When reporting Named RDR iterations through the SwNextRDR() function, the Class will be reported as RDR_CLASS_RDR, and the Type reported will be a synonym for the Namespace. The names in an RDR namespace can be iterated separately from the named RDRs, by calling SwFindRDRbyType() with the Class RDR_CLASS_RDR, and using the Namespace as the Type for the iteration.

The RDR interface is generally thread-safe, however the users of a particular RDR have to agree on the lifetimes of registered objects, so that one client does not deregister and free an object after another client has discovered it, but not finished using it. Using SwLockNextRDR() and paying attention to the SW_RDR_ERROR_IN_USE result value when deregistering RDRs can help clients avoid this problem.

Priorities, overriding, hiding, and filtering

Ideally, where two RDRs of the same Class, Type, and ID (or Namespace, Name and ID) are registered, the first would be the default definition, and the second the overridden version. In practice this chronology may be difficult to ensure, so RDR registration takes a priority parameter. High priority registrations always override lower priority registrations, regardless of registration ordering. Strict chronological ordering is still maintained within any one priority level.

RDR priorities can be used to override registrations, to temporarily hide registrations, and to install API filters. The RDR system provides three suggested priority levels to use for registrations, but you may vary from these:

To temporarily override an RDR, you can register a new entity with the same Class, Type, and ID (or Namespace, Name and ID) but with a higher priority than any expected existing registration, perform an operation, and then deregister the entity. For this to be effective, you have to know that the client will perform a search or iteration over the RDRs during the period your registration is active.

To install API filters, you can use RDR to discover an API structure, retain a pointer or a copy of the API structure, and then install your own definition of the API structure with a higher priority that manipulates data or diverts the function calls, calling the saved API copy as necessary. The RDR examples section contains examples of these use cases.

While RDR provides a great deal of flexibility for developers, you also require equivalent responsibility to both document the expected protocols, and for clients to follow those protocols. Arbitrarily suppressing overriding RDRs may cause incorrect functioning of software that relies on them, including the Harlequin core RIP and SDK.

Uses of RDR by the RIP core

The main use for RDR by the Harlequin RIP core code is for discovery of externally provided implementation code for APIs. This allows OEMs to share libraries used by a RIP integration; to upgrade libraries provided by Global Graphics; and to provide custom implementations for some functionality.

The RIP also uses RDR so that optional or additional code, such as device type implementations, CMM and screening modules can use data supplied by the RIP skin without requiring a proprietary skin interface and associated build variance. This allows you to supply your own device type implementations, CMM or screening modules, or to omit them entirely, with no other configuration or build changes.

The RIP core uses RDR registered APIs for a number of libraries that it uses internally. Using RDR allows you to intercept and redirect the API calls, so you can upgrade the version of a library that the RIP core uses, or share the library with your own application code, without needing a new RIP core library.

RDR API discovery in the Harlequin RIP SDK

The utility function get_skin_api_ptr() is provided by the Harlequin RIP SDK to assist discovery of API pointers registered in the RDR Class RDR_CLASS_API. The get_skin_api_ptr() function has special logic to allow it to get the Pthreads API even before the SDK is initialized. If this function fails, the application should abort immediately. The Harlequin SDK and RIP will not function without it.

RDR examples

This section describes possible usages of the RDR system in more detail.

De-coupling run-time resource discovery from compile-time linkage

To have code access data located elsewhere, a symbol must be exported from the data provider and linked to the consumer. This kind of linkage can cause build difficulties, and is entirely inflexible the data cannot be optional unless the consumer is build-variant, and if there is a variable number of chunks of data, further complexity arises.

Registering data as an RDR, even when the supplier and consumer are within the same file, has many advantages including the ability to have that data overridden by some other system, or for further RDRs of that type to be defined.

For example, a module that displays the authors of all systems and modules in the build might be as simple as this:

void init_credits()
{
static char me[] = "Fred Bloggs\0" ;
SwRegisterRDRandID(RDR_CLASS_MISC, RDR_MISC_AUTHOR, 0, me, sizeof(me), 0) ;
}
// ...
void credits()
{
sw_rdr_iterator * iterator = SwFindRDRbyType(RDR_CLASS_MISC, RDR_MISC_AUTHOR) ;
if (iterator) {
void *ptr ;
while (SwNextRDR(iterator, 0, 0, 0, &ptr, 0) == SW_RDR_SUCCESS) {
const char *author = ptr ;
printf("%s\n",author) ;
}
SwFoundRDR(iterator) ;
}
}
sw_rdr_iterator * SwFindRDRbyType(sw_rdr_class rdrclass, sw_rdr_type rdrtype)
Find all RDRs of a specified Class and Type.
sw_rdr_result SwRegisterRDRandID(sw_rdr_class rdrclass, sw_rdr_type rdrtype, sw_rdr_id *prdrid, void *ptr, size_t length, sw_rdr_priority priority)
Register an RDR and allocate it a unique ID.
sw_rdr_result SwNextRDR(sw_rdr_iterator *iterator, sw_rdr_class *pclass, sw_rdr_type *ptype, sw_rdr_id *pid, void **pptr, size_t *plength)
Find an RDR by iteration.
sw_rdr_result SwFoundRDR(sw_rdr_iterator *iterator)
Destroy an RDR iterator.
@ SW_RDR_SUCCESS
Definition: rdrapi.h:617
Our private iterator structure.
Definition: rdrpriv.h:141

Anything that wanted to output such a message would register an RDR of the appropriate type and the RDR system does all the work. Note the usage of SwRegisterRDRandID() to ensure each registration has a unique ID so that all registrations are visible.

API detection and redefinition

It is possible to reveal APIs as RDRs. This allows a module controller to redefine an API implementation, but also allows multiple versions of an API to coexist without confusion.

For example, the sw_data_api implementor could publish its code like this:

&sw_data_api_impl, sizeof(sw_data_api_impl),
sw_rdr_result SwRegisterRDR(sw_rdr_class rdrclass, sw_rdr_type rdrtype, sw_rdr_id rdrid, void *ptr, size_t length, sw_rdr_priority priority)
Register an RDR.
@ RDR_API_DATA
Definition: apis.h:52
@ RDR_CLASS_API
Definition: rdrapi.h:517
@ SW_RDR_DEFAULT
Definition: rdrapi.h:609

Note that sizeof() is not usually important unless the thing pointed to can be different lengths, such as an array or a subclassed (extended) structure. To be generally useful with multiple API versions, versioned API struct definitions are also required, so a registration pointing at a structure of type sw_data_api_20071111 and a registration pointing at a structure of type sw_data_api_20110502 can exist simultaneously, using the same Class and Type but a different ID to discriminate between the different versions.

Anything that requires the data API would find it like this:

sw_data_api_20071111 *data_api = NULL ;
void *ptr ;
data_api = ptr ;
sw_rdr_result SwFindRDR(sw_rdr_class rdrclass, sw_rdr_type rdrtype, sw_rdr_id rdrid, void **pptr, size_t *plength)
Find an RDR given the Class, Type and ID.
#define NULL
Definition of NULL pointer.
Definition: hqtypes.h:37

Multiple versions of an API can coexist simultaneously without requiring code that uses those APIs to be changed when a newer version is added, and the newer version does not necessarily need to be backwards compatible.

This also allows a module controller to temporarily override an API with its own implementation during its module's initialization. Significantly, if it subsequently becomes necessary to override some other API that module implementation may already be using, no change to the module or the API is required the module controller just overrides that API too. For example:

sw_data_api_20071111 my_data_api = { // Our version of a standard API
//...
my_get_indexed, my_set_indexed,
//...
my_open_blob,
} ;
// Override that API
&my_data_api, sizeof(my_data_api), SW_RDR_OVERRIDE) ;
// Initialise our module, during which time it may ask for this API
initialise_my_module(...) ;
// Deregister the API so nothing else gets our version
&my_data_api, sizeof(my_data_api)) ;
sw_rdr_result SwDeregisterRDR(sw_rdr_class rdrclass, sw_rdr_type rdrtype, sw_rdr_id rdrid, void *ptr, size_t length)
Deregister an RDR.
@ SW_RDR_OVERRIDE
Definition: rdrapi.h:611

Note that such a module must find its APIs during its initialization and store them for later use, rather than finding them later.

The OEM can extend or modify a supplied API by finding the original with SwFindRDR(), copy or take a reference to it, then registering a replacement with a higher priority. A cloned API's lifetime would have to match that of the module that may be using it.

RDR iteration

In addition to finding an RDR by Class, Type and ID using SwFindRDR() or by Namespace, Name and ID using SwFindNamedRDR() (which may or may not succeed, depending on registrations), a consumer can also search through registered RDRs by Class and Type or by Namespace and Name.

The consumer calls SwFindRDRbyType() or SwFindNamedRDRbyName() to create an Iterator. It then calls SwNextRDR() repeatedly using that Iterator until that fails to return a matching RDR, and finally finishes with the Iterator by calling SwFoundRDR().

If such a search is a common occurrence, the consumer may choose to use a persistent Iterator. SwFindRDRbyType() and SwFindNamedRDRbyName() can be called long in advance of the search to create the Iterator. Once a search has completed you can call SwRestartFindRDR() to return the Iterator to its initialized state ready for another search. Once finished with, SwFoundRDR() must still be called to delete the Iterator.

Care must be taken to handle multi-threading safely when iterating. It is possible for an RDR to be de-registered by some other thread between a call to SwNextRDR() returning that RDR and the consumer using it. Using SwLockNextRDR() instead of SwNextRDR() avoids this possibility by locking the RDR returned to prevent it being deregistered. The RDR remains locked against deregistration until the consumer calls SwLockNextRDR() with the iterator again, or any of SwNextRDR(), SwFoundRDR() or SwRestartFindRDR().

If SwDeregisterRDR() or SwDeregisterNamedRDR() is called on a locked RDR it is deregistered at once to prevent further discovery but is only discarded once fully unlocked. Also note that multiple separate find operations could have locked the RDR many times, and all must unlock before the RDR is finally discarded.

A supplier which calls SwDeregisterRDR() or SwDeregisterNamedRDR() because it intends to discard the entity in question must therefore be prepared for that call to return SW_RDR_ERROR_IN_USE, indicating that the RDR has been locked, and retry the deregistration until that error is no longer returned, indicating the consumers have moved on to other RDRs. Only then is it safe to discard the entity in question.

Suppliers are encouraged to avoid blocking after SW_RDR_ERROR_IN_USE has been returned unless absolutely necessary.

Notes on RDR and events

The Event system is tied closely to RDR. The RDR and Event systems can be described using pull and push metaphors; or as passive and active systems.

RDR is a pull mechanism: something requiring an entity can find it (or them) at a certain moment, but the RDR system provides no direct mechanism for managing the lifetime of an individual RDR. It is conceivable that an RDR might be de-registered between something successfully finding it and actually accessing the contents. This must be considered when designing a protocol using RDRs.

The worked examples of publishing RDRs implicitly require that the lifetime of an RDR found by a module will exceed that of the module itself. The RDR system is passive, so there is no automatic usage counting. Entities that can disappear or change asynchronously, or that require lifetime management or long-term locking, should use the Event system or Timelines.

The Event system is a push mechanism: something that knows, has, or is about to remove something, can communicate immediately with interested parties with the possibility of those handlers refusing or modifying the intended behavior.

The RDR system is passive, but the Event system active. Events can also be used to find things, much like the RDR system. The distinction is that handlers are actually called by the Event system. Providers of RDRs are never informed when those RDRs are found, delivered or used.

The RDR system is automatically started when the Harlequin RIP SDK is started. It remains active until the Harlequin RIP SDK is shutdown.

The utility function rdr_result_translate() is provided the translate RDR error codes to generic HqnResult error codes.

Macro Definition Documentation

◆ SwFindRDRs

sw_rdr_iterator * SwFindRDRs (   void)    rdr_api->find_all

Find all RDRs.

Deprecated:
From Harlequin 13, this call is obsolete and will always return NULL.

This call begins an iteration to find all RDRs.

Returns
A pointer to a sw_rdr_iterator or NULL. If NULL, there was insufficient memory to create the iterator. Otherwise, this is passed (multiple times) to SwNextRDR(), and ultimately must be destroyed by calling SwFoundRDR().

Typedef Documentation

◆ sw_rdr_class

A type used to store and communicate RDR classes.

Values of this type will be one of the RDR_CLASSES enumeration values.

◆ sw_rdr_id

RDR IDs.

IDs are unique per Class and Type, and are either predefined elsewhere or allocated on demand by SwRegisterRDRandID().

◆ sw_rdr_iterator

Iterator for finding multiple RDRs.

These are created by any of the SwFindRDR*() calls, passed to SwNextRDR(), can be restarted by SwRestartFindRDR() and are destroyed by SwFoundRDR().

They are opaque and should not be inspected or altered.

◆ sw_rdr_namespace

A type used to store and communicate RDR Namespaces.

Values of this type will be one of the RDR_NAMES enumeration values.

◆ sw_rdr_priority

RDR priorities.

RDRs defined with the same Class:Type:ID or Namespace:Name:ID combination are held in strict chronological order, with the most recent registration being the visible definition. Prioritisation allows this chronology to be overridden, in that low priority RDRs are guaranteed to be superseded by higher priority registrations, regardless of chronology. Strict chronological ordering is maintained for RDRs at the same priority level.

◆ sw_rdr_result

A type used to communicate return values from RDR API calls.

This is a subclass of HqnResult that also supports some specific extra error codes generated by RDR (declared as the RDR_RESULT enumeration). Before assigning to values of HqnResult type or any of its other subclasses, sw_rdr_result values must be converted to change the RDR specific values to HQN_RESULT_SUCCESS or a monitor UID error code greater than MON_CLASS_ERROR. This can be done by including the file rdrerrors.h and calling the function rdr_result_translate().

◆ sw_rdr_type

RDR Types.

Types are defined on a per-Class basis elsewhere.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum

Enumeration of RDR priorities.

It is defined that the usual case is a priority of zero, so SW_RDR_NORMAL can be replaced with 0 in actual code.

Priority is primarily used to discern default from override definitions, but within any particular Class and Type, prioritisation can be used to implement any weighting, preference or selection process.

Note however that priority is an attribute of the Provider's registration, not of the RDR that is being registered - the priority of the RDR is not revealed to the Consumer.

Enumerator
SW_RDR_DEFAULT 

Known to be a default

SW_RDR_NORMAL 

The usual case

SW_RDR_OVERRIDE 

High priority registration

◆ RDR_APIS

enum RDR_APIS

RDR-discoverable API numbers (RDR Types for RDR_CLASS_API).

API numbering follows the numbering conventions for DEVICETYPE numbers.

  • The range 0x00000000-0x0000ffff is reserved for Global Graphics.
  • The range 0xXXXX0000-0xXXXXffff is reserved for customer number XXXX.
  • The range 0xffff0000-0xffffffff is for private use in closed environments.

These ranges are sub-allocated here and elsewhere.

Enumerator
RDR_API_RDR 

RIP Data Resource (RDR) System gets the pride of place!

RDR_API_EVENT 

Events system

RDR_API_PTHREADS 

Threads interface

RDR_API_TIMER 

Timed callback system

RDR_API_HTM 

Halftone module interface

RDR_API_TIMELINE 

Timeline API

RDR_API_DATA 

Structured data callback API

RDR_API_JPEG 

JPEG integration API

RDR_API_BARCODE 

Barcode Generation API

RDR_API_ZLIB 

ZLIB interface

RDR_API_LIBPNG 

LibPNG interface

RDR_API_EXPAT 

Expat XML parser interface

RDR_API_LIBJPEG 

LibJPEG library integration API

RDR_API_RASTERSTORE 

Raster store interface

RDR_API_GUISKIN 

(HMR only)

RDR_API_NAMEDCOLOR 

(HMR only)

RDR_API_CDF 

(HMR only)

RDR_API_THROUGHPUT 

(HMR only)

RDR_API_INPUTQ 

Input queue and source API (HMR and HHR)

RDR_API_RASTERMANAGER_OUTPUT 

RIP Farm Raster backend to Raster Manager API

RDR_API_COLORLOGIC 

(GG internal)

◆ RDR_CLASSES

RDR Classes.

Classes are defined here and subdivided into Types defined elsewhere.

Class numbering follows the numbering conventions for DEVICETYPE numbers.

  • The range 0x00000000-0x0000ffff is reserved for Global Graphics.
  • The range 0xXXXX0000-0xXXXXffff is reserved for customer number XXXX.
  • The range 0xffff0000-0xffffffff is for private use in closed environments.
Enumerator
RDR_CLASS_EVENT 

Asynchronous Events and Messages for Events system

RDR_CLASS_RDR 

For RDR's internal use

RDR_CLASS_FONT 

Embedded font files

RDR_CLASS_RESERVE1 

Reserved

RDR_CLASS_API 

Function tables, such as skin-supplied timer API. Type is identifier, ID is version number. Types are defined in apis.h

RDR_CLASS_TIMELINE 

Timeline specific definitions for Timeline API

RDR_CLASS_LOW_MEM 

Low-memory handlers

RDR_CLASS_SOAR 

SOAR NX command-line options (HMR only)

RDR_CLASS_DEVICETYPE 

DEVICETYPE structures provided by skin.

◆ RDR_NAMES

enum RDR_NAMES

RDR Namespaces.

Namespace numbering follows the numbering conventions for DEVICETYPE numbers.

  • The range 0x00000000-0x0000ffff is reserved for Global Graphics.
  • The range 0xXXXX0000-0xXXXXffff is reserved for customer number XXXX.
  • The range 0xffff0000-0xffffffff is for private use in closed environments.

These ranges are sub-allocated here and elsewhere.

Names in an RDR Namespace can be iterated by using SwFindRDRbyType(), using Class RDR_CLASS_RDR and the namespace as the iteration Type.

When reporting named RDR iterations through SwNextRDR(), the Class will be RDR_CLASS_RDR and the Type will be a synonym for the namespace, using one of the Namespace values.

Enumerator
RDR_NAMES_RDR 

Reserved for RDR internal use

RDR_NAMES_TILEAPI 

Instances of the Tiling method API

RDR_NAMES_CMMAPI 

Instances of the Color management module interface

RDR_NAMES_HTMAPI 

Instances of the Halftone module interface

RDR_NAMES_NAMEDCOLOR_DEVICE 

Details for named color device instance.

RDR_NAMES_RASTERAPI 

Instances of the Raster backend output API

◆ RDR_RESULT

enum RDR_RESULT

Return values from RDR API calls.

Enumerator
SW_RDR_SUCCESS 

Normal return value

SW_RDR_ERROR 

Some unknown failure occurred

SW_RDR_ERROR_UNKNOWN 

Specified RDR is undefined

SW_RDR_ERROR_SYNTAX 

Programming error - illegal parameters

SW_RDR_ERROR_IN_USE 

Re-entrancy error - iterator conflict

SW_RDR_ERROR_MEMORY 

Memory allocation failed

Function Documentation

◆ get_skin_api_ptr()

HqBool get_skin_api_ptr ( sw_rdr_type  apitype,
sw_rdr_id  id,
void *  papi 
)

Get an API pointer to a specified version of an RDR_CLASS_API resource.

Parameters
[in]apitypeThe API type to get the pointer for.
[in]idThe version number of the API to get the pointer for.
[out]papiA pointer to the API pointer to be updated. A pointer to the API version requested will be stored in this location, if the API version is known and the API is valid. Nothing will be written through this pointer if the API version is not known or it is not yet valid.
Return values
TRUEif the API pointer requested was stored in papi.
FALSEif the API pointer requested was not known or the API was not valid.

If the RDR API is linked into a dynamic library, applications or libraries linking with it will not have direct access to the storage for the API pointers used to indirect to the API functions. The recommended method of discovering this API is to look it up in RDR. However, the first access will happen before the pointer is accessible to a application. In this case, the API pointer can be discovered through this function.

◆ rdr_end()

void rdr_end ( void  )

Finalise the RDR system.

The control variable and mutex are destroyed, and allocations discarded.

Note
The RDR system is finalised when the Harlequin RIP SDK is shutdown. Do not call this function directly.

◆ rdr_result_translate()

static HqnResult rdr_result_translate ( sw_rdr_result  result)
inlinestatic

Translate an RDR-specific error code to a generic HqnResult error code.

Parameters
[in]resultOne of the RDR_RESULT values, or an error value greater than MON_CLASS_ERROR.
Returns
Either HQN_RESULT_SUCCESS, or an error value greater than MON_CLASS_ERROR.

The header file defining this function should be included explicitly in every C or C++ file that calls it.

◆ rdr_start()

int rdr_start ( void  )

Initialise the RDR system.

The mutex and control variables are created and configured, and the concurrency count zeroed.

Note
The RDR system is started when the Harlequin RIP SDK is started. Do not call this function directly.

◆ SwDeregisterNamedRDR()

sw_rdr_result SwDeregisterNamedRDR ( sw_rdr_namespace  rdrspace,
const char *  name,
size_t  namelen,
sw_rdr_id  rdrid,
void *  ptr,
size_t  length 
)

Deregister a Named RDR.

This call deregisters a Named RDR of a particular Namespace, Name and ID. Any previously registered RDR of that Namespace, Name and ID will reappear.

Parameters
[in]rdrspaceThe Namespace of the RDR when registered.
[in]nameThe Name of the RDR within this Namespace.
[in]namelenThe length of the RDR name.
[in]rdridThe ID of the Named RDR within this Namespace and Name. If an ID was automatically allocated, it must be supplied to deregister the RDR.
[in]ptrA pointer to the start of the data. This must be the originally registered pointer.
[in]lengthThe length of the data. This must be the originally registered length.
Return values
SW_RDR_SUCCESSif the RDR was deregistered.
SW_RDR_ERROR_UNKNOWNis returned if the RDR could not be found.
SW_RDR_ERROR_IN_USEif the RDR is locked. This is informational - the RDR has been deregistered and cannot be found again. It will be discarded only when there are no remaining locks on it. It is not safe to dispose of the RDR contents if this error is returned, see below.

All parameters MUST match those specified during registration for the RDR to be deregistered.

Note that this prevents (or at least changes) discovery of a particular RDR - it does not withdraw access rights from Consumers that have already found the RDR - that must be achieved by some additional protocol such as an Event or Timeline.

If the RDR has been locked by SwLockNextRDR(), it is deregistered but SW_RDR_ERROR_IN_USE is returned. This call can be repeated and will continue to return SW_RDR_ERROR_IN_USE for as long as the RDR is locked. Once unlocked it will automatically be discarded and this call will return SW_RDR_ERROR_UNKNOWN. See SwLockNextRDR() for more details of RDR locking.

Important: If the RDR refers to something that is to be discarded after deregistration it must NOT be discarded until SwDeregisterNamedRDR() returns something other than SW_RDR_ERROR_IN_USE.

When the last RDR using a particular name is deregistered from a namespace, the name is removed from the iterable names in the namespace.

◆ SwDeregisterRDR()

sw_rdr_result SwDeregisterRDR ( sw_rdr_class  rdrclass,
sw_rdr_type  rdrtype,
sw_rdr_id  rdrid,
void *  ptr,
size_t  length 
)

Deregister an RDR.

This call deregisters an RDR of a particular Class, Type and ID. Any previously registered RDR of that Class, Type and ID will reappear.

Parameters
[in]rdrclassThe Class of the RDR when registered.
[in]rdrtypeThe Type of the RDR when registered.
[in]rdridThe ID of the RDR within this Class and Type. If an ID was automatically allocated, it must be supplied to deregister the RDR.
[in]ptrA pointer to the start of the data. This must be the originally registered pointer.
[in]lengthThe length of the data. This must be the originally registered length.
Return values
SW_RDR_SUCCESSif the RDR was deregistered.
SW_RDR_ERROR_UNKNOWNis returned if the RDR could not be found.
SW_RDR_ERROR_IN_USEif the RDR is locked. This is informational - the RDR has been deregistered and cannot be found again. It will be discarded only when there are no remaining locks on it. It is not safe to dispose of the RDR contents if this error is returned, see below.

All parameters MUST match those specified during registration for the RDR to be deregistered.

Note that this prevents (or at least changes) discovery of a particular RDR - it does not withdraw access rights from Consumers that have already found the RDR - that must be achieved by some additional protocol such as an Event or Timeline.

If the RDR has been locked by SwLockNextRDR(), it is deregistered but SW_RDR_ERROR_IN_USE is returned. This call can be repeated and will continue to return SW_RDR_ERROR_IN_USE for as long as the RDR is locked. Once unlocked it will automatically be discarded and this call will return SW_RDR_ERROR_UNKNOWN. See SwLockNextRDR() for more details of RDR locking.

Important: If the RDR refers to something that is to be discarded after deregistration it must NOT be discarded until SwDeregisterRDR() returns something other than SW_RDR_ERROR_IN_USE.

◆ SwFindNamedRDR()

sw_rdr_result SwFindNamedRDR ( sw_rdr_namespace  rdrspace,
const char *  name,
size_t  namelen,
sw_rdr_id  rdrid,
void **  pptr,
size_t *  plength 
)

Find a named RDR given the Namespace, Name, and ID.

Parameters
[in]rdrspaceThe Namespace of the RDR.
[in]nameThe Name of the RDR within this Namespace.
[in]namelenThe length of the RDR name.
[in]rdridThe ID of the RDR.
[out]pptrA pointer to a pointer. If not NULL, this will be filled in with the pointer if the RDR is found.
[out]plengthA pointer to a length. If not NULL, this will be filled in with the length if the RDR is found.
Return values
SW_RDR_SUCCESSif the RDR was found;
SW_RDR_ERROR_UNKNOWNis returned if no named RDR with the specified Namespace, Name, and ID was found.

eg:

result = SwFindNamedRDR(mynamespace, CSTRING_AND_LENGTH("MyName"), myid, &ptr, &len);
if (result == SW_RDR_SUCCESS) {
...
}
sw_rdr_result SwFindNamedRDR(sw_rdr_namespace rdrspace, const char *name, size_t namelen, sw_rdr_id rdrid, void **pptr, size_t *plength)
Find a named RDR given the Namespace, Name, and ID.
#define CSTRING_AND_LENGTH(s1_)
Definition: std.h:156

◆ SwFindNamedRDRbyName()

sw_rdr_iterator* SwFindNamedRDRbyName ( sw_rdr_namespace  rdrspace,
const char *  name,
size_t  namelen 
)

Find all Named RDRs of a specified Namespace and Name.

This call begins an iteration to find all RDRs of a specific typa and name.

Parameters
[in]rdrspaceThe Namespace of the RDR.
[in]nameThe Name of the RDR within this Namespace.
[in]namelenThe length of the RDR name.
Returns
A pointer to a sw_rdr_iterator or NULL. If NULL, there was insufficient memory to create the iterator. Otherwise, this is passed (multiple times) to SwNextRDR(), and ultimately must be destroyed by calling SwFoundRDR().

It is permissible to create the iterator long in advance of calling SwNextRDR() to avoid the possibility of failing due to insufficient memory. Iterators can be restarted using SwRestartFindRDR() and hence multiple searches can be performed using the same iterator without having to call SwFoundRDR() and SwFindRDRbyName() again. e.g.,

iterator = SwFindNamedRDRbyName(mynamespace, CSTRING_AND_LENGTH("MyName"));
if (iterator) {
while (SwNextRDR(iterator, 0, 0, &id, &ptr, &len) == SW_RDR_SUCCESS) {
...
}
SwFoundRDR(iterator);
}
sw_rdr_iterator * SwFindNamedRDRbyName(sw_rdr_namespace rdrspace, const char *name, size_t namelen)
Find all Named RDRs of a specified Namespace and Name.

When calling SwNextRDR(), the namespace will be reported through that function's Type output pointer.

◆ SwFindRDR()

sw_rdr_result SwFindRDR ( sw_rdr_class  rdrclass,
sw_rdr_type  rdrtype,
sw_rdr_id  rdrid,
void **  pptr,
size_t *  plength 
)

Find an RDR given the Class, Type and ID.

This call allows the consumer to find a specific RDR.

Parameters
[in]rdrclassThe Class of the RDR.
[in]rdrtypeThe Type of the RDR.
[in]rdridThe ID of the RDR.
[out]pptrA pointer to a pointer. If not NULL, this will be filled in with the pointer if the RDR is found.
[out]plengthA pointer to a length. If not NULL, this will be filled in with the length if the RDR is found.
Return values
SW_RDR_SUCCESSif the RDR was found;
SW_RDR_ERROR_UNKNOWNis returned if no RDR of the specified Class, Type and ID was found.

eg:

result = SwFindRDR(myclass, mytype, myid, &ptr, &len);
if (result == SW_RDR_SUCCESS) {
...
}

◆ SwFindRDRbyClass()

sw_rdr_iterator* SwFindRDRbyClass ( sw_rdr_class  rdrclass)

Find all RDRs of a specified Class.

Deprecated:
From Harlequin 13, this call is obsolete and will always return NULL.

This call begins an iteration to find all RDRs of a specific class.

Parameters
[in]rdrclassThe Class of the RDR.
Returns
A pointer to a sw_rdr_iterator or NULL. If NULL, there was insufficient memory to create the iterator. Otherwise, this is passed (multiple times) to SwNextRDR(), and ultimately must be destroyed by calling SwFoundRDR().

◆ SwFindRDRbyType()

sw_rdr_iterator* SwFindRDRbyType ( sw_rdr_class  rdrclass,
sw_rdr_type  rdrtype 
)

Find all RDRs of a specified Class and Type.

This call begins an iteration to find all RDRs of a specific type.

Parameters
[in]rdrclassThe Class of the RDR.
[in]rdrtypeThe Type of the RDR.
Returns
A pointer to a sw_rdr_iterator or NULL. If NULL, there was insufficient memory to create the iterator. Otherwise, this is passed (multiple times) to SwNextRDR(), and ultimately must be destroyed by calling SwFoundRDR().

It is permissible to create the iterator long in advance of calling SwNextRDR() to avoid the possibility of failing due to insufficient memory. Iterators can be restarted using SwRestartFindRDR() and hence multiple searches can be performed using the same iterator without having to call SwFoundRDR() and SwFindRDRbyType() again. e.g.,

iterator = SwFindRDRbyType(myclass, mytype);
if (iterator) {
while (SwNextRDR(iterator, 0, 0, &id, &ptr, &len) == SW_RDR_SUCCESS) {
...
}
SwFoundRDR(iterator);
}

◆ SwFoundRDR()

sw_rdr_result SwFoundRDR ( sw_rdr_iterator iterator)

Destroy an RDR iterator.

This call ends an iteration to find RDRs.

Parameters
[in]iteratorThe iterator to destroy. Passing in a NULL iterator is pointless but safe.
Return values
SW_RDR_SUCCESSnormally;
SW_RDR_ERROR_IN_USEif the iterator cannot be destroyed because it is threaded;
SW_RDR_ERROR_SYNTAXif the iterator is not recognised.

This automatically unlocks the RDR returned by a call to SwLockNextRDR().

◆ SwLockNextRDR()

sw_rdr_result SwLockNextRDR ( sw_rdr_iterator iterator,
sw_rdr_class pclass,
sw_rdr_type ptype,
sw_rdr_id pid,
void **  pptr,
size_t *  plength 
)

Find an RDR by iteration and lock it to prevent deregistration.

All parameters and behavour as SwNextRDR(), except the returned RDR is locked and can not be deregistered. It is unlocked automatically when the iterator is next passed to SwNextRDR(), SwLockNextRDR(), SwFoundRDR() or SwRestartFindRDR().

If SwDeregisterRDR() or SwDeregisterNamedRDR() are called on a locked RDR it is deregistered at once to prevent further discovery but is only discarded once fully unlocked. Note that multiple seperate find operations could have locked the RDR many times, and all must unlock before the RDR is finally discarded.

Important: If the RDR refers to something that is to be discarded after deregistration it must NOT be discarded until SwDeregisterRDR() or SwDeregisterNamedRDR() returned something other than SW_RDR_ERROR_IN_USE.

◆ SwNextRDR()

sw_rdr_result SwNextRDR ( sw_rdr_iterator iterator,
sw_rdr_class pclass,
sw_rdr_type ptype,
sw_rdr_id pid,
void **  pptr,
size_t *  plength 
)

Find an RDR by iteration.

This call returns an RDR from the given iterator.

Parameters
[in]iteratorThe sw_rdr_iterator created by SwFindRDR*().
[out]pclassOptional pointer to an RDR class. If not NULL, this will be filled in with the class of the found RDR. If iterating named RDRs, the class will be RDR_CLASS_RDR.
[out]ptypeOptional pointer to an RDR type. If not NULL, this will be filled in with the type of the found RDR. If iterating named RDRs, the namespace will be returned through this pointer.
[out]pidOptional pointer to an RDR id. If not NULL, this will be filled in with the Id of the found RDR.
[out]pptrPointer to a pointer. If not NULL, this will be filled in with the ptr of the found RDR.
[out]plengthPointer to a length. If not NULL, this will be filled in with the length of the found RDR.
Return values
SW_RDR_SUCCESSif an RDR was found;
SW_RDR_ERROR_UNKNOWNif no further RDRs match;
SW_RDR_ERROR_SYNTAXif the iterator is invalid.

Once the iteration is finished, the iterator must be destroyed by calling SwFoundRDR(), or reset using SwRestartFindRDR() if the iterator is to persist or be reused immediately.

Note that in a multithreaded system it is possible for an RDR to be deregistered after this call has returned but before the caller tries to use it. See SwLockNextRDR().

◆ SwRegisterNamedRDR()

sw_rdr_result SwRegisterNamedRDR ( sw_rdr_namespace  rdrspace,
const char *  name,
size_t  namelen,
sw_rdr_id  rdrid,
void *  ptr,
size_t  length,
sw_rdr_priority  priority 
)

Register a Named RDR.

This call registers an RDR of a particular Namespace, Name, and ID.

Parameters
[in]rdrspaceThe Namespace of the Named RDR. Named RDRs are subdivided into Namespaces, which are enumerated elsewhere.
[in]nameThe Name of the RDR within this Namespace.
[in]namelenThe length of the RDR name.
[in]rdridThe ID of the RDR within this Namespace and Name.
[in]ptrA pointer to the start of the data. This pointer can be NULL. See below for special behaviour if length is also zero.
[in]lengthThe length of the data. This length can be zero. If ptr is NOT NULL then this delivers a zero-length RDR. This may still be meaningful to the consumer. If the length is zero AND the ptr is NULL (and this RDR is the highest priority registration), then any existing RDR of this Namespace, Name, and ID is suppressed and therefore appears to the consumer to be unregistered. Deregistering this RDR will cause the previous registration to reappear.
[in]priorityThe priority of the registration - usually zero. Known defaults can be registered with a negative priority such as SW_RDR_DEFAULT. This ensures they are placed below any existing definition of the same Namespace:Name:ID combination (with a higher priority) - as though the default registration occured first. Similarly, a positive priority such as SW_RDR_OVERRIDE will remain the definitive registration until a registration at the same or higher priority is made.
Returns
SW_RDR_SUCCESS if the RDR was successfully registered. One of the RDR_RESULT codes otherwise.

Reregistering an existing RDR (with the same parameters including ptr and length) does not produce multiple RDRs - it simply ensures that this RDR definition supersedes any of the same priority.

If there are any named RDRs registered in a namespace, the names in it can be iterated by using SwFindRDRbyType(), using Class RDR_CLASS_RDR and the namespace as the iteration Type.

◆ SwRegisterNamedRDRandID()

sw_rdr_result SwRegisterNamedRDRandID ( sw_rdr_namespace  rdrspace,
const char *  name,
size_t  namelen,
sw_rdr_id prdrid,
void *  ptr,
size_t  length,
sw_rdr_priority  priority 
)

Register a Named RDR and allocate it a unique ID.

This call registers an RDR as above, but also allocates it a new ID which has not been used within that Namespace and Name.

Parameters
[in]rdrspaceThe Namespace of the RDR.
[in]nameThe Name of the RDR within this Namespace.
[in]namelenThe length of the RDR name.
[out]prdridA pointer to an RDR ID, or NULL. An unused ID (within this Namespace and Name) will be allocated and returned if this pointer is not NULL. If no pointer is provided, an ID is still allocated but is not returned to the provider, so the RDR cannot be deregistered.
[in]ptrA pointer to the start of the data.
[in]lengthThe length of the data.
[in]priorityThe priority of the registration - usually zero.
Return values
SW_RDR_SUCCESSif the RDR was successfully registered.
SW_RDR_ERRORis returned in the unlikely event of every ID already having been allocated.

◆ SwRegisterRDR()

sw_rdr_result SwRegisterRDR ( sw_rdr_class  rdrclass,
sw_rdr_type  rdrtype,
sw_rdr_id  rdrid,
void *  ptr,
size_t  length,
sw_rdr_priority  priority 
)

Register an RDR.

This call registers an RDR of a particular Class, Type and ID.

Parameters
[in]rdrclassThe Class of the RDR, as enumerated above.
[in]rdrtypeThe Type of the RDR. RDR Classes are subdivided into Types, which are enumerated elsewhere.
[in]rdridThe ID of the RDR within this Class and Type.
[in]ptrA pointer to the start of the data. This pointer can be NULL. See below for special behaviour if length is also zero.
[in]lengthThe length of the data. This length can be zero. If ptr is NOT NULL then this delivers a zero-length RDR. This may still be meaningful to the consumer. If the length is zero AND the ptr is NULL (and this RDR is the highest priority registration), then any existing RDR of this Class, Type and ID is suppressed and therefore appears to the consumer to be unregistered. Deregistering this RDR will cause the previous registration to reappear.
[in]priorityThe priority of the registration - usually zero. Known defaults can be registered with a negative priority such as SW_RDR_DEFAULT. This ensures they are placed below any existing definition of the same Class:Type:ID combination (with a higher priority) - as though the default registration occured first. Similarly, a positive priority such as SW_RDR_OVERRIDE will remain the definitive registration until a registration at the same or higher priority is made.
Returns
SW_RDR_SUCCESS if the RDR was successfully registered. One of the RDR_RESULT codes or an error greater than MON_CLASS_ERROR otherwise.

Reregistering an existing RDR (with the same parameters including ptr and length) does not produce multiple RDRs - it simply ensures that this RDR definition supersedes any of the same priority.

◆ SwRegisterRDRandID()

sw_rdr_result SwRegisterRDRandID ( sw_rdr_class  rdrclass,
sw_rdr_type  rdrtype,
sw_rdr_id prdrid,
void *  ptr,
size_t  length,
sw_rdr_priority  priority 
)

Register an RDR and allocate it a unique ID.

This call registers an RDR as above, but also allocates it a new ID which has not been used within that Class and Type.

Parameters
[in]rdrclassThe Class of the RDR.
[in]rdrtypeThe Type of the RDR.
[out]prdridA pointer to an RDR ID, or NULL. An unused ID (within this Class and Type) will be allocated and returned if this pointer is not NULL. If no pointer is provided, an ID is still allocated but is not returned to the provider, so the RDR cannot be deregistered.
[in]ptrA pointer to the start of the data.
[in]lengthThe length of the data.
[in]priorityThe priority of the registration - usually zero.
Return values
SW_RDR_SUCCESSif the RDR was successfully registered.
SW_RDR_ERRORis returned in the unlikely event of every ID already having been allocated.
Returns
One of the RDR_RESULT codes or an error greater than MON_CLASS_ERROR for a specific error.

◆ SwRestartFindRDR()

sw_rdr_result SwRestartFindRDR ( sw_rdr_iterator iterator)

Restart an RDR iterator.

This call restarts the find process by returning the iterator to its initial state. It can be called instead of SwFoundRDR() to reuse a persistent iterator. Note that ultimately it is still necessary to call SwFoundRDR() to destroy the iterator. It can be called before SwNextRDR() has exhausted its results.

Parameters
[in]iteratorThe iterator to restart.
Return values
SW_RDR_SUCCESSnormally;
SW_RDR_ERROR_IN_USEif the iterator cannot be restarted because it is threaded;
SW_RDR_ERROR_SYNTAXif the iterator is not recognised.

This automatically unlocks the RDR returned by a call to SwLockNextRDR().