Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
ObjectId.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Runtime.InteropServices;
5 
6 namespace SiliconStudio.Core.Storage
7 {
8  /// <summary>
9  /// A hash to uniquely identify data.
10  /// </summary>
11  [StructLayout(LayoutKind.Sequential, Pack = 4)]
12  [DataContract("ObjectId")]
13  public unsafe partial struct ObjectId : IEquatable<ObjectId>, IComparable<ObjectId>
14  {
15  public static readonly ObjectId Empty = new ObjectId();
16 
17  // SHA1 hash size is 160 bits.
18  public const int HashSize = 16;
19  public const int HashStringLength = HashSize * 2;
20  private const int HashSizeInUInt = HashSize / sizeof(uint);
21  private const string HexDigits = "0123456789abcdef";
22  private uint hash1, hash2, hash3, hash4;
23 
24  /// <summary>
25  /// Initializes a new instance of the <see cref="ObjectId"/> struct.
26  /// </summary>
27  /// <param name="hash">The hash.</param>
28  /// <exception cref="System.ArgumentNullException">hash</exception>
29  /// <exception cref="System.InvalidOperationException">ObjectId value doesn't match expected size.</exception>
30  public ObjectId(byte[] hash)
31  {
32  if (hash == null) throw new ArgumentNullException("hash");
33 
34  if (hash.Length != HashSize)
35  throw new InvalidOperationException("ObjectId value doesn't match expected size.");
36 
37  fixed (byte* hashSource = hash)
38  {
39  var hashSourceCurrent = (uint*)hashSource;
40  hash1 = *hashSourceCurrent++;
41  hash2 = *hashSourceCurrent++;
42  hash3 = *hashSourceCurrent++;
43  hash4 = *hashSourceCurrent;
44  }
45  }
46 
47  public ObjectId(uint hash1, uint hash2, uint hash3, uint hash4)
48  {
49  this.hash1 = hash1;
50  this.hash2 = hash2;
51  this.hash3 = hash3;
52  this.hash4 = hash4;
53  }
54 
55  /// <summary>
56  /// Performs an explicit conversion from <see cref="ObjectId"/> to <see cref="byte[]"/>.
57  /// </summary>
58  /// <param name="objectId">The object id.</param>
59  /// <returns>The result of the conversion.</returns>
60  public static explicit operator byte[](ObjectId objectId)
61  {
62  var result = new byte[HashSize];
63  var hashSource = &objectId.hash1;
64  fixed (byte* hashDest = result)
65  {
66  var hashSourceCurrent = (uint*)hashSource;
67  var hashDestCurrent = (uint*)hashDest;
68  for (int i = 0; i < HashSizeInUInt; ++i)
69  *hashDestCurrent++ = *hashSourceCurrent++;
70  }
71  return result;
72  }
73 
74  /// <summary>
75  /// Implements the ==.
76  /// </summary>
77  /// <param name="left">The left.</param>
78  /// <param name="right">The right.</param>
79  /// <returns>The result of the operator.</returns>
80  public static bool operator ==(ObjectId left, ObjectId right)
81  {
82  return left.Equals(right);
83  }
84 
85  /// <summary>
86  /// Implements the !=.
87  /// </summary>
88  /// <param name="left">The left.</param>
89  /// <param name="right">The right.</param>
90  /// <returns>The result of the operator.</returns>
91  public static bool operator !=(ObjectId left, ObjectId right)
92  {
93  return !left.Equals(right);
94  }
95 
96  /// <summary>
97  /// Tries to parse an <see cref="ObjectId"/> from a string.
98  /// </summary>
99  /// <param name="input">The input hexa string.</param>
100  /// <param name="result">The result ObjectId.</param>
101  /// <returns><c>true</c> if parsing was successfull, <c>false</c> otherwise</returns>
102  public static bool TryParse(string input, out ObjectId result)
103  {
104  if (input.Length != HashStringLength)
105  {
106  result = Empty;
107  return false;
108  }
109 
110  var hash = new byte[HashSize];
111  for (int i = 0; i < HashStringLength; i += 2)
112  {
113  char c1 = input[i];
114  char c2 = input[i + 1];
115 
116  int digit1, digit2;
117  if (((digit1 = HexDigits.IndexOf(c1)) == -1)
118  || ((digit2 = HexDigits.IndexOf(c2)) == -1))
119  {
120  result = Empty;
121  return false;
122  }
123 
124  hash[i >> 1] = (byte)((digit1 << 4) | digit2);
125  }
126 
127  result = new ObjectId(hash);
128  return true;
129  }
130 
131  /// <inheritdoc/>
132  public bool Equals(ObjectId other)
133  {
134  // Compare content
135  fixed (uint* xPtr = &hash1)
136  {
137  var x1 = xPtr;
138  var y1 = &other.hash1;
139 
140  for (int i = 0; i < HashSizeInUInt; ++i)
141  {
142  if (*x1++ != *y1++)
143  return false;
144  }
145  }
146 
147  return true;
148  }
149 
150  /// <inheritdoc/>
151  public override bool Equals(object obj)
152  {
153  if (ReferenceEquals(null, obj)) return false;
154  return obj is ObjectId && Equals((ObjectId)obj);
155  }
156 
157  /// <inheritdoc/>
158  public override int GetHashCode()
159  {
160  fixed (uint* objPtr = &hash1)
161  {
162  var obj1 = (int*)objPtr;
163  return *obj1;
164  }
165  }
166 
167  /// <inheritdoc/>
168  public int CompareTo(ObjectId other)
169  {
170  // Compare content
171  fixed (uint* xPtr = &hash1)
172  {
173  var x1 = xPtr;
174  var y1 = &other.hash1;
175 
176  for (int i = 0; i < HashSizeInUInt; ++i)
177  {
178  var compareResult = (*x1++).CompareTo(*y1++);
179  if (compareResult != 0)
180  return compareResult;
181  }
182  }
183 
184  return 0;
185  }
186 
187  public override string ToString()
188  {
189  var c = new char[HashStringLength];
190 
191  fixed (uint* hashStart = &hash1)
192  {
193  var hashBytes = (byte*)hashStart;
194  for (int i = 0; i < HashStringLength; ++i)
195  {
196  int index0 = i >> 1;
197  var b = ((byte)(hashBytes[index0] >> 4));
198  c[i++] = HexDigits[b];
199 
200  b = ((byte)(hashBytes[index0] & 0x0F));
201  c[i] = HexDigits[b];
202  }
203  }
204 
205  return new string(c);
206  }
207 
208  /// <summary>
209  /// Gets a <see cref="Guid"/> from this object identifier.
210  /// </summary>
211  /// <returns>Guid.</returns>
212  public Guid ToGuid()
213  {
214  fixed (void* hashStart = &hash1)
215  {
216  return *(Guid*)hashStart;
217  }
218  }
219 
220  /// <summary>
221  /// News this instance.
222  /// </summary>
223  /// <returns>ObjectId.</returns>
224  public static ObjectId New()
225  {
226  return FromBytes(Guid.NewGuid().ToByteArray());
227  }
228 
229  /// <summary>
230  /// Computes a hash from a byte buffer.
231  /// </summary>
232  /// <param name="buffer">The byte buffer.</param>
233  /// <returns>The hash of the object.</returns>
234  /// <exception cref="System.ArgumentNullException">buffer</exception>
235  public static ObjectId FromBytes(byte[] buffer)
236  {
237  if (buffer == null) throw new ArgumentNullException("buffer");
238 
239  return FromBytes(buffer, 0, buffer.Length);
240  }
241 
242  /// <summary>
243  /// Computes a hash from a byte buffer.
244  /// </summary>
245  /// <param name="buffer">The byte buffer.</param>
246  /// <param name="offset">The offset into the buffer.</param>
247  /// <param name="count">The number of bytes to read from the buffer starting at offset position.</param>
248  /// <returns>The hash of the object.</returns>
249  /// <exception cref="System.ArgumentNullException">buffer</exception>
250  public static ObjectId FromBytes(byte[] buffer, int offset, int count)
251  {
252  if (buffer == null) throw new ArgumentNullException("buffer");
253 
254  var builder = new ObjectIdBuilder();
255  builder.Write(buffer, offset, count);
256  return builder.ComputeHash();
257  }
258  }
259 }
static ObjectId New()
News this instance.
Definition: ObjectId.cs:224
function b
bool Equals(ObjectId other)
Definition: ObjectId.cs:132
ObjectId(byte[] hash)
Initializes a new instance of the ObjectId struct.
Definition: ObjectId.cs:30
override bool Equals(object obj)
Definition: ObjectId.cs:151
Guid ToGuid()
Gets a Guid from this object identifier.
Definition: ObjectId.cs:212
_In_ size_t count
Definition: DirectXTexP.h:174
A hash to uniquely identify data.
Definition: ObjectId.cs:13
int CompareTo(ObjectId other)
Definition: ObjectId.cs:168
static bool TryParse(string input, out ObjectId result)
Tries to parse an ObjectId from a string.
Definition: ObjectId.cs:102
static ObjectId FromBytes(byte[] buffer, int offset, int count)
Computes a hash from a byte buffer.
Definition: ObjectId.cs:250
static ObjectId FromBytes(byte[] buffer)
Computes a hash from a byte buffer.
Definition: ObjectId.cs:235
ObjectId(uint hash1, uint hash2, uint hash3, uint hash4)
Definition: ObjectId.cs:47