File: SqlSequentialTextReaderSmi.cs

package info (click to toggle)
mono 6.12.0.199%2Bdfsg-6
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 1,296,836 kB
  • sloc: cs: 11,181,803; xml: 2,850,076; ansic: 699,709; cpp: 123,344; perl: 59,361; javascript: 30,841; asm: 21,853; makefile: 20,405; sh: 15,009; python: 4,839; pascal: 925; sql: 859; sed: 16; php: 1
file content (133 lines) | stat: -rw-r--r-- 4,645 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
using System;
using System.Data.Common;
using System.Diagnostics;
using Microsoft.SqlServer.Server;

namespace System.Data.SqlClient
{
    sealed internal class SqlSequentialTextReaderSmi : System.IO.TextReader
    {
        private SmiEventSink_Default _sink;
        private ITypedGettersV3 _getters;
        private int _columnIndex;       // The index of out column in the table
        private long _position;         // Current position in the stream
        private long _length;           // Total length of the stream
        private int _peekedChar;        // Current peeked character (if any)

        internal SqlSequentialTextReaderSmi(SmiEventSink_Default sink, ITypedGettersV3 getters, int columnIndex, long length)
        {
            _sink = sink;
            _getters = getters;
            _columnIndex = columnIndex;
            _length = length;
            _position = 0;
            _peekedChar = -1;
        }

        internal int ColumnIndex
        {
            get { return _columnIndex; }
        }

        public override int Peek()
        {
            if (!HasPeekedChar)
            {
                _peekedChar = Read();
            }

            Debug.Assert(_peekedChar == -1 || ((_peekedChar >= char.MinValue) && (_peekedChar <= char.MaxValue)), string.Format("Bad peeked character: {0}", _peekedChar));
            return _peekedChar;
        }

        public override int Read()
        {
            if (IsClosed)
            {
                throw ADP.ObjectDisposed(this);
            }

            int readChar = -1;

            // If there is already a peeked char, then return it
            if (HasPeekedChar)
            {
                readChar = _peekedChar;
                _peekedChar = -1;
            }
            // If there is data available try to read a char
            else if (_position < _length)
            {
                char[] tempBuffer = new char[1];
                int charsRead = ValueUtilsSmi.GetChars_Unchecked(_sink, _getters, _columnIndex, _position, tempBuffer, 0, 1);
                if (charsRead == 1)
                {
                    readChar = tempBuffer[0];
                    _position++;
                }
            }

            Debug.Assert(readChar == -1 || ((readChar >= char.MinValue) && (readChar <= char.MaxValue)), string.Format("Bad read character: {0}", readChar));
            return readChar;
        }

        public override int Read(char[] buffer, int index, int count)
        {
            SqlSequentialTextReader.ValidateReadParameters(buffer, index, count);
            if (IsClosed)
            {
                throw ADP.ObjectDisposed(this);
            }

            int charsRead = 0;
            // Load in peeked char
            if ((count > 0) && (HasPeekedChar))
            {
                Debug.Assert((_peekedChar >= char.MinValue) && (_peekedChar <= char.MaxValue), string.Format("Bad peeked character: {0}", _peekedChar));
                buffer[index + charsRead] = (char)_peekedChar;
                charsRead++;
                _peekedChar = -1;
            }

            // Read whichever is less: however much the user asked for, or however much we have
            // NOTE: It is safe to do this since count <= Int32.MaxValue, therefore the Math.Min should always result in an int
            int charsNeeded = (int)Math.Min((long)(count - charsRead), _length - _position);
            // If we need more data and there is data avaiable, read
            if (charsNeeded > 0)
            {
                int newCharsRead = ValueUtilsSmi.GetChars_Unchecked(_sink, _getters, _columnIndex, _position, buffer, index + charsRead, charsNeeded);
                _position += newCharsRead;
                charsRead += newCharsRead;
            }

            return charsRead;
        }
        
        /// <summary>
        /// Forces the TextReader to act as if it was closed
        /// This does not actually close the stream, read off the rest of the data or dispose this
        /// </summary>
        internal void SetClosed()
        {
            _sink = null;
            _getters = null;
            _peekedChar = -1;
        }

        /// <summary>
        /// True if this TextReader is supposed to be closed
        /// </summary>
        private bool IsClosed
        {
            get { return ((_sink == null) || (_getters == null)); } 
        }

        /// <summary>
        /// True if there is a peeked character available
        /// </summary>
        private bool HasPeekedChar
        {
            get { return (_peekedChar >= char.MinValue); }
        }
    }
}