Add some documentation to plist/xqos functions

Signed-off-by: Erik Boasson <eb@ilities.com>
This commit is contained in:
Erik Boasson 2020-06-03 15:28:57 +02:00 committed by eboasson
parent 2579256535
commit 6161f5c44d
2 changed files with 424 additions and 8 deletions

View file

@ -233,20 +233,64 @@ typedef struct ddsi_plist {
/***/ /***/
typedef struct ddsi_plist_src { typedef struct ddsi_plist_src {
nn_protocol_version_t protocol_version; nn_protocol_version_t protocol_version; /**< input protocol version */
nn_vendorid_t vendorid; nn_vendorid_t vendorid; /**< vendor code for input */
int encoding; int encoding; /**< PL_CDR_LE or PL_CDR_BE */
const unsigned char *buf; const unsigned char *buf; /**< input buffer */
size_t bufsz; size_t bufsz; /**< size of input buffer */
bool strict; bool strict; /**< whether to be strict in checking */
ddsi_tran_factory_t factory; /* eliminate this */ ddsi_tran_factory_t factory; /**< transport; eliminate this */
struct ddsrt_log_cfg *logconfig; struct ddsrt_log_cfg *logconfig; /**< logging configuration */
} ddsi_plist_src_t; } ddsi_plist_src_t;
/**
* @brief Initialize global parameter-list parsing indices.
*
* These indices are derived from compile-time constant tables. This only does the work
* once; ideally it would be done at compile time instead.
*/
void ddsi_plist_init_tables (void); void ddsi_plist_init_tables (void);
/**
* @brief Initialize a ddsi_plist_t as an empty object
*
* In principle, this only clears the "present" and "aliased" bitmasks. A debug build
* additionally initializes all other bytes to 0x55.
*
* @param[out] dest plist_t to be initialized.
*/
DDS_EXPORT void ddsi_plist_init_empty (ddsi_plist_t *dest); DDS_EXPORT void ddsi_plist_init_empty (ddsi_plist_t *dest);
/**
* @brief Extend "a" with selected entries present in "b"
*
* This copies into "a" any entries present in "b" that are included in "pmask" and
* "qmask" and missing in "a". It doesn't touch any entries already present in "a".
* Calling this on an empty "a" with all bits set in "pmask" and "qmask" all is equivalent
* to copying "b" into "a"; calling this with "pmask" and "qmask" both 0 copies nothing.
*
* @param[in,out] a ddsi_plist_t to be extended
* @param[in] b ddsi_plist_t from which to copy entries
* @param[in] pmask subset of non-QoS part of b (if PP_X is set, include X)
* @param[in] qmask subset of QoS part of b (if QP_X is set, include X)
*/
DDS_EXPORT void ddsi_plist_mergein_missing (ddsi_plist_t *a, const ddsi_plist_t *b, uint64_t pmask, uint64_t qmask); DDS_EXPORT void ddsi_plist_mergein_missing (ddsi_plist_t *a, const ddsi_plist_t *b, uint64_t pmask, uint64_t qmask);
/**
* @brief Copy "src" to "dst"
*
* @param[out] dst destination, any contents are overwritten
* @param[in] src source ddsi_plist_t
*/
DDS_EXPORT void ddsi_plist_copy (ddsi_plist_t *dst, const ddsi_plist_t *src); DDS_EXPORT void ddsi_plist_copy (ddsi_plist_t *dst, const ddsi_plist_t *src);
/**
* @brief Duplicate "src"
*
* @param[in] src ddsi_plist_t to be duplicated
*
* @returns a new (allocated using ddsrt_malloc) ddsi_plist_t containing a copy of "src".
*/
DDS_EXPORT ddsi_plist_t *ddsi_plist_dup (const ddsi_plist_t *src); DDS_EXPORT ddsi_plist_t *ddsi_plist_dup (const ddsi_plist_t *src);
/** /**
@ -296,19 +340,176 @@ DDS_EXPORT ddsi_plist_t *ddsi_plist_dup (const ddsi_plist_t *src);
* flag set; dest is cleared, *nextafterplist is NULL. * flag set; dest is cleared, *nextafterplist is NULL.
*/ */
DDS_EXPORT dds_return_t ddsi_plist_init_frommsg (ddsi_plist_t *dest, char **nextafterplist, uint64_t pwanted, uint64_t qwanted, const ddsi_plist_src_t *src); DDS_EXPORT dds_return_t ddsi_plist_init_frommsg (ddsi_plist_t *dest, char **nextafterplist, uint64_t pwanted, uint64_t qwanted, const ddsi_plist_src_t *src);
/**
* @brief Free memory owned by "ps"
*
* A ddsi_plist_t may own other allocated blocks of memory, depending on which fields are
* set, their types and whether they are marked as "aliased". This function releases any
* such memory owned by "ps", but not "ps" itself. Afterward, the contents of "ps" is
* undefined and must not be used again without initialising it (either via
* `ddsi_plist_init_empty`, `ddsi_plist_init_frommsg` or `ddsi_plist_copy`.
*
* @param[in] ps ddsi_plist_t for which to free memory
*/
DDS_EXPORT void ddsi_plist_fini (ddsi_plist_t *ps); DDS_EXPORT void ddsi_plist_fini (ddsi_plist_t *ps);
/**
* @brief Free memory owned by "plist" for a subset of the entries
*
* A ddsi_plist_t may own other allocated blocks of memory, depending on which fields are
* set, their types and whether they are marked as "aliased". This function releases any
* such memory owned by "plist" for entries included in "pmask" and "qmask". The
* "present" and "aliased" bits are cleared accordingly.
*
* @param[in,out] plist ddsi_plist_t for which to free memory
* @param[in] pmask subset of non-QoS part of b (if PP_X is set, free X if present)
* @param[in] qmask subset of QoS part of b (if QP_X is set, free X if present)
*/
DDS_EXPORT void ddsi_plist_fini_mask (ddsi_plist_t *plist, uint64_t pmask, uint64_t qmask); DDS_EXPORT void ddsi_plist_fini_mask (ddsi_plist_t *plist, uint64_t pmask, uint64_t qmask);
/**
* @brief Replace any memory "plist" aliases by copies it owns
*
* A ddsi_plist_t may can reference other memory without owning it. This functions allows
* one to replace any such aliased memory by copies, allowing one to free the original
* copy.
*
* @param[in,out] plist ddsi_plist_t for which to replace all aliased memory by owned
* copies
*/
DDS_EXPORT void ddsi_plist_unalias (ddsi_plist_t *plist); DDS_EXPORT void ddsi_plist_unalias (ddsi_plist_t *plist);
/**
* @brief Add selected entries in "ps" to a message in native endianness.
*
* This functions appends to "m" a serialized copy of the the entries selected by
* "pwanted"/"qwanted" and present in "ps". Each copy is preceded by a 4-byte header with
* a parameter id and length (conform the PL_CDR representation). It does *not* add a
* sentinel to allow adding additional data to the parameter list. A sentinel can be
* added using `nn_xmsg_addpar_sentinel`.
*
* @param[in,out] m message to append the parameters to
* @param[in] ps source
* @param[in] pwanted subset of non-QoS part of ps (if PP_X is set, add X if present)
* @param[in] qwanted subset of QoS part of ps (if QP_X is set, add X if present)
*/
DDS_EXPORT void ddsi_plist_addtomsg (struct nn_xmsg *m, const ddsi_plist_t *ps, uint64_t pwanted, uint64_t qwanted); DDS_EXPORT void ddsi_plist_addtomsg (struct nn_xmsg *m, const ddsi_plist_t *ps, uint64_t pwanted, uint64_t qwanted);
/**
* @brief Add selected entries in "ps" to a message with selected endianness.
*
* This functions appends to "m" a serialized copy of the the entries selected by
* "pwanted"/"qwanted" and present in "ps". Each copy is preceded by a 4-byte header with
* a parameter id and length (conform the PL_CDR representation). It does *not* add a
* sentinel to allow adding additional data to the parameter list. A sentinel can be
* added using `nn_xmsg_addpar_sentinel`.
*
* @param[in,out] m message to append the parameters to
* @param[in] ps source
* @param[in] pwanted subset of non-QoS part of ps (if PP_X is set, add X if present)
* @param[in] qwanted subset of QoS part of ps (if QP_X is set, add X if present)
* @param[in] be use native endianness if false, big-endian if true
*/
DDS_EXPORT void ddsi_plist_addtomsg_bo (struct nn_xmsg *m, const ddsi_plist_t *ps, uint64_t pwanted, uint64_t qwanted, bool be); DDS_EXPORT void ddsi_plist_addtomsg_bo (struct nn_xmsg *m, const ddsi_plist_t *ps, uint64_t pwanted, uint64_t qwanted, bool be);
/**
* @brief Initialize plist to match default settings for a participant
*
* @param[out] plist plist to contain the default settings.
*/
DDS_EXPORT void ddsi_plist_init_default_participant (ddsi_plist_t *plist); DDS_EXPORT void ddsi_plist_init_default_participant (ddsi_plist_t *plist);
/**
* @brief Determine the set of entries in which "x" differs from "y"
*
* This computes the entries set in "x" but not set in "y", not set in "x" but set in "y",
* or set in both "x" and "y" but to a different value. It returns this set reduced to
* only those included in "pmask"/"qmask", that is, if bit X is clear in "pmask", bit X
* will be clear in "pdelta", etc.
*
* @param[out] pdelta non-QoS entries that are different and not masked out
* @param[out] qdelta QoS entries that are different and not masked out
* @param[in] x one of the two plists to compare
* @param[in] y other plist to compare
* @param[in] pmask subset of non-QoS part to be compared
* @param[in] qmask subset of QoS part to be compared
*/
DDS_EXPORT void ddsi_plist_delta (uint64_t *pdelta, uint64_t *qdelta, const ddsi_plist_t *x, const ddsi_plist_t *y, uint64_t pmask, uint64_t qmask); DDS_EXPORT void ddsi_plist_delta (uint64_t *pdelta, uint64_t *qdelta, const ddsi_plist_t *x, const ddsi_plist_t *y, uint64_t pmask, uint64_t qmask);
/**
* @brief Formats plist using `ddsi_plist_print` and writes it to the trace.
*
* @param[in] cat log category to use
* @param[in] logcfg logging configuration
* @param[in] plist parameter list to be logged
*/
DDS_EXPORT void ddsi_plist_log (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const ddsi_plist_t *plist); DDS_EXPORT void ddsi_plist_log (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const ddsi_plist_t *plist);
/**
* @brief Formats plist into a buffer
*
* The representation is somewhat cryptic as all enumerated types are dumped as numbers
* and timestamps are durations as nanoseconds with "infinite" represented as
* 9223372036854775807 (INT64_MAX).
*
* @param[out] buf buffer to store the formatted representation in
* @param[in] bufsize size of buffer, if > 0, there will be a terminating 0 in buf on
* return
* @param[in] plist parameter list to be formatted as a string
*
* @returns number of bytes written to buf, excluding a terminating 0.
*/
DDS_EXPORT size_t ddsi_plist_print (char * __restrict buf, size_t bufsize, const ddsi_plist_t *plist); DDS_EXPORT size_t ddsi_plist_print (char * __restrict buf, size_t bufsize, const ddsi_plist_t *plist);
struct nn_rsample_info; struct nn_rsample_info;
/**
* @brief Scan a PL_CDR-serialized parameter list, checking structure and copying some information to "dest".
*
* This checks that the serialized data is structured correctly (proper aligned headers,
* declared lengths within bounds, a sentinel at the end). It sets the `statusinfo` of
* `dest` to the least significant two bits (UNREGISTER and DISPOSE) of a status info
* parameter if present, else to 0. A statusinfo parameter that is too short (less than 4
* bytes) is treated as an invalid input.
*
* It sets the `complex_qos` flag if it encounters any parameter other than a statusinfo
* limited to those two bits, keyhash or padding, and clears it otherwise.
*
* It clears the `bswap` flag in `dest` if the input is in native endianness, and sets it
* otherwise.
*
* @param[in] src input description (see `ddsi_plist_init_frommsg`)
* @param[out] dest internal sample info of which some fields will be set
*
* @return pointer to the first byte following the sentinel if the input is well-formed, a
* null pointer if it is not.
*/
DDS_EXPORT unsigned char *ddsi_plist_quickscan (struct nn_rsample_info *dest, const ddsi_plist_src_t *src); DDS_EXPORT unsigned char *ddsi_plist_quickscan (struct nn_rsample_info *dest, const ddsi_plist_src_t *src);
/**
* @brief Locate a specific parameter in a PL_CDR-serialized parameter list
*
* This scans the serialized data until it encounters the sentinel, recording whether the
* specified parameter occurs and returning the size and address of it in `buf`.
*
* If `needle` is PID_SENTINEL, it will simply check well-formedness of the input and
* `needlep` and `needlesz` must both be null pointers. If `needle` is not PID_SENTINEL,
* `needlep` and `needlesz` may not be null pointers.
*
* @param[in] buf serialized parameter list to scan
* @param[in] bufsz length of serialized form
* @param[in] encoding encoding of `buf`, either PL_CDR_LE or PL_CDR_BE
* @param[in] needle parameter id to look for
* @param[out] needlep where to store the address of the `needle` value
* @param[out] needlesz where to store the size of the `needle` value
*
* @return Whether input was valid and if so, whether it contains the needle.
*
* @retval DDS_RETCODE_BAD_PARAMETER invalid input
* @retval DDS_RETCODE_NOT_FOUND valid input, `needle` not present
* @retval DDS_RETCODE_OK valid input, `needle` is present
*/
DDS_EXPORT dds_return_t ddsi_plist_findparam_checking (const void *buf, size_t bufsz, uint16_t encoding, nn_parameterid_t needle, void **needlep, size_t *needlesz); DDS_EXPORT dds_return_t ddsi_plist_findparam_checking (const void *buf, size_t bufsz, uint16_t encoding, nn_parameterid_t needle, void **needlep, size_t *needlesz);
#if defined (__cplusplus) #if defined (__cplusplus)

View file

@ -304,25 +304,240 @@ struct dds_qos {
struct nn_xmsg; struct nn_xmsg;
/**
* @brief Initialize a new empty dds_qos_t as an empty object
*
* In principle, this only clears the "present" and "aliased" bitmasks. A debug build
* additionally initializes all other bytes to 0x55.
*
* @param[out] xqos qos object to be initialized.
*/
DDS_EXPORT void ddsi_xqos_init_empty (dds_qos_t *xqos); DDS_EXPORT void ddsi_xqos_init_empty (dds_qos_t *xqos);
/**
* @brief Initialize xqos to match default QoS settings for a reader
*
* @param[out] xqos qos object to contain the default settings.
*/
DDS_EXPORT void ddsi_xqos_init_default_reader (dds_qos_t *xqos); DDS_EXPORT void ddsi_xqos_init_default_reader (dds_qos_t *xqos);
/**
* @brief Initialize xqos to match default QoS settings for a writer
*
* @param[out] xqos qos object to contain the default settings.
*/
DDS_EXPORT void ddsi_xqos_init_default_writer (dds_qos_t *xqos); DDS_EXPORT void ddsi_xqos_init_default_writer (dds_qos_t *xqos);
/**
* @brief Initialize xqos to match default QoS settings for a non-autodispose writer
*
* The default writer QoS has "auto dispose unregistered instances" set to true, and
* opinions differ about what the correct behaviour is, but the setting doesn't really
* make any sense if it is treated as a macro on the writing such, such that each
* "unregister" call also performs a dispose. Cyclone DDS implements the interpretation
* that matches the name (whenever no registrations are left, make it disposed), which is
* a refinement of OpenSplice's interpretation (whenever an unregister event occurs, make
* it disposed). All these differences originate in the DCPS spec not being clear enough
* and the complicating factor is that the two different interpretations existed before
* the introduction of the DDSI specification, and yet the DDSI specification doesn't
* provide a standard way of discovering the setting for remote writers.
*
* Cyclone DDS uses the same vendor-specific extension as OpenSplice for communicating it,
* and uses a different default for different implementations. So this is the default
* used for the "RTI interpretation".
*
* @param[out] xqos qos object to contain the default settings.
*/
DDS_EXPORT void ddsi_xqos_init_default_writer_noautodispose (dds_qos_t *xqos); DDS_EXPORT void ddsi_xqos_init_default_writer_noautodispose (dds_qos_t *xqos);
/**
* @brief Initialize xqos to match default QoS settings for a subscriber
*
* @param[out] xqos qos object to contain the default settings.
*/
DDS_EXPORT void ddsi_xqos_init_default_subscriber (dds_qos_t *xqos); DDS_EXPORT void ddsi_xqos_init_default_subscriber (dds_qos_t *xqos);
/**
* @brief Initialize xqos to match default QoS settings for a publisher
*
* @param[out] xqos qos object to contain the default settings.
*/
DDS_EXPORT void ddsi_xqos_init_default_publisher (dds_qos_t *xqos); DDS_EXPORT void ddsi_xqos_init_default_publisher (dds_qos_t *xqos);
/**
* @brief Initialize xqos to match default QoS settings for a topic
*
* @param[out] xqos qos object to contain the default settings.
*/
DDS_EXPORT void ddsi_xqos_init_default_topic (dds_qos_t *xqos); DDS_EXPORT void ddsi_xqos_init_default_topic (dds_qos_t *xqos);
/**
* @brief Copy "src" to "dst"
*
* @param[out] dst destination, any contents are overwritten
* @param[in] src source dds_qos_t
*/
DDS_EXPORT void ddsi_xqos_copy (dds_qos_t *dst, const dds_qos_t *src); DDS_EXPORT void ddsi_xqos_copy (dds_qos_t *dst, const dds_qos_t *src);
/**
* @brief Replace any memory "xqos" aliases by copies it owns
*
* A dds_qos_t may can reference other memory without owning it. This functions allows
* one to replace any such aliased memory by copies, allowing one to free the original
* copy.
*
* @param[in,out] xqos qos object for which to replace all aliased memory by owned
* copies
*/
DDS_EXPORT void ddsi_xqos_unalias (dds_qos_t *xqos); DDS_EXPORT void ddsi_xqos_unalias (dds_qos_t *xqos);
/**
* @brief Free memory owned by "xqos"
*
* A dds_qos_t may own other allocated blocks of memory, depending on which fields are
* set, their types and whether they are marked as "aliased". This function releases any
* such memory owned by "xqos", but not "xqos" itself. Afterward, the content of "xqos"
* is undefined and must not be used again without initialising it.
*
* @param[in] xqos dds_qos_t for which to free memory
*/
DDS_EXPORT void ddsi_xqos_fini (dds_qos_t *xqos); DDS_EXPORT void ddsi_xqos_fini (dds_qos_t *xqos);
/**
* @brief Free memory owned by "xqos" for a subset of the entries
*
* A dds_qos_t may own other allocated blocks of memory, depending on which fields are
* set, their types and whether they are marked as "aliased". This function releases any
* such memory owned by "xqos" for entries included in "mask". The "present" and
* "aliased" bits are cleared accordingly.
*
* @param[in,out] xqos dds_qos_t for which to free memory
* @param[in] mask entries to free (if QP_X is set, free X if present)
*/
DDS_EXPORT void ddsi_xqos_fini_mask (dds_qos_t *xqos, uint64_t mask); DDS_EXPORT void ddsi_xqos_fini_mask (dds_qos_t *xqos, uint64_t mask);
/**
* @brief Check whether xqos is valid according to the validation rules in the spec
*
* The checks concern the values for the individual fields as well as a few combinations
* of fields. Only those that are set are checked (the defaults are all valid anyway),
* and where a combination of fields must be checked and some but not all fields are
* specified, it uses the defaults for the missing ones.
*
* Invalid values get logged as category "plist" according to the specified logging
* configuration.
*
* @param[in] logcfg logging configuration
* @param[in] xqos qos object to check
*
* @returns DDS_RETCODE_OK or DDS_RETCODE_BAD_PARAMETER
*/
DDS_EXPORT dds_return_t ddsi_xqos_valid (const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos); DDS_EXPORT dds_return_t ddsi_xqos_valid (const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos);
/**
* @brief Extend "a" with selected entries present in "b"
*
* This copies into "a" any entries present in "b" that are included in "mask" and missing
* in "a". It doesn't touch any entries already present in "a". Calling this on an empty
* "a" with all bits set in "mask" is equivalent to copying "b" into "a"; calling this
* with "mask" 0 copies nothing.
*
* @param[in,out] a dds_qos_t to be extended
* @param[in] b dds_qos_t from which to copy entries
* @param[in] mask which to include (if QP_X is set, include X)
*/
DDS_EXPORT void ddsi_xqos_mergein_missing (dds_qos_t *a, const dds_qos_t *b, uint64_t mask); DDS_EXPORT void ddsi_xqos_mergein_missing (dds_qos_t *a, const dds_qos_t *b, uint64_t mask);
/**
* @brief Determine the set of entries in which "x" differs from "y"
*
* This computes the entries set in "x" but not set in "y", not set in "x" but set in "y",
* or set in both "x" and "y" but to a different value. It returns this set reduced to
* only those included in "mask", that is, if bit X is clear in "mask", bit X will be
* clear in the result.
*
* @param[in] a one of the two plists to compare
* @param[in] b other plist to compare
* @param[in] mask subset of entries to be compared
*
* @returns Bitmask of differences
*/
DDS_EXPORT uint64_t ddsi_xqos_delta (const dds_qos_t *a, const dds_qos_t *b, uint64_t mask); DDS_EXPORT uint64_t ddsi_xqos_delta (const dds_qos_t *a, const dds_qos_t *b, uint64_t mask);
/**
* @brief Add selected entries in "xqos" to a message in native endianness.
*
* This functions appends to "xqos" a serialized copy of the the entries selected by
* "wanted" and present in "xqos". Each copy is preceded by a 4-byte header with a
* parameter id and length (conform the PL_CDR representation). It does *not* add a
* sentinel to allow adding additional data to the parameter list. A sentinel can be
* added using `nn_xmsg_addpar_sentinel`.
*
* @param[in,out] m message to append the parameters to
* @param[in] xqos source
* @param[in] wanted subset to be added (if QP_X is set, add X if present)
*/
DDS_EXPORT void ddsi_xqos_addtomsg (struct nn_xmsg *m, const dds_qos_t *xqos, uint64_t wanted); DDS_EXPORT void ddsi_xqos_addtomsg (struct nn_xmsg *m, const dds_qos_t *xqos, uint64_t wanted);
/**
* @brief Formats xqos using `ddsi_xqos_print` and writes it to the trace.
*
* @param[in] cat log category to use
* @param[in] logcfg logging configuration
* @param[in] xqos qos object to be logged
*/
DDS_EXPORT void ddsi_xqos_log (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos); DDS_EXPORT void ddsi_xqos_log (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos);
/**
* @brief Formats xqos into a buffer
*
* The representation is somewhat cryptic as all enumerated types are dumped as numbers
* and timestamps are durations as nanoseconds with "infinite" represented as
* 9223372036854775807 (INT64_MAX).
*
* @param[out] buf buffer to store the formatted representation in
* @param[in] bufsize size of buffer, if > 0, there will be a terminating 0 in buf on
* return
* @param[in] xqos parameter list to be formatted as a string
*
* @returns number of bytes written to buf, excluding a terminating 0.
*/
DDS_EXPORT size_t ddsi_xqos_print (char * __restrict buf, size_t bufsize, const dds_qos_t *xqos); DDS_EXPORT size_t ddsi_xqos_print (char * __restrict buf, size_t bufsize, const dds_qos_t *xqos);
/**
* @brief Duplicate "src"
*
* @param[in] src dds_qos_t to be duplicated
*
* @returns a new (allocated using ddsrt_malloc) dds_qos_t containing a copy of "src".
*/
DDS_EXPORT dds_qos_t *ddsi_xqos_dup (const dds_qos_t *src); DDS_EXPORT dds_qos_t *ddsi_xqos_dup (const dds_qos_t *src);
/**
* @brief Check if "xqos" includes properties with a name starting with "nameprefix"
*
* That is, if xqos.present has QP_PROPERTY_LIST set, and at least one of them has a name
* starting with "nameprefix".
*
* @param[in] xqos qos object to check
* @param[in] nameprefix prefix to check for
*
* @returns true iff xqos contains a matching property
*/
DDS_EXPORT bool ddsi_xqos_has_prop_prefix (const dds_qos_t *xqos, const char *nameprefix); DDS_EXPORT bool ddsi_xqos_has_prop_prefix (const dds_qos_t *xqos, const char *nameprefix);
/**
* @brief Lookup property "name" in "xqos" and return a pointer to its value
*
* The value pointer is left unchanged if the property doesn't exist. The returned
* address points into the memory owned by the QoS object and must not be freed.
*
* @param[in] xqos qos object to check
* @param[in] name name to look for
* @param[out] value pointer to set to the value of the property if it exists
*
* @returns true iff xqos contains the property
*/
DDS_EXPORT bool ddsi_xqos_find_prop (const dds_qos_t *xqos, const char *name, const char **value); DDS_EXPORT bool ddsi_xqos_find_prop (const dds_qos_t *xqos, const char *name, const char **value);
#ifdef DDSI_INCLUDE_SECURITY #ifdef DDSI_INCLUDE_SECURITY