2009-04-14 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / System.Runtime.Serialization / System.Xml / UniqueId.cs
1 //
2 // UniqueId.cs
3 //
4 // Author:
5 //      Atsushi Enomoto <atsushi@ximian.com>
6 //      Jonathan Pryor <jpryor@novell.com>
7 //
8 // Copyright (C) 2005,2007,2009 Novell, Inc.  http://www.novell.com
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29 #if NET_2_0
30 using System;
31 using System.Collections.Generic;
32 using System.Security;
33
34 namespace System.Xml
35 {
36         public class UniqueId
37         {
38                 Guid guid;
39                 string id;
40
41                 public UniqueId ()
42                         : this (Guid.NewGuid ())
43                 {
44                 }
45
46                 public UniqueId (byte [] id)
47                         : this (id, 0)
48                 {
49                 }
50
51                 [SecuritySafeCritical]
52                 [SecurityTreatAsSafe]
53                 public UniqueId (Guid id)
54                 {
55                         this.guid = id;
56                 }
57
58                 public UniqueId (string value)
59                 {
60                         if (value == null)
61                                 throw new ArgumentNullException ("value cannot be null", "value");
62
63                         if (value.Length == 0)
64                                 throw new FormatException ("UniqueId cannot be zero length");
65
66                         this.id = value;
67                 }
68
69                 [SecuritySafeCritical]
70                 [SecurityTreatAsSafe]
71                 public UniqueId (byte [] id, int offset)
72                 {
73                         if (id == null)
74                                 throw new ArgumentNullException ();
75                         if (offset < 0)
76                                 throw new ArgumentOutOfRangeException ("offset");
77                         if (offset >= id.Length)
78                                 throw new ArgumentException ("id too small.", "offset");
79
80                         if (id.Length - offset != 16)
81                                 throw new ArgumentException ("id and offset provide less than 16 bytes");
82
83                         if (offset == 0)
84                                 guid = new Guid (id);
85                         else {
86                                 List<byte> buf = new List<byte> (id);
87                                 buf.RemoveRange (0, offset);
88                                 guid = new Guid (buf.ToArray ());
89                         }
90                 }
91
92                 [SecuritySafeCritical]
93                 [SecurityTreatAsSafe]
94                 public UniqueId (char [] id, int offset, int count)
95                 {
96                         if (id == null)
97                                 throw new ArgumentNullException ("id");
98                         if (offset < 0 || offset >= id.Length)
99                                 throw new ArgumentOutOfRangeException ("offset");
100                         if (count < 0 || id.Length - offset < count)
101                                 throw new ArgumentOutOfRangeException ("count");
102                         if (count == 0)
103                                 throw new FormatException ();
104
105                         // Does it start with "urn:uuid:"?  If so, it's a Guid.
106                         if (count > 8 && id [offset] == 'u' && id [offset+1] == 'r' && 
107                                         id [offset+2] == 'n' && id [offset+3] == ':' &&
108                                         id [offset+4] == 'u' && id [offset+5] == 'u' &&
109                                         id [offset+6] == 'i' && id [offset+7] == 'd' &&
110                                         id [offset+8] == ':') {
111                                 if (count != 45)
112                                         throw new ArgumentOutOfRangeException ("Invalid Guid");
113                                 this.guid = new Guid (new string (id, offset+9, count-9));
114                         } else
115                                 this.id = new string (id, offset, count);
116                 }
117
118                 [SecuritySafeCritical]
119                 [SecurityTreatAsSafe]
120                 public int CharArrayLength {
121                         get {return id != null ? id.Length : 45;}
122                 }
123
124                 public bool IsGuid {
125                         get { return guid != default (Guid); }
126                 }
127
128                 public override bool Equals (Object obj)
129                 {
130                         UniqueId other = obj as UniqueId;
131
132                         if (other == null)
133                                 return false;
134
135                         if (IsGuid && other.IsGuid) {
136                                 return guid.Equals (other.guid);
137                         }
138
139                         return id == other.id;
140                 }
141
142                 [SecuritySafeCritical]
143                 [SecurityTreatAsSafe]
144                 [MonoTODO ("Determine semantics when IsGuid==true")]
145                 public override int GetHashCode ()
146                 {
147                         return id != null ? id.GetHashCode () : guid.GetHashCode ();
148                 }
149
150                 public static bool operator == (UniqueId id1, UniqueId id2)
151                 {
152                         return object.Equals (id1, id2);
153                 }
154
155                 public static bool operator != (UniqueId id1, UniqueId id2)
156                 {
157                         return ! (id1 == id2);
158                 }
159
160                 [SecuritySafeCritical]
161                 [SecurityTreatAsSafe]
162                 public int ToCharArray (char [] array, int offset)
163                 {
164                         if (array == null)
165                                 throw new ArgumentNullException ("array");
166                         if (offset < 0 || offset >= array.Length)
167                                 throw new ArgumentOutOfRangeException ("offset");
168
169                         string s = ToString ();
170                         s.CopyTo (0, array, offset, s.Length);
171                         return s.Length;
172                 }
173
174                 public override string ToString ()
175                 {
176                         if (id == null)
177                                 return "urn:uuid:" + guid;
178
179                         return id;
180                 }
181
182                 public bool TryGetGuid (out Guid guid)
183                 {
184                         if (IsGuid) {
185                                 guid = this.guid;
186                                 return true;
187                         } else {
188                                 guid = default (Guid);
189                                 return false;
190                         }
191                 }
192
193                 [SecuritySafeCritical]
194                 [SecurityTreatAsSafe]
195                 public bool TryGetGuid (byte [] buffer, int offset)
196                 {
197                         if (!IsGuid)
198                                 return false;
199
200                         if (buffer == null)
201                                 throw new ArgumentNullException ("buffer");
202                         if (offset < 0 || offset >= buffer.Length)
203                                 throw new ArgumentOutOfRangeException ("offset");
204                         if (buffer.Length - offset < 16)
205                                 throw new ArgumentOutOfRangeException ("offset");
206
207                         guid.ToByteArray ().CopyTo (buffer, offset);
208                         return true;
209                 }
210         }
211 }
212 #endif