corrade-vassal – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | vero | 1 | /* |
2 | * Copyright (c) 2006-2014, openmetaverse.org |
||
3 | * All rights reserved. |
||
4 | * |
||
5 | * - Redistribution and use in source and binary forms, with or without |
||
6 | * modification, are permitted provided that the following conditions are met: |
||
7 | * |
||
8 | * - Redistributions of source code must retain the above copyright notice, this |
||
9 | * list of conditions and the following disclaimer. |
||
10 | * - Neither the name of the openmetaverse.org nor the names |
||
11 | * of its contributors may be used to endorse or promote products derived from |
||
12 | * this software without specific prior written permission. |
||
13 | * |
||
14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||
15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
||
18 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||
19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||
20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||
21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||
22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||
23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||
24 | * POSSIBILITY OF SUCH DAMAGE. |
||
25 | */ |
||
26 | |||
27 | using System; |
||
28 | |||
29 | namespace OpenMetaverse |
||
30 | { |
||
31 | /// <summary> |
||
32 | /// A 128-bit Universally Unique Identifier, used throughout the Second |
||
33 | /// Life networking protocol |
||
34 | /// </summary> |
||
35 | [Serializable] |
||
36 | public struct UUID : IComparable<UUID>, IEquatable<UUID> |
||
37 | { |
||
38 | /// <summary>The System.Guid object this struct wraps around</summary> |
||
39 | public Guid Guid; |
||
40 | |||
41 | #region Constructors |
||
42 | |||
43 | /// <summary> |
||
44 | /// Constructor that takes a string UUID representation |
||
45 | /// </summary> |
||
46 | /// <param name="val">A string representation of a UUID, case |
||
47 | /// insensitive and can either be hyphenated or non-hyphenated</param> |
||
48 | /// <example>UUID("11f8aa9c-b071-4242-836b-13b7abe0d489")</example> |
||
49 | public UUID(string val) |
||
50 | { |
||
51 | if (String.IsNullOrEmpty(val)) |
||
52 | Guid = new Guid(); |
||
53 | else |
||
54 | Guid = new Guid(val); |
||
55 | } |
||
56 | |||
57 | /// <summary> |
||
58 | /// Constructor that takes a System.Guid object |
||
59 | /// </summary> |
||
60 | /// <param name="val">A Guid object that contains the unique identifier |
||
61 | /// to be represented by this UUID</param> |
||
62 | public UUID(Guid val) |
||
63 | { |
||
64 | Guid = val; |
||
65 | } |
||
66 | |||
67 | /// <summary> |
||
68 | /// Constructor that takes a byte array containing a UUID |
||
69 | /// </summary> |
||
70 | /// <param name="source">Byte array containing a 16 byte UUID</param> |
||
71 | /// <param name="pos">Beginning offset in the array</param> |
||
72 | public UUID(byte[] source, int pos) |
||
73 | { |
||
74 | Guid = UUID.Zero.Guid; |
||
75 | FromBytes(source, pos); |
||
76 | } |
||
77 | |||
78 | /// <summary> |
||
79 | /// Constructor that takes an unsigned 64-bit unsigned integer to |
||
80 | /// convert to a UUID |
||
81 | /// </summary> |
||
82 | /// <param name="val">64-bit unsigned integer to convert to a UUID</param> |
||
83 | public UUID(ulong val) |
||
84 | { |
||
85 | byte[] end = BitConverter.GetBytes(val); |
||
86 | if (!BitConverter.IsLittleEndian) |
||
87 | Array.Reverse(end); |
||
88 | |||
89 | Guid = new Guid(0, 0, 0, end); |
||
90 | } |
||
91 | |||
92 | /// <summary> |
||
93 | /// Copy constructor |
||
94 | /// </summary> |
||
95 | /// <param name="val">UUID to copy</param> |
||
96 | public UUID(UUID val) |
||
97 | { |
||
98 | Guid = val.Guid; |
||
99 | } |
||
100 | |||
101 | #endregion Constructors |
||
102 | |||
103 | #region Public Methods |
||
104 | |||
105 | /// <summary> |
||
106 | /// IComparable.CompareTo implementation |
||
107 | /// </summary> |
||
108 | public int CompareTo(UUID id) |
||
109 | { |
||
110 | return Guid.CompareTo(id.Guid); |
||
111 | } |
||
112 | |||
113 | /// <summary> |
||
114 | /// Assigns this UUID from 16 bytes out of a byte array |
||
115 | /// </summary> |
||
116 | /// <param name="source">Byte array containing the UUID to assign this UUID to</param> |
||
117 | /// <param name="pos">Starting position of the UUID in the byte array</param> |
||
118 | public void FromBytes(byte[] source, int pos) |
||
119 | { |
||
120 | int a = (source[pos + 0] << 24) | (source[pos + 1] << 16) | (source[pos + 2] << 8) | source[pos + 3]; |
||
121 | short b = (short)((source[pos + 4] << 8) | source[pos + 5]); |
||
122 | short c = (short)((source[pos + 6] << 8) | source[pos + 7]); |
||
123 | |||
124 | Guid = new Guid(a, b, c, source[pos + 8], source[pos + 9], source[pos + 10], source[pos + 11], |
||
125 | source[pos + 12], source[pos + 13], source[pos + 14], source[pos + 15]); |
||
126 | } |
||
127 | |||
128 | /// <summary> |
||
129 | /// Returns a copy of the raw bytes for this UUID |
||
130 | /// </summary> |
||
131 | /// <returns>A 16 byte array containing this UUID</returns> |
||
132 | public byte[] GetBytes() |
||
133 | { |
||
134 | byte[] output = new byte[16]; |
||
135 | ToBytes(output, 0); |
||
136 | return output; |
||
137 | } |
||
138 | |||
139 | /// <summary> |
||
140 | /// Writes the raw bytes for this UUID to a byte array |
||
141 | /// </summary> |
||
142 | /// <param name="dest">Destination byte array</param> |
||
143 | /// <param name="pos">Position in the destination array to start |
||
144 | /// writing. Must be at least 16 bytes before the end of the array</param> |
||
145 | public void ToBytes(byte[] dest, int pos) |
||
146 | { |
||
147 | byte[] bytes = Guid.ToByteArray(); |
||
148 | dest[pos + 0] = bytes[3]; |
||
149 | dest[pos + 1] = bytes[2]; |
||
150 | dest[pos + 2] = bytes[1]; |
||
151 | dest[pos + 3] = bytes[0]; |
||
152 | dest[pos + 4] = bytes[5]; |
||
153 | dest[pos + 5] = bytes[4]; |
||
154 | dest[pos + 6] = bytes[7]; |
||
155 | dest[pos + 7] = bytes[6]; |
||
156 | Buffer.BlockCopy(bytes, 8, dest, pos + 8, 8); |
||
157 | } |
||
158 | |||
159 | /// <summary> |
||
160 | /// Calculate an LLCRC (cyclic redundancy check) for this UUID |
||
161 | /// </summary> |
||
162 | /// <returns>The CRC checksum for this UUID</returns> |
||
163 | public uint CRC() |
||
164 | { |
||
165 | uint retval = 0; |
||
166 | byte[] bytes = GetBytes(); |
||
167 | |||
168 | retval += (uint)((bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]); |
||
169 | retval += (uint)((bytes[7] << 24) + (bytes[6] << 16) + (bytes[5] << 8) + bytes[4]); |
||
170 | retval += (uint)((bytes[11] << 24) + (bytes[10] << 16) + (bytes[9] << 8) + bytes[8]); |
||
171 | retval += (uint)((bytes[15] << 24) + (bytes[14] << 16) + (bytes[13] << 8) + bytes[12]); |
||
172 | |||
173 | return retval; |
||
174 | } |
||
175 | |||
176 | /// <summary> |
||
177 | /// Create a 64-bit integer representation from the second half of this UUID |
||
178 | /// </summary> |
||
179 | /// <returns>An integer created from the last eight bytes of this UUID</returns> |
||
180 | public ulong GetULong() |
||
181 | { |
||
182 | byte[] bytes = Guid.ToByteArray(); |
||
183 | |||
184 | return (ulong) |
||
185 | ((ulong)bytes[8] + |
||
186 | ((ulong)bytes[9] << 8) + |
||
187 | ((ulong)bytes[10] << 16) + |
||
188 | ((ulong)bytes[12] << 24) + |
||
189 | ((ulong)bytes[13] << 32) + |
||
190 | ((ulong)bytes[13] << 40) + |
||
191 | ((ulong)bytes[14] << 48) + |
||
192 | ((ulong)bytes[15] << 56)); |
||
193 | } |
||
194 | |||
195 | #endregion Public Methods |
||
196 | |||
197 | #region Static Methods |
||
198 | |||
199 | /// <summary> |
||
200 | /// Generate a UUID from a string |
||
201 | /// </summary> |
||
202 | /// <param name="val">A string representation of a UUID, case |
||
203 | /// insensitive and can either be hyphenated or non-hyphenated</param> |
||
204 | /// <example>UUID.Parse("11f8aa9c-b071-4242-836b-13b7abe0d489")</example> |
||
205 | public static UUID Parse(string val) |
||
206 | { |
||
207 | return new UUID(val); |
||
208 | } |
||
209 | |||
210 | /// <summary> |
||
211 | /// Generate a UUID from a string |
||
212 | /// </summary> |
||
213 | /// <param name="val">A string representation of a UUID, case |
||
214 | /// insensitive and can either be hyphenated or non-hyphenated</param> |
||
215 | /// <param name="result">Will contain the parsed UUID if successful, |
||
216 | /// otherwise null</param> |
||
217 | /// <returns>True if the string was successfully parse, otherwise false</returns> |
||
218 | /// <example>UUID.TryParse("11f8aa9c-b071-4242-836b-13b7abe0d489", result)</example> |
||
219 | public static bool TryParse(string val, out UUID result) |
||
220 | { |
||
221 | if (String.IsNullOrEmpty(val) || |
||
222 | (val[0] == '{' && val.Length != 38) || |
||
223 | (val.Length != 36 && val.Length != 32)) |
||
224 | { |
||
225 | result = UUID.Zero; |
||
226 | return false; |
||
227 | } |
||
228 | |||
229 | try |
||
230 | { |
||
231 | result = Parse(val); |
||
232 | return true; |
||
233 | } |
||
234 | catch (Exception) |
||
235 | { |
||
236 | result = UUID.Zero; |
||
237 | return false; |
||
238 | } |
||
239 | } |
||
240 | |||
241 | /// <summary> |
||
242 | /// Combine two UUIDs together by taking the MD5 hash of a byte array |
||
243 | /// containing both UUIDs |
||
244 | /// </summary> |
||
245 | /// <param name="first">First UUID to combine</param> |
||
246 | /// <param name="second">Second UUID to combine</param> |
||
247 | /// <returns>The UUID product of the combination</returns> |
||
248 | public static UUID Combine(UUID first, UUID second) |
||
249 | { |
||
250 | // Construct the buffer that MD5ed |
||
251 | byte[] input = new byte[32]; |
||
252 | Buffer.BlockCopy(first.GetBytes(), 0, input, 0, 16); |
||
253 | Buffer.BlockCopy(second.GetBytes(), 0, input, 16, 16); |
||
254 | |||
255 | return new UUID(Utils.MD5(input), 0); |
||
256 | } |
||
257 | |||
258 | /// <summary> |
||
259 | /// |
||
260 | /// </summary> |
||
261 | /// <returns></returns> |
||
262 | public static UUID Random() |
||
263 | { |
||
264 | return new UUID(Guid.NewGuid()); |
||
265 | } |
||
266 | |||
267 | #endregion Static Methods |
||
268 | |||
269 | #region Overrides |
||
270 | |||
271 | /// <summary> |
||
272 | /// Return a hash code for this UUID, used by .NET for hash tables |
||
273 | /// </summary> |
||
274 | /// <returns>An integer composed of all the UUID bytes XORed together</returns> |
||
275 | public override int GetHashCode() |
||
276 | { |
||
277 | return Guid.GetHashCode(); |
||
278 | } |
||
279 | |||
280 | /// <summary> |
||
281 | /// Comparison function |
||
282 | /// </summary> |
||
283 | /// <param name="o">An object to compare to this UUID</param> |
||
284 | /// <returns>True if the object is a UUID and both UUIDs are equal</returns> |
||
285 | public override bool Equals(object o) |
||
286 | { |
||
287 | if (!(o is UUID)) return false; |
||
288 | |||
289 | UUID uuid = (UUID)o; |
||
290 | return Guid == uuid.Guid; |
||
291 | } |
||
292 | |||
293 | /// <summary> |
||
294 | /// Comparison function |
||
295 | /// </summary> |
||
296 | /// <param name="uuid">UUID to compare to</param> |
||
297 | /// <returns>True if the UUIDs are equal, otherwise false</returns> |
||
298 | public bool Equals(UUID uuid) |
||
299 | { |
||
300 | return Guid == uuid.Guid; |
||
301 | } |
||
302 | |||
303 | /// <summary> |
||
304 | /// Get a hyphenated string representation of this UUID |
||
305 | /// </summary> |
||
306 | /// <returns>A string representation of this UUID, lowercase and |
||
307 | /// with hyphens</returns> |
||
308 | /// <example>11f8aa9c-b071-4242-836b-13b7abe0d489</example> |
||
309 | public override string ToString() |
||
310 | { |
||
311 | if (Guid == Guid.Empty) |
||
312 | return ZeroString; |
||
313 | else |
||
314 | return Guid.ToString(); |
||
315 | } |
||
316 | |||
317 | #endregion Overrides |
||
318 | |||
319 | #region Operators |
||
320 | |||
321 | /// <summary> |
||
322 | /// Equals operator |
||
323 | /// </summary> |
||
324 | /// <param name="lhs">First UUID for comparison</param> |
||
325 | /// <param name="rhs">Second UUID for comparison</param> |
||
326 | /// <returns>True if the UUIDs are byte for byte equal, otherwise false</returns> |
||
327 | public static bool operator ==(UUID lhs, UUID rhs) |
||
328 | { |
||
329 | return lhs.Guid == rhs.Guid; |
||
330 | } |
||
331 | |||
332 | /// <summary> |
||
333 | /// Not equals operator |
||
334 | /// </summary> |
||
335 | /// <param name="lhs">First UUID for comparison</param> |
||
336 | /// <param name="rhs">Second UUID for comparison</param> |
||
337 | /// <returns>True if the UUIDs are not equal, otherwise true</returns> |
||
338 | public static bool operator !=(UUID lhs, UUID rhs) |
||
339 | { |
||
340 | return !(lhs == rhs); |
||
341 | } |
||
342 | |||
343 | /// <summary> |
||
344 | /// XOR operator |
||
345 | /// </summary> |
||
346 | /// <param name="lhs">First UUID</param> |
||
347 | /// <param name="rhs">Second UUID</param> |
||
348 | /// <returns>A UUID that is a XOR combination of the two input UUIDs</returns> |
||
349 | public static UUID operator ^(UUID lhs, UUID rhs) |
||
350 | { |
||
351 | byte[] lhsbytes = lhs.GetBytes(); |
||
352 | byte[] rhsbytes = rhs.GetBytes(); |
||
353 | byte[] output = new byte[16]; |
||
354 | |||
355 | for (int i = 0; i < 16; i++) |
||
356 | { |
||
357 | output[i] = (byte)(lhsbytes[i] ^ rhsbytes[i]); |
||
358 | } |
||
359 | |||
360 | return new UUID(output, 0); |
||
361 | } |
||
362 | |||
363 | /// <summary> |
||
364 | /// String typecasting operator |
||
365 | /// </summary> |
||
366 | /// <param name="val">A UUID in string form. Case insensitive, |
||
367 | /// hyphenated or non-hyphenated</param> |
||
368 | /// <returns>A UUID built from the string representation</returns> |
||
369 | public static explicit operator UUID(string val) |
||
370 | { |
||
371 | return new UUID(val); |
||
372 | } |
||
373 | |||
374 | #endregion Operators |
||
375 | |||
376 | /// <summary>An UUID with a value of all zeroes</summary> |
||
377 | public static readonly UUID Zero = new UUID(); |
||
378 | |||
379 | /// <summary>A cache of UUID.Zero as a string to optimize a common path</summary> |
||
380 | private static readonly string ZeroString = Guid.Empty.ToString(); |
||
381 | } |
||
382 | } |