diff --git a/VisualCard.Calendar/CalendarTools.cs b/VisualCard.Calendar/CalendarTools.cs
index 01caefe..afd3ce5 100644
--- a/VisualCard.Calendar/CalendarTools.cs
+++ b/VisualCard.Calendar/CalendarTools.cs
@@ -79,11 +79,13 @@ public static Parts.Calendar[] GetCalendars(StreamReader stream)
// Parse the lines of the calendar file
string CalendarLine;
- StringBuilder CalendarContent = new();
+ List<(int, string)> lines = [];
Version CalendarVersion = new();
+ int lineNumber = 0;
while (!stream.EndOfStream)
{
bool append = false;
+ lineNumber++;
// Skip empty lines
CalendarLine = stream.ReadLine();
@@ -97,7 +99,7 @@ public static Parts.Calendar[] GetCalendars(StreamReader stream)
!CalendarLine.EqualsNoCase(VCalendarConstants._endText))
append = true;
if (append)
- CalendarContent.Append(CalendarLine);
+ lines.Add((lineNumber, CalendarLine));
// All vCalendars must begin with BEGIN:VCALENDAR
if (!CalendarLine.EqualsNoCase(VCalendarConstants._beginText) && !BeginSpotted)
@@ -130,17 +132,13 @@ public static Parts.Calendar[] GetCalendars(StreamReader stream)
EndSpotted = true;
// Make a new parser instance
- string content = CalendarContent.ToString();
- string[] contentLines = content.SplitNewLines();
- VCalendarParser CalendarParser = new(contentLines, CalendarVersion);
+ VCalendarParser CalendarParser = new([.. lines], CalendarVersion);
FinalParsers.Add(CalendarParser);
// Clear the content in case we want to make a second contact
- CalendarContent.Clear();
+ lines.Clear();
BeginSpotted = false;
}
- else if (append)
- CalendarContent.AppendLine();
}
// Close the stream to avoid stuck file handle
diff --git a/VisualCard.Calendar/Parsers/VCalendarParser.cs b/VisualCard.Calendar/Parsers/VCalendarParser.cs
index fa0f1f1..92cb8e3 100644
--- a/VisualCard.Calendar/Parsers/VCalendarParser.cs
+++ b/VisualCard.Calendar/Parsers/VCalendarParser.cs
@@ -40,12 +40,12 @@ namespace VisualCard.Calendar.Parsers
internal class VCalendarParser
{
private readonly Version calendarVersion = new();
- private readonly string[] calendarContent = [];
+ private readonly (int, string)[] calendarContent = [];
///
/// vCalendar calendar content
///
- public string[] CalendarContent =>
+ public (int, string)[] CalendarContent =>
calendarContent;
///
/// vCalendar calendar version
@@ -73,8 +73,9 @@ public Parts.Calendar Parse()
for (int i = 0; i < CalendarContent.Length; i++)
{
// Get line
- string _value = CalendarContent[i];
- int lineNumber = i + 1;
+ var content = CalendarContent[i];
+ string _value = content.Item2;
+ int lineNumber = content.Item1;
if (string.IsNullOrEmpty(_value))
continue;
@@ -84,7 +85,7 @@ public Parts.Calendar Parse()
subPart = begins[begins.Count - 1].Item2;
// First, check to see if we need to construct blocks
- string secondLine = i + 1 < CalendarContent.Length ? CalendarContent[i + 1] : "";
+ string secondLine = i + 1 < CalendarContent.Length ? CalendarContent[i + 1].Item2 : "";
bool firstConstructedLine = !_value.StartsWith(VcardConstants._spaceBreak) && !_value.StartsWith(VcardConstants._tabBreak);
constructing = secondLine.StartsWithAnyOf([VcardConstants._spaceBreak, VcardConstants._tabBreak]);
secondLine = secondLine.Length > 1 ? secondLine.Substring(1) : "";
@@ -540,7 +541,7 @@ private void SaveLastSubPart(Parts.Calendar? subpart, ref Parts.Calendar part)
throw new ArgumentException($"Can't place {subpart.GetType().Name} inside {part.GetType().Name}");
}
- internal VCalendarParser(string[] calendarContent, Version calendarVersion)
+ internal VCalendarParser((int, string)[] calendarContent, Version calendarVersion)
{
this.calendarContent = calendarContent;
this.calendarVersion = calendarVersion;
diff --git a/VisualCard/CardTools.cs b/VisualCard/CardTools.cs
index 2117df9..b2a7d36 100644
--- a/VisualCard/CardTools.cs
+++ b/VisualCard/CardTools.cs
@@ -79,14 +79,16 @@ public static Card[] GetCards(StreamReader stream)
// Parse the lines of the card file
string CardLine;
- StringBuilder CardContent = new();
Version CardVersion = new();
List nestedCards = [];
+ List<(int, string)> lines = [];
bool nested = false;
bool versionDirect = false;
+ int lineNumber = 0;
while (!stream.EndOfStream)
{
bool append = false;
+ lineNumber++;
// Skip empty lines
CardLine = stream.ReadLine();
@@ -125,7 +127,7 @@ public static Card[] GetCards(StreamReader stream)
continue;
}
if (append)
- CardContent.Append(CardLine);
+ lines.Add((lineNumber, CardLine));
// All VCards must begin with BEGIN:VCARD
if (!CardLine.EqualsNoCase(VcardConstants._beginText) && !BeginSpotted)
@@ -170,22 +172,18 @@ public static Card[] GetCards(StreamReader stream)
nested = false;
// Make a new parser instance
- string content = CardContent.ToString();
- string[] contentLines = content.SplitNewLines();
- VcardParser CardParser = new(contentLines, CardVersion)
+ VcardParser CardParser = new([.. lines], CardVersion)
{
nestedCards = [.. nestedCards]
};
FinalParsers.Add(CardParser);
// Clear the content in case we want to make a second contact
- CardContent.Clear();
+ lines.Clear();
nestedCards.Clear();
BeginSpotted = false;
versionDirect = false;
}
- else if (append)
- CardContent.AppendLine();
}
// Close the stream to avoid stuck file handle
diff --git a/VisualCard/Parsers/VcardParser.cs b/VisualCard/Parsers/VcardParser.cs
index 6e70a26..15fb85b 100644
--- a/VisualCard/Parsers/VcardParser.cs
+++ b/VisualCard/Parsers/VcardParser.cs
@@ -40,12 +40,12 @@ internal class VcardParser
{
internal Card[] nestedCards = [];
private readonly Version cardVersion = new();
- private string[] cardContent = [];
+ private (int, string)[] cardContent = [];
///
/// VCard card content
///
- public string[] CardContent =>
+ public (int, string)[] CardContent =>
cardContent;
///
/// VCard card version
@@ -69,9 +69,9 @@ public Card Parse()
// Move kind to the top
if (CardVersion.Major >= 4)
{
- string kindLine = CardContent.SingleOrDefault((line) => line.ToUpper().StartsWith(VcardConstants._kindSpecifier));
- if (!string.IsNullOrEmpty(kindLine))
- cardContent = [kindLine, .. cardContent.Where((line) => line != kindLine).ToArray()];
+ var kindLine = CardContent.SingleOrDefault((line) => line.Item2.ToUpper().StartsWith(VcardConstants._kindSpecifier));
+ if (!string.IsNullOrEmpty(kindLine.Item2))
+ cardContent = [kindLine, .. cardContent.Where((line) => line.Item2 != kindLine.Item2).ToArray()];
}
// Iterate through all the lines
@@ -82,13 +82,14 @@ public Card Parse()
for (int i = 0; i < CardContent.Length; i++)
{
// Get line
- string _value = CardContent[i];
- int lineNumber = i + 1;
+ var content = CardContent[i];
+ string _value = content.Item2;
+ int lineNumber = content.Item1;
if (string.IsNullOrEmpty(_value))
continue;
// First, check to see if we need to construct blocks
- string secondLine = i + 1 < CardContent.Length ? CardContent[i + 1] : "";
+ string secondLine = i + 1 < CardContent.Length ? CardContent[i + 1].Item2 : "";
bool firstConstructedLine = !_value.StartsWith(VcardConstants._spaceBreak) && !_value.StartsWith(VcardConstants._tabBreak);
constructing = secondLine.StartsWithAnyOf([VcardConstants._spaceBreak, VcardConstants._tabBreak]);
secondLine = secondLine.Length > 1 ? secondLine.Substring(1) : "";
@@ -321,7 +322,7 @@ private bool ValidateComponent(ref string[] expectedFields, out stri
return actualFields.SequenceEqual(expectedFields);
}
- internal VcardParser(string[] cardContent, Version cardVersion)
+ internal VcardParser((int, string)[] cardContent, Version cardVersion)
{
this.cardContent = cardContent;
this.cardVersion = cardVersion;