1 //
2 // ArrayType.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@gmail.com)
6 //
7 // Copyright (c) 2008 - 2011 Jb Evain
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.Text;
31 using Mono.Collections.Generic;
32 using MD = Mono.Cecil.Metadata;
33 
34 namespace Mono.Cecil {
35 
36 	public struct ArrayDimension {
37 
38 		int? lower_bound;
39 		int? upper_bound;
40 
41 		public int? LowerBound {
42 			get { return lower_bound; }
43 			set { lower_bound = value; }
44 		}
45 
46 		public int? UpperBound {
47 			get { return upper_bound; }
48 			set { upper_bound = value; }
49 		}
50 
51 		public bool IsSized {
52 			get { return lower_bound.HasValue || upper_bound.HasValue; }
53 		}
54 
ArrayDimensionMono.Cecil.ArrayDimension55 		public ArrayDimension (int? lowerBound, int? upperBound)
56 		{
57 			this.lower_bound = lowerBound;
58 			this.upper_bound = upperBound;
59 		}
60 
ToStringMono.Cecil.ArrayDimension61 		public override string ToString ()
62 		{
63 			return !IsSized
64 				? string.Empty
65 				: lower_bound + "..." + upper_bound;
66 		}
67 	}
68 
69 	public sealed class ArrayType : TypeSpecification {
70 
71 		Collection<ArrayDimension> dimensions;
72 
73 		public Collection<ArrayDimension> Dimensions {
74 			get {
75 				if (dimensions != null)
76 					return dimensions;
77 
78 				dimensions = new Collection<ArrayDimension> ();
79 				dimensions.Add (new ArrayDimension ());
80 				return dimensions;
81 			}
82 		}
83 
84 		public int Rank {
85 			get { return dimensions == null ? 1 : dimensions.Count; }
86 		}
87 
88 		public bool IsVector {
89 			get {
90 				if (dimensions == null)
91 					return true;
92 
93 				if (dimensions.Count > 1)
94 					return false;
95 
96 				var dimension = dimensions [0];
97 
98 				return !dimension.IsSized;
99 			}
100 		}
101 
102 		public override bool IsValueType {
103 			get { return false; }
104 			set { throw new InvalidOperationException (); }
105 		}
106 
107 		public override string Name {
108 			get { return base.Name + Suffix; }
109 		}
110 
111 		public override string FullName {
112 			get { return base.FullName + Suffix; }
113 		}
114 
115 		string Suffix {
116 			get {
117 				if (IsVector)
118 					return "[]";
119 
120 				var suffix = new StringBuilder ();
121 				suffix.Append ("[");
122 				for (int i = 0; i < dimensions.Count; i++) {
123 					if (i > 0)
124 						suffix.Append (",");
125 
126 					suffix.Append (dimensions [i].ToString ());
127 				}
128 				suffix.Append ("]");
129 
130 				return suffix.ToString ();
131 			}
132 		}
133 
134 		public override bool IsArray {
135 			get { return true; }
136 		}
137 
ArrayType(TypeReference type)138 		public ArrayType (TypeReference type)
139 			: base (type)
140 		{
141 			Mixin.CheckType (type);
142 			this.etype = MD.ElementType.Array;
143 		}
144 
ArrayType(TypeReference type, int rank)145 		public ArrayType (TypeReference type, int rank)
146 			: this (type)
147 		{
148 			Mixin.CheckType (type);
149 
150 			if (rank == 1)
151 				return;
152 
153 			dimensions = new Collection<ArrayDimension> (rank);
154 			for (int i = 0; i < rank; i++)
155 				dimensions.Add (new ArrayDimension ());
156 			this.etype = MD.ElementType.Array;
157 		}
158 	}
159 }
160