{
}
+ static XmlException invalidDataException = new XmlException ("invalid data.");
+
public override void Close ()
{
this.input.Close ();
}
+ public override int Read ([In, Out] char[] dest_buffer, int index, int count)
+ {
+ try {
+ return base.Read (dest_buffer, index, count);
+ }
+#if NET_1_1
+ catch (System.ArgumentException) {
+ throw invalidDataException;
+ }
+#else
+ catch (System.Text.DecoderFallbackException) {
+ throw invalidDataException;
+ }
+#endif
+ }
+
protected override void Dispose (bool disposing)
{
base.Dispose (disposing);
#endregion
#region NonBlockingStreamReader
- // mostly copied from StreamReader.
+ // mostly copied from StreamReader, removing BOM checks, ctor
+ // parameter checks and some extra public members.
internal class NonBlockingStreamReader : TextReader {
const int DefaultBufferSize = 1024;
Stream base_stream;
bool mayBlock;
+ StringBuilder line_builder;
public NonBlockingStreamReader(Stream stream, Encoding encoding)
{
pos = 0;
}
+ public Encoding Encoding {
+ get { return encoding; }
+ }
+
public override void Close ()
{
Dispose (true);
{
pos = decoded_count = 0;
mayBlock = false;
+#if NET_2_0
+ decoder.Reset ();
+#else
+ decoder = encoding.GetDecoder ();
+#endif
}
// the buffer is empty, fill it again
return chars_read;
}
+ bool foundCR;
+ int FindNextEOL ()
+ {
+ char c = '\0';
+ for (; pos < decoded_count; pos++) {
+ c = decoded_buffer [pos];
+ if (c == '\n') {
+ pos++;
+ int res = (foundCR) ? (pos - 2) : (pos - 1);
+ if (res < 0)
+ res = 0; // if a new buffer starts with a \n and there was a \r at
+ // the end of the previous one, we get here.
+ foundCR = false;
+ return res;
+ } else if (foundCR) {
+ foundCR = false;
+ return pos - 1;
+ }
+
+ foundCR = (c == '\r');
+ }
+
+ return -1;
+ }
+
public override string ReadLine()
{
if (base_stream == null)
throw new ObjectDisposedException ("StreamReader", "Cannot read from a closed StreamReader");
-
- bool foundCR = false;
- StringBuilder text = new StringBuilder ();
- while (true) {
- int c = Read ();
+ if (pos >= decoded_count && ReadBuffer () == 0)
+ return null;
- if (c == -1) { // end of stream
- if (text.Length == 0)
- return null;
+ int begin = pos;
+ int end = FindNextEOL ();
+ if (end < decoded_count && end >= begin)
+ return new string (decoded_buffer, begin, end - begin);
- if (foundCR)
- text.Length--;
+ if (line_builder == null)
+ line_builder = new StringBuilder ();
+ else
+ line_builder.Length = 0;
- break;
+ while (true) {
+ if (foundCR) // don't include the trailing CR if present
+ decoded_count--;
+
+ line_builder.Append (new string (decoded_buffer, begin, decoded_count - begin));
+ if (ReadBuffer () == 0) {
+ if (line_builder.Capacity > 32768) {
+ StringBuilder sb = line_builder;
+ line_builder = null;
+ return sb.ToString (0, sb.Length);
+ }
+ return line_builder.ToString (0, line_builder.Length);
}
- if (c == '\n') { // newline
- if ((text.Length > 0) && (text [text.Length - 1] == '\r'))
- text.Length--;
-
- foundCR = false;
- break;
- } else if (foundCR) {
- pos--;
- text.Length--;
- break;
+ begin = pos;
+ end = FindNextEOL ();
+ if (end < decoded_count && end >= begin) {
+ line_builder.Append (new string (decoded_buffer, begin, end - begin));
+ if (line_builder.Capacity > 32768) {
+ StringBuilder sb = line_builder;
+ line_builder = null;
+ return sb.ToString (0, sb.Length);
+ }
+ return line_builder.ToString (0, line_builder.Length);
}
-
- if (c == '\r')
- foundCR = true;
-
-
- text.Append ((char) c);
}
-
- return text.ToString ();
}
public override string ReadToEnd()
Initialize (stream);
}
+ static string GetStringFromBytes (byte [] bytes, int index, int count)
+ {
+#if MOONLIGHT
+ char [] chars = new char [count];
+ for (int i = index; i < count; i++)
+ chars [i] = (char) bytes [i];
+
+ return new string (chars);
+#else
+ return Encoding.ASCII.GetString (bytes, index, count);
+#endif
+ }
+
private void Initialize (Stream stream)
{
buffer = new byte [64];
break;
case '<':
// try to get encoding name from XMLDecl.
- if (bufLength >= 5 && Encoding.ASCII.GetString (buffer, 1, 4) == "?xml") {
+ if (bufLength >= 5 && GetStringFromBytes (buffer, 1, 4) == "?xml") {
bufPos += 4;
c = SkipWhitespace ();
if (c == 'e') {
int remaining = bufLength - bufPos;
- if (remaining >= 7 && Encoding.ASCII.GetString(buffer, bufPos, 7) == "ncoding") {
+ if (remaining >= 7 && GetStringFromBytes (buffer, bufPos, 7) == "ncoding") {
bufPos += 7;
c = SkipWhitespace();
if (c != '=')
}
}
}
+#if TARGET_JVM
+ else {
+ if (bufLength >= 10 && Encoding.Unicode.GetString (buffer, 2, 8) == "?xml")
+ enc = Encoding.Unicode;
+ }
+#endif
bufPos = 0;
break;
default:
return c;
}
}
- throw new InvalidOperationException ();
}
public Encoding ActualEncoding {