aboutsummaryrefslogtreecommitdiffstats
path: root/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/util')
-rw-r--r--src/util/Alloc.cxx76
-rw-r--r--src/util/Alloc.hxx67
-rw-r--r--src/util/Cast.hxx (renamed from src/util/growing_fifo.h)55
-rw-r--r--src/util/Clamp.hxx49
-rw-r--r--src/util/ConstBuffer.hxx118
-rw-r--r--src/util/Domain.hxx40
-rw-r--r--src/util/DynamicFifoBuffer.hxx199
-rw-r--r--src/util/Error.cxx43
-rw-r--r--src/util/Error.hxx42
-rw-r--r--src/util/FormatString.cxx5
-rw-r--r--src/util/OptionDef.hxx63
-rw-r--r--src/util/OptionParser.cxx59
-rw-r--r--src/util/OptionParser.hxx88
-rw-r--r--src/util/PeakBuffer.cxx72
-rw-r--r--src/util/PeakBuffer.hxx11
-rw-r--r--src/util/SplitString.cxx37
-rw-r--r--src/util/SplitString.hxx71
-rw-r--r--src/util/StringUtil.cxx8
-rw-r--r--src/util/StringUtil.hxx4
-rw-r--r--src/util/Tokenizer.cxx5
-rw-r--r--src/util/UriUtil.cxx10
-rw-r--r--src/util/UriUtil.hxx7
-rw-r--r--src/util/VarSize.hxx83
-rw-r--r--src/util/WritableBuffer.hxx93
-rw-r--r--src/util/fifo_buffer.c218
-rw-r--r--src/util/fifo_buffer.h164
-rw-r--r--src/util/growing_fifo.c90
27 files changed, 1142 insertions, 635 deletions
diff --git a/src/util/Alloc.cxx b/src/util/Alloc.cxx
new file mode 100644
index 000000000..ec3579470
--- /dev/null
+++ b/src/util/Alloc.cxx
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "Alloc.hxx"
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+gcc_noreturn
+static void
+oom()
+{
+ (void)write(STDERR_FILENO, "Out of memory\n", 14);
+ _exit(1);
+}
+
+void *
+xalloc(size_t size)
+{
+ void *p = malloc(size);
+ if (gcc_unlikely(p == nullptr))
+ oom();
+
+ return p;
+}
+
+void *
+xmemdup(const void *s, size_t size)
+{
+ void *p = xalloc(size);
+ memcpy(p, s, size);
+ return p;
+}
+
+char *
+xstrdup(const char *s)
+{
+ char *p = strdup(s);
+ if (gcc_unlikely(p == nullptr))
+ oom();
+
+ return p;
+}
+
+char *
+xstrndup(const char *s, size_t n)
+{
+#ifdef WIN32
+ char *p = (char *)xalloc(n + 1);
+ memcpy(p, s, n);
+ p[n] = 0;
+#else
+ char *p = strndup(s, n);
+ if (gcc_unlikely(p == nullptr))
+ oom();
+#endif
+
+ return p;
+}
diff --git a/src/util/Alloc.hxx b/src/util/Alloc.hxx
new file mode 100644
index 000000000..15c123b7a
--- /dev/null
+++ b/src/util/Alloc.hxx
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_ALLOC_HXX
+#define MPD_ALLOC_HXX
+
+#include "Compiler.h"
+
+#include <stddef.h>
+
+/**
+ * Allocate memory. Use free() to free it.
+ *
+ * This function never fails; in out-of-memory situations, it aborts
+ * the process.
+ */
+gcc_malloc
+void *
+xalloc(size_t size);
+
+/**
+ * Duplicate memory. Use free() to free it.
+ *
+ * This function never fails; in out-of-memory situations, it aborts
+ * the process.
+ */
+gcc_malloc gcc_nonnull_all
+void *
+xmemdup(const void *s, size_t size);
+
+/**
+ * Duplicate a string. Use free() to free it.
+ *
+ * This function never fails; in out-of-memory situations, it aborts
+ * the process.
+ */
+gcc_malloc gcc_nonnull_all
+char *
+xstrdup(const char *s);
+
+/**
+ * Duplicate a string. Use free() to free it.
+ *
+ * This function never fails; in out-of-memory situations, it aborts
+ * the process.
+ */
+gcc_malloc gcc_nonnull_all
+char *
+xstrndup(const char *s, size_t n);
+
+#endif
diff --git a/src/util/growing_fifo.h b/src/util/Cast.hxx
index 723c3b3ff..69172e6de 100644
--- a/src/util/growing_fifo.h
+++ b/src/util/Cast.hxx
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
- * http://www.musicpd.org
+ * Copyright (C) 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
@@ -28,46 +27,32 @@
* 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
+#ifndef CAST_HXX
+#define CAST_HXX
#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)
+ * Offset the given pointer by the specified number of bytes.
*/
-void *
-growing_fifo_write(struct fifo_buffer **buffer_p, size_t length);
+static constexpr void *
+OffsetPointer(void *p, ptrdiff_t offset)
+{
+ return (char *)p + offset;
+}
+
+template<typename T, typename U>
+static constexpr T *
+OffsetCast(U *p, ptrdiff_t offset)
+{
+ return reinterpret_cast<T *>(OffsetPointer(p, offset));
+}
/**
- * A helper function that combines growing_fifo_write(), memcpy(),
- * fifo_buffer_append().
+ * Cast the given pointer to a struct member to its parent structure.
*/
-void
-growing_fifo_append(struct fifo_buffer **buffer_p,
- const void *data, size_t length);
+#define ContainerCast(p, container, attribute) \
+ OffsetCast<container, decltype(((container*)nullptr)->attribute)>\
+ ((p), -ptrdiff_t(offsetof(container, attribute)))
#endif
diff --git a/src/util/Clamp.hxx b/src/util/Clamp.hxx
new file mode 100644
index 000000000..3217ef9f7
--- /dev/null
+++ b/src/util/Clamp.hxx
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012 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 CLAMP_HPP
+#define CLAMP_HPP
+
+#include "Compiler.h"
+
+/**
+ * Clamps the specified value in a range. Returns #min or #max if the
+ * value is outside.
+ */
+template<typename T>
+static inline constexpr const T &
+Clamp(const T &value, const T &min, const T &max)
+{
+ return gcc_unlikely(value < min)
+ ? min
+ : (gcc_unlikely(value > max)
+ ? max : value);
+}
+
+#endif
diff --git a/src/util/ConstBuffer.hxx b/src/util/ConstBuffer.hxx
new file mode 100644
index 000000000..bd3c405e5
--- /dev/null
+++ b/src/util/ConstBuffer.hxx
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 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 CONST_BUFFER_HPP
+#define CONST_BUFFER_HPP
+
+#include "Compiler.h"
+
+#include <cstddef>
+
+#ifndef NDEBUG
+#include <assert.h>
+#endif
+
+/**
+ * A reference to a memory area that is read-only.
+ */
+template<typename T>
+struct ConstBuffer {
+ typedef size_t size_type;
+ typedef const T *pointer_type;
+ typedef pointer_type const_pointer_type;
+ typedef pointer_type iterator;
+ typedef pointer_type const_iterator;
+
+ pointer_type data;
+ size_type size;
+
+ ConstBuffer() = default;
+
+ constexpr ConstBuffer(std::nullptr_t):data(nullptr), size(0) {}
+
+ constexpr ConstBuffer(pointer_type _data, size_type _size)
+ :data(_data), size(_size) {}
+
+ constexpr static ConstBuffer Null() {
+ return ConstBuffer(nullptr, 0);
+ }
+
+ /**
+ * Cast a ConstBuffer<void> to a ConstBuffer<T>. A "void"
+ * buffer records its size in bytes, and when casting to "T",
+ * the assertion below ensures that the size is a multiple of
+ * sizeof(T).
+ */
+#ifdef NDEBUG
+ constexpr
+#endif
+ static ConstBuffer<T> FromVoid(ConstBuffer<void> other) {
+ static_assert(sizeof(T) > 0, "Empty base type");
+#ifndef NDEBUG
+ assert(other.size % sizeof(T) == 0);
+#endif
+ return ConstBuffer<T>(pointer_type(other.data),
+ other.size / sizeof(T));
+ }
+
+ constexpr ConstBuffer<void> ToVoid() const {
+ static_assert(sizeof(T) > 0, "Empty base type");
+ return ConstBuffer<void>(data, size * sizeof(T));
+ }
+
+ constexpr bool IsNull() const {
+ return data == nullptr;
+ }
+
+ constexpr bool IsEmpty() const {
+ return size == 0;
+ }
+
+ constexpr iterator begin() const {
+ return data;
+ }
+
+ constexpr iterator end() const {
+ return data + size;
+ }
+
+ constexpr const_iterator cbegin() const {
+ return data;
+ }
+
+ constexpr const_iterator cend() const {
+ return data + size;
+ }
+
+ constexpr operator ConstBuffer<void>() const {
+ return { data, size };
+ }
+};
+
+#endif
diff --git a/src/util/Domain.hxx b/src/util/Domain.hxx
index bbdbf8371..6dce7b731 100644
--- a/src/util/Domain.hxx
+++ b/src/util/Domain.hxx
@@ -1,24 +1,34 @@
/*
- * Copyright (C) 2003-2013 The Music Player Daemon Project
- * http://www.musicpd.org
+ * Copyright (C) 2013 Max Kellermann <max@duempel.org>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * - 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 MPD_DOMAIN_HXX
-#define MPD_DOMAIN_HXX
+#ifndef DOMAIN_HXX
+#define DOMAIN_HXX
class Domain {
const char *const name;
diff --git a/src/util/DynamicFifoBuffer.hxx b/src/util/DynamicFifoBuffer.hxx
new file mode 100644
index 000000000..df50328b4
--- /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:
+ explicit 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/Error.cxx b/src/util/Error.cxx
index 5675f4d81..649276b20 100644
--- a/src/util/Error.cxx
+++ b/src/util/Error.cxx
@@ -1,31 +1,44 @@
/*
- * Copyright (C) 2003-2013 The Music Player Daemon Project
- * http://www.musicpd.org
+ * Copyright (C) 2013 Max Kellermann <max@duempel.org>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * - 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 "config.h"
#include "Error.hxx"
#include "Domain.hxx"
+#ifdef WIN32
#include <glib.h>
+#endif
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
+#include <string.h>
const Domain errno_domain("errno");
@@ -70,7 +83,7 @@ Error::FormatPrefix(const char *fmt, ...)
void
Error::SetErrno(int e)
{
- Set(errno_domain, e, g_strerror(e));
+ Set(errno_domain, e, strerror(e));
}
void
@@ -82,7 +95,7 @@ Error::SetErrno()
void
Error::SetErrno(int e, const char *prefix)
{
- Format(errno_domain, e, "%s: %s", prefix, g_strerror(e));
+ Format(errno_domain, e, "%s: %s", prefix, strerror(e));
}
void
diff --git a/src/util/Error.hxx b/src/util/Error.hxx
index ec8867c6c..898a8f1c1 100644
--- a/src/util/Error.hxx
+++ b/src/util/Error.hxx
@@ -1,30 +1,40 @@
/*
- * Copyright (C) 2003-2013 The Music Player Daemon Project
- * http://www.musicpd.org
+ * Copyright (C) 2013 Max Kellermann <max@duempel.org>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * - 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 MPD_ERROR_HXX
-#define MPD_ERROR_HXX
+#ifndef ERROR_HXX
+#define ERROR_HXX
#include "check.h"
#include "Compiler.h"
#include <string>
-#include <algorithm>
+#include <utility>
#include <assert.h>
diff --git a/src/util/FormatString.cxx b/src/util/FormatString.cxx
index c13d0fb52..ea6d41860 100644
--- a/src/util/FormatString.cxx
+++ b/src/util/FormatString.cxx
@@ -19,10 +19,13 @@
#include "FormatString.hxx"
-#include <string.h>
#include <stdio.h>
#include <stdlib.h>
+#ifdef WIN32
+#include <string.h>
+#endif
+
char *
FormatNewV(const char *fmt, va_list args)
{
diff --git a/src/util/OptionDef.hxx b/src/util/OptionDef.hxx
new file mode 100644
index 000000000..ca9e6083f
--- /dev/null
+++ b/src/util/OptionDef.hxx
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_UTIL_OPTIONDEF_HXX
+#define MPD_UTIL_OPTIONDEF_HXX
+
+/**
+ * Command line option definition.
+ */
+class OptionDef
+{
+ const char *long_option;
+ char short_option;
+ const char *desc;
+public:
+ constexpr OptionDef(const char *_long_option, const char *_desc)
+ : long_option(_long_option),
+ short_option(0),
+ desc(_desc) { }
+
+ constexpr OptionDef(const char *_long_option,
+ char _short_option, const char *_desc)
+ : long_option(_long_option),
+ short_option(_short_option),
+ desc(_desc) { }
+
+ bool HasLongOption() const { return long_option != nullptr; }
+ bool HasShortOption() const { return short_option != 0; }
+ bool HasDescription() const { return desc != nullptr; }
+
+ const char *GetLongOption() const {
+ assert(HasLongOption());
+ return long_option;
+ }
+
+ char GetShortOption() const {
+ assert(HasShortOption());
+ return short_option;
+ }
+
+ const char *GetDescription() const {
+ assert(HasDescription());
+ return desc;
+ }
+};
+
+#endif
diff --git a/src/util/OptionParser.cxx b/src/util/OptionParser.cxx
new file mode 100644
index 000000000..b8addb9a2
--- /dev/null
+++ b/src/util/OptionParser.cxx
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "OptionParser.hxx"
+#include "OptionDef.hxx"
+
+#include <string.h>
+
+bool OptionParser::CheckOption(const OptionDef &opt)
+{
+ assert(option != nullptr);
+
+ if (is_long)
+ return opt.HasLongOption() &&
+ strcmp(option, opt.GetLongOption()) == 0;
+
+ return opt.HasShortOption() &&
+ option[0] == opt.GetShortOption() &&
+ option[1] == '\0';
+}
+
+bool OptionParser::ParseNext()
+{
+ assert(HasEntries());
+ char *arg = *argv;
+ ++argv;
+ --argc;
+ if (arg[0] == '-') {
+ if (arg[1] == '-') {
+ option = arg + 2;
+ is_long = true;
+ }
+ else {
+ option = arg + 1;
+ is_long = false;
+ }
+ option_raw = arg;
+ return true;
+ }
+ option = nullptr;
+ option_raw = nullptr;
+ return false;
+}
diff --git a/src/util/OptionParser.hxx b/src/util/OptionParser.hxx
new file mode 100644
index 000000000..74091bc29
--- /dev/null
+++ b/src/util/OptionParser.hxx
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_UTIL_OPTIONPARSER_HXX
+#define MPD_UTIL_OPTIONPARSER_HXX
+
+#include <assert.h>
+
+class OptionDef;
+
+/**
+ * Command line option parser.
+ */
+class OptionParser
+{
+ int argc;
+ char **argv;
+ char *option;
+ char *option_raw;
+ bool is_long;
+public:
+ /**
+ * Constructs #OptionParser.
+ */
+ OptionParser(int _argc, char **_argv)
+ : argc(_argc - 1), argv(_argv + 1),
+ option(nullptr), option_raw(nullptr), is_long(false) { }
+
+ /**
+ * Checks if there are command line entries to process.
+ */
+ bool HasEntries() const { return argc > 0; }
+
+ /**
+ * Gets the last parsed option.
+ */
+ char *GetOption() {
+ assert(option_raw != nullptr);
+ return option_raw;
+ }
+
+ /**
+ * Checks if current option is a specified option.
+ */
+ bool CheckOption(const OptionDef& opt);
+
+ /**
+ * Checks if current option is a specified option
+ * or specified alternative option.
+ */
+ bool CheckOption(const OptionDef& opt, const OptionDef &alt_opt) {
+ return CheckOption(opt) || CheckOption(alt_opt);
+ }
+
+ /**
+ * Parses current command line entry.
+ * Returns true on success, false otherwise.
+ * Regardless of result, advances current position to the next
+ * command line entry.
+ */
+ bool ParseNext();
+
+ /**
+ * Checks if specified string is a command line option.
+ */
+ static bool IsOption(const char *s) {
+ assert(s != nullptr);
+ return s[0] == '-';
+ }
+};
+
+#endif
diff --git a/src/util/PeakBuffer.cxx b/src/util/PeakBuffer.cxx
index a3659b8f4..5e86503e8 100644
--- a/src/util/PeakBuffer.cxx
+++ b/src/util/PeakBuffer.cxx
@@ -18,46 +18,39 @@
*/
#include "PeakBuffer.hxx"
-#include "HugeAllocator.hxx"
-#include "fifo_buffer.h"
+#include "DynamicFifoBuffer.hxx"
#include <algorithm>
#include <assert.h>
-#include <stdint.h>
#include <string.h>
PeakBuffer::~PeakBuffer()
{
- if (normal_buffer != nullptr)
- fifo_buffer_free(normal_buffer);
-
- if (peak_buffer != nullptr)
- HugeFree(peak_buffer, peak_size);
+ delete normal_buffer;
+ delete peak_buffer;
}
bool
PeakBuffer::IsEmpty() const
{
- return (normal_buffer == nullptr ||
- fifo_buffer_is_empty(normal_buffer)) &&
- (peak_buffer == nullptr ||
- fifo_buffer_is_empty(peak_buffer));
+ return (normal_buffer == nullptr || normal_buffer->IsEmpty()) &&
+ (peak_buffer == nullptr || peak_buffer->IsEmpty());
}
-const void *
-PeakBuffer::Read(size_t *length_r) const
+WritableBuffer<void>
+PeakBuffer::Read() const
{
if (normal_buffer != nullptr) {
- const void *p = fifo_buffer_read(normal_buffer, length_r);
- if (p != nullptr)
- return p;
+ const auto p = normal_buffer->Read();
+ if (!p.IsEmpty())
+ return p.ToVoid();
}
if (peak_buffer != nullptr) {
- const void *p = fifo_buffer_read(peak_buffer, length_r);
- if (p != nullptr)
- return p;
+ const auto p = peak_buffer->Read();
+ if (!p.IsEmpty())
+ return p.ToVoid();
}
return nullptr;
@@ -66,15 +59,15 @@ PeakBuffer::Read(size_t *length_r) const
void
PeakBuffer::Consume(size_t length)
{
- if (normal_buffer != nullptr && !fifo_buffer_is_empty(normal_buffer)) {
- fifo_buffer_consume(normal_buffer, length);
+ if (normal_buffer != nullptr && !normal_buffer->IsEmpty()) {
+ normal_buffer->Consume(length);
return;
}
- if (peak_buffer != nullptr && !fifo_buffer_is_empty(peak_buffer)) {
- fifo_buffer_consume(peak_buffer, length);
- if (fifo_buffer_is_empty(peak_buffer)) {
- HugeFree(peak_buffer, peak_size);
+ if (peak_buffer != nullptr && !peak_buffer->IsEmpty()) {
+ peak_buffer->Consume(length);
+ if (peak_buffer->IsEmpty()) {
+ delete peak_buffer;
peak_buffer = nullptr;
}
@@ -83,7 +76,7 @@ PeakBuffer::Consume(size_t length)
}
static size_t
-AppendTo(fifo_buffer *buffer, const void *data, size_t length)
+AppendTo(DynamicFifoBuffer<uint8_t> &buffer, const void *data, size_t length)
{
assert(data != nullptr);
assert(length > 0);
@@ -91,14 +84,13 @@ AppendTo(fifo_buffer *buffer, const void *data, size_t length)
size_t total = 0;
do {
- size_t max_length;
- void *p = fifo_buffer_write(buffer, &max_length);
- if (p == nullptr)
+ const auto p = buffer.Write();
+ if (p.IsEmpty())
break;
- const size_t nbytes = std::min(length, max_length);
- memcpy(p, data, nbytes);
- fifo_buffer_append(buffer, nbytes);
+ const size_t nbytes = std::min(length, p.size);
+ memcpy(p.data, data, nbytes);
+ buffer.Append(nbytes);
data = (const uint8_t *)data + nbytes;
length -= nbytes;
@@ -114,15 +106,15 @@ PeakBuffer::Append(const void *data, size_t length)
if (length == 0)
return true;
- if (peak_buffer != nullptr && !fifo_buffer_is_empty(peak_buffer)) {
- size_t nbytes = AppendTo(peak_buffer, data, length);
+ if (peak_buffer != nullptr && !peak_buffer->IsEmpty()) {
+ size_t nbytes = AppendTo(*peak_buffer, data, length);
return nbytes == length;
}
if (normal_buffer == nullptr)
- normal_buffer = fifo_buffer_new(normal_size);
+ normal_buffer = new DynamicFifoBuffer<uint8_t>(normal_size);
- size_t nbytes = AppendTo(normal_buffer, data, length);
+ size_t nbytes = AppendTo(*normal_buffer, data, length);
if (nbytes > 0) {
data = (const uint8_t *)data + nbytes;
length -= nbytes;
@@ -131,13 +123,11 @@ PeakBuffer::Append(const void *data, size_t length)
}
if (peak_buffer == nullptr && peak_size > 0) {
- peak_buffer = (fifo_buffer *)HugeAllocate(peak_size);
+ peak_buffer = new DynamicFifoBuffer<uint8_t>(peak_size);
if (peak_buffer == nullptr)
return false;
-
- fifo_buffer_init(peak_buffer, peak_size);
}
- nbytes = AppendTo(peak_buffer, data, length);
+ nbytes = AppendTo(*peak_buffer, data, length);
return nbytes == length;
}
diff --git a/src/util/PeakBuffer.hxx b/src/util/PeakBuffer.hxx
index a3f385e3e..66f4c1a9f 100644
--- a/src/util/PeakBuffer.hxx
+++ b/src/util/PeakBuffer.hxx
@@ -20,11 +20,14 @@
#ifndef MPD_PEAK_BUFFER_HXX
#define MPD_PEAK_BUFFER_HXX
+#include "WritableBuffer.hxx"
#include "Compiler.h"
#include <stddef.h>
+#include <stdint.h>
-struct fifo_buffer;
+template<typename T> struct WritableBuffer;
+template<typename T> class DynamicFifoBuffer;
/**
* A FIFO-like buffer that will allocate more memory on demand to
@@ -34,7 +37,7 @@ struct fifo_buffer;
class PeakBuffer {
size_t normal_size, peak_size;
- fifo_buffer *normal_buffer, *peak_buffer;
+ DynamicFifoBuffer<uint8_t> *normal_buffer, *peak_buffer;
public:
PeakBuffer(size_t _normal_size, size_t _peak_size)
@@ -57,7 +60,9 @@ public:
gcc_pure
bool IsEmpty() const;
- const void *Read(size_t *length_r) const;
+ gcc_pure
+ WritableBuffer<void> Read() const;
+
void Consume(size_t length);
bool Append(const void *data, size_t length);
diff --git a/src/util/SplitString.cxx b/src/util/SplitString.cxx
new file mode 100644
index 000000000..c8314f28f
--- /dev/null
+++ b/src/util/SplitString.cxx
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "SplitString.hxx"
+
+#include <string.h>
+
+SplitString::SplitString(const char *s, char separator)
+ :first(nullptr)
+{
+ const char *x = strchr(s, separator);
+ if (x == nullptr)
+ return;
+
+ size_t length = x - s;
+ second = x + 1;
+
+ first = new char[length + 1];
+ memcpy(first, s, length);
+ first[length] = 0;
+}
diff --git a/src/util/SplitString.hxx b/src/util/SplitString.hxx
new file mode 100644
index 000000000..a8512b13c
--- /dev/null
+++ b/src/util/SplitString.hxx
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_SPLIT_STRING_HXX
+#define MPD_SPLIT_STRING_HXX
+
+#include "Compiler.h"
+
+#include <assert.h>
+
+/**
+ * Split a given constant string at a separator character. Duplicates
+ * the first part to be able to null-terminate it.
+ */
+class SplitString {
+ char *first;
+ const char *second;
+
+public:
+ SplitString(const char *s, char separator);
+
+ ~SplitString() {
+ delete[] first;
+ }
+
+ /**
+ * Was the separator found?
+ */
+ bool IsDefined() const {
+ return first != nullptr;
+ }
+
+ /**
+ * Is the first part empty?
+ */
+ bool IsEmpty() const {
+ assert(IsDefined());
+
+ return *first == 0;
+ }
+
+ const char *GetFirst() const {
+ assert(IsDefined());
+
+ return first;
+ }
+
+ const char *GetSecond() const {
+ assert(IsDefined());
+
+ return second;
+ }
+};
+
+#endif
diff --git a/src/util/StringUtil.cxx b/src/util/StringUtil.cxx
index 7e295bf90..512a75f5c 100644
--- a/src/util/StringUtil.cxx
+++ b/src/util/StringUtil.cxx
@@ -22,6 +22,7 @@
#include "ASCII.hxx"
#include <assert.h>
+#include <string.h>
const char *
strchug_fast(const char *p)
@@ -33,6 +34,13 @@ strchug_fast(const char *p)
}
bool
+StringStartsWith(const char *haystack, const char *needle)
+{
+ const size_t length = strlen(needle);
+ return memcmp(haystack, needle, length) == 0;
+}
+
+bool
string_array_contains(const char *const* haystack, const char *needle)
{
assert(haystack != nullptr);
diff --git a/src/util/StringUtil.hxx b/src/util/StringUtil.hxx
index 1c67910a9..f25160107 100644
--- a/src/util/StringUtil.hxx
+++ b/src/util/StringUtil.hxx
@@ -40,6 +40,10 @@ strchug_fast(char *p)
return const_cast<char *>(strchug_fast((const char *)p));
}
+gcc_pure
+bool
+StringStartsWith(const char *haystack, const char *needle);
+
/**
* Checks whether a string array contains the specified string.
*
diff --git a/src/util/Tokenizer.cxx b/src/util/Tokenizer.cxx
index 1c8af23fd..a57f5b20c 100644
--- a/src/util/Tokenizer.cxx
+++ b/src/util/Tokenizer.cxx
@@ -24,11 +24,6 @@
#include "Error.hxx"
#include "Domain.hxx"
-#include <glib.h>
-
-#include <assert.h>
-#include <string.h>
-
static constexpr Domain tokenizer_domain("tokenizer");
static inline bool
diff --git a/src/util/UriUtil.cxx b/src/util/UriUtil.cxx
index 2609db2cf..174c977e1 100644
--- a/src/util/UriUtil.cxx
+++ b/src/util/UriUtil.cxx
@@ -27,6 +27,16 @@ bool uri_has_scheme(const char *uri)
return strstr(uri, "://") != nullptr;
}
+std::string
+uri_get_scheme(const char *uri)
+{
+ const char *end = strstr(uri, "://");
+ if (end == nullptr)
+ end = uri;
+
+ return std::string(uri, end);
+}
+
/* suffixes should be ascii only characters */
const char *
uri_get_suffix(const char *uri)
diff --git a/src/util/UriUtil.hxx b/src/util/UriUtil.hxx
index 78d0a6bff..20e468103 100644
--- a/src/util/UriUtil.hxx
+++ b/src/util/UriUtil.hxx
@@ -31,6 +31,13 @@
gcc_pure
bool uri_has_scheme(const char *uri);
+/**
+ * Returns the scheme name of the specified URI, or an empty string.
+ */
+gcc_pure
+std::string
+uri_get_scheme(const char *uri);
+
gcc_pure
const char *
uri_get_suffix(const char *uri);
diff --git a/src/util/VarSize.hxx b/src/util/VarSize.hxx
new file mode 100644
index 000000000..04f1bf580
--- /dev/null
+++ b/src/util/VarSize.hxx
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2008-2014 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 MPD_VAR_SIZE_HXX
+#define MPD_VAR_SIZE_HXX
+
+#include "Alloc.hxx"
+#include "Compiler.h"
+
+#include <type_traits>
+#include <utility>
+#include <new>
+
+/**
+ * Allocate and construct a variable-size object. That is useful for
+ * example when you want to store a variable-length string as the last
+ * attribute without the overhead of a second allocation.
+ *
+ * @param T a struct/class with a variable-size last attribute
+ * @param declared_tail_size the declared size of the last element in
+ * #T
+ * @param real_tail_size the real required size of the last element in
+ * #T
+ */
+template<class T, typename... Args>
+gcc_malloc
+T *
+NewVarSize(size_t declared_tail_size, size_t real_tail_size, Args&&... args)
+{
+ static_assert(std::is_standard_layout<T>::value,
+ "Not standard-layout");
+
+ /* determine the total size of this instance */
+ size_t size = sizeof(T) - declared_tail_size + real_tail_size;
+
+ /* allocate memory */
+ T *instance = (T *)xalloc(size);
+
+ /* call the constructor */
+ new(instance) T(std::forward<Args>(args)...);
+
+ return instance;
+}
+
+template<typename T>
+gcc_nonnull_all
+void
+DeleteVarSize(T *instance)
+{
+ /* call the destructor */
+ instance->T::~T();
+
+ /* free memory */
+ free(instance);
+}
+
+#endif
diff --git a/src/util/WritableBuffer.hxx b/src/util/WritableBuffer.hxx
index 4e529cfad..7267813f5 100644
--- a/src/util/WritableBuffer.hxx
+++ b/src/util/WritableBuffer.hxx
@@ -32,7 +32,11 @@
#include "Compiler.h"
-#include <stddef.h>
+#include <cstddef>
+
+#ifndef NDEBUG
+#include <assert.h>
+#endif
/**
* A reference to a memory area that is writable.
@@ -41,47 +45,72 @@
*/
template<typename T>
struct WritableBuffer {
- typedef size_t size_type;
- typedef T *pointer_type;
- typedef const T *const_pointer_type;
- typedef pointer_type iterator;
- typedef const_pointer_type const_iterator;
+ typedef size_t size_type;
+ typedef T *pointer_type;
+ typedef const T *const_pointer_type;
+ typedef pointer_type iterator;
+ typedef const_pointer_type const_iterator;
+
+ pointer_type data;
+ size_type size;
+
+ WritableBuffer() = default;
- pointer_type data;
- size_type size;
+ constexpr WritableBuffer(std::nullptr_t):data(nullptr), size(0) {}
- WritableBuffer() = default;
+ constexpr WritableBuffer(pointer_type _data, size_type _size)
+ :data(_data), size(_size) {}
- constexpr WritableBuffer(pointer_type _data, size_type _size)
- :data(_data), size(_size) {}
+ constexpr static WritableBuffer Null() {
+ return { nullptr, 0 };
+ }
+
+ /**
+ * Cast a WritableBuffer<void> to a WritableBuffer<T>. A "void"
+ * buffer records its size in bytes, and when casting to "T",
+ * the assertion below ensures that the size is a multiple of
+ * sizeof(T).
+ */
+#ifdef NDEBUG
+ constexpr
+#endif
+ static WritableBuffer<T> FromVoid(WritableBuffer<void> other) {
+ static_assert(sizeof(T) > 0, "Empty base type");
+#ifndef NDEBUG
+ assert(other.size % sizeof(T) == 0);
+#endif
+ return WritableBuffer<T>(pointer_type(other.data),
+ other.size / sizeof(T));
+ }
- constexpr static WritableBuffer Null() {
- return { nullptr, 0 };
- }
+ constexpr WritableBuffer<void> ToVoid() const {
+ static_assert(sizeof(T) > 0, "Empty base type");
+ return WritableBuffer<void>(data, size * sizeof(T));
+ }
- constexpr bool IsNull() const {
- return data == nullptr;
- }
+ constexpr bool IsNull() const {
+ return data == nullptr;
+ }
- constexpr bool IsEmpty() const {
- return size == 0;
- }
+ constexpr bool IsEmpty() const {
+ return size == 0;
+ }
- constexpr iterator begin() const {
- return data;
- }
+ constexpr iterator begin() const {
+ return data;
+ }
- constexpr iterator end() const {
- return data + size;
- }
+ constexpr iterator end() const {
+ return data + size;
+ }
- constexpr const_iterator cbegin() const {
- return data;
- }
+ constexpr const_iterator cbegin() const {
+ return data;
+ }
- constexpr const_iterator cend() const {
- return data + size;
- }
+ constexpr const_iterator cend() const {
+ return data + size;
+ }
};
#endif
diff --git a/src/util/fifo_buffer.c b/src/util/fifo_buffer.c
deleted file mode 100644
index 162ddf946..000000000
--- a/src/util/fifo_buffer.c
+++ /dev/null
@@ -1,218 +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 "config.h"
-#include "fifo_buffer.h"
-
-#include <glib.h>
-
-#include <assert.h>
-#include <string.h>
-
-struct fifo_buffer {
- size_t size, start, end;
- unsigned char buffer[sizeof(size_t)];
-};
-
-struct fifo_buffer *
-fifo_buffer_new(size_t size)
-{
- struct fifo_buffer *buffer;
-
- assert(size > 0);
-
- buffer = (struct fifo_buffer *)g_malloc(sizeof(*buffer) -
- sizeof(buffer->buffer) + size);
-
- buffer->size = size;
- buffer->start = 0;
- buffer->end = 0;
-
- return buffer;
-}
-
-void
-fifo_buffer_init(struct fifo_buffer *buffer, size_t size)
-{
- buffer->size = size - (sizeof(*buffer) - sizeof(buffer->buffer));
- buffer->start = 0;
- buffer->end = 0;
-}
-
-static void
-fifo_buffer_move(struct fifo_buffer *buffer);
-
-struct fifo_buffer *
-fifo_buffer_realloc(struct fifo_buffer *buffer, size_t new_size)
-{
- if (buffer == NULL)
- return new_size > 0
- ? fifo_buffer_new(new_size)
- : NULL;
-
- /* existing data must fit in new size */
- assert(new_size >= buffer->end - buffer->start);
-
- if (new_size == 0) {
- fifo_buffer_free(buffer);
- return NULL;
- }
-
- /* compress the buffer when we're shrinking and the tail of
- the buffer would exceed the new size */
- if (buffer->end > new_size)
- fifo_buffer_move(buffer);
-
- /* existing data must fit in new size: second check */
- assert(buffer->end <= new_size);
-
- buffer = g_realloc(buffer, sizeof(*buffer) - sizeof(buffer->buffer) +
- new_size);
- buffer->size = new_size;
- return buffer;
-}
-
-void
-fifo_buffer_free(struct fifo_buffer *buffer)
-{
- assert(buffer != NULL);
-
- g_free(buffer);
-}
-
-size_t
-fifo_buffer_capacity(const struct fifo_buffer *buffer)
-{
- assert(buffer != NULL);
-
- return buffer->size;
-}
-
-size_t
-fifo_buffer_available(const struct fifo_buffer *buffer)
-{
- assert(buffer != NULL);
-
- return buffer->end - buffer->start;
-}
-
-void
-fifo_buffer_clear(struct fifo_buffer *buffer)
-{
- assert(buffer != NULL);
-
- buffer->start = 0;
- buffer->end = 0;
-}
-
-const void *
-fifo_buffer_read(const struct fifo_buffer *buffer, size_t *length_r)
-{
- assert(buffer != NULL);
- assert(buffer->end >= buffer->start);
- assert(length_r != NULL);
-
- if (buffer->start == buffer->end)
- /* the buffer is empty */
- return NULL;
-
- *length_r = buffer->end - buffer->start;
- return buffer->buffer + buffer->start;
-}
-
-void
-fifo_buffer_consume(struct fifo_buffer *buffer, size_t length)
-{
- assert(buffer != NULL);
- assert(buffer->end >= buffer->start);
- assert(buffer->start + length <= buffer->end);
-
- buffer->start += length;
-}
-
-/**
- * Move data to the beginning of the buffer, to make room at the end.
- */
-static void
-fifo_buffer_move(struct fifo_buffer *buffer)
-{
- if (buffer->start == 0)
- return;
-
- if (buffer->end > buffer->start)
- memmove(buffer->buffer,
- buffer->buffer + buffer->start,
- buffer->end - buffer->start);
-
- buffer->end -= buffer->start;
- buffer->start = 0;
-}
-
-void *
-fifo_buffer_write(struct fifo_buffer *buffer, size_t *max_length_r)
-{
- assert(buffer != NULL);
- assert(buffer->end <= buffer->size);
- assert(max_length_r != NULL);
-
- if (buffer->end == buffer->size) {
- fifo_buffer_move(buffer);
- if (buffer->end == buffer->size)
- return NULL;
- } else if (buffer->start > 0 && buffer->start == buffer->end) {
- buffer->start = 0;
- buffer->end = 0;
- }
-
- *max_length_r = buffer->size - buffer->end;
- return buffer->buffer + buffer->end;
-}
-
-void
-fifo_buffer_append(struct fifo_buffer *buffer, size_t length)
-{
- assert(buffer != NULL);
- assert(buffer->end >= buffer->start);
- assert(buffer->end + length <= buffer->size);
-
- buffer->end += length;
-}
-
-bool
-fifo_buffer_is_empty(struct fifo_buffer *buffer)
-{
- return buffer->start == buffer->end;
-}
-
-bool
-fifo_buffer_is_full(struct fifo_buffer *buffer)
-{
- return buffer->start == 0 && buffer->end == buffer->size;
-}
diff --git a/src/util/fifo_buffer.h b/src/util/fifo_buffer.h
deleted file mode 100644
index ccea97d86..000000000
--- a/src/util/fifo_buffer.h
+++ /dev/null
@@ -1,164 +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
- *
- * This is a general purpose FIFO buffer library. You may append data
- * at the end, while another instance reads data from the beginning.
- * It is optimized for zero-copy usage: you get pointers to the real
- * buffer, where you may operate on.
- *
- * This library is not thread safe.
- */
-
-#ifndef MPD_FIFO_BUFFER_H
-#define MPD_FIFO_BUFFER_H
-
-#include <stdbool.h>
-#include <stddef.h>
-
-struct fifo_buffer;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Creates a new #fifo_buffer object. Free this object with
- * fifo_buffer_free().
- *
- * @param size the size of the buffer in bytes
- * @return the new #fifo_buffer object
- */
-struct fifo_buffer *
-fifo_buffer_new(size_t size);
-
-void
-fifo_buffer_init(struct fifo_buffer *buffer, size_t size);
-
-/**
- * Change the capacity of the #fifo_buffer, while preserving existing
- * data.
- *
- * @param buffer the old buffer, may be NULL
- * @param new_size the requested new size of the #fifo_buffer; must
- * not be smaller than the data which is stored in the old buffer
- * @return the new buffer, may be NULL if the requested new size is 0
- */
-struct fifo_buffer *
-fifo_buffer_realloc(struct fifo_buffer *buffer, size_t new_size);
-
-/**
- * Frees the resources consumed by this #fifo_buffer object.
- */
-void
-fifo_buffer_free(struct fifo_buffer *buffer);
-
-/**
- * Return the capacity of the buffer, i.e. the size that was passed to
- * fifo_buffer_new().
- */
-size_t
-fifo_buffer_capacity(const struct fifo_buffer *buffer);
-
-/**
- * Return the number of bytes currently stored in the buffer.
- */
-size_t
-fifo_buffer_available(const struct fifo_buffer *buffer);
-
-/**
- * Clears all data currently in this #fifo_buffer object. This does
- * not overwrite the actuall buffer; it just resets the internal
- * pointers.
- */
-void
-fifo_buffer_clear(struct fifo_buffer *buffer);
-
-/**
- * Reads from the beginning of the buffer. To remove consumed data
- * from the buffer, call fifo_buffer_consume().
- *
- * @param buffer the #fifo_buffer object
- * @param length_r the maximum amount to read is returned here
- * @return a pointer to the beginning of the buffer, or NULL if the
- * buffer is empty
- */
-const void *
-fifo_buffer_read(const struct fifo_buffer *buffer, size_t *length_r);
-
-/**
- * Marks data at the beginning of the buffer as "consumed".
- *
- * @param buffer the #fifo_buffer object
- * @param length the number of bytes which were consumed
- */
-void
-fifo_buffer_consume(struct fifo_buffer *buffer, size_t length);
-
-/**
- * Prepares writing to the buffer. This returns a buffer which you
- * can write to. To commit the write operation, call
- * fifo_buffer_append().
- *
- * @param buffer the #fifo_buffer object
- * @param max_length_r the maximum amount to write is returned here
- * @return a pointer to the end of the buffer, or NULL if the buffer
- * is already full
- */
-void *
-fifo_buffer_write(struct fifo_buffer *buffer, size_t *max_length_r);
-
-/**
- * Commits the write operation initiated by fifo_buffer_write().
- *
- * @param buffer the #fifo_buffer object
- * @param length the number of bytes which were written
- */
-void
-fifo_buffer_append(struct fifo_buffer *buffer, size_t length);
-
-/**
- * Checks if the buffer is empty.
- */
-bool
-fifo_buffer_is_empty(struct fifo_buffer *buffer);
-
-/**
- * Checks if the buffer is full.
- */
-bool
-fifo_buffer_is_full(struct fifo_buffer *buffer);
-
-#ifdef __cplusplus
-}
-#endif
-
-#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);
-}