File: System\Xml\Xsl\Xslt\QilStrConcatenator.cs
Web Access
Project: src\src\libraries\System.Private.Xml\src\System.Private.Xml.csproj (System.Private.Xml)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Diagnostics;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Xsl.Qil;
using System.Xml.Xsl.XPath;
 
namespace System.Xml.Xsl.Xslt
{
    internal sealed class QilStrConcatenator
    {
        private readonly XPathQilFactory _f;
        private readonly StringBuilder _builder;
        private QilList? _concat;
        private bool _inUse;
 
        public QilStrConcatenator(XPathQilFactory f)
        {
            _f = f;
            _builder = new StringBuilder();
        }
 
        public void Reset()
        {
            Debug.Assert(!_inUse);
            _inUse = true;
            _builder.Length = 0;
            _concat = null;
        }
 
        private void FlushBuilder()
        {
            _concat ??= _f.BaseFactory.Sequence();
            if (_builder.Length != 0)
            {
                _concat.Add(_f.String(_builder.ToString()));
                _builder.Length = 0;
            }
        }
 
        public void Append(string value)
        {
            Debug.Assert(_inUse, "Reset() wasn't called");
            _builder.Append(value);
        }
 
        public void Append(char value)
        {
            Debug.Assert(_inUse, "Reset() wasn't called");
            _builder.Append(value);
        }
 
        public void Append(QilNode? value)
        {
            Debug.Assert(_inUse, "Reset() wasn't called");
            if (value != null)
            {
                Debug.Assert(value.XmlType!.TypeCode == XmlTypeCode.String);
                if (value.NodeType == QilNodeType.LiteralString)
                {
                    _builder.Append((string)(QilLiteral)value);
                }
                else
                {
                    FlushBuilder();
                    _concat!.Add(value);
                }
            }
        }
 
        public QilNode ToQil()
        {
            Debug.Assert(_inUse); // If we want allow multiple calls to ToQil() this logic should be changed
            _inUse = false;
            if (_concat == null)
            {
                return _f.String(_builder.ToString());
            }
            else
            {
                FlushBuilder();
                return _f.StrConcat(_concat);
            }
        }
    }
}