corrade-vassal – Blame information for rev 1

Subversion Repositories:
Rev:
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 }