namespace HaWeb.HTMLParser; using HaXMLReader.Interfaces; using HaXMLReader.EvArgs; using System.Text; using System.Collections.Generic; using System; public class LineXMLHelper { protected IReader _in; protected StringBuilder _target; protected List<(Func, bool>, Action>)>? _OTag_Funcs; protected List<(Func, bool>, Action>)>? _STag_Funcs; protected List<(Func, bool>, Action>)>? _CTag_Funcs; protected List<(Func, bool>, Action>)>? _Text_Funcs; protected List<(Func, bool>, Action>)>? _WS_Funcs; public T State; public Stack OpenTags; public Dictionary> LastSingleTags; public StringBuilder LastText; public string CurrentPage { get; private set; } public string CurrentLine { get; private set; } public List<(string Page, string Line, string Text)>? Lines { get; private set; } public (string Page, string Line)? CatchPageLine { get; private set; } private bool _newpage; private bool _firstline; private StringBuilder _currentText; public LineXMLHelper( T state, IReader input, StringBuilder target, List<(Func, bool>, Action>)>? OTag_Funcs = null, List<(Func, bool>, Action>)>? STag_Funcs = null, List<(Func, bool>, Action>)>? CTag_Funcs = null, List<(Func, bool>, Action>)>? Text_Funcs = null, List<(Func, bool>, Action>)>? WS_Funcs = null, string startPage = "-1", string startLine = "-1", // Set if only a specific line should be appended to the output (string Page, string Line)? CatchPageLine = null ) { if (input == null || target == null || state == null) throw new ArgumentNullException(); State = state; _in = input; _target = target; _OTag_Funcs = OTag_Funcs; _STag_Funcs = STag_Funcs; _CTag_Funcs = CTag_Funcs; _Text_Funcs = Text_Funcs; _WS_Funcs = WS_Funcs; OpenTags = new Stack(); LastSingleTags = new Dictionary>(); LastText = new StringBuilder(); CurrentPage = startPage; CurrentLine = startLine; _currentText = new StringBuilder(); input.SingleTag += _setPageLine; input.ReadingStop += _pushLine; _newpage = false; _firstline = true; _in.OpenTag += OnOTag; _in.SingleTag += OnSTag; _in.CloseTag += OnCTag; _in.Text += OnText; _in.Whitespace += OnWS; } private void _pushLine(object? _, EventArgs _empty) { if (Lines == null) Lines = new List<(string Page, string Line, string Text)>(); Lines.Add((CurrentPage, CurrentLine, _currentText.ToString())); _currentText.Clear(); } private void _setPageLine(object? _, Tag tag) { if (tag.Name == "page" && !String.IsNullOrWhiteSpace(tag["index"])) { _pushLine(_, EventArgs.Empty); CurrentPage = tag["index"]; _newpage = true; } if (tag.Name == "line" && !String.IsNullOrWhiteSpace(tag["index"])) { if (!_newpage && !_firstline) { _pushLine(_, EventArgs.Empty); } _firstline = false; _newpage = false; CurrentLine = tag["index"]; } } protected virtual void OnText(object? _, Text text) { LastText.Append(text.Value); _currentText.Append(text.Value); if (_Text_Funcs != null) foreach (var entry in _Text_Funcs) if (entry.Item1(text, this)) entry.Item2(_target, text, this); } protected virtual void OnWS(object? _, Whitespace ws) { LastText.Append(ws.Value); _currentText.Append(ws.Value); if (_WS_Funcs != null) foreach (var entry in _WS_Funcs) if (entry.Item1(ws, this)) entry.Item2(_target, ws, this); } protected virtual void OnOTag(object? _, Tag tag) { OpenTags.Push(tag); if (_OTag_Funcs != null) foreach (var entry in _OTag_Funcs) if (entry.Item1(tag, this)) entry.Item2(_target, tag, this); } protected virtual void OnSTag(object? _, Tag tag) { if (!LastSingleTags.ContainsKey(tag.Name)) LastSingleTags.Add(tag.Name, new List()); LastSingleTags[tag.Name].Add(tag); if (_STag_Funcs != null) foreach (var entry in _STag_Funcs) if (entry.Item1(tag, this)) entry.Item2(_target, tag, this); } protected virtual void OnCTag(object? _, Tag tag) { OpenTags.Pop(); if (_CTag_Funcs != null) foreach (var entry in _CTag_Funcs) if (entry.Item1(tag, this)) entry.Item2(_target, tag, this); } internal void Dispose() { OpenTags.Clear(); LastSingleTags.Clear(); LastText.Clear(); if (_in != null) { if (_OTag_Funcs != null) _in.OpenTag -= OnOTag; if (_STag_Funcs != null) _in.SingleTag -= OnSTag; if (_CTag_Funcs != null) _in.CloseTag -= OnCTag; if (_Text_Funcs != null) _in.Text -= OnText; if (_WS_Funcs != null) _in.Whitespace -= OnWS; } } ~LineXMLHelper() { Dispose(); } }