Skip to content

Commit 6d7def1

Browse files
author
Marco De Salvo
committed
WIP Turtle/TriG buffered stream reader
1 parent c637600 commit 6d7def1

File tree

9 files changed

+4848
-4690
lines changed

9 files changed

+4848
-4690
lines changed

RDFSharp/Model/Serializers/RDFNTriples.cs renamed to RDFSharp/Model/Serializers/N-Triples/RDFNTriples.cs

Lines changed: 487 additions & 487 deletions
Large diffs are not rendered by default.

RDFSharp/Model/Serializers/RDFTriX.cs renamed to RDFSharp/Model/Serializers/TriX/RDFTriX.cs

Lines changed: 394 additions & 394 deletions
Large diffs are not rendered by default.

RDFSharp/Model/Serializers/RDFTurtle.cs renamed to RDFSharp/Model/Serializers/Turtle/RDFTurtle.cs

Lines changed: 1581 additions & 1640 deletions
Large diffs are not rendered by default.
Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
/*
2+
Copyright 2012-2025 Marco De Salvo
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
using System;
18+
using System.IO;
19+
20+
namespace RDFSharp.Model
21+
{
22+
/// <summary>
23+
/// Buffer scorrevole per la lettura efficiente di stream di grandi dimensioni durante il parsing Turtle
24+
/// </summary>
25+
internal class TurtleStreamBuffer : IDisposable
26+
{
27+
private readonly StreamReader _reader;
28+
private readonly char[] _buffer;
29+
private readonly int _bufferSize;
30+
31+
private int _bufferStart; // Posizione assoluta nel file del primo carattere nel buffer
32+
private int _bufferLength; // Numero di caratteri validi nel buffer
33+
private bool _endOfStream;
34+
35+
/// <summary>
36+
/// Posizione corrente nel file
37+
/// </summary>
38+
public int Position { get; set; }
39+
40+
/// <summary>
41+
/// Indica se abbiamo raggiunto la fine del file
42+
/// </summary>
43+
public bool IsEndOfFile => _endOfStream && Position >= _bufferStart + _bufferLength;
44+
45+
public TurtleStreamBuffer(StreamReader reader, int bufferSize = 8192)
46+
{
47+
_reader = reader ?? throw new ArgumentNullException(nameof(reader));
48+
_bufferSize = bufferSize;
49+
_buffer = new char[bufferSize];
50+
_bufferStart = 0;
51+
_bufferLength = 0;
52+
Position = 0;
53+
_endOfStream = false;
54+
55+
// Carica il primo blocco
56+
FillBuffer();
57+
}
58+
59+
/// <summary>
60+
/// Legge il prossimo code point Unicode
61+
/// </summary>
62+
public int ReadCodePoint()
63+
{
64+
if (IsEndOfFile)
65+
return -1;
66+
67+
// Assicurati che il carattere corrente sia nel buffer
68+
EnsureBufferContainsPosition();
69+
70+
if (Position >= _bufferStart + _bufferLength)
71+
return -1; // EOF
72+
73+
int bufferIndex = Position - _bufferStart;
74+
char highSurrogate = _buffer[bufferIndex];
75+
Position++;
76+
77+
// Gestione surrogate pairs per caratteri Unicode supplementari
78+
if (char.IsHighSurrogate(highSurrogate))
79+
{
80+
EnsureBufferContainsPosition();
81+
if (Position < _bufferStart + _bufferLength)
82+
{
83+
bufferIndex = Position - _bufferStart;
84+
char lowSurrogate = _buffer[bufferIndex];
85+
if (char.IsLowSurrogate(lowSurrogate))
86+
{
87+
Position++;
88+
return char.ConvertToUtf32(highSurrogate, lowSurrogate);
89+
}
90+
}
91+
}
92+
93+
return highSurrogate;
94+
}
95+
96+
/// <summary>
97+
/// Sbircia il prossimo code point senza avanzare la posizione
98+
/// </summary>
99+
public int PeekCodePoint()
100+
{
101+
int currentPos = Position;
102+
int codePoint = ReadCodePoint();
103+
Position = currentPos; // Ripristina posizione
104+
return codePoint;
105+
}
106+
107+
/// <summary>
108+
/// Torna indietro di un code point
109+
/// </summary>
110+
public void UnreadCodePoint(int codePoint)
111+
{
112+
if (codePoint == -1)
113+
return;
114+
115+
if (IsSupplementaryCodePoint(codePoint))
116+
{
117+
// Carattere supplementare (surrogate pair) - torna indietro di 2 posizioni
118+
Position = Math.Max(0, Position - 2);
119+
}
120+
else
121+
{
122+
// Carattere normale - torna indietro di 1 posizione
123+
Position = Math.Max(0, Position - 1);
124+
}
125+
}
126+
127+
/// <summary>
128+
/// Torna indietro per una stringa di caratteri
129+
/// </summary>
130+
public void UnreadString(string str)
131+
{
132+
if (string.IsNullOrEmpty(str))
133+
return;
134+
135+
// Torna indietro carattere per carattere (dal fondo)
136+
for (int i = str.Length - 1; i >= 0; i--)
137+
{
138+
UnreadCodePoint(str[i]);
139+
}
140+
}
141+
142+
/// <summary>
143+
/// Assicura che il buffer contenga la posizione corrente
144+
/// </summary>
145+
private void EnsureBufferContainsPosition()
146+
{
147+
// Se la posizione è oltre la fine del buffer corrente, carica nuovo buffer
148+
if (Position >= _bufferStart + _bufferLength && !_endOfStream)
149+
{
150+
FillBuffer();
151+
}
152+
// Se la posizione è prima dell'inizio del buffer, dobbiamo gestire backward seek
153+
else if (Position < _bufferStart)
154+
{
155+
// Per semplicità, ricarica dall'inizio (può essere ottimizzato se necessario)
156+
ReloadFromPosition(Position);
157+
}
158+
}
159+
160+
/// <summary>
161+
/// Riempie il buffer dalla posizione corrente
162+
/// </summary>
163+
private void FillBuffer()
164+
{
165+
if (_endOfStream)
166+
return;
167+
168+
// Se siamo alla fine del buffer corrente, shift del buffer
169+
if (Position >= _bufferStart + _bufferLength)
170+
{
171+
_bufferStart = Position;
172+
}
173+
174+
// Leggi il prossimo blocco
175+
_bufferLength = _reader.Read(_buffer, 0, _bufferSize);
176+
177+
if (_bufferLength == 0)
178+
{
179+
_endOfStream = true;
180+
}
181+
}
182+
183+
/// <summary>
184+
/// Ricarica il buffer da una posizione specifica (per backward seeks)
185+
/// </summary>
186+
private void ReloadFromPosition(int position)
187+
{
188+
// Questo è un caso limite - per semplicità resettiamo lo stream
189+
// In un'implementazione più sofisticata si potrebbe mantenere un buffer circolare
190+
if (_reader.BaseStream.CanSeek)
191+
{
192+
_reader.BaseStream.Seek(0, SeekOrigin.Begin);
193+
_reader.DiscardBufferedData();
194+
_bufferStart = 0;
195+
Position = 0;
196+
_endOfStream = false;
197+
198+
// Avanza fino alla posizione desiderata
199+
while (Position < position && !IsEndOfFile)
200+
{
201+
ReadCodePoint();
202+
}
203+
Position = position;
204+
}
205+
else
206+
{
207+
throw new InvalidOperationException("Cannot seek backward on non-seekable stream");
208+
}
209+
}
210+
211+
/// <summary>
212+
/// Determina se il code point richiede surrogate pair
213+
/// </summary>
214+
private static bool IsSupplementaryCodePoint(int codePoint)
215+
=> (codePoint & ~char.MaxValue) != 0;
216+
217+
public void Dispose()
218+
{
219+
_reader?.Dispose();
220+
}
221+
}
222+
}

0 commit comments

Comments
 (0)