Files
pvData/src/copy/pv/createRequest.h
Michael Davidsaver 32aa0dd72f drop extractRequestMask()
superceded by PVRequestMapper
2018-09-21 10:27:43 -07:00

234 lines
8.5 KiB
C++

/*createRequest.h*/
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
#ifndef CREATEREQUEST_H
#define CREATEREQUEST_H
#include <string>
#include <sstream>
#include <vector>
#include <pv/pvData.h>
#include <pv/lock.h>
#include <pv/bitSet.h>
#include <shareLib.h>
namespace epics { namespace pvData {
class BitSet;
/**
* @brief Create pvRequest structure for Channel methods.
*
* Many methods of the Channel class of pvAccess have an
* argument <b>PVStructurePtr const * pvRequest</b>.
* This class provides a method that creates a valid pvRequest.
*
*/
class epicsShareClass CreateRequest {
public:
POINTER_DEFINITIONS(CreateRequest);
/**
* Create s new instance of CreateRequest
* @returns A shared pointer to the new instance.
*/
static CreateRequest::shared_pointer create();
~CreateRequest() {};
/**
* Create a request structure for the create calls in Channel.
* See the package overview documentation for details.
* @param request The field request. See the package overview documentation for details.
* @return The request PVStructure if a valid request was given.
* If a NULL PVStructure is returned then getMessage will return
* the reason.
*/
PVStructure::shared_pointer createRequest(std::string const & request);
/**
* Get the error message of createRequest returns NULL
* return the error message
*/
std::string getMessage() {return message;}
protected:
CreateRequest() {}
std::string message;
};
/** Parse and build pvRequest structure.
*
@params request the Request string to be parsed. eg. "field(value)"
@returns The resulting strucuture. Never NULL
@throws std::exception for various parsing errors
*/
epicsShareExtern
PVStructure::shared_pointer createRequest(std::string const & request);
/** Helper for implementations of epics::pvAccess::ChannelProvider in interpreting the
* 'field' substructure of a pvRequest.
* Copies between an internal (base) Structure, and a client/user visible (requested) Structure.
*
* @note PVRequestMapper is not re-entrant. It is copyable and swap()able.
*/
class epicsShareClass PVRequestMapper {
public:
enum mode_t {
/** Masking mode.
*
* Requested Structure is identical to Base.
* The 'field' substructure of the provided pvRequest is used to construct a BitSet
* where the bits corresponding to the "selected" fields are set. This mask can be
* access via. requestedMask(). The copy* and mask* methods operate only
* on "selected" fields.
*/
Mask,
/** Slice mode
*
* The Requested Structure is a strict sub-set of the Base Structure containing
* those fields "selected" by the 'field' substructure of the provided pvRequest.
*/
Slice,
};
PVRequestMapper();
//! @see compute()
PVRequestMapper(const PVStructure& base,
const PVStructure& pvRequest,
mode_t mode = Mask);
//! return to state of default ctor
void reset();
//! @returns the Structure of the PVStructure previously passed to compute(). NULL if never computed()'d
inline const StructureConstPtr& base() const { return typeBase; }
//! @returns the Structure which is the selected sub-set of the base Structure. NULL if never computed()'d
inline const StructureConstPtr& requested() const { return typeRequested; }
/** A mask of all fields in the base structure which are also in the requested structure,
* and any parent/structure "compress" bits. eg. bit 0 is always set.
*
@code
PVRequestMapper mapper(...);
...
BitSet changed = ...; // a base changed mask
bool wouldcopy = changed.logical_and(mapper.requestedMask());
// wouldcopy==false means that copyBaseToRequested(..., changed, ...) would be a no-op
@endcode
*
* eg. allows early detection of empty monitor updates.
*/
inline const BitSet& requestedMask() const { return maskRequested; }
//! @returns A new instance of the requested() Structure
PVStructurePtr buildRequested() const;
//! @returns A new instance of the base() Structure
PVStructurePtr buildBase() const;
/** (re)compute the selected subset of provided base structure.
* @param base A full base structure.
* Must be "top level" (field offset zero).
* @param pvRequest The user/client provided request modifier
* @param mode Control how the mapping is constructed. @see mode_t for a description of mapping modes.
*
* @post Updates warnings()
* @throws std::runtime_error For errors involving invalid pvRequest
* @throws std::logic_error if the provided base is not a "top level" PVStructure.
*/
void compute(const PVStructure& base,
const PVStructure& pvRequest,
mode_t mode = Mask);
//! After compute(), check if !warnings().empty()
inline const std::string& warnings() const { return messages; }
/** Copy field values from Base structure into Requested structure
*
* @param base An instance of the base Structure. Field values are copied from it.
* Need not be the same instance passed to compute().
* @param baseMask A bit mask selecting those base fields to copy.
* @param request An instance of the requested() Structure. Field values are copied to it.
* @param requestMask A bit mask indicating which requested fields were copied.
* BitSet::clear() is not called.
*/
void copyBaseToRequested(
const PVStructure& base,
const BitSet& baseMask,
PVStructure& request,
BitSet& requestMask
) const;
/** Copy field values into Base structure from Requested structure
*
* @param base An instance of the base Structure. Field values are copied into it.
* Need not be the same instance passed to compute().
* @param baseMask A bit mask indicating which base fields were copied.
* BitSet::clear() is not called.
* @param request An instance of the requested() Structure. Field values are copied from it.
* @param requestMask A bit mask selecting those requested fields to copy.
*/
void copyBaseFromRequested(
PVStructure& base,
BitSet& baseMask,
const PVStructure& request,
const BitSet& requestMask
) const;
//! Translate Base bit mask into requested bit mask.
//! BitSet::clear() is not called.
inline void maskBaseToRequested(
const BitSet& baseMask,
BitSet& requestMask
) const
{ _mapMask(baseMask, requestMask, false); }
//! Translate requested bit mask into base bit mask.
//! BitSet::clear() is not called.
inline void maskBaseFromRequested(
BitSet& baseMask,
const BitSet& requestMask
) const
{ _mapMask(requestMask, baseMask, true); }
//! Exchange contents of two mappers. O(0) and never throws.
void swap(PVRequestMapper& other);
private:
bool _compute(const PVStructure& base, const PVStructure& pvReq,
FieldBuilderPtr& builder, bool keepids, unsigned depth);
void _map(const PVStructure& src,
const BitSet& maskSrc,
PVStructure& dest,
BitSet& maskDest,
bool dir_r2b) const;
void _mapMask(const BitSet& maskSrc,
BitSet& maskDest,
bool dir_r2b) const;
StructureConstPtr typeBase, typeRequested;
BitSet maskRequested;
// Map between field offsets of base and requested Structures.
// Include all fields, both leaf and sub-structure.
struct Mapping {
size_t to; // offset in destination Structure
BitSet tomask, // if !leaf these are the other bits in the destination mask to changed
frommask; // if !leaf these are the other bits in the source mask to be copied
bool valid; // only true in (sparse) base -> requested mapping
bool leaf; // not a (sub)Structure?
Mapping() :valid(false) {}
Mapping(size_t to, bool leaf) :to(to), valid(true), leaf(leaf) {}
};
typedef std::vector<Mapping> mapping_t;
mapping_t base2req, req2base;
std::string messages;
mutable BitSet scratch; // avoid temporary allocs. (we aren't re-entrant!)
};
}}
#endif /* CREATEREQUEST_H */