Reformat per new coding guidelines.

Change-Id: Ib0e5d3a6fabe6db414d72b334ca7a7f33bc5726b
This commit is contained in:
Peter Johnson
2015-06-25 22:57:43 -07:00
parent f5a82be9e5
commit cee77a3228
26 changed files with 1296 additions and 1576 deletions

View File

@@ -64,12 +64,12 @@
#include "nt_base64.h"
namespace NtImpl {
namespace ntimpl {
/* aaaack but it's fast and const should make it shared text page. */
// aaaack but it's fast and const should make it shared text page.
static const unsigned char pr2six[256] =
{
/* ASCII table */
// ASCII table
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
@@ -88,106 +88,88 @@ static const unsigned char pr2six[256] =
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
};
std::size_t
base64decode_len(const char *bufcoded)
{
const unsigned char *bufin = (const unsigned char *) bufcoded;
while (pr2six[*(bufin++)] <= 63) {}
std::size_t base64decode_len(const char *bufcoded) {
const unsigned char *bufin = (const unsigned char *)bufcoded;
while (pr2six[*(bufin++)] <= 63) {
}
std::size_t nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
std::size_t nbytesdecoded = ((nprbytes + 3) / 4) * 3;
std::size_t nprbytes = (bufin - (const unsigned char *)bufcoded) - 1;
std::size_t nbytesdecoded = ((nprbytes + 3) / 4) * 3;
return nbytesdecoded + 1;
return nbytesdecoded + 1;
}
std::size_t
base64decode(char *bufplain, const char *bufcoded)
{
const unsigned char *bufin = (const unsigned char *) bufcoded;
while (pr2six[*(bufin++)] <= 63) {}
std::size_t nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
std::size_t nbytesdecoded = ((nprbytes + 3) / 4) * 3;
std::size_t base64decode(char *bufplain, const char *bufcoded) {
const unsigned char *bufin = (const unsigned char *)bufcoded;
while (pr2six[*(bufin++)] <= 63) {
}
std::size_t nprbytes = (bufin - (const unsigned char *)bufcoded) - 1;
std::size_t nbytesdecoded = ((nprbytes + 3) / 4) * 3;
unsigned char *bufout = (unsigned char *) bufplain;
bufin = (const unsigned char *) bufcoded;
unsigned char *bufout = (unsigned char *)bufplain;
bufin = (const unsigned char *)bufcoded;
while (nprbytes > 4)
{
*(bufout++) =
(unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
*(bufout++) =
(unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
*(bufout++) =
(unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
bufin += 4;
nprbytes -= 4;
}
while (nprbytes > 4) {
*(bufout++) = (unsigned char)(pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
*(bufout++) =
(unsigned char)(pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
*(bufout++) = (unsigned char)(pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
bufin += 4;
nprbytes -= 4;
}
/* Note: (nprbytes == 1) would be an error, so just ingore that case */
if (nprbytes > 1)
{
*(bufout++) =
(unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
}
if (nprbytes > 2)
{
*(bufout++) =
(unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
}
if (nprbytes > 3)
{
*(bufout++) =
(unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
}
// Note: (nprbytes == 1) would be an error, so just ingore that case
if (nprbytes > 1) {
*(bufout++) = (unsigned char)(pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
}
if (nprbytes > 2) {
*(bufout++) =
(unsigned char)(pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
}
if (nprbytes > 3) {
*(bufout++) = (unsigned char)(pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
}
*(bufout++) = '\0';
nbytesdecoded -= (4 - nprbytes) & 3;
return nbytesdecoded;
*(bufout++) = '\0';
nbytesdecoded -= (4 - nprbytes) & 3;
return nbytesdecoded;
}
static const char basis_64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
std::size_t
base64encode_len(std::size_t len)
{
return ((len + 2) / 3 * 4) + 1;
std::size_t base64encode_len(std::size_t len) {
return ((len + 2) / 3 * 4) + 1;
}
std::size_t
base64encode(char *encoded, const unsigned char *string, std::size_t len)
{
std::size_t i;
char *p = encoded;
std::size_t base64encode(char *encoded, const unsigned char *string,
std::size_t len) {
std::size_t i;
char *p = encoded;
for (i = 0; i < len - 2; i += 3)
{
*p++ = basis_64[(string[i] >> 2) & 0x3F];
*p++ = basis_64[((string[i] & 0x3) << 4) |
((int) (string[i + 1] & 0xF0) >> 4)];
*p++ = basis_64[((string[i + 1] & 0xF) << 2) |
((int) (string[i + 2] & 0xC0) >> 6)];
*p++ = basis_64[string[i + 2] & 0x3F];
}
if (i < len)
{
*p++ = basis_64[(string[i] >> 2) & 0x3F];
if (i == (len - 1))
{
*p++ = basis_64[((string[i] & 0x3) << 4)];
*p++ = '=';
}
else
{
*p++ = basis_64[((string[i] & 0x3) << 4) |
((int) (string[i + 1] & 0xF0) >> 4)];
*p++ = basis_64[((string[i + 1] & 0xF) << 2)];
}
*p++ = '=';
for (i = 0; i < len - 2; i += 3) {
*p++ = basis_64[(string[i] >> 2) & 0x3F];
*p++ =
basis_64[((string[i] & 0x3) << 4) | ((int)(string[i + 1] & 0xF0) >> 4)];
*p++ = basis_64[((string[i + 1] & 0xF) << 2) |
((int)(string[i + 2] & 0xC0) >> 6)];
*p++ = basis_64[string[i + 2] & 0x3F];
}
if (i < len) {
*p++ = basis_64[(string[i] >> 2) & 0x3F];
if (i == (len - 1)) {
*p++ = basis_64[((string[i] & 0x3) << 4)];
*p++ = '=';
} else {
*p++ = basis_64[((string[i] & 0x3) << 4) |
((int)(string[i + 1] & 0xF0) >> 4)];
*p++ = basis_64[((string[i + 1] & 0xF) << 2)];
}
*p++ = '=';
}
*p++ = '\0';
return p - encoded;
*p++ = '\0';
return p - encoded;
}
} // namespace NtImpl
} // namespace ntimpl

View File

@@ -10,7 +10,7 @@
#include <cstddef>
namespace NtImpl {
namespace ntimpl {
std::size_t base64decode_len(const char *bufcoded);
std::size_t base64decode(char *bufplain, const char *bufcoded);
@@ -18,6 +18,6 @@ std::size_t base64encode_len(std::size_t len);
std::size_t base64encode(char *encoded, const unsigned char *string,
std::size_t len);
} // namespace NtImpl
} // namespace ntimpl
#endif /* NT_BASE64_H_ */
#endif // NT_BASE64_H_

View File

@@ -8,26 +8,26 @@
#ifndef NT_INTERNAL_H_
#define NT_INTERNAL_H_
namespace NtImpl {
namespace ntimpl {
enum MsgType {
NT_MSG_KEEP_ALIVE = 0x00,
NT_MSG_CLIENT_HELLO = 0x01,
NT_MSG_PROTO_UNSUP = 0x02,
NT_MSG_SERVER_HELLO_DONE = 0x03,
NT_MSG_SERVER_HELLO = 0x04,
NT_MSG_CLIENT_HELLO_DONE = 0x05,
NT_MSG_ENTRY_ASSIGN = 0x10,
NT_MSG_ENTRY_UPDATE = 0x11,
NT_MSG_FLAGS_UPDATE = 0x12,
NT_MSG_ENTRY_DELETE = 0x13,
NT_MSG_CLEAR_ENTRIES = 0x14,
NT_MSG_EXECUTE_RPC = 0x20,
NT_MSG_RPC_RESPONSE = 0x21
NT_MSG_KEEP_ALIVE = 0x00,
NT_MSG_CLIENT_HELLO = 0x01,
NT_MSG_PROTO_UNSUP = 0x02,
NT_MSG_SERVER_HELLO_DONE = 0x03,
NT_MSG_SERVER_HELLO = 0x04,
NT_MSG_CLIENT_HELLO_DONE = 0x05,
NT_MSG_ENTRY_ASSIGN = 0x10,
NT_MSG_ENTRY_UPDATE = 0x11,
NT_MSG_FLAGS_UPDATE = 0x12,
NT_MSG_ENTRY_DELETE = 0x13,
NT_MSG_CLEAR_ENTRIES = 0x14,
NT_MSG_EXECUTE_RPC = 0x20,
NT_MSG_RPC_RESPONSE = 0x21
};
#define NT_CLEAR_ALL_MAGIC 0xD06CB27Aul
#define NT_CLEAR_ALL_MAGIC 0xD06CB27Aul
} // namespace NtImpl
} // namespace ntimpl
#endif /* NT_INTERNAL_H_ */
#endif // NT_INTERNAL_H_

View File

@@ -9,7 +9,7 @@
#include "nt_raw_istream.h"
namespace NtImpl {
namespace ntimpl {
/**
* size_uleb128 - get size of unsigned LEB128 data
@@ -20,15 +20,13 @@ namespace NtImpl {
* on the encodings refer to section "7.6 - Variable Length Data". Return
* the number of bytes required.
*/
std::size_t
size_uleb128(unsigned long val)
{
std::size_t count = 0;
do {
val >>= 7;
++count;
} while (val != 0);
return count;
std::size_t size_uleb128(unsigned long val) {
std::size_t count = 0;
do {
val >>= 7;
++count;
} while (val != 0);
return count;
}
/**
@@ -41,24 +39,22 @@ size_uleb128(unsigned long val)
* encodings refer to section "7.6 - Variable Length Data". Return
* the number of bytes written.
*/
std::size_t
write_uleb128(char* addr, unsigned long val)
{
std::size_t count = 0;
std::size_t write_uleb128(char* addr, unsigned long val) {
std::size_t count = 0;
do {
unsigned char byte = val & 0x7f;
val >>= 7;
do {
unsigned char byte = val & 0x7f;
val >>= 7;
if (val != 0)
byte |= 0x80; // mark this byte to show that more bytes will follow
if (val != 0)
byte |= 0x80; // mark this byte to show that more bytes will follow
*((unsigned char *)addr) = byte;
addr++;
count++;
} while (val != 0);
*((unsigned char*)addr) = byte;
addr++;
count++;
} while (val != 0);
return count;
return count;
}
/**
@@ -71,29 +67,25 @@ write_uleb128(char* addr, unsigned long val)
* encodings refer to section "7.6 - Variable Length Data". Return
* the number of bytes read.
*/
std::size_t
read_uleb128(char* addr, unsigned long* ret)
{
unsigned long result = 0;
int shift = 0;
std::size_t count = 0;
std::size_t read_uleb128(char* addr, unsigned long* ret) {
unsigned long result = 0;
int shift = 0;
std::size_t count = 0;
while (1)
{
unsigned char byte = *((unsigned char *)addr);
addr++;
count++;
while (1) {
unsigned char byte = *((unsigned char*)addr);
addr++;
count++;
result |= (byte & 0x7f) << shift;
shift += 7;
result |= (byte & 0x7f) << shift;
shift += 7;
if (!(byte & 0x80))
break;
}
if (!(byte & 0x80)) break;
}
*ret = result;
*ret = result;
return count;
return count;
}
/**
@@ -106,28 +98,23 @@ read_uleb128(char* addr, unsigned long* ret)
* encodings refer to section "7.6 - Variable Length Data". Return
* false on stream error, true on success.
*/
bool
read_uleb128(raw_istream& is, unsigned long* ret)
{
unsigned long result = 0;
int shift = 0;
bool read_uleb128(raw_istream& is, unsigned long* ret) {
unsigned long result = 0;
int shift = 0;
while (1)
{
unsigned char byte;
if (!is.read((char*)&byte, 1))
return false;
while (1) {
unsigned char byte;
if (!is.read((char*)&byte, 1)) return false;
result |= (byte & 0x7f) << shift;
shift += 7;
result |= (byte & 0x7f) << shift;
shift += 7;
if (!(byte & 0x80))
break;
}
if (!(byte & 0x80)) break;
}
*ret = result;
*ret = result;
return true;
return true;
}
} // namespace NtImpl
} // namespace ntimpl

View File

@@ -10,7 +10,7 @@
#include <cstddef>
namespace NtImpl {
namespace ntimpl {
class raw_istream;
@@ -19,6 +19,6 @@ std::size_t write_uleb128(char* addr, unsigned long val);
std::size_t read_uleb128(char* addr, unsigned long* ret);
bool read_uleb128(raw_istream& is, unsigned long* ret);
} // namespace NtImpl
} // namespace ntimpl
#endif /* NT_LEB128_H_ */
#endif // NT_LEB128_H_

View File

@@ -14,191 +14,156 @@
#include "nt_internal.h"
#include "nt_leb128.h"
using namespace NtImpl;
using namespace ntimpl;
void
MessageHandler::anchor()
{
}
void MessageHandler::anchor() {}
MessageReader::MessageReader(MessageHandler& handler,
raw_istream& is,
MessageReader::MessageReader(MessageHandler& handler, raw_istream& is,
unsigned int proto_rev)
: WireDecoder(is, proto_rev)
, m_handler(handler)
{
}
: WireDecoder(is, proto_rev), m_handler(handler) {}
MessageReader::~MessageReader()
{
}
MessageReader::~MessageReader() {}
bool
MessageReader::Run()
{
unsigned int msg_type;
if (!Read8(&msg_type)) return false;
switch (msg_type)
{
bool MessageReader::Run() {
unsigned int msg_type;
if (!Read8(&msg_type)) return false;
switch (msg_type) {
case NT_MSG_KEEP_ALIVE:
m_handler.GotKeepAlive();
break;
case NT_MSG_CLIENT_HELLO:
{
unsigned int proto_rev;
if (!Read16(&proto_rev)) return false;
NT_String self_id;
NT_InitString(&self_id);
// This intentionally uses the provided proto_rev instead of
// m_proto_rev.
if (proto_rev >= 0x0300u)
{
if (!ReadString(&self_id)) return false;
}
m_handler.GotClientHello(proto_rev, self_id);
break;
m_handler.GotKeepAlive();
break;
case NT_MSG_CLIENT_HELLO: {
unsigned int proto_rev;
if (!Read16(&proto_rev)) return false;
NT_String self_id;
NT_InitString(&self_id);
// This intentionally uses the provided proto_rev instead of
// m_proto_rev.
if (proto_rev >= 0x0300u) {
if (!ReadString(&self_id)) return false;
}
m_handler.GotClientHello(proto_rev, self_id);
break;
}
case NT_MSG_PROTO_UNSUP:
{
unsigned int proto_rev;
if (!Read16(&proto_rev)) return false;
m_handler.GotProtoUnsup(proto_rev);
break;
case NT_MSG_PROTO_UNSUP: {
unsigned int proto_rev;
if (!Read16(&proto_rev)) return false;
m_handler.GotProtoUnsup(proto_rev);
break;
}
case NT_MSG_SERVER_HELLO_DONE:
if (m_proto_rev < 0x0300u)
{
m_error = "received SERVER_HELLO_DONE in protocol < 3.0";
return false;
}
m_handler.GotServerHelloDone();
break;
if (m_proto_rev < 0x0300u) {
m_error = "received SERVER_HELLO_DONE in protocol < 3.0";
return false;
}
m_handler.GotServerHelloDone();
break;
case NT_MSG_CLIENT_HELLO_DONE:
if (m_proto_rev < 0x0300u)
{
m_error = "received CLIENT_HELLO_DONE in protocol < 3.0";
return false;
}
m_handler.GotClientHelloDone();
break;
case NT_MSG_ENTRY_ASSIGN:
{
NT_String name;
if (!ReadString(&name)) return false;
NT_Type type;
unsigned int id, seq_num;
unsigned int flags = 0;
NT_Value value;
if (!ReadType(&type) ||
!Read16(&id) ||
!Read16(&seq_num) ||
(m_proto_rev >= 0x0300u && !Read8(&flags)) ||
!ReadValue(type, &value))
{
NT_DisposeString(&name);
return false;
}
m_handler.GotEntryAssign(name, id, seq_num, value, flags);
break;
if (m_proto_rev < 0x0300u) {
m_error = "received CLIENT_HELLO_DONE in protocol < 3.0";
return false;
}
m_handler.GotClientHelloDone();
break;
case NT_MSG_ENTRY_ASSIGN: {
NT_String name;
if (!ReadString(&name)) return false;
NT_Type type;
unsigned int id, seq_num;
unsigned int flags = 0;
NT_Value value;
if (!ReadType(&type) || !Read16(&id) || !Read16(&seq_num) ||
(m_proto_rev >= 0x0300u && !Read8(&flags)) ||
!ReadValue(type, &value)) {
NT_DisposeString(&name);
return false;
}
m_handler.GotEntryAssign(name, id, seq_num, value, flags);
break;
}
case NT_MSG_ENTRY_UPDATE:
{
unsigned int id, seq_num;
NT_Value value;
if (!Read16(&id)) return false;
if (!Read16(&seq_num)) return false;
NT_Type type;
if (m_proto_rev >= 0x0300u)
{
unsigned int itype;
if (!Read8(&itype)) return false;
type = static_cast<NT_Type>(itype);
}
else
type = m_handler.GetEntryType(id);
if (!ReadValue(type, &value)) return false;
m_handler.GotEntryUpdate(id, seq_num, value);
break;
case NT_MSG_ENTRY_UPDATE: {
unsigned int id, seq_num;
NT_Value value;
if (!Read16(&id)) return false;
if (!Read16(&seq_num)) return false;
NT_Type type;
if (m_proto_rev >= 0x0300u) {
unsigned int itype;
if (!Read8(&itype)) return false;
type = static_cast<NT_Type>(itype);
} else
type = m_handler.GetEntryType(id);
if (!ReadValue(type, &value)) return false;
m_handler.GotEntryUpdate(id, seq_num, value);
break;
}
case NT_MSG_FLAGS_UPDATE:
{
if (m_proto_rev < 0x0300u)
{
m_error = "received FLAGS_UPDATE in protocol < 3.0";
return false;
}
unsigned int id, flags;
if (!Read16(&id)) return false;
if (!Read8(&flags)) return false;
m_handler.GotFlagsUpdate(id, flags);
break;
case NT_MSG_FLAGS_UPDATE: {
if (m_proto_rev < 0x0300u) {
m_error = "received FLAGS_UPDATE in protocol < 3.0";
return false;
}
unsigned int id, flags;
if (!Read16(&id)) return false;
if (!Read8(&flags)) return false;
m_handler.GotFlagsUpdate(id, flags);
break;
}
case NT_MSG_ENTRY_DELETE:
{
if (m_proto_rev < 0x0300u)
{
m_error = "received ENTRY_DELETE in protocol < 3.0";
return false;
}
unsigned int id;
if (!Read16(&id)) return false;
m_handler.GotEntryDelete(id);
break;
case NT_MSG_ENTRY_DELETE: {
if (m_proto_rev < 0x0300u) {
m_error = "received ENTRY_DELETE in protocol < 3.0";
return false;
}
unsigned int id;
if (!Read16(&id)) return false;
m_handler.GotEntryDelete(id);
break;
}
case NT_MSG_CLEAR_ENTRIES:
{
if (m_proto_rev < 0x0300u)
{
m_error = "received CLEAR_ENTRIES in protocol < 3.0";
return false;
}
unsigned long magic;
if (!Read32(&magic)) return false;
if (magic != NT_CLEAR_ALL_MAGIC)
{
m_error = "received incorrect CLEAR_ENTRIES magic value, ignoring";
return true;
}
m_handler.GotClearEntries();
break;
case NT_MSG_CLEAR_ENTRIES: {
if (m_proto_rev < 0x0300u) {
m_error = "received CLEAR_ENTRIES in protocol < 3.0";
return false;
}
unsigned long magic;
if (!Read32(&magic)) return false;
if (magic != NT_CLEAR_ALL_MAGIC) {
m_error = "received incorrect CLEAR_ENTRIES magic value, ignoring";
return true;
}
m_handler.GotClearEntries();
break;
}
case NT_MSG_EXECUTE_RPC:
{
if (m_proto_rev < 0x0300u)
{
m_error = "received EXECUTE_RPC in protocol < 3.0";
return false;
}
unsigned int id, uid;
if (!Read16(&id)) return false;
if (!Read16(&uid)) return false;
unsigned long size;
if (!ReadULEB128(&size)) return false;
char *params;
if (!Read(&params, size)) return false;
m_handler.GotExecuteRpc(id, uid, params, size);
break;
case NT_MSG_EXECUTE_RPC: {
if (m_proto_rev < 0x0300u) {
m_error = "received EXECUTE_RPC in protocol < 3.0";
return false;
}
unsigned int id, uid;
if (!Read16(&id)) return false;
if (!Read16(&uid)) return false;
unsigned long size;
if (!ReadULEB128(&size)) return false;
char* params;
if (!Read(&params, size)) return false;
m_handler.GotExecuteRpc(id, uid, params, size);
break;
}
case NT_MSG_RPC_RESPONSE:
{
if (m_proto_rev < 0x0300u)
{
m_error = "received RPC_RESPONSE in protocol < 3.0";
return false;
}
unsigned int id, uid;
if (!Read16(&id)) return false;
if (!Read16(&uid)) return false;
unsigned long size;
if (!ReadULEB128(&size)) return false;
char *results;
if (!Read(&results, size)) return false;
m_handler.GotRpcResponse(id, uid, results, size);
break;
case NT_MSG_RPC_RESPONSE: {
if (m_proto_rev < 0x0300u) {
m_error = "received RPC_RESPONSE in protocol < 3.0";
return false;
}
unsigned int id, uid;
if (!Read16(&id)) return false;
if (!Read16(&uid)) return false;
unsigned long size;
if (!ReadULEB128(&size)) return false;
char* results;
if (!Read(&results, size)) return false;
m_handler.GotRpcResponse(id, uid, results, size);
break;
}
default:
m_error = "unrecognized message type";
return false;
}
return true;
m_error = "unrecognized message type";
return false;
}
return true;
}

View File

@@ -10,84 +10,65 @@
#include "nt_wiredecoder.h"
namespace NtImpl {
namespace ntimpl {
class MessageHandler
{
void anchor();
class MessageHandler {
void anchor();
public:
// Needed for protocol rev 2.0 ENTRY_UPDATE messages.
virtual NT_Type GetEntryType(unsigned int id) = 0;
public:
// Needed for protocol rev 2.0 ENTRY_UPDATE messages.
virtual NT_Type GetEntryType(unsigned int id) = 0;
// All of these functions are expected to take ownership of passed
// strings/values.
virtual ~MessageHandler() {}
virtual void GotKeepAlive() = 0;
virtual void GotClientHello(unsigned int proto_rev,
NT_String& self_id) = 0;
virtual void GotProtoUnsup(unsigned int proto_rev) = 0;
virtual void GotServerHelloDone() = 0;
virtual void GotServerHello(unsigned int flags,
NT_String& self_id) = 0;
virtual void GotClientHelloDone() = 0;
virtual void GotEntryAssign(NT_String& name,
unsigned int id,
unsigned int seq_num,
NT_Value& value,
unsigned int flags) = 0;
virtual void GotEntryUpdate(unsigned int id,
unsigned int seq_num,
NT_Value& value) = 0;
virtual void GotFlagsUpdate(unsigned int id, unsigned int flags) = 0;
virtual void GotEntryDelete(unsigned int id) = 0;
virtual void GotClearEntries() = 0;
virtual void GotExecuteRpc(unsigned int id,
unsigned int uid,
const char* params,
std::size_t params_len) = 0;
virtual void GotRpcResponse(unsigned int id,
unsigned int uid,
const char* results,
std::size_t results_len) = 0;
// All of these functions are expected to take ownership of passed
// strings/values.
virtual ~MessageHandler() {}
virtual void GotKeepAlive() = 0;
virtual void GotClientHello(unsigned int proto_rev, NT_String& self_id) = 0;
virtual void GotProtoUnsup(unsigned int proto_rev) = 0;
virtual void GotServerHelloDone() = 0;
virtual void GotServerHello(unsigned int flags, NT_String& self_id) = 0;
virtual void GotClientHelloDone() = 0;
virtual void GotEntryAssign(NT_String& name, unsigned int id,
unsigned int seq_num, NT_Value& value,
unsigned int flags) = 0;
virtual void GotEntryUpdate(unsigned int id, unsigned int seq_num,
NT_Value& value) = 0;
virtual void GotFlagsUpdate(unsigned int id, unsigned int flags) = 0;
virtual void GotEntryDelete(unsigned int id) = 0;
virtual void GotClearEntries() = 0;
virtual void GotExecuteRpc(unsigned int id, unsigned int uid,
const char* params, std::size_t params_len) = 0;
virtual void GotRpcResponse(unsigned int id, unsigned int uid,
const char* results, std::size_t results_len) = 0;
MessageHandler() = default;
MessageHandler(const MessageHandler&) = delete;
MessageHandler& operator= (const MessageHandler&) = delete;
MessageHandler() = default;
MessageHandler(const MessageHandler&) = delete;
MessageHandler& operator=(const MessageHandler&) = delete;
};
class MessageReader : private WireDecoder
{
public:
explicit MessageReader(MessageHandler &handler,
raw_istream& is,
unsigned int proto_rev);
~MessageReader();
class MessageReader : private WireDecoder {
public:
explicit MessageReader(MessageHandler& handler, raw_istream& is,
unsigned int proto_rev);
~MessageReader();
void SetProtocolRev(unsigned int proto_rev)
{
WireDecoder::SetProtocolRev(proto_rev);
}
void SetProtocolRev(unsigned int proto_rev) {
WireDecoder::SetProtocolRev(proto_rev);
}
bool Run();
bool Run();
void Reset()
{
WireDecoder::Reset();
}
void Reset() { WireDecoder::Reset(); }
const char* GetError() const
{
return WireDecoder::GetError();
}
const char* GetError() const { return WireDecoder::GetError(); }
MessageReader(const MessageReader&) = delete;
MessageReader& operator= (const MessageReader&) = delete;
MessageReader(const MessageReader&) = delete;
MessageReader& operator=(const MessageReader&) = delete;
private:
MessageHandler& m_handler;
private:
MessageHandler& m_handler;
};
} // namespace NtImpl
} // namespace ntimpl
#endif /* NT_MESSAGEREADER_H_ */
#endif // NT_MESSAGEREADER_H_

View File

@@ -9,155 +9,107 @@
#include "nt_internal.h"
using namespace NtImpl;
using namespace ntimpl;
MessageWriter::~MessageWriter()
{
MessageWriter::~MessageWriter() {}
void MessageWriter::WriteKeepAlive() { Write8(NT_MSG_KEEP_ALIVE); }
void MessageWriter::WriteClientHello(const NT_String& self_id) {
Write8(NT_MSG_CLIENT_HELLO);
Write16(m_proto_rev);
if (m_proto_rev < 0x0300u) return;
WriteString(self_id);
}
void
MessageWriter::WriteKeepAlive()
{
Write8(NT_MSG_KEEP_ALIVE);
void MessageWriter::WriteProtoUnsup() {
Write8(NT_MSG_PROTO_UNSUP);
Write16(m_proto_rev);
}
void
MessageWriter::WriteClientHello(const NT_String& self_id)
{
Write8(NT_MSG_CLIENT_HELLO);
Write16(m_proto_rev);
if (m_proto_rev < 0x0300u)
return;
WriteString(self_id);
void MessageWriter::WriteServerHelloDone() { Write8(NT_MSG_SERVER_HELLO_DONE); }
void MessageWriter::WriteServerHello(unsigned int flags,
const NT_String& self_id) {
if (m_proto_rev < 0x0300u) return; // new message in version 3.0
Write8(NT_MSG_SERVER_HELLO);
Write8(flags);
WriteString(self_id);
}
void
MessageWriter::WriteProtoUnsup()
{
Write8(NT_MSG_PROTO_UNSUP);
Write16(m_proto_rev);
void MessageWriter::WriteClientHelloDone() {
if (m_proto_rev < 0x0300u) return; // new message in version 3.0
Write8(NT_MSG_CLIENT_HELLO_DONE);
}
void
MessageWriter::WriteServerHelloDone()
{
Write8(NT_MSG_SERVER_HELLO_DONE);
void MessageWriter::WriteEntryAssign(const NT_String& name, unsigned int id,
unsigned int seq_num,
const NT_Value& value,
unsigned int flags) {
Write8(NT_MSG_ENTRY_ASSIGN);
WriteString(name);
WriteType(value.type);
Write16(id);
Write16(seq_num);
if (m_proto_rev >= 0x0300u) Write8(flags);
WriteValue(value);
}
void
MessageWriter::WriteServerHello(unsigned int flags, const NT_String& self_id)
{
if (m_proto_rev < 0x0300u)
return; // new message in version 3.0
Write8(NT_MSG_SERVER_HELLO);
Write8(flags);
WriteString(self_id);
void MessageWriter::WriteEntryUpdate(unsigned int id, unsigned int seq_num,
const NT_Value& value) {
Write8(NT_MSG_ENTRY_UPDATE);
Write16(id);
Write16(seq_num);
if (m_proto_rev >= 0x0300u) Write8(value.type);
WriteValue(value);
}
void
MessageWriter::WriteClientHelloDone()
{
if (m_proto_rev < 0x0300u)
return; // new message in version 3.0
Write8(NT_MSG_CLIENT_HELLO_DONE);
void MessageWriter::WriteFlagsUpdate(unsigned int id, unsigned int flags) {
if (m_proto_rev < 0x0300u) return; // new message in version 3.0
Write8(NT_MSG_FLAGS_UPDATE);
Write16(id);
Write8(flags);
}
void
MessageWriter::WriteEntryAssign(const NT_String& name,
unsigned int id,
unsigned int seq_num,
const NT_Value& value,
unsigned int flags)
{
Write8(NT_MSG_ENTRY_ASSIGN);
WriteString(name);
WriteType(value.type);
Write16(id);
Write16(seq_num);
if (m_proto_rev >= 0x0300u)
Write8(flags);
WriteValue(value);
void MessageWriter::WriteEntryDelete(unsigned int id) {
if (m_proto_rev < 0x0300u) return; // new message in version 3.0
Write8(NT_MSG_ENTRY_DELETE);
Write16(id);
}
void
MessageWriter::WriteEntryUpdate(unsigned int id,
unsigned int seq_num,
const NT_Value& value)
{
Write8(NT_MSG_ENTRY_UPDATE);
Write16(id);
Write16(seq_num);
if (m_proto_rev >= 0x0300u)
Write8(value.type);
WriteValue(value);
void MessageWriter::WriteClearEntries() {
if (m_proto_rev < 0x0300u) return; // new message in version 3.0
Write8(NT_MSG_CLEAR_ENTRIES);
Write32(NT_CLEAR_ALL_MAGIC);
}
void
MessageWriter::WriteFlagsUpdate(unsigned int id, unsigned int flags)
{
if (m_proto_rev < 0x0300u)
return; // new message in version 3.0
Write8(NT_MSG_FLAGS_UPDATE);
Write16(id);
Write8(flags);
void MessageWriter::WriteExecuteRpc(unsigned int id, unsigned int uid,
const NT_Value* params_start,
const NT_Value* params_end) {
WriteRpc(NT_MSG_EXECUTE_RPC, id, uid, params_start, params_end);
}
void
MessageWriter::WriteEntryDelete(unsigned int id)
{
if (m_proto_rev < 0x0300u)
return; // new message in version 3.0
Write8(NT_MSG_ENTRY_DELETE);
Write16(id);
void MessageWriter::WriteRpcResponse(unsigned int id, unsigned int uid,
const NT_Value* results_start,
const NT_Value* results_end) {
WriteRpc(NT_MSG_RPC_RESPONSE, id, uid, results_start, results_end);
}
void
MessageWriter::WriteClearEntries()
{
if (m_proto_rev < 0x0300u)
return; // new message in version 3.0
void MessageWriter::WriteRpc(unsigned int msg_type, unsigned int id,
unsigned int uid, const NT_Value* values_start,
const NT_Value* values_end) {
if (m_proto_rev < 0x0300u) return; // new message in version 3.0
Write8(NT_MSG_CLEAR_ENTRIES);
Write32(NT_CLEAR_ALL_MAGIC);
}
void
MessageWriter::WriteExecuteRpc(unsigned int id,
unsigned int uid,
const NT_Value* params_start,
const NT_Value* params_end)
{
WriteRpc(NT_MSG_EXECUTE_RPC, id, uid, params_start, params_end);
}
void
MessageWriter::WriteRpcResponse(unsigned int id,
unsigned int uid,
const NT_Value* results_start,
const NT_Value* results_end)
{
WriteRpc(NT_MSG_RPC_RESPONSE, id, uid, results_start, results_end);
}
void
MessageWriter::WriteRpc(unsigned int msg_type,
unsigned int id,
unsigned int uid,
const NT_Value* values_start,
const NT_Value* values_end)
{
if (m_proto_rev < 0x0300u)
return; // new message in version 3.0
Write8(msg_type);
Write16(id);
Write16(uid);
unsigned long len = 0;
for (const NT_Value* value = values_start; value != values_end; ++value)
len += GetValueSize(*value);
WriteULEB128(len);
for (const NT_Value* value = values_start; value != values_end; ++value)
WriteValue(*value);
Write8(msg_type);
Write16(id);
Write16(uid);
unsigned long len = 0;
for (const NT_Value* value = values_start; value != values_end; ++value)
len += GetValueSize(*value);
WriteULEB128(len);
for (const NT_Value* value = values_start; value != values_end; ++value)
WriteValue(*value);
}

View File

@@ -10,76 +10,54 @@
#include "nt_wireencoder.h"
namespace NtImpl {
namespace ntimpl {
class MessageWriter : private WireEncoder
{
public:
explicit MessageWriter(unsigned int proto_rev) : WireEncoder(proto_rev) {}
~MessageWriter();
class MessageWriter : private WireEncoder {
public:
explicit MessageWriter(unsigned int proto_rev) : WireEncoder(proto_rev) {}
~MessageWriter();
void SetProtocolRev(unsigned int proto_rev)
{
WireEncoder::SetProtocolRev(proto_rev);
}
void SetProtocolRev(unsigned int proto_rev) {
WireEncoder::SetProtocolRev(proto_rev);
}
void Reset()
{
WireEncoder::Reset();
}
void Reset() { WireEncoder::Reset(); }
const char* GetError() const
{
return WireEncoder::GetError();
}
const char* GetError() const { return WireEncoder::GetError(); }
const char* GetData() const
{
return WireEncoder::GetData();
}
const char* GetData() const { return WireEncoder::GetData(); }
std::size_t GetSize() const
{
return WireEncoder::GetSize();
}
std::size_t GetSize() const { return WireEncoder::GetSize(); }
void WriteKeepAlive();
void WriteClientHello(const NT_String& self_id);
void WriteProtoUnsup();
void WriteServerHelloDone();
void WriteServerHello(unsigned int flags, const NT_String& self_id);
void WriteClientHelloDone();
void WriteEntryAssign(const NT_String& name,
unsigned int id,
unsigned int seq_num,
const NT_Value& value,
unsigned int flags);
void WriteEntryUpdate(unsigned int id,
unsigned int seq_num,
const NT_Value& value);
void WriteFlagsUpdate(unsigned int id, unsigned int flags);
void WriteEntryDelete(unsigned int id);
void WriteClearEntries();
void WriteExecuteRpc(unsigned int id,
unsigned int uid,
const NT_Value* params_start,
const NT_Value* params_end);
void WriteRpcResponse(unsigned int id,
unsigned int uid,
const NT_Value* results_start,
const NT_Value* results_end);
void WriteKeepAlive();
void WriteClientHello(const NT_String& self_id);
void WriteProtoUnsup();
void WriteServerHelloDone();
void WriteServerHello(unsigned int flags, const NT_String& self_id);
void WriteClientHelloDone();
void WriteEntryAssign(const NT_String& name, unsigned int id,
unsigned int seq_num, const NT_Value& value,
unsigned int flags);
void WriteEntryUpdate(unsigned int id, unsigned int seq_num,
const NT_Value& value);
void WriteFlagsUpdate(unsigned int id, unsigned int flags);
void WriteEntryDelete(unsigned int id);
void WriteClearEntries();
void WriteExecuteRpc(unsigned int id, unsigned int uid,
const NT_Value* params_start,
const NT_Value* params_end);
void WriteRpcResponse(unsigned int id, unsigned int uid,
const NT_Value* results_start,
const NT_Value* results_end);
MessageWriter(const MessageWriter&) = delete;
MessageWriter& operator= (const MessageWriter&) = delete;
MessageWriter(const MessageWriter&) = delete;
MessageWriter& operator=(const MessageWriter&) = delete;
private:
void WriteRpc(unsigned int msg_type,
unsigned int id,
unsigned int uid,
const NT_Value* values_start,
const NT_Value* values_end);
private:
void WriteRpc(unsigned int msg_type, unsigned int id, unsigned int uid,
const NT_Value* values_start, const NT_Value* values_end);
};
} // namespace NtImpl
} // namespace ntimpl
#endif /* NT_MESSAGEWRITER_H_ */
#endif // NT_MESSAGEWRITER_H_

View File

@@ -13,142 +13,143 @@
#include "nt_base64.h"
#include "nt_storage.h"
using namespace NtImpl;
using namespace ntimpl;
static void
write_string(FILE* f, llvm::StringRef str)
{
fputc('"', f);
for (unsigned int i = 0, e = str.size(); i != e; ++i)
{
unsigned char c = str[i];
static void write_string(FILE* f, llvm::StringRef str) {
fputc('"', f);
for (unsigned int i = 0, e = str.size(); i != e; ++i) {
unsigned char c = str[i];
switch (c)
{
case '\\': fputs("\\\\", f); break;
case '\t': fputs("\\t", f); break;
case '\n': fputs("\\n", f); break;
case '"': fputs("\\\"", f); break;
default:
if (std::isprint(c))
{
fputc(c, f);
break;
}
// Write out the escaped representation.
fputs("\\x", f);
fputc(llvm::hexdigit((c >> 4 & 0xF)), f);
fputc(llvm::hexdigit((c >> 0) & 0xF), f);
switch (c) {
case '\\':
fputs("\\\\", f);
break;
case '\t':
fputs("\\t", f);
break;
case '\n':
fputs("\\n", f);
break;
case '"':
fputs("\\\"", f);
break;
default:
if (std::isprint(c)) {
fputc(c, f);
break;
}
// Write out the escaped representation.
fputs("\\x", f);
fputc(llvm::hexdigit((c >> 4 & 0xF)), f);
fputc(llvm::hexdigit((c >> 0) & 0xF), f);
}
fputc('"', f);
}
fputc('"', f);
}
const char*
NT_SavePersistent(const char* filename)
{
FILE* f = fopen(filename, "wt");
if (!f)
return "could not open file";
const char* NT_SavePersistent(const char* filename) {
FILE* f = fopen(filename, "wt");
if (!f) return "could not open file";
fputs("[NetworkTables Storage 3.0]\n", f);
fputs("[NetworkTables Storage 3.0]\n", f);
Storage& storage = Storage::GetInstance();
for (Storage::EntriesMap::const_iterator i = storage.entries.begin(),
end = storage.entries.end(); i != end; ++i)
{
const StorageEntry& entry = i->getValue();
// only write persistent-flagged values
if ((entry.flags & NT_PERSISTENT) == 0)
continue;
Storage& storage = Storage::GetInstance();
for (Storage::EntriesMap::const_iterator i = storage.entries.begin(),
end = storage.entries.end();
i != end; ++i) {
const StorageEntry& entry = i->getValue();
// only write persistent-flagged values
if ((entry.flags & NT_PERSISTENT) == 0) continue;
// type
const NT_Value& v = entry.value;
switch (v.type)
{
case NT_BOOLEAN: fputs("boolean ", f); break;
case NT_DOUBLE: fputs("double ", f); break;
case NT_STRING: fputs("string ", f); break;
case NT_RAW: fputs("raw ", f); break;
case NT_BOOLEAN_ARRAY: fputs("array boolean ", f); break;
case NT_DOUBLE_ARRAY: fputs("array double ", f); break;
case NT_STRING_ARRAY: fputs("array string ", f); break;
default:
continue;
}
// name
write_string(f, i->getKey());
// =
fputc('=', f);
// value
switch (v.type)
{
case NT_BOOLEAN:
fputs(v.data.v_boolean ? "true" : "false", f);
break;
case NT_DOUBLE:
fprintf(f, "%g", v.data.v_double);
break;
case NT_STRING:
write_string(f, make_StringRef(v.data.v_string));
break;
case NT_RAW:
{
char* buf = new char[base64encode_len(v.data.v_raw.len)];
base64encode(buf,
reinterpret_cast<const unsigned char*>(v.data.v_raw.str),
v.data.v_raw.len);
fputs(buf, f);
delete[] buf;
break;
}
case NT_BOOLEAN_ARRAY:
for (size_t i=0; i<v.data.arr_boolean.size; ++i)
{
fputs(v.data.arr_boolean.arr[i] ? "true" : "false", f);
if (i != (v.data.arr_boolean.size - 1))
fputc(',', f);
}
break;
case NT_DOUBLE_ARRAY:
for (size_t i=0; i<v.data.arr_double.size; ++i)
{
fprintf(f, "%g", v.data.arr_double.arr[i]);
if (i != (v.data.arr_double.size - 1))
fputc(',', f);
}
break;
case NT_STRING_ARRAY:
for (size_t i=0; i<v.data.arr_double.size; ++i)
{
write_string(f, make_StringRef(v.data.arr_string.arr[i]));
if (i != (v.data.arr_double.size - 1))
fputc(',', f);
}
break;
default:
break;
}
// eol
fputc('\n', f);
// type
const NT_Value& v = entry.value;
switch (v.type) {
case NT_BOOLEAN:
fputs("boolean ", f);
break;
case NT_DOUBLE:
fputs("double ", f);
break;
case NT_STRING:
fputs("string ", f);
break;
case NT_RAW:
fputs("raw ", f);
break;
case NT_BOOLEAN_ARRAY:
fputs("array boolean ", f);
break;
case NT_DOUBLE_ARRAY:
fputs("array double ", f);
break;
case NT_STRING_ARRAY:
fputs("array string ", f);
break;
default:
continue;
}
fclose(f);
return 0;
// name
write_string(f, i->getKey());
// =
fputc('=', f);
// value
switch (v.type) {
case NT_BOOLEAN:
fputs(v.data.v_boolean ? "true" : "false", f);
break;
case NT_DOUBLE:
fprintf(f, "%g", v.data.v_double);
break;
case NT_STRING:
write_string(f, make_StringRef(v.data.v_string));
break;
case NT_RAW: {
char* buf = new char[base64encode_len(v.data.v_raw.len)];
base64encode(buf,
reinterpret_cast<const unsigned char*>(v.data.v_raw.str),
v.data.v_raw.len);
fputs(buf, f);
delete[] buf;
break;
}
case NT_BOOLEAN_ARRAY:
for (size_t i = 0; i < v.data.arr_boolean.size; ++i) {
fputs(v.data.arr_boolean.arr[i] ? "true" : "false", f);
if (i != (v.data.arr_boolean.size - 1)) fputc(',', f);
}
break;
case NT_DOUBLE_ARRAY:
for (size_t i = 0; i < v.data.arr_double.size; ++i) {
fprintf(f, "%g", v.data.arr_double.arr[i]);
if (i != (v.data.arr_double.size - 1)) fputc(',', f);
}
break;
case NT_STRING_ARRAY:
for (size_t i = 0; i < v.data.arr_double.size; ++i) {
write_string(f, make_StringRef(v.data.arr_string.arr[i]));
if (i != (v.data.arr_double.size - 1)) fputc(',', f);
}
break;
default:
break;
}
// eol
fputc('\n', f);
}
fclose(f);
return 0;
}
const char*
NT_LoadPersistent(const char* filename)
{
FILE* f = fopen(filename, "rt");
if (!f)
return "could not open file";
const char* NT_LoadPersistent(const char* filename) {
FILE* f = fopen(filename, "rt");
if (!f) return "could not open file";
fclose(f);
return 0;
fclose(f);
return 0;
}

View File

@@ -9,20 +9,14 @@
#include <cstring>
using namespace NtImpl;
using namespace ntimpl;
void
raw_istream::anchor()
{
}
void raw_istream::anchor() {}
bool
raw_mem_istream::read(void* data, std::size_t len)
{
if (len > m_left)
return false;
std::memcpy(data, m_cur, len);
m_cur += len;
m_left -= len;
return true;
bool raw_mem_istream::read(void* data, std::size_t len) {
if (len > m_left) return false;
std::memcpy(data, m_cur, len);
m_cur += len;
m_left -= len;
return true;
}

View File

@@ -10,35 +10,33 @@
#include <cstddef>
namespace NtImpl {
namespace ntimpl {
class raw_istream
{
void anchor();
public:
raw_istream() {}
virtual ~raw_istream() {}
virtual bool read(void* data, std::size_t len) = 0;
virtual void close() = 0;
class raw_istream {
void anchor();
raw_istream(const raw_istream&) = delete;
raw_istream& operator= (const raw_istream&) = delete;
public:
raw_istream() {}
virtual ~raw_istream() {}
virtual bool read(void* data, std::size_t len) = 0;
virtual void close() = 0;
raw_istream(const raw_istream&) = delete;
raw_istream& operator=(const raw_istream&) = delete;
};
class raw_mem_istream : public raw_istream
{
public:
raw_mem_istream(const char* mem, std::size_t len)
: m_cur(mem), m_left(len)
{}
virtual ~raw_mem_istream() {}
virtual bool read(void* data, std::size_t len);
virtual void close() {}
private:
const char* m_cur;
std::size_t m_left;
class raw_mem_istream : public raw_istream {
public:
raw_mem_istream(const char* mem, std::size_t len) : m_cur(mem), m_left(len) {}
virtual ~raw_mem_istream() {}
virtual bool read(void* data, std::size_t len);
virtual void close() {}
private:
const char* m_cur;
std::size_t m_left;
};
} // namespace NtImpl
} // namespace ntimpl
#endif /* NT_RAW_ISTREAM_H_ */
#endif // NT_RAW_ISTREAM_H_

View File

@@ -7,26 +7,24 @@
#include "nt_seqnum.h"
namespace NtImpl {
namespace ntimpl {
bool operator< (const SequenceNumber& lhs, const SequenceNumber& rhs)
{
if (lhs.m_val < rhs.m_val)
return (rhs.m_val - lhs.m_val) < (1u<<15);
else if (lhs.m_val > rhs.m_val)
return (lhs.m_val - rhs.m_val) > (1u<<15);
else
return false;
bool operator<(const SequenceNumber& lhs, const SequenceNumber& rhs) {
if (lhs.m_val < rhs.m_val)
return (rhs.m_val - lhs.m_val) < (1u << 15);
else if (lhs.m_val > rhs.m_val)
return (lhs.m_val - rhs.m_val) > (1u << 15);
else
return false;
}
bool operator> (const SequenceNumber& lhs, const SequenceNumber& rhs)
{
if (lhs.m_val < rhs.m_val)
return (rhs.m_val - lhs.m_val) > (1u<<15);
else if (lhs.m_val > rhs.m_val)
return (lhs.m_val - rhs.m_val) < (1u<<15);
else
return false;
bool operator>(const SequenceNumber& lhs, const SequenceNumber& rhs) {
if (lhs.m_val < rhs.m_val)
return (rhs.m_val - lhs.m_val) > (1u << 15);
else if (lhs.m_val > rhs.m_val)
return (lhs.m_val - rhs.m_val) < (1u << 15);
else
return false;
}
} // namespace NtImpl
} // namespace ntimpl

View File

@@ -8,67 +8,54 @@
#ifndef NT_SEQNUM_H_
#define NT_SEQNUM_H_
namespace NtImpl {
namespace ntimpl {
class SequenceNumber
{
public:
explicit SequenceNumber(unsigned int val) : m_val(val) {}
unsigned int GetVal() const { return m_val; }
class SequenceNumber {
public:
explicit SequenceNumber(unsigned int val) : m_val(val) {}
unsigned int GetVal() const { return m_val; }
SequenceNumber& operator++()
{
++m_val;
if (m_val > 0xffff)
m_val = 0;
return *this;
}
SequenceNumber operator++(int)
{
SequenceNumber tmp(*this);
operator++();
return tmp;
}
SequenceNumber& operator++() {
++m_val;
if (m_val > 0xffff) m_val = 0;
return *this;
}
SequenceNumber operator++(int) {
SequenceNumber tmp(*this);
operator++();
return tmp;
}
friend bool operator< (const SequenceNumber& lhs,
const SequenceNumber& rhs);
friend bool operator> (const SequenceNumber& lhs,
const SequenceNumber& rhs);
friend bool operator<= (const SequenceNumber& lhs,
const SequenceNumber& rhs);
friend bool operator>= (const SequenceNumber& lhs,
const SequenceNumber& rhs);
friend bool operator== (const SequenceNumber& lhs,
const SequenceNumber& rhs);
friend bool operator!= (const SequenceNumber& lhs,
const SequenceNumber& rhs);
private:
unsigned int m_val;
friend bool operator<(const SequenceNumber& lhs, const SequenceNumber& rhs);
friend bool operator>(const SequenceNumber& lhs, const SequenceNumber& rhs);
friend bool operator<=(const SequenceNumber& lhs, const SequenceNumber& rhs);
friend bool operator>=(const SequenceNumber& lhs, const SequenceNumber& rhs);
friend bool operator==(const SequenceNumber& lhs, const SequenceNumber& rhs);
friend bool operator!=(const SequenceNumber& lhs, const SequenceNumber& rhs);
private:
unsigned int m_val;
};
bool operator< (const SequenceNumber& lhs, const SequenceNumber& rhs);
bool operator> (const SequenceNumber& lhs, const SequenceNumber& rhs);
bool operator<(const SequenceNumber& lhs, const SequenceNumber& rhs);
bool operator>(const SequenceNumber& lhs, const SequenceNumber& rhs);
inline bool operator<= (const SequenceNumber& lhs, const SequenceNumber& rhs)
{
return lhs == rhs || lhs < rhs;
inline bool operator<=(const SequenceNumber& lhs, const SequenceNumber& rhs) {
return lhs == rhs || lhs < rhs;
}
inline bool operator>= (const SequenceNumber& lhs, const SequenceNumber& rhs)
{
return lhs == rhs || lhs > rhs;
inline bool operator>=(const SequenceNumber& lhs, const SequenceNumber& rhs) {
return lhs == rhs || lhs > rhs;
}
inline bool operator== (const SequenceNumber& lhs, const SequenceNumber& rhs)
{
return lhs.m_val == rhs.m_val;
inline bool operator==(const SequenceNumber& lhs, const SequenceNumber& rhs) {
return lhs.m_val == rhs.m_val;
}
inline bool operator!= (const SequenceNumber& lhs, const SequenceNumber& rhs)
{
return lhs.m_val != rhs.m_val;
inline bool operator!=(const SequenceNumber& lhs, const SequenceNumber& rhs) {
return lhs.m_val != rhs.m_val;
}
} // namespace NtImpl
} // namespace ntimpl
#endif /* NT_SEQNUM_H_ */
#endif // NT_SEQNUM_H_

View File

@@ -7,14 +7,10 @@
#include "nt_storage.h"
using namespace NtImpl;
using namespace ntimpl;
Storage* Storage::m_instance = nullptr;
Storage::Storage()
{
}
Storage::Storage() {}
Storage::~Storage()
{
}
Storage::~Storage() {}

View File

@@ -12,55 +12,46 @@
#include "llvm/StringMap.h"
namespace NtImpl {
namespace ntimpl {
inline llvm::StringRef
make_StringRef(const NT_String& str)
{
return llvm::StringRef(str.str, str.len);
inline llvm::StringRef make_StringRef(const NT_String& str) {
return llvm::StringRef(str.str, str.len);
}
class StorageEntry
{
public:
StorageEntry()
{
NT_InitValue(&value);
flags = 0;
}
~StorageEntry()
{
NT_DisposeValue(&value);
}
NT_Value value;
unsigned int flags;
class StorageEntry {
public:
StorageEntry() {
NT_InitValue(&value);
flags = 0;
}
~StorageEntry() { NT_DisposeValue(&value); }
StorageEntry(const StorageEntry&) = delete;
StorageEntry& operator= (const StorageEntry&) = delete;
NT_Value value;
unsigned int flags;
StorageEntry(const StorageEntry&) = delete;
StorageEntry& operator=(const StorageEntry&) = delete;
};
class Storage
{
public:
static Storage& GetInstance()
{
if (!m_instance)
m_instance = new Storage;
return *m_instance;
}
class Storage {
public:
static Storage& GetInstance() {
if (!m_instance) m_instance = new Storage;
return *m_instance;
}
typedef llvm::StringMap<StorageEntry> EntriesMap;
EntriesMap entries;
typedef llvm::StringMap<StorageEntry> EntriesMap;
EntriesMap entries;
private:
Storage();
~Storage();
Storage(const Storage&) = delete;
Storage& operator= (const Storage&) = delete;
private:
Storage();
~Storage();
Storage(const Storage&) = delete;
Storage& operator=(const Storage&) = delete;
static Storage* m_instance;
static Storage* m_instance;
};
} // namespace NtImpl
} // namespace ntimpl
#endif /* NT_STORAGE_H_ */
#endif // NT_STORAGE_H_

View File

@@ -10,67 +10,55 @@
#include "ntcore.h"
void
NT_DisposeValue(NT_Value *value)
{
switch (value->type)
{
void NT_DisposeValue(NT_Value *value) {
switch (value->type) {
case NT_UNASSIGNED:
case NT_BOOLEAN:
case NT_DOUBLE:
break;
break;
case NT_STRING:
case NT_RAW:
case NT_RPC:
std::free(value->data.v_string.str);
break;
std::free(value->data.v_string.str);
break;
case NT_BOOLEAN_ARRAY:
std::free(value->data.arr_boolean.arr);
break;
std::free(value->data.arr_boolean.arr);
break;
case NT_DOUBLE_ARRAY:
std::free(value->data.arr_double.arr);
break;
case NT_STRING_ARRAY:
{
for (size_t i=0; i<value->data.arr_string.size; i++)
std::free(value->data.arr_string.arr[i].str);
std::free(value->data.arr_string.arr);
break;
std::free(value->data.arr_double.arr);
break;
case NT_STRING_ARRAY: {
for (size_t i = 0; i < value->data.arr_string.size; i++)
std::free(value->data.arr_string.arr[i].str);
std::free(value->data.arr_string.arr);
break;
}
default:
assert(0 && "unknown value type");
}
value->type = NT_UNASSIGNED;
value->last_change = 0;
assert(0 && "unknown value type");
}
value->type = NT_UNASSIGNED;
value->last_change = 0;
}
void
NT_InitValue(NT_Value *value)
{
value->type = NT_UNASSIGNED;
value->last_change = 0;
void NT_InitValue(NT_Value *value) {
value->type = NT_UNASSIGNED;
value->last_change = 0;
}
void
NT_DisposeString(NT_String *str)
{
std::free(str->str);
str->str = nullptr;
str->len = 0;
void NT_DisposeString(NT_String *str) {
std::free(str->str);
str->str = nullptr;
str->len = 0;
}
void
NT_InitString(NT_String *str)
{
str->str = nullptr;
str->len = 0;
void NT_InitString(NT_String *str) {
str->str = nullptr;
str->len = 0;
}
void
NT_DisposeConnectionInfoArray(NT_ConnectionInfo *arr, size_t count)
{
unsigned int i;
for (i=0; i<count; i++)
std::free(arr[i].remote_id.str);
std::free(arr);
void NT_DisposeConnectionInfoArray(NT_ConnectionInfo *arr, size_t count) {
unsigned int i;
for (i = 0; i < count; i++)
std::free(arr[i].remote_id.str);
std::free(arr);
}

View File

@@ -12,56 +12,45 @@
#include "ntcore.h"
bool
operator== (const NT_Value& lhs, const NT_Value& rhs)
{
if (lhs.type != rhs.type)
return false;
switch (lhs.type)
{
bool operator==(const NT_Value& lhs, const NT_Value& rhs) {
if (lhs.type != rhs.type) return false;
switch (lhs.type) {
case NT_UNASSIGNED:
return true; // XXX: is this better being false instead?
return true; // XXX: is this better being false instead?
case NT_BOOLEAN:
return lhs.data.v_boolean == rhs.data.v_boolean;
return lhs.data.v_boolean == rhs.data.v_boolean;
case NT_DOUBLE:
return lhs.data.v_double == rhs.data.v_double;
return lhs.data.v_double == rhs.data.v_double;
case NT_STRING:
case NT_RAW:
case NT_RPC:
if (lhs.data.v_string.len != rhs.data.v_string.len)
return false;
return std::memcmp(lhs.data.v_string.str, rhs.data.v_string.str,
lhs.data.v_string.len) == 0;
if (lhs.data.v_string.len != rhs.data.v_string.len) return false;
return std::memcmp(lhs.data.v_string.str, rhs.data.v_string.str,
lhs.data.v_string.len) == 0;
case NT_BOOLEAN_ARRAY:
if (lhs.data.arr_boolean.size != rhs.data.arr_boolean.size)
return false;
return std::memcmp(lhs.data.arr_boolean.arr, rhs.data.arr_boolean.arr,
lhs.data.arr_boolean.size *
sizeof(lhs.data.arr_boolean.arr[0])) == 0;
if (lhs.data.arr_boolean.size != rhs.data.arr_boolean.size) return false;
return std::memcmp(lhs.data.arr_boolean.arr, rhs.data.arr_boolean.arr,
lhs.data.arr_boolean.size *
sizeof(lhs.data.arr_boolean.arr[0])) == 0;
case NT_DOUBLE_ARRAY:
if (lhs.data.arr_double.size != rhs.data.arr_double.size)
return false;
return std::memcmp(lhs.data.arr_double.arr, rhs.data.arr_double.arr,
lhs.data.arr_double.size *
sizeof(lhs.data.arr_double.arr[0])) == 0;
case NT_STRING_ARRAY:
{
if (lhs.data.arr_string.size != rhs.data.arr_string.size)
return false;
for (size_t i=0; i<lhs.data.arr_string.size; i++)
{
if (lhs.data.arr_string.arr[i].len !=
rhs.data.arr_string.arr[i].len)
return false;
if (std::memcmp(lhs.data.arr_string.arr[i].str,
rhs.data.arr_string.arr[i].str,
lhs.data.arr_string.arr[i].len) != 0)
return false;
}
return true;
if (lhs.data.arr_double.size != rhs.data.arr_double.size) return false;
return std::memcmp(lhs.data.arr_double.arr, rhs.data.arr_double.arr,
lhs.data.arr_double.size *
sizeof(lhs.data.arr_double.arr[0])) == 0;
case NT_STRING_ARRAY: {
if (lhs.data.arr_string.size != rhs.data.arr_string.size) return false;
for (size_t i = 0; i < lhs.data.arr_string.size; i++) {
if (lhs.data.arr_string.arr[i].len != rhs.data.arr_string.arr[i].len)
return false;
if (std::memcmp(lhs.data.arr_string.arr[i].str,
rhs.data.arr_string.arr[i].str,
lhs.data.arr_string.arr[i].len) != 0)
return false;
}
return true;
}
default:
//assert(false && "unknown value type");
return false;
}
// assert(false && "unknown value type");
return false;
}
}

View File

@@ -10,10 +10,8 @@
struct NT_Value;
namespace NtImpl {
namespace ntimpl {} // namespace ntimpl
} // namespace NtImpl
bool operator==(const NT_Value& lhs, const NT_Value& rhs);
bool operator== (const NT_Value& lhs, const NT_Value& rhs);
#endif /* NT_VALUE_H_ */
#endif // NT_VALUE_H_

View File

@@ -15,196 +15,191 @@
#include "nt_internal.h"
#include "nt_leb128.h"
using namespace NtImpl;
using namespace ntimpl;
static double
read_double(char*& buf)
{
std::uint64_t val = (*((unsigned char *)buf)) & 0xff;
++buf; val <<= 8; val |= (*((unsigned char *)buf)) & 0xff;
++buf; val <<= 8; val |= (*((unsigned char *)buf)) & 0xff;
++buf; val <<= 8; val |= (*((unsigned char *)buf)) & 0xff;
++buf; val <<= 8; val |= (*((unsigned char *)buf)) & 0xff;
++buf; val <<= 8; val |= (*((unsigned char *)buf)) & 0xff;
++buf; val <<= 8; val |= (*((unsigned char *)buf)) & 0xff;
++buf; val <<= 8; val |= (*((unsigned char *)buf)) & 0xff;
++buf;
return *reinterpret_cast<double*>(&val);
static double read_double(char*& buf) {
std::uint64_t val = (*((unsigned char*)buf)) & 0xff;
++buf;
val <<= 8;
val |= (*((unsigned char*)buf)) & 0xff;
++buf;
val <<= 8;
val |= (*((unsigned char*)buf)) & 0xff;
++buf;
val <<= 8;
val |= (*((unsigned char*)buf)) & 0xff;
++buf;
val <<= 8;
val |= (*((unsigned char*)buf)) & 0xff;
++buf;
val <<= 8;
val |= (*((unsigned char*)buf)) & 0xff;
++buf;
val <<= 8;
val |= (*((unsigned char*)buf)) & 0xff;
++buf;
val <<= 8;
val |= (*((unsigned char*)buf)) & 0xff;
++buf;
return *reinterpret_cast<double*>(&val);
}
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 = nullptr;
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 = nullptr;
}
WireDecoder::~WireDecoder()
{
std::free(m_buf);
WireDecoder::~WireDecoder() { std::free(m_buf); }
bool WireDecoder::ReadDouble(double* val) {
char* buf;
if (!Read(&buf, 8)) return false;
*val = read_double(buf);
return true;
}
bool
WireDecoder::ReadDouble(double* val)
{
char* buf;
if (!Read(&buf, 8)) return false;
*val = read_double(buf);
return true;
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;
}
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;
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;
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;
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_DOUBLE: {
if (!ReadDouble(&value->data.v_double)) return false;
break;
}
case NT_STRING:
if (!ReadString(&value->data.v_string)) return false;
break;
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;
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;
// 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;
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] = read_double(buf);
break;
// 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] = read_double(buf);
break;
}
case NT_STRING_ARRAY:
{
// size
unsigned int size;
if (!Read8(&size)) return false;
value->data.arr_string.size = size;
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;
}
// 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;
}
break;
}
default:
m_error = "invalid type when trying to read value";
return false;
}
return true;
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;
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;
}

View File

@@ -14,94 +14,84 @@
#include "nt_leb128.h"
#include "nt_raw_istream.h"
namespace NtImpl {
namespace ntimpl {
class WireDecoder
{
public:
explicit WireDecoder(raw_istream& is, unsigned int proto_rev);
~WireDecoder();
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 SetProtocolRev(unsigned int proto_rev) { m_proto_rev = proto_rev; }
void Reset()
{
m_error = nullptr;
}
void Reset() { m_error = nullptr; }
const char* GetError() const
{
return m_error;
}
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 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 = (*((unsigned char *)buf)) & 0xff;
return true;
}
bool Read8(unsigned int* val) {
char* buf;
if (!Read(&buf, 1)) return false;
*val = (*((unsigned char*)buf)) & 0xff;
return true;
}
bool Read16(unsigned int* val)
{
char* buf;
if (!Read(&buf, 2)) return false;
unsigned int v = (*((unsigned char *)buf)) & 0xff;
++buf; v <<= 8; v |= (*((unsigned char *)buf)) & 0xff;
*val = v;
return true;
}
bool Read16(unsigned int* val) {
char* buf;
if (!Read(&buf, 2)) return false;
unsigned int v = (*((unsigned char*)buf)) & 0xff;
++buf;
v <<= 8;
v |= (*((unsigned char*)buf)) & 0xff;
*val = v;
return true;
}
bool Read32(unsigned long *val)
{
char* buf;
if (!Read(&buf, 4)) return false;
unsigned int v = (*((unsigned char *)buf)) & 0xff;
++buf; v <<= 8; v |= (*((unsigned char *)buf)) & 0xff;
++buf; v <<= 8; v |= (*((unsigned char *)buf)) & 0xff;
++buf; v <<= 8; v |= (*((unsigned char *)buf)) & 0xff;
*val = v;
return true;
}
bool Read32(unsigned long* val) {
char* buf;
if (!Read(&buf, 4)) return false;
unsigned int v = (*((unsigned char*)buf)) & 0xff;
++buf;
v <<= 8;
v |= (*((unsigned char*)buf)) & 0xff;
++buf;
v <<= 8;
v |= (*((unsigned char*)buf)) & 0xff;
++buf;
v <<= 8;
v |= (*((unsigned char*)buf)) & 0xff;
*val = v;
return true;
}
bool ReadDouble(double* val);
bool ReadDouble(double* val);
bool ReadULEB128(unsigned long* val)
{
return read_uleb128(m_is, val);
}
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);
bool ReadType(NT_Type* type);
bool ReadValue(NT_Type type, NT_Value* value);
bool ReadString(NT_String* str);
WireDecoder(const WireDecoder&) = delete;
WireDecoder& operator= (const WireDecoder&) = delete;
WireDecoder(const WireDecoder&) = delete;
WireDecoder& operator=(const WireDecoder&) = delete;
protected:
unsigned int m_proto_rev;
const char* m_error;
protected:
unsigned int m_proto_rev;
const char* m_error;
private:
void Realloc(std::size_t len);
private:
void Realloc(std::size_t len);
raw_istream& m_is;
raw_istream& m_is;
char* m_buf;
std::size_t m_allocated;
char* m_buf;
std::size_t m_allocated;
};
} // namespace NtImpl
} // namespace ntimpl
#endif /* NT_WIREDECODER_H_ */
#endif // NT_WIREDECODER_H_

View File

@@ -15,214 +15,186 @@
#include "nt_internal.h"
#include "nt_leb128.h"
using namespace NtImpl;
using namespace ntimpl;
WireEncoder::WireEncoder(unsigned int proto_rev)
{
m_start = m_cur = (char *)std::malloc(1024);
m_end = m_start + 1024;
m_proto_rev = proto_rev;
m_error = nullptr;
WireEncoder::WireEncoder(unsigned int proto_rev) {
m_start = m_cur = (char*)std::malloc(1024);
m_end = m_start + 1024;
m_proto_rev = proto_rev;
m_error = nullptr;
}
WireEncoder::~WireEncoder()
{
std::free(m_start);
WireEncoder::~WireEncoder() { std::free(m_start); }
void WireEncoder::WriteDouble(double val) {
Reserve(8);
std::uint64_t v = *reinterpret_cast<uint64_t*>(&val);
*m_cur++ = (char)((v >> 56) & 0xff);
*m_cur++ = (char)((v >> 48) & 0xff);
*m_cur++ = (char)((v >> 40) & 0xff);
*m_cur++ = (char)((v >> 32) & 0xff);
*m_cur++ = (char)((v >> 24) & 0xff);
*m_cur++ = (char)((v >> 16) & 0xff);
*m_cur++ = (char)((v >> 8) & 0xff);
*m_cur++ = (char)(v & 0xff);
}
void
WireEncoder::WriteDouble(double val)
{
Reserve(8);
std::uint64_t v = *reinterpret_cast<uint64_t*>(&val);
*m_cur++ = (char)((v >> 56) & 0xff);
*m_cur++ = (char)((v >> 48) & 0xff);
*m_cur++ = (char)((v >> 40) & 0xff);
*m_cur++ = (char)((v >> 32) & 0xff);
*m_cur++ = (char)((v >> 24) & 0xff);
*m_cur++ = (char)((v >> 16) & 0xff);
*m_cur++ = (char)((v >> 8) & 0xff);
*m_cur++ = (char)(v & 0xff);
void WireEncoder::ReserveSlow(std::size_t len) {
assert(m_end > m_cur);
if (static_cast<std::size_t>(m_end - m_cur) >= len) return;
std::size_t pos = m_cur - m_start;
std::size_t newlen = (m_end - m_start) * 2;
while (newlen < (pos + len)) newlen *= 2;
m_start = (char*)std::realloc(m_start, newlen);
m_cur = m_start + pos;
m_end = m_start + newlen;
}
void
WireEncoder::ReserveSlow(std::size_t len)
{
assert(m_end > m_cur);
if (static_cast<std::size_t>(m_end - m_cur) >= len)
return;
std::size_t pos = m_cur - m_start;
std::size_t newlen = (m_end - m_start) * 2;
while (newlen < (pos + len))
newlen *= 2;
m_start = (char *)std::realloc(m_start, newlen);
m_cur = m_start + pos;
m_end = m_start + newlen;
void WireEncoder::WriteULEB128(unsigned long val) {
Reserve(size_uleb128(val));
m_cur += write_uleb128(m_cur, val);
}
void
WireEncoder::WriteULEB128(unsigned long val)
{
Reserve(size_uleb128(val));
m_cur += write_uleb128(m_cur, val);
}
void
WireEncoder::WriteType(NT_Type type)
{
Reserve(1);
switch (type)
{
case NT_BOOLEAN: *m_cur = 0x00; break;
case NT_DOUBLE: *m_cur = 0x01; break;
case NT_STRING: *m_cur = 0x02; break;
case NT_RAW:
if (m_proto_rev < 0x0300u)
{
m_error = "raw type not supported in protocol < 3.0";
return;
}
*m_cur = 0x03;
break;
case NT_BOOLEAN_ARRAY: *m_cur = 0x10; break;
case NT_DOUBLE_ARRAY: *m_cur = 0x11; break;
case NT_STRING_ARRAY: *m_cur = 0x12; break;
case NT_RPC:
if (m_proto_rev < 0x0300u)
{
m_error = "RPC type not supported in protocol < 3.0";
return;
}
*m_cur = 0x20;
break;
default:
m_error = "unrecognized type";
return;
}
++m_cur;
}
std::size_t
WireEncoder::GetValueSize(const NT_Value& value)
{
switch (value.type)
{
void WireEncoder::WriteType(NT_Type type) {
Reserve(1);
switch (type) {
case NT_BOOLEAN:
return 1;
*m_cur = 0x00;
break;
case NT_DOUBLE:
return 8;
*m_cur = 0x01;
break;
case NT_STRING:
return GetStringSize(value.data.v_string);
*m_cur = 0x02;
break;
case NT_RAW:
case NT_RPC:
if (m_proto_rev < 0x0300u)
return 0;
return GetStringSize(value.data.v_raw);
case NT_BOOLEAN_ARRAY:
return 1 + value.data.arr_boolean.size;
case NT_DOUBLE_ARRAY:
return 1 + value.data.arr_double.size * 8;
case NT_STRING_ARRAY:
{
size_t len = 1;
for (size_t i=0; i<value.data.arr_string.size; ++i)
len += GetStringSize(value.data.arr_string.arr[i]);
return len;
}
default:
return 0;
}
}
void
WireEncoder::WriteValue(const NT_Value& value)
{
switch (value.type)
{
case NT_BOOLEAN:
Write8(value.data.v_boolean ? 1 : 0);
break;
case NT_DOUBLE:
WriteDouble(value.data.v_double);
break;
case NT_STRING:
WriteString(value.data.v_string);
break;
case NT_RAW:
case NT_RPC:
if (m_proto_rev < 0x0300u)
{
m_error = "raw and rpc values not supported in protocol < 3.0";
return;
}
WriteString(value.data.v_raw);
break;
case NT_BOOLEAN_ARRAY:
{
std::size_t size = value.data.arr_boolean.size;
if (size > 0xff)
size = 0xff;
Reserve(1+size);
Write8(size);
for (std::size_t i=0; i<size; ++i)
Write8(value.data.arr_boolean.arr[i] ? 1 : 0);
break;
}
case NT_DOUBLE_ARRAY:
{
std::size_t size = value.data.arr_double.size;
if (size > 0xff)
size = 0xff;
Reserve(1+size*8);
Write8(size);
for (std::size_t i=0; i<size; ++i)
WriteDouble(value.data.arr_double.arr[i] ? 1 : 0);
break;
}
case NT_STRING_ARRAY:
{
std::size_t size = value.data.arr_string.size;
if (size > 0xff)
size = 0xff;
Write8(size);
for (std::size_t i=0; i<size; ++i)
WriteString(value.data.arr_string.arr[i]);
break;
}
default:
m_error = "unrecognized type when writing value";
if (m_proto_rev < 0x0300u) {
m_error = "raw type not supported in protocol < 3.0";
return;
}
*m_cur = 0x03;
break;
case NT_BOOLEAN_ARRAY:
*m_cur = 0x10;
break;
case NT_DOUBLE_ARRAY:
*m_cur = 0x11;
break;
case NT_STRING_ARRAY:
*m_cur = 0x12;
break;
case NT_RPC:
if (m_proto_rev < 0x0300u) {
m_error = "RPC type not supported in protocol < 3.0";
return;
}
*m_cur = 0x20;
break;
default:
m_error = "unrecognized type";
return;
}
++m_cur;
}
std::size_t WireEncoder::GetValueSize(const NT_Value& value) {
switch (value.type) {
case NT_BOOLEAN:
return 1;
case NT_DOUBLE:
return 8;
case NT_STRING:
return GetStringSize(value.data.v_string);
case NT_RAW:
case NT_RPC:
if (m_proto_rev < 0x0300u) return 0;
return GetStringSize(value.data.v_raw);
case NT_BOOLEAN_ARRAY:
return 1 + value.data.arr_boolean.size;
case NT_DOUBLE_ARRAY:
return 1 + value.data.arr_double.size * 8;
case NT_STRING_ARRAY: {
size_t len = 1;
for (size_t i = 0; i < value.data.arr_string.size; ++i)
len += GetStringSize(value.data.arr_string.arr[i]);
return len;
}
default:
return 0;
}
}
std::size_t
WireEncoder::GetStringSize(const NT_String& str)
{
if (m_proto_rev < 0x0300u)
return 2 + str.len;
return size_uleb128(str.len) + str.len;
}
void WireEncoder::WriteValue(const NT_Value& value) {
switch (value.type) {
case NT_BOOLEAN:
Write8(value.data.v_boolean ? 1 : 0);
break;
case NT_DOUBLE:
WriteDouble(value.data.v_double);
break;
case NT_STRING:
WriteString(value.data.v_string);
break;
case NT_RAW:
case NT_RPC:
if (m_proto_rev < 0x0300u) {
m_error = "raw and rpc values not supported in protocol < 3.0";
return;
}
WriteString(value.data.v_raw);
break;
case NT_BOOLEAN_ARRAY: {
std::size_t size = value.data.arr_boolean.size;
if (size > 0xff) size = 0xff;
Reserve(1 + size);
Write8(size);
void
WireEncoder::WriteString(const NT_String& str)
{
// length
std::size_t len = str.len;
if (m_proto_rev < 0x0300u)
{
// Limited to 64K length; truncate if necessary
if (len > 0xffff)
len = 0xffff;
Write16(len);
for (std::size_t i = 0; i < size; ++i)
Write8(value.data.arr_boolean.arr[i] ? 1 : 0);
break;
}
else
WriteULEB128(len);
case NT_DOUBLE_ARRAY: {
std::size_t size = value.data.arr_double.size;
if (size > 0xff) size = 0xff;
Reserve(1 + size * 8);
Write8(size);
// contents
Reserve(len);
std::memcpy(m_cur, str.str, len);
m_cur += len;
for (std::size_t i = 0; i < size; ++i)
WriteDouble(value.data.arr_double.arr[i] ? 1 : 0);
break;
}
case NT_STRING_ARRAY: {
std::size_t size = value.data.arr_string.size;
if (size > 0xff) size = 0xff;
Write8(size);
for (std::size_t i = 0; i < size; ++i)
WriteString(value.data.arr_string.arr[i]);
break;
}
default:
m_error = "unrecognized type when writing value";
return;
}
}
std::size_t WireEncoder::GetStringSize(const NT_String& str) {
if (m_proto_rev < 0x0300u) return 2 + str.len;
return size_uleb128(str.len) + str.len;
}
void WireEncoder::WriteString(const NT_String& str) {
// length
std::size_t len = str.len;
if (m_proto_rev < 0x0300u) {
// Limited to 64K length; truncate if necessary
if (len > 0xffff) len = 0xffff;
Write16(len);
} else
WriteULEB128(len);
// contents
Reserve(len);
std::memcpy(m_cur, str.str, len);
m_cur += len;
}

View File

@@ -13,94 +13,75 @@
#include "ntcore.h"
namespace NtImpl {
namespace ntimpl {
class WireEncoder
{
public:
explicit WireEncoder(unsigned int proto_rev);
~WireEncoder();
class WireEncoder {
public:
explicit WireEncoder(unsigned int proto_rev);
~WireEncoder();
void SetProtocolRev(unsigned int proto_rev)
{
m_proto_rev = proto_rev;
}
void SetProtocolRev(unsigned int proto_rev) { m_proto_rev = proto_rev; }
void Reset()
{
m_cur = m_start;
m_error = nullptr;
}
void Reset() {
m_cur = m_start;
m_error = nullptr;
}
const char* GetError() const
{
return m_error;
}
const char* GetError() const { return m_error; }
const char* GetData() const
{
return m_start;
}
const char* GetData() const { return m_start; }
std::size_t GetSize() const
{
return m_cur - m_start;
}
std::size_t GetSize() const { return m_cur - m_start; }
void Reserve(std::size_t len)
{
//assert(m_end > m_cur);
if (static_cast<size_t>(m_end - m_cur) < len)
ReserveSlow(len);
}
void Reserve(std::size_t len) {
// assert(m_end > m_cur);
if (static_cast<size_t>(m_end - m_cur) < len) ReserveSlow(len);
}
void Write8(unsigned int val)
{
Reserve(1);
*m_cur++ = (char)(val & 0xff);
}
void Write8(unsigned int val) {
Reserve(1);
*m_cur++ = (char)(val & 0xff);
}
void Write16(unsigned int val)
{
Reserve(2);
*m_cur++ = (char)((val >> 8) & 0xff);
*m_cur++ = (char)(val & 0xff);
}
void Write16(unsigned int val) {
Reserve(2);
*m_cur++ = (char)((val >> 8) & 0xff);
*m_cur++ = (char)(val & 0xff);
}
void Write32(unsigned long val)
{
Reserve(4);
*m_cur++ = (char)((val >> 24) & 0xff);
*m_cur++ = (char)((val >> 16) & 0xff);
*m_cur++ = (char)((val >> 8) & 0xff);
*m_cur++ = (char)(val & 0xff);
}
void Write32(unsigned long val) {
Reserve(4);
*m_cur++ = (char)((val >> 24) & 0xff);
*m_cur++ = (char)((val >> 16) & 0xff);
*m_cur++ = (char)((val >> 8) & 0xff);
*m_cur++ = (char)(val & 0xff);
}
void WriteDouble(double val);
void WriteDouble(double val);
void WriteULEB128(unsigned long val);
void WriteType(NT_Type type);
void WriteValue(const NT_Value& value);
void WriteString(const NT_String& str);
void WriteULEB128(unsigned long val);
void WriteType(NT_Type type);
void WriteValue(const NT_Value& value);
void WriteString(const NT_String& str);
std::size_t GetValueSize(const NT_Value& value);
std::size_t GetStringSize(const NT_String& str);
std::size_t GetValueSize(const NT_Value& value);
std::size_t GetStringSize(const NT_String& str);
WireEncoder(const WireEncoder&) = delete;
WireEncoder& operator= (const WireEncoder&) = delete;
WireEncoder(const WireEncoder&) = delete;
WireEncoder& operator=(const WireEncoder&) = delete;
protected:
unsigned int m_proto_rev;
const char* m_error;
protected:
unsigned int m_proto_rev;
const char* m_error;
private:
void ReserveSlow(std::size_t len);
private:
void ReserveSlow(std::size_t len);
char* m_start;
char* m_cur;
char* m_end;
char* m_start;
char* m_cur;
char* m_end;
};
} // namespace NtImpl
} // namespace ntimpl
#endif /* NT_WIREENCODER_H_ */
#endif // NT_WIREENCODER_H_

View File

@@ -4,8 +4,8 @@
// - see < http://opensource.org/licenses/BSD-2-Clause>
//
#ifndef CONCURRENT_QUEUE_
#define CONCURRENT_QUEUE_
#ifndef NT_SUPPORT_CONCURRENT_QUEUE_H_
#define NT_SUPPORT_CONCURRENT_QUEUE_H_
#include <queue>
#include <thread>
@@ -13,56 +13,49 @@
#include <condition_variable>
template <typename T>
class ConcurrentQueue
{
public:
T pop()
{
std::unique_lock<std::mutex> mlock(mutex_);
while (queue_.empty())
{
cond_.wait(mlock);
}
auto item = std::move(queue_.front());
queue_.pop();
return item;
class ConcurrentQueue {
public:
T pop() {
std::unique_lock<std::mutex> mlock(mutex_);
while (queue_.empty()) {
cond_.wait(mlock);
}
auto item = std::move(queue_.front());
queue_.pop();
return item;
}
void pop(T& item)
{
std::unique_lock<std::mutex> mlock(mutex_);
while (queue_.empty())
{
cond_.wait(mlock);
}
item = queue_.front();
queue_.pop();
void pop(T& item) {
std::unique_lock<std::mutex> mlock(mutex_);
while (queue_.empty()) {
cond_.wait(mlock);
}
item = queue_.front();
queue_.pop();
}
void push(const T& item)
{
std::unique_lock<std::mutex> mlock(mutex_);
queue_.push(item);
mlock.unlock();
cond_.notify_one();
}
void push(const T& item) {
std::unique_lock<std::mutex> mlock(mutex_);
queue_.push(item);
mlock.unlock();
cond_.notify_one();
}
void push(T&& item)
{
std::unique_lock<std::mutex> mlock(mutex_);
queue_.push(std::move(item));
mlock.unlock();
cond_.notify_one();
}
void push(T&& item) {
std::unique_lock<std::mutex> mlock(mutex_);
queue_.push(std::move(item));
mlock.unlock();
cond_.notify_one();
}
ConcurrentQueue() = default;
ConcurrentQueue(const ConcurrentQueue&) = delete;
ConcurrentQueue& operator=(const ConcurrentQueue&) = delete;
private:
std::queue<T> queue_;
std::mutex mutex_;
std::condition_variable cond_;
ConcurrentQueue() = default;
ConcurrentQueue(const ConcurrentQueue&) = delete;
ConcurrentQueue& operator=(const ConcurrentQueue&) = delete;
private:
std::queue<T> queue_;
std::mutex mutex_;
std::condition_variable cond_;
};
#endif
#endif // NT_SUPPORT_CONCURRENT_QUEUE_H_

View File

@@ -1,3 +1,9 @@
/*----------------------------------------------------------------------------*/
/* 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 "timestamp.h"
#include <cassert>
@@ -10,82 +16,74 @@
#endif
// offset in microseconds
static unsigned long long
zerotime()
{
static unsigned long long zerotime() {
#ifdef _WIN32
FILETIME ft;
unsigned long long tmpres = 0;
// 100-nanosecond intervals since January 1, 1601 (UTC)
// which means 0.1 us
GetSystemTimeAsFileTime(&ft);
tmpres |= ft.dwHighDateTime;
tmpres <<= 32;
tmpres |= ft.dwLowDateTime;
// January 1st, 1970 - January 1st, 1601 UTC ~ 369 years
// or 116444736000000000 us
static const unsigned long long deltaepoch = 116444736000000000ull;
tmpres -= deltaepoch;
return tmpres;
FILETIME ft;
unsigned long long tmpres = 0;
// 100-nanosecond intervals since January 1, 1601 (UTC)
// which means 0.1 us
GetSystemTimeAsFileTime(&ft);
tmpres |= ft.dwHighDateTime;
tmpres <<= 32;
tmpres |= ft.dwLowDateTime;
// January 1st, 1970 - January 1st, 1601 UTC ~ 369 years
// or 116444736000000000 us
static const unsigned long long deltaepoch = 116444736000000000ull;
tmpres -= deltaepoch;
return tmpres;
#else
timespec ts;
timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
clock_gettime(CLOCK_REALTIME, &ts);
// in 100-ns intervals
return static_cast<unsigned long long>(ts.tv_sec) * 10000000ull +
static_cast<unsigned long long>(ts.tv_nsec) / 100u;
// in 100-ns intervals
return static_cast<unsigned long long>(ts.tv_sec) * 10000000ull +
static_cast<unsigned long long>(ts.tv_nsec) / 100u;
#endif
}
static unsigned long long
timestamp()
{
static unsigned long long timestamp() {
#ifdef _WIN32
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
// there is an imprecision with the initial value,
// but what matters is that timestamps are monotonic and consistent
return static_cast<unsigned long long>(li.QuadPart);
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
// there is an imprecision with the initial value,
// but what matters is that timestamps are monotonic and consistent
return static_cast<unsigned long long>(li.QuadPart);
#else
timespec ts;
timespec ts;
// cannot fail, parameters are correct and we checked earlier we can
// access the clock
clock_gettime(CLOCK_MONOTONIC, &ts);
// in ns
return static_cast<unsigned long long>(ts.tv_sec) * 1000000000ull +
static_cast<unsigned long long>(ts.tv_nsec);
// cannot fail, parameters are correct and we checked earlier we can
// access the clock
clock_gettime(CLOCK_MONOTONIC, &ts);
// in ns
return static_cast<unsigned long long>(ts.tv_sec) * 1000000000ull +
static_cast<unsigned long long>(ts.tv_nsec);
#endif
}
static unsigned long long
update_frequency()
{
static unsigned long long update_frequency() {
#ifdef _WIN32
LARGE_INTEGER li;
if (!QueryPerformanceFrequency(&li) || !li.QuadPart)
{
// log something
std::terminate();
}
return static_cast<unsigned long long>(li.QuadPart);
LARGE_INTEGER li;
if (!QueryPerformanceFrequency(&li) || !li.QuadPart) {
// log something
std::terminate();
}
return static_cast<unsigned long long>(li.QuadPart);
#else
timespec ts;
timespec ts;
if (clock_getres(CLOCK_MONOTONIC, &ts) < 0)
{
// log error
std::terminate();
}
if (clock_getres(CLOCK_MONOTONIC, &ts) < 0) {
// log error
std::terminate();
}
assert(!ts.tv_sec);
assert(!ts.tv_sec);
// this is the precision of the clock, we want the number of updates per
// second, which is 1 / ts.tv_nsec * 1,000,000,000
static const unsigned long long billion = 1000000000ull;
// this is the precision of the clock, we want the number of updates per
// second, which is 1 / ts.tv_nsec * 1,000,000,000
static const unsigned long long billion = 1000000000ull;
return billion / static_cast<unsigned long long>(ts.tv_nsec);
return billion / static_cast<unsigned long long>(ts.tv_nsec);
#endif
}
@@ -93,14 +91,12 @@ static const unsigned long long zerotime_val = zerotime();
static const unsigned long long offset_val = timestamp();
static const unsigned long long frequency_val = update_frequency();
unsigned long long
NT_Now()
{
assert(offset_val > 0u);
assert(frequency_val > 0u);
unsigned long long delta = timestamp() - offset_val;
// because the frequency is in update per seconds, we have to multiply the
// delta by 10,000,000
unsigned long long delta_in_us = delta * 10000000ull / frequency_val;
return delta_in_us + zerotime_val;
unsigned long long NT_Now() {
assert(offset_val > 0u);
assert(frequency_val > 0u);
unsigned long long delta = timestamp() - offset_val;
// because the frequency is in update per seconds, we have to multiply the
// delta by 10,000,000
unsigned long long delta_in_us = delta * 10000000ull / frequency_val;
return delta_in_us + zerotime_val;
}

View File

@@ -1,12 +1,20 @@
#ifndef TIMESTAMP_H_
#define TIMESTAMP_H_
/*----------------------------------------------------------------------------*/
/* 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_SUPPORT_TIMESTAMP_H_
#define NT_SUPPORT_TIMESTAMP_H_
#ifdef __cplusplus
extern "C" {
#endif
unsigned long long NT_Now(void);
#ifdef __cplusplus
}
#endif
#endif /* TIMESTAMP_H_ */
#endif // NT_SUPPORT_TIMESTAMP_H_