CssValueBuilder
The class that is responsible for book-keeping information
about the current CSS value that is been build.
using AngleSharp.DOM.Css;
using System.Collections.Generic;
using System.Diagnostics;
namespace AngleSharp.Parser.Css
{
[DebuggerStepThrough]
internal sealed class CssValueBuilder
{
private sealed class FunctionBuffer
{
private string _name;
private List<CSSValue> _arguments;
public int StartIndex { get; set; }
public List<CSSValue> Arguments => _arguments;
public FunctionBuffer(string name)
{
_arguments = new List<CSSValue>();
_name = name;
}
public CSSValue ToValue()
{
return CSSFunctions.Create(_name, _arguments);
}
}
private readonly Stack<FunctionBuffer> _functions;
private readonly List<CSSValue> _values;
private bool _error;
public bool IsFaulted {
get {
return _error;
}
set {
_error = value;
}
}
public CssValueBuilder()
{
_functions = new Stack<FunctionBuffer>();
_values = new List<CSSValue>();
Reset();
}
public void AddFunction(string name)
{
FunctionBuffer functionBuffer = new FunctionBuffer(name);
functionBuffer.StartIndex = _values.Count;
_functions.Push(functionBuffer);
}
public void AddValue(CSSValue value)
{
_values.Add(value);
}
public void CloseFunction()
{
NextArgument();
AddValue(_functions.Pop().ToValue());
}
public void InsertDelimiter()
{
_values.Add(CSSValue.Delimiter);
}
public void NextArgument()
{
if (_functions.Count > 0) {
FunctionBuffer functionBuffer = _functions.Peek();
CSSValue item = Create(functionBuffer.StartIndex);
_values.RemoveRange(functionBuffer.StartIndex, _values.Count - functionBuffer.StartIndex);
functionBuffer.Arguments.Add(item);
functionBuffer.StartIndex = _values.Count;
} else if (_values.Count == 0 || _values[_values.Count - 1] == CSSValue.Separator) {
IsFaulted = true;
} else {
_values.Add(CSSValue.Separator);
}
}
public void Reset()
{
_error = false;
_functions.Clear();
_values.Clear();
}
public CSSValue ToValue()
{
if (!_error) {
while (_functions.Count > 0) {
CloseFunction();
}
return Create(0);
}
return null;
}
private CSSValue Create(int start = 0)
{
return Create(start, _values.Count);
}
private CSSValue Create(int start, int end)
{
if (end - start != 1) {
CSSValueList cSSValueList = new CSSValueList();
for (int i = start; i < end; i++) {
cSSValueList.Add(_values[i]);
}
return cSSValueList;
}
return _values[start];
}
}
}