[corlib] Fixed StringBuilder construction bugs in marshalling caused by changes to...
[mono.git] / mcs / class / System / System.Runtime.Versioning / FrameworkName.cs
1 //
2 // System.Runtime.Versioning.FrameworkName class
3 //
4 // Authors
5 //      Marek Habersack <mhabersack@novell.com>
6 //
7 // Copyright (C) 2009 Novell, Inc (http://novell.com)
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 using System;
29 using System.Text;
30
31 namespace System.Runtime.Versioning
32 {
33         [Serializable]
34         public sealed class FrameworkName : IEquatable <FrameworkName>
35         {               
36                 string fullName;
37                 int? hashCode;
38                 
39                 public string FullName {
40                         get {
41                                 if (fullName == null) {
42                                         var sb = new StringBuilder (Identifier);
43                                         sb.Append (",Version=v");
44                                         sb.Append (Version.ToString ());
45
46                                         string profile = Profile;
47                                         if (!String.IsNullOrEmpty (profile)) {
48                                                 sb.Append (",Profile=");
49                                                 sb.Append (profile);
50                                         }
51
52                                         fullName = sb.ToString ();
53                                 }
54
55                                 return fullName;
56                         }
57                 }
58                 
59                 public string Identifier {
60                         get; private set;
61                 }
62
63                 public string Profile {
64                         get; private set;
65                 }
66                 
67                 public Version Version {
68                         get; private set;
69                 }
70                 
71                 public FrameworkName (string frameworkName)
72                 {
73                         if (frameworkName == null)
74                                 throw new ArgumentNullException ("frameworkName");
75
76                         if (frameworkName.Length == 0)
77                                 throw new ArgumentException ("The parameter 'frameworkName' cannot be an empty string.", "frameworkName");
78
79                         this.Profile = String.Empty;
80                         ParseFrameworkName (frameworkName);
81                 }
82
83                 public FrameworkName (string identifier, Version version)
84                         : this (identifier, version, String.Empty)
85                 {
86                 }
87
88                 public FrameworkName (string identifier, Version version, string profile)
89                 {
90                         if (identifier == null)
91                                 throw new ArgumentNullException ("identifier");
92
93                         if (version == null)
94                                 throw new ArgumentNullException ("version");
95
96                         if (identifier.Length == 0)
97                                 throw new ArgumentException ("The parameter 'identifier' cannot be an empty string.", "identifier");
98                         
99                         this.Identifier = identifier;
100                         this.Version = version;
101                         if (profile == null)
102                                 this.Profile = String.Empty;
103                         else
104                                 this.Profile = profile;
105                 }
106
107                 public bool Equals (FrameworkName other)
108                 {
109                         if (Object.ReferenceEquals (other, null))
110                                 return false;
111
112                         return (other.Version == this.Version &&
113                                 String.Compare (other.Identifier, this.Identifier, StringComparison.Ordinal) == 0 &&
114                                 String.Compare (other.Profile, this.Profile, StringComparison.Ordinal) == 0);
115                 }
116
117                 public override bool Equals (object obj)
118                 {
119                         return Equals (obj as FrameworkName);
120                 }
121
122                 public override int GetHashCode ()
123                 {
124                         if (hashCode == null) {
125                                 hashCode = Version.GetHashCode () ^ Identifier.GetHashCode ();
126                                 string profile = Profile;
127                                 if (profile != null)
128                                         hashCode ^= profile.GetHashCode ();
129                         }
130                         
131                         return (int)hashCode;
132                 }
133
134                 public override string ToString ()
135                 {
136                         return FullName;
137                 }
138
139                 public static bool operator == (FrameworkName left, FrameworkName right)
140                 {
141                         if (((object)left) == null && ((object)right) == null)
142                                 return true;
143
144                         if (((object)left) == null || ((object)right) == null)
145                                 return false;
146
147                         return left.Equals (right);
148                 }
149
150                 public static bool operator != (FrameworkName left, FrameworkName right)
151                 {
152                         if (((object)left) == null && ((object)right) == null)
153                                 return false;
154
155                         if (((object)left) == null || ((object)right) == null)
156                                 return true;
157
158                         return !left.Equals (right);
159                 }
160                 
161                 void ParseFrameworkName (string frameworkName)
162                 {
163                         string[] parts = frameworkName.Split (',');
164                         int len = parts.Length;
165
166                         if (len < 2 || len > 3)
167                                 throw new ArgumentException ("FrameworkName cannot have less than two components or more than three components.");
168
169                         bool invalid = false;
170                         string part;
171                         string[] splitPart;
172                         int splen;
173                         
174                         for (int i = 0; i < len; i++) {
175                                 part = parts [i].Trim ();
176                                 if (part.Length == 0) {
177                                         invalid = true;
178                                         break;
179                                 }
180
181                                 splitPart = part.Split ('=');
182                                 splen = splitPart.Length;
183                                 
184                                 if (String.Compare ("version", splitPart [0], StringComparison.OrdinalIgnoreCase) == 0) {
185                                         if (i == 0 || splen != 2) {
186                                                 invalid = true;
187                                                 break;
188                                         }                                       
189
190                                         try {
191                                                 char first = splitPart [1][0];
192                                                 if (first == 'v' || first == 'V')
193                                                         splitPart [1] = splitPart [1].Substring (1);
194                                                 this.Version = new Version (splitPart [1]);
195                                         } catch (Exception ex) {
196                                                 throw new ArgumentException ("FrameworkName version component is invalid.", ex);
197                                         }                                       
198
199                                         continue;
200                                 }
201
202                                 if (String.Compare ("profile", splitPart [0], StringComparison.OrdinalIgnoreCase) == 0) {
203                                         if (i == 0) {
204                                                 invalid = true;
205                                                 break;
206                                         }
207
208                                         if (splen > 1)
209                                                 Profile = String.Join ("=", splitPart, 1, splen - 1);
210                                         
211                                         continue;
212                                 }
213
214                                 if (i == 0) {
215                                         Identifier = part;
216                                         continue;
217                                 }
218
219                                 invalid = true;
220                                 break;
221                         }
222
223                         if (invalid)
224                                 throw new ArgumentException ("FrameworkName is invalid.");
225
226                         if (Version == null)
227                                 throw new ArgumentException ("FrameworkName version component is missing.");
228                         
229                 }
230         }
231 }