StylesheetReader.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. using System.Collections.Generic;
  2. using System.IO;
  3. using System.Text;
  4. using ExCSS.Model;
  5. #pragma warning disable
  6. namespace ExCSS
  7. {
  8. internal class StylesheetReader
  9. {
  10. private int _insertion;
  11. private readonly Stack<int> _collengths;
  12. private TextReader _reader;
  13. private readonly StringBuilder _buffer;
  14. private bool _lineWithReturn;
  15. StylesheetReader()
  16. {
  17. _buffer = new StringBuilder();
  18. _collengths = new Stack<int>();
  19. Column = 1;
  20. Line = 1;
  21. }
  22. internal StylesheetReader(string styleText) : this()
  23. {
  24. if (styleText == null)
  25. styleText = "";
  26. _reader = new StringReader(styleText);
  27. ReadCurrent();
  28. }
  29. internal StylesheetReader(Stream styleStream) : this()
  30. {
  31. _reader = new StreamReader(styleStream, true);
  32. ReadCurrent();
  33. }
  34. internal bool IsBeginning
  35. {
  36. get { return _insertion < 2; }
  37. }
  38. internal int Line { get; private set; }
  39. internal int Column { get; private set; }
  40. internal bool IsEnded { get; private set; }
  41. internal bool IsEnding
  42. {
  43. get { return Current == Specification.EndOfFile; }
  44. }
  45. internal char Current { get; private set; }
  46. internal char Next
  47. {
  48. get
  49. {
  50. Advance();
  51. return Current;
  52. }
  53. }
  54. internal char Previous
  55. {
  56. get
  57. {
  58. Back();
  59. return Current;
  60. }
  61. }
  62. internal void Advance()
  63. {
  64. if (!IsEnding)
  65. {
  66. AdvanceUnsafe();
  67. }
  68. else if (!IsEnded)
  69. {
  70. IsEnded = true;
  71. }
  72. }
  73. internal void Advance(int positions)
  74. {
  75. while (positions-- > 0 && !IsEnding)
  76. {
  77. AdvanceUnsafe();
  78. }
  79. }
  80. internal void Back()
  81. {
  82. IsEnded = false;
  83. if (!IsBeginning)
  84. {
  85. BackUnsafe();
  86. }
  87. }
  88. internal void Back(int positions)
  89. {
  90. IsEnded = false;
  91. while (positions-- > 0 && !IsBeginning)
  92. {
  93. BackUnsafe();
  94. }
  95. }
  96. private void ReadCurrent()
  97. {
  98. if (_insertion < _buffer.Length)
  99. {
  100. Current = _buffer[_insertion];
  101. _insertion++;
  102. return;
  103. }
  104. var nextPosition = _reader.Read();
  105. Current = nextPosition == -1 ? Specification.EndOfFile : (char)nextPosition;
  106. if (Current == Specification.CarriageReturn)
  107. {
  108. Current = Specification.LineFeed;
  109. _lineWithReturn = true;
  110. }
  111. else if (_lineWithReturn)
  112. {
  113. _lineWithReturn = false;
  114. if (Current == Specification.LineFeed)
  115. {
  116. ReadCurrent();
  117. return;
  118. }
  119. }
  120. _buffer.Append(Current);
  121. _insertion++;
  122. }
  123. private void AdvanceUnsafe()
  124. {
  125. if (Current.IsLineBreak())
  126. {
  127. _collengths.Push(Column);
  128. Column = 1;
  129. Line++;
  130. }
  131. else
  132. {
  133. Column++;
  134. }
  135. ReadCurrent();
  136. }
  137. private void BackUnsafe()
  138. {
  139. _insertion--;
  140. if (_insertion == 0)
  141. {
  142. Column = 0;
  143. Current = Specification.Null;
  144. return;
  145. }
  146. Current = _buffer[_insertion - 1];
  147. if (Current.IsLineBreak())
  148. {
  149. Column = _collengths.Count != 0 ? _collengths.Pop() : 1;
  150. Line--;
  151. }
  152. else
  153. {
  154. Column--;
  155. }
  156. }
  157. }
  158. }
  159. #pragma warning restore