namespace Mono.CSharp {
+ public interface GenericConstraints {
+ bool HasConstructor { get; }
+ bool IsReferenceType { get; }
+ bool IsValueType { get; }
+ bool HasClassConstraint { get; }
+ Type ClassConstraint { get; }
+ Type[] InterfaceConstraints { get; }
+ }
+
public interface ParameterData {
Type ParameterType (int pos);
+ GenericConstraints GenericConstraints (int pos);
+ bool HasArrayParameter { get; }
int Count { get; }
string ParameterName (int pos);
string ParameterDesc (int pos);
public class ReflectionParameters : ParameterData {
ParameterInfo [] pi;
bool last_arg_is_params = false;
-
- public ReflectionParameters (ParameterInfo [] pi)
+ bool is_varargs = false;
+ ParameterData gpd;
+
+ public ReflectionParameters (MethodBase mb)
{
object [] attrs;
-
+
+ ParameterInfo [] pi = mb.GetParameters ();
+ is_varargs = (mb.CallingConvention & CallingConventions.VarArgs) != 0;
+
this.pi = pi;
int count = pi.Length-1;
- if (count >= 0) {
- attrs = pi [count].GetCustomAttributes (TypeManager.param_array_type, true);
+ if (count < 0)
+ return;
- if (attrs == null)
- return;
-
- if (attrs.Length == 0)
- return;
+ if (mb.Mono_IsInflatedMethod) {
+ MethodInfo generic = mb.GetGenericMethodDefinition ();
+ gpd = Invocation.GetParameterData (generic);
- last_arg_is_params = true;
+ last_arg_is_params = gpd.HasArrayParameter;
+ return;
}
+
+ attrs = pi [count].GetCustomAttributes (TypeManager.param_array_type, true);
+ if (attrs == null)
+ return;
+
+ if (attrs.Length == 0)
+ return;
+
+ last_arg_is_params = true;
+ }
+
+ public bool HasArrayParameter {
+ get { return last_arg_is_params; }
}
-
+
public Type ParameterType (int pos)
{
if (last_arg_is_params && pos >= pi.Length - 1)
return pi [pi.Length - 1].ParameterType;
+ else if (is_varargs && pos >= pi.Length)
+ return TypeManager.runtime_argument_handle_type;
else {
Type t = pi [pos].ParameterType;
}
}
+ public GenericConstraints GenericConstraints (int pos)
+ {
+ if (gpd != null)
+ return gpd.GenericConstraints (pos);
+
+ Type t = ParameterType (pos);
+ if (!t.IsGenericParameter)
+ return null;
+
+ return ReflectionConstraints.Create (t);
+ }
+
public string ParameterName (int pos)
{
if (last_arg_is_params && pos >= pi.Length - 1)
return pi [pi.Length - 1].Name;
+ else if (is_varargs && pos >= pi.Length)
+ return "__arglist";
else
return pi [pos].Name;
}
public string ParameterDesc (int pos)
{
+ if (is_varargs && pos >= pi.Length)
+ return "";
+
StringBuilder sb = new StringBuilder ();
if (pi [pos].IsIn)
{
int len = pi.Length;
- if (pos >= len - 1)
- if (last_arg_is_params)
+ if (last_arg_is_params && pos >= pi.Length - 1)
return Parameter.Modifier.PARAMS;
+ else if (is_varargs && pos >= pi.Length)
+ return Parameter.Modifier.ARGLIST;
Type t = pi [pos].ParameterType;
if (t.IsByRef){
public int Count {
get {
- return pi.Length;
+ return is_varargs ? pi.Length + 1 : pi.Length;
+ }
+ }
+
+ protected class ReflectionConstraints : GenericConstraints
+ {
+ bool has_ctor;
+ bool is_reference_type;
+ bool is_value_type;
+ Type class_constraint;
+ Type[] iface_constraints;
+
+ protected ReflectionConstraints (bool has_ctor, Type class_constr,
+ Type[] iface_constrs)
+ {
+ this.has_ctor = has_ctor;
+ this.class_constraint = class_constr;
+ this.iface_constraints = iface_constrs;
+
+ if (class_constraint != null) {
+ if (class_constraint == TypeManager.object_type)
+ is_reference_type = true;
+ else if (class_constraint == TypeManager.value_type)
+ is_value_type = true;
+ }
+ }
+
+ public static GenericConstraints Create (Type t)
+ {
+ Type class_constr = null;
+ Type[] iface_constrs = t.GetInterfaces ();
+ if (iface_constrs == null)
+ iface_constrs = Type.EmptyTypes;
+ if (t.BaseType != TypeManager.object_type)
+ class_constr = t.BaseType;
+
+ return new ReflectionConstraints (
+ false, class_constr, iface_constrs);
+ }
+
+ public bool HasConstructor {
+ get { return has_ctor; }
+ }
+
+ public bool HasClassConstraint {
+ get { return class_constraint != null; }
+ }
+
+ public bool IsReferenceType {
+ get { return is_reference_type; }
+ }
+
+ public bool IsValueType {
+ get { return is_value_type; }
+ }
+
+ public Type ClassConstraint {
+ get { return class_constraint; }
+ }
+
+ public Type[] InterfaceConstraints {
+ get { return iface_constraints; }
}
}
-
}
public class InternalParameters : ParameterData {
Type [] param_types;
+ bool has_varargs;
+ int count;
public readonly Parameters Parameters;
public InternalParameters (DeclSpace ds, Parameters parameters)
: this (parameters.GetParameterInfo (ds), parameters)
{
+ has_varargs = parameters.HasArglist;
+
+ if (param_types == null)
+ count = 0;
+ else
+ count = param_types.Length;
}
public int Count {
get {
- if (param_types == null)
- return 0;
-
- return param_types.Length;
+ return has_varargs ? count + 1 : count;
}
}
+ public bool HasArrayParameter {
+ get { return Parameters.ArrayParameter != null; }
+ }
+
Parameter GetParameter (int pos)
{
Parameter [] fixed_pars = Parameters.FixedParameters;
public Type ParameterType (int pos)
{
+ if (has_varargs && pos >= count)
+ return TypeManager.runtime_argument_handle_type;
+
if (param_types == null)
return null;
return GetParameter (pos).ExternalType ();
}
+ public GenericConstraints GenericConstraints (int pos)
+ {
+ if (param_types == null)
+ return null;
+
+ return GetParameter (pos).GenericConstraints;
+ }
public string ParameterName (int pos)
{
+ if (has_varargs && pos >= count)
+ return "__arglist";
+
return GetParameter (pos).Name;
}
public string ParameterDesc (int pos)
{
+ if (has_varargs && pos >= count)
+ return "__arglist";
+
string tmp = String.Empty;
Parameter p = GetParameter (pos);
public Parameter.Modifier ParameterModifier (int pos)
{
+ if (has_varargs && pos >= count)
+ return Parameter.Modifier.ARGLIST;
+
Parameter.Modifier mod = GetParameter (pos).ModFlags;
if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0)
}
class PtrHashtable : Hashtable {
- class PtrComparer : IComparer {
+ sealed class PtrComparer : IComparer {
+ private PtrComparer () {}
+
+ public static PtrComparer Instance = new PtrComparer ();
+
public int Compare (object x, object y)
{
if (x == y)
public PtrHashtable ()
{
- comparer = new PtrComparer ();
+ comparer = PtrComparer.Instance;
}
}
+ /*
+ * Hashtable whose keys are character arrays with the same length
+ */
+ class CharArrayHashtable : Hashtable {
+ sealed class ArrComparer : IComparer {
+ private int len;
+
+ public ArrComparer (int len) {
+ this.len = len;
+ }
+
+ public int Compare (object x, object y)
+ {
+ char[] a = (char[])x;
+ char[] b = (char[])y;
+
+ for (int i = 0; i < len; ++i)
+ if (a [i] != b [i])
+ return 1;
+ return 0;
+ }
+ }
+
+ private int len;
+
+ protected override int GetHash (Object key)
+ {
+ char[] arr = (char[])key;
+ int h = 0;
+
+ for (int i = 0; i < len; ++i)
+ h = (h << 5) - h + arr [i];
+
+ return h;
+ }
+
+ public CharArrayHashtable (int len)
+ {
+ this.len = len;
+ comparer = new ArrComparer (len);
+ }
+ }
+
//
// Compares member infos based on their name and
// also allows one argument to be a string
}
if (a is string)
- return String.Compare ((string) a, ((MemberInfo)b).Name);
+ return String.Compare ((string) a, ((MemberInfo)b).Name, false, CultureInfo.InvariantCulture);
if (b is string)
- return String.Compare (((MemberInfo)a).Name, (string) b);
+ return String.Compare (((MemberInfo)a).Name, (string) b, false, CultureInfo.InvariantCulture);
- return String.Compare (((MemberInfo)a).Name, ((MemberInfo)b).Name);
+ return String.Compare (((MemberInfo)a).Name, ((MemberInfo)b).Name, false, CultureInfo.InvariantCulture);
}
}
{
this.reader = reader;
this.buffer = new char [DefaultCacheSize];
+
+ // Compute the preamble size
+
+ // Let the StreamWriter autodetect the encoder
+ reader.Peek ();
+
+ reader.BaseStream.Position = 0;
+ Encoding enc = reader.CurrentEncoding;
+ // First of all, get at least a char
+
+ byte[] auxb = new byte [50];
+ int num_bytes = 0;
+ int num_chars = 0;
+ int br = 0;
+ do {
+ br = reader.BaseStream.Read (auxb, num_bytes, auxb.Length - num_bytes);
+ num_bytes += br;
+ num_chars = enc.GetCharCount (auxb, 0, num_bytes);
+ }
+ while (num_chars == 0 && br > 0);
+
+ if (num_chars != 0)
+ {
+ // Now, check which bytes at the beginning have no effect in the
+ // char count
+
+ int p = 0;
+ while (enc.GetCharCount (auxb, p, num_bytes-p) >= num_chars)
+ p++;
+
+ preamble_size = p - 1;
+ reader.BaseStream.Position = 0;
+ reader.DiscardBufferedData ();
+
+ buffer_start = preamble_size;
+ }
}
public SeekableStreamReader (Stream stream, Encoding encoding, bool detect_encoding_from_bytemarks)
private const int DefaultCacheSize = 1024;
char[] buffer;
- int buffer_start;
- int buffer_size;
- int pos;
+ int buffer_start; // in bytes
+ int buffer_size; // in bytes
+ int char_count; // count buffer[] valid characters
+ int pos; // index into buffer[]
+ int preamble_size;
/// <remarks>
/// The difference to the StreamReader's BaseStream.Position is that this one is reliable; ie. it
/// </remarks>
public int Position {
get {
- return buffer_start + pos;
+ return buffer_start + reader.CurrentEncoding.GetByteCount (buffer, 0, pos);
}
set {
// This one is easy: we're modifying the position within our current
// buffer.
if ((value >= buffer_start) && (value < buffer_start + buffer_size)) {
- pos = value - buffer_start;
+ int byte_offset = value - buffer_start;
+ pos = byte_offset;
+ // encoded characters can take more than 1 byte length
+ while (reader.CurrentEncoding.GetByteCount (buffer, 0, pos) > byte_offset)
+ pos--;
+
return;
}
+
+ if (value == 0) // Skip preamble
+ value = preamble_size;
// Ok, now we need to seek.
reader.DiscardBufferedData ();
reader.BaseStream.Position = buffer_start = value;
- buffer_size = pos = 0;
+ char_count = buffer_size = pos = 0;
}
}
{
pos = 0;
buffer_start += buffer_size;
- buffer_size = reader.Read (buffer, 0, buffer.Length);
+ char_count = reader.Read (buffer, 0, buffer.Length);
+ buffer_size = reader.CurrentEncoding.GetByteCount (buffer, 0, char_count);
return buffer_size > 0;
}
public int Peek ()
{
- if ((pos >= buffer_size) && !ReadBuffer ())
+ if ((pos >= char_count) && !ReadBuffer ())
return -1;
return buffer [pos];
public int Read ()
{
- if ((pos >= buffer_size) && !ReadBuffer ())
+ if ((pos >= char_count) && !ReadBuffer ())
return -1;
return buffer [pos++];
}
public class DoubleHash {
- Hashtable l = new Hashtable ();
+ const int DEFAULT_INITIAL_BUCKETS = 100;
+
+ public DoubleHash () : this (DEFAULT_INITIAL_BUCKETS) {}
- public DoubleHash ()
+ public DoubleHash (int size)
{
+ count = size;
+ buckets = new Entry [size];
+ }
+
+ int count;
+ Entry [] buckets;
+ int size = 0;
+
+ class Entry {
+ public object key1;
+ public object key2;
+ public int hash;
+ public object value;
+ public Entry next;
+
+ public Entry (object key1, object key2, int hash, object value, Entry next)
+ {
+ this.key1 = key1;
+ this.key2 = key2;
+ this.hash = hash;
+ this.next = next;
+ this.value = value;
+ }
}
public bool Lookup (object a, object b, out object res)
{
- object r = l [a];
- if (r == null){
- res = null;
- return false;
- }
- Hashtable ht = (Hashtable) r;
- if (ht.Contains (b)){
- res = ht [b];
- return true;
+ int h = (a.GetHashCode () ^ b.GetHashCode ()) & 0x7FFFFFFF;
+
+ for (Entry e = buckets [h % count]; e != null; e = e.next) {
+ if (e.hash == h && e.key1.Equals (a) && e.key2.Equals (b)) {
+ res = e.value;
+ return true;
+ }
}
res = null;
return false;
public void Insert (object a, object b, object value)
{
- Hashtable ht;
- object r = l [a];
- if (r == null){
- ht = new Hashtable ();
- l [a] = ht;
- ht [b] = value;
- return;
+ // Is it an existing one?
+
+ int h = (a.GetHashCode () ^ b.GetHashCode ()) & 0x7FFFFFFF;
+
+ for (Entry e = buckets [h % count]; e != null; e = e.next) {
+ if (e.hash == h && e.key1.Equals (a) && e.key2.Equals (b))
+ e.value = value;
+ }
+
+ int bucket = h % count;
+ buckets [bucket] = new Entry (a, b, h, value, buckets [bucket]);
+
+ // Grow whenever we double in size
+ if (size++ == count) {
+ count <<= 1;
+ count ++;
+
+ Entry [] newBuckets = new Entry [count];
+ foreach (Entry root in buckets) {
+ Entry e = root;
+ while (e != null) {
+ int newLoc = e.hash % count;
+ Entry n = e.next;
+ e.next = newBuckets [newLoc];
+ newBuckets [newLoc] = e;
+ e = n;
+ }
+ }
+
+ buckets = newBuckets;
}
- ht = (Hashtable) r;
- ht [b] = value;
}
}
}