aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2013-12-05 11:09:04 +0100
committerMax Kellermann <max@duempel.org>2013-12-05 11:49:21 +0100
commitad7302a032847636d6462946a662f441bdfaaf56 (patch)
tree9f40559b7e42139dd58cd93578c77ae5ebaf776b
parent9f3bead99f6dc0e2879158177b55f4818d011f2d (diff)
downloadmpd-ad7302a032847636d6462946a662f441bdfaaf56.tar.gz
mpd-ad7302a032847636d6462946a662f441bdfaaf56.tar.xz
mpd-ad7302a032847636d6462946a662f441bdfaaf56.zip
util/DynamicFifoBuffer: new class replacing growing_fifo
-rw-r--r--Makefile.am2
-rw-r--r--src/encoder/FlacEncoderPlugin.cxx30
-rw-r--r--src/encoder/NullEncoderPlugin.cxx30
-rw-r--r--src/encoder/WaveEncoderPlugin.cxx37
-rw-r--r--src/util/DynamicFifoBuffer.hxx199
-rw-r--r--src/util/growing_fifo.c90
-rw-r--r--src/util/growing_fifo.h73
7 files changed, 230 insertions, 231 deletions
diff --git a/Makefile.am b/Makefile.am
index 560c01c56..c916f9b4d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -261,9 +261,9 @@ libutil_a_SOURCES = \
src/util/RefCount.hxx \
src/util/fifo_buffer.c src/util/fifo_buffer.h \
src/util/FifoBuffer.hxx \
+ src/util/DynamicFifoBuffer.hxx \
src/util/ConstBuffer.hxx \
src/util/WritableBuffer.hxx \
- src/util/growing_fifo.c src/util/growing_fifo.h \
src/util/LazyRandomEngine.cxx src/util/LazyRandomEngine.hxx \
src/util/SliceBuffer.hxx \
src/util/HugeAllocator.cxx src/util/HugeAllocator.hxx \
diff --git a/src/encoder/FlacEncoderPlugin.cxx b/src/encoder/FlacEncoderPlugin.cxx
index 2569ca95f..91c9382ad 100644
--- a/src/encoder/FlacEncoderPlugin.cxx
+++ b/src/encoder/FlacEncoderPlugin.cxx
@@ -23,15 +23,10 @@
#include "AudioFormat.hxx"
#include "pcm/PcmBuffer.hxx"
#include "ConfigError.hxx"
+#include "util/Manual.hxx"
+#include "util/DynamicFifoBuffer.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
-#include "util/fifo_buffer.h"
-
-extern "C" {
-#include "util/growing_fifo.h"
-}
-
-#include <string.h>
#include <FLAC/stream_encoder.h>
@@ -53,7 +48,7 @@ struct flac_encoder {
* This buffer will hold encoded data from libFLAC until it is
* picked up with flac_encoder_read().
*/
- struct fifo_buffer *output_buffer;
+ Manual<DynamicFifoBuffer<uint8_t>> output_buffer;
flac_encoder():encoder(flac_encoder_plugin) {}
};
@@ -140,7 +135,7 @@ flac_write_callback(gcc_unused const FLAC__StreamEncoder *fse,
struct flac_encoder *encoder = (struct flac_encoder *) client_data;
//transfer data to buffer
- growing_fifo_append(&encoder->output_buffer, data, bytes);
+ encoder->output_buffer->Append((const uint8_t *)data, bytes);
return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
}
@@ -153,7 +148,7 @@ flac_encoder_close(Encoder *_encoder)
FLAC__stream_encoder_delete(encoder->fse);
encoder->expand_buffer.Clear();
- fifo_buffer_free(encoder->output_buffer);
+ encoder->output_buffer.Destruct();
}
static bool
@@ -195,7 +190,7 @@ flac_encoder_open(Encoder *_encoder, AudioFormat &audio_format, Error &error)
return false;
}
- encoder->output_buffer = growing_fifo_new();
+ encoder->output_buffer.Construct(8192);
/* this immediately outputs data through callback */
@@ -304,18 +299,7 @@ flac_encoder_read(Encoder *_encoder, void *dest, size_t length)
{
struct flac_encoder *encoder = (struct flac_encoder *)_encoder;
- size_t max_length;
- const char *src = (const char *)
- fifo_buffer_read(encoder->output_buffer, &max_length);
- if (src == nullptr)
- return 0;
-
- if (length > max_length)
- length = max_length;
-
- memcpy(dest, src, length);
- fifo_buffer_consume(encoder->output_buffer, length);
- return length;
+ return encoder->output_buffer->Read((uint8_t *)dest, length);
}
static const char *
diff --git a/src/encoder/NullEncoderPlugin.cxx b/src/encoder/NullEncoderPlugin.cxx
index 3b1aae5e2..d35d880d4 100644
--- a/src/encoder/NullEncoderPlugin.cxx
+++ b/src/encoder/NullEncoderPlugin.cxx
@@ -20,21 +20,19 @@
#include "config.h"
#include "NullEncoderPlugin.hxx"
#include "EncoderAPI.hxx"
-#include "util/fifo_buffer.h"
-extern "C" {
-#include "util/growing_fifo.h"
-}
+#include "util/Manual.hxx"
+#include "util/DynamicFifoBuffer.hxx"
#include "Compiler.h"
#include <assert.h>
-#include <string.h>
struct NullEncoder final {
Encoder encoder;
- struct fifo_buffer *buffer;
+ Manual<DynamicFifoBuffer<uint8_t>> buffer;
- NullEncoder():encoder(null_encoder_plugin) {}
+ NullEncoder()
+ :encoder(null_encoder_plugin) {}
};
static Encoder *
@@ -58,7 +56,7 @@ null_encoder_close(Encoder *_encoder)
{
NullEncoder *encoder = (NullEncoder *)_encoder;
- fifo_buffer_free(encoder->buffer);
+ encoder->buffer.Destruct();
}
@@ -68,7 +66,7 @@ null_encoder_open(Encoder *_encoder,
gcc_unused Error &error)
{
NullEncoder *encoder = (NullEncoder *)_encoder;
- encoder->buffer = growing_fifo_new();
+ encoder->buffer.Construct(8192);
return true;
}
@@ -79,7 +77,7 @@ null_encoder_write(Encoder *_encoder,
{
NullEncoder *encoder = (NullEncoder *)_encoder;
- growing_fifo_append(&encoder->buffer, data, length);
+ encoder->buffer->Append((const uint8_t *)data, length);
return length;
}
@@ -88,17 +86,7 @@ null_encoder_read(Encoder *_encoder, void *dest, size_t length)
{
NullEncoder *encoder = (NullEncoder *)_encoder;
- size_t max_length;
- const void *src = fifo_buffer_read(encoder->buffer, &max_length);
- if (src == nullptr)
- return 0;
-
- if (length > max_length)
- length = max_length;
-
- memcpy(dest, src, length);
- fifo_buffer_consume(encoder->buffer, length);
- return length;
+ return encoder->buffer->Read((uint8_t *)dest, length);
}
const EncoderPlugin null_encoder_plugin = {
diff --git a/src/encoder/WaveEncoderPlugin.cxx b/src/encoder/WaveEncoderPlugin.cxx
index acae0be9e..083d25f95 100644
--- a/src/encoder/WaveEncoderPlugin.cxx
+++ b/src/encoder/WaveEncoderPlugin.cxx
@@ -21,10 +21,8 @@
#include "WaveEncoderPlugin.hxx"
#include "EncoderAPI.hxx"
#include "system/ByteOrder.hxx"
-#include "util/fifo_buffer.h"
-extern "C" {
-#include "util/growing_fifo.h"
-}
+#include "util/Manual.hxx"
+#include "util/DynamicFifoBuffer.hxx"
#include <assert.h>
#include <string.h>
@@ -33,7 +31,7 @@ struct WaveEncoder {
Encoder encoder;
unsigned bits;
- struct fifo_buffer *buffer;
+ Manual<DynamicFifoBuffer<uint8_t>> buffer;
WaveEncoder():encoder(wave_encoder_plugin) {}
};
@@ -128,9 +126,11 @@ wave_encoder_open(Encoder *_encoder,
break;
}
- encoder->buffer = growing_fifo_new();
- wave_header *header = (wave_header *)
- growing_fifo_write(&encoder->buffer, sizeof(*header));
+ encoder->buffer.Construct(8192);
+
+ auto range = encoder->buffer->Write();
+ assert(range.size >= sizeof(wave_header));
+ wave_header *header = (wave_header *)range.data;
/* create PCM wave header in initial buffer */
fill_wave_header(header,
@@ -138,7 +138,8 @@ wave_encoder_open(Encoder *_encoder,
encoder->bits,
audio_format.sample_rate,
(encoder->bits / 8) * audio_format.channels);
- fifo_buffer_append(encoder->buffer, sizeof(*header));
+
+ encoder->buffer->Append(sizeof(*header));
return true;
}
@@ -148,7 +149,7 @@ wave_encoder_close(Encoder *_encoder)
{
WaveEncoder *encoder = (WaveEncoder *)_encoder;
- fifo_buffer_free(encoder->buffer);
+ encoder->buffer.Destruct();
}
static size_t
@@ -198,7 +199,7 @@ wave_encoder_write(Encoder *_encoder,
{
WaveEncoder *encoder = (WaveEncoder *)_encoder;
- uint8_t *dst = (uint8_t *)growing_fifo_write(&encoder->buffer, length);
+ uint8_t *dst = encoder->buffer->Write(length);
if (IsLittleEndian()) {
switch (encoder->bits) {
@@ -230,7 +231,7 @@ wave_encoder_write(Encoder *_encoder,
}
}
- fifo_buffer_append(encoder->buffer, length);
+ encoder->buffer->Append(length);
return true;
}
@@ -239,17 +240,7 @@ wave_encoder_read(Encoder *_encoder, void *dest, size_t length)
{
WaveEncoder *encoder = (WaveEncoder *)_encoder;
- size_t max_length;
- const void *src = fifo_buffer_read(encoder->buffer, &max_length);
- if (src == NULL)
- return 0;
-
- if (length > max_length)
- length = max_length;
-
- memcpy(dest, src, length);
- fifo_buffer_consume(encoder->buffer, length);
- return length;
+ return encoder->buffer->Read((uint8_t *)dest, length);
}
static const char *
diff --git a/src/util/DynamicFifoBuffer.hxx b/src/util/DynamicFifoBuffer.hxx
new file mode 100644
index 000000000..ead7389e9
--- /dev/null
+++ b/src/util/DynamicFifoBuffer.hxx
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2003-2013 Max Kellermann <max@duempel.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FIFO_BUFFER_HPP
+#define FIFO_BUFFER_HPP
+
+#include "WritableBuffer.hxx"
+
+#include <utility>
+#include <algorithm>
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+
+/**
+ * A first-in-first-out buffer: you can append data at the end, and
+ * read data from the beginning. This class automatically shifts the
+ * buffer as needed. It is not thread safe.
+ */
+template<typename T>
+class DynamicFifoBuffer {
+public:
+ typedef size_t size_type;
+ typedef WritableBuffer<T> Range;
+ typedef typename Range::pointer_type pointer_type;
+ typedef typename Range::const_pointer_type const_pointer_type;
+
+protected:
+ size_type head, tail, capacity;
+ T *data;
+
+public:
+ DynamicFifoBuffer(size_type _capacity)
+ :head(0), tail(0), capacity(_capacity),
+ data(new T[capacity]) {}
+ ~DynamicFifoBuffer() {
+ delete[] data;
+ }
+
+ DynamicFifoBuffer(const DynamicFifoBuffer &) = delete;
+
+ size_type GetCapacity() {
+ return capacity;
+ }
+
+ void Grow(size_type new_capacity) {
+ assert(new_capacity > capacity);
+
+ T *new_data = new T[new_capacity];
+ std::move(data + head, data + tail, new_data);
+ delete[] data;
+ data = new_data;
+ capacity = new_capacity;
+ tail -= head;
+ head = 0;
+ }
+
+ void Clear() {
+ head = tail = 0;
+ }
+
+ bool IsEmpty() const {
+ return head == tail;
+ }
+
+ bool IsFull() const {
+ return head == 0 && tail == capacity;
+ }
+
+ /**
+ * Prepares writing. Returns a buffer range which may be written.
+ * When you are finished, call append().
+ */
+ Range Write() {
+ Shift();
+ return Range(data + tail, capacity - tail);
+ }
+
+ /**
+ * Expands the tail of the buffer, after data has been written to
+ * the buffer returned by write().
+ */
+ void Append(size_type n) {
+ assert(tail <= capacity);
+ assert(n <= capacity);
+ assert(tail + n <= capacity);
+
+ tail += n;
+ }
+
+ void WantWrite(size_type n) {
+ if (tail + n <= capacity)
+ /* enough space after the tail */
+ return;
+
+ const size_type in_use = tail - head;
+ const size_type required_capacity = in_use + n;
+ if (capacity >= required_capacity) {
+ Shift();
+ } else {
+ size_type new_capacity = capacity;
+ do {
+ new_capacity <<= 1;
+ } while (new_capacity < required_capacity);
+
+ Grow(new_capacity);
+ }
+ }
+
+ /**
+ * Write data to the bfufer, growing it as needed. Returns a
+ * writable pointer.
+ */
+ pointer_type Write(size_type n) {
+ WantWrite(n);
+ return data + tail;
+ }
+
+ /**
+ * Append data to the buffer, growing it as needed.
+ */
+ void Append(const_pointer_type p, size_type n) {
+ std::copy_n(p, n, Write(n));
+ Append(n);
+ }
+
+ /**
+ * Return a buffer range which may be read. The buffer pointer is
+ * writable, to allow modifications while parsing.
+ */
+ Range Read() {
+ return Range(data + head, tail - head);
+ }
+
+ /**
+ * Marks a chunk as consumed.
+ */
+ void Consume(size_type n) {
+ assert(tail <= capacity);
+ assert(head <= tail);
+ assert(n <= tail);
+ assert(head + n <= tail);
+
+ head += n;
+ }
+
+ size_type Read(pointer_type p, size_type n) {
+ auto range = Read();
+ if (n > range.size)
+ n = range.size;
+ std::copy_n(range.data, n, p);
+ Consume(n);
+ return n;
+ }
+
+protected:
+ void Shift() {
+ if (head == 0)
+ return;
+
+ assert(head <= capacity);
+ assert(tail <= capacity);
+ assert(tail >= head);
+
+ std::move(data + head, data + tail, data);
+
+ tail -= head;
+ head = 0;
+ }
+};
+
+#endif
diff --git a/src/util/growing_fifo.c b/src/util/growing_fifo.c
deleted file mode 100644
index 88431f60e..000000000
--- a/src/util/growing_fifo.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
- * http://www.musicpd.org
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "growing_fifo.h"
-#include "fifo_buffer.h"
-
-#include <assert.h>
-#include <string.h>
-
-/**
- * Align buffer sizes at 8 kB boundaries. Must be a power of two.
- */
-static const size_t GROWING_FIFO_ALIGN = 8192;
-
-/**
- * Align the specified size to the next #GROWING_FIFO_ALIGN boundary.
- */
-static size_t
-align(size_t size)
-{
- return ((size - 1) | (GROWING_FIFO_ALIGN - 1)) + 1;
-}
-
-struct fifo_buffer *
-growing_fifo_new(void)
-{
- return fifo_buffer_new(GROWING_FIFO_ALIGN);
-}
-
-void *
-growing_fifo_write(struct fifo_buffer **buffer_p, size_t length)
-{
- assert(buffer_p != NULL);
-
- struct fifo_buffer *buffer = *buffer_p;
- assert(buffer != NULL);
-
- size_t max_length;
- void *p = fifo_buffer_write(buffer, &max_length);
- if (p != NULL && max_length >= length)
- return p;
-
- /* grow */
- size_t new_size = fifo_buffer_available(buffer) + length;
- assert(new_size > fifo_buffer_capacity(buffer));
- *buffer_p = buffer = fifo_buffer_realloc(buffer, align(new_size));
-
- /* try again */
- p = fifo_buffer_write(buffer, &max_length);
- assert(p != NULL);
- assert(max_length >= length);
-
- return p;
-}
-
-void
-growing_fifo_append(struct fifo_buffer **buffer_p,
- const void *data, size_t length)
-{
- void *p = growing_fifo_write(buffer_p, length);
- memcpy(p, data, length);
- fifo_buffer_append(*buffer_p, length);
-}
diff --git a/src/util/growing_fifo.h b/src/util/growing_fifo.h
deleted file mode 100644
index 723c3b3ff..000000000
--- a/src/util/growing_fifo.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
- * http://www.musicpd.org
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** \file
- *
- * Helper functions for our FIFO buffer library (fifo_buffer.h) that
- * allows growing the buffer on demand.
- *
- * This library is not thread safe.
- */
-
-#ifndef MPD_GROWING_FIFO_H
-#define MPD_GROWING_FIFO_H
-
-#include <stddef.h>
-
-struct fifo_buffer;
-
-/**
- * Allocate a new #fifo_buffer with the default size.
- */
-struct fifo_buffer *
-growing_fifo_new(void);
-
-/**
- * Prepares writing to the buffer, see fifo_buffer_write() for
- * details. The difference is that this function will automatically
- * grow the buffer if it is too small.
- *
- * The caller is responsible for limiting the capacity of the buffer.
- *
- * @param length the number of bytes that will be written
- * @return a pointer to the end of the buffer (will not be NULL)
- */
-void *
-growing_fifo_write(struct fifo_buffer **buffer_p, size_t length);
-
-/**
- * A helper function that combines growing_fifo_write(), memcpy(),
- * fifo_buffer_append().
- */
-void
-growing_fifo_append(struct fifo_buffer **buffer_p,
- const void *data, size_t length);
-
-#endif