diff --git a/src/remote/abstractResponseHandler.cpp b/src/remote/abstractResponseHandler.cpp index 71790e4..1a494f0 100644 --- a/src/remote/abstractResponseHandler.cpp +++ b/src/remote/abstractResponseHandler.cpp @@ -4,8 +4,6 @@ * in file LICENSE that is included with this distribution. */ -#include - #include #include @@ -15,9 +13,6 @@ #include #include -using std::ostringstream; -using std::hex; - using namespace epics::pvData; namespace epics { @@ -44,13 +39,10 @@ void ResponseHandler::handleResponse(osiSockAddr* responseFrom, char ipAddrStr[48]; ipAddrToDottedIP(&responseFrom->ia, ipAddrStr, sizeof(ipAddrStr)); - ostringstream prologue; - prologue<<"Message [0x"<getRemoteName(); - - hexDump(prologue.str(), _description, - (const int8*)payloadBuffer->getArray(), - payloadBuffer->getPosition(), static_cast(payloadSize)); + std::cerr<<"Message [0x"<getRemoteName() + <<" : "<<_description<<"\n" + <getArray(), - buffer->getPosition(), buffer->getRemaining()); - } - */ - if (bytesSent < 0) { // connection lost @@ -1302,13 +1288,6 @@ int BlockingTCPTransportCodec::read(epics::pvData::ByteBuffer* dst) { // NOTE: do not log here, you might override SOCKERRNO relevant to recv() operation above - /* - if (IS_LOGGABLE(logLevelTrace)) { - hexDump(std::string("READ"), - (const int8 *)(dst->getArray()+pos), bytesRead); - } - */ - if(unlikely(bytesRead<=0)) { if (bytesRead<0) diff --git a/src/remoteClient/clientContextImpl.cpp b/src/remoteClient/clientContextImpl.cpp index bea6744..68f507d 100644 --- a/src/remoteClient/clientContextImpl.cpp +++ b/src/remoteClient/clientContextImpl.cpp @@ -2998,10 +2998,14 @@ public: { if (command < 0 || command >= (int8)m_handlerTable.size()) { - // TODO remove debug output - char buf[100]; - sprintf(buf, "Invalid (or unsupported) command %d, its payload", command); - hexDump(buf, (const int8*)(payloadBuffer->getArray()), payloadBuffer->getPosition(), payloadSize); + LOG(logLevelError, + "Invalid (or unsupported) command: %x.", (0xFF&command)); + + if(pvAccessIsLoggable(logLevelError)) { + std::cerr<<"Invalid PVA header "<=(int8)m_handlerTable.size()) { - LOG(logLevelDebug, + LOG(logLevelError, "Invalid (or unsupported) command: %x.", (0xFF&command)); - // TODO remove debug output - std::ostringstream name; - name<<"Invalid PVA header "<getArray(), - payloadBuffer->getPosition(), payloadSize); + if(pvAccessIsLoggable(logLevelError)) { + std::cerr<<"Invalid PVA header "< #include #include +#include +#include + +#include #define epicsExportSharedSymbols #include -using namespace epics::pvData; -using std::string; -using std::stringstream; -using std::endl; -using std::cout; - namespace epics { namespace pvAccess { -/// Byte to hexchar mapping. -static const char lookup[] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' -}; +HexDump::HexDump(const char* buf, size_t len) + :buf(buf) + ,buflen(len) + ,_limit(1024u) + ,_groupBy(4u) + ,_perLine(16u) +{} -/// Get hex representation of byte. -string toHex(int8 b) { - string sb; - - int upper = (b>>4)&0x0F; - sb += lookup[upper]; - - int lower = b&0x0F; - sb += lookup[lower]; - - sb += ' '; - - return sb; +HexDump::HexDump(const pvData::ByteBuffer& bb, + size_t size, size_t offset) + :buf(bb.getBuffer() + bb.getPosition()) + ,buflen(bb.getRemaining()) + ,_limit((size_t)-1) + ,_groupBy(4u) + ,_perLine(16u) +{ + if(offset > buflen) + offset = buflen; + buf += offset; + buflen -= offset; + if(buflen > size) + buflen = size; } -/// Get ASCII representation of byte, dot if non-readable. -char toAscii(int8 b) { - if(b>(int8)31&&b<(int8)127) - return (char)b; - else - return '.'; +HexDump::~HexDump() {} + +static +size_t ilog2(size_t val) +{ + size_t ret = 0; + while(val >>= 1) + ret++; + return ret; } -void hexDump(std::string const & name, const int8 *bs, int len) { - hexDump(name, bs, 0, len); +static +size_t bits2bytes(size_t val) +{ + // round up to next multiple of 8 + val -= 1u; + val |= 7u; + val += 1u; + // bits -> bytes + val /= 8u; + return val; } -void hexDump(std::string const & name, const int8 *bs, int start, int len) { - hexDump("", name, bs, start, len); -} +epicsShareFunc +std::ostream& operator<<(std::ostream& strm, const HexDump& hex) +{ + size_t len = std::min(hex.buflen, hex._limit); + // find address width in hex chars + // find bit width, rounded up to 8 bits, divide down to bytes + size_t addrwidth = bits2bytes(ilog2(len))*2u; -void hexDump(std::string const & prologue, string const & name, const int8 *bs, - int start, int len) { + for(size_t i=0; i + #ifdef epicsExportSharedSymbols # define hexDumpEpicsExportSharedSymbols # undef epicsExportSharedSymbols @@ -22,35 +24,34 @@ #include namespace epics { +namespace pvData { +class ByteBuffer; +} namespace pvAccess { -/** - * Output a buffer in hex format. - * @param name name (description) of the message. - * @param bs buffer to dump - * @param len first bytes (length) to dump. - */ -epicsShareFunc void hexDump(std::string const & name, const epics::pvData::int8 *bs, int len); +class epicsShareClass HexDump { + const char* buf; + size_t buflen; + size_t _limit; + unsigned _groupBy; + unsigned _perLine; +public: + HexDump(const char* buf, size_t len); + explicit HexDump(const pvData::ByteBuffer& buf, size_t size=(size_t)-1, size_t offset=0u); + ~HexDump(); -/** - * Output a buffer in hex format. - * @param[in] name name (description) of the message. - * @param[in] bs buffer to dump - * @param[in] start dump message using given offset. - * @param[in] len first bytes (length) to dump. - */ -epicsShareFunc void hexDump(std::string const & name, const epics::pvData::int8 *bs, int start, int len); + //! safety limit on max bytes printed + inline HexDump& limit(size_t n=(size_t)-1) { _limit = n; return *this; } + //! insert a space after this many bytes + inline HexDump& bytesPerGroup(size_t n=(size_t)-1) { _groupBy = n; return *this; } + //! start a new line after this many bytes + inline HexDump& bytesPerLine(size_t n=(size_t)-1) { _perLine = n; return *this; } -/** - * Output a buffer in hex format. - * @param[in] prologue string to prefixed to debug output, can be null - * @param[in] name name (description) of the message. - * @param[in] bs buffer to dump - * @param[in] start dump message using given offset. - * @param[in] len first bytes (length) to dump. - */ -epicsShareFunc void hexDump(std::string const & prologue, std::string const & name, - const epics::pvData::int8 *bs, int start, int len); + friend std::ostream& operator<<(std::ostream& strm, const HexDump& hex); +}; + +epicsShareFunc +std::ostream& operator<<(std::ostream& strm, const HexDump& hex); } } diff --git a/testApp/utils/testHexDump.cpp b/testApp/utils/testHexDump.cpp index d4cf207..bd10005 100644 --- a/testApp/utils/testHexDump.cpp +++ b/testApp/utils/testHexDump.cpp @@ -1,6 +1,9 @@ -#include + +#include + #include +#include #include using namespace epics::pvData; @@ -8,19 +11,16 @@ using namespace epics::pvAccess; MAIN(testHexDump) { - testPlan(3); + testPlan(1); testDiag("Tests for hexDump"); - char TO_DUMP[] = "pvAccess dump test\0\1\2\3\4\5\6\254\255\256"; + char TO_DUMP[] = "pvAccess dump test\0\1\2\3\4\5\6\xfd\xfe\xff"; - hexDump("test", (int8*)TO_DUMP, 18+9); - testPass("Entire array"); + std::ostringstream msg; + msg<