diff options
Diffstat (limited to 'ingen')
-rw-r--r-- | ingen/AtomForge.hpp | 121 | ||||
-rw-r--r-- | ingen/AtomForgeSink.hpp | 102 | ||||
-rw-r--r-- | ingen/AtomWriter.hpp | 11 |
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 |