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, ADP.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; }
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); }