diff options
Diffstat (limited to 'src')
41 files changed, 697 insertions, 889 deletions
diff --git a/src/AtomWriter.cpp b/src/AtomWriter.cpp index 27f224fc..e2c0f252 100644 --- a/src/AtomWriter.cpp +++ b/src/AtomWriter.cpp @@ -74,11 +74,14 @@ namespace ingen { -AtomWriter::AtomWriter(URIMap& map, URIs& uris, AtomSink& sink) - : _map(map) - , _uris(uris) - , _sink(sink) - , _forge(map.urid_map_feature()->urid_map) +AtomWriter::AtomWriter(serd::World& world, + URIMap& map, + URIs& uris, + AtomSink& sink) + : _map(map) + , _uris(uris) + , _sink(sink) + , _forge(world, map.urid_map_feature()->urid_map) { } @@ -135,7 +138,7 @@ AtomWriter::operator()(const BundleEnd& message) void AtomWriter::forge_uri(const URI& uri) { - if (serd_uri_string_has_scheme((const uint8_t*)uri.c_str())) { + if (serd_uri_string_has_scheme(uri.c_str())) { lv2_atom_forge_urid(&_forge, _map.map_uri(uri.c_str())); } else { lv2_atom_forge_uri(&_forge, uri.c_str(), uri.length()); diff --git a/src/Configuration.cpp b/src/Configuration.cpp index 5178e97a..611d949b 100644 --- a/src/Configuration.cpp +++ b/src/Configuration.cpp @@ -22,10 +22,8 @@ #include "ingen/ingen.h" #include "ingen/runtime_paths.hpp" #include "lv2/urid/urid.h" -#include "serd/serd.h" -#include "sord/sord.h" -#include "sord/sordmm.hpp" -#include "sratom/sratom.h" +#include "serd/serd.hpp" +#include "sratom/sratom.hpp" #include <algorithm> #include <cassert> @@ -33,6 +31,7 @@ #include <cstdint> #include <cstdlib> #include <cstring> +#include <fstream> #include <memory> #include <thread> #include <utility> @@ -226,43 +225,40 @@ Configuration::parse(int argc, char** argv) } bool -Configuration::load(const FilePath& path) +Configuration::load(serd::World& world, const FilePath& path) { if (!filesystem::exists(path)) { return false; } - SerdNode node = serd_node_new_file_uri( - (const uint8_t*)path.c_str(), nullptr, nullptr, true); - const std::string uri((const char*)node.buf); - - Sord::World world; - Sord::Model model(world, uri, SORD_SPO, false); - SerdEnv* env = serd_env_new(&node); - model.load_file(env, SERD_TURTLE, uri, uri); - - Sord::Node nodemm(world, Sord::Node::URI, (const char*)node.buf); - Sord::Node nil; - for (Sord::Iter i = model.find(nodemm, nil, nil); !i.end(); ++i) { - const Sord::Node& pred = i.get_predicate(); - const Sord::Node& obj = i.get_object(); - if (pred.to_string().substr(0, sizeof(INGEN_NS) - 1) == INGEN_NS) { - const std::string key = pred.to_string().substr(sizeof(INGEN_NS) - 1); - const Keys::iterator k = _keys.find(key); - if (k != _keys.end() && obj.type() == Sord::Node::LITERAL) { + const serd::Node uri(serd::make_file_uri(path.c_str(), nullptr)); + serd::Env env(uri); + serd::Model model(world, serd::ModelFlag::index_SPO); + serd::Inserter inserter(model, env); + serd::Reader reader(world, serd::Syntax::Turtle, {}, inserter.sink(), 4096); + reader.start_file(uri); + reader.read_document(); + reader.finish(); + + for (const auto& s : model.range(uri, {}, {})) { + const auto& pred = s.predicate(); + const auto& obj = s.object(); + if (pred.str().substr(0, sizeof(INGEN_NS) - 1) == INGEN_NS) { + const auto key = pred.str().substr(sizeof(INGEN_NS) - 1); + const Keys::iterator k = _keys.find(key.str()); + if (k != _keys.end() && obj.type() == serd::NodeType::literal) { set_value_from_string(_options.find(k->second)->second, - obj.to_string()); + std::string(obj)); } } } - serd_node_free(&node); - serd_env_free(env); return true; } FilePath -Configuration::save(URIMap& uri_map, +Configuration::save(serd::World& world, + URIMap& uri_map, const std::string& app, const FilePath& filename, unsigned scopes) @@ -281,41 +277,33 @@ Configuration::save(URIMap& uri_map, } // Attempt to open file for writing - std::unique_ptr<FILE, decltype(&fclose)> file{fopen(path.c_str(), "w"), - &fclose}; - if (!file) { + std::ofstream file(path); + if (!file.good()) { throw FileError(fmt("Failed to open file %1% (%2%)", path, strerror(errno))); } // Use the file's URI as the base URI - SerdURI base_uri; - SerdNode base = serd_node_new_file_uri( - (const uint8_t*)path.c_str(), nullptr, &base_uri, true); + serd::Node base = serd::make_file_uri(path.c_str()); // Create environment with ingen prefix - SerdEnv* env = serd_env_new(&base); - serd_env_set_prefix_from_strings( - env, (const uint8_t*)"ingen", (const uint8_t*)INGEN_NS); + serd::Env env(base); + env.set_prefix("ingen", INGEN_NS); // Create Turtle writer - SerdWriter* writer = serd_writer_new( - SERD_TURTLE, - (SerdStyle)(SERD_STYLE_RESOLVED|SERD_STYLE_ABBREVIATED), - env, - &base_uri, - serd_file_sink, - file.get()); + serd::Writer writer(world, + serd::Syntax::Turtle, + {}, + env, + file); // Write a prefix directive for each prefix in the environment - serd_env_foreach(env, (SerdPrefixSink)serd_writer_set_prefix, writer); + env.write_prefixes(writer.sink()); // Create an atom serialiser and connect it to the Turtle writer - Sratom* sratom = sratom_new(&uri_map.urid_map_feature()->urid_map); - sratom_set_pretty_numbers(sratom, true); - sratom_set_sink(sratom, (const char*)base.buf, - (SerdStatementSink)serd_writer_write_statement, nullptr, - writer); + sratom::Streamer streamer{world, + uri_map.urid_map_feature()->urid_map, + uri_map.urid_unmap_feature()->urid_unmap}; // Write a statement for each valid option for (const auto& o : _options) { @@ -327,35 +315,31 @@ Configuration::save(URIMap& uri_map, } const std::string key(std::string("ingen:") + o.second.key); - SerdNode pred = serd_node_from_string( - SERD_CURIE, (const uint8_t*)key.c_str()); - sratom_write(sratom, &uri_map.urid_unmap_feature()->urid_unmap, 0, - &base, &pred, value.type(), value.size(), value.get_body()); + const serd::Node pred = serd::make_curie(key); + streamer.write( + writer.sink(), base, pred, *value.atom(), sratom::Flag::pretty_numbers); } - sratom_free(sratom); - serd_writer_free(writer); - serd_env_free(env); - serd_node_free(&base); - return path; } std::list<FilePath> -Configuration::load_default(const std::string& app, const FilePath& filename) +Configuration::load_default(serd::World& world, + const std::string& app, + const FilePath& filename) { std::list<FilePath> loaded; const std::vector<FilePath> dirs = system_config_dirs(); for (const auto& d : dirs) { const FilePath path = d / app / filename; - if (load(path)) { + if (load(world, path)) { loaded.push_back(path); } } const FilePath path = user_config_dir() / app / filename; - if (load(path)) { + if (load(world, path)) { loaded.push_back(path); } diff --git a/src/FilePath.cpp b/src/FilePath.cpp index d16c133c..33b1b937 100644 --- a/src/FilePath.cpp +++ b/src/FilePath.cpp @@ -89,7 +89,7 @@ FilePath::operator+=(value_type chr) } FilePath& -FilePath::operator+=(boost::basic_string_view<value_type> sv) +FilePath::operator+=(serd::StringView sv) { _str.append(sv.data(), sv.size()); return *this; diff --git a/src/Forge.cpp b/src/Forge.cpp index cc1b12c8..d9390e08 100644 --- a/src/Forge.cpp +++ b/src/Forge.cpp @@ -35,7 +35,7 @@ Forge::Forge(URIMap& map) Atom Forge::make_urid(const ingen::URI& u) { - const LV2_URID urid = _map.map_uri(u.string()); + const LV2_URID urid = _map.map_uri(u.c_str()); return Atom(sizeof(int32_t), URID, &urid); } diff --git a/src/Parser.cpp b/src/Parser.cpp index 5cc1dedd..936f1b9f 100644 --- a/src/Parser.cpp +++ b/src/Parser.cpp @@ -16,6 +16,9 @@ #include "ingen/Parser.hpp" +#include <boost/optional/optional.hpp> +#include <boost/optional/optional_io.hpp> + #include "ingen/Atom.hpp" #include "ingen/AtomForge.hpp" #include "ingen/Forge.hpp" @@ -35,9 +38,7 @@ #include "lv2/urid/urid.h" #include "raul/Path.hpp" #include "raul/Symbol.hpp" -#include "serd/serd.h" -#include "sord/sord.h" -#include "sord/sordmm.hpp" +#include "serd/serd.hpp" #include <cassert> #include <cstdint> @@ -52,36 +53,43 @@ namespace ingen { +static void +load_file(serd::World& world, + serd::Model& model, + serd::Env& env, + const URI& file_uri) +{ + serd::Inserter inserter(model, env); + serd::Reader reader(world, serd::Syntax::Turtle, {}, inserter.sink(), 4096); + + reader.start_file(file_uri.str()); + reader.read_document(); + reader.finish(); +} + std::set<Parser::ResourceRecord> -Parser::find_resources(Sord::World& world, - const URI& manifest_uri, - const URI& type_uri) +Parser::find_resources(const URI& manifest_uri, const URI& type_uri) { - const Sord::URI base (world, manifest_uri.string()); - const Sord::URI type (world, type_uri.string()); - const Sord::URI rdf_type (world, NS_RDF "type"); - const Sord::URI rdfs_seeAlso(world, NS_RDFS "seeAlso"); - const Sord::Node nil; + const auto rdf_type = serd::make_uri(NS_RDF "type"); + const auto rdfs_seeAlso = serd::make_uri(NS_RDFS "seeAlso"); + + serd::World world; + serd::Env env{serd::Node(manifest_uri)}; + serd::Model model{world, + serd::ModelFlag::index_SPO | serd::ModelFlag::index_OPS}; - SerdEnv* env = serd_env_new(sord_node_to_serd_node(base.c_obj())); - Sord::Model model(world, manifest_uri.string()); - model.load_file(env, SERD_TURTLE, manifest_uri.string()); + load_file(world, model, env, manifest_uri); std::set<ResourceRecord> resources; - for (Sord::Iter i = model.find(nil, rdf_type, type); !i.end(); ++i) { - const Sord::Node resource = i.get_subject(); - const std::string resource_uri = resource.to_c_string(); - Sord::Iter f = model.find(resource, rdfs_seeAlso, nil); - std::string file_path; - if (!f.end()) { - uint8_t* p = serd_file_uri_parse(f.get_object().to_u_string(), nullptr); - file_path = (const char*)p; - serd_free(p); - } + for (const auto& s : model.range({}, rdf_type, type_uri)) { + const auto& resource = s.subject(); + const auto f = model.find(resource, rdfs_seeAlso, {}); + const FilePath file_path = + ((f != model.end() ? serd::file_uri_parse((*f).object().str()) + : "")); resources.insert(ResourceRecord(resource, file_path)); } - serd_env_free(env); return resources; } @@ -89,13 +97,14 @@ static boost::optional<Raul::Path> get_path(const URI& base, const URI& uri) { const URI relative = uri.make_relative(base); - const std::string uri_str = "/" + relative.string(); + const std::string uri_str = relative.string(); + // assert(Raul::Path::is_valid(uri_str)); return Raul::Path::is_valid(uri_str) ? Raul::Path(uri_str) : boost::optional<Raul::Path>(); } static bool -skip_property(ingen::URIs& uris, const Sord::Node& predicate) +skip_property(ingen::URIs& uris, const serd::Node& predicate) { return (predicate == INGEN__file || predicate == uris.ingen_arc || @@ -105,25 +114,20 @@ skip_property(ingen::URIs& uris, const Sord::Node& predicate) static Properties get_properties(ingen::World& world, - Sord::Model& model, - const Sord::Node& subject, + serd::Model& model, + const serd::Node& subject, Resource::Graph ctx, const boost::optional<Properties>& data = {}) { - 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())) { - 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)); - props.emplace(i.get_predicate(), Property(atomm, ctx)); + AtomForge forge(world.rdf_world(), + world.uri_map().urid_map_feature()->urid_map); + + Properties props; + for (const auto& s : model.range(subject, {}, {})) { + if (!skip_property(world.uris(), s.predicate())) { + auto atom = forge.read(model, s.object()); + props.emplace(s.predicate(), + Property(world.forge().alloc(atom), ctx)); } } @@ -151,8 +155,8 @@ using PortRecord = std::pair<Raul::Path, Properties>; static boost::optional<PortRecord> get_port(ingen::World& world, - Sord::Model& model, - const Sord::Node& subject, + serd::Model& model, + const serd::Node& subject, Resource::Graph ctx, const Raul::Path& parent, uint32_t* index) @@ -180,8 +184,8 @@ get_port(ingen::World& world, if (s != props.end() && s->second.type() == world.forge().String) { sym = s->second.ptr<char>(); } else { - const std::string subject_str = subject.to_string(); - const size_t last_slash = subject_str.find_last_of('/'); + const std::string subject_str{subject.str()}; + const size_t last_slash{subject_str.find_last_of('/')}; sym = ((last_slash == std::string::npos) ? subject_str @@ -204,9 +208,8 @@ static boost::optional<Raul::Path> parse( World& world, Interface& target, - Sord::Model& model, + serd::Model& model, const URI& base_uri, - Sord::Node& subject, const boost::optional<Raul::Path>& parent = boost::optional<Raul::Path>(), const boost::optional<Raul::Symbol>& symbol = boost::optional<Raul::Symbol>(), const boost::optional<Properties>& data = boost::optional<Properties>()); @@ -215,9 +218,9 @@ static boost::optional<Raul::Path> parse_graph( World& world, Interface& target, - Sord::Model& model, + serd::Model& model, const URI& base_uri, - const Sord::Node& subject, + const serd::Node& subject, Resource::Graph ctx, const boost::optional<Raul::Path>& parent = boost::optional<Raul::Path>(), const boost::optional<Raul::Symbol>& symbol = boost::optional<Raul::Symbol>(), @@ -227,9 +230,9 @@ static boost::optional<Raul::Path> parse_block( World& world, Interface& target, - Sord::Model& model, + serd::Model& model, const URI& base_uri, - const Sord::Node& subject, + const serd::Node& subject, const Raul::Path& path, const boost::optional<Properties>& data = boost::optional<Properties>()); @@ -237,70 +240,58 @@ static bool parse_arcs( World& world, Interface& target, - Sord::Model& model, + serd::Model& model, const URI& base_uri, - const Sord::Node& subject, + const serd::Node& subject, const Raul::Path& graph); static boost::optional<Raul::Path> parse_block(ingen::World& world, ingen::Interface& target, - Sord::Model& model, + serd::Model& model, const URI& base_uri, - const Sord::Node& subject, + const serd::Node& subject, const Raul::Path& path, const boost::optional<Properties>& data) { const URIs& uris = world.uris(); // Try lv2:prototype and old ingen:prototype for backwards compatibility - const Sord::URI prototype_predicates[] = { - Sord::URI(*world.rdf_world(), uris.lv2_prototype), - Sord::URI(*world.rdf_world(), uris.ingen_prototype) - }; + const serd::Node prototype_predicates[] = {uris.lv2_prototype, + uris.ingen_prototype}; // Get prototype - Sord::Node prototype; - for (const Sord::URI& pred : prototype_predicates) { - prototype = model.get(subject, pred, Sord::Node()); - if (prototype.is_valid()) { + serd::Optional<serd::NodeView> prototype; + for (const auto& pred : prototype_predicates) { + prototype = model.get(subject, pred, {}); + if (prototype) { break; } } - if (!prototype.is_valid()) { - world.log().error("Block %1% (%2%) missing mandatory lv2:prototype\n", - subject, path); + if (!prototype) { + world.log().error( + fmt("Block %1% (%2%) missing mandatory lv2:prototype\n", + subject, path)); return boost::optional<Raul::Path>(); } - const auto* type_uri = (const uint8_t*)prototype.to_c_string(); - if (!serd_uri_string_has_scheme(type_uri) || - !strncmp((const char*)type_uri, "file:", 5)) { + const char* type_uri = prototype->c_str(); + if (!serd_uri_string_has_scheme(type_uri) || !strncmp(type_uri, "file:", 5)) { // Prototype is a file, subgraph - SerdURI base_uri_parts; - serd_uri_parse((const uint8_t*)base_uri.c_str(), &base_uri_parts); - - SerdURI ignored; - SerdNode sub_uri = serd_node_new_uri_from_string( - type_uri, - &base_uri_parts, - &ignored); - - const std::string sub_uri_str = (const char*)sub_uri.buf; - const std::string sub_file = sub_uri_str + "/main.ttl"; + serd::Node sub_uri = serd::make_relative_uri(type_uri, base_uri); - const SerdNode sub_base = serd_node_from_string( - SERD_URI, (const uint8_t*)sub_file.c_str()); + const URI sub_file{sub_uri.str().str() + "/main.ttl"}; + const serd::Node sub_base = serd::make_uri(sub_file.c_str()); - Sord::Model sub_model(*world.rdf_world(), sub_file); - SerdEnv* env = serd_env_new(&sub_base); - sub_model.load_file(env, SERD_TURTLE, sub_file); - serd_env_free(env); + serd::Model sub_model(world.rdf_world(), + serd::ModelFlag::index_SPO | + serd::ModelFlag::index_OPS); + serd::Env env(sub_base); + load_file(world.rdf_world(), sub_model, env, sub_file); - Sord::URI sub_node(*world.rdf_world(), sub_file); parse_graph(world, target, sub_model, sub_base, - sub_node, Resource::Graph::INTERNAL, + sub_uri, Resource::Graph::INTERNAL, path.parent(), Raul::Symbol(path.symbol()), data); parse_graph(world, target, model, base_uri, @@ -319,9 +310,9 @@ parse_block(ingen::World& world, static boost::optional<Raul::Path> parse_graph(ingen::World& world, ingen::Interface& target, - Sord::Model& model, + serd::Model& model, const URI& base_uri, - const Sord::Node& subject, + const serd::Node& subject, Resource::Graph ctx, const boost::optional<Raul::Path>& parent, const boost::optional<Raul::Symbol>& symbol, @@ -329,11 +320,9 @@ parse_graph(ingen::World& world, { const URIs& uris = world.uris(); - const Sord::URI ingen_block(*world.rdf_world(), uris.ingen_block); - const Sord::URI lv2_port(*world.rdf_world(), LV2_CORE__port); + const serd::Node lv2_port = serd::make_uri(LV2_CORE__port); - const Sord::Node& graph = subject; - const Sord::Node nil; + const serd::Node& graph = subject; // Build graph path and symbol Raul::Path graph_path; @@ -352,8 +341,8 @@ parse_graph(ingen::World& world, // For each port on this graph using PortRecords = std::map<uint32_t, PortRecord>; PortRecords ports; - for (Sord::Iter p = model.find(graph, lv2_port, nil); !p.end(); ++p) { - Sord::Node port = p.get_object(); + for (const auto& s : model.range(graph, lv2_port, {})) { + const auto& port = s.object(); // Get all properties uint32_t index = 0; @@ -385,9 +374,9 @@ parse_graph(ingen::World& world, } // For each block in this graph - for (Sord::Iter n = model.find(subject, ingen_block, nil); !n.end(); ++n) { - Sord::Node node = n.get_object(); - URI node_uri = node; + for (const auto& b : model.range(subject, uris.ingen_block, {})) { + const auto& node = b.object(); + URI node_uri = node; assert(!node_uri.path().empty() && node_uri.path() != "/"); const Raul::Path block_path = graph_path.child( Raul::Symbol(FilePath(node_uri.path()).stem().string())); @@ -397,13 +386,12 @@ parse_graph(ingen::World& world, boost::optional<Properties>()); // For each port on this block - for (Sord::Iter p = model.find(node, lv2_port, nil); !p.end(); ++p) { - Sord::Node port = p.get_object(); + for (const auto& p : model.range(node, lv2_port, {})) { + const auto& port = p.object(); Resource::Graph subctx = Resource::Graph::DEFAULT; - if (!model.find(node, - Sord::URI(*world.rdf_world(), uris.rdf_type), - Sord::URI(*world.rdf_world(), uris.ingen_Graph)).end()) { + if (model.find(node, uris.rdf_type, uris.ingen_Graph) == + model.end()) { subctx = Resource::Graph::EXTERNAL; } @@ -431,50 +419,38 @@ parse_graph(ingen::World& world, static bool parse_arc(ingen::World& world, ingen::Interface& target, - Sord::Model& model, + serd::Model& model, const URI& base_uri, - const Sord::Node& subject, + const serd::Node& subject, const Raul::Path& graph) { const URIs& uris = world.uris(); - const Sord::URI ingen_tail(*world.rdf_world(), uris.ingen_tail); - const Sord::URI ingen_head(*world.rdf_world(), uris.ingen_head); - const Sord::Node nil; + const auto& tail = model.get(subject, uris.ingen_tail, {}); + const auto& head = model.get(subject, uris.ingen_head, {}); - Sord::Iter t = model.find(subject, ingen_tail, nil); - Sord::Iter h = model.find(subject, ingen_head, nil); - - if (t.end()) { + if (!tail) { world.log().error("Arc has no tail\n"); return false; - } else if (h.end()) { + } else if (!head) { world.log().error("Arc has no head\n"); return false; } const boost::optional<Raul::Path> tail_path = get_path( - base_uri, t.get_object()); + base_uri, *tail); if (!tail_path) { world.log().error("Arc tail has invalid URI\n"); return false; } const boost::optional<Raul::Path> head_path = get_path( - base_uri, h.get_object()); + base_uri, *head); if (!head_path) { world.log().error("Arc head has invalid URI\n"); return false; } - if (!(++t).end()) { - world.log().error("Arc has multiple tails\n"); - return false; - } else if (!(++h).end()) { - world.log().error("Arc has multiple heads\n"); - return false; - } - target.connect(graph.child(*tail_path), graph.child(*head_path)); return true; @@ -483,16 +459,13 @@ parse_arc(ingen::World& world, static bool parse_arcs(ingen::World& world, ingen::Interface& target, - Sord::Model& model, + serd::Model& model, const URI& base_uri, - const Sord::Node& subject, + const serd::Node& subject, const Raul::Path& graph) { - const Sord::URI ingen_arc(*world.rdf_world(), world.uris().ingen_arc); - const Sord::Node nil; - - for (Sord::Iter i = model.find(subject, ingen_arc, nil); !i.end(); ++i) { - parse_arc(world, target, model, base_uri, i.get_object(), graph); + for (const auto& s : model.range(subject, world.uris().ingen_arc, {})) { + parse_arc(world, target, model, base_uri, s.object(), graph); } return true; @@ -501,72 +474,56 @@ parse_arcs(ingen::World& world, static boost::optional<Raul::Path> parse(ingen::World& world, ingen::Interface& target, - Sord::Model& model, + serd::Model& model, const URI& base_uri, - Sord::Node& subject, const boost::optional<Raul::Path>& parent, const boost::optional<Raul::Symbol>& symbol, const boost::optional<Properties>& data) { - const URIs& uris = world.uris(); + using Subjects = std::map<serd::Node, std::set<serd::Node>>; - const Sord::URI graph_class (*world.rdf_world(), uris.ingen_Graph); - const Sord::URI block_class (*world.rdf_world(), uris.ingen_Block); - const Sord::URI arc_class (*world.rdf_world(), uris.ingen_Arc); - const Sord::URI internal_class(*world.rdf_world(), uris.ingen_Internal); - const Sord::URI in_port_class (*world.rdf_world(), LV2_CORE__InputPort); - const Sord::URI out_port_class(*world.rdf_world(), LV2_CORE__OutputPort); - const Sord::URI lv2_class (*world.rdf_world(), LV2_CORE__Plugin); - const Sord::URI rdf_type (*world.rdf_world(), uris.rdf_type); - const Sord::Node nil; - - // Parse explicit subject graph - if (subject.is_valid()) { - return parse_graph(world, target, model, base_uri, - subject, Resource::Graph::INTERNAL, - parent, symbol, data); - } + const URIs& uris = world.uris(); // Get all subjects and their types (?subject a ?type) - using Subjects = std::map< Sord::Node, std::set<Sord::Node> >; Subjects subjects; - for (Sord::Iter i = model.find(subject, rdf_type, nil); !i.end(); ++i) { - const Sord::Node& subject = i.get_subject(); - const Sord::Node& rdf_class = i.get_object(); - - assert(rdf_class.is_uri()); - auto s = subjects.find(subject); - if (s == subjects.end()) { - std::set<Sord::Node> types; + for (const auto& s : model.range({}, uris.rdf_type, {})) { + const auto& subject = s.subject(); + const auto& rdf_class = s.object(); + + assert(rdf_class.type() == serd::NodeType::URI); + auto t = subjects.find(subject); + if (t == subjects.end()) { + std::set<serd::Node> types; types.insert(rdf_class); subjects.emplace(subject, types); } else { - s->second.insert(rdf_class); + t->second.insert(rdf_class); } } // Parse and create each subject for (const auto& i : subjects) { - const Sord::Node& s = i.first; - const std::set<Sord::Node>& types = i.second; + const auto& s = i.first; + const auto& types = i.second; + boost::optional<Raul::Path> ret; - if (types.find(graph_class) != types.end()) { + if (types.find(uris.ingen_Graph) != types.end()) { ret = parse_graph(world, target, model, base_uri, s, Resource::Graph::INTERNAL, parent, symbol, data); - } else if (types.find(block_class) != types.end()) { + } else if (types.find(uris.ingen_Block) != types.end()) { const Raul::Path rel_path(*get_path(base_uri, s)); const Raul::Path path = parent ? parent->child(rel_path) : rel_path; ret = parse_block(world, target, model, base_uri, s, path, data); - } else if (types.find(in_port_class) != types.end() || - types.find(out_port_class) != types.end()) { + } else if (types.find(uris.lv2_InputPort) != types.end() || + types.find(uris.lv2_OutputPort) != types.end()) { const Raul::Path rel_path(*get_path(base_uri, s)); const Raul::Path path = parent ? parent->child(rel_path) : rel_path; const Properties properties = get_properties( world, model, s, Resource::Graph::DEFAULT, data); target.put(path_to_uri(path), properties); ret = path; - } else if (types.find(arc_class) != types.end()) { + } else if (types.find(uris.ingen_Arc) != types.end()) { Raul::Path parent_path(parent ? parent.get() : Raul::Path("/")); parse_arc(world, target, model, base_uri, s, parent_path); } else { @@ -599,8 +556,8 @@ Parser::parse_file(ingen::World& world, URI manifest_uri(manifest_path); // Find graphs in manifest - const std::set<ResourceRecord> resources = find_resources( - *world.rdf_world(), manifest_uri, URI(INGEN__Graph)); + const std::set<ResourceRecord> resources = + find_resources(manifest_uri, URI(INGEN__Graph)); if (resources.empty()) { world.log().error("No graphs found in %1%\n", path); @@ -610,7 +567,7 @@ Parser::parse_file(ingen::World& world, /* Choose the graph to load. If this is a manifest, then there should only be one, but if this is a graph file, subgraphs will be returned as well. In this case, choose the one with the file URI. */ - URI uri; + boost::optional<URI> uri; for (const ResourceRecord& r : resources) { if (r.uri == URI(manifest_path)) { uri = r.uri; @@ -619,7 +576,7 @@ Parser::parse_file(ingen::World& world, } } - if (uri.empty()) { + if (!uri) { // Didn't find a graph with the same URI as the file, use the first uri = (*resources.begin()).uri; file_path = (*resources.begin()).filename; @@ -631,15 +588,13 @@ Parser::parse_file(ingen::World& world, } // Initialise parsing environment - const URI file_uri = URI(file_path); - const auto* uri_c_str = (const uint8_t*)uri.c_str(); - SerdNode base_node = serd_node_from_string(SERD_URI, uri_c_str); - SerdEnv* env = serd_env_new(&base_node); + const URI file_uri(file_path); + serd::Env env(*uri); // Load graph into model - Sord::Model model(*world.rdf_world(), uri.string(), SORD_SPO|SORD_PSO, false); - model.load_file(env, SERD_TURTLE, file_uri); - serd_env_free(env); + serd::Model model(world.rdf_world(), + serd::ModelFlag::index_SPO | serd::ModelFlag::index_OPS); + load_file(world.rdf_world(), model, env, file_uri); world.log().info("Loading %1% from %2%\n", uri, file_path); if (parent) { @@ -649,15 +604,21 @@ Parser::parse_file(ingen::World& world, world.log().info("Symbol: %1%\n", symbol->c_str()); } - Sord::Node subject(*world.rdf_world(), Sord::Node::URI, uri.string()); - boost::optional<Raul::Path> parsed_path - = parse(world, target, model, model.base_uri(), - subject, parent, symbol, data); + boost::optional<Raul::Path> parsed_path = + parse_graph(world, + target, + model, + *uri, + *uri, + Resource::Graph::INTERNAL, + parent, + symbol, + data); if (parsed_path) { target.set_property(path_to_uri(*parsed_path), URI(INGEN__file), - world.forge().alloc_uri(uri.string())); + world.forge().alloc_uri(uri->string())); return true; } else { world.log().warn("Document URI lost\n"); @@ -675,23 +636,27 @@ Parser::parse_string(ingen::World& world, const boost::optional<Properties>& data) { // Load string into model - Sord::Model model(*world.rdf_world(), base_uri, SORD_SPO|SORD_PSO, false); + serd::Model model(world.rdf_world(), + serd::ModelFlag::index_SPO | serd::ModelFlag::index_OPS); - SerdEnv* env = serd_env_new(nullptr); + serd::Env env; if (!base_uri.empty()) { - const SerdNode base = serd_node_from_string( - SERD_URI, (const uint8_t*)base_uri.c_str()); - serd_env_set_base_uri(env, &base); + env.set_base_uri(base_uri); } - model.load_string(env, SERD_TURTLE, str.c_str(), str.length(), base_uri); - URI actual_base((const char*)serd_env_get_base_uri(env, nullptr)->buf); - serd_env_free(env); + serd::Inserter inserter(model, env); + serd::Reader reader( + world.rdf_world(), serd::Syntax::Turtle, {}, inserter.sink(), 4096); + + reader.start_string(str); + reader.read_document(); + reader.finish(); + + URI actual_base(env.base_uri()); world.log().info("Parsing string (base %1%)\n", base_uri); - Sord::Node subject; - parse(world, target, model, actual_base, subject, parent, symbol, data); + parse(world, target, model, actual_base, parent, symbol, data); return actual_base; } diff --git a/src/Serialiser.cpp b/src/Serialiser.cpp index f0b5009e..3ac18fe2 100644 --- a/src/Serialiser.cpp +++ b/src/Serialiser.cpp @@ -38,15 +38,16 @@ #include "raul/Path.hpp" #include "raul/Symbol.hpp" #include "serd/serd.h" -#include "sord/sord.h" -#include "sord/sordmm.hpp" -#include "sratom/sratom.h" +#include "serd/serd.hpp" +#include "sratom/sratom.hpp" #include <cassert> #include <cstdint> #include <cstring> +#include <fstream> #include <map> #include <set> +#include <sstream> #include <stdexcept> #include <string> #include <utility> @@ -55,15 +56,14 @@ namespace ingen { struct Serialiser::Impl { explicit Impl(World& world) - : _root_path("/") - , _mode(Mode::TO_FILE) - , _world(world) - , _model(nullptr) - , _sratom(sratom_new(&_world.uri_map().urid_map_feature()->urid_map)) - {} - - ~Impl() { - sratom_free(_sratom); + : _root_path("/") + , _mode(Mode::TO_STRING) + , _base_uri("ingen:") + , _world(world) + , _streamer(_world.rdf_world(), + _world.uri_map().urid_map_feature()->urid_map, + _world.uri_map().urid_unmap_feature()->urid_unmap) + { } Impl(const Impl&) = delete; @@ -77,22 +77,22 @@ struct Serialiser::Impl { const FilePath& filename); std::set<const Resource*> serialise_graph(const SPtr<const Node>& graph, - const Sord::Node& graph_id); + const serd::Node& graph_id); void serialise_block(const SPtr<const Node>& block, - const Sord::Node& class_id, - const Sord::Node& block_id); + const serd::Node& class_id, + const serd::Node& block_id); void serialise_port(const Node* port, Resource::Graph context, - const Sord::Node& port_id); + const serd::Node& port_id); - void serialise_properties(Sord::Node id, + void serialise_properties(serd::Node id, const Properties& props); void write_bundle(const SPtr<const Node>& graph, const URI& uri); - Sord::Node path_rdf_node(const Raul::Path& path); + serd::Node path_rdf_node(const Raul::Path& path); void write_manifest(const FilePath& bundle_path, const SPtr<const Node>& graph); @@ -100,18 +100,18 @@ struct Serialiser::Impl { void write_plugins(const FilePath& bundle_path, const std::set<const Resource*>& plugins); - void serialise_arc(const Sord::Node& parent, - const SPtr<const Arc>& arc); + void serialise_arc(const serd::Optional<serd::Node>& parent, + const SPtr<const Arc>& arc); std::string finish(); - Raul::Path _root_path; - Mode _mode; - URI _base_uri; - FilePath _basename; - World& _world; - Sord::Model* _model; - Sratom* _sratom; + Raul::Path _root_path; + Mode _mode; + URI _base_uri; + FilePath _basename; + World& _world; + UPtr<serd::Model> _model; + sratom::Streamer _streamer; }; Serialiser::Serialiser(World& world) @@ -129,24 +129,17 @@ Serialiser::Impl::write_manifest(const FilePath& bundle_path, start_to_file(Raul::Path("/"), manifest_path); - Sord::World& world = _model->world(); - const URIs& uris = _world.uris(); + const URIs& uris = _world.uris(); const std::string filename("main.ttl"); - const Sord::URI subject(world, filename, _base_uri); - - _model->add_statement(subject, - Sord::URI(world, uris.rdf_type), - Sord::URI(world, uris.ingen_Graph)); - _model->add_statement(subject, - Sord::URI(world, uris.rdf_type), - Sord::URI(world, uris.lv2_Plugin)); - _model->add_statement(subject, - Sord::URI(world, uris.rdfs_seeAlso), - Sord::URI(world, filename, _base_uri)); - _model->add_statement(subject, - Sord::URI(world, uris.lv2_prototype), - Sord::URI(world, uris.ingen_GraphPrototype)); + const serd::Node subject = serd::make_resolved_uri(filename, _base_uri); + + _model->insert(subject, uris.rdf_type, uris.ingen_Graph); + _model->insert(subject, uris.rdf_type, uris.lv2_Plugin); + _model->insert(subject, uris.lv2_prototype, uris.ingen_GraphPrototype); + _model->insert(subject, + uris.rdfs_seeAlso, + serd::make_resolved_uri(filename, _base_uri)); finish(); } @@ -159,24 +152,21 @@ Serialiser::Impl::write_plugins(const FilePath& bundle_path, start_to_file(Raul::Path("/"), plugins_path); - Sord::World& world = _model->world(); - const URIs& uris = _world.uris(); + const URIs& uris = _world.uris(); for (const auto& p : plugins) { const Atom& minor = p->get_property(uris.lv2_minorVersion); const Atom& micro = p->get_property(uris.lv2_microVersion); - _model->add_statement(Sord::URI(world, p->uri()), - Sord::URI(world, uris.rdf_type), - Sord::URI(world, uris.lv2_Plugin)); + _model->insert(p->uri(), uris.rdf_type, uris.lv2_Plugin); if (minor.is_valid() && micro.is_valid()) { - _model->add_statement(Sord::URI(world, p->uri()), - Sord::URI(world, uris.lv2_minorVersion), - Sord::Literal::integer(world, minor.get<int32_t>())); - _model->add_statement(Sord::URI(world, p->uri()), - Sord::URI(world, uris.lv2_microVersion), - Sord::Literal::integer(world, micro.get<int32_t>())); + _model->insert(p->uri(), + uris.lv2_minorVersion, + serd::make_integer(minor.get<int32_t>())); + _model->insert(p->uri(), + uris.lv2_microVersion, + serd::make_integer(micro.get<int32_t>())); } } @@ -207,7 +197,7 @@ Serialiser::Impl::write_bundle(const SPtr<const Node>& graph, const URI& uri) std::set<const Resource*> plugins = serialise_graph( graph, - Sord::URI(_model->world(), main_file, _base_uri)); + serd::make_resolved_uri(main_file.c_str(), _base_uri)); finish(); write_manifest(path, graph); @@ -230,9 +220,11 @@ Serialiser::Impl::start_to_file(const Raul::Path& root, _basename = filename.parent_path().stem(); } - _model = new Sord::Model(*_world.rdf_world(), _base_uri); - _mode = Mode::TO_FILE; _root_path = root; + _mode = Mode::TO_FILE; + _model = make_unique<serd::Model>(_world.rdf_world(), + serd::ModelFlag::index_SPO | + serd::ModelFlag::index_OPS); } void @@ -240,8 +232,10 @@ Serialiser::start_to_string(const Raul::Path& root, const URI& base_uri) { me->_root_path = root; me->_base_uri = base_uri; - me->_model = new Sord::Model(*me->_world.rdf_world(), base_uri); me->_mode = Impl::Mode::TO_STRING; + me->_model = make_unique<serd::Model>(me->_world.rdf_world(), + serd::ModelFlag::index_SPO | + serd::ModelFlag::index_OPS); } void @@ -259,32 +253,54 @@ Serialiser::finish() std::string Serialiser::Impl::finish() { - std::string ret; + std::string ret{}; + serd::Env env{_world.env()}; + + env.set_base_uri(_base_uri); + if (_mode == Mode::TO_FILE) { - SerdStatus st = _model->write_to_file(_base_uri, SERD_TURTLE); - if (st) { - _world.log().error("Error writing file %1% (%2%)\n", - _base_uri, serd_strerror(st)); + const std::string path = serd::file_uri_parse(_base_uri.string()); + std::ofstream file(path); + serd::Writer writer( + _world.rdf_world(), serd::Syntax::Turtle, {}, env, file); + + env.write_prefixes(writer.sink()); + const serd::Status st = _model->all().serialise(writer.sink()); + + if (st != serd::Status::success) { + _world.log().error(fmt("Error writing file %1% (%2%)\n", + _base_uri, serd::strerror(st))); } } else { - ret = _model->write_to_string(_base_uri, SERD_TURTLE); + std::stringstream ss; + serd::Writer writer( + _world.rdf_world(), serd::Syntax::Turtle, {}, env, ss); + + env.write_prefixes(writer.sink()); + const serd::Status st = _model->all().serialise(writer.sink()); + + writer.finish(); + ret = ss.str(); + + if (st != serd::Status::success) { + _world.log().error(fmt("Error writing string (%2%)\n", + serd::strerror(st))); + } } - delete _model; - _model = nullptr; - _base_uri = URI(); + _model.reset(); + _base_uri = URI("ingen:"); return ret; } -Sord::Node +serd::Node Serialiser::Impl::path_rdf_node(const Raul::Path& path) { assert(_model); assert(path == _root_path || path.is_child_of(_root_path)); - return Sord::URI(_model->world(), - path.substr(_root_path.base().length()), - _base_uri); + return serd::make_resolved_uri(path.substr(_root_path.base().length()), + _base_uri); } void @@ -297,8 +313,9 @@ Serialiser::serialise(const SPtr<const Node>& object, Resource::Graph context) if (object->graph_type() == Node::GraphType::GRAPH) { me->serialise_graph(object, me->path_rdf_node(object->path())); } else if (object->graph_type() == Node::GraphType::BLOCK) { - const Sord::URI plugin_id(me->_model->world(), object->plugin()->uri()); - me->serialise_block(object, plugin_id, me->path_rdf_node(object->path())); + me->serialise_block(object, + object->plugin()->uri(), + me->path_rdf_node(object->path())); } else if (object->graph_type() == Node::GraphType::PORT) { me->serialise_port( object.get(), context, me->path_rdf_node(object->path())); @@ -310,32 +327,27 @@ Serialiser::serialise(const SPtr<const Node>& object, Resource::Graph context) std::set<const Resource*> Serialiser::Impl::serialise_graph(const SPtr<const Node>& graph, - const Sord::Node& graph_id) + const serd::Node& graph_id) { - Sord::World& world = _model->world(); - const URIs& uris = _world.uris(); + const URIs& uris = _world.uris(); - _model->add_statement(graph_id, - Sord::URI(world, uris.rdf_type), - Sord::URI(world, uris.ingen_Graph)); + _model->insert(graph_id, uris.rdf_type, uris.ingen_Graph); - _model->add_statement(graph_id, - Sord::URI(world, uris.rdf_type), - Sord::URI(world, uris.lv2_Plugin)); + _model->insert(graph_id, uris.rdf_type, uris.lv2_Plugin); - _model->add_statement(graph_id, - Sord::URI(world, uris.lv2_extensionData), - Sord::URI(world, LV2_STATE__interface)); + _model->insert(graph_id, + uris.lv2_extensionData, + serd::make_uri(LV2_STATE__interface)); - _model->add_statement(graph_id, - Sord::URI(world, LV2_UI__ui), - Sord::URI(world, "http://drobilla.net/ns/ingen#GraphUIGtk2")); + _model->insert(graph_id, + serd::make_uri(LV2_UI__ui), + serd::make_uri("http://drobilla.net/ns/ingen#GraphUIGtk2")); // If the graph has no doap:name (required by LV2), use the basename if (graph->properties().find(uris.doap_name) == graph->properties().end()) { - _model->add_statement(graph_id, - Sord::URI(world, uris.doap_name), - Sord::Literal(world, _basename)); + _model->insert(graph_id, + uris.doap_name, + serd::make_string((std::string)_basename)); } const Properties props = graph->properties(Resource::Graph::INTERNAL); @@ -352,45 +364,33 @@ Serialiser::Impl::serialise_graph(const SPtr<const Node>& graph, if (n->second->graph_type() == Node::GraphType::GRAPH) { SPtr<Node> subgraph = n->second; - SerdURI base_uri; - serd_uri_parse((const uint8_t*)_base_uri.c_str(), &base_uri); - const std::string sub_bundle_path = subgraph->path().substr(1) + ".ingen"; - SerdURI subgraph_uri; - SerdNode subgraph_node = serd_node_new_uri_from_string( - (const uint8_t*)sub_bundle_path.c_str(), - &base_uri, - &subgraph_uri); - - const Sord::URI subgraph_id(world, (const char*)subgraph_node.buf); + serd::Node subgraph_node = serd::make_resolved_uri( + sub_bundle_path, + _base_uri); // Save our state - URI my_base_uri = _base_uri; - Sord::Model* my_model = _model; + URI my_base_uri = _base_uri; + auto my_model = std::move(_model); // Write child bundle within this bundle - write_bundle(subgraph, subgraph_id); + write_bundle(subgraph, subgraph_node); // Restore our state _base_uri = my_base_uri; - _model = my_model; + _model = std::move(my_model); // Serialise reference to graph block - const Sord::Node block_id(path_rdf_node(subgraph->path())); - _model->add_statement(graph_id, - Sord::URI(world, uris.ingen_block), - block_id); - serialise_block(subgraph, subgraph_id, block_id); + const serd::Node block_id(path_rdf_node(subgraph->path())); + _model->insert(graph_id, uris.ingen_block, block_id); + serialise_block(subgraph, subgraph_node, block_id); } else if (n->second->graph_type() == Node::GraphType::BLOCK) { SPtr<const Node> block = n->second; - const Sord::URI class_id(world, block->plugin()->uri()); - const Sord::Node block_id(path_rdf_node(n->second->path())); - _model->add_statement(graph_id, - Sord::URI(world, uris.ingen_block), - block_id); - serialise_block(block, class_id, block_id); + const serd::Node block_id(path_rdf_node(n->second->path())); + _model->insert(graph_id, uris.ingen_block, block_id); + serialise_block(block, block->plugin()->uri(), block_id); plugins.insert(block->plugin()); } @@ -398,7 +398,7 @@ Serialiser::Impl::serialise_graph(const SPtr<const Node>& graph, for (uint32_t i = 0; i < graph->num_ports(); ++i) { Node* p = graph->port(i); - const Sord::Node port_id = path_rdf_node(p->path()); + const serd::Node port_id = path_rdf_node(p->path()); // Ensure lv2:name always exists so Graph is a valid LV2 plugin if (p->properties().find(uris.lv2_name) == p->properties().end()) { @@ -406,9 +406,7 @@ Serialiser::Impl::serialise_graph(const SPtr<const Node>& graph, _world.forge().alloc(p->symbol().c_str())); } - _model->add_statement(graph_id, - Sord::URI(world, LV2_CORE__port), - port_id); + _model->insert(graph_id, serd::make_uri(LV2_CORE__port), port_id); serialise_port(p, Resource::Graph::DEFAULT, port_id); serialise_port(p, Resource::Graph::INTERNAL, port_id); } @@ -422,17 +420,13 @@ Serialiser::Impl::serialise_graph(const SPtr<const Node>& graph, void Serialiser::Impl::serialise_block(const SPtr<const Node>& block, - const Sord::Node& class_id, - const Sord::Node& block_id) + const serd::Node& class_id, + const serd::Node& block_id) { const URIs& uris = _world.uris(); - _model->add_statement(block_id, - Sord::URI(_model->world(), uris.rdf_type), - Sord::URI(_model->world(), uris.ingen_Block)); - _model->add_statement(block_id, - Sord::URI(_model->world(), uris.lv2_prototype), - class_id); + _model->insert(block_id, uris.rdf_type, uris.ingen_Block); + _model->insert(block_id, uris.lv2_prototype, class_id); // Serialise properties, but remove possibly stale state:state (set again below) Properties props = block->properties(); @@ -445,36 +439,33 @@ Serialiser::Impl::serialise_block(const SPtr<const Node>& block, const FilePath state_dir = graph_dir / block->symbol(); const FilePath state_file = state_dir / "state.ttl"; if (block->save_state(state_dir)) { - _model->add_statement(block_id, - Sord::URI(_model->world(), uris.state_state), - Sord::URI(_model->world(), URI(state_file))); + _model->insert(block_id, + uris.state_state, + serd::make_uri((std::string)state_file)); } } for (uint32_t i = 0; i < block->num_ports(); ++i) { Node* const p = block->port(i); - const Sord::Node port_id = path_rdf_node(p->path()); + const serd::Node port_id = path_rdf_node(p->path()); serialise_port(p, Resource::Graph::DEFAULT, port_id); - _model->add_statement(block_id, - Sord::URI(_model->world(), uris.lv2_port), - port_id); + _model->insert(block_id, uris.lv2_port, port_id); } } void Serialiser::Impl::serialise_port(const Node* port, Resource::Graph context, - const Sord::Node& port_id) + const serd::Node& port_id) { - URIs& uris = _world.uris(); - Sord::World& world = _model->world(); + URIs& uris = _world.uris(); Properties props = port->properties(context); if (context == Resource::Graph::INTERNAL) { // Always write lv2:symbol for Graph ports (required for lv2:Plugin) - _model->add_statement(port_id, - Sord::URI(world, uris.lv2_symbol), - Sord::Literal(world, port->path().symbol())); + _model->insert(port_id, + uris.lv2_symbol, + serd::make_string(port->path().symbol())); } else if (context == Resource::Graph::EXTERNAL) { // Never write lv2:index for plugin instances (not persistent/stable) props.erase(uris.lv2_index); @@ -500,47 +491,38 @@ Serialiser::Impl::serialise_port(const Node* port, } void -Serialiser::serialise_arc(const Sord::Node& parent, - const SPtr<const Arc>& arc) +Serialiser::serialise_arc(const serd::Optional<serd::Node>& parent, + const SPtr<const Arc>& arc) { return me->serialise_arc(parent, arc); } void -Serialiser::Impl::serialise_arc(const Sord::Node& parent, - const SPtr<const Arc>& arc) +Serialiser::Impl::serialise_arc(const serd::Optional<serd::Node>& parent, + const SPtr<const Arc>& arc) { if (!_model) { throw std::logic_error( "serialise_arc called without serialisation in progress"); } - Sord::World& world = _model->world(); - const URIs& uris = _world.uris(); - - const Sord::Node src = path_rdf_node(arc->tail_path()); - const Sord::Node dst = path_rdf_node(arc->head_path()); - const Sord::Node arc_id = Sord::Node::blank_id(*_world.rdf_world()); - _model->add_statement(arc_id, - Sord::URI(world, uris.ingen_tail), - src); - _model->add_statement(arc_id, - Sord::URI(world, uris.ingen_head), - dst); - - if (parent.is_valid()) { - _model->add_statement(parent, - Sord::URI(world, uris.ingen_arc), - arc_id); + const URIs& uris = _world.uris(); + + const serd::Node src = path_rdf_node(arc->tail_path()); + const serd::Node dst = path_rdf_node(arc->head_path()); + const serd::Node arc_id = _world.rdf_world().get_blank(); + _model->insert(arc_id, uris.ingen_tail, src); + _model->insert(arc_id, uris.ingen_head, dst); + + if (parent) { + _model->insert(*parent, uris.ingen_arc, arc_id); } else { - _model->add_statement(arc_id, - Sord::URI(world, uris.rdf_type), - Sord::URI(world, uris.ingen_Arc)); + _model->insert(arc_id, uris.rdf_type, uris.ingen_Arc); } } static bool -skip_property(ingen::URIs& uris, const Sord::Node& predicate) +skip_property(ingen::URIs& uris, const serd::Node& predicate) { return (predicate == INGEN__file || predicate == uris.ingen_arc || @@ -549,45 +531,37 @@ skip_property(ingen::URIs& uris, const Sord::Node& predicate) } void -Serialiser::Impl::serialise_properties(Sord::Node id, +Serialiser::Impl::serialise_properties(serd::Node id, const Properties& props) { - LV2_URID_Unmap* unmap = &_world.uri_map().urid_unmap_feature()->urid_unmap; - SerdNode base = serd_node_from_string(SERD_URI, - (const uint8_t*)_base_uri.c_str()); - SerdEnv* env = serd_env_new(&base); - SordInserter* inserter = sord_inserter_new(_model->c_obj(), env); - - sratom_set_sink(_sratom, _base_uri.c_str(), - (SerdStatementSink)sord_inserter_write_statement, nullptr, - inserter); - - sratom_set_pretty_numbers(_sratom, true); + serd::Env env{_base_uri}; + serd::Inserter inserter{*_model, env, {}}; for (const auto& p : props) { - const Sord::URI key(_model->world(), p.first); + const serd::Node key = serd::make_uri(p.first.c_str()); if (!skip_property(_world.uris(), key)) { if (p.second.type() == _world.uris().atom_URI && - !strncmp((const char*)p.second.get_body(), "ingen:/main/", 13)) { + !strncmp( + (const char*)p.second.get_body(), "ingen:/main/", 13)) { /* Value is a graph URI relative to the running engine. Chop the prefix and save the path relative to the graph file. This allows saving references to bundle resources. */ - sratom_write(_sratom, unmap, 0, - sord_node_to_serd_node(id.c_obj()), - sord_node_to_serd_node(key.c_obj()), - p.second.type(), p.second.size(), - (const char*)p.second.get_body() + 13); + _streamer.write(inserter.sink(), + id, + key, + p.second.type(), + p.second.size(), + (const char*)p.second.get_body() + 13, + sratom::Flag::pretty_numbers); } else { - sratom_write(_sratom, unmap, 0, - sord_node_to_serd_node(id.c_obj()), - sord_node_to_serd_node(key.c_obj()), - p.second.type(), p.second.size(), p.second.get_body()); + _streamer.write(inserter.sink(), + id, + key, + *p.second.atom(), + sratom::Flag::pretty_numbers); } } } - - sord_inserter_free(inserter); - serd_env_free(env); } } // namespace ingen diff --git a/src/SocketReader.cpp b/src/SocketReader.cpp index 443c418f..273c9e49 100644 --- a/src/SocketReader.cpp +++ b/src/SocketReader.cpp @@ -21,10 +21,11 @@ #include "ingen/Log.hpp" #include "ingen/URIMap.hpp" #include "ingen/World.hpp" +#include "ingen/types.hpp" #include "lv2/atom/forge.h" #include "lv2/urid/urid.h" #include "raul/Socket.hpp" -#include "sord/sordmm.hpp" +#include "serd/serd.hpp" #include <cerrno> #include <cstdint> @@ -42,9 +43,6 @@ SocketReader::SocketReader(ingen::World& world, SPtr<Raul::Socket> sock) : _world(world) , _iface(iface) - , _env() - , _inserter(nullptr) - , _msg_node(nullptr) , _socket(std::move(sock)) , _exit_flag(false) , _thread(&SocketReader::run, this) @@ -57,46 +55,10 @@ SocketReader::~SocketReader() _thread.join(); } -SerdStatus -SocketReader::set_base_uri(SocketReader* iface, - const SerdNode* uri_node) -{ - return sord_inserter_set_base_uri(iface->_inserter, uri_node); -} - -SerdStatus -SocketReader::set_prefix(SocketReader* iface, - const SerdNode* name, - const SerdNode* uri_node) -{ - return sord_inserter_set_prefix(iface->_inserter, name, uri_node); -} - -SerdStatus -SocketReader::write_statement(SocketReader* iface, - SerdStatementFlags flags, - const SerdNode* graph, - const SerdNode* subject, - const SerdNode* predicate, - const SerdNode* object, - const SerdNode* object_datatype, - const SerdNode* object_lang) -{ - if (!iface->_msg_node) { - iface->_msg_node = sord_node_from_serd_node( - iface->_world.rdf_world()->c_obj(), iface->_env, subject, nullptr, nullptr); - } - - return sord_inserter_write_statement( - iface->_inserter, flags, graph, - subject, predicate, object, - object_datatype, object_lang); -} - void SocketReader::run() { - Sord::World* world = _world.rdf_world(); + serd::World& world = _world.rdf_world(); LV2_URID_Map& map = _world.uri_map().urid_map_feature()->urid_map; // Open socket as a FILE for reading directly with serd @@ -111,33 +73,51 @@ SocketReader::run() } // Set up a forge to build LV2 atoms from model - SordNode* base_uri = nullptr; - SordModel* model = nullptr; - AtomForge forge(map); + AtomForge forge(world, map); + serd::Optional<serd::Node> base_uri; + serd::Optional<serd::Model> model; + serd::Env env; + UPtr<serd::Inserter> inserter; + serd::Optional<serd::Node> msg_node; { // Lock RDF world std::lock_guard<std::mutex> lock(_world.rdf_mutex()); // Use <ingen:/> as base URI, so relative URIs are like bundle paths - base_uri = sord_new_uri(world->c_obj(), (const uint8_t*)"ingen:/"); + base_uri = serd::make_uri("ingen:/"); // Make a model and reader to parse the next Turtle message - _env = world->prefixes().c_obj(); - model = sord_new(world->c_obj(), SORD_SPO, false); + env = _world.env(); + model = serd::Model(world, serd::ModelFlag::index_SPO); // Create an inserter for writing incoming triples to model - _inserter = sord_inserter_new(model, _env); + inserter = UPtr<serd::Inserter>{new serd::Inserter(*model, env)}; } - SerdReader* reader = serd_reader_new( - SERD_TURTLE, this, nullptr, - (SerdBaseSink)set_base_uri, - (SerdPrefixSink)set_prefix, - (SerdStatementSink)write_statement, - nullptr); + serd::Sink sink; + + sink.set_base_func([&](const serd::Node& uri) { + return inserter->sink().base(uri); + }); + + sink.set_prefix_func([&](const serd::Node& name, const serd::Node& uri) { + return inserter->sink().prefix(name, uri); + }); + + sink.set_statement_func([&](const serd::StatementFlags flags, + const serd::Statement& statement) { + if (!msg_node) { + msg_node = statement.subject(); + } + + return inserter->sink().statement(flags, statement); + }); + + serd::Reader reader(world, serd::Syntax::Turtle, {}, sink, 4096); - serd_env_set_base_uri(_env, sord_node_to_serd_node(base_uri)); - serd_reader_start_stream(reader, f.get(), (const uint8_t*)"(socket)", false); + serd::Node name = serd::make_string("(socket)"); + env.set_base_uri(*base_uri); + reader.start_stream(f.get(), name, 1); // Make an AtomReader to call Ingen Interface methods based on Atom AtomReader ar(_world.uri_map(), _world.uris(), _world.log(), _iface); @@ -165,24 +145,22 @@ SocketReader::run() std::lock_guard<std::mutex> lock(_world.rdf_mutex()); // Read until the next '.' - SerdStatus st = serd_reader_read_chunk(reader); - if (st == SERD_FAILURE || !_msg_node) { - continue; // Read nothing, e.g. just whitespace - } else if (st) { - _world.log().error("Read error: %1%\n", serd_strerror(st)); + auto st = reader.read_chunk(); + if (st == serd::Status::failure || !msg_node) { + continue; // Read no node (e.g. a directive) + } else if (st != serd::Status::success) { + _world.log().error("Read error: %1%\n", serd::strerror(st)); continue; } - // Build an LV2_Atom at chunk.buf from the message - forge.read(*world, model, _msg_node); + // Build an LV2_Atom from the message + auto atom = forge.read(*model, *msg_node); - // Call _iface methods based on atom content - ar.write(forge.atom()); + // Call _iface methods with forged atom + ar.write(atom); // Reset everything for the next iteration - forge.clear(); - sord_node_free(world->c_obj(), _msg_node); - _msg_node = nullptr; + msg_node.reset(); } // Lock RDF world @@ -190,10 +168,7 @@ SocketReader::run() // Destroy everything f.reset(); - sord_inserter_free(_inserter); - serd_reader_end_stream(reader); - serd_reader_free(reader); - sord_free(model); + reader.finish(); _socket.reset(); } diff --git a/src/SocketWriter.cpp b/src/SocketWriter.cpp index 910f67f3..41254ef3 100644 --- a/src/SocketWriter.cpp +++ b/src/SocketWriter.cpp @@ -31,12 +31,13 @@ namespace ingen { -SocketWriter::SocketWriter(URIMap& map, +SocketWriter::SocketWriter(serd::World& world, + URIMap& map, URIs& uris, const URI& uri, SPtr<Raul::Socket> sock) - : TurtleWriter(map, uris, uri) - , _socket(std::move(sock)) + : TurtleWriter(world, map, uris, uri) + , _socket(std::move(sock)) {} void diff --git a/src/StreamWriter.cpp b/src/StreamWriter.cpp index d8a93a0b..32831601 100644 --- a/src/StreamWriter.cpp +++ b/src/StreamWriter.cpp @@ -21,14 +21,15 @@ namespace ingen { -StreamWriter::StreamWriter(URIMap& map, +StreamWriter::StreamWriter(serd::World& world, + URIMap& map, URIs& uris, const URI& uri, FILE* stream, ColorContext::Color color) - : TurtleWriter(map, uris, uri) - , _stream(stream) - , _color(color) + : TurtleWriter(world, map, uris, uri) + , _stream(stream) + , _color(color) {} size_t diff --git a/src/TurtleWriter.cpp b/src/TurtleWriter.cpp index 1deb2e13..e8a38561 100644 --- a/src/TurtleWriter.cpp +++ b/src/TurtleWriter.cpp @@ -19,72 +19,43 @@ #include "ingen/URIMap.hpp" #include "lv2/atom/atom.h" -#define USTR(s) ((const uint8_t*)(s)) - namespace ingen { -static size_t -c_text_sink(const void* buf, size_t len, void* stream) -{ - auto* writer = static_cast<TurtleWriter*>(stream); - return writer->text_sink(buf, len); -} - -static SerdStatus -write_prefix(void* handle, const SerdNode* name, const SerdNode* uri) -{ - serd_writer_set_prefix((SerdWriter*)handle, name, uri); - return SERD_SUCCESS; -} - -TurtleWriter::TurtleWriter(URIMap& map, URIs& uris, URI uri) - : AtomWriter(map, uris, *this) +TurtleWriter::TurtleWriter(serd::World& world, + URIMap& map, + URIs& uris, + const URI& uri) + : AtomWriter(world, map, uris, *this) , _map(map) - , _sratom(sratom_new(&map.urid_map_feature()->urid_map)) - , _base(SERD_NODE_NULL) - , _base_uri(SERD_URI_NULL) - , _uri(std::move(uri)) + , _streamer(world, + map.urid_map_feature()->urid_map, + map.urid_unmap_feature()->urid_unmap) + , _base(serd::make_uri("ingen:/")) // Make relative URIs like bundle paths + , _env(_base) + , _writer(world, + serd::Syntax::Turtle, + {}, + _env, + [&](const char* str, size_t len) { return text_sink(str, len); }) + , _uri(uri) , _wrote_prefixes(false) { - // Use <ingen:/> as base URI, so relative URIs are like bundle paths - _base = serd_node_from_string(SERD_URI, (const uint8_t*)"ingen:/"); - serd_uri_parse(_base.buf, &_base_uri); - - // Set up serialisation environment - _env = serd_env_new(&_base); - serd_env_set_prefix_from_strings(_env, USTR("atom"), USTR("http://lv2plug.in/ns/ext/atom#")); - serd_env_set_prefix_from_strings(_env, USTR("doap"), USTR("http://usefulinc.com/ns/doap#")); - serd_env_set_prefix_from_strings(_env, USTR("ingen"), USTR(INGEN_NS)); - serd_env_set_prefix_from_strings(_env, USTR("lv2"), USTR("http://lv2plug.in/ns/lv2core#")); - serd_env_set_prefix_from_strings(_env, USTR("midi"), USTR("http://lv2plug.in/ns/ext/midi#")); - serd_env_set_prefix_from_strings(_env, USTR("owl"), USTR("http://www.w3.org/2002/07/owl#")); - serd_env_set_prefix_from_strings(_env, USTR("patch"), USTR("http://lv2plug.in/ns/ext/patch#")); - serd_env_set_prefix_from_strings(_env, USTR("rdf"), USTR("http://www.w3.org/1999/02/22-rdf-syntax-ns#")); - serd_env_set_prefix_from_strings(_env, USTR("rdfs"), USTR("http://www.w3.org/2000/01/rdf-schema#")); - serd_env_set_prefix_from_strings(_env, USTR("xsd"), USTR("http://www.w3.org/2001/XMLSchema#")); - - // Make a Turtle writer that writes to text_sink - _writer = serd_writer_new( - SERD_TURTLE, - (SerdStyle)(SERD_STYLE_RESOLVED|SERD_STYLE_ABBREVIATED|SERD_STYLE_CURIED), - _env, - &_base_uri, - c_text_sink, - this); - - // Configure sratom to write directly to the writer (and thus text_sink) - sratom_set_sink(_sratom, - (const char*)_base.buf, - (SerdStatementSink)serd_writer_write_statement, - (SerdEndSink)serd_writer_end_anon, - _writer); + // Set namespace prefixes + _env.set_prefix("atom", "http://lv2plug.in/ns/ext/atom#"); + _env.set_prefix("doap", "http://usefulinc.com/ns/doap#"); + _env.set_prefix("ingen", INGEN_NS); + _env.set_prefix("lv2", "http://lv2plug.in/ns/lv2core#"); + _env.set_prefix("midi", "http://lv2plug.in/ns/ext/midi#"); + _env.set_prefix("owl", "http://www.w3.org/2002/07/owl#"); + _env.set_prefix("patch", "http://lv2plug.in/ns/ext/patch#"); + _env.set_prefix("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#"); + _env.set_prefix("rdfs", "http://www.w3.org/2000/01/rdf-schema#"); + _env.set_prefix("xsd", "http://www.w3.org/2001/XMLSchema#"); } TurtleWriter::~TurtleWriter() { - sratom_free(_sratom); - serd_writer_free(_writer); - serd_env_free(_env); + _writer.finish(); } bool @@ -92,13 +63,13 @@ TurtleWriter::write(const LV2_Atom* msg, int32_t) { if (!_wrote_prefixes) { // Write namespace prefixes once to reduce traffic - serd_env_foreach(_env, write_prefix, _writer); + _env.write_prefixes(_writer.sink()); + _writer.finish(); _wrote_prefixes = true; } - sratom_write(_sratom, &_map.urid_unmap_feature()->urid_unmap, 0, - nullptr, nullptr, msg->type, msg->size, LV2_ATOM_BODY_CONST(msg)); - serd_writer_finish(_writer); + _streamer.write(_writer.sink(), *msg); + _writer.finish(); return true; } diff --git a/src/URI.cpp b/src/URI.cpp index f7b64209..fd649393 100644 --- a/src/URI.cpp +++ b/src/URI.cpp @@ -22,102 +22,39 @@ namespace ingen { -URI::URI() - : _uri(SERD_URI_NULL) - , _node(SERD_NODE_NULL) -{} - URI::URI(const std::string& str) - : _uri(SERD_URI_NULL) - , _node(serd_node_new_uri_from_string((const uint8_t*)str.c_str(), - nullptr, - &_uri)) -{} - -URI::URI(const char* str) - : _uri(SERD_URI_NULL) - , _node(serd_node_new_uri_from_string((const uint8_t*)str, nullptr, &_uri)) -{} - -URI::URI(const std::string& str, const URI& base) - : _uri(SERD_URI_NULL) - , _node(serd_node_new_uri_from_string((const uint8_t*)str.c_str(), - &base._uri, - &_uri)) -{} - -URI::URI(SerdNode node) - : _uri(SERD_URI_NULL) - , _node(serd_node_new_uri_from_node(&node, nullptr, &_uri)) + : serd::Node{serd::make_uri(str)} { - assert(node.type == SERD_URI); } -URI::URI(SerdNode node, SerdURI uri) - : _uri(uri) - , _node(node) -{ - assert(node.type == SERD_URI); -} - -URI::URI(const Sord::Node& node) - : URI(*node.to_serd_node()) -{ -} - -URI::URI(const FilePath& path) - : _uri(SERD_URI_NULL) - , _node(serd_node_new_file_uri((const uint8_t*)path.c_str(), - nullptr, - &_uri, - true)) -{} - -URI::URI(const URI& uri) - : _uri(SERD_URI_NULL) - , _node(serd_node_new_uri(&uri._uri, nullptr, &_uri)) -{} - -URI& -URI::operator=(const URI& uri) +URI::URI(const char* str) + : serd::Node{serd::make_uri(str)} { - if (&uri != this) { - serd_node_free(&_node); - _node = serd_node_new_uri(&uri._uri, nullptr, &_uri); - } - - return *this; } -URI::URI(URI&& uri) noexcept - : _uri(uri._uri) - , _node(uri._node) +URI::URI(const serd::NodeView& node) + : serd::Node{node} { - uri._node = SERD_NODE_NULL; - uri._uri = SERD_URI_NULL; + assert(cobj()); + assert(node.type() == serd::NodeType::URI); } -URI& -URI::operator=(URI&& uri) noexcept +URI::URI(const serd::Node& node) + : serd::Node{node} { - _node = uri._node; - _uri = uri._uri; - uri._node = SERD_NODE_NULL; - uri._uri = SERD_URI_NULL; - return *this; + assert(cobj()); + assert(node.type() == serd::NodeType::URI); } -URI::~URI() +URI::URI(const FilePath& path) + : serd::Node{serd::make_file_uri(path.string())} { - serd_node_free(&_node); } URI URI::make_relative(const URI& base) const { - SerdURI uri; - SerdNode node = serd_node_new_relative_uri(&_uri, &base._uri, nullptr, &uri); - return URI(node, uri); + return URI(serd::make_relative_uri(std::string(*this), base)); } } // namespace ingen diff --git a/src/URIs.cpp b/src/URIs.cpp index dfe6b867..9c83a637 100644 --- a/src/URIs.cpp +++ b/src/URIs.cpp @@ -43,21 +43,8 @@ URIs::Quark::Quark(Forge& forge, : URI(str) , urid(forge.make_urid(URI(str))) , uri(forge.alloc_uri(str)) - , lnode(lilv_new_uri(lworld, str)) {} -URIs::Quark::Quark(const Quark& copy) - : URI(copy) - , urid(copy.urid) - , uri(copy.uri) - , lnode(lilv_node_duplicate(copy.lnode)) -{} - -URIs::Quark::~Quark() -{ - lilv_node_free(lnode); -} - #define NS_RDF "http://www.w3.org/1999/02/22-rdf-syntax-ns#" #define NS_RDFS "http://www.w3.org/2000/01/rdf-schema#" diff --git a/src/World.cpp b/src/World.cpp index 41e69826..12d10bb2 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -37,7 +37,7 @@ #include "lilv/lilv.h" #include "lv2/log/log.h" #include "lv2/urid/urid.h" -#include "sord/sordmm.hpp" +#include "serd/serd.hpp" #include <cstdint> #include <list> @@ -90,7 +90,6 @@ public: : argc(nullptr) , argv(nullptr) , lv2_features(nullptr) - , rdf_world(new Sord::World()) , lilv_world(lilv_world_new(), lilv_world_free) , uri_map(log, map, unmap) , forge(uri_map) @@ -108,16 +107,16 @@ public: lilv_world_load_all(lilv_world.get()); // Set up RDF namespaces - rdf_world->add_prefix("atom", "http://lv2plug.in/ns/ext/atom#"); - rdf_world->add_prefix("doap", "http://usefulinc.com/ns/doap#"); - rdf_world->add_prefix("ingen", INGEN_NS); - rdf_world->add_prefix("lv2", "http://lv2plug.in/ns/lv2core#"); - rdf_world->add_prefix("midi", "http://lv2plug.in/ns/ext/midi#"); - rdf_world->add_prefix("owl", "http://www.w3.org/2002/07/owl#"); - rdf_world->add_prefix("patch", "http://lv2plug.in/ns/ext/patch#"); - rdf_world->add_prefix("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#"); - rdf_world->add_prefix("rdfs", "http://www.w3.org/2000/01/rdf-schema#"); - rdf_world->add_prefix("xsd", "http://www.w3.org/2001/XMLSchema#"); + env.set_prefix("atom", "http://lv2plug.in/ns/ext/atom#"); + env.set_prefix("doap", "http://usefulinc.com/ns/doap#"); + env.set_prefix("ingen", INGEN_NS); + env.set_prefix("lv2", "http://lv2plug.in/ns/lv2core#"); + env.set_prefix("midi", "http://lv2plug.in/ns/ext/midi#"); + env.set_prefix("owl", "http://www.w3.org/2002/07/owl#"); + env.set_prefix("patch", "http://lv2plug.in/ns/ext/patch#"); + env.set_prefix("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#"); + env.set_prefix("rdfs", "http://www.w3.org/2000/01/rdf-schema#"); + env.set_prefix("xsd", "http://www.w3.org/2001/XMLSchema#"); // Load internal 'plugin' information into lilv world LilvNode* rdf_type = lilv_new_uri( @@ -183,7 +182,8 @@ public: int* argc; char*** argv; LV2Features* lv2_features; - UPtr<Sord::World> rdf_world; + serd::World rdf_world; + serd::Env env; LilvWorldUPtr lilv_world; URIMap uri_map; Forge forge; @@ -219,7 +219,8 @@ World::load_configuration(int& argc, char**& argv) _impl->argv = &argv; // Parse default configuration files - const auto files = _impl->conf.load_default("ingen", "options.ttl"); + const auto files = + _impl->conf.load_default(rdf_world(), "ingen", "options.ttl"); for (const auto& f : files) { _impl->log.info("Loaded configuration %1%\n", f); } @@ -247,7 +248,8 @@ Log& World::log() { return _impl->log; } std::mutex& World::rdf_mutex() { return _impl->rdf_mutex; } -Sord::World* World::rdf_world() { return _impl->rdf_world.get(); } +serd::World& World::rdf_world() { return _impl->rdf_world; } +serd::Env& World::env() { return _impl->env; } LilvWorld* World::lilv_world() { return _impl->lilv_world.get(); } LV2Features& World::lv2_features() { return *_impl->lv2_features; } diff --git a/src/client/ClientStore.cpp b/src/client/ClientStore.cpp index a42efd16..2fdfa4a7 100644 --- a/src/client/ClientStore.cpp +++ b/src/client/ClientStore.cpp @@ -59,6 +59,7 @@ ClientStore::clear() void ClientStore::add_object(SPtr<ObjectModel> object) { + _log.info("Add object %1%\n", object->path()); // If we already have "this" object, merge the existing one into the new // one (with precedence to the new values). auto existing = find(object->path()); diff --git a/src/client/PluginModel.cpp b/src/client/PluginModel.cpp index f0e3c3a0..b0a2c5cb 100644 --- a/src/client/PluginModel.cpp +++ b/src/client/PluginModel.cpp @@ -38,8 +38,6 @@ namespace client { LilvWorld* PluginModel::_lilv_world = nullptr; const LilvPlugins* PluginModel::_lilv_plugins = nullptr; -Sord::World* PluginModel::_rdf_world = nullptr; - PluginModel::PluginModel(URIs& uris, const URI& uri, const Atom& type, @@ -65,7 +63,7 @@ PluginModel::PluginModel(URIs& uris, if (uris.ingen_Internal == _type) { set_property(uris.doap_name, - uris.forge.alloc(std::string(uri.fragment().substr(1)))); + uris.forge.alloc(uri.fragment().substr(1))); } } @@ -103,7 +101,7 @@ PluginModel::get_property(const URI& key) const // No lv2:symbol from data or engine, invent one if (key == _uris.lv2_symbol) { - string str = this->uri(); + string str = this->uri().str(); size_t last_delim = last_uri_delim(str); while (last_delim != string::npos && !contains_alpha_after(str, last_delim)) { @@ -264,12 +262,13 @@ heading(const std::string& text, bool html, unsigned level) } static std::string -link(const std::string& addr, bool html) +link(const URI& addr, bool html) { if (html) { - return std::string("<a href=\"") + addr + "\">" + addr + "</a>"; + return std::string("<a href=\"") + addr.str() + "\">" + addr.str() + + "</a>"; } else { - return addr; + return addr.str(); } } diff --git a/src/client/PluginUI.cpp b/src/client/PluginUI.cpp index a997d716..72a1fba0 100644 --- a/src/client/PluginUI.cpp +++ b/src/client/PluginUI.cpp @@ -224,9 +224,9 @@ PluginUI::create(ingen::World& world, bool PluginUI::instantiate() { - const URIs& uris = _world.uris(); - const std::string plugin_uri = _block->plugin()->uri(); - LilvWorld* lworld = _world.lilv_world(); + const URIs& uris = _world.uris(); + const URI& plugin_uri = _block->plugin()->uri(); + LilvWorld* lworld = _world.lilv_world(); // Load seeAlso files to access data like portNotification descriptions lilv_world_load_resource(lworld, lilv_ui_get_uri(_ui)); diff --git a/src/client/wscript b/src/client/wscript index 394c9e4d..c42046e1 100644 --- a/src/client/wscript +++ b/src/client/wscript @@ -10,7 +10,7 @@ def build(bld): target = 'ingen_client', install_path = '${LIBDIR}', use = 'libingen', - uselib = 'GLIBMM LV2 LILV SUIL RAUL SERD SORD SIGCPP') + uselib = 'GLIBMM LV2 LILV SUIL RAUL SERD SIGCPP') obj.source = ''' BlockModel.cpp diff --git a/src/gui/App.cpp b/src/gui/App.cpp index dfa34998..0e2292eb 100644 --- a/src/gui/App.cpp +++ b/src/gui/App.cpp @@ -87,7 +87,7 @@ App::App(ingen::World& world) , _requested_plugins(false) , _is_plugin(false) { - _world.conf().load_default("ingen", "gui.ttl"); + _world.conf().load_default(_world.rdf_world(), "ingen", "gui.ttl"); WidgetFactory::get_widget_derived("connect_win", _connect_window); WidgetFactory::get_widget_derived("messages_win", _messages_window); @@ -99,7 +99,6 @@ App::App(ingen::World& world) _about_dialog->property_program_name() = "Ingen"; _about_dialog->property_logo_icon_name() = "ingen"; - PluginModel::set_rdf_world(*world.rdf_world()); PluginModel::set_lilv_world(world.lilv_world()); using namespace std::placeholders; @@ -178,7 +177,8 @@ App::attach(SPtr<ingen::Interface> client) } if (_world.conf().option("dump").get<int32_t>()) { - _dumper = SPtr<StreamWriter>(new StreamWriter(_world.uri_map(), + _dumper = SPtr<StreamWriter>(new StreamWriter(_world.rdf_world(), + _world.uri_map(), _world.uris(), URI("ingen:/client"), stderr, @@ -469,8 +469,11 @@ App::quit(Gtk::Window* dialog_parent) Gtk::Main::quit(); try { - const std::string path = _world.conf().save( - _world.uri_map(), "ingen", "gui.ttl", Configuration::GUI); + const std::string path = _world.conf().save(_world.rdf_world(), + _world.uri_map(), + "ingen", + "gui.ttl", + Configuration::GUI); std::cout << fmt("Saved GUI settings to %1%\n", path); } catch (const std::exception& e) { std::cerr << fmt("Error saving GUI settings (%1%)\n", e.what()); diff --git a/src/gui/ConnectWindow.cpp b/src/gui/ConnectWindow.cpp index 209475e0..a7b2cbf7 100644 --- a/src/gui/ConnectWindow.cpp +++ b/src/gui/ConnectWindow.cpp @@ -228,7 +228,7 @@ ConnectWindow::connect(bool existing) if (_mode == Mode::CONNECT_REMOTE) { std::string uri_str = world.conf().option("connect").ptr<char>(); if (existing) { - uri_str = world.interface()->uri(); + uri_str = world.interface()->uri().str(); _connect_stage = 1; SPtr<client::SocketClient> client = dynamic_ptr_cast<client::SocketClient>( world.interface()); diff --git a/src/gui/GraphCanvas.cpp b/src/gui/GraphCanvas.cpp index 13b17bdf..40373a1a 100644 --- a/src/gui/GraphCanvas.cpp +++ b/src/gui/GraphCanvas.cpp @@ -636,7 +636,7 @@ serialise_arc(GanvEdge* arc, void* data) gui::Arc* garc = dynamic_cast<gui::Arc*>(Glib::wrap(GANV_EDGE(arc))); if (garc) { - serialiser->serialise_arc(Sord::Node(), garc->model()); + serialiser->serialise_arc({}, garc->model()); } } @@ -690,7 +690,7 @@ GraphCanvas::paste() // Figure out the copy graph base path Raul::Path copy_root("/"); if (base_uri) { - std::string base = *base_uri; + std::string base = base_uri->str(); if (base[base.size() - 1] == '/') { base = base.substr(0, base.size() - 1); } diff --git a/src/gui/LoadPluginWindow.cpp b/src/gui/LoadPluginWindow.cpp index bb84f96f..32a35c65 100644 --- a/src/gui/LoadPluginWindow.cpp +++ b/src/gui/LoadPluginWindow.cpp @@ -459,7 +459,7 @@ LoadPluginWindow::filter_changed() field = get_author_name(plugin); break; case CriteriaColumns::Criteria::URI: - field = plugin->uri(); + field = plugin->uri().str(); break; } diff --git a/src/gui/NodeMenu.cpp b/src/gui/NodeMenu.cpp index e2478592..ef0e80dc 100644 --- a/src/gui/NodeMenu.cpp +++ b/src/gui/NodeMenu.cpp @@ -235,11 +235,11 @@ NodeMenu::on_save_preset_activated() } void -NodeMenu::on_preset_activated(const std::string& uri) +NodeMenu::on_preset_activated(const URI& uri) { _app->set_property(block()->uri(), _app->uris().pset_preset, - _app->forge().make_urid(URI(uri))); + _app->forge().make_urid(uri)); } bool diff --git a/src/gui/NodeMenu.hpp b/src/gui/NodeMenu.hpp index 2a3268b4..799abef3 100644 --- a/src/gui/NodeMenu.hpp +++ b/src/gui/NodeMenu.hpp @@ -60,7 +60,7 @@ protected: void on_menu_enabled(); void on_menu_randomize(); void on_save_preset_activated(); - void on_preset_activated(const std::string& uri); + void on_preset_activated(const URI& uri); Gtk::MenuItem* _popup_gui_menuitem; Gtk::CheckMenuItem* _embed_gui_menuitem; diff --git a/src/gui/Port.cpp b/src/gui/Port.cpp index 14f87fc1..63e90bdd 100644 --- a/src/gui/Port.cpp +++ b/src/gui/Port.cpp @@ -289,8 +289,8 @@ Port::build_uri_menu() // Add a menu item for each such class for (const auto& v : values) { if (!v.first.empty()) { - const std::string qname = world.rdf_world()->prefixes().qualify(v.second); - const std::string label = qname + " - " + v.first; + const auto qname = world.env().qualify(v.second); + const std::string label = std::string(*qname) + " - " + v.first; menu->items().push_back(Gtk::Menu_Helpers::MenuElem(label)); Gtk::MenuItem* menu_item = &(menu->items().back()); menu_item->signal_activate().connect( diff --git a/src/gui/PropertiesWindow.cpp b/src/gui/PropertiesWindow.cpp index 9912f73a..32ed24e5 100644 --- a/src/gui/PropertiesWindow.cpp +++ b/src/gui/PropertiesWindow.cpp @@ -114,7 +114,8 @@ PropertiesWindow::add_property(const URI& key, const Atom& value) LilvNode* prop = lilv_new_uri(world.lilv_world(), key.c_str()); std::string name = rdfs::label(world, prop); if (name.empty()) { - name = world.rdf_world()->prefixes().qualify(key); + const auto qname = world.env().qualify(key); + name = qname ? std::string(*qname) : key.str(); } Gtk::Label* label = new Gtk::Label( std::string("<a href=\"") + key.string() + "\">" + name + "</a>", diff --git a/src/gui/ingen_gui_lv2.cpp b/src/gui/ingen_gui_lv2.cpp index 4817e9ae..4107d5c0 100644 --- a/src/gui/ingen_gui_lv2.cpp +++ b/src/gui/ingen_gui_lv2.cpp @@ -143,6 +143,7 @@ instantiate(const LV2UI_Descriptor* descriptor, // Set up an engine interface that writes LV2 atoms ui->engine = SPtr<ingen::Interface>( new ingen::AtomWriter( + ui->world->rdf_world(), ui->world->uri_map(), ui->world->uris(), *ui->sink)); ui->world->set_interface(ui->engine); diff --git a/src/gui/wscript b/src/gui/wscript index b33bd31e..2a52849e 100644 --- a/src/gui/wscript +++ b/src/gui/wscript @@ -57,11 +57,10 @@ def build(bld): LILV LV2 RAUL - SIGCPP SERD - SORD - SRATOM + SIGCPP SOUP + SRATOM SUIL WEBKIT ''') @@ -124,4 +123,4 @@ def build(bld): target = 'ingen_gui_lv2', install_path = '${LV2DIR}/ingen.lv2/', use = 'libingen libingen_gui', - uselib = 'LV2 SERD SORD SRATOM LILV RAUL GLIBMM GTKMM') + uselib = 'LV2 SERD SRATOM LILV RAUL GLIBMM GTKMM') diff --git a/src/ingen/ingen.cpp b/src/ingen/ingen.cpp index 15544c10..214e9e01 100644 --- a/src/ingen/ingen.cpp +++ b/src/ingen/ingen.cpp @@ -200,31 +200,26 @@ main(int argc, char** argv) *world, *engine_interface, graph, parent, symbol); } else if (conf.option("server-load").is_valid()) { const char* path = conf.option("server-load").ptr<char>(); - if (serd_uri_string_has_scheme((const uint8_t*)path)) { + if (serd_uri_string_has_scheme(path)) { std::cout << "Loading " << path << " (server side)" << std::endl; engine_interface->copy(URI(path), main_uri()); } else { - SerdNode uri = serd_node_new_file_uri( - (const uint8_t*)path, nullptr, nullptr, true); - std::cout << "Loading " << (const char*)uri.buf - << " (server side)" << std::endl; - engine_interface->copy(URI((const char*)uri.buf), main_uri()); - serd_node_free(&uri); + serd::Node uri = serd::make_file_uri(path); + std::cout << "Loading " << uri << " (server side)" << std::endl; + engine_interface->copy(URI(uri), main_uri()); } } // Save the currently loaded graph if (conf.option("save").is_valid()) { const char* path = conf.option("save").ptr<char>(); - if (serd_uri_string_has_scheme((const uint8_t*)path)) { + if (serd_uri_string_has_scheme(path)) { std::cout << "Saving to " << path << std::endl; engine_interface->copy(main_uri(), URI(path)); } else { - SerdNode uri = serd_node_new_file_uri( - (const uint8_t*)path, nullptr, nullptr, true); - std::cout << "Saving to " << (const char*)uri.buf << std::endl; - engine_interface->copy(main_uri(), URI((const char*)uri.buf)); - serd_node_free(&uri); + serd::Node uri = serd::make_file_uri(path); + std::cout << "Saving to " << uri << std::endl; + engine_interface->copy(main_uri(), URI(uri)); } } @@ -256,8 +251,12 @@ main(int argc, char** argv) } // Save configuration to restore preferences on next run - const std::string path = conf.save( - world->uri_map(), "ingen", "options.ttl", Configuration::GLOBAL); + const std::string path = conf.save(world->rdf_world(), + world->uri_map(), + "ingen", + "options.ttl", + Configuration::GLOBAL); + std::cout << fmt("Saved configuration to %1%\n", path); engine_interface.reset(); diff --git a/src/server/Engine.cpp b/src/server/Engine.cpp index 8256981b..f1a86792 100644 --- a/src/server/Engine.cpp +++ b/src/server/Engine.cpp @@ -68,31 +68,37 @@ INGEN_THREAD_LOCAL unsigned ThreadManager::flags(0); bool ThreadManager::single_threaded(true); Engine::Engine(ingen::World& world) - : _world(world) - , _options(new LV2Options(world.uris())) - , _buffer_factory(new BufferFactory(*this, world.uris())) - , _maid(new Raul::Maid) - , _worker(new Worker(world.log(), event_queue_size())) - , _sync_worker(new Worker(world.log(), event_queue_size(), true)) - , _broadcaster(new Broadcaster()) - , _control_bindings(new ControlBindings(*this)) - , _block_factory(new BlockFactory(world)) - , _undo_stack(new UndoStack(world.uris(), world.uri_map())) - , _redo_stack(new UndoStack(world.uris(), world.uri_map())) - , _post_processor(new PostProcessor(*this)) - , _pre_processor(new PreProcessor(*this)) - , _event_writer(new EventWriter(*this)) - , _interface(_event_writer) - , _atom_interface( - new AtomReader(world.uri_map(), world.uris(), world.log(), *_interface)) - , _root_graph(nullptr) - , _cycle_start_time(0) - , _rand_engine(reinterpret_cast<uintptr_t>(this)) - , _uniform_dist(0.0f, 1.0f) - , _quit_flag(false) - , _reset_load_flag(false) - , _atomic_bundles(world.conf().option("atomic-bundles").get<int32_t>()) - , _activated(false) + : _world(world) + , _options(new LV2Options(world.uris())) + , _buffer_factory(new BufferFactory(*this, world.uris())) + , _maid(new Raul::Maid) + , _worker(new Worker(world.log(), event_queue_size())) + , _sync_worker(new Worker(world.log(), event_queue_size(), true)) + , _broadcaster(new Broadcaster()) + , _control_bindings(new ControlBindings(*this)) + , _block_factory(new BlockFactory(world)) + , _undo_stack(new UndoStack(world.rdf_world(), + world.uris(), + world.uri_map())) + , _redo_stack(new UndoStack(world.rdf_world(), + world.uris(), + world.uri_map())) + , _post_processor(new PostProcessor(*this)) + , _pre_processor(new PreProcessor(*this)) + , _event_writer(new EventWriter(*this)) + , _interface(_event_writer) + , _atom_interface(new AtomReader(world.uri_map(), + world.uris(), + world.log(), + *_interface)) + , _root_graph(nullptr) + , _cycle_start_time(0) + , _rand_engine(reinterpret_cast<uintptr_t>(this)) + , _uniform_dist(0.0f, 1.0f) + , _quit_flag(false) + , _reset_load_flag(false) + , _atomic_bundles(world.conf().option("atomic-bundles").get<int32_t>()) + , _activated(false) { if (!world.store()) { world.set_store(std::make_shared<ingen::Store>()); @@ -125,7 +131,8 @@ Engine::Engine(ingen::World& world) _interface = std::make_shared<Tee>( Tee::Sinks{ _event_writer, - std::make_shared<StreamWriter>(world.uri_map(), + std::make_shared<StreamWriter>(world.rdf_world(), + world.uri_map(), world.uris(), URI("ingen:/engine"), stderr, diff --git a/src/server/Event.hpp b/src/server/Event.hpp index 7da4b955..f5c826b4 100644 --- a/src/server/Event.hpp +++ b/src/server/Event.hpp @@ -133,7 +133,7 @@ protected: } inline bool pre_process_done(Status st, const URI& subject) { - _err_subject = subject; + _err_subject = std::string{subject}; return pre_process_done(st); } diff --git a/src/server/LV2Plugin.cpp b/src/server/LV2Plugin.cpp index 01357d8d..40ba34e7 100644 --- a/src/server/LV2Plugin.cpp +++ b/src/server/LV2Plugin.cpp @@ -68,7 +68,7 @@ LV2Plugin::update_properties() Raul::Symbol LV2Plugin::symbol() const { - std::string working = uri(); + std::string working(uri()); if (working.back() == '/') { working = working.substr(0, working.length() - 1); } diff --git a/src/server/PreProcessor.cpp b/src/server/PreProcessor.cpp index 872302c0..76e0ac73 100644 --- a/src/server/PreProcessor.cpp +++ b/src/server/PreProcessor.cpp @@ -176,8 +176,10 @@ PreProcessor::run() UndoStack& undo_stack = *_engine.undo_stack(); UndoStack& redo_stack = *_engine.redo_stack(); AtomWriter undo_writer( + _engine.world().rdf_world(), _engine.world().uri_map(), _engine.world().uris(), undo_stack); AtomWriter redo_writer( + _engine.world().rdf_world(), _engine.world().uri_map(), _engine.world().uris(), redo_stack); ThreadManager::set_flag(THREAD_PRE_PROCESS); diff --git a/src/server/SocketListener.cpp b/src/server/SocketListener.cpp index b4b50a14..51e07b2b 100644 --- a/src/server/SocketListener.cpp +++ b/src/server/SocketListener.cpp @@ -92,7 +92,7 @@ ingen_listen(Engine* engine, Raul::Socket* unix_sock, Raul::Socket* net_sock) // Bind UNIX socket and create PID-less symbolic link const URI unix_uri(unix_scheme + unix_path); bool make_link = true; - if (!unix_sock->bind(unix_uri) || !unix_sock->listen()) { + if (!unix_sock->bind(unix_uri.str()) || !unix_sock->listen()) { world.log().error("Failed to create UNIX socket\n"); unix_sock->close(); make_link = false; @@ -130,7 +130,7 @@ ingen_listen(Engine* engine, Raul::Socket* unix_sock, Raul::Socket* net_sock) const int port = world.conf().option("engine-port").get<int32_t>(); std::ostringstream ss; ss << "tcp://*:" << port; - if (!net_sock->bind(URI(ss.str())) || !net_sock->listen()) { + if (!net_sock->bind(ss.str()) || !net_sock->listen()) { world.log().error("Failed to create TCP socket\n"); net_sock->close(); } else { diff --git a/src/server/SocketServer.hpp b/src/server/SocketServer.hpp index f3f02a26..86f81d65 100644 --- a/src/server/SocketServer.hpp +++ b/src/server/SocketServer.hpp @@ -43,14 +43,16 @@ public: , _sink(world.conf().option("dump").get<int32_t>() ? SPtr<Interface>( new Tee({SPtr<Interface>(new EventWriter(engine)), - SPtr<Interface>(new StreamWriter(world.uri_map(), + SPtr<Interface>(new StreamWriter(world.rdf_world(), + world.uri_map(), world.uris(), URI("ingen:/engine"), stderr, ColorContext::Color::CYAN))})) : SPtr<Interface>(new EventWriter(engine))) , _reader(new SocketReader(world, *_sink.get(), sock)) - , _writer(new SocketWriter(world.uri_map(), + , _writer(new SocketWriter(world.rdf_world(), + world.uri_map(), world.uris(), URI(sock->uri()), sock)) diff --git a/src/server/UndoStack.cpp b/src/server/UndoStack.cpp index a94617a5..d6829200 100644 --- a/src/server/UndoStack.cpp +++ b/src/server/UndoStack.cpp @@ -23,15 +23,14 @@ #include "lv2/patch/patch.h" #include "lv2/urid/urid.h" #include "serd/serd.h" -#include "sratom/sratom.h" +#include "sratom/sratom.hpp" #include <ctime> +#include <fstream> #include <iterator> #include <memory> -#define NS_RDF (const uint8_t*)"http://www.w3.org/1999/02/22-rdf-syntax-ns#" - -#define USTR(s) ((const uint8_t*)(s)) +#define NS_RDF "http://www.w3.org/1999/02/22-rdf-syntax-ns#" namespace ingen { namespace server { @@ -120,9 +119,9 @@ UndoStack::pop() struct BlankIDs { explicit BlankIDs(char c='b') : c(c) {} - SerdNode get() { + serd::Node get() { snprintf(buf, sizeof(buf), "%c%u", c, n++); - return serd_node_from_string(SERD_BLANK, USTR(buf)); + return serd::make_blank(buf); } char buf[16]{}; @@ -131,126 +130,120 @@ struct BlankIDs { }; struct ListContext { - explicit ListContext(BlankIDs& ids, unsigned flags, const SerdNode* s, const SerdNode* p) - : ids(ids) - , s(*s) - , p(*p) - , flags(flags | SERD_LIST_O_BEGIN) + explicit ListContext(BlankIDs& ids, + serd::StatementFlags flags, + const serd::Node& s, + const serd::Node& p) + : ids(ids) + , s(s) + , p(p) + , flags(flags | serd::StatementFlag::list_O) {} - SerdNode start_node(SerdWriter* writer) { - const SerdNode node = ids.get(); - serd_writer_write_statement(writer, flags, nullptr, &s, &p, &node, nullptr, nullptr); + serd::Node start_node(serd::Writer& writer) { + const serd::Node node = ids.get(); + writer.sink().write(flags, s, p, node); return node; } - void append(SerdWriter* writer, unsigned oflags, const SerdNode* value) { + void append(serd::Writer& writer, + serd::StatementFlags oflags, + const serd::Node& value) + { // s p node - const SerdNode node = start_node(writer); + const serd::Node node = start_node(writer); // node rdf:first value - p = serd_node_from_string(SERD_URI, NS_RDF "first"); - flags = SERD_LIST_CONT; - serd_writer_write_statement(writer, flags|oflags, nullptr, &node, &p, value, nullptr, nullptr); + p = serd::make_uri(NS_RDF "first"); + flags = {}; + writer.sink().write(flags | oflags, node, p, value); - end_node(writer, &node); + end_node(writer, node); } - void end_node(SerdWriter*, const SerdNode* node) { + void end_node(serd::Writer&, const serd::Node& node) { // Prepare for next call: node rdf:rest ... - s = *node; - p = serd_node_from_string(SERD_URI, NS_RDF "rest"); + s = node; + p = serd::make_uri(NS_RDF "rest"); } - void end(SerdWriter* writer) { - const SerdNode nil = serd_node_from_string(SERD_URI, NS_RDF "nil"); - serd_writer_write_statement(writer, flags, nullptr, &s, &p, &nil, nullptr, nullptr); + void end(serd::Writer& writer) { + const serd::Node nil = serd::make_uri(NS_RDF "nil"); + writer.sink().write(flags, s, p, nil); } - BlankIDs& ids; - SerdNode s; - SerdNode p; - unsigned flags; + BlankIDs& ids; + serd::Node s; + serd::Node p; + serd::StatementFlags flags; }; void -UndoStack::write_entry(Sratom* sratom, - SerdWriter* writer, - const SerdNode* const subject, +UndoStack::write_entry(sratom::Streamer& streamer, + serd::Writer& writer, + const serd::Node& subject, const UndoStack::Entry& entry) { char time_str[24]; strftime(time_str, sizeof(time_str), "%FT%T", gmtime(&entry.time)); - // entry rdf:type ingen:UndoEntry - SerdNode p = serd_node_from_string(SERD_URI, USTR(INGEN_NS "time")); - SerdNode o = serd_node_from_string(SERD_LITERAL, USTR(time_str)); - serd_writer_write_statement(writer, SERD_ANON_CONT, nullptr, subject, &p, &o, nullptr, nullptr); + writer.sink().write({}, + subject, + serd::make_uri(INGEN_NS "time"), + serd::make_string(time_str)); - p = serd_node_from_string(SERD_URI, USTR(INGEN_NS "events")); + serd::Node p = serd::make_uri(INGEN_NS "events"); BlankIDs ids('e'); - ListContext ctx(ids, SERD_ANON_CONT, subject, &p); + ListContext ctx(ids, {}, subject, p); for (const LV2_Atom* atom : entry.events) { - const SerdNode node = ctx.start_node(writer); - - p = serd_node_from_string(SERD_URI, NS_RDF "first"); - ctx.flags = SERD_LIST_CONT; - sratom_write(sratom, &_map.urid_unmap_feature()->urid_unmap, SERD_LIST_CONT, - &node, &p, - atom->type, atom->size, LV2_ATOM_BODY_CONST(atom)); + const serd::Node node = ctx.start_node(writer); - ctx.end_node(writer, &node); + p = serd::make_uri(NS_RDF "first"); + ctx.flags = {}; + streamer.write(writer.sink(), node, p, *atom); + ctx.end_node(writer, node); } ctx.end(writer); } void -UndoStack::save(FILE* stream, const char* name) +UndoStack::save(std::ofstream& stream, const char* name) { - SerdEnv* env = serd_env_new(nullptr); - serd_env_set_prefix_from_strings(env, USTR("atom"), USTR(LV2_ATOM_PREFIX)); - serd_env_set_prefix_from_strings(env, USTR("ingen"), USTR(INGEN_NS)); - serd_env_set_prefix_from_strings(env, USTR("patch"), USTR(LV2_PATCH_PREFIX)); - - const SerdNode base = serd_node_from_string(SERD_URI, USTR("ingen:/")); - SerdURI base_uri; - serd_uri_parse(base.buf, &base_uri); - - SerdWriter* writer = serd_writer_new( - SERD_TURTLE, - (SerdStyle)(SERD_STYLE_RESOLVED|SERD_STYLE_ABBREVIATED|SERD_STYLE_CURIED), - env, - &base_uri, - serd_file_sink, - stream); + serd::Env env; + env.set_prefix("atom", LV2_ATOM_PREFIX); + env.set_prefix("ingen", INGEN_NS); + env.set_prefix("patch", LV2_PATCH_PREFIX); + + const serd::Node base = serd::make_uri("ingen:/"); + + serd::Writer writer(_world, + serd::Syntax::Turtle, + {}, + env, + stream); // Configure sratom to write directly to the writer (and thus the socket) - Sratom* sratom = sratom_new(&_map.urid_map_feature()->urid_map); - sratom_set_sink(sratom, - (const char*)base.buf, - (SerdStatementSink)serd_writer_write_statement, - (SerdEndSink)serd_writer_end_anon, - writer); + sratom::Streamer streamer{_world, + _map.urid_map_feature()->urid_map, + _map.urid_unmap_feature()->urid_unmap}; - SerdNode s = serd_node_from_string(SERD_BLANK, (const uint8_t*)name); - SerdNode p = serd_node_from_string(SERD_URI, USTR(INGEN_NS "entries")); + serd::Node s = serd::make_blank(name); + serd::Node p = serd::make_uri(INGEN_NS "entries"); BlankIDs ids('u'); - ListContext ctx(ids, 0, &s, &p); + ListContext ctx(ids, {}, s, p); for (const Entry& e : _stack) { - const SerdNode entry = ids.get(); - ctx.append(writer, SERD_ANON_O_BEGIN, &entry); - write_entry(sratom, writer, &entry, e); - serd_writer_end_anon(writer, &entry); + const serd::Node entry = ids.get(); + ctx.append(writer, serd::StatementFlag::anon_O, entry); + write_entry(streamer, writer, entry, e); + writer.sink().end(entry); } ctx.end(writer); - sratom_free(sratom); - serd_writer_finish(writer); - serd_writer_free(writer); + writer.finish(); } } // namespace server diff --git a/src/server/UndoStack.hpp b/src/server/UndoStack.hpp index 04021b99..7d79e7fc 100644 --- a/src/server/UndoStack.hpp +++ b/src/server/UndoStack.hpp @@ -21,8 +21,7 @@ #include "ingen/ingen.h" #include "lv2/atom/atom.h" #include "lv2/atom/util.h" -#include "serd/serd.h" -#include "sratom/sratom.h" +#include "serd/serd.hpp" #include <cstdint> #include <cstdio> @@ -30,6 +29,9 @@ #include <cstring> #include <ctime> #include <deque> +#include <iosfwd> + +namespace sratom { class Streamer; } namespace ingen { @@ -80,7 +82,10 @@ public: std::deque<LV2_Atom*> events; }; - UndoStack(URIs& uris, URIMap& map) : _uris(uris), _map(map), _depth(0) {} + UndoStack(serd::World& world, URIs& uris, URIMap& map) + : _world(world), _uris(uris), _map(map), _depth(0) + { + } int start_entry(); bool write(const LV2_Atom* msg, int32_t default_id=0) override; @@ -89,17 +94,18 @@ public: bool empty() const { return _stack.empty(); } Entry pop(); - void save(FILE* stream, const char* name="undo"); + void save(std::ofstream& stream, const char* name="undo"); private: bool ignore_later_event(const LV2_Atom* first, const LV2_Atom* second) const; - void write_entry(Sratom* sratom, - SerdWriter* writer, - const SerdNode* subject, - const Entry& entry); + void write_entry(sratom::Streamer& streamer, + serd::Writer& writer, + const serd::Node& subject, + const Entry& entry); + serd::World& _world; URIs& _uris; URIMap& _map; std::deque<Entry> _stack; diff --git a/src/server/events/Copy.cpp b/src/server/events/Copy.cpp index 5418af4b..5ac31f55 100644 --- a/src/server/events/Copy.cpp +++ b/src/server/events/Copy.cpp @@ -131,9 +131,10 @@ Copy::engine_to_engine(PreProcessContext& ctx) } static bool -ends_with(const std::string& str, const std::string& end) +ends_with(const URI& uri, const std::string& end) { - if (str.length() >= end.length()) { + const auto& str = uri.str(); + if (str.length() >= end.length()) { return !str.compare(str.length() - end.length(), end.length(), end); } return false; diff --git a/src/server/events/Delta.cpp b/src/server/events/Delta.cpp index 0a7b05ea..ab751b76 100644 --- a/src/server/events/Delta.cpp +++ b/src/server/events/Delta.cpp @@ -35,6 +35,8 @@ #include "ingen/World.hpp" #include "raul/Maid.hpp" +#include <boost/optional/optional_io.hpp> + #include <mutex> #include <set> #include <string> @@ -364,7 +366,7 @@ Delta::pre_process(PreProcessContext& ctx) _status = Status::BAD_VALUE_TYPE; } } else if (key == uris.pset_preset) { - URI uri; + boost::optional<URI> uri; if (uris.forge.is_uri(value)) { const std::string uri_str = uris.forge.str(value, false); if (URI::is_valid(uri_str)) { @@ -374,9 +376,9 @@ Delta::pre_process(PreProcessContext& ctx) uri = URI(FilePath(value.ptr<char>())); } - if (!uri.empty()) { + if (uri) { op = SpecialType::PRESET; - if ((_state = block->load_preset(uri))) { + if ((_state = block->load_preset(*uri))) { lilv_state_emit_port_values( _state, s_add_set_event, this); } else { diff --git a/src/server/ingen_lv2.cpp b/src/server/ingen_lv2.cpp index 57663344..8a639765 100644 --- a/src/server/ingen_lv2.cpp +++ b/src/server/ingen_lv2.cpp @@ -60,8 +60,7 @@ #include "raul/RingBuffer.hpp" #include "raul/Semaphore.hpp" #include "raul/Symbol.hpp" -#include "serd/serd.h" -#include "sord/sordmm.hpp" +#include "serd/serd.hpp" #include <algorithm> #include <cstdint> @@ -123,7 +122,8 @@ public: engine.world().uris(), engine.world().log(), *engine.world().interface().get()) - , _writer(engine.world().uri_map(), + , _writer(engine.world().rdf_world(), + engine.world().uri_map(), engine.world().uris(), *this) , _from_ui(ui_ring_size(block_length)) @@ -460,11 +460,10 @@ struct IngenPlugin { static Lib::Graphs find_graphs(const URI& manifest_uri) { - Sord::World world; + serd::World world; Parser parser; const std::set<Parser::ResourceRecord> resources = parser.find_resources( - world, manifest_uri, URI(INGEN__Graph)); @@ -512,11 +511,8 @@ ingen_instantiate(const LV2_Descriptor* descriptor, set_bundle_path(bundle_path); const std::string manifest_path = ingen::bundle_file_path("manifest.ttl"); - SerdNode manifest_node = serd_node_new_file_uri( - (const uint8_t*)manifest_path.c_str(), nullptr, nullptr, true); - - Lib::Graphs graphs = find_graphs(URI((const char*)manifest_node.buf)); - serd_node_free(&manifest_node); + serd::Node manifest_node = serd::make_file_uri(manifest_path); + Lib::Graphs graphs = find_graphs(URI(manifest_node)); const LV2Graph* graph = nullptr; for (const auto& g : graphs) { @@ -823,13 +819,9 @@ LV2Graph::LV2Graph(Parser::ResourceRecord record) Lib::Lib(const char* bundle_path) { ingen::set_bundle_path(bundle_path); - const std::string manifest_path = ingen::bundle_file_path("manifest.ttl"); - SerdNode manifest_node = serd_node_new_file_uri( - (const uint8_t*)manifest_path.c_str(), nullptr, nullptr, true); - - graphs = find_graphs(URI((const char*)manifest_node.buf)); - serd_node_free(&manifest_node); + const auto manifest_path = ingen::bundle_file_path("manifest.ttl"); + graphs = find_graphs(serd::make_file_uri(manifest_path.string())); } static void diff --git a/src/server/wscript b/src/server/wscript index 00588915..137b85c9 100644 --- a/src/server/wscript +++ b/src/server/wscript @@ -53,7 +53,7 @@ def build(bld): mix.cpp ''' - core_libs = 'LV2 LILV RAUL SERD SORD SRATOM' + core_libs = 'LV2 LILV RAUL SERD SRATOM' bld(features = 'cxx cxxshlib', source = core_source, diff --git a/src/wscript b/src/wscript index 72c7d48c..39789778 100644 --- a/src/wscript +++ b/src/wscript @@ -41,7 +41,7 @@ def build(bld): vnum = bld.env.INGEN_VERSION, install_path = '${LIBDIR}', lib = lib, - uselib = 'LV2 LILV RAUL SERD SORD SRATOM', + uselib = 'LV2 LILV RAUL SERD SRATOM', cxxflags = (['-fvisibility=hidden'] + bld.env.PTHREAD_CFLAGS + bld.env.INGEN_TEST_CXXFLAGS), linkflags = bld.env.PTHREAD_LINKFLAGS + bld.env.INGEN_TEST_LINKFLAGS) |