6using System.Threading.Tasks;
39 private readonly Dictionary<string, string> namespaces =
new Dictionary<string, string>
41 {
"xsd", XmlSchema.Namespace },
42 {
"ttl",
"http://www.w3.org/2008/turtle#" }
44 private readonly Dictionary<string, ISemanticLiteral> dataTypes =
new Dictionary<string, ISemanticLiteral>();
45 private readonly
string text;
46 private readonly
string blankNodeIdPrefix;
47 private readonly
int len;
49 private DateTimeOffset? date =
null;
50 private Uri baseUri =
null;
51 private int blankNodeIndex = 0;
69 : this(
Text, BaseUri,
"n")
94 this.len = this.text.Length;
95 this.baseUri = BaseUri;
96 this.blankNodeIdPrefix = BlankNodeIdPrefix;
99 if (!(this.baseUri is
null))
100 this.namespaces[
string.Empty] = this.baseUri.ToString();
108 public string Text => this.text;
113 public DateTimeOffset?
Date => this.date;
115 private void ParseTriples()
117 this.ParseTriples(
null);
119 if (this.pos < this.len)
127 int TriplePosition = Subject is
null ? 0 : 1;
128 bool InBlankNode = !(Subject is
null);
130 while (this.pos < this.len)
132 Object = this.ParseElement(TriplePosition,
139 else if (Predicate is
null)
155 if (!(AdditionalTriples is
null))
156 this.
triples.AddRange(AdditionalTriples);
158 else if (Predicate is
null)
163 if (!(AdditionalTriples is
null))
164 this.
triples.AddRange(AdditionalTriples);
169 if (!(AdditionalTriples is
null))
170 this.
triples.AddRange(AdditionalTriples);
172 switch (this.NextNonWhitespaceChar())
187 this.SkipWhiteSpace();
188 if (this.PeekNextChar() ==
'.')
224 this.SkipWhiteSpace();
225 if (this.PeekNextChars(2) ==
"{|")
232 this.ParseTriples(T);
234 this.SkipWhiteSpace();
235 if (this.NextChar() !=
'}')
243 AdditionalTriples =
null;
247 char ch = this.NextNonWhitespaceChar();
255 string s = this.ParseName();
260 ch = this.NextNonWhitespaceChar();
264 this.baseUri = this.ParseUri().
Uri;
266 if (this.NextNonWhitespaceChar() !=
'.')
272 this.SkipWhiteSpace();
274 s = this.ParseName();
276 if (this.NextNonWhitespaceChar() !=
':')
279 if (this.NextNonWhitespaceChar() !=
'<')
282 this.namespaces[s] = this.ParseUri().
Uri.ToString();
284 if (this.NextNonWhitespaceChar() !=
'.')
295 switch (TriplePosition)
299 this.ParseTriples(Node);
301 this.SkipWhiteSpace();
302 if (this.PeekNextChar() ==
'.')
306 if (!(AdditionalTriples is
null))
307 this.
triples.AddRange(AdditionalTriples);
320 Node = this.CreateBlankNode();
321 this.ParseTriples(Node);
332 return this.ParseCollection(out AdditionalTriples);
338 if (this.PeekNextChar() ==
'<')
346 if (this.NextNonWhitespaceChar() !=
'>')
349 if (this.NextNonWhitespaceChar() !=
'>')
352 if (!(AdditionalTriples1 is
null))
353 this.
triples.AddRange(AdditionalTriples1);
355 if (!(AdditionalTriples2 is
null))
356 this.
triples.AddRange(AdditionalTriples2);
358 if (!(AdditionalTriples3 is
null))
359 this.
triples.AddRange(AdditionalTriples3);
364 return this.ParseUri();
368 if (TriplePosition != 2)
371 if (this.pos < this.len - 1 && this.text[this.pos] == ch && this.text[this.pos + 1] == ch)
374 s = this.ParseString(ch,
true,
true);
377 s = this.ParseString(ch,
false,
true);
379 string Language =
null;
381 if (this.pos < this.len && this.text[this.pos] ==
'@')
384 Language = this.ParseName();
387 if (this.pos < this.len - 1 && this.text[this.pos] ==
'^' && this.text[this.pos + 1] ==
'^')
391 string DataType = this.ParseUriOrPrefixedToken().
Uri.ToString();
393 if (!this.dataTypes.TryGetValue(DataType, out
ISemanticLiteral LiteralType))
398 this.dataTypes[DataType] = LiteralType;
401 return LiteralType.Parse(s, DataType, Language);
403 else if (!
string.IsNullOrEmpty(Language))
409 return this.ParsePrefixedToken(
string.Empty);
412 if (
char.IsWhiteSpace(ch))
417 if (this.NextNonWhitespaceChar() !=
':')
422 else if (
char.IsLetter(ch) || ch ==
':')
425 s = this.ParseName();
427 if (this.PeekNextChar() ==
':')
430 return this.ParsePrefixedToken(s);
436 if (TriplePosition == 1)
441 if (TriplePosition == 2)
446 if (TriplePosition == 2)
455 if (TriplePosition != 2)
459 return this.ParseNumber();
468 return new BlankNode(this.blankNodeIdPrefix + Guid.NewGuid().ToString());
470 return new BlankNode(this.blankNodeIdPrefix + (++this.blankNodeIndex).
ToString());
476 AdditionalTriples =
null;
478 this.SkipWhiteSpace();
480 while (this.pos < this.len)
482 if (this.text[this.pos] ==
')')
486 if (Elements is
null)
490 BlankNode Result = this.CreateBlankNode();
494 while (!(Loop is
null))
496 for (i = Loop.
Start, c = Loop.
Pos; i < c; i++)
500 if (i < c - 1 || !(Loop.
Next is
null))
519 if (!(AdditionalTriples2 is
null))
521 if (AdditionalTriples is
null)
524 AdditionalTriples.AddRange(AdditionalTriples2);
530 if (Elements is
null)
533 Elements.
Add(Element);
534 this.SkipWhiteSpace();
540 private UriNode ParseUriOrPrefixedToken()
542 if (this.pos >= this.len)
545 if (this.text[this.pos] ==
'<')
548 return this.ParseUri();
551 string Prefix = this.ParseName();
553 if (this.NextChar() !=
':')
556 return this.ParsePrefixedToken(Prefix);
559 private UriNode ParsePrefixedToken(
string Prefix)
561 if (!this.namespaces.TryGetValue(Prefix, out
string Namespace))
564 this.SkipWhiteSpace();
566 string LocalName = this.ParseName();
568 return new UriNode(
new Uri(Namespace + LocalName), Prefix +
":" + LocalName);
571 private string ParseName()
576 int Start = this.pos++;
577 bool LastPeriod =
false;
579 while (
IsNameChar(this.PeekNextChar(), ref LastPeriod))
585 return this.text.Substring(Start, this.pos - Start);
607 else if (ch <
'\xc0')
609 else if (ch <=
'\xd6')
611 else if (ch <
'\xd8')
613 else if (ch <=
'\xf6')
615 else if (ch <
'\xf8')
617 else if (ch <=
'\x02ff')
619 else if (ch <
'\x0370')
621 else if (ch <=
'\x037d')
623 else if (ch <
'\x037f')
625 else if (ch <=
'\x1fff')
627 else if (ch <
'\x037f')
629 else if (ch <=
'\x1fff')
631 else if (ch <
'\x200c')
633 else if (ch <=
'\x200d')
635 else if (ch <
'\x2070')
637 else if (ch <=
'\x218f')
639 else if (ch <
'\x2C00')
641 else if (ch <=
'\x2FEF')
643 else if (ch <
'\x3001')
645 else if (ch <=
'\xD7FF')
647 else if (ch <
'\xF900')
649 else if (ch <=
'\xFDCF')
651 else if (ch <
'\xFDF0')
653 else if (ch <=
'\xFFFD')
691 else if (ch <
'\x00B7')
693 else if (ch ==
'\x00B7')
698 else if (ch <
'\x0300')
700 else if (ch <=
'\x036F')
705 else if (ch <
'\x203F')
707 else if (ch <=
'\x2040')
718 int Start = this.pos;
719 char ch = this.PeekNextChar();
720 bool HasDigits =
false;
721 bool HasDecimal =
false;
722 bool HasExponent =
false;
724 if (ch ==
'+' || ch ==
'-')
727 ch = this.PeekNextChar();
730 while (
char.IsDigit(ch))
733 ch = this.PeekNextChar();
741 ch = this.PeekNextChar();
743 while (
char.IsDigit(ch))
746 ch = this.PeekNextChar();
750 if (ch ==
'e' || ch ==
'E')
754 ch = this.PeekNextChar();
756 if (ch ==
'+' || ch ==
'-')
759 ch = this.PeekNextChar();
762 while (
char.IsDigit(ch))
765 ch = this.PeekNextChar();
769 if (this.pos > Start)
771 string s = this.text.Substring(Start, this.pos - Start);
789 if (BigInteger.TryParse(s, out BigInteger bi))
799 private string ParseString(
char EndChar,
bool MultiLine,
bool IncludeWhiteSpace)
801 StringBuilder sb =
null;
802 int Start = this.pos;
805 while ((ch = this.PeekNextChar()) != (
char)0)
813 if (this.pos < this.len - 1 && this.text[this.pos] == EndChar && this.text[this.pos + 1] == EndChar)
816 return sb?.ToString() ?? this.text.Substring(Start, this.pos - Start - 3);
822 return sb?.ToString() ?? this.text.Substring(Start, this.pos - Start - 1);
828 sb =
new StringBuilder();
830 if (this.pos > Start + 1)
831 sb.Append(this.text.Substring(Start,
this.pos - Start - 1));
834 switch (ch = this.NextChar())
868 if (this.pos < this.len - 3 &&
int.TryParse(this.text.Substring(
this.pos, 4),
System.Globalization.NumberStyles.HexNumber,
null, out
int i))
878 if (this.pos < this.len - 7 &&
int.TryParse(this.text.Substring(
this.pos, 8),
System.Globalization.NumberStyles.HexNumber,
null, out i))
892 else if (IncludeWhiteSpace || !
char.IsWhiteSpace(ch))
896 throw this.
ParsingException(
"Expected " +
new string(EndChar, MultiLine ? 3 : 1));
906 string Short = this.ParseString(
'>',
false,
false);
908 if (this.baseUri is
null)
910 if (Uri.TryCreate(Short, UriKind.RelativeOrAbsolute, out Uri URI))
911 return new UriNode(URI, Short);
917 if (
string.IsNullOrEmpty(Short))
918 return new UriNode(this.baseUri, Short);
919 else if (Uri.TryCreate(
this.baseUri, Short, out Uri URI))
920 return new UriNode(URI, Short);
926 private void SkipLine()
930 while ((ch = this.PeekNextChar()) !=
'\r' && ch !=
'\n' && ch != 0)
934 private void SkipWhiteSpace()
940 ch = this.PeekNextChar();
942 if (
char.IsWhiteSpace(ch))
951 private char PeekNextChar()
953 if (this.pos < this.len)
954 return this.text[this.pos];
959 private string PeekNextChars(
int NrChars)
961 if (this.pos + NrChars <= this.len)
962 return this.text.Substring(this.pos, NrChars);
967 private char NextChar()
969 if (this.pos < this.len)
971 char ch = this.text[this.pos++];
975 if (this.pos < this.len)
976 ch = this.text[this.pos++];
987 private char NextNonWhitespaceChar()
993 ch = this.NextChar();
995 while (ch != 0 &&
char.IsWhiteSpace(ch));
1006 this.date = HttpResponse.Headers.Date;
1007 return Task.CompletedTask;
Helps with parsing of commong data types.
static bool TryParse(string s, out double Value)
Tries to decode a string encoded double.
ChunkedList< ISemanticTriple > triples
Triples in model.
Represents a bool literal.
Represents a custom literal.
Represents a decimal literal.
Represents a double literal.
Represents an integer literal of undefined size.
Represents a string literal.
Abstract base class for semantic literal values.
Implements a semantic triple.
Contains semantic information stored in an RDF document.
static UriNode RdfType
rdf:type predicate
static UriNode RdfNil
Predefined reference to end of collection.
static UriNode RdfRest
Predefined reference to next element in a collection.
static UriNode RdfFirst
Predefined reference to first element in a collection.
Contains semantic information stored in a turtle document. https://www.w3.org/TR/rdf12-turtle/ https:...
override void Add(ISemanticTriple Triple)
Adds a triple to the cube.
static bool IsNameChar(char ch, ref bool LastPeriod)
Checks if a character can be included in a name.
string Text
Original text of document.
TurtleDocument(string Text)
Contains semantic information stored in a turtle document.
Task DecodeMetaInformation(HttpResponseMessage HttpResponse)
Decodes meta-information available in the HTTP Response.
DateTimeOffset? Date
Server timestamp of document.
static bool IsNameStartChar(char ch)
Checks if a character is a character that can start a name.
TurtleDocument(string Text, Uri BaseUri, string BlankNodeIdPrefix)
Contains semantic information stored in a turtle document.
TurtleDocument(string Text, Uri BaseUri)
Contains semantic information stored in a turtle document.
TurtleDocument(string Text, Uri BaseUri, string BlankNodeIdPrefix, BlankNodeIdMode BlankNodeIdMode)
Contains semantic information stored in a turtle document.
Node referencing a chunk in a ChunkedList<T>
ChunkNode< T > Next
Next chunk
int Pos
Index after the last element in chunk.
int Start
Index of first element in chunk.
A chunked list is a linked list of chunks of objects of type T .
ChunkNode< T > FirstChunk
First chunk
void Add(T Item)
Adds an item to the collection.
Static class that dynamically manages types and interfaces available in the runtime environment.
Interface for content classes, that process information available in HTTP headers in the response.
Interface for semantic nodes.
Interface for semantic literals.
Interface for semantic triples.
ISemanticElement Object
Object element
ISemanticElement Predicate
Predicate element
ISemanticElement Subject
Subject element
BlankNodeIdMode
How blank node IDs are generated
delegate string ToString(IElement Element)
Delegate for callback methods that convert an element value to a string.
Prefix
SI prefixes. http://physics.nist.gov/cuu/Units/prefixes.html