2 // support.cs: Support routines to work around the fact that System.Reflection.Emit
3 // can not introspect types that are being constructed
6 // Miguel de Icaza (miguel@ximian.com)
7 // Marek Safar (marek.safar@gmail.com)
9 // Copyright 2001 Ximian, Inc (http://www.ximian.com)
10 // Copyright 2003-2009 Novell, Inc
11 // Copyright 2011 Xamarin Inc
17 using System.Collections.Generic;
19 namespace Mono.CSharp {
21 sealed class ReferenceEquality<T> : IEqualityComparer<T> where T : class
23 public static readonly IEqualityComparer<T> Default = new ReferenceEquality<T> ();
25 private ReferenceEquality ()
29 public bool Equals (T x, T y)
31 return ReferenceEquals (x, y);
34 public int GetHashCode (T obj)
36 return System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode (obj);
40 static class ArrayComparer
42 public static bool IsEqual<T> (T[] array1, T[] array2)
44 if (array1 == null || array2 == null)
45 return array1 == array2;
47 var eq = EqualityComparer<T>.Default;
49 for (int i = 0; i < array1.Length; ++i) {
50 if (!eq.Equals (array1[i], array2[i])) {
60 /// This is an arbitrarily seekable StreamReader wrapper.
62 /// It uses a self-tuning buffer to cache the seekable data,
63 /// but if the seek is too far, it may read the underly
64 /// stream all over from the beginning.
66 public class SeekableStreamReader : IDisposable
68 public const int DefaultReadAheadSize =
70 65536 / 2; // Large buffer because of ReadChars of large literal string
79 int read_ahead_length; // the length of read buffer
80 int buffer_start; // in chars
81 int char_count; // count of filled characters in buffer[]
82 int pos; // index into buffer[]
84 public SeekableStreamReader (Stream stream, Encoding encoding, char[] sharedBuffer = null)
87 this.buffer = sharedBuffer;
89 InitializeStream (DefaultReadAheadSize);
90 reader = new StreamReader (stream, encoding, true);
93 public void Dispose ()
95 // Needed to release stream reader buffers
99 void InitializeStream (int read_length_inc)
101 read_ahead_length += read_length_inc;
103 int required_buffer_size = read_ahead_length * 2;
105 if (buffer == null || buffer.Length < required_buffer_size)
106 buffer = new char [required_buffer_size];
109 buffer_start = char_count = pos = 0;
113 /// This value corresponds to the current position in a stream of characters.
114 /// The StreamReader hides its manipulation of the underlying byte stream and all
115 /// character set/decoding issues. Thus, we cannot use this position to guess at
116 /// the corresponding position in the underlying byte stream even though there is
117 /// a correlation between them.
119 public int Position {
121 return buffer_start + pos;
126 // If the lookahead was too small, re-read from the beginning. Increase the buffer size while we're at it
127 // This should never happen until we are parsing some weird source code
129 if (value < buffer_start) {
130 InitializeStream (read_ahead_length);
133 // Discard buffer data after underlying stream changed position
134 // Cannot use handy reader.DiscardBufferedData () because it for
135 // some strange reason resets encoding as well
137 reader = new StreamReader (stream, reader.CurrentEncoding, true);
140 while (value > buffer_start + char_count) {
143 throw new InternalErrorException ("Seek beyond end of file: " + (buffer_start + char_count - value));
146 pos = value - buffer_start;
152 int slack = buffer.Length - char_count;
155 // read_ahead_length is only half of the buffer to deal with
156 // reads ahead and moves back without re-reading whole buffer
158 if (slack <= read_ahead_length) {
160 // shift the buffer to make room for read_ahead_length number of characters
162 int shift = read_ahead_length - slack;
163 Array.Copy (buffer, shift, buffer, 0, char_count - shift);
165 // Update all counters
168 buffer_start += shift;
172 char_count += reader.Read (buffer, char_count, slack);
174 return pos < char_count;
177 public char[] ReadChars (int fromPosition, int toPosition)
179 char[] chars = new char[toPosition - fromPosition];
180 if (buffer_start <= fromPosition && toPosition <= buffer_start + buffer.Length) {
181 Array.Copy (buffer, fromPosition - buffer_start, chars, 0, chars.Length);
183 throw new NotImplementedException ();
191 if ((pos >= char_count) && !ReadBuffer ())
199 if ((pos >= char_count) && !ReadBuffer ())
202 return buffer [pos++];
206 public class UnixUtils {
207 [System.Runtime.InteropServices.DllImport ("libc", EntryPoint="isatty")]
208 extern static int _isatty (int fd);
210 public static bool isatty (int fd)
213 return _isatty (fd) == 1;
221 /// An exception used to terminate the compiler resolution phase and provide completions
224 /// This is thrown when we want to return the completions or
225 /// terminate the completion process by AST nodes used in
226 /// the completion process.
228 public class CompletionResult : Exception {
232 public CompletionResult (string base_text, string [] res)
234 if (base_text == null)
235 throw new ArgumentNullException ("base_text");
236 this.base_text = base_text;
242 public string [] Result {
248 public string BaseText {
255 struct TypeNameParser
257 internal static string Escape(string name)
262 StringBuilder sb = null;
263 for (int pos = 0; pos < name.Length; pos++) {
274 sb = new StringBuilder(name, 0, pos, name.Length + 3);
276 sb.Append("\\").Append(c);
285 return sb != null ? sb.ToString() : name;