System.Data.SqlClient.SqlStreamingXml.GetChars C# (CSharp) Method

GetChars() public method

public GetChars ( long dataIndex, char buffer, int bufferIndex, int length ) : long
dataIndex long
buffer char
bufferIndex int
length int
return long
        public long GetChars(long dataIndex, char[] buffer, int bufferIndex, int length)
        {
            if (_xmlReader == null)
            {
                SqlStream sqlStream = new SqlStream(_columnOrdinal, _reader, true /* addByteOrderMark */, false /* processAllRows*/, false /*advanceReader*/);
                _xmlReader = sqlStream.ToXmlReader();
                _strWriter = new StringWriter((System.IFormatProvider)null);
                XmlWriterSettings writerSettings = new XmlWriterSettings();
                writerSettings.CloseOutput = true;      // close the memory stream when done
                writerSettings.ConformanceLevel = ConformanceLevel.Fragment;
                _xmlWriter = XmlWriter.Create(_strWriter, writerSettings);
            }

            int charsToSkip = 0;
            int cnt = 0;
            if (dataIndex < _charsRemoved)
            {
                throw ADP.NonSeqByteAccess(dataIndex, _charsRemoved, nameof(GetChars));
            }
            else if (dataIndex > _charsRemoved)
            {
                charsToSkip = (int)(dataIndex - _charsRemoved);
            }

            // If buffer parameter is null, we have to return -1 since there is no way for us to know the
            // total size up front without reading and converting the XML.
            if (buffer == null)
            {
                return (long)(-1);
            }

            StringBuilder strBldr = _strWriter.GetStringBuilder();
            while (!_xmlReader.EOF)
            {
                if (strBldr.Length >= (length + charsToSkip))
                {
                    break;
                }
                // Can't call _xmlWriter.WriteNode here, since it reads all of the data in before returning the first char.
                // Do own implementation of WriteNode instead that reads just enough data to return the required number of chars
                //_xmlWriter.WriteNode(_xmlReader, true);
                //  _xmlWriter.Flush();
                WriteXmlElement();
                if (charsToSkip > 0)
                {
                    // Aggressively remove the characters we want to skip to avoid growing StringBuilder size too much
                    cnt = strBldr.Length < charsToSkip ? strBldr.Length : charsToSkip;
                    strBldr.Remove(0, cnt);
                    charsToSkip -= cnt;
                    _charsRemoved += (long)cnt;
                }
            }

            if (charsToSkip > 0)
            {
                cnt = strBldr.Length < charsToSkip ? strBldr.Length : charsToSkip;
                strBldr.Remove(0, cnt);
                charsToSkip -= cnt;
                _charsRemoved += (long)cnt;
            }

            if (strBldr.Length == 0)
            {
                return 0;
            }
            // At this point charsToSkip must be 0
            Debug.Assert(charsToSkip == 0);

            cnt = strBldr.Length < length ? strBldr.Length : length;
            for (int i = 0; i < cnt; i++)
            {
                buffer[bufferIndex + i] = strBldr[i];
            }
            // Remove the characters we have already returned
            strBldr.Remove(0, cnt);
            _charsRemoved += (long)cnt;
            return (long)cnt;
        }