2010-06-29 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / class / System.Data / System.Data.SqlClient.jvm / SqlXmlTextReader.cs
1 //
2 // System.Data.SqlClient.SqlXmlTextReader.cs
3 //
4 // Author:
5 //   Konstantin Triger (kostat@mainsoft.com)
6 //
7 // Copyright (C) 2006 Mainsoft, corp. (http://www.mainsoft.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System;
30 using System.IO;
31 using System.Text;
32 using System.Xml;
33
34 namespace System.Data.SqlClient {
35         internal sealed class SqlXmlTextReader : TextReader {
36
37                 #region FragmentXmlTextReader
38
39                 sealed class FragmentXmlTextReader : XmlTextReader {
40                         public FragmentXmlTextReader(System.IO.TextReader reader) : base(reader) {}
41
42                         public override bool Read() {
43                                 do {
44                                         if (!base.Read())
45                                                 return false;
46                                 }while(base.Depth == 0);
47
48                                 return true;
49                         }
50
51                         public override int Depth {
52                                 get {
53                                         int depth = base.Depth;
54                                         if (depth >= 1)
55                                                 depth --;
56
57                                         return depth;
58                                 }
59                         }
60                 }
61
62                 #endregion
63
64                 #region Fields
65
66                 bool _hasPeekedChar;
67                 readonly char[] _peekedChar = new char[1];
68                 readonly SqlDataReader _reader;
69
70                 string _data;
71                 int _rootPosition;
72                 int _position = -1;
73                 bool _eof;
74
75                 static readonly char[] OpenRoot = new char[] {'<', 'X', '>'};
76                 const int OpenRootLength = 3;
77                 static readonly char[] CloseRoot = new char[] {'<', '/', 'X', '>'};
78                 const int CloseRootLength = 4;
79
80                 #endregion // Fields
81
82                 #region Constructors
83
84                 private SqlXmlTextReader (SqlDataReader reader) {
85                         _reader = reader;
86                 }
87
88                 #endregion
89
90                 #region Methods
91
92                 public static XmlReader Create(SqlDataReader dataReader) {
93                         return new FragmentXmlTextReader(new SqlXmlTextReader(dataReader));
94                 }
95
96                 public override void Close() {
97                         _reader.Close ();       
98                 }
99
100                 public override int Peek () {
101                         if (!_hasPeekedChar) {
102
103                                 int consumed = Read(_peekedChar, 0, 1);
104                                 if (consumed < 0)
105                                         return -1;
106
107                                 _hasPeekedChar = true;
108                         }
109
110                         return _peekedChar[0];
111                 }
112                         
113                 public override int Read () {
114                         int c = Peek();
115                         _hasPeekedChar = false;
116                         return c;
117                 }       
118
119                 public override int Read (char[] buffer, int index, int count) {
120                         if (buffer == null)
121                                 throw new ArgumentNullException("buffer");
122
123                         if (index < 0)
124                                 throw new ArgumentOutOfRangeException("index");
125
126                         if (count < 0)
127                                 throw new ArgumentOutOfRangeException("count");
128
129                         if (count == 0)
130                                 return 0;
131
132                         int got = 0;
133
134                         if (_hasPeekedChar) {
135                                 buffer[index++] = _peekedChar[0];
136                                 count--;
137                                 _hasPeekedChar = false;
138                                 got ++;
139                         }
140
141                         if (!_eof) {
142                                 while (count > 0) {
143
144                                         if (_rootPosition < OpenRootLength) {
145                                                 buffer[index++] = OpenRoot[_rootPosition++];
146                                                 count --;
147                                                 got ++;
148                                                 continue;
149                                         }
150
151                                         if (_position < 0) {
152                                                 if (_reader.Read()) {
153                                                         _position = 0;
154                                                         _data = _reader.GetString(0);
155                                                 }
156                                                 else {
157                                                         if(_reader.NextResult())
158                                                                 continue;
159                                                         else {
160                                                                 _rootPosition = 0;
161                                                                 _eof = true;
162                                                                 break;
163                                                         }
164                                                 }
165                                         }
166
167                                         int consumed = ((_position + count) > _data.Length) ? (_data.Length - (int)_position) : count;
168                                         _data.CopyTo(_position, buffer, index, consumed);
169                                                 
170                                         if (consumed > 0) {
171                                                 _position += consumed;
172                                                 got += consumed;
173                                                 index += consumed;
174                                                 count -= consumed;
175                                         }
176                                         else
177                                                 _position = -1;
178                                 }
179                         }
180
181                         while (count > 0 && _rootPosition < CloseRootLength) {
182                                 buffer[index++] = CloseRoot[_rootPosition++];
183                                 count --;
184                                 got ++;
185                         }
186
187
188                         return got;
189                 }
190
191                 #endregion // Methods
192         }
193 }