Skip to content

Commit

Permalink
Add a PacketListener class with callbacks.
Browse files Browse the repository at this point in the history
Tests currently fail due to confusion about the meaning of available()
  • Loading branch information
eric-wieser committed Dec 29, 2016
1 parent a083630 commit b303c99
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 0 deletions.
102 changes: 102 additions & 0 deletions src/PacketListener.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#pragma once

#include "packet_interfaces.h"

#include "../test/test_helpers.h"

namespace packetio {

// A wrapper for a lambda function, that works with captured variables
template<typename LambdaType> class Handler {};
template<typename Out, typename ...In> class Handler<Out(In...)> {
Out (*function)(void *, In...);
void *context;

static Out _no_context_handler(void* context, In... arguments) {
return ((Out (*)(In...))context)(arguments...);
}
public:
Handler(Out (*fptr)(In...)) {
context = reinterpret_cast<void*>(fptr);
function = _no_context_handler;
}
template <typename T>
Handler(T &lambda) {
context = static_cast<void*>(&lambda);
function = [](void *context, In... arguments) {
return ((T *)context)->operator()(arguments...);
};
}
Out operator()(In ... in)
{
return function(context, in...);
}
operator bool() {
return context != nullptr;
}
};

template<size_t BufferSize = 256>
class PacketListener_ {
public:
enum class Error {
Overflow,
Framing
};
typedef Handler<void(uint8_t*, size_t, Error)> ErrorHandler;
typedef Handler<void(uint8_t*, size_t)> MessageHandler;

private:
PacketStream& _base;
uint8_t _buffer[BufferSize];
size_t _buffer_index = 0;

ErrorHandler _errorHandler = nullptr;
MessageHandler _messageHandler = nullptr;

inline void _onMessage(uint8_t* message, size_t len) {
if(_messageHandler) _messageHandler(message, len);
}
inline void _onError(uint8_t* message, size_t len, Error e) {
if(_errorHandler) _errorHandler(message, len, e);
}
public:
PacketListener_(PacketStream& base) : _base(base) {}

void update() {
int a = 0;
while((a = _base.available()) > 0) {
if(_buffer_index >= BufferSize) {
_onError(_buffer, _buffer_index, Error::Overflow);
_buffer_index = 0;
_base.next();
return;
}

int c = _base.read();
if(c == PacketStream::EOF) {
return;
}
else if(c == PacketStream::EOP) {
_onMessage(_buffer, _buffer_index);
_buffer_index = 0;
_base.next();
}
else {
_buffer[_buffer_index++] = c;
}
}
}

void onMessage(MessageHandler handler) {
_messageHandler = handler;
}

void onError(ErrorHandler handler) {
_errorHandler = handler;
}
};

typedef PacketListener_<> PacketListener;

}
60 changes: 60 additions & 0 deletions test/test_handler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#ifdef UNIT_TEST

#include "test_helpers.h"
#include "mock_print.h"
#include "cobs/Stream.h"
#include "cobs/Print.h"
#include "PacketListener.h"

using namespace packetio;

static MockABuffer<512> long_buf;

static void test_handler_basic() {
// output
MockPrint mp(long_buf);
COBSPrint output(mp);

//input
MockStream ms(mp);
COBSStream input(ms);

PacketListener handler(input);

size_t received = 0;
size_t sent = 0;
const size_t N = 2;

const MockSBuffer messages[N] = {
"Hello world",
"Go\0dbye world"
};

auto onMessage = [&](uint8_t* data, size_t len) {
const MockSBuffer expected = messages[received++];
TEST_ASSERT_EQUAL_STREAM(expected, MockSBuffer(data, len));
};
handler.onMessage(onMessage);
handler.update();
TEST_ASSERT_EQUAL_MESSAGE(sent, received, "Nothing ran");

for(size_t i = 0; i < N; i++) {
output.write(messages[i].get_buffer(), messages[i].size());
handler.update();

TEST_ASSERT_EQUAL_MESSAGE(sent, received, "Sent too soon");

output.end();
sent++;
handler.update();
TEST_ASSERT_EQUAL(sent, received);
}

(void) sent;
}

void run_all_handler() {
RUN_TEST(test_handler_basic);
}

#endif
2 changes: 2 additions & 0 deletions test/test_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ extern void run_all_mocks();
extern void run_all_cobs_encode();
extern void run_all_cobs_decode();
extern void run_all_cobs_roundtrip();
extern void run_all_handler();

void run_all_tests() {
UNITY_BEGIN();
Expand All @@ -14,6 +15,7 @@ void run_all_tests() {
run_all_cobs_encode();
run_all_cobs_decode();
run_all_cobs_roundtrip();
run_all_handler();

UNITY_END();
}
Expand Down

0 comments on commit b303c99

Please sign in to comment.