From: bruceperens Date: Wed, 22 Jan 2014 07:14:04 +0000 (+0000) Subject: FIFO works. X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=d6b5192b36fcfa7e1dfd01f496275d3aefd26484;p=freetel-svn-tracking.git FIFO works. git-svn-id: https://svn.code.sf.net/p/freetel/code@1391 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/freedv-server/CMakeLists.txt b/freedv-server/CMakeLists.txt index fac3274d..a5d03cb1 100644 --- a/freedv-server/CMakeLists.txt +++ b/freedv-server/CMakeLists.txt @@ -140,6 +140,7 @@ set(Test.sources source/test/audio_sink.cpp source/test/base.cpp source/test/blank_panel.cpp + source/test/fifo.cpp source/test/keying_sink.cpp source/test/ptt_constant.cpp source/test/text_constant.cpp diff --git a/freedv-server/source/drivers.h b/freedv-server/source/drivers.h index 98cb614a..ca672972 100644 --- a/freedv-server/source/drivers.h +++ b/freedv-server/source/drivers.h @@ -41,6 +41,12 @@ namespace FreeDV { ~FIFO(); + /// Returns the amount of space available for incoming data. + /// \return The amount of space, in bytes, available for incoming data. + inline std::size_t incoming_available() const { + return buffer_end - in + out - buffer; + } + /// Return the address of an incoming data buffer of the requested size. /// Throws an error if we run the buffer out of space. Well-behaved code /// won't allocate a size that can't be drained before it is further @@ -53,7 +59,7 @@ namespace FreeDV { inline char * incoming_buffer(std::size_t io_length) { const char * io_end = in + io_length; - if ( io_end >= buffer_end ) + if ( io_end > buffer_end ) return reorder(io_length); else return in; @@ -66,12 +72,6 @@ namespace FreeDV { in += length; } - /// Returns the amount of space available for incoming data. - /// \return The amount of space, in bytes, available for incoming data. - inline std::size_t incoming_space() const { - return buffer_end - in + out - buffer; - } - /// Returns the amount of data available to read. /// \return The amount of data, in bytes, available to read. inline std::size_t outgoing_available() const { diff --git a/freedv-server/source/fifo.cpp b/freedv-server/source/fifo.cpp index 5d094dd2..b4df8ea0 100644 --- a/freedv-server/source/fifo.cpp +++ b/freedv-server/source/fifo.cpp @@ -4,17 +4,22 @@ namespace FreeDV { FIFO::FIFO(std::size_t size) - : buffer(new char[size]), buffer_end(buffer + size) + : buffer(new char[size]), buffer_end(buffer + size), in(buffer), out(buffer) { } + FIFO::~FIFO() + { + delete buffer; + } + char * FIFO::reorder(std::size_t size) { const std::size_t bytes = in - out; - if ( bytes > 0 ) { + if ( bytes > 0 && out > buffer ) { // memmove() is specified to handle overlap properly. memmove(buffer, out, bytes); diff --git a/freedv-server/source/test/fifo.cpp b/freedv-server/source/test/fifo.cpp new file mode 100644 index 00000000..da7a6ae1 --- /dev/null +++ b/freedv-server/source/test/fifo.cpp @@ -0,0 +1,70 @@ +// Tests for the Base class. +#include +#include +#include + +using namespace FreeDV; + +class FIFOTest : public ::testing::Test { +protected: + FIFO * f; + + FIFOTest() + : f(0) + { + } + + void SetUp() { + f = new FIFO(100); + } + + void TearDown() { + delete f; + } +}; + +TEST_F(FIFOTest, CanFillAndDrain) { + ASSERT_EQ(100, f->incoming_available()); + memset(f->incoming_buffer(100), 255, 100); + ASSERT_EQ(0, f->outgoing_available()); + f->incoming_done(100); + ASSERT_EQ(100, f->outgoing_available()); + ASSERT_EQ(0, f->incoming_available()); + EXPECT_THROW(f->incoming_buffer(1), std::runtime_error); + ASSERT_EQ(100, f->outgoing_available()); + ASSERT_NE((char *)0, f->outgoing_buffer(100)); + f->outgoing_done(100); + ASSERT_EQ(0, f->outgoing_available()); + ASSERT_EQ(100, f->incoming_available()); + ASSERT_EQ(100, f->incoming_available()); + memset(f->incoming_buffer(100), 255, 100); + ASSERT_EQ(0, f->outgoing_available()); + f->incoming_done(100); + ASSERT_EQ(100, f->outgoing_available()); + ASSERT_EQ(0, f->incoming_available()); +} + +TEST_F(FIFOTest, Reorder) { + char * b; + const char * r; + + ASSERT_EQ(100, f->incoming_available()); + ASSERT_NE((char *)0, b = f->incoming_buffer(99)); + memset(b, 0, 98); + b[98] = 'b'; + f->incoming_done(99); + ASSERT_EQ(1, f->incoming_available()); + ASSERT_EQ(99, f->outgoing_available()); + ASSERT_NE((char *)0, f->outgoing_buffer(98)); + f->outgoing_done(98); + ASSERT_EQ(1, f->outgoing_available()); + ASSERT_EQ(99, f->incoming_available()); + // This should cause reorder(). + ASSERT_NE((char *)0, b = f->incoming_buffer(2)); + f->incoming_done(0); + ASSERT_EQ(99, f->incoming_available()); + ASSERT_EQ(1, f->outgoing_available()); + ASSERT_NE((char *)0, r = f->outgoing_buffer(1)); + ASSERT_EQ('b', *r); + f->outgoing_done(1); +}