summaryrefslogtreecommitdiffstats
path: root/ingen
diff options
context:
space:
mode:
Diffstat (limited to 'ingen')
-rw-r--r--ingen/AtomForge.hpp121
-rw-r--r--ingen/AtomForgeSink.hpp102
-rw-r--r--ingen/AtomWriter.hpp11
3 files changed, 126 insertions, 108 deletions
diff --git a/ingen/AtomForge.hpp b/ingen/AtomForge.hpp
new file mode 100644
index 00000000..acb24fac
--- /dev/null
+++ b/ingen/AtomForge.hpp
@@ -0,0 +1,121 @@
+/*
+ This file is part of Ingen.
+ Copyright 2007-2017 David Robillard <http://drobilla.net/>
+
+ Ingen is free software: you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free
+ Software Foundation, either version 3 of the License, or any later version.
+
+ Ingen 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 Affero General Public License for details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with Ingen. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef INGEN_ATOMFORGE_HPP
+#define INGEN_ATOMFORGE_HPP
+
+#include "ingen/types.hpp"
+#include "lv2/atom/atom.h"
+#include "lv2/atom/forge.h"
+#include "lv2/atom/util.h"
+#include "sord/sordmm.hpp"
+#include "sratom/sratom.h"
+
+#include <cassert>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+
+namespace ingen {
+
+/// An atom forge that writes to an automatically-resized memory buffer
+class AtomForge : public LV2_Atom_Forge
+{
+public:
+ explicit AtomForge(LV2_URID_Map& map)
+ : _size{0}
+ , _capacity{8 * sizeof(LV2_Atom)}
+ , _sratom{sratom_new(&map)}
+ , _buf{(LV2_Atom*)calloc(8, sizeof(LV2_Atom))}
+ {
+ lv2_atom_forge_init(this, &map);
+ lv2_atom_forge_set_sink(this, c_append, c_deref, this);
+ }
+
+ /// Forge an atom from `node` in `model`
+ void read(Sord::World& world, SordModel* model, const SordNode* node)
+ {
+ sratom_read(_sratom.get(), this, world.c_obj(), model, node);
+ }
+
+ /// Return the top-level atom that has been forged
+ const LV2_Atom* atom() const { return _buf.get(); }
+
+ /// Clear the atom buffer and reset the forge
+ void clear()
+ {
+ lv2_atom_forge_set_sink(this, c_append, c_deref, this);
+ _size = 0;
+ *_buf = {0U, 0U};
+ }
+
+ /// Return the internal atom serialiser
+ Sratom& sratom() { return *_sratom; }
+
+private:
+ struct SratomDeleter { void operator()(Sratom* s) { sratom_free(s); } };
+
+ using AtomPtr = UPtr<LV2_Atom, FreeDeleter<LV2_Atom>>;
+ using SratomPtr = UPtr<Sratom, SratomDeleter>;
+
+ /// Append some data and return a reference to its start
+ intptr_t append(const void* buf, uint32_t len) {
+ // Record offset of the start of this write (+1 to avoid null)
+ const intptr_t ref = _size + 1;
+
+ // Update size and reallocate if necessary
+ if (lv2_atom_pad_size(_size + len) > _capacity) {
+ _capacity = lv2_atom_pad_size(_size + len);
+ _buf = AtomPtr{(LV2_Atom*)realloc(_buf.release(), _capacity)};
+ }
+
+ // Append new data
+ memcpy((uint8_t*)_buf.get() + _size, buf, len);
+ _size += len;
+ return ref;
+ }
+
+ /// Dereference a reference previously returned by append()
+ LV2_Atom* deref(intptr_t ref) {
+ /* Make some assumptions and do unnecessary math to appease
+ -Wcast-align. This is questionable at best, though the forge should
+ only dereference references to aligned atoms. */
+ assert((ref - 1) % sizeof(LV2_Atom) == 0);
+ return (LV2_Atom*)(_buf.get() + (ref - 1) / sizeof(LV2_Atom));
+
+ // Alternatively:
+ // return (LV2_Atom*)((uint8_t*)_buf + ref - 1);
+ }
+
+ static LV2_Atom_Forge_Ref
+ c_append(void* handle, const void* buf, uint32_t len) {
+ return ((AtomForge*)handle)->append(buf, len);
+ }
+
+ static LV2_Atom*
+ c_deref(void* handle, LV2_Atom_Forge_Ref ref) {
+ return ((AtomForge*)handle)->deref(ref);
+ }
+
+ size_t _size; ///< Current atom size
+ size_t _capacity; ///< Allocated size of atom buffer
+ SratomPtr _sratom; ///< Atom serialiser
+ AtomPtr _buf; ///< Atom buffer
+};
+
+} // namespace ingen
+
+#endif // INGEN_ATOMFORGE_HPP
diff --git a/ingen/AtomForgeSink.hpp b/ingen/AtomForgeSink.hpp
deleted file mode 100644
index 04799986..00000000
--- a/ingen/AtomForgeSink.hpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- This file is part of Ingen.
- Copyright 2007-2017 David Robillard <http://drobilla.net/>
-
- Ingen is free software: you can redistribute it and/or modify it under the
- terms of the GNU Affero General Public License as published by the Free
- Software Foundation, either version 3 of the License, or any later version.
-
- Ingen 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 Affero General Public License for details.
-
- You should have received a copy of the GNU Affero General Public License
- along with Ingen. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef INGEN_ATOMFORGESINK_HPP
-#define INGEN_ATOMFORGESINK_HPP
-
-#include "lv2/atom/atom.h"
-#include "lv2/atom/forge.h"
-#include "lv2/atom/util.h"
-
-#include <cassert>
-#include <cstdint>
-#include <cstdlib>
-#include <cstring>
-
-namespace ingen {
-
-/** A resizing sink for LV2_Atom_Forge. */
-class AtomForgeSink
-{
-public:
- explicit AtomForgeSink(LV2_Atom_Forge* forge = nullptr)
- : _capacity(8 * sizeof(LV2_Atom))
- , _size(0)
- , _buf((LV2_Atom*)calloc(8, sizeof(LV2_Atom)))
- {
- if (forge) {
- set_forge_sink(forge);
- }
- }
-
- ~AtomForgeSink() { free(_buf); }
-
- void set_forge_sink(LV2_Atom_Forge* forge) {
- lv2_atom_forge_set_sink(forge, c_append, c_deref, this);
- }
-
- /** Append some data and return a reference to its start. */
- intptr_t append(const void* buf, uint32_t len) {
- // Record offset of the start of this write (+1 to avoid null)
- const intptr_t ref = _size + 1;
-
- // Update size and reallocate if necessary
- if (lv2_atom_pad_size(_size + len) > _capacity) {
- _capacity = lv2_atom_pad_size(_size + len);
- _buf = (LV2_Atom*)realloc(_buf, _capacity);
- }
-
- // Append new data
- memcpy((uint8_t*)_buf + _size, buf, len);
- _size += len;
- return ref;
- }
-
- /** Dereference a reference previously returned by append. */
- LV2_Atom* deref(intptr_t ref) {
- /* Make some assumptions and do unnecessary math to appease
- -Wcast-align. This is questionable at best, though the forge should
- only dereference references to aligned atoms. */
- assert((ref - 1) % sizeof(LV2_Atom) == 0);
- return (LV2_Atom*)(_buf + (ref - 1) / sizeof(LV2_Atom));
-
- // Alternatively:
- // return (LV2_Atom*)((uint8_t*)_buf + ref - 1);
- }
-
- const LV2_Atom* atom() const { return _buf; }
-
- void clear() { _buf->type = 0; _buf->size = 0; _size = 0; }
-
- static LV2_Atom_Forge_Ref
- c_append(void* handle, const void* buf, uint32_t len) {
- return ((AtomForgeSink*)handle)->append(buf, len);
- }
-
- static LV2_Atom*
- c_deref(void* handle, LV2_Atom_Forge_Ref ref) {
- return ((AtomForgeSink*)handle)->deref(ref);
- }
-
-private:
- size_t _capacity;
- size_t _size;
- LV2_Atom* _buf;
-};
-
-} // namespace ingen
-
-#endif // INGEN_ATOMFORGESINK_HPP
diff --git a/ingen/AtomWriter.hpp b/ingen/AtomWriter.hpp
index ee27436d..6c1786f4 100644
--- a/ingen/AtomWriter.hpp
+++ b/ingen/AtomWriter.hpp
@@ -17,7 +17,7 @@
#ifndef INGEN_ATOMWRITER_HPP
#define INGEN_ATOMWRITER_HPP
-#include "ingen/AtomForgeSink.hpp"
+#include "ingen/AtomForge.hpp"
#include "ingen/Interface.hpp"
#include "ingen/Message.hpp"
#include "ingen/Properties.hpp"
@@ -74,11 +74,10 @@ private:
void finish_msg();
- URIMap& _map;
- URIs& _uris;
- AtomSink& _sink;
- AtomForgeSink _out;
- LV2_Atom_Forge _forge;
+ URIMap& _map;
+ URIs& _uris;
+ AtomSink& _sink;
+ AtomForge _forge;
};
} // namespace ingen