From 6e44b54cfbd5cf285599f4bc2004da2248061e3b Mon Sep 17 00:00:00 2001 From: David Robillard Date: Wed, 9 Nov 2011 08:09:44 +0000 Subject: Link Atom classes to C type identifiers. Define C types for all Atom classes where a useful C type is possible. --- ext/atom.lv2/atom.h | 53 ++++++++++++++--- ext/atom.lv2/atom.ttl | 145 +++++++++++++++++++++++------------------------ lv2specgen/lv2specgen.py | 25 +++++--- 3 files changed, 132 insertions(+), 91 deletions(-) diff --git a/ext/atom.lv2/atom.h b/ext/atom.lv2/atom.h index 4b57040..39d721c 100644 --- a/ext/atom.lv2/atom.h +++ b/ext/atom.lv2/atom.h @@ -76,13 +76,13 @@ typedef struct { } LV2_Atom_Literal; /** - An atom:ID. + An atom:URID or atom:BlankID. This type may safely be cast to LV2_Atom. */ typedef struct { uint32_t type; /**< Type of this atom (mapped URI). */ uint32_t size; /**< Size in bytes, not including type and size. */ - uint32_t id; /**< Value, a URI mapped to an integer. */ + uint32_t id; /**< URID (integer mapped URI) or blank node ID. */ } LV2_Atom_ID; /** @@ -119,13 +119,8 @@ typedef struct { } LV2_Thing; /** - An Event (a timestamped Atom). - - Note this struct is different from the other structs in this header in that - it does not describe the body of some LV2_Atom, but instead is a "larger" - type which contains an LV2_Atom as its payload. This makes it possible for - an Event to be interpreted as an Atom in-place by simply pointing at - the @ref body field of the Event. + An atom:Event, a timestamped Atom. + Note this type is not an LV2_Atom, but contains an Atom as payload. */ typedef struct { uint32_t frames; /**< Time in frames relative to this block. */ @@ -133,6 +128,46 @@ typedef struct { LV2_Atom body; /**< Event body. */ } LV2_Atom_Event; +/** + An atom:Int32, a signed 32-bit integer. + This type may safely be cast to LV2_Atom. +*/ +typedef struct { + uint32_t type; + uint32_t size; + int32_t value; +} LV2_Atom_Int32; + +/** + An atom:Int64, a signed 64-bit integer. + This type may safely be cast to LV2_Atom. +*/ +typedef struct { + uint32_t type; + uint32_t size; + int64_t value; +} LV2_Atom_Int64; + +/** + An atom:Float, a 32-bit IEEE-754 floating point number. + This type may safely be cast to LV2_Atom. +*/ +typedef struct { + uint32_t type; + uint32_t size; + float value; +} LV2_Atom_Float; + +/** + An atom:Double, a 64-bit IEEE-754 floating point number. + This type may safely be cast to LV2_Atom. +*/ +typedef struct { + uint32_t type; + uint32_t size; + double value; +} LV2_Atom_Double; + /** A buffer of events (the contents of an atom:EventPort). diff --git a/ext/atom.lv2/atom.ttl b/ext/atom.lv2/atom.ttl index ce125d6..e49c544 100644 --- a/ext/atom.lv2/atom.ttl +++ b/ext/atom.lv2/atom.ttl @@ -20,6 +20,7 @@ @prefix rdf: . @prefix rdfs: . @prefix xsd: . +@prefix owl: . a lv2:Specification ; @@ -75,6 +76,7 @@ extension.

atom:Atom a rdfs:Class ; rdfs:label "Atom" ; + atom:cType "LV2_Atom" ; lv2:documentation """

Abstract base class for all atoms. An LV2_Atom has a 32-bit type and size followed by a body of @@ -102,11 +104,13 @@ atom:String a rdfs:Class ; rdfs:subClassOf atom:Atom ; rdfs:label "String" ; + atom:cType "LV2_Atom_String" ; lv2:documentation """

A UTF-8 encoded string.

-

The body of an atom:String is a C string in UTF-8 encoding, i.e. an array of -bytes (uint8_t) terminated with a NULL byte ('\\0').

+

The body of an LV2_Atom_String is a C string in UTF-8 encoding, i.e. an +array of bytes (uint8_t) terminated with a NULL byte +('\\0').

This type can be used for free-form strings, but in most cases it is better to use atom:Literal since this supports a language tag or datatype. Implementations @@ -118,48 +122,43 @@ atom:Literal a rdfs:Class ; rdfs:subClassOf atom:Atom ; rdfs:label "String Literal" ; + atom:cType "LV2_Atom_Literal" ; lv2:documentation """ -

A UTF-8 encoded string literal, with an optional language tag or datatype.

- -

This type is compatible with an RDF literal and is capable of expressing a -string in any language, or a value of any type. An LV2_Atom_Literal has a -URID lang and datatype followed by the -string data in UTF-8 encoding. The length of the string data in bytes is -size - (2 * sizeof(uint32_t)), including the terminating NULL -character. The lang field SHOULD be a URI of the form +

A UTF-8 encoded string literal, with an optional datatype or language.

+ +

This type is compatible with rdf:Literal and is capable of expressing a +string in any language, or a value of any type. A Literal has a +datatype and lang followed by string data in UTF-8 +encoding. The length of the string data in bytes is size - +sizeof(LV2_Atom_Literal), including the terminating NULL character. The +lang field SHOULD be a URI of the form <http://lexvo.org/id/term/LANG> where LANG is an ISO 693-2 or ISO 693-3 language code.

-

For example, "Hello" in English:

-
-struct LV2_Atom {
-    uint16_t type = uri_to_id(atom:Literal);
-    uint16_t size = 14;
-}
-uint32_t datatype = 0;
-uint32_t lang     = uri_to_id("http://lexvo.org/id/term/en");
-char     str[]    = "Hello";
-
-and French: +

For compatibility, a Literal MUST have either a datatype +or a lang, but never both.

+ +

For example, a Literal can be "Hello" in English:

-struct LV2_Atom {
-    uint16_t type = uri_to_id(atom:Literal);
-    uint16_t size = 16;
+void set_to_hello_in_english(LV2_Atom_Literal* lit) {
+     lit->type     = map(expand("atom:Literal"));
+     lit->size     = 14;
+     lit->datatype = 0;
+     lit->lang     = map("http://lexvo.org/id/term/en");
+     memcpy(lit->str, "Hello", sizeof("Hello"));  // Assumes enough space
 }
-uint32_t datatype = 0;
-uint32_t lang     = uri_to_id("http://lexvo.org/id/term/fr");
-char     str[]    = "Bonjour";
 
+

or a Turtle string:

-struct LV2_Atom {
-    uint16_t type = uri_to_id(atom:Literal);
-    uint16_t size = 64;
+void set_to_turtle_string(LV2_Atom_Literal* lit, const char* ttl) {
+     lit->type     = map(expand("atom:Literal"));
+     lit->size     = 64;
+     lit->datatype = map("http://www.w3.org/2008/turtle#turtle");
+     lit->lang     = 0;
+     memcpy(lit->str, ttl, strlen(ttl) + 1);  // Assumes enough space
 }
-uint32_t datatype = uri_to_id("http://www.w3.org/2008/turtle#turtle");
-uint32_t lang     = 0;
-char     str[]    = "<http://example.org/foo> a <http://example.org/Thing> ."
 
""" . @@ -167,6 +166,7 @@ atom:URID a rdfs:Class ; rdfs:subClassOf atom:Atom ; rdfs:label "Integer ID mapped from a URI" ; + atom:cType "LV2_Atom_ID" ; lv2:documentation """ An unsigned 32-bit integer mapped from a URI using the URI Map extension's @@ -177,6 +177,7 @@ atom:BlankID a rdfs:Class ; rdfs:subClassOf atom:Atom ; rdfs:label "Integer ID for a blank node" ; + atom:cType "LV2_Atom_ID" ; lv2:documentation """ An unsigned 32-bit integer identifier for a blank node. A BlankID is only meaningful within a limited scope (e.g. the Atom in which it appears), and @@ -188,38 +189,30 @@ atom:Vector a rdfs:Class ; rdfs:subClassOf atom:Atom ; rdfs:label "Vector" ; + atom:cType "LV2_Atom_Vector" ; lv2:documentation """

A homogeneous sequence of atoms with equivalent type and size.

-

An LV2_Atom_Vector is a 16-bit elem_count and +

An LV2_Atom_Vector is a 32-bit elem_count and elem_type followed by elem_count atom bodies of type elem_type. The element type must be a fixed size atom:Atom type, i.e. the size of each element is the vector's size / elem_count.

-

For example, an atom:Vector containing 42 elements of type atom:Float looks -like this in memory:

+

For example, an atom:Vector containing 42 elements of type atom:Float:

-struct LV2_Atom {
-    uint16_t type = uri_to_id(atom:Vector);
-    uint16_t size = sizeof(LV2_Atom) + sizeof(LV2_Atom_Vector) + (42 * sizeof(float);
-}
-struct LV2_Vector {
-    uint16_t elem_count = 42;
-    uint16_t elem_type  = uri_to_id(atom:Float);
-}
-float elem_00;
-float elem_01;
-...
-float elem_41;
+struct VectorOf42Floats {
+    uint32_t type;        // map(expand("atom:Vector"))
+    uint32_t size;        // sizeof(LV2_Atom_Vector) + (42 * sizeof(float);
+    uint32_t elem_count;  // 42
+    uint32_t elem_type;   // map(expand("atom:Float"))
+    float    elems[32];
+};
 

Note that it is possible to construct a valid Atom for each element of the vector, even by an implementation which does not understand elem_type.

- -

A Vector header is 64-bits, thus the first element of a Vector is 64-bit -aligned if the Vector itself is 64-bit aligned.

""" . atom:Tuple @@ -234,20 +227,11 @@ and size.

32 bits.

""" . -atom:Property - a rdfs:Class ; - rdfs:subClassOf atom:Atom ; - rdfs:label "Property of a Thing" ; - lv2:documentation """ -A single property of some lv2:Thing. An -LV2_Atom_Property has an atom:URID key and an atom:Atom -value. -""" . - atom:Thing a rdfs:Class ; rdfs:subClassOf atom:Atom ; rdfs:label "Thing" ; + atom:cType "LV2_Thing" ; lv2:documentation """

Abstract base class for a "Thing", i.e. an atom:Atom with a number of properties. An LV2_Object is an unsigned @@ -269,6 +253,7 @@ code using only a 64-bit header for both.

atom:Resource a rdfs:Class ; rdfs:subClassOf atom:Thing ; + atom:cType "LV2_Thing" ; lv2:documentation """ An atom:Thing where id is the URI of the resource mapped to an atom:URID. @@ -277,6 +262,7 @@ atom:URID. atom:Blank a rdfs:Class ; rdfs:subClassOf atom:Thing ; + atom:cType "LV2_Thing" ; lv2:documentation """ An atom:Thing where id is the blank node ID of the object, which is only meaningful within a certain limited scope (e.g. the container of the @@ -287,6 +273,7 @@ NOT an ID. atom:Message a rdfs:Class ; rdfs:subClassOf atom:Thing ; + atom:cType "LV2_Thing" ; lv2:documentation """ A atom:Thing where id is a message type ID. Conceptually, a Message is identical to a Blank, but is a distinct type with a single type @@ -299,6 +286,7 @@ value id unmapped to a URI. atom:Event a rdfs:Class ; rdfs:label "Event" ; + atom:cType "LV2_Atom_Event" ; lv2:documentation """ An atom with a time stamp header prepended, typically for sample accurate transmission via LV2 ports. See struct LV2_Atom_Event. @@ -309,40 +297,40 @@ atom:Bang rdfs:subClassOf atom:Atom ; rdfs:label "Bang (activity) (size = 0)" . -atom:Byte - a rdfs:Class ; - rdfs:subClassOf atom:Atom ; - rdfs:label "Byte (size = 1)" . - atom:Number a rdfs:Class ; - rdfs:subClassOf atom:Atom ; + rdfs:subClassOf atom:Atom ; rdfs:label "Number (abstract class)." . atom:Int32 a rdfs:Class ; rdfs:subClassOf atom:Number ; - rdfs:label "Signed 32-bit integer" . + rdfs:label "Signed 32-bit integer" ; + atom:cType "LV2_Atom_Int32" . atom:Int64 a rdfs:Class ; rdfs:subClassOf atom:Number ; - rdfs:label "Signed 64-bit integer" . + rdfs:label "Signed 64-bit integer" ; + atom:cType "LV2_Atom_Int64" . atom:Bool a rdfs:Class ; rdfs:subClassOf atom:Atom ; - rdfs:label "Signed 32-bit integer where 0 is false" . + rdfs:label "An atom:Int32 where 0 is false and all other values true" ; + atom:cType "LV2_Atom_Int32" . atom:Float a rdfs:Class ; rdfs:subClassOf atom:Number ; - rdfs:label "32-bit IEEE-754 floating point number" . + rdfs:label "32-bit IEEE-754 floating point number" ; + atom:cType "LV2_Atom_Float" . atom:Double a rdfs:Class ; rdfs:subClassOf atom:Number ; - rdfs:label "64-bit IEEE-754 floating point number" . + rdfs:label "64-bit IEEE-754 floating point number" ; + atom:cType "LV2_Atom_Double" . atom:blobSupport a lv2:Feature ; @@ -410,6 +398,17 @@ Intuitively, a MessagePort contains a "message" or "command" or "event" which is reacted to, NOT a "value" or "signal" (which is computed with). """ . +atom:cType + a rdf:Property , + owl:DatatypeProperty ; + rdfs:label "C type" ; + rdfs:domain rdfs:Class ; + rdfs:range xsd:string ; + rdfs:comment """ +The identifier for a C type describing the in-memory representation of +an instance of this class. +""" . + atom:EventPort a rdfs:Class ; rdfs:label "Event port" ; @@ -417,7 +416,7 @@ atom:EventPort lv2:documentation """ A port used for communicating time-stamped atoms in the audio context. Ports of this type are connected to an LV2_Atom_Buffer, which contains a flat -time-stamped sequence of atom:Event. +time-stamped sequence of atom:Event. This port type is intended as a simpler and atom compatible successor to ev:EventPort. diff --git a/lv2specgen/lv2specgen.py b/lv2specgen/lv2specgen.py index 7f86686..428a6ef 100755 --- a/lv2specgen/lv2specgen.py +++ b/lv2specgen/lv2specgen.py @@ -210,7 +210,21 @@ if have_pygments: (r'(?=\s*\.)', Text, '#pop'), ], } + +def linkify(string): + "Add links to code documentation for identifiers" + if string in linkmap.keys(): + # Exact match for complete string + return linkmap[string] + + rgx = re.compile('([^a-zA-Z0-9_:])(' + \ + '|'.join(map(re.escape, linkmap)) + \ + ')([^a-aA-Z0-9_:])') + + def translateCodeLink(match): + return match.group(1) + linkmap[match.group(2)] + match.group(3) + return rgx.sub(translateCodeLink, string) def getComment(m, urinode, classlist): c = findOne(m, urinode, lv2.documentation, None) @@ -246,14 +260,7 @@ def getComment(m, urinode, classlist): markup = code_rgx.sub(code_str, markup, 1) # Add links to code documentation for identifiers - rgx = re.compile('([^a-zA-Z0-9_:])(' + \ - '|'.join(map(re.escape, linkmap)) + \ - ')([^a-aA-Z0-9_:])') - - def translateCodeLink(match): - return match.group(1) + linkmap[match.group(2)] + match.group(3) - - markup = rgx.sub(translateCodeLink, markup) + markup = linkify(markup) # Replace ext:ClassName with links to appropriate fragment rgx = re.compile(spec_pre + ':([A-Z][a-zA-Z0-9_-]*)') @@ -513,7 +520,7 @@ def extraInfo(term, m): if isResource(getObject(p)): doc += getProperty(getTermLink(getObject(p), term, getPredicate(p)), first) elif isLiteral(getObject(p)): - doc += getProperty(str(getObject(p)), first) + doc += getProperty(linkify(str(getObject(p))), first) elif isBlank(getObject(p)): doc += getProperty(str(blankNodeDesc(getObject(p), m)), first) else: -- cgit v1.2.1