//
// System.Data.SqlClient.SqlXmlTextReader.cs
//
// Author:
// Konstantin Triger (kostat@mainsoft.com)
//
// Copyright (C) 2006 Mainsoft, corp. (http://www.mainsoft.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.IO;
using System.Text;
using System.Xml;
namespace System.Data.SqlClient{
internal sealed class SqlXmlTextReader : TextReader {
#region FragmentXmlTextReader
sealed class FragmentXmlTextReader : XmlTextReader {
public FragmentXmlTextReader(System.IO.TextReader reader) : base(reader) {}
public override bool Read() {
do {
if (!base.Read())
return false;
}while(base.Depth == 0);
return true;
}
public override int Depth {
get {
int depth = base.Depth;
if (depth >= 1)
depth --;
return depth;
}
}
}
#endregion
#region Fields
bool _hasPeekedChar;
readonly char[] _peekedChar = new char[1];
readonly SqlDataReader _reader;
string _data;
int _rootPosition;
int _position = -1;
bool _eof;
static readonly char[] OpenRoot = new char[] {'<', 'X', '>'};
const int OpenRootLength = 3;
static readonly char[] CloseRoot = new char[] {'<', '/', 'X', '>'};
const int CloseRootLength = 4;
#endregion // Fields
#region Constructors
private SqlXmlTextReader (SqlDataReader reader) {
_reader = reader;
}
#endregion
#region Methods
public static XmlReader Create(SqlDataReader dataReader) {
return new FragmentXmlTextReader(new SqlXmlTextReader(dataReader));
}
public override void Close() {
_reader.Close ();
}
public override int Peek () {
if (!_hasPeekedChar) {
int consumed = Read(_peekedChar, 0, 1);
if (consumed < 0)
return -1;
_hasPeekedChar = true;
}
return _peekedChar[0];
}
public override int Read () {
int c = Peek();
_hasPeekedChar = false;
return c;
}
public override int Read (char[] buffer, int index, int count) {
if (buffer == null)
throw new ArgumentNullException("buffer");
if (index < 0)
throw new ArgumentOutOfRangeException("index");
if (count < 0)
throw new ArgumentOutOfRangeException("count");
if (count == 0)
return 0;
int got = 0;
if (_hasPeekedChar) {
buffer[index++] = _peekedChar[0];
count--;
_hasPeekedChar = false;
got ++;
}
if (!_eof) {
while (count > 0) {
if (_rootPosition < OpenRootLength) {
buffer[index++] = OpenRoot[_rootPosition++];
count --;
got ++;
continue;
}
if (_position < 0) {
if (_reader.Read()) {
_position = 0;
_data = _reader.GetString(0);
}
else {
if(_reader.NextResult())
continue;
else {
_rootPosition = 0;
_eof = true;
break;
}
}
}
int consumed = ((_position + count) > _data.Length) ? (_data.Length - (int)_position) : count;
_data.CopyTo(_position, buffer, index, consumed);
if (consumed > 0) {
_position += consumed;
got += consumed;
index += consumed;
count -= consumed;
}
else
_position = -1;
}
}
while (count > 0 && _rootPosition < CloseRootLength) {
buffer[index++] = CloseRoot[_rootPosition++];
count --;
got ++;
}
return got;
}
#endregion // Methods
}
}
|