diff options
author | David Robillard <d@drobilla.net> | 2019-03-09 17:15:10 +0100 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2019-03-09 17:15:10 +0100 |
commit | 2058c121a6224263368d584c1cdc05c1819b0721 (patch) | |
tree | c1c3e4043e68788c01c17b8aac402e05ef8def4b | |
parent | 50b5df8e10ecb32b2691dd3871de92539766d451 (diff) | |
download | ingen-2058c121a6224263368d584c1cdc05c1819b0721.tar.gz ingen-2058c121a6224263368d584c1cdc05c1819b0721.tar.bz2 ingen-2058c121a6224263368d584c1cdc05c1819b0721.zip |
Clean up AtomForge
-rw-r--r-- | ingen/AtomForge.hpp | 121 | ||||
-rw-r--r-- | ingen/AtomForgeSink.hpp | 102 | ||||
-rw-r--r-- | ingen/AtomWriter.hpp | 11 | ||||
-rw-r--r-- | src/AtomWriter.cpp | 12 | ||||
-rw-r--r-- | src/Parser.cpp | 21 | ||||
-rw-r--r-- | src/SocketReader.cpp | 21 | ||||
-rw-r--r-- | tests/ingen_test.cpp | 22 |
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 |