2016-02-10 20:30:38 +09:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Runtime.CompilerServices;
|
2016-02-19 05:53:48 +09:00
|
|
|
|
using Textamina.Markdig.Helpers;
|
2016-02-17 01:05:13 +09:00
|
|
|
|
using Textamina.Markdig.Parsing;
|
2016-02-10 20:30:38 +09:00
|
|
|
|
|
2016-02-17 01:05:13 +09:00
|
|
|
|
namespace Textamina.Markdig.Syntax
|
2016-02-10 20:30:38 +09:00
|
|
|
|
{
|
2016-02-17 01:00:26 +09:00
|
|
|
|
public sealed class StringLine
|
2016-02-10 20:30:38 +09:00
|
|
|
|
{
|
2016-02-17 01:05:13 +09:00
|
|
|
|
public StringLine(string text)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (text == null) throw new ArgumentNullException(nameof(text));
|
|
|
|
|
|
Text = text;
|
|
|
|
|
|
Start = 0;
|
|
|
|
|
|
End = Text.Length - 1;
|
|
|
|
|
|
Column = 0;
|
|
|
|
|
|
SpaceHeaderCount = 0;
|
|
|
|
|
|
Current = End >= 0 ? Text[0] : (char)0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public string Text { get; private set; }
|
2016-02-10 20:30:38 +09:00
|
|
|
|
|
2016-02-17 01:05:13 +09:00
|
|
|
|
public int Start { get; set; }
|
2016-02-15 07:28:15 +09:00
|
|
|
|
|
2016-02-16 21:03:44 +09:00
|
|
|
|
public int End { get; set; }
|
2016-02-10 20:30:38 +09:00
|
|
|
|
|
2016-02-16 20:35:42 +09:00
|
|
|
|
public int SpaceHeaderCount { get; set; }
|
|
|
|
|
|
|
2016-02-15 20:58:12 +09:00
|
|
|
|
public int Column { get; private set; }
|
2016-02-10 20:30:38 +09:00
|
|
|
|
|
|
|
|
|
|
public char Current { get; private set; }
|
|
|
|
|
|
|
2016-02-17 01:05:13 +09:00
|
|
|
|
public bool IsEol => Start > End;
|
2016-02-10 20:30:38 +09:00
|
|
|
|
|
|
|
|
|
|
private bool isBlankLine;
|
|
|
|
|
|
|
2016-02-15 07:28:15 +09:00
|
|
|
|
public char this[int index] => Text[index];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public State Save()
|
|
|
|
|
|
{
|
2016-02-16 20:35:42 +09:00
|
|
|
|
return new State(Start, End, Column, SpaceHeaderCount, Current);
|
2016-02-15 07:28:15 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-16 22:42:40 +09:00
|
|
|
|
public void Restore(State state)
|
|
|
|
|
|
{
|
|
|
|
|
|
Restore(ref state);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-15 07:28:15 +09:00
|
|
|
|
public void Restore(ref State state)
|
|
|
|
|
|
{
|
|
|
|
|
|
Start = state.Start;
|
2016-02-16 20:35:42 +09:00
|
|
|
|
End = state.End;
|
|
|
|
|
|
Column = state.Column;
|
|
|
|
|
|
SpaceHeaderCount = state.SpaceHeaderCount;
|
2016-02-15 07:28:15 +09:00
|
|
|
|
Current = state.Current;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-10 20:30:38 +09:00
|
|
|
|
[MethodImpl(MethodImplOptionPortable.AggressiveInlining)]
|
|
|
|
|
|
public char NextChar()
|
|
|
|
|
|
{
|
2016-02-15 07:28:15 +09:00
|
|
|
|
Start++;
|
2016-02-15 20:58:12 +09:00
|
|
|
|
if (Start <= End)
|
2016-02-10 20:30:38 +09:00
|
|
|
|
{
|
2016-02-15 20:58:12 +09:00
|
|
|
|
// If previous character was a tab make the Column += 4
|
|
|
|
|
|
Column++;
|
2016-02-19 05:53:48 +09:00
|
|
|
|
if (CharHelper.IsTab(Current))
|
2016-02-10 20:30:38 +09:00
|
|
|
|
{
|
2016-02-15 20:58:12 +09:00
|
|
|
|
// Align the tab on a column
|
|
|
|
|
|
Column = ((Column + 3) / 4) * 4;
|
2016-02-10 20:30:38 +09:00
|
|
|
|
}
|
2016-02-15 07:28:15 +09:00
|
|
|
|
Current = Text[Start];
|
2016-02-10 20:30:38 +09:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2016-02-15 20:58:12 +09:00
|
|
|
|
Start = End + 1;
|
2016-02-10 20:30:38 +09:00
|
|
|
|
Current = (char) 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
return Current;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-16 22:42:40 +09:00
|
|
|
|
[MethodImpl(MethodImplOptionPortable.AggressiveInlining)]
|
|
|
|
|
|
public char PeekChar(int offset)
|
|
|
|
|
|
{
|
|
|
|
|
|
var index = Start + offset;
|
|
|
|
|
|
return index <= End ? Text[index] : (char) 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public bool Match(string text, int offset = 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
return Match(text, End, offset);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public bool Match(string text, int end, int offset)
|
|
|
|
|
|
{
|
2016-02-17 00:10:37 +09:00
|
|
|
|
var index = Start + offset;
|
2016-02-16 22:42:40 +09:00
|
|
|
|
int i = 0;
|
|
|
|
|
|
for (; index <= end && i < text.Length; i++, index++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (text[i] != Text[index])
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return i == text.Length;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-17 00:10:37 +09:00
|
|
|
|
public bool MatchLowercase(string text, int end, int offset)
|
|
|
|
|
|
{
|
|
|
|
|
|
var index = Start + offset;
|
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
for (; index <= end && i < text.Length; i++, index++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (text[i] != char.ToLowerInvariant(Text[index]))
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return i == text.Length;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-16 22:42:40 +09:00
|
|
|
|
public bool Search(string text, int offset = 0)
|
|
|
|
|
|
{
|
2016-02-17 00:10:37 +09:00
|
|
|
|
var end = End - text.Length + 1;
|
2016-02-16 22:42:40 +09:00
|
|
|
|
for (int i = Start; i <= end; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (Match(text, End, i))
|
|
|
|
|
|
{
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-17 00:10:37 +09:00
|
|
|
|
public bool SearchLowercase(string text, int offset = 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
var end = End - text.Length + 1;
|
|
|
|
|
|
for (int i = Start; i <= end; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (MatchLowercase(text, End, i))
|
|
|
|
|
|
{
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-10 20:30:38 +09:00
|
|
|
|
[MethodImpl(MethodImplOptionPortable.AggressiveInlining)]
|
|
|
|
|
|
public bool IsBlankLine()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (isBlankLine)
|
|
|
|
|
|
{
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-17 01:05:13 +09:00
|
|
|
|
for (int i = Start; i <= End; i++)
|
2016-02-10 20:30:38 +09:00
|
|
|
|
{
|
2016-02-19 05:53:48 +09:00
|
|
|
|
if (!CharHelper.IsSpace(Text[i]))
|
2016-02-10 20:30:38 +09:00
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
isBlankLine = true;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
2016-02-17 01:05:13 +09:00
|
|
|
|
|
2016-02-16 22:42:40 +09:00
|
|
|
|
public void SkipLeadingSpaces3()
|
2016-02-10 20:30:38 +09:00
|
|
|
|
{
|
2016-02-16 22:42:40 +09:00
|
|
|
|
for (int i = 0; i < 3; i++)
|
2016-02-10 20:30:38 +09:00
|
|
|
|
{
|
2016-02-19 05:53:48 +09:00
|
|
|
|
if (!CharHelper.IsSpace(Current))
|
2016-02-10 20:30:38 +09:00
|
|
|
|
{
|
2016-02-16 22:42:40 +09:00
|
|
|
|
break;
|
2016-02-10 20:30:38 +09:00
|
|
|
|
}
|
|
|
|
|
|
NextChar();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-17 01:20:42 +09:00
|
|
|
|
public StringSlice ToSlice()
|
|
|
|
|
|
{
|
|
|
|
|
|
return new StringSlice(Text, Start, End);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-18 22:32:45 +09:00
|
|
|
|
public void TrimStart()
|
|
|
|
|
|
{
|
|
|
|
|
|
// Strip leading spaces
|
|
|
|
|
|
var c = Current;
|
2016-02-19 05:53:48 +09:00
|
|
|
|
while (CharHelper.IsSpace(c))
|
2016-02-18 22:32:45 +09:00
|
|
|
|
{
|
|
|
|
|
|
c = NextChar();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void TrimEnd()
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int i = End; i >= Start; i--)
|
|
|
|
|
|
{
|
|
|
|
|
|
End = i;
|
2016-02-19 05:53:48 +09:00
|
|
|
|
if (!CharHelper.IsSpace(this[i]))
|
2016-02-18 22:32:45 +09:00
|
|
|
|
{
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Trim()
|
|
|
|
|
|
{
|
|
|
|
|
|
TrimStart();
|
|
|
|
|
|
TrimEnd();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-10 20:30:38 +09:00
|
|
|
|
public override string ToString()
|
|
|
|
|
|
{
|
2016-02-17 01:05:13 +09:00
|
|
|
|
return Start <= End ? Text.Substring(Start, End - Start + 1) : string.Empty;
|
2016-02-15 07:28:15 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public struct State
|
|
|
|
|
|
{
|
2016-02-16 20:35:42 +09:00
|
|
|
|
public State(int start, int end, int column, int spaceHeaderCount, char current)
|
2016-02-15 07:28:15 +09:00
|
|
|
|
{
|
|
|
|
|
|
Start = start;
|
2016-02-16 20:35:42 +09:00
|
|
|
|
End = end;
|
|
|
|
|
|
Column = column;
|
|
|
|
|
|
SpaceHeaderCount = spaceHeaderCount;
|
2016-02-15 07:28:15 +09:00
|
|
|
|
Current = current;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public readonly int Start;
|
|
|
|
|
|
|
2016-02-16 20:35:42 +09:00
|
|
|
|
public readonly int End;
|
|
|
|
|
|
|
|
|
|
|
|
public readonly int Column;
|
|
|
|
|
|
|
|
|
|
|
|
public readonly int SpaceHeaderCount;
|
2016-02-15 07:28:15 +09:00
|
|
|
|
|
|
|
|
|
|
public readonly char Current;
|
2016-02-10 20:30:38 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|