Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / Data / System / Data / SqlClient / SqlStream.cs / 1 / SqlStream.cs
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// [....]
// [....]
//-----------------------------------------------------------------------------
namespace System.Data.SqlClient {
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Xml;
using System.Reflection;
sealed internal class SqlStream : Stream {
private SqlDataReader _reader; // reader we will stream off
private int _columnOrdinal;
private long _bytesCol;
int _bom;
private byte[] _bufferedData;
private bool _processAllRows;
private bool _advanceReader;
private bool _readFirstRow = false;
private bool _endOfColumn = false;
internal SqlStream(SqlDataReader reader, bool addByteOrderMark, bool processAllRows) :
this(0, reader, addByteOrderMark, processAllRows, true) {
}
internal SqlStream(int columnOrdinal, SqlDataReader reader, bool addByteOrderMark , bool processAllRows, bool advanceReader) {
_columnOrdinal = columnOrdinal;
_reader = reader;
_bom = addByteOrderMark ? 0xfeff : 0;
_processAllRows = processAllRows;
_advanceReader = advanceReader;
}
override public bool CanRead {
get {
return true;
}
}
override public bool CanSeek {
get {
return false;
}
}
override public bool CanWrite {
get {
return false;
}
}
override public long Length {
get {
throw ADP.NotSupported();
}
}
override public long Position {
get {
throw ADP.NotSupported();
}
set {
throw ADP.NotSupported();
}
}
override protected void Dispose(bool disposing) {
try {
if (disposing && _advanceReader && _reader != null && !_reader.IsClosed) {
_reader.Close();
}
_reader = null;
}
finally {
base.Dispose(disposing);
}
}
override public void Flush() {
throw ADP.NotSupported();
}
override public int Read(byte[] buffer, int offset, int count) {
int intCount = 0;
int cBufferedData = 0;
if ((null == _reader)) {
throw ADP.StreamClosed(ADP.Read);
}
if (null == buffer) {
throw ADP.ArgumentNull(ADP.ParameterBuffer);
}
if ((offset < 0) || (count < 0)) {
throw ADP.ArgumentOutOfRange(String.Empty, (offset < 0 ? ADP.ParameterOffset : ADP.ParameterCount));
}
if (buffer.Length - offset < count) {
throw ADP.ArgumentOutOfRange(ADP.ParameterCount);
}
// Need to find out if we should add byte order mark or not.
// We need to add this if we are getting ntext xml, not if we are getting binary xml
// Binary Xml always begins with the bytes 0xDF and 0xFF
// If we aren't getting these, then we are getting unicode xml
if (_bom > 0 ) {
// Read and buffer the first two bytes
_bufferedData = new byte[2];
cBufferedData = ReadBytes(_bufferedData, 0, 2);
// Check to se if we should add the byte order mark
if ((cBufferedData < 2) || ((_bufferedData[0] == 0xDF) && (_bufferedData[1] == 0xFF))){
_bom = 0;
}
while (count > 0) {
if (_bom > 0) {
buffer[offset] = (byte)_bom;
_bom >>= 8;
offset++;
count--;
intCount++;
}
else {
break;
}
}
}
if (cBufferedData > 0) {
while (count > 0) {
buffer[offset++] = _bufferedData[0];
intCount++;
count--;
if ((cBufferedData > 1) && (count > 0)) {
buffer[offset++] = _bufferedData[1];
intCount++;
count--;
break;
}
}
_bufferedData = null;
}
intCount += ReadBytes(buffer, offset, count);
return intCount;
}
private int ReadBytes(byte[] buffer, int offset, int count) {
bool gotData = true;
int intCount = 0;
int cb = 0;
if (_reader.IsClosed || _endOfColumn) {
return 0;
}
try {
while (count > 0) {
// if I haven't read any bytes, get the next row
if (_advanceReader && (0 == _bytesCol)) {
gotData = false;
do {
if (_readFirstRow && !_processAllRows) {
_reader.Close();
break;
}
if (_reader.Read()) {
_readFirstRow = true;
gotData = true;
break;
}
} while (_reader.NextResult());
}
if (gotData) {
cb = (int) _reader.GetBytesInternal(_columnOrdinal, _bytesCol, buffer, offset, count);
if (cb < count) {
_bytesCol = 0;
gotData = false;
if (!_advanceReader) {
_endOfColumn = true;
}
}
else {
_bytesCol += cb;
}
// we are guaranteed that cb is < Int32.Max since we always pass in count which is of type Int32 to
// our getbytes interface
count -= (int)cb;
offset += (int)cb;
intCount += (int)cb;
}
else {
break; // no more data available, we are done
}
}
if (!gotData && _advanceReader) {
_reader.Close(); // Need to close the reader if we are done reading
}
}
catch (Exception e) {
if (_advanceReader && ADP.IsCatchableExceptionType(e)) {
_reader.Close();
}
throw;
}
return intCount;
}
internal XmlReader ToXmlReader() {
XmlReaderSettings readerSettings = new XmlReaderSettings();
readerSettings.ConformanceLevel = ConformanceLevel.Fragment;
readerSettings.CloseInput = true;
// Call internal XmlReader.CreateSqlReader from System.Xml.
// Signature: internal static XmlReader CreateSqlReader(Stream input, XmlReaderSettings settings, XmlParserContext inputContext);
MethodInfo createSqlReaderMethodInfo = typeof(System.Xml.XmlReader).GetMethod("CreateSqlReader", BindingFlags.Static | BindingFlags.NonPublic);
object[] args = new object[3] { (Stream)this, readerSettings, null };
XmlReader xr;
new System.Security.Permissions.ReflectionPermission(System.Security.Permissions.ReflectionPermissionFlag.MemberAccess).Assert();
try {
xr = (XmlReader)createSqlReaderMethodInfo.Invoke(null, args);
}
finally {
System.Security.Permissions.ReflectionPermission.RevertAssert();
}
return xr;
}
override public long Seek(long offset, SeekOrigin origin) {
throw ADP.NotSupported();
}
override public void SetLength(long value) {
throw ADP.NotSupported();
}
override public void Write(byte[] buffer, int offset, int count) {
throw ADP.NotSupported();
}
}
// XmlTextReader does not read all the bytes off the network buffers, so we have to cache it here in the random access
// case. This causes double buffering and is a perf hit, but this is not the high perf way for accessing this type of data.
// In the case of sequential access, we do not have to do any buffering since the XmlTextReader we return can become
// invalid as soon as we move off the current column.
sealed internal class SqlCachedStream : Stream {
int _currentPosition; // Position within the current array byte
int _currentArrayIndex; // Index into the _cachedBytes ArrayList
ArrayList _cachedBytes;
long _totalLength;
// Reads off from the network buffer and caches bytes. Only reads one column value in the current row.
internal SqlCachedStream(SqlCachedBuffer sqlBuf ) {
_cachedBytes = sqlBuf.CachedBytes;
}
override public bool CanRead {
get {
return true;
}
}
override public bool CanSeek {
get {
return true;
}
}
override public bool CanWrite {
get {
return false;
}
}
override public long Length {
get {
return TotalLength;
}
}
override public long Position {
get {
long pos = 0;
byte[] bytArr = null;
if (_currentArrayIndex > 0) {
for (int ii = 0 ; ii < _currentArrayIndex ; ii++) {
bytArr = (byte[])(_cachedBytes[ii]);
pos += bytArr.Length;
}
}
pos+= _currentPosition;
return pos;
}
set {
if (null == _cachedBytes) {
throw ADP.StreamClosed(ADP.ParameterSetPosition);
}
SetInternalPosition(value, ADP.ParameterSetPosition);
}
}
override protected void Dispose(bool disposing) {
try {
if (disposing && _cachedBytes != null)
_cachedBytes.Clear();
_cachedBytes = null;
_currentPosition = 0;
_currentArrayIndex = 0;
_totalLength = 0;
}
finally {
base.Dispose(disposing);
}
}
override public void Flush() {
throw ADP.NotSupported();
}
override public int Read(byte[] buffer, int offset, int count) {
int cb;
int intCount = 0;
byte[] curBytes = null;
if (null == _cachedBytes) {
throw ADP.StreamClosed(ADP.Read);
}
if (null == buffer) {
throw ADP.ArgumentNull(ADP.ParameterBuffer);
}
if ((offset < 0) || (count < 0)) {
throw ADP.ArgumentOutOfRange(String.Empty, (offset < 0 ? ADP.ParameterOffset : ADP.ParameterCount));
}
if (buffer.Length - offset < count) {
throw ADP.ArgumentOutOfRange(ADP.ParameterCount);
}
if (_cachedBytes.Count > _currentArrayIndex) {
curBytes = (byte [])(_cachedBytes[_currentArrayIndex]);
}
else {
return 0; // Everything is read!
}
while (count > 0) {
if (curBytes.Length <= _currentPosition) {
_currentArrayIndex++; // We are done reading this chunk, go to next
if (_cachedBytes.Count > _currentArrayIndex) {
curBytes = (byte [])(_cachedBytes[_currentArrayIndex]);
_currentPosition = 0;
}
else {
break;
}
}
cb = curBytes.Length - _currentPosition;
if (cb > count)
cb = count;
Array.Copy(curBytes, _currentPosition, buffer, offset, cb);
_currentPosition += cb;
count -= (int)cb;
offset += (int)cb;
intCount += (int)cb;
}
return intCount;
}
override public long Seek(long offset, SeekOrigin origin) {
long pos = 0;
if (null == _cachedBytes) {
throw ADP.StreamClosed(ADP.Read);
}
switch(origin) {
case SeekOrigin.Begin:
SetInternalPosition(offset, ADP.ParameterOffset);
break;
case SeekOrigin.Current:
pos = offset + Position;
SetInternalPosition(pos, ADP.ParameterOffset);
break;
case SeekOrigin.End:
pos = TotalLength + offset;
SetInternalPosition(pos, ADP.ParameterOffset);
break;
default:
throw ADP.InvalidSeekOrigin(ADP.ParameterOffset);
}
return pos;
}
override public void SetLength(long value) {
throw ADP.NotSupported();
}
override public void Write(byte[] buffer, int offset, int count) {
throw ADP.NotSupported();
}
private void SetInternalPosition(long lPos, string argumentName) {
long pos = lPos;
byte[] bytArr = null;
if (pos < 0) {
throw new ArgumentOutOfRangeException(argumentName);
}
for (int ii = 0 ; ii < _cachedBytes.Count ; ii++) {
bytArr = (byte[])(_cachedBytes[ii]);
if (pos > bytArr.Length) {
pos -= bytArr.Length;
}
else {
_currentArrayIndex = ii;
_currentPosition = (int)pos;
return;
}
}
if (pos > 0)
throw new ArgumentOutOfRangeException(argumentName);
}
private long TotalLength {
get {
if ((_totalLength == 0) && (_cachedBytes != null)) {
long pos = 0;
byte[] bytArr = null;
for (int ii = 0 ; ii < _cachedBytes.Count ; ii++) {
bytArr = (byte[])( _cachedBytes[ii]);
pos += bytArr.Length;
}
_totalLength = pos;
}
return _totalLength;
}
}
}
sealed internal class SqlStreamingXml {
int _columnOrdinal;
SqlDataReader _reader;
XmlReader _xmlReader;
XmlWriter _xmlWriter;
StringWriter _strWriter;
long _charsRemoved;
public SqlStreamingXml(int i, SqlDataReader reader) {
_columnOrdinal = i;
_reader = reader;
}
public void Close() {
((IDisposable)_xmlWriter).Dispose();
((IDisposable)_xmlReader).Dispose();
_reader = null;
_xmlReader = null;
_xmlWriter = null;
_strWriter = null;
}
public int ColumnOrdinal {
get {
return _columnOrdinal;
}
}
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;
}
// This method duplicates the work of XmlWriter.WriteNode except that it reads one element at a time
// instead of reading the entire node like XmlWriter.
private void WriteXmlElement() {
if (_xmlReader.EOF)
return;
bool canReadChunk = _xmlReader.CanReadValueChunk;
char[] writeNodeBuffer = null;
// Constants
const int WriteNodeBufferSize = 1024;
_xmlReader.Read();
switch (_xmlReader.NodeType) {
case XmlNodeType.Element:
_xmlWriter.WriteStartElement(_xmlReader.Prefix, _xmlReader.LocalName, _xmlReader.NamespaceURI);
_xmlWriter.WriteAttributes(_xmlReader, true);
if (_xmlReader.IsEmptyElement) {
_xmlWriter.WriteEndElement();
break;
}
break;
case XmlNodeType.Text:
if (canReadChunk) {
if (writeNodeBuffer == null) {
writeNodeBuffer = new char[WriteNodeBufferSize];
}
int read;
while ((read = _xmlReader.ReadValueChunk(writeNodeBuffer, 0, WriteNodeBufferSize)) > 0) {
_xmlWriter.WriteChars(writeNodeBuffer, 0, read);
}
}
else {
_xmlWriter.WriteString(_xmlReader.Value);
}
break;
case XmlNodeType.Whitespace:
case XmlNodeType.SignificantWhitespace:
_xmlWriter.WriteWhitespace(_xmlReader.Value);
break;
case XmlNodeType.CDATA:
_xmlWriter.WriteCData(_xmlReader.Value);
break;
case XmlNodeType.EntityReference:
_xmlWriter.WriteEntityRef(_xmlReader.Name);
break;
case XmlNodeType.XmlDeclaration:
case XmlNodeType.ProcessingInstruction:
_xmlWriter.WriteProcessingInstruction(_xmlReader.Name, _xmlReader.Value);
break;
case XmlNodeType.DocumentType:
_xmlWriter.WriteDocType(_xmlReader.Name, _xmlReader.GetAttribute("PUBLIC"), _xmlReader.GetAttribute("SYSTEM"), _xmlReader.Value);
break;
case XmlNodeType.Comment:
_xmlWriter.WriteComment(_xmlReader.Value);
break;
case XmlNodeType.EndElement:
_xmlWriter.WriteFullEndElement();
break;
}
_xmlWriter.Flush();
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// [....]
// [....]
//-----------------------------------------------------------------------------
namespace System.Data.SqlClient {
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Xml;
using System.Reflection;
sealed internal class SqlStream : Stream {
private SqlDataReader _reader; // reader we will stream off
private int _columnOrdinal;
private long _bytesCol;
int _bom;
private byte[] _bufferedData;
private bool _processAllRows;
private bool _advanceReader;
private bool _readFirstRow = false;
private bool _endOfColumn = false;
internal SqlStream(SqlDataReader reader, bool addByteOrderMark, bool processAllRows) :
this(0, reader, addByteOrderMark, processAllRows, true) {
}
internal SqlStream(int columnOrdinal, SqlDataReader reader, bool addByteOrderMark , bool processAllRows, bool advanceReader) {
_columnOrdinal = columnOrdinal;
_reader = reader;
_bom = addByteOrderMark ? 0xfeff : 0;
_processAllRows = processAllRows;
_advanceReader = advanceReader;
}
override public bool CanRead {
get {
return true;
}
}
override public bool CanSeek {
get {
return false;
}
}
override public bool CanWrite {
get {
return false;
}
}
override public long Length {
get {
throw ADP.NotSupported();
}
}
override public long Position {
get {
throw ADP.NotSupported();
}
set {
throw ADP.NotSupported();
}
}
override protected void Dispose(bool disposing) {
try {
if (disposing && _advanceReader && _reader != null && !_reader.IsClosed) {
_reader.Close();
}
_reader = null;
}
finally {
base.Dispose(disposing);
}
}
override public void Flush() {
throw ADP.NotSupported();
}
override public int Read(byte[] buffer, int offset, int count) {
int intCount = 0;
int cBufferedData = 0;
if ((null == _reader)) {
throw ADP.StreamClosed(ADP.Read);
}
if (null == buffer) {
throw ADP.ArgumentNull(ADP.ParameterBuffer);
}
if ((offset < 0) || (count < 0)) {
throw ADP.ArgumentOutOfRange(String.Empty, (offset < 0 ? ADP.ParameterOffset : ADP.ParameterCount));
}
if (buffer.Length - offset < count) {
throw ADP.ArgumentOutOfRange(ADP.ParameterCount);
}
// Need to find out if we should add byte order mark or not.
// We need to add this if we are getting ntext xml, not if we are getting binary xml
// Binary Xml always begins with the bytes 0xDF and 0xFF
// If we aren't getting these, then we are getting unicode xml
if (_bom > 0 ) {
// Read and buffer the first two bytes
_bufferedData = new byte[2];
cBufferedData = ReadBytes(_bufferedData, 0, 2);
// Check to se if we should add the byte order mark
if ((cBufferedData < 2) || ((_bufferedData[0] == 0xDF) && (_bufferedData[1] == 0xFF))){
_bom = 0;
}
while (count > 0) {
if (_bom > 0) {
buffer[offset] = (byte)_bom;
_bom >>= 8;
offset++;
count--;
intCount++;
}
else {
break;
}
}
}
if (cBufferedData > 0) {
while (count > 0) {
buffer[offset++] = _bufferedData[0];
intCount++;
count--;
if ((cBufferedData > 1) && (count > 0)) {
buffer[offset++] = _bufferedData[1];
intCount++;
count--;
break;
}
}
_bufferedData = null;
}
intCount += ReadBytes(buffer, offset, count);
return intCount;
}
private int ReadBytes(byte[] buffer, int offset, int count) {
bool gotData = true;
int intCount = 0;
int cb = 0;
if (_reader.IsClosed || _endOfColumn) {
return 0;
}
try {
while (count > 0) {
// if I haven't read any bytes, get the next row
if (_advanceReader && (0 == _bytesCol)) {
gotData = false;
do {
if (_readFirstRow && !_processAllRows) {
_reader.Close();
break;
}
if (_reader.Read()) {
_readFirstRow = true;
gotData = true;
break;
}
} while (_reader.NextResult());
}
if (gotData) {
cb = (int) _reader.GetBytesInternal(_columnOrdinal, _bytesCol, buffer, offset, count);
if (cb < count) {
_bytesCol = 0;
gotData = false;
if (!_advanceReader) {
_endOfColumn = true;
}
}
else {
_bytesCol += cb;
}
// we are guaranteed that cb is < Int32.Max since we always pass in count which is of type Int32 to
// our getbytes interface
count -= (int)cb;
offset += (int)cb;
intCount += (int)cb;
}
else {
break; // no more data available, we are done
}
}
if (!gotData && _advanceReader) {
_reader.Close(); // Need to close the reader if we are done reading
}
}
catch (Exception e) {
if (_advanceReader && ADP.IsCatchableExceptionType(e)) {
_reader.Close();
}
throw;
}
return intCount;
}
internal XmlReader ToXmlReader() {
XmlReaderSettings readerSettings = new XmlReaderSettings();
readerSettings.ConformanceLevel = ConformanceLevel.Fragment;
readerSettings.CloseInput = true;
// Call internal XmlReader.CreateSqlReader from System.Xml.
// Signature: internal static XmlReader CreateSqlReader(Stream input, XmlReaderSettings settings, XmlParserContext inputContext);
MethodInfo createSqlReaderMethodInfo = typeof(System.Xml.XmlReader).GetMethod("CreateSqlReader", BindingFlags.Static | BindingFlags.NonPublic);
object[] args = new object[3] { (Stream)this, readerSettings, null };
XmlReader xr;
new System.Security.Permissions.ReflectionPermission(System.Security.Permissions.ReflectionPermissionFlag.MemberAccess).Assert();
try {
xr = (XmlReader)createSqlReaderMethodInfo.Invoke(null, args);
}
finally {
System.Security.Permissions.ReflectionPermission.RevertAssert();
}
return xr;
}
override public long Seek(long offset, SeekOrigin origin) {
throw ADP.NotSupported();
}
override public void SetLength(long value) {
throw ADP.NotSupported();
}
override public void Write(byte[] buffer, int offset, int count) {
throw ADP.NotSupported();
}
}
// XmlTextReader does not read all the bytes off the network buffers, so we have to cache it here in the random access
// case. This causes double buffering and is a perf hit, but this is not the high perf way for accessing this type of data.
// In the case of sequential access, we do not have to do any buffering since the XmlTextReader we return can become
// invalid as soon as we move off the current column.
sealed internal class SqlCachedStream : Stream {
int _currentPosition; // Position within the current array byte
int _currentArrayIndex; // Index into the _cachedBytes ArrayList
ArrayList _cachedBytes;
long _totalLength;
// Reads off from the network buffer and caches bytes. Only reads one column value in the current row.
internal SqlCachedStream(SqlCachedBuffer sqlBuf ) {
_cachedBytes = sqlBuf.CachedBytes;
}
override public bool CanRead {
get {
return true;
}
}
override public bool CanSeek {
get {
return true;
}
}
override public bool CanWrite {
get {
return false;
}
}
override public long Length {
get {
return TotalLength;
}
}
override public long Position {
get {
long pos = 0;
byte[] bytArr = null;
if (_currentArrayIndex > 0) {
for (int ii = 0 ; ii < _currentArrayIndex ; ii++) {
bytArr = (byte[])(_cachedBytes[ii]);
pos += bytArr.Length;
}
}
pos+= _currentPosition;
return pos;
}
set {
if (null == _cachedBytes) {
throw ADP.StreamClosed(ADP.ParameterSetPosition);
}
SetInternalPosition(value, ADP.ParameterSetPosition);
}
}
override protected void Dispose(bool disposing) {
try {
if (disposing && _cachedBytes != null)
_cachedBytes.Clear();
_cachedBytes = null;
_currentPosition = 0;
_currentArrayIndex = 0;
_totalLength = 0;
}
finally {
base.Dispose(disposing);
}
}
override public void Flush() {
throw ADP.NotSupported();
}
override public int Read(byte[] buffer, int offset, int count) {
int cb;
int intCount = 0;
byte[] curBytes = null;
if (null == _cachedBytes) {
throw ADP.StreamClosed(ADP.Read);
}
if (null == buffer) {
throw ADP.ArgumentNull(ADP.ParameterBuffer);
}
if ((offset < 0) || (count < 0)) {
throw ADP.ArgumentOutOfRange(String.Empty, (offset < 0 ? ADP.ParameterOffset : ADP.ParameterCount));
}
if (buffer.Length - offset < count) {
throw ADP.ArgumentOutOfRange(ADP.ParameterCount);
}
if (_cachedBytes.Count > _currentArrayIndex) {
curBytes = (byte [])(_cachedBytes[_currentArrayIndex]);
}
else {
return 0; // Everything is read!
}
while (count > 0) {
if (curBytes.Length <= _currentPosition) {
_currentArrayIndex++; // We are done reading this chunk, go to next
if (_cachedBytes.Count > _currentArrayIndex) {
curBytes = (byte [])(_cachedBytes[_currentArrayIndex]);
_currentPosition = 0;
}
else {
break;
}
}
cb = curBytes.Length - _currentPosition;
if (cb > count)
cb = count;
Array.Copy(curBytes, _currentPosition, buffer, offset, cb);
_currentPosition += cb;
count -= (int)cb;
offset += (int)cb;
intCount += (int)cb;
}
return intCount;
}
override public long Seek(long offset, SeekOrigin origin) {
long pos = 0;
if (null == _cachedBytes) {
throw ADP.StreamClosed(ADP.Read);
}
switch(origin) {
case SeekOrigin.Begin:
SetInternalPosition(offset, ADP.ParameterOffset);
break;
case SeekOrigin.Current:
pos = offset + Position;
SetInternalPosition(pos, ADP.ParameterOffset);
break;
case SeekOrigin.End:
pos = TotalLength + offset;
SetInternalPosition(pos, ADP.ParameterOffset);
break;
default:
throw ADP.InvalidSeekOrigin(ADP.ParameterOffset);
}
return pos;
}
override public void SetLength(long value) {
throw ADP.NotSupported();
}
override public void Write(byte[] buffer, int offset, int count) {
throw ADP.NotSupported();
}
private void SetInternalPosition(long lPos, string argumentName) {
long pos = lPos;
byte[] bytArr = null;
if (pos < 0) {
throw new ArgumentOutOfRangeException(argumentName);
}
for (int ii = 0 ; ii < _cachedBytes.Count ; ii++) {
bytArr = (byte[])(_cachedBytes[ii]);
if (pos > bytArr.Length) {
pos -= bytArr.Length;
}
else {
_currentArrayIndex = ii;
_currentPosition = (int)pos;
return;
}
}
if (pos > 0)
throw new ArgumentOutOfRangeException(argumentName);
}
private long TotalLength {
get {
if ((_totalLength == 0) && (_cachedBytes != null)) {
long pos = 0;
byte[] bytArr = null;
for (int ii = 0 ; ii < _cachedBytes.Count ; ii++) {
bytArr = (byte[])( _cachedBytes[ii]);
pos += bytArr.Length;
}
_totalLength = pos;
}
return _totalLength;
}
}
}
sealed internal class SqlStreamingXml {
int _columnOrdinal;
SqlDataReader _reader;
XmlReader _xmlReader;
XmlWriter _xmlWriter;
StringWriter _strWriter;
long _charsRemoved;
public SqlStreamingXml(int i, SqlDataReader reader) {
_columnOrdinal = i;
_reader = reader;
}
public void Close() {
((IDisposable)_xmlWriter).Dispose();
((IDisposable)_xmlReader).Dispose();
_reader = null;
_xmlReader = null;
_xmlWriter = null;
_strWriter = null;
}
public int ColumnOrdinal {
get {
return _columnOrdinal;
}
}
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;
}
// This method duplicates the work of XmlWriter.WriteNode except that it reads one element at a time
// instead of reading the entire node like XmlWriter.
private void WriteXmlElement() {
if (_xmlReader.EOF)
return;
bool canReadChunk = _xmlReader.CanReadValueChunk;
char[] writeNodeBuffer = null;
// Constants
const int WriteNodeBufferSize = 1024;
_xmlReader.Read();
switch (_xmlReader.NodeType) {
case XmlNodeType.Element:
_xmlWriter.WriteStartElement(_xmlReader.Prefix, _xmlReader.LocalName, _xmlReader.NamespaceURI);
_xmlWriter.WriteAttributes(_xmlReader, true);
if (_xmlReader.IsEmptyElement) {
_xmlWriter.WriteEndElement();
break;
}
break;
case XmlNodeType.Text:
if (canReadChunk) {
if (writeNodeBuffer == null) {
writeNodeBuffer = new char[WriteNodeBufferSize];
}
int read;
while ((read = _xmlReader.ReadValueChunk(writeNodeBuffer, 0, WriteNodeBufferSize)) > 0) {
_xmlWriter.WriteChars(writeNodeBuffer, 0, read);
}
}
else {
_xmlWriter.WriteString(_xmlReader.Value);
}
break;
case XmlNodeType.Whitespace:
case XmlNodeType.SignificantWhitespace:
_xmlWriter.WriteWhitespace(_xmlReader.Value);
break;
case XmlNodeType.CDATA:
_xmlWriter.WriteCData(_xmlReader.Value);
break;
case XmlNodeType.EntityReference:
_xmlWriter.WriteEntityRef(_xmlReader.Name);
break;
case XmlNodeType.XmlDeclaration:
case XmlNodeType.ProcessingInstruction:
_xmlWriter.WriteProcessingInstruction(_xmlReader.Name, _xmlReader.Value);
break;
case XmlNodeType.DocumentType:
_xmlWriter.WriteDocType(_xmlReader.Name, _xmlReader.GetAttribute("PUBLIC"), _xmlReader.GetAttribute("SYSTEM"), _xmlReader.Value);
break;
case XmlNodeType.Comment:
_xmlWriter.WriteComment(_xmlReader.Value);
break;
case XmlNodeType.EndElement:
_xmlWriter.WriteFullEndElement();
break;
}
_xmlWriter.Flush();
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- Volatile.cs
- FixedSOMLineRanges.cs
- RoleGroupCollection.cs
- ObjectItemAssemblyLoader.cs
- CodeEventReferenceExpression.cs
- SetStoryboardSpeedRatio.cs
- BatchWriter.cs
- ZoomPercentageConverter.cs
- LinearGradientBrush.cs
- ButtonColumn.cs
- DataBindingHandlerAttribute.cs
- CDSsyncETWBCLProvider.cs
- SingleResultAttribute.cs
- PreviousTrackingServiceAttribute.cs
- WorkflowControlClient.cs
- ScriptResourceHandler.cs
- WmlObjectListAdapter.cs
- BufferAllocator.cs
- DynamicActivityXamlReader.cs
- COSERVERINFO.cs
- ObjectRef.cs
- WindowsImpersonationContext.cs
- ImageAttributes.cs
- SimpleMailWebEventProvider.cs
- HwndHost.cs
- NonVisualControlAttribute.cs
- DockPattern.cs
- CachedFontFamily.cs
- _ShellExpression.cs
- HtmlUtf8RawTextWriter.cs
- XamlReaderConstants.cs
- _OverlappedAsyncResult.cs
- StateManager.cs
- DynamicQueryableWrapper.cs
- StringSorter.cs
- ComponentManagerBroker.cs
- DefaultPropertyAttribute.cs
- SurrogateSelector.cs
- PointCollection.cs
- EventHandlersStore.cs
- SchemaType.cs
- DetailsViewPagerRow.cs
- DataService.cs
- FirstMatchCodeGroup.cs
- TaskHelper.cs
- FormViewPagerRow.cs
- ImageMapEventArgs.cs
- ControlPropertyNameConverter.cs
- RequestCache.cs
- DataGridViewSortCompareEventArgs.cs
- ChildDocumentBlock.cs
- CodeAccessPermission.cs
- NamedObject.cs
- Page.cs
- ComNativeDescriptor.cs
- ViewManager.cs
- NamespaceList.cs
- RSATokenProvider.cs
- HwndPanningFeedback.cs
- HTMLTagNameToTypeMapper.cs
- ServiceOperationParameter.cs
- ExceptionHandlersDesigner.cs
- StaticContext.cs
- ApplicationId.cs
- PasswordBoxAutomationPeer.cs
- BoolLiteral.cs
- WebAdminConfigurationHelper.cs
- Application.cs
- BidPrivateBase.cs
- DataSourceCacheDurationConverter.cs
- ScrollChrome.cs
- SimpleTextLine.cs
- ListViewDataItem.cs
- ClassDataContract.cs
- MaterialGroup.cs
- linebase.cs
- InstanceData.cs
- ColumnHeader.cs
- FixUp.cs
- TextInfo.cs
- DnsCache.cs
- WebContext.cs
- SchemaHelper.cs
- Point.cs
- IPEndPointCollection.cs
- ProfileInfo.cs
- EventDescriptorCollection.cs
- MexServiceChannelBuilder.cs
- Section.cs
- DropDownList.cs
- HtmlImage.cs
- NTAccount.cs
- MeasurementDCInfo.cs
- _StreamFramer.cs
- KeyGestureValueSerializer.cs
- JsonXmlDataContract.cs
- ObjectDataProvider.cs
- unsafenativemethodsother.cs
- FixedDocumentSequencePaginator.cs
- Queue.cs