Files
markdig/src/Textamina.Markdig/Syntax/StringLineGroup.cs

255 lines
6.5 KiB
C#
Raw Normal View History

2016-02-18 00:34:26 +09:00
using System;
using System.Collections.ObjectModel;
using System.Text;
using Textamina.Markdig.Helpers;
2016-02-17 01:00:26 +09:00
using Textamina.Markdig.Parsing;
namespace Textamina.Markdig.Syntax
{
public class StringLineGroup : Collection<StringLine>
2016-02-17 01:00:26 +09:00
{
2016-02-17 20:34:26 +09:00
private StringLine currentLine;
public StringLineGroup()
{
}
public StringLineGroup(string text)
{
if (text == null) throw new ArgumentNullException(nameof(text));
Add(new StringLine(text));
}
2016-02-17 20:34:26 +09:00
public int LinePosition { get; private set; }
public int ColumnPosition { get; private set; }
public StringLine Current => currentLine;
public char CurrentChar { get; private set; }
2016-02-17 20:34:26 +09:00
2016-02-18 00:34:26 +09:00
public char PreviousChar1 { get; private set; }
public char PreviousChar2 { get; private set; }
public void Reset()
2016-02-17 20:34:26 +09:00
{
ColumnPosition = -1;
2016-02-20 01:18:40 +09:00
LinePosition = 0;
2016-02-17 20:34:26 +09:00
currentLine = Count > 0 ? this[0] : null;
if (currentLine != null)
{
ColumnPosition = currentLine.Start - 1;
}
2016-02-17 20:34:26 +09:00
NextChar();
}
2016-02-22 20:40:34 +09:00
public void SetColumn(int index)
{
if (Current != null && index <= Current.End)
{
CurrentChar = Current[index];
ColumnPosition = index;
// Don't set previous char
PreviousChar1 = '\0';
PreviousChar2 = '\0';
}
}
public char PeekCharOnSameLine()
{
if (Current != null && (ColumnPosition+1) <= Current.End)
{
return Current[ColumnPosition + 1];
}
return (char)0;
}
protected override void ClearItems()
{
base.ClearItems();
Reset();
}
protected override void InsertItem(int index, StringLine item)
{
base.InsertItem(index, item);
if (index == 0)
{
Reset();
}
}
protected override void SetItem(int index, StringLine item)
{
base.SetItem(index, item);
if (index == 0)
{
Reset();
}
}
protected override void RemoveItem(int index)
{
base.RemoveItem(index);
if (index == 0)
{
Reset();
}
}
public bool IsEndOfLines => CurrentChar == '\0';
2016-02-17 20:34:26 +09:00
public State Save()
{
return new State(currentLine, LinePosition, ColumnPosition, CurrentChar, PreviousChar1, PreviousChar2);
2016-02-17 20:34:26 +09:00
}
public void Restore(ref State state)
{
currentLine = state.CurrentLine;
LinePosition = state.LinePosition;
ColumnPosition = state.ColumnPosition;
CurrentChar = state.Current;
2016-02-18 00:34:26 +09:00
PreviousChar1 = state.PreviousChar1;
PreviousChar2 = state.PreviousChar2;
2016-02-17 20:34:26 +09:00
}
public char NextChar()
{
2016-02-18 00:34:26 +09:00
PreviousChar2 = PreviousChar1;
PreviousChar1 = CurrentChar;
2016-02-17 20:34:26 +09:00
if (currentLine != null)
{
ColumnPosition++;
if (ColumnPosition <= currentLine.End)
{
CurrentChar = currentLine[ColumnPosition];
2016-02-17 20:34:26 +09:00
}
else
{
LinePosition++;
2016-02-20 01:18:40 +09:00
if (LinePosition < Count)
{
currentLine = this[LinePosition];
}
else
{
currentLine = null;
LinePosition = Count;
}
ColumnPosition = -1;
if (currentLine != null)
{
ColumnPosition = currentLine.Start - 1;
}
CurrentChar = currentLine != null ? '\n' : '\0';
2016-02-17 20:34:26 +09:00
}
}
else
{
CurrentChar = '\0';
2016-02-17 20:34:26 +09:00
}
return CurrentChar;
2016-02-17 20:34:26 +09:00
}
public bool SkipWhiteSpaces()
{
bool hasWhitespaces = false;
while (CurrentChar.IsWhitespace())
{
NextChar();
hasWhitespaces = true;
}
return hasWhitespaces;
}
public bool SkipWhiteSpaces(out int newLineCount)
{
bool hasWhitespaces = false;
newLineCount = 0;
while (CurrentChar.IsWhitespace())
{
if (CurrentChar == '\n')
{
newLineCount++;
}
NextChar();
hasWhitespaces = true;
}
return hasWhitespaces;
}
2016-02-17 01:00:26 +09:00
public void TrimStart()
{
if (Count == 0)
{
return;
}
// Strip leading and
this[0].TrimStart();
Reset();
2016-02-17 01:00:26 +09:00
}
public void TrimEnd()
{
if (Count == 0)
{
return;
}
this[Count - 1].TrimEnd();
Reset();
2016-02-17 01:00:26 +09:00
}
public void Trim()
{
TrimStart();
TrimEnd();
}
2016-02-17 20:34:26 +09:00
public override string ToString()
{
var stringBuilder = new StringBuilder();
bool firstLine = true;
foreach (var line in this)
{
if (!firstLine)
{
stringBuilder.Append('\n');
}
stringBuilder.Append(line);
firstLine = false;
}
return stringBuilder.ToString();
}
2016-02-17 20:34:26 +09:00
public class State
{
2016-02-18 00:34:26 +09:00
public State(StringLine currentLine, int linePosition, int columnPosition, char current, char previousChar1, char previousChar2)
2016-02-17 20:34:26 +09:00
{
CurrentLine = currentLine;
LinePosition = linePosition;
ColumnPosition = columnPosition;
Current = current;
2016-02-18 00:34:26 +09:00
PreviousChar1 = previousChar1;
PreviousChar2 = previousChar2;
2016-02-17 20:34:26 +09:00
}
public readonly StringLine CurrentLine;
public readonly int LinePosition;
public readonly int ColumnPosition;
public readonly char Current;
2016-02-18 00:34:26 +09:00
public readonly char PreviousChar1;
public readonly char PreviousChar2;
2016-02-17 20:34:26 +09:00
}
2016-02-17 01:00:26 +09:00
}
}