// Copyright (C) 2004-2010 Novell, Inc (http://www.novell.com)
// Copyright 2012, 2014 Xamarin, Inc (http://www.xamarin.com)
//
-// References
-// 1. UUIDs and GUIDs (DRAFT), Section 3.4
-// http://www.ics.uci.edu/~ejw/authoring/uuid-guid/draft-leach-uuids-guids-01.txt
-//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-using System.Runtime.InteropServices;
-using System.Security.Cryptography;
-using System.Text;
-#if MONOTOUCH && FULL_AOT_RUNTIME
-using Crimson.CommonCrypto;
-#endif
-
-namespace System {
-
- [Serializable]
- [StructLayout (LayoutKind.Sequential)]
- [ComVisible (true)]
- public struct Guid : IFormattable, IComparable, IComparable<Guid>, IEquatable<Guid> {
-#if MONOTOUCH
- static Guid () {
- if (MonoTouchAOTHelper.FalseFlag) {
- var comparer = new System.Collections.Generic.GenericComparer <Guid> ();
- var eqcomparer = new System.Collections.Generic.GenericEqualityComparer <Guid> ();
- }
- }
-#endif
- private int _a; //_timeLow;
- private short _b; //_timeMid;
- private short _c; //_timeHighAndVersion;
- private byte _d; //_clockSeqHiAndReserved;
- private byte _e; //_clockSeqLow;
- private byte _f; //_node0;
- private byte _g; //_node1;
- private byte _h; //_node2;
- private byte _i; //_node3;
- private byte _j; //_node4;
- private byte _k; //_node5;
-
- enum Format {
- N, // 00000000000000000000000000000000
- D, // 00000000-0000-0000-0000-000000000000
- B, // {00000000-0000-0000-0000-000000000000}
- P, // (00000000-0000-0000-0000-000000000000)
- X, // {0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
- }
-
- struct GuidParser
- {
- private string _src;
- private int _length;
- private int _cur;
-
- public GuidParser (string src)
- {
- _src = src.Trim ();
- _cur = 0;
- _length = _src.Length;
- }
-
- void Reset ()
- {
- _cur = 0;
- _length = _src.Length;
- }
-
- bool Eof {
- get { return _cur >= _length; }
- }
-
- public static bool HasHyphen (Format format)
- {
- switch (format) {
- case Format.D:
- case Format.B:
- case Format.P:
- return true;
- default:
- return false;
- }
- }
-
- bool TryParseNDBP (Format format, out Guid guid)
- {
- ulong a, b, c;
- guid = new Guid ();
-
- if (format == Format.B && !ParseChar ('{'))
- return false;
-
- if (format == Format.P && !ParseChar ('('))
- return false;
-
- if (!ParseHex (8, true, out a))
- return false;
-
- var has_hyphen = HasHyphen (format);
-
- if (has_hyphen && !ParseChar ('-'))
- return false;
-
- if (!ParseHex (4, true, out b))
- return false;
-
- if (has_hyphen && !ParseChar ('-'))
- return false;
-
- if (!ParseHex (4, true, out c))
- return false;
-
- if (has_hyphen && !ParseChar ('-'))
- return false;
-
- var d = new byte [8];
- for (int i = 0; i < d.Length; i++) {
- ulong dd;
- if (!ParseHex (2, true, out dd))
- return false;
-
- if (i == 1 && has_hyphen && !ParseChar ('-'))
- return false;
-
- d [i] = (byte) dd;
- }
-
- if (format == Format.B && !ParseChar ('}'))
- return false;
-
- if (format == Format.P && !ParseChar (')'))
- return false;
-
- if (!Eof)
- return false;
-
- guid = new Guid ((int) a, (short) b, (short) c, d);
- return true;
- }
-
- bool TryParseX (out Guid guid)
- {
- ulong a, b, c;
- guid = new Guid ();
-
- if (!(ParseChar ('{')
- && ParseHexPrefix ()
- && ParseHex (8, false, out a)
- && ParseCharWithWhiteSpaces (',')
- && ParseHexPrefix ()
- && ParseHex (4, false, out b)
- && ParseCharWithWhiteSpaces (',')
- && ParseHexPrefix ()
- && ParseHex (4, false, out c)
- && ParseCharWithWhiteSpaces (',')
- && ParseCharWithWhiteSpaces ('{'))) {
-
- return false;
- }
-
- var d = new byte [8];
- for (int i = 0; i < d.Length; ++i) {
- ulong dd;
-
- if (!(ParseHexPrefix () && ParseHex (2, false, out dd)))
- return false;
-
- d [i] = (byte) dd;
-
- if (i != 7 && !ParseCharWithWhiteSpaces (','))
- return false;
- }
-
- if (!(ParseCharWithWhiteSpaces ('}') && ParseCharWithWhiteSpaces ('}')))
- return false;
-
- if (!Eof)
- return false;
-
- guid = new Guid ((int) a, (short) b, (short) c, d);
- return true;
- }
-
- bool ParseHexPrefix ()
- {
- // It can be prefixed with whitespaces
- for (; _cur < _length - 1; ++_cur) {
- var ch = _src [_cur];
- if (ch == '0') {
- ++_cur;
- return _src [_cur++] == 'x';
- }
-
- if (!char.IsWhiteSpace (ch))
- break;
- }
-
- return false;
- }
-
- bool ParseCharWithWhiteSpaces (char c)
- {
- while (!Eof) {
- var ch = _src [_cur++];
- if (ch == c)
- return true;
-
- if (!char.IsWhiteSpace (ch))
- break;
- }
-
- return false;
- }
-
- bool ParseChar (char c)
- {
- if (!Eof && _src [_cur] == c) {
- _cur++;
- return true;
- }
-
- return false;
- }
-
- bool ParseHex (int length, bool strict, out ulong res)
- {
- res = 0;
-
- for (int i = 0; i < length; i++) {
- if (Eof)
- return !(strict && (i + 1 != length));
-
- char c = _src [_cur];
- if (Char.IsDigit (c)) {
- res = res * 16 + c - '0';
- _cur++;
- continue;
- }
-
- if (c >= 'a' && c <= 'f') {
- res = res * 16 + c - 'a' + 10;
- _cur++;
- continue;
- }
-
- if (c >= 'A' && c <= 'F') {
- res = res * 16 + c - 'A' + 10;
- _cur++;
- continue;
- }
-
- if (!strict)
- return true;
-
- return false; //!(strict && (i + 1 != length));
- }
-
- return true;
- }
-
- public bool Parse (Format format, out Guid guid)
- {
- if (format == Format.X)
- return TryParseX (out guid);
-
- return TryParseNDBP (format, out guid);
- }
-
- public bool Parse (out Guid guid)
- {
- switch (_length) {
- case 32:
- if (TryParseNDBP (Format.N, out guid))
- return true;
- break;
- case 36:
- if (TryParseNDBP (Format.D, out guid))
- return true;
- break;
- case 38:
- switch (_src [0]) {
- case '{':
- if (TryParseNDBP (Format.B, out guid))
- return true;
- break;
- case '(':
- if (TryParseNDBP (Format.P, out guid))
- return true;
- break;
- }
- break;
- }
-
- Reset ();
- return TryParseX (out guid);
- }
- }
-
- private static void CheckNull (object o)
- {
- if (o == null) {
- throw new ArgumentNullException (Locale.GetText ("Value cannot be null."));
- }
- }
-
- private static void CheckLength (byte[] o, int l)
- {
- if (o . Length != l) {
- throw new ArgumentException (String.Format (Locale.GetText ("Array should be exactly {0} bytes long."), l));
- }
- }
-
- private static void CheckArray (byte[] o, int l)
- {
- CheckNull (o);
- CheckLength (o, l);
- }
-
- public Guid (byte[] b)
- {
- CheckArray (b, 16);
- _a = Mono.Security.BitConverterLE.ToInt32 (b, 0);
- _b = Mono.Security.BitConverterLE.ToInt16 (b, 4);
- _c = Mono.Security.BitConverterLE.ToInt16 (b, 6);
- _d = b [8];
- _e = b [9];
- _f = b [10];
- _g = b [11];
- _h = b [12];
- _i = b [13];
- _j = b [14];
- _k = b [15];
- }
-
- public Guid (string g)
- {
- CheckNull (g);
- Guid guid;
- if (!new GuidParser (g).Parse (out guid))
- throw CreateFormatException (g);
-
- this = guid;
- }
-
- static Exception CreateFormatException (string s)
- {
- return new FormatException (string.Format ("Invalid Guid format: {0}", s));
- }
-
- public Guid (int a, short b, short c, byte[] d)
- {
- CheckArray (d, 8);
- _a = (int) a;
- _b = (short) b;
- _c = (short) c;
- _d = d [0];
- _e = d [1];
- _f = d [2];
- _g = d [3];
- _h = d [4];
- _i = d [5];
- _j = d [6];
- _k = d [7];
- }
-
- public Guid (int a, short b, short c, byte d, byte e, byte f, byte g, byte h, byte i, byte j, byte k)
- {
- _a = a;
- _b = b;
- _c = c;
- _d = d;
- _e = e;
- _f = f;
- _g = g;
- _h = h;
- _i = i;
- _j = j;
- _k = k;
- }
-
- [CLSCompliant (false)]
- public Guid (uint a, ushort b, ushort c, byte d, byte e, byte f, byte g, byte h, byte i, byte j, byte k)
- : this((int) a, (short) b, (short) c, d, e, f, g, h, i, j, k)
- {
- }
-
- public static readonly Guid Empty = new Guid (0,0,0,0,0,0,0,0,0,0,0);
-
- private static int Compare (int x, int y)
- {
- return ((uint)x < (uint)y) ? -1 : 1;
- }
-
- public int CompareTo (object value)
- {
- if (value == null)
- return 1;
-
- if (!(value is Guid)) {
- throw new ArgumentException ("value", Locale.GetText (
- "Argument of System.Guid.CompareTo should be a Guid."));
- }
-
- return CompareTo ((Guid)value);
- }
-
- public override bool Equals (object o)
- {
- if (o is Guid)
- return CompareTo ((Guid)o) == 0;
- return false;
- }
-
- public int CompareTo (Guid value)
- {
- if (_a != value._a) {
- return Compare (_a, value._a);
- }
- if (_b != value._b) {
- return Compare (_b, value._b);
- }
- if (_c != value._c) {
- return Compare (_c, value._c);
- }
- if (_d != value._d) {
- return Compare (_d, value._d);
- }
- if (_e != value._e) {
- return Compare (_e, value._e);
- }
- if (_f != value._f) {
- return Compare (_f, value._f);
- }
- if (_g != value._g) {
- return Compare (_g, value._g);
- }
- if (_h != value._h) {
- return Compare (_h, value._h);
- }
- if (_i != value._i) {
- return Compare (_i, value._i);
- }
- if (_j != value._j) {
- return Compare (_j, value._j);
- }
- if (_k != value._k) {
- return Compare (_k, value._k);
- }
- return 0;
- }
-
- public bool Equals (Guid g)
- {
- return CompareTo (g) == 0;
- }
-
- public override int GetHashCode ()
- {
- int res;
-
- res = (int) _a;
- res = res ^ ((int) _b << 16 | _c);
- res = res ^ ((int) _d << 24);
- res = res ^ ((int) _e << 16);
- res = res ^ ((int) _f << 8);
- res = res ^ ((int) _g);
- res = res ^ ((int) _h << 24);
- res = res ^ ((int) _i << 16);
- res = res ^ ((int) _j << 8);
- res = res ^ ((int) _k);
-
- return res;
- }
+#if !FULL_AOT_RUNTIME
- private static char ToHex (int b)
- {
- return (char)((b<0xA)?('0' + b):('a' + b - 0xA));
- }
+using System.Security.Cryptography;
-#if !FULL_AOT_RUNTIME
+namespace System
+{
+ partial struct Guid
+ {
private static object _rngAccess = new object ();
private static RandomNumberGenerator _rng;
private static RandomNumberGenerator _fastRng;
-#endif
-#if FULL_AOT_RUNTIME && !MONOTOUCH
- // NSA approved random generator.
- static void LameRandom (byte [] b)
- {
- var r = new Random ();
- r.NextBytes (b);
- }
-#endif
-
- // generated as per section 3.4 of the specification
public static Guid NewGuid ()
{
byte[] b = new byte [16];
-#if !FULL_AOT_RUNTIME
// thread-safe access to the prng
lock (_rngAccess) {
if (_rng == null)
_rng = RandomNumberGenerator.Create ();
_rng.GetBytes (b);
}
-#elif MONOTOUCH
- Cryptor.GetRandom (b);
-#else
- LameRandom (b);
-#endif
Guid res = new Guid (b);
// Mask in Variant 1-0 in Bit[7..6]
return res;
}
-#if !FULL_AOT_RUNTIME
// used in ModuleBuilder so mcs doesn't need to invoke
// CryptoConfig for simple assemblies.
internal static byte[] FastNewGuidArray ()
return guid;
}
-#endif
- public byte[] ToByteArray ()
- {
- byte[] res = new byte[16];
- byte[] tmp;
- int d = 0;
- int s;
-
- tmp = Mono.Security.BitConverterLE.GetBytes(_a);
- for (s=0; s<4; ++s) {
- res[d++] = tmp[s];
- }
-
- tmp = Mono.Security.BitConverterLE.GetBytes(_b);
- for (s=0; s<2; ++s) {
- res[d++] = tmp[s];
- }
-
- tmp = Mono.Security.BitConverterLE.GetBytes(_c);
- for (s=0; s<2; ++s) {
- res[d++] = tmp[s];
- }
-
- res[8] = _d;
- res[9] = _e;
- res[10] = _f;
- res[11] = _g;
- res[12] = _h;
- res[13] = _i;
- res[14] = _j;
- res[15] = _k;
-
- return res;
- }
-
- static void AppendInt (StringBuilder builder, int value) {
- builder.Append (ToHex ((value >> 28) & 0xf));
- builder.Append (ToHex ((value >> 24) & 0xf));
- builder.Append (ToHex ((value >> 20) & 0xf));
- builder.Append (ToHex ((value >> 16) & 0xf));
- builder.Append (ToHex ((value >> 12) & 0xf));
- builder.Append (ToHex ((value >> 8) & 0xf));
- builder.Append (ToHex ((value >> 4) & 0xf));
- builder.Append (ToHex (value & 0xf));
- }
-
- static void AppendShort (StringBuilder builder, short value) {
- builder.Append (ToHex ((value >> 12) & 0xf));
- builder.Append (ToHex ((value >> 8) & 0xf));
- builder.Append (ToHex ((value >> 4) & 0xf));
- builder.Append (ToHex (value & 0xf));
- }
-
- static void AppendByte (StringBuilder builder, byte value) {
- builder.Append (ToHex ((value >> 4) & 0xf));
- builder.Append (ToHex (value & 0xf));
- }
-
- string ToString (Format format)
- {
- int length;
- switch (format) {
- case Format.B:
- case Format.P:
- length = 38;
- break;
- case Format.D:
- length = 36;
- break;
- case Format.N:
- length = 32;
- break;
- case Format.X:
- length = 68;
- break;
- default:
- throw new NotImplementedException (format.ToString ());
- }
-
- StringBuilder res = new StringBuilder (length);
- bool has_hyphen = GuidParser.HasHyphen (format);
-
- if (format == Format.P) {
- res.Append ('(');
- } else if (format == Format.B) {
- res.Append ('{');
- } else if (format == Format.X) {
- res.Append ('{').Append ('0').Append ('x');
- }
-
- AppendInt (res, _a);
- if (has_hyphen) {
- res.Append ('-');
- } else if (format == Format.X) {
- res.Append (',').Append ('0').Append ('x');
- }
-
- AppendShort (res, _b);
- if (has_hyphen) {
- res.Append ('-');
- } else if (format == Format.X) {
- res.Append (',').Append ('0').Append ('x');
- }
-
- AppendShort (res, _c);
- if (has_hyphen) {
- res.Append ('-');
- }
-
- if (format == Format.X) {
- res.Append (',').Append ('{').Append ('0').Append ('x');
- AppendByte (res, _d);
- res.Append (',').Append ('0').Append ('x');
- AppendByte (res, _e);
- res.Append (',').Append ('0').Append ('x');
- AppendByte (res, _f);
- res.Append (',').Append ('0').Append ('x');
- AppendByte (res, _g);
- res.Append (',').Append ('0').Append ('x');
- AppendByte (res, _h);
- res.Append (',').Append ('0').Append ('x');
- AppendByte (res, _i);
- res.Append (',').Append ('0').Append ('x');
- AppendByte (res, _j);
- res.Append (',').Append ('0').Append ('x');
- AppendByte (res, _k);
- res.Append ('}').Append ('}');;
- } else {
- AppendByte (res, _d);
- AppendByte (res, _e);
-
- if (has_hyphen) {
- res.Append ('-');
- }
-
- AppendByte (res, _f);
- AppendByte (res, _g);
- AppendByte (res, _h);
- AppendByte (res, _i);
- AppendByte (res, _j);
- AppendByte (res, _k);
-
- if (format == Format.P) {
- res.Append (')');
- } else if (format == Format.B) {
- res.Append ('}');
- }
- }
-
- return res.ToString ();
- }
-
- public override string ToString ()
- {
- return ToString (Format.D);
- }
-
- public string ToString (string format)
- {
- return ToString (ParseFormat (format));
- }
-
- // provider value is never used
- public string ToString (string format, IFormatProvider provider)
- {
- return ToString (format);
- }
-
- public static bool operator == (Guid a, Guid b)
- {
- return a.Equals(b);
- }
-
- public static bool operator != (Guid a, Guid b)
- {
- return !( a.Equals (b) );
- }
-
- public static Guid Parse (string input)
- {
- if (input == null)
- throw new ArgumentNullException ("input");
-
- Guid guid;
- if (!TryParse (input, out guid))
- throw CreateFormatException (input);
-
- return guid;
- }
-
- public static Guid ParseExact (string input, string format)
- {
- if (input == null)
- throw new ArgumentNullException ("input");
- if (format == null)
- throw new ArgumentNullException ("format");
-
- Guid guid;
- if (!TryParseExact (input, format, out guid))
- throw CreateFormatException (input);
-
- return guid;
- }
-
- public static bool TryParse (string input, out Guid result)
- {
- if (input == null) {
- result = Empty;
- return false;
- }
-
- var parser = new GuidParser (input);
- return parser.Parse (out result);
- }
-
- public static bool TryParseExact (string input, string format, out Guid result)
- {
- if (input == null || format == null) {
- result = Empty;
- return false;
- }
-
- var parser = new GuidParser (input);
- return parser.Parse (ParseFormat (format), out result);
- }
-
- static Format ParseFormat (string format)
- {
- if (string.IsNullOrEmpty (format))
- return Format.D;
-
- switch (format [0]) {
- case 'N':
- case 'n':
- return Format.N;
- case 'D':
- case 'd':
- return Format.D;
- case 'B':
- case 'b':
- return Format.B;
- case 'P':
- case 'p':
- return Format.P;
- case 'X':
- case 'x':
- return Format.X;
- }
-
- throw new FormatException (
- "Format String can be only one of \"D\", \"d\", \"N\", \"n\", \"P\", \"p\", \"B\", \"b\", \"X\" or \"x\""
- );
- }
}
}
+
+#endif
\ No newline at end of file