summaryrefslogtreecommitdiffstats
path: root/src/serialisation/Parser.cpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2011-05-25 00:32:23 +0000
committerDavid Robillard <d@drobilla.net>2011-05-25 00:32:23 +0000
commitd6bd53fe5ca146398e9c3547b6cd9a06cf56d90f (patch)
treeabc77893f16cb66cce1fd66afc0f8e77bdbbc40a /src/serialisation/Parser.cpp
parent1b29d7799c32b7be8bc563d2b21349115be04e6e (diff)
downloadingen-d6bd53fe5ca146398e9c3547b6cd9a06cf56d90f.tar.gz
ingen-d6bd53fe5ca146398e9c3547b6cd9a06cf56d90f.tar.bz2
ingen-d6bd53fe5ca146398e9c3547b6cd9a06cf56d90f.zip
Move sanitised serialisation headers to public include directory
git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@3320 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/serialisation/Parser.cpp')
-rw-r--r--src/serialisation/Parser.cpp652
1 files changed, 350 insertions, 302 deletions
diff --git a/src/serialisation/Parser.cpp b/src/serialisation/Parser.cpp
index 198a520e..27110c9d 100644
--- a/src/serialisation/Parser.cpp
+++ b/src/serialisation/Parser.cpp
@@ -38,8 +38,7 @@
#include "shared/World.hpp"
#include "shared/LV2URIMap.hpp"
-#include "Parser.hpp"
-#include "names.hpp"
+#include "ingen/serialisation/Parser.hpp"
#define LOG(s) s << "[Parser] "
@@ -102,226 +101,6 @@ skip_property(const Sord::Node& predicate)
|| predicate.to_string() == "http://lv2plug.in/ns/lv2core#port");
}
-Parser::Parser(Ingen::Shared::World& world)
-{
-}
-
-Parser::PatchRecords
-Parser::find_patches(Ingen::Shared::World* world,
- SerdEnv* env,
- const Glib::ustring& manifest_uri)
-{
- const Sord::URI ingen_Patch (*world->rdf_world(), NS_INGEN "Patch");
- const Sord::URI rdf_type (*world->rdf_world(), NS_RDF "type");
- const Sord::URI rdfs_seeAlso(*world->rdf_world(), NS_RDFS "seeAlso");
-
- Sord::Model model(*world->rdf_world(), manifest_uri);
- model.load_file(env, SERD_TURTLE, manifest_uri);
-
- std::list<PatchRecord> records;
- for (Sord::Iter i = model.find(nil, rdf_type, ingen_Patch); !i.end(); ++i) {
- const Sord::Node patch = i.get_subject();
- Sord::Iter f = model.find(patch, rdfs_seeAlso, nil);
- if (!f.end()) {
- records.push_back(PatchRecord(patch.to_c_string(),
- f.get_object().to_c_string()));
- } else {
- LOG(error) << "Patch has no rdfs:seeAlso" << endl;
- }
- }
- return records;
-}
-
-/** Parse a patch from RDF into a CommonInterface (engine or client).
- * @return whether or not load was successful.
- */
-bool
-Parser::parse_file(Ingen::Shared::World* world,
- Ingen::CommonInterface* target,
- Glib::ustring file_uri,
- boost::optional<Raul::Path> parent,
- boost::optional<Raul::Symbol> symbol,
- boost::optional<GraphObject::Properties> data)
-{
- const size_t colon = file_uri.find(":");
- if (colon != Glib::ustring::npos) {
- const Glib::ustring scheme = file_uri.substr(0, colon);
- if (scheme != "file") {
- LOG(error) << (boost::format("Unsupported URI scheme `%1%'")
- % scheme) << endl;
- return false;
- }
- } else {
- file_uri = Glib::ustring("file://") + file_uri;
- }
-
- const bool is_bundle = (file_uri.substr(file_uri.length() - 4) != ".ttl");
-
- if (is_bundle && file_uri[file_uri.length() - 1] != '/') {
- file_uri.append("/");
- }
-
- SerdNode base_node = serd_node_from_string(
- SERD_URI, (const uint8_t*)file_uri.c_str());
- SerdEnv* env = serd_env_new(&base_node);
-
- if (file_uri.substr(file_uri.length() - 4) != ".ttl") {
- // Not a Turtle file, try to open it as a bundle
- if (file_uri[file_uri.length() - 1] != '/') {
- file_uri.append("/");
- }
- Parser::PatchRecords records = find_patches(world, env, file_uri + "manifest.ttl");
- if (!records.empty()) {
- file_uri = records.front().file_uri;
- }
- }
-
- base_node = serd_node_from_string(
- SERD_URI, (const uint8_t*)file_uri.c_str());
- serd_env_set_base_uri(env, &base_node);
-
- // Load patch file into model
- Sord::Model model(*world->rdf_world(), file_uri);
- model.load_file(env, SERD_TURTLE, file_uri);
-
- serd_env_free(env);
-
- LOG(info) << "Parsing " << file_uri << endl;
- if (parent)
- LOG(info) << "Parent: " << *parent << endl;
- if (symbol)
- LOG(info) << "Symbol: " << *symbol << endl;
-
- boost::optional<Path> parsed_path
- = parse(world, target, model, file_uri, Path("/"), parent, symbol, data);
-
- if (parsed_path) {
- target->set_property(*parsed_path, "http://drobilla.net/ns/ingen#document",
- Atom(Atom::URI, file_uri.c_str()));
- } else {
- LOG(warn) << "Document URI lost" << endl;
- }
-
- return parsed_path;
-}
-
-bool
-Parser::parse_string(Ingen::Shared::World* world,
- Ingen::CommonInterface* target,
- const Glib::ustring& str,
- const Glib::ustring& base_uri,
- boost::optional<Raul::Path> parent,
- boost::optional<Raul::Symbol> symbol,
- boost::optional<GraphObject::Properties> data)
-{
- // Load string into model
- Sord::Model model(*world->rdf_world(), base_uri);
- SerdEnv* env = serd_env_new(NULL);
- model.load_string(env, SERD_TURTLE, str.c_str(), str.length(), base_uri);
- serd_env_free(env);
-
- LOG(info) << "Parsing string";
- if (!base_uri.empty())
- info << " (base " << base_uri << ")";
- info << endl;
-
- boost::optional<Raul::Path> data_path;
- bool ret = parse(world, target, model, base_uri, data_path, parent, symbol, data);
- Sord::URI subject(*world->rdf_world(), base_uri);
- parse_connections(world, target, model, subject, parent ? *parent : "/");
-
- return ret;
-}
-
-boost::optional<Path>
-Parser::parse(Ingen::Shared::World* world,
- Ingen::CommonInterface* target,
- Sord::Model& model,
- Glib::ustring document_uri,
- boost::optional<Raul::Path> data_path,
- boost::optional<Raul::Path> parent,
- boost::optional<Raul::Symbol> symbol,
- boost::optional<GraphObject::Properties> data)
-{
- const Sord::URI patch_class (*world->rdf_world(), NS_INGEN "Patch");
- const Sord::URI node_class (*world->rdf_world(), NS_INGEN "Node");
- const Sord::URI port_class (*world->rdf_world(), NS_INGEN "Port");
- const Sord::URI internal_class(*world->rdf_world(), NS_INGEN "Internal");
- const Sord::URI in_port_class (*world->rdf_world(), NS_LV2 "InputPort");
- const Sord::URI out_port_class(*world->rdf_world(), NS_LV2 "OutputPort");
- const Sord::URI lv2_class (*world->rdf_world(), NS_LV2 "Plugin");
- const Sord::URI rdf_type (*world->rdf_world(), NS_RDF "type");
-
- Sord::Node subject = nil;
- if (data_path && data_path->is_root()) {
- subject = model.base_uri();
- } else if (data_path) {
- subject = Sord::URI(*world->rdf_world(), data_path->chop_start("/"));
- }
-
- Raul::Path path("/");
- if (data_path) {
- path = *data_path;
- } else if (parent && symbol) {
- path = parent->child(*symbol);
- }
-
- // Get all subjects and their types (?subject a ?type)
- typedef std::map< Sord::Node, std::set<Sord::Node> > Subjects;
- 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());
- Subjects::iterator s = subjects.find(subject);
- if (s == subjects.end()) {
- std::set<Sord::Node> types;
- types.insert(rdf_class);
- subjects.insert(make_pair(subject, types));
- } else {
- s->second.insert(rdf_class);
- }
- }
-
- // Parse and create each subject
- boost::optional<Path> ret;
- boost::optional<Path> root_path;
- for (Subjects::const_iterator i = subjects.begin(); i != subjects.end(); ++i) {
- const Sord::Node& subject = i->first;
- const std::set<Sord::Node>& types = i->second;
- if (types.find(patch_class) != types.end()) {
- ret = parse_patch(world, target, model, subject, parent, symbol, data);
- } else if (types.find(node_class) != types.end()) {
- ret = parse_node(world, target, model,
- subject, path.child(subject.to_string()),
- data);
- } else if (types.find(port_class) != types.end()) {
- parse_properties(world, target, model, subject, path, data);
- ret = path;
- } else {
- LOG(error) << "Subject has no known types" << endl;
- }
-
- if (!ret) {
- LOG(error) << "Failed to parse " << path << endl;
- LOG(error) << "Types:" << endl;
- for (std::set<Sord::Node>::const_iterator t = types.begin();
- t != types.end(); ++t) {
- LOG(error) << " :: " << *t << endl;
- assert((*t).is_uri());
- }
- return boost::optional<Path>();
- }
-
- if (data_path && subject.to_string() == data_path->str()) {
- root_path = ret;
- }
- }
-
- return path;
-}
-
static Resource::Properties
get_properties(Sord::Model& model,
const Sord::Node& subject)
@@ -376,14 +155,122 @@ get_port(Ingen::Shared::World* world,
return index;
}
-boost::optional<Path>
-Parser::parse_patch(Ingen::Shared::World* world,
- Ingen::CommonInterface* target,
- Sord::Model& model,
- const Sord::Node& subject_node,
- boost::optional<Raul::Path> parent,
- boost::optional<Raul::Symbol> a_symbol,
- boost::optional<GraphObject::Properties> data)
+static boost::optional<Raul::Path>
+parse(
+ Shared::World* world,
+ CommonInterface* target,
+ Sord::Model& model,
+ Glib::ustring document_uri,
+ boost::optional<Raul::Path> data_path = boost::optional<Raul::Path>(),
+ boost::optional<Raul::Path> parent = boost::optional<Raul::Path>(),
+ boost::optional<Raul::Symbol> symbol = boost::optional<Raul::Symbol>(),
+ boost::optional<Resource::Properties> data = boost::optional<Resource::Properties>());
+
+static boost::optional<Raul::Path>
+parse_patch(
+ Shared::World* world,
+ CommonInterface* target,
+ Sord::Model& model,
+ const Sord::Node& subject,
+ boost::optional<Raul::Path> parent = boost::optional<Raul::Path>(),
+ boost::optional<Raul::Symbol> symbol = boost::optional<Raul::Symbol>(),
+ boost::optional<Resource::Properties> data = boost::optional<Resource::Properties>());
+
+
+static boost::optional<Raul::Path>
+parse_node(
+ Shared::World* world,
+ CommonInterface* target,
+ Sord::Model& model,
+ const Sord::Node& subject,
+ const Raul::Path& path,
+ boost::optional<Resource::Properties> data = boost::optional<Resource::Properties>());
+
+
+static bool
+parse_properties(
+ Shared::World* world,
+ CommonInterface* target,
+ Sord::Model& model,
+ const Sord::Node& subject,
+ const Raul::URI& uri,
+ boost::optional<Resource::Properties> data = boost::optional<Resource::Properties>());
+
+static bool
+parse_connections(
+ Shared::World* world,
+ CommonInterface* target,
+ Sord::Model& model,
+ const Sord::Node& subject,
+ const Raul::Path& patch);
+
+static boost::optional<Path>
+parse_node(Ingen::Shared::World* world,
+ Ingen::CommonInterface* target,
+ Sord::Model& model,
+ const Sord::Node& subject,
+ const Raul::Path& path,
+ boost::optional<GraphObject::Properties> data)
+{
+ const LV2URIMap& uris = *world->uris().get();
+
+ Sord::URI rdf_instanceOf(*world->rdf_world(), NS_RDF "instanceOf");
+
+ Sord::Iter i = model.find(subject, rdf_instanceOf, nil);
+ if (i.end() || i.get_object().type() != Sord::Node::URI) {
+ LOG(error) << "Node missing mandatory rdf:instanceOf" << endl;
+ return boost::optional<Path>();
+ }
+
+ const std::string type_uri = relative_uri(
+ model.base_uri().to_string(),
+ i.get_object().to_string(),
+ false);
+
+ if (!serd_uri_string_has_scheme((const uint8_t*)type_uri.c_str())) {
+ SerdURI base_uri;
+ serd_uri_parse(model.base_uri().to_u_string(), &base_uri);
+
+ SerdURI ignored;
+ SerdNode sub_uri = serd_node_new_uri_from_string(
+ i.get_object().to_u_string(),
+ &base_uri,
+ &ignored);
+
+ const std::string sub_uri_str((const char*)sub_uri.buf);
+ std::string basename = get_basename(sub_uri_str);
+
+ const std::string sub_file =
+ string((const char*)sub_uri.buf) + "/" + basename + ".ttl";
+
+ Sord::Model sub_model(*world->rdf_world(), sub_file);
+ SerdEnv* env = serd_env_new(NULL);
+ sub_model.load_file(env, SERD_TURTLE, sub_file);
+ serd_env_free(env);
+
+ Sord::URI sub_node(*world->rdf_world(), sub_file);
+ parse_patch(world, target, sub_model, sub_node,
+ path.parent(), Raul::Symbol(path.symbol()));
+
+ parse_patch(world, target, model, subject,
+ path.parent(), Raul::Symbol(path.symbol()));
+ } else {
+ Resource::Properties props = get_properties(model, subject);
+ props.insert(make_pair(uris.rdf_type,
+ Raul::URI(uris.ingen_Node)));
+ target->put(path, props);
+ }
+ return path;
+}
+
+static boost::optional<Path>
+parse_patch(Ingen::Shared::World* world,
+ Ingen::CommonInterface* target,
+ Sord::Model& model,
+ const Sord::Node& subject_node,
+ boost::optional<Raul::Path> parent,
+ boost::optional<Raul::Symbol> a_symbol,
+ boost::optional<GraphObject::Properties> data)
{
const Sord::URI ingen_node(*world->rdf_world(), NS_INGEN "node");
const Sord::URI ingen_polyphony(*world->rdf_world(), NS_INGEN "polyphony");
@@ -494,71 +381,12 @@ Parser::parse_patch(Ingen::Shared::World* world,
return patch_path;
}
-boost::optional<Path>
-Parser::parse_node(Ingen::Shared::World* world,
- Ingen::CommonInterface* target,
- Sord::Model& model,
- const Sord::Node& subject,
- const Raul::Path& path,
- boost::optional<GraphObject::Properties> data)
-{
- const LV2URIMap& uris = *world->uris().get();
-
- Sord::URI rdf_instanceOf(*world->rdf_world(), NS_RDF "instanceOf");
-
- Sord::Iter i = model.find(subject, rdf_instanceOf, nil);
- if (i.end() || i.get_object().type() != Sord::Node::URI) {
- LOG(error) << "Node missing mandatory rdf:instanceOf" << endl;
- return boost::optional<Path>();
- }
-
- const std::string type_uri = relative_uri(
- model.base_uri().to_string(),
- i.get_object().to_string(),
- false);
-
- if (!serd_uri_string_has_scheme((const uint8_t*)type_uri.c_str())) {
- SerdURI base_uri;
- serd_uri_parse(model.base_uri().to_u_string(), &base_uri);
-
- SerdURI ignored;
- SerdNode sub_uri = serd_node_new_uri_from_string(
- i.get_object().to_u_string(),
- &base_uri,
- &ignored);
-
- const std::string sub_uri_str((const char*)sub_uri.buf);
- std::string basename = get_basename(sub_uri_str);
-
- const std::string sub_file =
- string((const char*)sub_uri.buf) + "/" + basename + ".ttl";
-
- Sord::Model sub_model(*world->rdf_world(), sub_file);
- SerdEnv* env = serd_env_new(NULL);
- sub_model.load_file(env, SERD_TURTLE, sub_file);
- serd_env_free(env);
-
- Sord::URI sub_node(*world->rdf_world(), sub_file);
- parse_patch(world, target, sub_model, sub_node,
- path.parent(), Raul::Symbol(path.symbol()));
-
- parse_patch(world, target, model, subject,
- path.parent(), Raul::Symbol(path.symbol()));
- } else {
- Resource::Properties props = get_properties(model, subject);
- props.insert(make_pair(uris.rdf_type,
- Raul::URI(uris.ingen_Node)));
- target->put(path, props);
- }
- return path;
-}
-
-bool
-Parser::parse_connections(Ingen::Shared::World* world,
- Ingen::CommonInterface* target,
- Sord::Model& model,
- const Sord::Node& subject,
- const Raul::Path& parent)
+static bool
+parse_connections(Ingen::Shared::World* world,
+ Ingen::CommonInterface* target,
+ Sord::Model& model,
+ const Sord::Node& subject,
+ const Raul::Path& parent)
{
Sord::URI ingen_connection(*world->rdf_world(), NS_INGEN "connection");
Sord::URI ingen_source(*world->rdf_world(), NS_INGEN "source");
@@ -602,13 +430,13 @@ Parser::parse_connections(Ingen::Shared::World* world,
return true;
}
-bool
-Parser::parse_properties(Ingen::Shared::World* world,
- Ingen::CommonInterface* target,
- Sord::Model& model,
- const Sord::Node& subject,
- const Raul::URI& uri,
- boost::optional<GraphObject::Properties> data)
+static bool
+parse_properties(Ingen::Shared::World* world,
+ Ingen::CommonInterface* target,
+ Sord::Model& model,
+ const Sord::Node& subject,
+ const Raul::URI& uri,
+ boost::optional<GraphObject::Properties> data)
{
Resource::Properties properties;
for (Sord::Iter i = model.find(subject, nil, nil); !i.end(); ++i) {
@@ -629,6 +457,226 @@ Parser::parse_properties(Ingen::Shared::World* world,
return true;
}
+static boost::optional<Path>
+parse(Ingen::Shared::World* world,
+ Ingen::CommonInterface* target,
+ Sord::Model& model,
+ Glib::ustring document_uri,
+ boost::optional<Raul::Path> data_path,
+ boost::optional<Raul::Path> parent,
+ boost::optional<Raul::Symbol> symbol,
+ boost::optional<GraphObject::Properties> data)
+{
+ const Sord::URI patch_class (*world->rdf_world(), NS_INGEN "Patch");
+ const Sord::URI node_class (*world->rdf_world(), NS_INGEN "Node");
+ const Sord::URI port_class (*world->rdf_world(), NS_INGEN "Port");
+ const Sord::URI internal_class(*world->rdf_world(), NS_INGEN "Internal");
+ const Sord::URI in_port_class (*world->rdf_world(), NS_LV2 "InputPort");
+ const Sord::URI out_port_class(*world->rdf_world(), NS_LV2 "OutputPort");
+ const Sord::URI lv2_class (*world->rdf_world(), NS_LV2 "Plugin");
+ const Sord::URI rdf_type (*world->rdf_world(), NS_RDF "type");
+
+ Sord::Node subject = nil;
+ if (data_path && data_path->is_root()) {
+ subject = model.base_uri();
+ } else if (data_path) {
+ subject = Sord::URI(*world->rdf_world(), data_path->chop_start("/"));
+ }
+
+ Raul::Path path("/");
+ if (data_path) {
+ path = *data_path;
+ } else if (parent && symbol) {
+ path = parent->child(*symbol);
+ }
+
+ // Get all subjects and their types (?subject a ?type)
+ typedef std::map< Sord::Node, std::set<Sord::Node> > Subjects;
+ 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());
+ Subjects::iterator s = subjects.find(subject);
+ if (s == subjects.end()) {
+ std::set<Sord::Node> types;
+ types.insert(rdf_class);
+ subjects.insert(make_pair(subject, types));
+ } else {
+ s->second.insert(rdf_class);
+ }
+ }
+
+ // Parse and create each subject
+ boost::optional<Path> ret;
+ boost::optional<Path> root_path;
+ for (Subjects::const_iterator i = subjects.begin(); i != subjects.end(); ++i) {
+ const Sord::Node& subject = i->first;
+ const std::set<Sord::Node>& types = i->second;
+ if (types.find(patch_class) != types.end()) {
+ ret = parse_patch(world, target, model, subject, parent, symbol, data);
+ } else if (types.find(node_class) != types.end()) {
+ ret = parse_node(world, target, model,
+ subject, path.child(subject.to_string()),
+ data);
+ } else if (types.find(port_class) != types.end()) {
+ parse_properties(world, target, model, subject, path, data);
+ ret = path;
+ } else {
+ LOG(error) << "Subject has no known types" << endl;
+ }
+
+ if (!ret) {
+ LOG(error) << "Failed to parse " << path << endl;
+ LOG(error) << "Types:" << endl;
+ for (std::set<Sord::Node>::const_iterator t = types.begin();
+ t != types.end(); ++t) {
+ LOG(error) << " :: " << *t << endl;
+ assert((*t).is_uri());
+ }
+ return boost::optional<Path>();
+ }
+
+ if (data_path && subject.to_string() == data_path->str()) {
+ root_path = ret;
+ }
+ }
+
+ return path;
+}
+
+Parser::Parser(Ingen::Shared::World& world)
+{
+}
+
+Parser::PatchRecords
+Parser::find_patches(Ingen::Shared::World* world,
+ SerdEnv* env,
+ const Glib::ustring& manifest_uri)
+{
+ const Sord::URI ingen_Patch (*world->rdf_world(), NS_INGEN "Patch");
+ const Sord::URI rdf_type (*world->rdf_world(), NS_RDF "type");
+ const Sord::URI rdfs_seeAlso(*world->rdf_world(), NS_RDFS "seeAlso");
+
+ Sord::Model model(*world->rdf_world(), manifest_uri);
+ model.load_file(env, SERD_TURTLE, manifest_uri);
+
+ std::list<PatchRecord> records;
+ for (Sord::Iter i = model.find(nil, rdf_type, ingen_Patch); !i.end(); ++i) {
+ const Sord::Node patch = i.get_subject();
+ Sord::Iter f = model.find(patch, rdfs_seeAlso, nil);
+ if (!f.end()) {
+ records.push_back(PatchRecord(patch.to_c_string(),
+ f.get_object().to_c_string()));
+ } else {
+ LOG(error) << "Patch has no rdfs:seeAlso" << endl;
+ }
+ }
+ return records;
+}
+
+/** Parse a patch from RDF into a CommonInterface (engine or client).
+ * @return whether or not load was successful.
+ */
+bool
+Parser::parse_file(Ingen::Shared::World* world,
+ Ingen::CommonInterface* target,
+ Glib::ustring file_uri,
+ boost::optional<Raul::Path> parent,
+ boost::optional<Raul::Symbol> symbol,
+ boost::optional<GraphObject::Properties> data)
+{
+ const size_t colon = file_uri.find(":");
+ if (colon != Glib::ustring::npos) {
+ const Glib::ustring scheme = file_uri.substr(0, colon);
+ if (scheme != "file") {
+ LOG(error) << (boost::format("Unsupported URI scheme `%1%'")
+ % scheme) << endl;
+ return false;
+ }
+ } else {
+ file_uri = Glib::ustring("file://") + file_uri;
+ }
+
+ const bool is_bundle = (file_uri.substr(file_uri.length() - 4) != ".ttl");
+
+ if (is_bundle && file_uri[file_uri.length() - 1] != '/') {
+ file_uri.append("/");
+ }
+
+ SerdNode base_node = serd_node_from_string(
+ SERD_URI, (const uint8_t*)file_uri.c_str());
+ SerdEnv* env = serd_env_new(&base_node);
+
+ if (file_uri.substr(file_uri.length() - 4) != ".ttl") {
+ // Not a Turtle file, try to open it as a bundle
+ if (file_uri[file_uri.length() - 1] != '/') {
+ file_uri.append("/");
+ }
+ Parser::PatchRecords records = find_patches(world, env, file_uri + "manifest.ttl");
+ if (!records.empty()) {
+ file_uri = records.front().file_uri;
+ }
+ }
+
+ base_node = serd_node_from_string(
+ SERD_URI, (const uint8_t*)file_uri.c_str());
+ serd_env_set_base_uri(env, &base_node);
+
+ // Load patch file into model
+ Sord::Model model(*world->rdf_world(), file_uri);
+ model.load_file(env, SERD_TURTLE, file_uri);
+
+ serd_env_free(env);
+
+ LOG(info) << "Parsing " << file_uri << endl;
+ if (parent)
+ LOG(info) << "Parent: " << *parent << endl;
+ if (symbol)
+ LOG(info) << "Symbol: " << *symbol << endl;
+
+ boost::optional<Path> parsed_path
+ = parse(world, target, model, file_uri, Path("/"), parent, symbol, data);
+
+ if (parsed_path) {
+ target->set_property(*parsed_path, "http://drobilla.net/ns/ingen#document",
+ Atom(Atom::URI, file_uri.c_str()));
+ } else {
+ LOG(warn) << "Document URI lost" << endl;
+ }
+
+ return parsed_path;
+}
+
+bool
+Parser::parse_string(Ingen::Shared::World* world,
+ Ingen::CommonInterface* target,
+ const Glib::ustring& str,
+ const Glib::ustring& base_uri,
+ boost::optional<Raul::Path> parent,
+ boost::optional<Raul::Symbol> symbol,
+ boost::optional<GraphObject::Properties> data)
+{
+ // Load string into model
+ Sord::Model model(*world->rdf_world(), base_uri);
+ SerdEnv* env = serd_env_new(NULL);
+ model.load_string(env, SERD_TURTLE, str.c_str(), str.length(), base_uri);
+ serd_env_free(env);
+
+ LOG(info) << "Parsing string";
+ if (!base_uri.empty())
+ info << " (base " << base_uri << ")";
+ info << endl;
+
+ boost::optional<Raul::Path> data_path;
+ bool ret = parse(world, target, model, base_uri, data_path, parent, symbol, data);
+ Sord::URI subject(*world->rdf_world(), base_uri);
+ parse_connections(world, target, model, subject, parent ? *parent : "/");
+
+ return ret;
+}
+
} // namespace Serialisation
} // namespace Ingen