diff --git a/testApp/remote/pvutils.cpp b/testApp/remote/pvutils.cpp new file mode 100644 index 0000000..52e6c59 --- /dev/null +++ b/testApp/remote/pvutils.cpp @@ -0,0 +1,218 @@ +#include "pvutils.h" + +#include + +#include +#include +#include +#include +#include + +using namespace std; +using namespace std::tr1; +using namespace epics::pvData; +using namespace epics::pvAccess; + +RequesterImpl::RequesterImpl(String const & requesterName) : + m_requesterName(requesterName) +{ +} + +String RequesterImpl::getRequesterName() +{ + return "RequesterImpl"; +} + +void RequesterImpl::message(String const & message, MessageType messageType) +{ + std::cout << "[" << getRequesterName() << "] message(" << message << ", " << getMessageTypeName(messageType) << ")" << std::endl; +} + + +char separator = ' '; +void terseSeparator(char c) +{ + separator = c; +} + +std::ostream& terse(std::ostream& o, PVField::shared_pointer const & pv) +{ + Type type = pv->getField()->getType(); + switch (type) + { + case scalar: + o << *(pv.get()); + return o; + case structure: + return terseStructure(o, static_pointer_cast(pv)); + break; + case scalarArray: + return terseScalarArray(o, static_pointer_cast(pv)); + break; + case structureArray: + return terseStructureArray(o, static_pointer_cast(pv)); + break; + default: + throw logic_error("unknown Field type: " + type); + } +} + +std::ostream& terseStructure(std::ostream& o, PVStructure::shared_pointer const & pvStructure) +{ + PVFieldPtrArray fieldsData = pvStructure->getPVFields(); + size_t length = pvStructure->getStructure()->getNumberFields(); + bool first = true; + for (size_t i = 0; i < length; i++) { + if (first) + first = false; + else + o << separator; + + terse(o, fieldsData[i]); + } + return o; +} + +std::ostream& terseScalarArray(std::ostream& o, PVScalarArray::shared_pointer const & pvArray) +{ + size_t length = pvArray->getLength(); + if (length<=0) + { + o << '0'; + return o; + } + o << length << separator; + + bool first = true; + for (size_t i = 0; i < length; i++) { + if (first) + first = false; + else + o << separator; + + pvArray->dumpValue(o, i); + } + return o; + + // avoid brackets + /* + o << *(pvArray.get()); + return o; + */ +} + +std::ostream& terseStructureArray(std::ostream& o, PVStructureArray::shared_pointer const & pvArray) +{ + size_t length = pvArray->getLength(); + if (length<=0) + { + o << '0'; + return o; + } + o << length << separator; + + StructureArrayData data = StructureArrayData(); + pvArray->get(0, length, data); + bool first = true; + for (size_t i = 0; i < length; i++) { + if (first) + first = false; + else + o << separator; + + terseStructure(o, data.data[i]); + } + return o; +} + + + + + + + + + + + +/* Converts a hex character to its integer value */ +char from_hex(char ch) { + return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10; +} + +/* Converts an integer value to its hex character*/ +char to_hex(char code) { + static char hex[] = "0123456789abcdef"; + return hex[code & 15]; +} + +/* Returns a url-encoded version of str */ +/* IMPORTANT: be sure to free() the returned string after use */ +char *url_encode(const char *str) { + const char *pstr = str; + char *buf = (char*)malloc(strlen(str) * 3 + 1), *pbuf = buf; + bool firstEquals = true; + while (*pstr) { + if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~') + *pbuf++ = *pstr; + else if (*pstr == ' ') + *pbuf++ = '+'; + else if (*pstr == '=' && firstEquals) + { + firstEquals = false; + *pbuf++ = '='; + } + else + *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15); + pstr++; + } + *pbuf = '\0'; + return buf; +} + + + +String ChannelRequesterImpl::getRequesterName() +{ + return "ChannelRequesterImpl"; +}; + +void ChannelRequesterImpl::message(String const & message, MessageType messageType) +{ + std::cerr << "[" << getRequesterName() << "] message(" << message << ", " << getMessageTypeName(messageType) << ")" << std::endl; +} + +void ChannelRequesterImpl::channelCreated(const epics::pvData::Status& status, Channel::shared_pointer const & channel) +{ + if (status.isSuccess()) + { + // show warning + if (!status.isOK()) + { + std::cerr << "[" << channel->getChannelName() << "] channel create: " << status.toString() << std::endl; + } + } + else + { + std::cerr << "[" << channel->getChannelName() << "] failed to create a channel: " << status.toString() << std::endl; + } +} + +void ChannelRequesterImpl::channelStateChange(Channel::shared_pointer const & /*channel*/, Channel::ConnectionState connectionState) +{ + if (connectionState == Channel::CONNECTED) + { + m_event.signal(); + } + /* + else if (connectionState != Channel::DESTROYED) + { + std::cout << "[" << channel->getChannelName() << "] channel state change: " << Channel::ConnectionStateNames[connectionState] << std::endl; + } + */ +} + +bool ChannelRequesterImpl::waitUntilConnected(double timeOut) +{ + return m_event.wait(timeOut); +} diff --git a/testApp/remote/pvutils.h b/testApp/remote/pvutils.h new file mode 100644 index 0000000..1369b4c --- /dev/null +++ b/testApp/remote/pvutils.h @@ -0,0 +1,54 @@ +#include +#include +#include + +/// terse mode functions +void convertStructure(epics::pvData::StringBuilder buffer, epics::pvData::PVStructure *data, int notFirst); +void convertArray(epics::pvData::StringBuilder buffer, epics::pvData::PVScalarArray * pv, int notFirst); +void convertStructureArray(epics::pvData::StringBuilder buffer, epics::pvData::PVStructureArray * pvdata, int notFirst); + +void terseSeparator(char c); +std::ostream& terse(std::ostream& o, epics::pvData::PVField::shared_pointer const & pv); +std::ostream& terseStructure(std::ostream& o, epics::pvData::PVStructure::shared_pointer const & pvStructure); +std::ostream& terseScalarArray(std::ostream& o, epics::pvData::PVScalarArray::shared_pointer const & pvArray); +std::ostream& terseStructureArray(std::ostream& o, epics::pvData::PVStructureArray::shared_pointer const & pvArray); + + +/* Converts a hex character to its integer value */ +char from_hex(char ch); + +/* Converts an integer value to its hex character*/ +char to_hex(char code); + +/* Returns a url-encoded version of str */ +/* IMPORTANT: be sure to free() the returned string after use */ +char *url_encode(const char *str); + + +class RequesterImpl : + public epics::pvData::Requester +{ + public: + RequesterImpl(epics::pvData::String const & requesterName); + virtual epics::pvData::String getRequesterName(); + virtual void message(epics::pvData::String const & message, epics::pvData::MessageType messageType); + + private: + epics::pvData::String m_requesterName; +}; + +class ChannelRequesterImpl : + public epics::pvAccess::ChannelRequester +{ + private: + epics::pvData::Event m_event; + + public: + virtual epics::pvData::String getRequesterName(); + virtual void message(epics::pvData::String const & message, epics::pvData::MessageType messageType); + + virtual void channelCreated(const epics::pvData::Status& status, epics::pvAccess::Channel::shared_pointer const & channel); + virtual void channelStateChange(epics::pvAccess::Channel::shared_pointer const & channel, epics::pvAccess::Channel::ConnectionState connectionState); + + bool waitUntilConnected(double timeOut); +};