diff options
author | David Robillard <d@drobilla.net> | 2019-03-09 17:44:36 +0100 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2019-12-12 19:42:09 +0100 |
commit | 3c0ed6b66b6e99c68fc01c86b5796a55d74a5977 (patch) | |
tree | 7be3252c13ef123b956424169c1bfbf55359564a | |
parent | e32f32a360f2bf8f017ea347b6d1e568c0beaf68 (diff) | |
download | ingen-3c0ed6b66b6e99c68fc01c86b5796a55d74a5977.tar.gz ingen-3c0ed6b66b6e99c68fc01c86b5796a55d74a5977.tar.bz2 ingen-3c0ed6b66b6e99c68fc01c86b5796a55d74a5977.zip |
WIP: Port to serd1serd1
65 files changed, 1034 insertions, 1657 deletions
diff --git a/doc/style.css b/doc/style.css index 172be516..5079e86c 100644 --- a/doc/style.css +++ b/doc/style.css @@ -1,54 +1,108 @@ body { - max-width: 80em; - margin: 0; + background: #FFF; + color: #222; + font-style: normal; + line-height: 1.6em; margin-left: auto; margin-right: auto; - background: #FFF; - color: #000; + max-width: 60em; + /* padding: 0; */ + font-family: "DejaVu Serif",Palatino,serif; + text-rendering: optimizeLegibility; } -#titlearea { - display: none; +/* #titlearea { */ +/* display: none; */ +/* } */ + +h1, .title, #projectname, h2, h3, h4, h5, h6 { + line-height: 1.0125em; + color: #222; + font-family: "DejaVu Sans","Helvetica","Arial"; + margin: 1em 0 0.5em 0; +} + +h1, .title, #projectname { + font-size: 320%; + font-weight: 400; +} + +.title { + margin-bottom: 0.25em; + margin-top: 0; +} + +#titlebox, #metabox { + display: inline-block; +} +#titlebox{ + display: inline-block; + width: 75%; + left: 0; + top: 0; +} +#title { + margin-top: 0; + margin-bottom: 0.25em; +} + +#shortdesc { + margin: 0 0 0.5em 0; + color: #666; + display: inline-block; + font-style: italic; + padding: 0; } -h1 { - font-size: 180%; - font-weight: 900; +#titlearea { + margin: 2em auto 1em auto; + padding: 0 0.5em 0 0.5em; + position: relative; + clear: both; + line-height: 1.0em; } h2 { - font-size: 140%; - font-weight: 700; + font-size: 160%; + font-weight: 400; } h3 { - font-size: 120%; - font-weight: 700; + font-size: 140%; + font-weight: 400; } h4 { - font-size: 110%; - font-weight: 700; + font-size: 120%; + font-weight: 500; } -h5 { - font-size: 100%; - font-weight: 700; +h5, h6 { + font-size: 110%; + font-weight: 600; } -h6 { - font-size: 100%; - font-weight: 600; +h1 a, h1 a:link, h1 a:visited , +h2 a, h2 a:link, h2 a:visited , +h3 a, h3 a:link, h3 a:visited , +h4 a, h4 a:link, h4 a:visited , +h5 a, h5 a:link, h5 a:visited , +h6 a, h6 a:link, h6 a:visited { + color: #444; } p { - margin: 0 0 1em 0; + margin: 0.5em 0 0.5em 0; } dt { font-weight: 700; } +dd { + margin-left: 2em; +} + p.startli,p.startdd,p.starttd { margin-top: 2px; } @@ -70,12 +124,12 @@ caption { } span.legend { - font-size: 70%; + font-size: small; text-align: center; } h3.version { - font-size: 90%; + font-size: small; text-align: center; } @@ -130,8 +184,6 @@ dl.el { .fragment { font-family: monospace, fixed; - font-size: 105%; - padding-bottom: 1em; } pre.fragment { @@ -140,7 +192,6 @@ pre.fragment { padding: 4px 6px; margin: 4px 8px 4px 2px; overflow: auto; - font-size: 9pt; line-height: 125%; } @@ -170,10 +221,11 @@ div.groupText { font-style: italic; } -div.contents { - margin-top: 10px; - margin-left: 10px; - margin-right: 10px; +div.contents, #content { + padding: 0 0.5em 0 0.5em; + max-width: 60em; + margin-left: auto; + margin-right: auto; } td.indexkey { @@ -191,6 +243,10 @@ td.indexvalue { margin: 2px 0; } +table.memname { + font-family: "DejaVu Sans Mono",monospace; +} + tr.memlist { background-color: #EEF1F7; } @@ -267,7 +323,7 @@ span.vhdllogic { /* @end */ td.tiny { - font-size: 75%; + font-size: x-small; } .dirtab { @@ -295,11 +351,12 @@ hr.footer { /* @group Member Descriptions */ table.memberdecls { border-spacing: 0.125em; + line-height: 1.3em; } -h2.groupheader { - margin: 1em 0 0.5em 0; -} +/* h2.groupheader { */ +/* margin: 0.5em 0 0.25em 0; */ +/* } */ .mdescLeft,.mdescRight,.memItemLeft,.memItemRight,.memTemplItemLeft,.memTemplItemRight,.memTemplParams { margin: 0; @@ -313,7 +370,6 @@ h2.groupheader { .memItemLeft,.memItemRight,.memTemplParams { border: 0; font-family: monospace, fixed; - font-size: 90%; } .memItemLeft,.memTemplItemLeft { @@ -349,7 +405,6 @@ td.mlabels-right { /* @group Member Details */ /* Styles for detailed member documentation */ .memtemplate { - font-size: 80%; color: #4665A2; font-weight: bold; } @@ -364,24 +419,32 @@ td.mlabels-right { } .memitem { - padding: 0; - margin: 1em 0 1em 0; + padding: 0.25em 0.5em 0.25em 0.5em; + margin: 0 0 1em 0; + border-radius: 6px; + border: 1px solid #DDD; } .memproto { - padding: 0; font-size: 110%; - font-weight: bold; - color: #000; + font-weight: 400; + line-height: 1em; + /* line-height: 1.0125em; */ + color: #000; } .memproto .paramname { - color: #444; font-style: normal; } .memdoc { - padding: 0 0 0.5em 2em; + padding: 0 0.25em 0 0.25em; +} + +.memdoc p:first-of-type { + /* color: #666; */ + /* font-style: italic; */ + /* margin-top: 0.25em; */ } .paramkey { @@ -389,36 +452,57 @@ td.mlabels-right { } .paramtype { - color: #3E873E; + color: #666; + padding-right: 0.5em; white-space: nowrap; } .paramname { - color: #444; + color: #111; white-space: nowrap; - font-weight: bold; -} - -td.paramname { - vertical-align: top; + /* font-weight: bold; */ + font-family: monospace; + font-style: italic; + padding-right: 0.5em; + /* padding-left: 0.5em; */ } .fieldname { color: #000; } +.fieldtable { + padding-top: 0.25em; + border-top: 1px dashed #DDD; +} + +.fieldtable tbody tr:first-child { + display: none; +} + td.fieldname { - padding-right: 1em; + padding: 0 0.5em 0 0.25em; + /* padding-left: 2em; */ vertical-align: top; + font-family: monospace; } td.fieldtype { + color: #666; + padding: 0 0.5em 0 0; vertical-align: top; - color: #444; + font-family: monospace; } td.fielddoc p { margin: 0; + vertical-align: top; + padding: 0 0.5em 0 0; +} + +p.reference { + font-size: x-small; + font-style: italic; } /* @end */ @@ -558,11 +642,10 @@ div.navpath { } div.summary { - float: right; - font-size: x-small; - padding: 0.25em 0.5em 0 0; - width: 50%; - text-align: right; + font-size: small; + font-family: "DejaVu Sans","Helvetica","Arial"; + margin: 0.5em 0 0.5em 0; + color: #FFF; /* Hide separator bars */ } div.summary a { @@ -570,23 +653,62 @@ div.summary a { } div.header { - background-color: #F3F3F3; - margin: 0; - border: 0; + /* background-color: #F3F3F3; */ + padding: 0; + margin: 0 0.5em 1em 0.5em; + /* border: 0; */ + border-top: 1px solid #DDD; + border-bottom: 1px solid #DDD; } div.headertitle { - font-size: 180%; - font-weight: bold; - color: #FFF; - padding: 0.125em 0.25em 0.125em 0.25em; - background-color: #333; - background: linear-gradient(to bottom, #333 0%, #111 100%); - border: solid 1px #444; - border-top: 0; - border-radius: 0 0 6px 6px; + display: none; + /* font-size: 180%; */ + /* font-weight: bold; */ + /* color: #FFF; */ + /* padding: 0.125em 0.25em 0.125em 0.25em; */ + /* background-color: #333; */ + /* background: linear-gradient(to bottom, #333 0%, #111 100%); */ + /* border: solid 1px #444; */ + /* border-top: 0; */ + /* border-radius: 0 0 6px 6px; */ +} + +/* Metadata box (right aligned next to title) */ + +#metabox { + bottom: 0; + display: inline-block; + font-size: x-small; + font-style: italic; + margin: 0 0 0.5em 0; + position: absolute; + right: 0; + color: #666; + padding: 0; +} + +#meta { + border-style: hidden; + margin-right: 0.25em; +} + +#meta tr, #meta th, #meta td { + background-color: transparent; + border: 0; + font-weight: normal; + /* padding: 0.125em 0.25em 0.125em 0.25em; */ +} + +#meta th { + text-align: right; +} + +#meta th:after { + content: ":"; } + div.line { font-family: monospace, fixed; font-size: 13px; @@ -637,6 +759,9 @@ span.lineno a:hover { th { text-align: left; + font-family: "DejaVu Sans","Helvetica","Arial"; + font-size: 110%; + font-weight: 500; } .mlabel { @@ -672,9 +797,9 @@ th { outline: none; } -.header a { - color: #859900; -} +/* .header a { */ +/* color: #859900; */ +/* } */ .tabs3 .tablist a { padding: 0 10px; @@ -682,464 +807,15 @@ th { .tablist a:hover { color: #fff; + text-shadow: 0 1px 1px rgba(0, 0, 0, 1.0); text-decoration: none; } .tablist li.current a { color: #fff; + text-shadow: 0 1px 1px rgba(0, 0, 0, 1.0); } span.icon { display: none; } - -/* nav bar */ - -.sm { - position: relative; - z-index: 9999; -} - -.sm,.sm ul,.sm li { - display: block; - list-style: none; - margin: 0; - padding: 0; - line-height: normal; - direction: ltr; - text-align: left; - -webkit-tap-highlight-color: rgba(0,0,0,0); -} - -.sm-rtl,.sm-rtl ul,.sm-rtl li { - direction: rtl; - text-align: right; -} - -.sm>li>h1,.sm>li>h2,.sm>li>h3,.sm>li>h4,.sm>li>h5,.sm>li>h6 { - margin: 0; - padding: 0; -} - -.sm ul { - display: none; -} - -.sm li,.sm a { - position: relative; -} - -.sm a { - display: block; -} - -.sm a.disabled { - cursor: not-allowed; -} - -.sm:after { - content: "\00a0"; - display: block; - height: 0; - font: 0/0 serif; - clear: both; - visibility: hidden; - overflow: hidden; -} - -.sm,.sm *,.sm :before,.sm :after { - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; -} - -#doc-content { - overflow: auto; - display: block; - padding: 0; - margin: 0; - -webkit-overflow-scrolling: touch; -} - -.sm-dox { - background-image: none; - background-color: #333; - background: linear-gradient(to bottom, #333 0%, #111 100%); - color: #fff; -} - -.sm-dox a,.sm-dox a:focus,.sm-dox a:hover,.sm-dox a:active { - padding: 0 12px; - padding-right: 43px; - font-size: small; - font-weight: 600; - line-height: auto; - text-decoration: none; - text-shadow: none; - color: inherit; - outline: 0; -} - -.sm-dox a:hover { - background-image: none; - background-repeat: repeat-x; - color: inherit; - text-shadow: 0 1px 1px #000; -} - -.sm-dox a.current { - color: #d23600; -} - -.sm-dox a.disabled { - color: #bbb; -} - -.sm-dox a span.sub-arrow { - position: absolute; - top: 50%; - margin-top: -14px; - left: auto; - right: 3px; - width: 28px; - height: 28px; - overflow: hidden; - font: bold 12px/28px monospace !important; - text-align: center; - text-shadow: none; - background: rgba(255,255,255,0.5); - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - border-radius: 5px; -} - -.sm-dox a.highlighted span.sub-arrow:before { - display: block; - content: '-'; -} - -.sm-dox>li:first-child>a,.sm-dox>li:first-child>:not(ul) a { - -moz-border-radius: 5px 5px 0 0; - -webkit-border-radius: 5px; - border-radius: 5px 5px 0 0; -} - -.sm-dox>li:last-child>a,.sm-dox>li:last-child>:not(ul) a,.sm-dox>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul { - -moz-border-radius: 0 0 5px 5px; - -webkit-border-radius: 0; - border-radius: 0 0 5px 5px; -} - -.sm-dox>li:last-child>a.highlighted,.sm-dox>li:last-child>:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>:not(ul) a.highlighted { - -moz-border-radius: 0; - -webkit-border-radius: 0; - border-radius: 0; -} - -.sm-dox ul { - background: rgba(162,162,162,0.1); -} - -.sm-dox ul a,.sm-dox ul a:focus,.sm-dox ul a:hover,.sm-dox ul a:active { - font-size: 12px; - border-left: 8px solid transparent; - line-height: auto; - text-shadow: none; - background-color: #fff; - background-image: none; -} - -.sm-dox ul a:hover { - background-image: none; - background-repeat: repeat-x; - color: inherit; - text-shadow: 0 1px 1px #000; -} - -.sm-dox ul ul a,.sm-dox ul ul a:hover,.sm-dox ul ul a:focus,.sm-dox ul ul a:active { - border-left: 16px solid transparent; -} - -.sm-dox ul ul ul a,.sm-dox ul ul ul a:hover,.sm-dox ul ul ul a:focus,.sm-dox ul ul ul a:active { - border-left: 24px solid transparent; -} - -.sm-dox ul ul ul ul a,.sm-dox ul ul ul ul a:hover,.sm-dox ul ul ul ul a:focus,.sm-dox ul ul ul ul a:active { - border-left: 32px solid transparent; -} - -.sm-dox ul ul ul ul ul a,.sm-dox ul ul ul ul ul a:hover,.sm-dox ul ul ul ul ul a:focus,.sm-dox ul ul ul ul ul a:active { - border-left: 40px solid transparent; -} - -@media(min-width:768px) { - .sm-dox ul { - position: absolute; - width: 12em; - } - - .sm-dox li { - float: left; - } - - .sm-dox.sm-rtl li { - float: right; - } - - .sm-dox ul li,.sm-dox.sm-rtl ul li,.sm-dox.sm-vertical li { - float: none; - } - - .sm-dox a { - white-space: nowrap; - } - - .sm-dox ul a,.sm-dox.sm-vertical a { - white-space: normal; - } - - .sm-dox .sm-nowrap>li>a,.sm-dox .sm-nowrap>li>:not(ul) a { - white-space: nowrap; - } - - .sm-dox { - padding: 0 10px; - background-image: none; - background-color: #000; - line-height: normal; - background-image: none; - background-color: #333; - background: linear-gradient(to bottom, #333 0%, #111 100%); - color: #ddd; - } - - .sm-dox a span.sub-arrow { - top: 50%; - margin-top: -2px; - right: 12px; - width: 0; - height: 0; - border-width: 4px; - border-style: solid dashed dashed; - border-color: #ddd transparent transparent; - background: transparent; - -moz-border-radius: 0; - -webkit-border-radius: 0; - border-radius: 0; - } - - .sm-dox a,.sm-dox a:focus,.sm-dox a:active,.sm-dox a:hover,.sm-dox a.highlighted { - padding: 0 1em 0 0; - background-image: none; - background-repeat: no-repeat; - background-position: right; - -moz-border-radius: 0 !important; - -webkit-border-radius: 0; - border-radius: 0 !important; - } - - .sm-dox a:hover { - background-image: none; - background-repeat: repeat-x; - color: #fff; - text-shadow: 0 1px 1px #000; - } - - .sm-dox a:hover span.sub-arrow { - border-color: #fff transparent transparent; - } - - .sm-dox a.has-submenu { - padding-right: 24px; - } - - .sm-dox li { - border-top: 0; - } - - .sm-dox>li>ul:before,.sm-dox>li>ul:after { - content: ''; - position: absolute; - top: -18px; - left: 30px; - width: 0; - height: 0; - overflow: hidden; - border-width: 9px; - border-style: dashed dashed solid; - border-color: transparent transparent #bbb; - } - - .sm-dox>li>ul:after { - top: -16px; - left: 31px; - border-width: 8px; - border-color: transparent transparent #fff; - } - - .sm-dox ul { - border: 1px solid #bbb; - padding: 5px 0; - background: initial; - -moz-border-radius: 5px !important; - -webkit-border-radius: 5px; - border-radius: 5px !important; - -moz-box-shadow: 0 5px 9px rgba(0,0,0,0.2); - -webkit-box-shadow: 0 5px 9px rgba(0,0,0,0.2); - box-shadow: 0 5px 9px rgba(0,0,0,0.2); - } - - .sm-dox ul a span.sub-arrow { - right: 8px; - top: 50%; - margin-top: -5px; - border-width: 5px; - border-color: transparent transparent transparent #555; - border-style: dashed dashed dashed solid; - } - - .sm-dox ul a,.sm-dox ul a:hover,.sm-dox ul a:focus,.sm-dox ul a:active,.sm-dox ul a.highlighted { - color: #555; - background-image: none; - border: 0 !important; - color: #555; - background-image: none; - } - - .sm-dox ul a:hover { - background-image: none; - background-repeat: repeat-x; - color: #fff; - text-shadow: 0 1px 1px #000; - } - - .sm-dox ul a:hover span.sub-arrow { - border-color: transparent transparent transparent #fff; - } - - .sm-dox span.scroll-up,.sm-dox span.scroll-down { - position: absolute; - display: none; - visibility: hidden; - overflow: hidden; - background: initial; - height: 36px; - } - - .sm-dox span.scroll-up:hover,.sm-dox span.scroll-down:hover { - background: #eee; - } - - .sm-dox span.scroll-up:hover span.scroll-up-arrow,.sm-dox span.scroll-up:hover span.scroll-down-arrow { - border-color: transparent transparent #d23600; - } - - .sm-dox span.scroll-down:hover span.scroll-down-arrow { - border-color: #d23600 transparent transparent; - } - - .sm-dox span.scroll-up-arrow,.sm-dox span.scroll-down-arrow { - position: absolute; - top: 0; - left: 50%; - margin-left: -6px; - width: 0; - height: 0; - overflow: hidden; - border-width: 6px; - border-style: dashed dashed solid; - border-color: transparent transparent #555; - } - - .sm-dox span.scroll-down-arrow { - top: 8px; - border-style: solid dashed dashed; - border-color: #555 transparent transparent; - } - - .sm-dox.sm-rtl a.has-submenu { - padding-right: 12px; - padding-left: 24px; - } - - .sm-dox.sm-rtl a span.sub-arrow { - right: auto; - left: 12px; - } - - .sm-dox.sm-rtl.sm-vertical a.has-submenu { - padding: 10px 20px; - } - - .sm-dox.sm-rtl.sm-vertical a span.sub-arrow { - right: auto; - left: 8px; - border-style: dashed solid dashed dashed; - border-color: transparent #555 transparent transparent; - } - - .sm-dox.sm-rtl>li>ul:before { - left: auto; - right: 30px; - } - - .sm-dox.sm-rtl>li>ul:after { - left: auto; - right: 31px; - } - - .sm-dox.sm-rtl ul a.has-submenu { - padding: 10px 20px !important; - } - - .sm-dox.sm-rtl ul a span.sub-arrow { - right: auto; - left: 8px; - border-style: dashed solid dashed dashed; - border-color: transparent #555 transparent transparent; - } - - .sm-dox.sm-vertical { - padding: 10px 0; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - border-radius: 5px; - } - - .sm-dox.sm-vertical a { - padding: 10px 20px; - } - - .sm-dox.sm-vertical a:hover,.sm-dox.sm-vertical a:focus,.sm-dox.sm-vertical a:active,.sm-dox.sm-vertical a.highlighted { - background: initial; - } - - .sm-dox.sm-vertical a.disabled { - background-image: none; - } - - .sm-dox.sm-vertical a span.sub-arrow { - right: 8px; - top: 50%; - margin-top: -5px; - border-width: 5px; - border-style: dashed dashed dashed solid; - border-color: transparent transparent transparent #555; - } - - .sm-dox.sm-vertical>li>ul:before,.sm-dox.sm-vertical>li>ul:after { - display: none; - } - - .sm-dox.sm-vertical ul a { - padding: 10px 20px; - } - - .sm-dox.sm-vertical ul a:hover,.sm-dox.sm-vertical ul a:focus,.sm-dox.sm-vertical ul a:active,.sm-dox.sm-vertical ul a.highlighted { - background: #eee; - } - - .sm-dox.sm-vertical ul a.disabled { - background: initial; - } -} diff --git a/ingen/AtomForge.hpp b/ingen/AtomForge.hpp index acb24fac..241233ea 100644 --- a/ingen/AtomForge.hpp +++ b/ingen/AtomForge.hpp @@ -21,8 +21,8 @@ #include "lv2/atom/atom.h" #include "lv2/atom/forge.h" #include "lv2/atom/util.h" -#include "sord/sordmm.hpp" -#include "sratom/sratom.h" +#include "serd/serd.hpp" +#include "sratom/sratom.hpp" #include <cassert> #include <cstdint> @@ -31,14 +31,19 @@ namespace ingen { -/// An atom forge that writes to an automatically-resized memory buffer +/** An atom forge that writes to an automatically-resized memory buffer. + * + * Can be used to easily forge a complete atom from a node using read(), or + * manually to forge more complex atoms using clear(), atom(), and the + * LV2_Atom_Forge interface. + */ class AtomForge : public LV2_Atom_Forge { public: - explicit AtomForge(LV2_URID_Map& map) + explicit AtomForge(serd::World& world, LV2_URID_Map& map) : _size{0} , _capacity{8 * sizeof(LV2_Atom)} - , _sratom{sratom_new(&map)} + , _forger{world, map} , _buf{(LV2_Atom*)calloc(8, sizeof(LV2_Atom))} { lv2_atom_forge_init(this, &map); @@ -46,14 +51,15 @@ public: } /// Forge an atom from `node` in `model` - void read(Sord::World& world, SordModel* model, const SordNode* node) + const LV2_Atom* read(serd::Model& model, + const serd::Node& node, + const sratom::Flags flags = {}) { - sratom_read(_sratom.get(), this, world.c_obj(), model, node); + clear(); + _forger.read(serd::make_uri("file:///"), *this, model, node, flags); + return atom(); } - /// Return the top-level atom that has been forged - const LV2_Atom* atom() const { return _buf.get(); } - /// Clear the atom buffer and reset the forge void clear() { @@ -62,14 +68,11 @@ public: *_buf = {0U, 0U}; } - /// Return the internal atom serialiser - Sratom& sratom() { return *_sratom; } + /// Return the top-level atom that has been forged + const LV2_Atom* atom() const { return _buf.get(); } private: - struct SratomDeleter { void operator()(Sratom* s) { sratom_free(s); } }; - using AtomPtr = UPtr<LV2_Atom, FreeDeleter<LV2_Atom>>; - using SratomPtr = UPtr<Sratom, SratomDeleter>; /// Append some data and return a reference to its start intptr_t append(const void* buf, uint32_t len) { @@ -110,10 +113,10 @@ private: return ((AtomForge*)handle)->deref(ref); } - size_t _size; ///< Current atom size - size_t _capacity; ///< Allocated size of atom buffer - SratomPtr _sratom; ///< Atom serialiser - AtomPtr _buf; ///< Atom buffer + size_t _size; ///< Current atom size + size_t _capacity; ///< Allocated size of atom buffer + sratom::Forger _forger; ///< Atom forger + AtomPtr _buf; ///< Atom buffer }; } // namespace ingen diff --git a/ingen/AtomWriter.hpp b/ingen/AtomWriter.hpp index f9052d93..565fbdba 100644 --- a/ingen/AtomWriter.hpp +++ b/ingen/AtomWriter.hpp @@ -43,7 +43,7 @@ class INGEN_API AtomWriter : public Interface public: using result_type = void; ///< For boost::apply_visitor - AtomWriter(URIMap& map, URIs& uris, AtomSink& sink); + AtomWriter(serd::World& world, URIMap& map, URIs& uris, AtomSink& sink); URI uri() const override { return URI("ingen:/clients/atom_writer"); } diff --git a/ingen/Configuration.hpp b/ingen/Configuration.hpp index 6c0343b1..20fc79f5 100644 --- a/ingen/Configuration.hpp +++ b/ingen/Configuration.hpp @@ -22,6 +22,7 @@ #include "ingen/ingen.h" #include "lv2/urid/urid.h" #include "raul/Exception.hpp" +#include "serd/serd.hpp" #include <cstdio> #include <list> @@ -86,7 +87,7 @@ public: void parse(int argc, char **argv); /** Load a specific file. */ - bool load(const FilePath& path); + bool load(serd::World& world, const FilePath& path); /** Save configuration to a file. * @@ -103,7 +104,8 @@ public: * * @return The absolute path of the saved configuration file. */ - FilePath save(URIMap& uri_map, + FilePath save(serd::World& world, + URIMap& uri_map, const std::string& app, const FilePath& filename, unsigned scopes); @@ -114,7 +116,8 @@ public: * will be loaded before the user's, e.g. ~/.config/appname/filename, * so the user options will override the system options. */ - std::list<FilePath> load_default(const std::string& app, + std::list<FilePath> load_default(serd::World& world, + const std::string& app, const FilePath& filename); const Atom& option(const std::string& long_name) const; diff --git a/ingen/FilePath.hpp b/ingen/FilePath.hpp index 98893dfc..8d5c6882 100644 --- a/ingen/FilePath.hpp +++ b/ingen/FilePath.hpp @@ -19,7 +19,7 @@ #include "ingen/ingen.h" -#include <boost/utility/string_view.hpp> +#include "serd/serd.hpp" #include <ostream> #include <string> @@ -57,7 +57,7 @@ public: FilePath(string_type&& str) : _str(std::move(str)) {} FilePath(const string_type& str) : _str(str) {} FilePath(const value_type* str) : _str(str) {} - FilePath(const boost::basic_string_view<value_type>& sv) + FilePath(const serd::StringView& sv) : _str(sv.data(), sv.length()) {} @@ -73,7 +73,7 @@ public: FilePath& operator+=(const string_type& str); FilePath& operator+=(const value_type* str); FilePath& operator+=(value_type chr); - FilePath& operator+=(boost::basic_string_view<value_type> sv); + FilePath& operator+=(serd::StringView sv); void clear() noexcept { _str.clear(); } diff --git a/ingen/Forge.hpp b/ingen/Forge.hpp index b414a6ab..53cae153 100644 --- a/ingen/Forge.hpp +++ b/ingen/Forge.hpp @@ -19,7 +19,9 @@ #include "ingen/Atom.hpp" #include "ingen/ingen.h" +#include "lv2/atom/atom.h" #include "lv2/atom/forge.h" +#include "serd/serd.hpp" #include <cstdint> #include <cstring> @@ -59,8 +61,12 @@ public: return Atom(size, type, val); } + Atom alloc(const LV2_Atom* atom) { + return Atom(atom->size, atom->type, LV2_ATOM_BODY_CONST(atom)); + } + Atom alloc(const char* v) { - const size_t len = strlen(v); + const auto len = strlen(v); return Atom(len + 1, String, v); } @@ -68,12 +74,11 @@ public: return Atom(v.length() + 1, String, v.c_str()); } - Atom alloc_uri(const char* v) { - const size_t len = strlen(v); - return Atom(len + 1, URI, v); + Atom alloc(serd::StringView v) { + return Atom(v.length() + 1, String, v.c_str()); } - Atom alloc_uri(const std::string& v) { + Atom alloc_uri(serd::StringView v) { return Atom(v.length() + 1, URI, v.c_str()); } diff --git a/ingen/Parser.hpp b/ingen/Parser.hpp index 45d087cd..697e96c8 100644 --- a/ingen/Parser.hpp +++ b/ingen/Parser.hpp @@ -30,8 +30,6 @@ #include <string> #include <utility> -namespace Sord { class World; } - namespace ingen { class Interface; @@ -63,9 +61,8 @@ public: }; /** Find all resources of a given type listed in a manifest file. */ - virtual std::set<ResourceRecord> find_resources(Sord::World& world, - const URI& manifest_uri, - const URI& type_uri); + virtual std::set<ResourceRecord> find_resources(const URI& manifest_uri, + const URI& type_uri); /** Parse a graph from RDF into a Interface (engine or client). * diff --git a/ingen/Serialiser.hpp b/ingen/Serialiser.hpp index 1ac5c151..522d0bdb 100644 --- a/ingen/Serialiser.hpp +++ b/ingen/Serialiser.hpp @@ -21,7 +21,7 @@ #include "ingen/Properties.hpp" #include "ingen/ingen.h" #include "ingen/types.hpp" -#include "sord/sordmm.hpp" +#include "serd/serd.hpp" #include <string> @@ -30,6 +30,7 @@ namespace Raul { class Path; } namespace ingen { class Arc; +class FilePath; class Node; class URI; class World; @@ -84,8 +85,8 @@ public: * * @throw std::logic_error */ - virtual void serialise_arc(const Sord::Node& parent, - const SPtr<const Arc>& arc); + virtual void serialise_arc(const serd::Optional<serd::Node>& parent, + const SPtr<const Arc>& arc); /** Finish serialization. * diff --git a/ingen/SocketReader.hpp b/ingen/SocketReader.hpp index 3c3c5f3c..8afcafb7 100644 --- a/ingen/SocketReader.hpp +++ b/ingen/SocketReader.hpp @@ -19,8 +19,6 @@ #include "ingen/ingen.h" #include "ingen/types.hpp" -#include "serd/serd.h" -#include "sord/sord.h" #include <thread> @@ -47,29 +45,11 @@ protected: private: void run(); - static SerdStatus set_base_uri(SocketReader* iface, - const SerdNode* uri_node); - - static SerdStatus set_prefix(SocketReader* iface, - const SerdNode* name, - const SerdNode* uri_node); - - static SerdStatus 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); - World& _world; Interface& _iface; - SerdEnv* _env; - SordInserter* _inserter; - SordNode* _msg_node; SPtr<Raul::Socket> _socket; bool _exit_flag; + std::thread _thread; }; diff --git a/ingen/SocketWriter.hpp b/ingen/SocketWriter.hpp index 2424fe24..b3852940 100644 --- a/ingen/SocketWriter.hpp +++ b/ingen/SocketWriter.hpp @@ -39,7 +39,8 @@ class URIs; class INGEN_API SocketWriter : public TurtleWriter { public: - SocketWriter(URIMap& map, + SocketWriter(serd::World& world, + URIMap& map, URIs& uris, const URI& uri, SPtr<Raul::Socket> sock); diff --git a/ingen/StreamWriter.hpp b/ingen/StreamWriter.hpp index 56603b92..15ef42c1 100644 --- a/ingen/StreamWriter.hpp +++ b/ingen/StreamWriter.hpp @@ -34,7 +34,8 @@ class URIs; class INGEN_API StreamWriter : public TurtleWriter { public: - StreamWriter(URIMap& map, + StreamWriter(serd::World& world, + URIMap& map, URIs& uris, const URI& uri, FILE* stream, diff --git a/ingen/TurtleWriter.hpp b/ingen/TurtleWriter.hpp index 9c88be2e..09c01d26 100644 --- a/ingen/TurtleWriter.hpp +++ b/ingen/TurtleWriter.hpp @@ -23,7 +23,7 @@ #include "ingen/ingen.h" #include "lv2/atom/atom.h" #include "serd/serd.h" -#include "sratom/sratom.h" +#include "sratom/sratom.hpp" #include <cstddef> #include <cstdint> @@ -41,7 +41,7 @@ class URIs; class INGEN_API TurtleWriter : public AtomWriter, public AtomSink { public: - TurtleWriter(URIMap& map, URIs& uris, URI uri); + TurtleWriter(serd::World& world, URIMap& map, URIs& uris, const URI& uri); ~TurtleWriter() override; @@ -54,14 +54,13 @@ public: URI uri() const override { return _uri; } protected: - URIMap& _map; - Sratom* _sratom; - SerdNode _base; - SerdURI _base_uri; - SerdEnv* _env; - SerdWriter* _writer; - URI _uri; - bool _wrote_prefixes; + URIMap& _map; + sratom::Streamer _streamer; + serd::Node _base; + serd::Env _env; + serd::Writer _writer; + URI _uri; + bool _wrote_prefixes; }; } // namespace ingen diff --git a/ingen/URI.hpp b/ingen/URI.hpp index cbbfd46a..489b6219 100644 --- a/ingen/URI.hpp +++ b/ingen/URI.hpp @@ -19,8 +19,7 @@ #include "ingen/FilePath.hpp" #include "ingen/ingen.h" -#include "serd/serd.h" -#include "sord/sordmm.hpp" +#include "serd/serd.hpp" #include <boost/utility/string_view.hpp> @@ -31,130 +30,45 @@ namespace ingen { -class INGEN_API URI +class INGEN_API URI : public serd::Node { public: - using Chunk = boost::string_view; + using Slice = serd::StringView; - URI(); explicit URI(const std::string& str); explicit URI(const char* str); - URI(const std::string& str, const URI& base); - URI(const Sord::Node& node); - URI(SerdNode node); + URI(const serd::NodeView& node); + URI(const serd::Node& node); explicit URI(const FilePath& path); - URI(const URI& uri); - URI& operator=(const URI& uri); - - URI(URI&& uri) noexcept; - URI& operator=(URI&& uri) noexcept; - - ~URI(); - URI make_relative(const URI& base) const; - bool empty() const { return !_node.buf; } - - std::string string() const { return std::string(c_str(), _node.n_bytes); } - size_t length() const { return _node.n_bytes; } - const char* c_str() const { return (const char*)_node.buf; } + std::string string() const { return std::string(*this); } + std::string str() const { return std::string(*this); } FilePath file_path() const { return scheme() == "file" ? FilePath(path()) : FilePath(); } - operator std::string() const { return string(); } - - const char* begin() const { return (const char*)_node.buf; } - const char* end() const { return (const char*)_node.buf + _node.n_bytes; } - - Chunk scheme() const { return make_chunk(_uri.scheme); } - Chunk authority() const { return make_chunk(_uri.authority); } - Chunk path() const { return make_chunk(_uri.path); } - Chunk query() const { return make_chunk(_uri.query); } - Chunk fragment() const { return make_chunk(_uri.fragment); } + Slice scheme() const { return serd::URI{*this}.scheme(); } + Slice authority() const { return serd::URI{*this}.authority(); } + Slice path() const { return serd::URI{*this}.path(); } + Slice query() const { return serd::URI{*this}.query(); } + Slice fragment() const { return serd::URI{*this}.fragment(); } static bool is_valid(const char* str) { - return serd_uri_string_has_scheme((const uint8_t*)str); + return serd_uri_string_has_scheme(str); } static bool is_valid(const std::string& str) { return is_valid(str.c_str()); } - -private: - URI(SerdNode node, SerdURI uri); - - static Chunk make_chunk(const SerdChunk& chunk) { - return Chunk((const char*)chunk.buf, chunk.len); - } - - SerdURI _uri; - SerdNode _node; }; -inline bool operator==(const URI& lhs, const URI& rhs) -{ - return lhs.string() == rhs.string(); -} - inline bool operator==(const URI& lhs, const std::string& rhs) { - return lhs.string() == rhs; -} - -inline bool operator==(const URI& lhs, const char* rhs) -{ - return lhs.string() == rhs; -} - -inline bool operator==(const URI& lhs, const Sord::Node& rhs) -{ - return rhs.type() == Sord::Node::URI && lhs.string() == rhs.to_string(); -} - -inline bool operator==(const Sord::Node& lhs, const URI& rhs) -{ - return rhs == lhs; -} - -inline bool operator!=(const URI& lhs, const URI& rhs) -{ - return lhs.string() != rhs.string(); -} - -inline bool operator!=(const URI& lhs, const std::string& rhs) -{ - return lhs.string() != rhs; -} - -inline bool operator!=(const URI& lhs, const char* rhs) -{ - return lhs.string() != rhs; -} - -inline bool operator!=(const URI& lhs, const Sord::Node& rhs) -{ - return !(lhs == rhs); -} - -inline bool operator!=(const Sord::Node& lhs, const URI& rhs) -{ - return !(lhs == rhs); -} - -inline bool operator<(const URI& lhs, const URI& rhs) -{ - return lhs.string() < rhs.string(); -} - -template <typename Char, typename Traits> -inline std::basic_ostream<Char, Traits>& -operator<<(std::basic_ostream<Char, Traits>& os, const URI& uri) -{ - return os << uri.string(); + return lhs.c_str() == rhs; } } // namespace ingen diff --git a/ingen/URIMap.hpp b/ingen/URIMap.hpp index a3b9f219..3ca22557 100644 --- a/ingen/URIMap.hpp +++ b/ingen/URIMap.hpp @@ -18,6 +18,7 @@ #define INGEN_URIMAP_HPP #include "ingen/LV2Features.hpp" +#include "ingen/URI.hpp" #include "ingen/ingen.h" #include "ingen/types.hpp" #include "lv2/core/lv2.h" @@ -45,6 +46,7 @@ public: uint32_t map_uri(const char* uri); uint32_t map_uri(const std::string& uri) { return map_uri(uri.c_str()); } + uint32_t map_uri(const URI& uri) { return map_uri(uri.c_str()); } const char* unmap_uri(uint32_t urid) const; class Feature : public LV2Features::Feature { diff --git a/ingen/URIs.hpp b/ingen/URIs.hpp index eb657473..f8bf65a9 100644 --- a/ingen/URIs.hpp +++ b/ingen/URIs.hpp @@ -47,17 +47,12 @@ public: LilvWorld* lworld, const char* str); - Quark(const Quark& copy); - - ~Quark(); - operator LV2_URID() const { return urid.get<LV2_URID>(); } explicit operator Atom() const { return urid; } - operator const LilvNode*() const { return lnode; } + operator const LilvNode*() const { return cobj(); } - Atom urid; - Atom uri; - LilvNode* lnode; + Atom urid; + Atom uri; }; ingen::Forge& forge; diff --git a/ingen/World.hpp b/ingen/World.hpp index a2906525..62d160b1 100644 --- a/ingen/World.hpp +++ b/ingen/World.hpp @@ -28,7 +28,7 @@ typedef struct LilvWorldImpl LilvWorld; -namespace Sord { class World; } +namespace serd { class World; class Env; } namespace ingen { @@ -49,7 +49,7 @@ class URIs; * * This is the root to which all components of Ingen are connected. It * contains all necessary shared data (including the world for libraries like - * Sord and Lilv) and holds references to components. + * Serd and Lilv) and holds references to components. * * Some functionality in Ingen is implemented in dynamically loaded modules, * which are loaded using this interface. When loaded, those modules add @@ -126,7 +126,8 @@ public: /** Lock for rdf_world() or lilv_world(). */ virtual std::mutex& rdf_mutex(); - virtual Sord::World* rdf_world(); + virtual serd::World& rdf_world(); + virtual serd::Env& env(); virtual LilvWorld* lilv_world(); virtual LV2Features& lv2_features(); diff --git a/ingen/client/PluginModel.hpp b/ingen/client/PluginModel.hpp index 5f43b3c4..c2d291f0 100644 --- a/ingen/client/PluginModel.hpp +++ b/ingen/client/PluginModel.hpp @@ -25,7 +25,7 @@ #include "ingen/types.hpp" #include "lilv/lilv.h" #include "raul/Symbol.hpp" -#include "sord/sordmm.hpp" +#include "serd/serd.hpp" #include <cstdint> #include <map> @@ -88,12 +88,6 @@ public: std::string documentation(bool html) const; std::string port_documentation(uint32_t index, bool html) const; - static void set_rdf_world(Sord::World& world) { - _rdf_world = &world; - } - - static Sord::World* rdf_world() { return _rdf_world; } - // Signals INGEN_SIGNAL(changed, void); INGEN_SIGNAL(property, void, const URI&, const Atom&); @@ -111,7 +105,6 @@ protected: private: std::string get_documentation(const LilvNode* subject, bool html) const; - static Sord::World* _rdf_world; static LilvWorld* _lilv_world; static const LilvPlugins* _lilv_plugins; diff --git a/ingen/client/SocketClient.hpp b/ingen/client/SocketClient.hpp index 092ef9d2..b3656d92 100644 --- a/ingen/client/SocketClient.hpp +++ b/ingen/client/SocketClient.hpp @@ -33,9 +33,13 @@ public: const URI& uri, SPtr<Raul::Socket> sock, SPtr<Interface> respondee) - : SocketWriter(world.uri_map(), world.uris(), uri, sock) - , _respondee(respondee) - , _reader(world, *respondee.get(), sock) + : SocketWriter(world.rdf_world(), + world.uri_map(), + world.uris(), + uri, + sock) + , _respondee(respondee) + , _reader(world, *respondee.get(), sock) {} SPtr<Interface> respondee() const override { @@ -56,7 +60,7 @@ public: : Raul::Socket::Type::TCP); SPtr<Raul::Socket> sock(new Raul::Socket(type)); - if (!sock->connect(uri)) { + if (!sock->connect(uri.str())) { world.log().error("Failed to connect <%1%> (%2%)\n", sock->uri(), strerror(errno)); return SPtr<Interface>(); diff --git a/ingen/filesystem.hpp b/ingen/filesystem.hpp index 5156eb79..8be6b1f4 100644 --- a/ingen/filesystem.hpp +++ b/ingen/filesystem.hpp @@ -27,6 +27,8 @@ # include <io.h> # define F_OK 0 # define mkdir(path, flags) _mkdir(path) +#else +# include <unistd.h> #endif #include <cerrno> diff --git a/ingen/paths.hpp b/ingen/paths.hpp index 05496114..fa6c9aff 100644 --- a/ingen/paths.hpp +++ b/ingen/paths.hpp @@ -29,12 +29,12 @@ inline URI main_uri() { return URI("ingen:/main"); } inline bool uri_is_path(const URI& uri) { - const size_t root_len = main_uri().string().length(); + const size_t root_len = main_uri().length(); if (uri == main_uri()) { return true; } else { - return uri.string().substr(0, root_len + 1) == - main_uri().string() + "/"; + return uri.str().substr(0, root_len + 1) == + main_uri().str() + "/"; } } 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) diff --git a/tests/empty.ingen/main.ttl b/tests/empty.ingen/main.ttl index 8b60b3aa..4a0925c3 100644 --- a/tests/empty.ingen/main.ttl +++ b/tests/empty.ingen/main.ttl @@ -46,4 +46,3 @@ lv2:symbol "notify" ; a atom:AtomPort , lv2:OutputPort . - diff --git a/tests/ingen_test.cpp b/tests/ingen_test.cpp index 476fab64..96117e8f 100644 --- a/tests/ingen_test.cpp +++ b/tests/ingen_test.cpp @@ -15,6 +15,7 @@ */ #include "TestClient.hpp" + #include "ingen_config.h" #include "ingen/Atom.hpp" @@ -37,15 +38,15 @@ #include "ingen/runtime_paths.hpp" #include "ingen/types.hpp" #include "raul/Path.hpp" -#include "serd/serd.h" -#include "sord/sordmm.hpp" -#include "sratom/sratom.h" +#include "serd/serd.hpp" +#include "sratom/sratom.hpp" #include <chrono> #include <cstdint> #include <cstdlib> #include <iostream> #include <string> +#include <string> #include <utility> using namespace std; @@ -124,9 +125,8 @@ main(int argc, char** argv) // Read commands - AtomForge forge(world->uri_map().urid_map_feature()->urid_map); - - sratom_set_object_mode(&forge.sratom(), SRATOM_OBJECT_MODE_BLANK_SUBJECT); + AtomForge forge(world->rdf_world(), + world->uri_map().urid_map_feature()->urid_map); // AtomReader to read commands from a file and send them to engine AtomReader atom_reader(world->uri_map(), @@ -140,47 +140,46 @@ main(int argc, char** argv) world->interface()->set_respondee(client); world->engine()->register_client(client); - SerdURI cmds_base; - SerdNode cmds_file_uri = serd_node_new_file_uri( - (const uint8_t*)run_path.c_str(), - nullptr, &cmds_base, true); - Sord::Model* cmds = new Sord::Model(*world->rdf_world(), - (const char*)cmds_file_uri.buf); - SerdEnv* env = serd_env_new(&cmds_file_uri); - cmds->load_file(env, SERD_TURTLE, run_path); - Sord::Node nil; + serd::Node run_uri = serd::make_file_uri(run_path.string()); + serd::Model cmds(world->rdf_world(), + serd::ModelFlag::index_SPO | serd::ModelFlag::index_OPS); + + serd::Env env(run_uri); + serd::Inserter inserter(cmds, env); + serd::Reader reader( + world->rdf_world(), serd::Syntax::Turtle, {}, inserter.sink(), 4096); + + reader.start_file(run_path.string()); + reader.read_document(); + reader.finish(); + int n_events = 0; for (;; ++n_events) { - std::string subject_str = fmt("msg%1%", n_events); - Sord::URI subject(*world->rdf_world(), subject_str, - (const char*)cmds_file_uri.buf); - Sord::Iter iter = cmds->find(subject, nil, nil); - if (iter.end()) { + const auto subject = serd::make_resolved_uri( + std::string("msg") + std::to_string(n_events), run_uri); + if (!cmds.ask(subject, {}, {})) { break; } - forge.clear(); - forge.read(*world->rdf_world(), cmds->c_obj(), subject.c_obj()); + auto atom = forge.read(cmds, subject); #if 0 - const LV2_Atom* atom = forge.atom(); - cerr << "READ " << atom->size << " BYTES" << endl; - cerr << sratom_to_turtle( - sratom, - &world->uri_map().urid_unmap_feature()->urid_unmap, - (const char*)cmds_file_uri.buf, - nullptr, nullptr, atom->type, atom->size, LV2_ATOM_BODY(atom)) << endl; + sratom::Streamer streamer{ + world->rdf_world(), + world->uri_map().urid_map_feature()->urid_map, + world->uri_map().urid_unmap_feature()->urid_unmap}; + + auto str = streamer.to_string(env, *atom); + cerr << "Read " << atom->size << " bytes:\n" << str << endl; #endif - if (!atom_reader.write(forge.atom(), n_events + 1)) { + if (!atom_reader.write(atom, n_events + 1)) { return EXIT_FAILURE; } world->engine()->flush_events(std::chrono::milliseconds(20)); } - delete cmds; - // Save resulting graph auto r = world->store()->find(Raul::Path("/")); const std::string base = run_path.stem(); @@ -212,9 +211,6 @@ main(int argc, char** argv) const FilePath redo_path = filesystem::current_path() / redo_name; world->serialiser()->write_bundle(r->second, URI(redo_path)); - serd_env_free(env); - serd_node_free(&cmds_file_uri); - // Shut down world->engine()->deactivate(); diff --git a/tests/tst_FilePath.cpp b/tests/tst_FilePath.cpp index 768371fe..68f734f0 100644 --- a/tests/tst_FilePath.cpp +++ b/tests/tst_FilePath.cpp @@ -18,8 +18,7 @@ #include "ingen/FilePath.hpp" #include "ingen/fmt.hpp" - -#include <boost/utility/string_view.hpp> +#include "serd/serd.hpp" #include <string> @@ -91,7 +90,7 @@ main(int, char**) path += 'r'; EXPECT_EQ(path, "/a/bar/car"); - path += boost::string_view("/d"); + path += serd::StringView("/d"); EXPECT_EQ(path, "/a/bar/car/d"); const FilePath apple("apple"); @@ -6,7 +6,7 @@ from waflib import Logs, Options, Utils from waflib.extras import autowaf # Package version -INGEN_VERSION = '0.5.1' +INGEN_VERSION = '1.0.0' INGEN_MAJOR_VERSION = '0' # Mandatory waf variables @@ -67,10 +67,9 @@ def configure(conf): conf.check_pkg('lv2 >= 1.16.0', uselib_store='LV2') conf.check_pkg('lilv-0 >= 0.21.5', uselib_store='LILV') conf.check_pkg('suil-0 >= 0.8.7', uselib_store='SUIL') - conf.check_pkg('sratom-0 >= 0.4.6', uselib_store='SRATOM') + conf.check_pkg('sratom-1 >= 1.0.0', uselib_store='SRATOM') conf.check_pkg('raul-1 >= 1.0.0', uselib_store='RAUL') - conf.check_pkg('serd-0 >= 0.30.3', uselib_store='SERD', mandatory=False) - conf.check_pkg('sord-0 >= 0.12.0', uselib_store='SORD', mandatory=False) + conf.check_pkg('serd-1 >= 1.0.0', uselib_store='SERD', mandatory=False) conf.check_pkg('portaudio-2.0', uselib_store='PORTAUDIO', mandatory=False) conf.check_pkg('sigc++-2.0', uselib_store='SIGCPP', mandatory=False) @@ -91,7 +90,6 @@ def configure(conf): defines = '_GNU_SOURCE=1', define_name = 'HAVE_VASPRINTF', mandatory = False) - conf.check(define_name = 'HAVE_LIBDL', lib = 'dl', mandatory = False) @@ -216,7 +214,7 @@ def build(bld): target = 'ingen', includes = ['.'], use = 'libingen', - uselib = 'SERD SORD SRATOM RAUL LILV LV2', + uselib = 'SERD SRATOM RAUL LILV LV2', install_path = '${BINDIR}') # Test program @@ -227,7 +225,7 @@ def build(bld): target = 'tests/%s' % i, includes = ['.'], use = 'libingen', - uselib = 'SERD SORD SRATOM RAUL LILV LV2', + uselib = 'SERD SRATOM RAUL LILV LV2', install_path = '', cxxflags = bld.env.INGEN_TEST_CXXFLAGS, linkflags = bld.env.INGEN_TEST_LINKFLAGS) |