mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-07-04 03:11:43 +00:00
Refactor MessageReader into WireDecoder.
Change-Id: If5842b4f6b9a7db3d3de515cd71324ab7ee82f50
This commit is contained in:
@@ -24,30 +24,13 @@ MessageHandler::anchor()
|
||||
MessageReader::MessageReader(MessageHandler &handler,
|
||||
raw_istream& is,
|
||||
unsigned int proto_rev)
|
||||
: m_handler(handler)
|
||||
, m_is(is)
|
||||
: WireDecoder(is, proto_rev)
|
||||
, m_handler(handler)
|
||||
{
|
||||
m_allocated = 1024;
|
||||
m_buf = (char *)std::malloc(m_allocated);
|
||||
m_proto_rev = proto_rev;
|
||||
m_error = 0;
|
||||
}
|
||||
|
||||
MessageReader::~MessageReader()
|
||||
{
|
||||
std::free(m_buf);
|
||||
}
|
||||
|
||||
void
|
||||
MessageReader::Realloc(std::size_t len)
|
||||
{
|
||||
if (m_allocated >= len)
|
||||
return;
|
||||
std::size_t newlen = m_allocated * 2;
|
||||
while (newlen < len)
|
||||
newlen *= 2;
|
||||
m_buf = (char *)std::realloc(m_buf, newlen);
|
||||
m_allocated = newlen;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -191,7 +174,8 @@ MessageReader::Run()
|
||||
if (!Read16(&uid)) return false;
|
||||
unsigned long size;
|
||||
if (!ReadULEB128(&size)) return false;
|
||||
if (!Read(size)) return false;
|
||||
char *buf;
|
||||
if (!Read(&buf, size)) return false;
|
||||
}
|
||||
case NT_MSG_RPC_RESPONSE:
|
||||
{
|
||||
@@ -205,7 +189,8 @@ MessageReader::Run()
|
||||
if (!Read16(&uid)) return false;
|
||||
unsigned long size;
|
||||
if (!ReadULEB128(&size)) return false;
|
||||
if (!Read(size)) return false;
|
||||
char *buf;
|
||||
if (!Read(&buf, size)) return false;
|
||||
}
|
||||
default:
|
||||
m_error = "unrecognized message type";
|
||||
@@ -213,138 +198,3 @@ MessageReader::Run()
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MessageReader::ReadType(NT_Type *type)
|
||||
{
|
||||
if (!Read(1)) return false;
|
||||
size_t len = NT_ReadType(m_buf, type, m_proto_rev);
|
||||
if (len == 0)
|
||||
{
|
||||
m_error = "unrecognized value type";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MessageReader::ReadValue(NT_Type type, NT_Value *value)
|
||||
{
|
||||
value->type = type;
|
||||
value->last_change = 0;
|
||||
switch (type)
|
||||
{
|
||||
case NT_BOOLEAN:
|
||||
{
|
||||
unsigned int v;
|
||||
if (!Read8(&v)) return false;
|
||||
value->data.v_boolean = v ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
case NT_DOUBLE:
|
||||
{
|
||||
if (!Read(8)) return false;
|
||||
char *buf = m_buf;
|
||||
value->data.v_double = ReadDouble(buf);
|
||||
break;
|
||||
}
|
||||
case NT_STRING:
|
||||
if (!ReadString(&value->data.v_string)) return false;
|
||||
break;
|
||||
case NT_RAW:
|
||||
case NT_RPC:
|
||||
if (m_proto_rev < 0x0300u)
|
||||
{
|
||||
m_error = "received raw or RPC value in protocol < 3.0";
|
||||
return false;
|
||||
}
|
||||
if (!ReadString(&value->data.v_raw)) return false;
|
||||
break;
|
||||
case NT_BOOLEAN_ARRAY:
|
||||
{
|
||||
// size
|
||||
unsigned int size;
|
||||
if (!Read8(&size)) return false;
|
||||
value->data.arr_boolean.size = size;
|
||||
|
||||
// array values
|
||||
if (!Read(size)) return false;
|
||||
value->data.arr_boolean.arr = (int *)std::malloc(size * sizeof(int));
|
||||
for (unsigned int i=0; i<size; ++i)
|
||||
value->data.arr_boolean.arr[i] = m_buf[i] ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
case NT_DOUBLE_ARRAY:
|
||||
{
|
||||
// size
|
||||
unsigned int size;
|
||||
if (!Read8(&size)) return false;
|
||||
value->data.arr_double.size = size;
|
||||
|
||||
// array values
|
||||
if (!Read(size*8)) return false;
|
||||
value->data.arr_double.arr =
|
||||
(double *)std::malloc(size * sizeof(double));
|
||||
char *buf = m_buf;
|
||||
for (unsigned int i=0; i<size; ++i)
|
||||
value->data.arr_double.arr[i] = ReadDouble(buf);
|
||||
break;
|
||||
}
|
||||
case NT_STRING_ARRAY:
|
||||
{
|
||||
// size
|
||||
unsigned int size;
|
||||
if (!Read8(&size)) return false;
|
||||
value->data.arr_string.size = size;
|
||||
|
||||
// array values
|
||||
if (!Read(size*8)) return false;
|
||||
value->data.arr_string.arr =
|
||||
(NT_String *)std::malloc(size * sizeof(NT_String));
|
||||
for (unsigned int i=0; i<size; ++i)
|
||||
{
|
||||
if (!ReadString(&value->data.arr_string.arr[i]))
|
||||
{
|
||||
// cleanup to avoid memory leaks
|
||||
for (unsigned int j=0; j<i; ++j)
|
||||
{
|
||||
std::free(value->data.arr_string.arr[j].str);
|
||||
}
|
||||
std::free(value->data.arr_string.arr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
m_error = "invalid type when trying to read value";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MessageReader::ReadString(NT_String *str)
|
||||
{
|
||||
if (m_proto_rev < 0x0300u)
|
||||
{
|
||||
unsigned int v;
|
||||
if (!Read16(&v)) return false;
|
||||
str->len = v;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned long v;
|
||||
if (!ReadULEB128(&v)) return false;
|
||||
str->len = v;
|
||||
}
|
||||
str->str = (char *)std::malloc(str->len + 1);
|
||||
if (!m_is.read(str->str, str->len))
|
||||
{
|
||||
std::free(str->str);
|
||||
str->str = 0;
|
||||
return false;
|
||||
}
|
||||
str->str[str->len] = '\0';
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -8,12 +8,7 @@
|
||||
#ifndef NT_MESSAGEREADER_H_
|
||||
#define NT_MESSAGEREADER_H_
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "ntcore.h"
|
||||
#include "nt_leb128.h"
|
||||
#include "nt_raw_istream.h"
|
||||
#include "nt_encoding.h"
|
||||
#include "nt_wiredecoder.h"
|
||||
|
||||
namespace NtImpl {
|
||||
|
||||
@@ -22,9 +17,8 @@ class MessageHandler
|
||||
void anchor();
|
||||
|
||||
public:
|
||||
// Needed for protocol rev 2.0 ENTRY_UPDATE messages.
|
||||
virtual NT_Type GetEntryType(unsigned int id) = 0;
|
||||
virtual size_t GetRpcParamTypes(NT_Type *types, unsigned int id) = 0;
|
||||
virtual size_t GetRpcResultTypes(NT_Type *types, unsigned int id) = 0;
|
||||
|
||||
// All of these functions are expected to take ownership of passed
|
||||
// strings/values.
|
||||
@@ -50,19 +44,17 @@ public:
|
||||
virtual void GotClearEntries() = 0;
|
||||
virtual void GotExecuteRpc(unsigned int id,
|
||||
unsigned int uid,
|
||||
NT_Value *params_start,
|
||||
NT_Value *params_end) = 0;
|
||||
const char *params) = 0;
|
||||
virtual void GotRpcResponse(unsigned int id,
|
||||
unsigned int uid,
|
||||
NT_Value *results_start,
|
||||
NT_Value *results_end) = 0;
|
||||
const char *results) = 0;
|
||||
|
||||
private:
|
||||
MessageHandler(const MessageHandler&);
|
||||
MessageHandler& operator= (const MessageHandler&);
|
||||
};
|
||||
|
||||
class MessageReader
|
||||
class MessageReader : private WireDecoder
|
||||
{
|
||||
public:
|
||||
explicit MessageReader(MessageHandler &handler,
|
||||
@@ -72,76 +64,26 @@ public:
|
||||
|
||||
void SetProtocolRev(unsigned int proto_rev)
|
||||
{
|
||||
m_proto_rev = proto_rev;
|
||||
WireDecoder::SetProtocolRev(proto_rev);
|
||||
}
|
||||
|
||||
bool Run();
|
||||
|
||||
void Reset()
|
||||
{
|
||||
m_error = 0;
|
||||
WireDecoder::Reset();
|
||||
}
|
||||
|
||||
const char *GetError() const
|
||||
{
|
||||
return m_error;
|
||||
return WireDecoder::GetError();
|
||||
}
|
||||
|
||||
protected:
|
||||
bool Read(std::size_t len)
|
||||
{
|
||||
if (len > m_allocated)
|
||||
Realloc(len);
|
||||
return m_is.read(m_buf, len);
|
||||
}
|
||||
|
||||
bool Read8(unsigned int *val)
|
||||
{
|
||||
if (!Read(1)) return false;
|
||||
char *buf = m_buf;
|
||||
*val = NtImpl::Read8(buf);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Read16(unsigned int *val)
|
||||
{
|
||||
if (!Read(2)) return false;
|
||||
char *buf = m_buf;
|
||||
*val = NtImpl::Read16(buf);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Read32(unsigned long *val)
|
||||
{
|
||||
if (!Read(4)) return false;
|
||||
char *buf = m_buf;
|
||||
*val = NtImpl::Read32(buf);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReadULEB128(unsigned long *val)
|
||||
{
|
||||
return read_uleb128(m_is, val);
|
||||
}
|
||||
|
||||
bool ReadType(NT_Type *type);
|
||||
bool ReadValue(NT_Type type, NT_Value *value);
|
||||
bool ReadString(NT_String *str);
|
||||
|
||||
private:
|
||||
MessageReader(const MessageReader&);
|
||||
MessageReader& operator= (const MessageReader&);
|
||||
|
||||
void Realloc(std::size_t len);
|
||||
|
||||
MessageHandler &m_handler;
|
||||
raw_istream &m_is;
|
||||
|
||||
char *m_buf;
|
||||
std::size_t m_allocated;
|
||||
|
||||
unsigned int m_proto_rev;
|
||||
const char *m_error;
|
||||
NT_Type m_rpc_types[256];
|
||||
};
|
||||
|
||||
|
||||
186
src/nt_wiredecoder.cpp
Normal file
186
src/nt_wiredecoder.cpp
Normal file
@@ -0,0 +1,186 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2015. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "nt_wiredecoder.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "nt_internal.h"
|
||||
#include "nt_leb128.h"
|
||||
|
||||
using namespace NtImpl;
|
||||
|
||||
WireDecoder::WireDecoder(raw_istream& is, unsigned int proto_rev)
|
||||
: m_is(is)
|
||||
{
|
||||
m_allocated = 1024;
|
||||
m_buf = (char *)std::malloc(m_allocated);
|
||||
m_proto_rev = proto_rev;
|
||||
m_error = 0;
|
||||
}
|
||||
|
||||
WireDecoder::~WireDecoder()
|
||||
{
|
||||
std::free(m_buf);
|
||||
}
|
||||
|
||||
void
|
||||
WireDecoder::Realloc(std::size_t len)
|
||||
{
|
||||
if (m_allocated >= len)
|
||||
return;
|
||||
std::size_t newlen = m_allocated * 2;
|
||||
while (newlen < len)
|
||||
newlen *= 2;
|
||||
m_buf = (char *)std::realloc(m_buf, newlen);
|
||||
m_allocated = newlen;
|
||||
}
|
||||
|
||||
bool
|
||||
WireDecoder::ReadType(NT_Type *type)
|
||||
{
|
||||
unsigned int itype;
|
||||
if (!Read8(&itype)) return false;
|
||||
switch (itype)
|
||||
{
|
||||
case 0x00: *type = NT_BOOLEAN; break;
|
||||
case 0x01: *type = NT_DOUBLE; break;
|
||||
case 0x02: *type = NT_STRING; break;
|
||||
case 0x03: *type = NT_RAW; break;
|
||||
case 0x10: *type = NT_BOOLEAN_ARRAY; break;
|
||||
case 0x11: *type = NT_DOUBLE_ARRAY; break;
|
||||
case 0x12: *type = NT_STRING_ARRAY; break;
|
||||
case 0x20: *type = NT_RPC; break;
|
||||
default:
|
||||
m_error = "unrecognized value type";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
WireDecoder::ReadValue(NT_Type type, NT_Value *value)
|
||||
{
|
||||
value->type = type;
|
||||
value->last_change = 0;
|
||||
switch (type)
|
||||
{
|
||||
case NT_BOOLEAN:
|
||||
{
|
||||
unsigned int v;
|
||||
if (!Read8(&v)) return false;
|
||||
value->data.v_boolean = v ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
case NT_DOUBLE:
|
||||
{
|
||||
if (!ReadDouble(&value->data.v_double)) return false;
|
||||
break;
|
||||
}
|
||||
case NT_STRING:
|
||||
if (!ReadString(&value->data.v_string)) return false;
|
||||
break;
|
||||
case NT_RAW:
|
||||
case NT_RPC:
|
||||
if (m_proto_rev < 0x0300u)
|
||||
{
|
||||
m_error = "received raw or RPC value in protocol < 3.0";
|
||||
return false;
|
||||
}
|
||||
if (!ReadString(&value->data.v_raw)) return false;
|
||||
break;
|
||||
case NT_BOOLEAN_ARRAY:
|
||||
{
|
||||
// size
|
||||
unsigned int size;
|
||||
if (!Read8(&size)) return false;
|
||||
value->data.arr_boolean.size = size;
|
||||
|
||||
// array values
|
||||
char *buf;
|
||||
if (!Read(&buf, size)) return false;
|
||||
value->data.arr_boolean.arr = (int *)std::malloc(size * sizeof(int));
|
||||
for (unsigned int i=0; i<size; ++i)
|
||||
value->data.arr_boolean.arr[i] = buf[i] ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
case NT_DOUBLE_ARRAY:
|
||||
{
|
||||
// size
|
||||
unsigned int size;
|
||||
if (!Read8(&size)) return false;
|
||||
value->data.arr_double.size = size;
|
||||
|
||||
// array values
|
||||
char *buf;
|
||||
if (!Read(&buf, size*8)) return false;
|
||||
value->data.arr_double.arr =
|
||||
(double *)std::malloc(size * sizeof(double));
|
||||
for (unsigned int i=0; i<size; ++i)
|
||||
value->data.arr_double.arr[i] = NtImpl::ReadDouble(buf);
|
||||
break;
|
||||
}
|
||||
case NT_STRING_ARRAY:
|
||||
{
|
||||
// size
|
||||
unsigned int size;
|
||||
if (!Read8(&size)) return false;
|
||||
value->data.arr_string.size = size;
|
||||
|
||||
// array values
|
||||
value->data.arr_string.arr =
|
||||
(NT_String *)std::malloc(size * sizeof(NT_String));
|
||||
for (unsigned int i=0; i<size; ++i)
|
||||
{
|
||||
if (!ReadString(&value->data.arr_string.arr[i]))
|
||||
{
|
||||
// cleanup to avoid memory leaks
|
||||
for (unsigned int j=0; j<i; ++j)
|
||||
{
|
||||
std::free(value->data.arr_string.arr[j].str);
|
||||
}
|
||||
std::free(value->data.arr_string.arr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
m_error = "invalid type when trying to read value";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
WireDecoder::ReadString(NT_String *str)
|
||||
{
|
||||
if (m_proto_rev < 0x0300u)
|
||||
{
|
||||
unsigned int v;
|
||||
if (!Read16(&v)) return false;
|
||||
str->len = v;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned long v;
|
||||
if (!ReadULEB128(&v)) return false;
|
||||
str->len = v;
|
||||
}
|
||||
str->str = (char *)std::malloc(str->len + 1);
|
||||
if (!m_is.read(str->str, str->len))
|
||||
{
|
||||
std::free(str->str);
|
||||
str->str = 0;
|
||||
return false;
|
||||
}
|
||||
str->str[str->len] = '\0';
|
||||
return true;
|
||||
}
|
||||
108
src/nt_wiredecoder.h
Normal file
108
src/nt_wiredecoder.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2015. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef NT_WIREDECODER_H_
|
||||
#define NT_WIREDECODER_H_
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "ntcore.h"
|
||||
#include "nt_leb128.h"
|
||||
#include "nt_raw_istream.h"
|
||||
#include "nt_encoding.h"
|
||||
|
||||
namespace NtImpl {
|
||||
|
||||
class WireDecoder
|
||||
{
|
||||
public:
|
||||
explicit WireDecoder(raw_istream& is, unsigned int proto_rev);
|
||||
~WireDecoder();
|
||||
|
||||
void SetProtocolRev(unsigned int proto_rev)
|
||||
{
|
||||
m_proto_rev = proto_rev;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
m_error = 0;
|
||||
}
|
||||
|
||||
const char *GetError() const
|
||||
{
|
||||
return m_error;
|
||||
}
|
||||
|
||||
bool Read(char **buf, std::size_t len)
|
||||
{
|
||||
if (len > m_allocated)
|
||||
Realloc(len);
|
||||
*buf = m_buf;
|
||||
return m_is.read(m_buf, len);
|
||||
}
|
||||
|
||||
bool Read8(unsigned int *val)
|
||||
{
|
||||
char *buf;
|
||||
if (!Read(&buf, 1)) return false;
|
||||
*val = NtImpl::Read8(buf);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Read16(unsigned int *val)
|
||||
{
|
||||
char *buf;
|
||||
if (!Read(&buf, 2)) return false;
|
||||
*val = NtImpl::Read16(buf);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Read32(unsigned long *val)
|
||||
{
|
||||
char *buf;
|
||||
if (!Read(&buf, 4)) return false;
|
||||
*val = NtImpl::Read32(buf);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReadDouble(double *val)
|
||||
{
|
||||
char *buf;
|
||||
if (!Read(&buf, 8)) return false;
|
||||
*val = NtImpl::ReadDouble(buf);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReadULEB128(unsigned long *val)
|
||||
{
|
||||
return read_uleb128(m_is, val);
|
||||
}
|
||||
|
||||
bool ReadType(NT_Type *type);
|
||||
bool ReadValue(NT_Type type, NT_Value *value);
|
||||
bool ReadString(NT_String *str);
|
||||
|
||||
protected:
|
||||
unsigned int m_proto_rev;
|
||||
const char *m_error;
|
||||
|
||||
private:
|
||||
WireDecoder(const WireDecoder&);
|
||||
WireDecoder& operator= (const WireDecoder&);
|
||||
|
||||
void Realloc(std::size_t len);
|
||||
|
||||
raw_istream &m_is;
|
||||
|
||||
char *m_buf;
|
||||
std::size_t m_allocated;
|
||||
};
|
||||
|
||||
} // namespace NtImpl
|
||||
|
||||
#endif /* NT_WIREDECODER_H_ */
|
||||
Reference in New Issue
Block a user