summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2019-03-09 17:15:10 +0100
committerDavid Robillard <d@drobilla.net>2019-03-09 17:15:10 +0100
commit2058c121a6224263368d584c1cdc05c1819b0721 (patch)
treec1c3e4043e68788c01c17b8aac402e05ef8def4b
parent50b5df8e10ecb32b2691dd3871de92539766d451 (diff)
downloadingen-2058c121a6224263368d584c1cdc05c1819b0721.tar.gz
ingen-2058c121a6224263368d584c1cdc05c1819b0721.tar.bz2
ingen-2058c121a6224263368d584c1cdc05c1819b0721.zip
Clean up AtomForge
-rw-r--r--ingen/AtomForge.hpp121
-rw-r--r--ingen/AtomForgeSink.hpp102
-rw-r--r--ingen/AtomWriter.hpp11
-rw-r--r--src/AtomWriter.cpp12
-rw-r--r--src/Parser.cpp21
-rw-r--r--src/SocketReader.cpp21
-rw-r--r--tests/ingen_test.cpp22
7 files changed, 152 insertions, 158 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
diff --git a/src/AtomWriter.cpp b/src/AtomWriter.cpp
index d7982cb0..27f224fc 100644
--- a/src/AtomWriter.cpp
+++ b/src/AtomWriter.cpp
@@ -47,10 +47,11 @@
* manipulating data in this model which resemble HTTP methods.
*/
+#include "ingen/AtomWriter.hpp"
+
#include "ingen/Atom.hpp"
-#include "ingen/AtomForgeSink.hpp"
+#include "ingen/AtomForge.hpp"
#include "ingen/AtomSink.hpp"
-#include "ingen/AtomWriter.hpp"
#include "ingen/Message.hpp"
#include "ingen/Properties.hpp"
#include "ingen/Resource.hpp"
@@ -77,17 +78,16 @@ AtomWriter::AtomWriter(URIMap& map, URIs& uris, AtomSink& sink)
: _map(map)
, _uris(uris)
, _sink(sink)
+ , _forge(map.urid_map_feature()->urid_map)
{
- lv2_atom_forge_init(&_forge, &map.urid_map_feature()->urid_map);
- _out.set_forge_sink(&_forge);
}
void
AtomWriter::finish_msg()
{
assert(!_forge.stack);
- _sink.write(_out.atom());
- _out.clear();
+ _sink.write(_forge.atom());
+ _forge.clear();
}
void
diff --git a/src/Parser.cpp b/src/Parser.cpp
index cda039eb..ff416106 100644
--- a/src/Parser.cpp
+++ b/src/Parser.cpp
@@ -17,7 +17,7 @@
#include "ingen/Parser.hpp"
#include "ingen/Atom.hpp"
-#include "ingen/AtomForgeSink.hpp"
+#include "ingen/AtomForge.hpp"
#include "ingen/Forge.hpp"
#include "ingen/Interface.hpp"
#include "ingen/Log.hpp"
@@ -38,7 +38,6 @@
#include "serd/serd.h"
#include "sord/sord.h"
#include "sord/sordmm.hpp"
-#include "sratom/sratom.h"
#include <cassert>
#include <cstdint>
@@ -111,22 +110,16 @@ get_properties(ingen::World& world,
Resource::Graph ctx,
boost::optional<Properties> data = {})
{
- LV2_URID_Map* map = &world.uri_map().urid_map_feature()->urid_map;
- Sratom* sratom = sratom_new(map);
-
- LV2_Atom_Forge forge;
- lv2_atom_forge_init(&forge, map);
-
- AtomForgeSink out(&forge);
+ AtomForge forge(world.uri_map().urid_map_feature()->urid_map);
const Sord::Node nil;
Properties props;
for (Sord::Iter i = model.find(subject, nil, nil); !i.end(); ++i) {
if (!skip_property(world.uris(), i.get_predicate())) {
- out.clear();
- sratom_read(sratom, &forge, world.rdf_world()->c_obj(),
- model.c_obj(), i.get_object().c_obj());
- const LV2_Atom* atom = out.atom();
+ forge.clear();
+ forge.read(
+ *world.rdf_world(), model.c_obj(), i.get_object().c_obj());
+ const LV2_Atom* atom = forge.atom();
Atom atomm;
atomm = world.forge().alloc(
atom->size, atom->type, LV2_ATOM_BODY_CONST(atom));
@@ -134,8 +127,6 @@ get_properties(ingen::World& world,
}
}
- sratom_free(sratom);
-
// Replace any properties given in `data`
if (data) {
for (const auto& prop : *data) {
diff --git a/src/SocketReader.cpp b/src/SocketReader.cpp
index 21859339..d2fb3677 100644
--- a/src/SocketReader.cpp
+++ b/src/SocketReader.cpp
@@ -16,7 +16,7 @@
#include "ingen/SocketReader.hpp"
-#include "ingen/AtomForgeSink.hpp"
+#include "ingen/AtomForge.hpp"
#include "ingen/AtomReader.hpp"
#include "ingen/Log.hpp"
#include "ingen/URIMap.hpp"
@@ -25,7 +25,6 @@
#include "lv2/urid/urid.h"
#include "raul/Socket.hpp"
#include "sord/sordmm.hpp"
-#include "sratom/sratom.h"
#include <cerrno>
#include <cstdint>
@@ -97,7 +96,7 @@ void
SocketReader::run()
{
Sord::World* world = _world.rdf_world();
- LV2_URID_Map* map = &_world.uri_map().urid_map_feature()->urid_map;
+ LV2_URID_Map& map = _world.uri_map().urid_map_feature()->urid_map;
// Open socket as a FILE for reading directly with serd
std::unique_ptr<FILE, decltype(&fclose)> f{fdopen(_socket->fd(), "r"),
@@ -110,15 +109,10 @@ SocketReader::run()
return;
}
- // Set up sratom and a forge to build LV2 atoms from model
- Sratom* sratom = sratom_new(map);
- LV2_Atom_Forge forge;
- lv2_atom_forge_init(&forge, map);
-
- AtomForgeSink buffer(&forge);
-
+ // Set up a forge to build LV2 atoms from model
SordNode* base_uri = nullptr;
SordModel* model = nullptr;
+ AtomForge forge(map);
{
// Lock RDF world
std::lock_guard<std::mutex> lock(_world.rdf_mutex());
@@ -179,13 +173,13 @@ SocketReader::run()
}
// Build an LV2_Atom at chunk.buf from the message
- sratom_read(sratom, &forge, world->c_obj(), model, _msg_node);
+ forge.read(*world, model, _msg_node);
// Call _iface methods based on atom content
- ar.write(buffer.atom());
+ ar.write(forge.atom());
// Reset everything for the next iteration
- buffer.clear();
+ forge.clear();
sord_node_free(world->c_obj(), _msg_node);
_msg_node = nullptr;
}
@@ -197,7 +191,6 @@ SocketReader::run()
f.reset();
sord_inserter_free(_inserter);
serd_reader_end_stream(reader);
- sratom_free(sratom);
serd_reader_free(reader);
sord_free(model);
_socket.reset();
diff --git a/tests/ingen_test.cpp b/tests/ingen_test.cpp
index fc114fb1..319a027c 100644
--- a/tests/ingen_test.cpp
+++ b/tests/ingen_test.cpp
@@ -18,7 +18,7 @@
#include "ingen_config.h"
#include "ingen/Atom.hpp"
-#include "ingen/AtomForgeSink.hpp"
+#include "ingen/AtomForge.hpp"
#include "ingen/AtomReader.hpp"
#include "ingen/AtomWriter.hpp"
#include "ingen/Configuration.hpp"
@@ -116,15 +116,9 @@ main(int argc, char** argv)
// Read commands
- LV2_URID_Map* map = &world->uri_map().urid_map_feature()->urid_map;
- Sratom* sratom = sratom_new(map);
+ AtomForge forge(world->uri_map().urid_map_feature()->urid_map);
- sratom_set_object_mode(sratom, SRATOM_OBJECT_MODE_BLANK_SUBJECT);
-
- LV2_Atom_Forge forge;
- lv2_atom_forge_init(&forge, map);
-
- AtomForgeSink out(&forge);
+ sratom_set_object_mode(&forge.sratom(), SRATOM_OBJECT_MODE_BLANK_SUBJECT);
// AtomReader to read commands from a file and send them to engine
AtomReader atom_reader(world->uri_map(),
@@ -157,12 +151,11 @@ main(int argc, char** argv)
break;
}
- out.clear();
- sratom_read(sratom, &forge, world->rdf_world()->c_obj(),
- cmds->c_obj(), subject.c_obj());
+ forge.clear();
+ forge.read(*world->rdf_world(), cmds->c_obj(), subject.c_obj());
#if 0
- const LV2_Atom* atom = out.atom();
+ const LV2_Atom* atom = forge.atom();
cerr << "READ " << atom->size << " BYTES" << endl;
cerr << sratom_to_turtle(
sratom,
@@ -171,7 +164,7 @@ main(int argc, char** argv)
nullptr, nullptr, atom->type, atom->size, LV2_ATOM_BODY(atom)) << endl;
#endif
- if (!atom_reader.write(out.atom(), n_events + 1)) {
+ if (!atom_reader.write(forge.atom(), n_events + 1)) {
return EXIT_FAILURE;
}
@@ -212,7 +205,6 @@ main(int argc, char** argv)
world->serialiser()->write_bundle(r->second, URI(redo_path));
serd_env_free(env);
- sratom_free(sratom);
serd_node_free(&cmds_file_uri);
// Shut down