diff options
Diffstat (limited to 'src/mscorlib/src/System/Guid.cs')
-rw-r--r-- | src/mscorlib/src/System/Guid.cs | 1290 |
1 files changed, 1290 insertions, 0 deletions
diff --git a/src/mscorlib/src/System/Guid.cs b/src/mscorlib/src/System/Guid.cs new file mode 100644 index 0000000000..2dca1eb4a7 --- /dev/null +++ b/src/mscorlib/src/System/Guid.cs @@ -0,0 +1,1290 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace System { + + using System; + using System.Globalization; + using System.Text; + using Microsoft.Win32; + using System.Runtime.InteropServices; + using System.Runtime.CompilerServices; + using System.Diagnostics.Contracts; + + // Represents a Globally Unique Identifier. + [StructLayout(LayoutKind.Sequential)] + [Serializable] +[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.Versioning.NonVersionable] // This only applies to field layout + public struct Guid : IFormattable, IComparable + , IComparable<Guid>, IEquatable<Guid> + { + public static readonly Guid Empty = new Guid(); + //////////////////////////////////////////////////////////////////////////////// + // Member variables + //////////////////////////////////////////////////////////////////////////////// + private int _a; + private short _b; + private short _c; + private byte _d; + private byte _e; + private byte _f; + private byte _g; + private byte _h; + private byte _i; + private byte _j; + private byte _k; + + + + //////////////////////////////////////////////////////////////////////////////// + // Constructors + //////////////////////////////////////////////////////////////////////////////// + + // Creates a new guid from an array of bytes. + // + public Guid(byte[] b) + { + if (b==null) + throw new ArgumentNullException("b"); + if (b.Length != 16) + throw new ArgumentException(Environment.GetResourceString("Arg_GuidArrayCtor", "16")); + Contract.EndContractBlock(); + + _a = ((int)b[3] << 24) | ((int)b[2] << 16) | ((int)b[1] << 8) | b[0]; + _b = (short)(((int)b[5] << 8) | b[4]); + _c = (short)(((int)b[7] << 8) | 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]; + } + + [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) + { + _a = (int)a; + _b = (short)b; + _c = (short)c; + _d = d; + _e = e; + _f = f; + _g = g; + _h = h; + _i = i; + _j = j; + _k = k; + } + + + // Creates a new GUID initialized to the value represented by the arguments. + // + public Guid(int a, short b, short c, byte[] d) + { + if (d==null) + throw new ArgumentNullException("d"); + // Check that array is not too big + if(d.Length != 8) + throw new ArgumentException(Environment.GetResourceString("Arg_GuidArrayCtor", "8")); + Contract.EndContractBlock(); + + _a = a; + _b = b; + _c = 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]; + } + + // Creates a new GUID initialized to the value represented by the + // arguments. The bytes are specified like this to avoid endianness issues. + // + 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; + } + + [Flags] + private enum GuidStyles { + None = 0x00000000, + AllowParenthesis = 0x00000001, //Allow the guid to be enclosed in parens + AllowBraces = 0x00000002, //Allow the guid to be enclosed in braces + AllowDashes = 0x00000004, //Allow the guid to contain dash group separators + AllowHexPrefix = 0x00000008, //Allow the guid to contain {0xdd,0xdd} + RequireParenthesis = 0x00000010, //Require the guid to be enclosed in parens + RequireBraces = 0x00000020, //Require the guid to be enclosed in braces + RequireDashes = 0x00000040, //Require the guid to contain dash group separators + RequireHexPrefix = 0x00000080, //Require the guid to contain {0xdd,0xdd} + + HexFormat = RequireBraces | RequireHexPrefix, /* X */ + NumberFormat = None, /* N */ + DigitFormat = RequireDashes, /* D */ + BraceFormat = RequireBraces | RequireDashes, /* B */ + ParenthesisFormat = RequireParenthesis | RequireDashes, /* P */ + + Any = AllowParenthesis | AllowBraces | AllowDashes | AllowHexPrefix, + } + private enum GuidParseThrowStyle { + None = 0, + All = 1, + AllButOverflow = 2 + } + private enum ParseFailureKind { + None = 0, + ArgumentNull = 1, + Format = 2, + FormatWithParameter = 3, + NativeException = 4, + FormatWithInnerException = 5 + } + + // This will store the result of the parsing. And it will eventually be used to construct a Guid instance. + private struct GuidResult { + internal Guid parsedGuid; + internal GuidParseThrowStyle throwStyle; + + internal ParseFailureKind m_failure; + internal string m_failureMessageID; + internal object m_failureMessageFormatArgument; + internal string m_failureArgumentName; + internal Exception m_innerException; + + internal void Init(GuidParseThrowStyle canThrow) { + parsedGuid = Guid.Empty; + throwStyle = canThrow; + } + internal void SetFailure(Exception nativeException) { + m_failure = ParseFailureKind.NativeException; + m_innerException = nativeException; + } + internal void SetFailure(ParseFailureKind failure, string failureMessageID) { + SetFailure(failure, failureMessageID, null, null, null); + } + internal void SetFailure(ParseFailureKind failure, string failureMessageID, object failureMessageFormatArgument) { + SetFailure(failure, failureMessageID, failureMessageFormatArgument, null, null); + } + internal void SetFailure(ParseFailureKind failure, string failureMessageID, object failureMessageFormatArgument, + string failureArgumentName, Exception innerException) { + Contract.Assert(failure != ParseFailureKind.NativeException, "ParseFailureKind.NativeException should not be used with this overload"); + m_failure = failure; + m_failureMessageID = failureMessageID; + m_failureMessageFormatArgument = failureMessageFormatArgument; + m_failureArgumentName = failureArgumentName; + m_innerException = innerException; + if (throwStyle != GuidParseThrowStyle.None) { + throw GetGuidParseException(); + } + } + + internal Exception GetGuidParseException() { + switch (m_failure) { + case ParseFailureKind.ArgumentNull: + return new ArgumentNullException(m_failureArgumentName, Environment.GetResourceString(m_failureMessageID)); + + case ParseFailureKind.FormatWithInnerException: + return new FormatException(Environment.GetResourceString(m_failureMessageID), m_innerException); + + case ParseFailureKind.FormatWithParameter: + return new FormatException(Environment.GetResourceString(m_failureMessageID, m_failureMessageFormatArgument)); + + case ParseFailureKind.Format: + return new FormatException(Environment.GetResourceString(m_failureMessageID)); + + case ParseFailureKind.NativeException: + return m_innerException; + + default: + Contract.Assert(false, "Unknown GuidParseFailure: " + m_failure); + return new FormatException(Environment.GetResourceString("Format_GuidUnrecognized")); + } + } + } + + // Creates a new guid based on the value in the string. The value is made up + // of hex digits speared by the dash ("-"). The string may begin and end with + // brackets ("{", "}"). + // + // The string must be of the form dddddddd-dddd-dddd-dddd-dddddddddddd. where + // d is a hex digit. (That is 8 hex digits, followed by 4, then 4, then 4, + // then 12) such as: "CA761232-ED42-11CE-BACD-00AA0057B223" + // + public Guid(String g) + { + if (g==null) { + throw new ArgumentNullException("g"); + } + Contract.EndContractBlock(); + this = Guid.Empty; + + GuidResult result = new GuidResult(); + result.Init(GuidParseThrowStyle.All); + if (TryParseGuid(g, GuidStyles.Any, ref result)) { + this = result.parsedGuid; + } + else { + throw result.GetGuidParseException(); + } + } + + + public static Guid Parse(String input) + { + if (input == null) { + throw new ArgumentNullException("input"); + } + Contract.EndContractBlock(); + + GuidResult result = new GuidResult(); + result.Init(GuidParseThrowStyle.AllButOverflow); + if (TryParseGuid(input, GuidStyles.Any, ref result)) { + return result.parsedGuid; + } + else { + throw result.GetGuidParseException(); + } + } + + public static bool TryParse(String input, out Guid result) + { + GuidResult parseResult = new GuidResult(); + parseResult.Init(GuidParseThrowStyle.None); + if (TryParseGuid(input, GuidStyles.Any, ref parseResult)) { + result = parseResult.parsedGuid; + return true; + } + else { + result = Guid.Empty; + return false; + } + } + + public static Guid ParseExact(String input, String format) + { + if (input == null) + throw new ArgumentNullException("input"); + + if (format == null) + throw new ArgumentNullException("format"); + + if( format.Length != 1) { + // all acceptable format strings are of length 1 + throw new FormatException(Environment.GetResourceString("Format_InvalidGuidFormatSpecification")); + } + + GuidStyles style; + char formatCh = format[0]; + if (formatCh == 'D' || formatCh == 'd') { + style = GuidStyles.DigitFormat; + } + else if (formatCh == 'N' || formatCh == 'n') { + style = GuidStyles.NumberFormat; + } + else if (formatCh == 'B' || formatCh == 'b') { + style = GuidStyles.BraceFormat; + } + else if (formatCh == 'P' || formatCh == 'p') { + style = GuidStyles.ParenthesisFormat; + } + else if (formatCh == 'X' || formatCh == 'x') { + style = GuidStyles.HexFormat; + } + else { + throw new FormatException(Environment.GetResourceString("Format_InvalidGuidFormatSpecification")); + } + + GuidResult result = new GuidResult(); + result.Init(GuidParseThrowStyle.AllButOverflow); + if (TryParseGuid(input, style, ref result)) { + return result.parsedGuid; + } + else { + throw result.GetGuidParseException(); + } + } + + public static bool TryParseExact(String input, String format, out Guid result) + { + if (format == null || format.Length != 1) { + result = Guid.Empty; + return false; + } + + GuidStyles style; + char formatCh = format[0]; + + if (formatCh == 'D' || formatCh == 'd') { + style = GuidStyles.DigitFormat; + } + else if (formatCh == 'N' || formatCh == 'n') { + style = GuidStyles.NumberFormat; + } + else if (formatCh == 'B' || formatCh == 'b') { + style = GuidStyles.BraceFormat; + } + else if (formatCh == 'P' || formatCh == 'p') { + style = GuidStyles.ParenthesisFormat; + } + else if (formatCh == 'X' || formatCh == 'x') { + style = GuidStyles.HexFormat; + } + else { + // invalid guid format specification + result = Guid.Empty; + return false; + } + + GuidResult parseResult = new GuidResult(); + parseResult.Init(GuidParseThrowStyle.None); + if (TryParseGuid(input, style, ref parseResult)) { + result = parseResult.parsedGuid; + return true; + } + else { + result = Guid.Empty; + return false; + } + } + + + private static bool TryParseGuid(String g, GuidStyles flags, ref GuidResult result) + { + if (g == null) { + result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized"); + return false; + } + String guidString = g.Trim(); //Remove Whitespace + + if (guidString.Length == 0) { + result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized"); + return false; + } + + // Check for dashes + bool dashesExistInString = (guidString.IndexOf('-', 0) >= 0); + + if (dashesExistInString) { + if ((flags & (GuidStyles.AllowDashes | GuidStyles.RequireDashes)) == 0) { + // dashes are not allowed + result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized"); + return false; + } + } + else { + if ((flags & GuidStyles.RequireDashes) != 0) { + // dashes are required + result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized"); + return false; + } + } + + // Check for braces + bool bracesExistInString = (guidString.IndexOf('{', 0) >= 0); + + if (bracesExistInString) { + if ((flags & (GuidStyles.AllowBraces | GuidStyles.RequireBraces)) == 0) { + // braces are not allowed + result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized"); + return false; + } + } + else { + if ((flags & GuidStyles.RequireBraces) != 0) { + // braces are required + result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized"); + return false; + } + } + + // Check for parenthesis + bool parenthesisExistInString = (guidString.IndexOf('(', 0) >= 0); + + if (parenthesisExistInString) { + if ((flags & (GuidStyles.AllowParenthesis | GuidStyles.RequireParenthesis)) == 0) { + // parenthesis are not allowed + result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized"); + return false; + } + } + else { + if ((flags & GuidStyles.RequireParenthesis) != 0) { + // parenthesis are required + result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized"); + return false; + } + } + + try { + // let's get on with the parsing + if (dashesExistInString) { + // Check if it's of the form [{|(]dddddddd-dddd-dddd-dddd-dddddddddddd[}|)] + return TryParseGuidWithDashes(guidString, ref result); + } + else if (bracesExistInString) { + // Check if it's of the form {0xdddddddd,0xdddd,0xdddd,{0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd}} + return TryParseGuidWithHexPrefix(guidString, ref result); + } + else { + // Check if it's of the form dddddddddddddddddddddddddddddddd + return TryParseGuidWithNoStyle(guidString, ref result); + } + } + catch(IndexOutOfRangeException ex) { + result.SetFailure(ParseFailureKind.FormatWithInnerException, "Format_GuidUnrecognized", null, null, ex); + return false; + } + catch (ArgumentException ex) { + result.SetFailure(ParseFailureKind.FormatWithInnerException, "Format_GuidUnrecognized", null, null, ex); + return false; + } + } + + + // Check if it's of the form {0xdddddddd,0xdddd,0xdddd,{0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd}} + private static bool TryParseGuidWithHexPrefix(String guidString, ref GuidResult result) { + int numStart = 0; + int numLen = 0; + + // Eat all of the whitespace + guidString = EatAllWhitespace(guidString); + + // Check for leading '{' + if(String.IsNullOrEmpty(guidString) || guidString[0] != '{') { + result.SetFailure(ParseFailureKind.Format, "Format_GuidBrace"); + return false; + } + + // Check for '0x' + if(!IsHexPrefix(guidString, 1)) { + result.SetFailure(ParseFailureKind.Format, "Format_GuidHexPrefix", "{0xdddddddd, etc}"); + return false; + } + + // Find the end of this hex number (since it is not fixed length) + numStart = 3; + numLen = guidString.IndexOf(',', numStart) - numStart; + if(numLen <= 0) { + result.SetFailure(ParseFailureKind.Format, "Format_GuidComma"); + return false; + } + + + if (!StringToInt(guidString.Substring(numStart, numLen) /*first DWORD*/, -1, ParseNumbers.IsTight, out result.parsedGuid._a, ref result)) + return false; + + // Check for '0x' + if(!IsHexPrefix(guidString, numStart+numLen+1)) { + result.SetFailure(ParseFailureKind.Format, "Format_GuidHexPrefix", "{0xdddddddd, 0xdddd, etc}"); + return false; + } + // +3 to get by ',0x' + numStart = numStart + numLen + 3; + numLen = guidString.IndexOf(',', numStart) - numStart; + if(numLen <= 0) { + result.SetFailure(ParseFailureKind.Format, "Format_GuidComma"); + return false; + } + + // Read in the number + if (!StringToShort(guidString.Substring(numStart, numLen) /*first DWORD*/, -1, ParseNumbers.IsTight, out result.parsedGuid._b, ref result)) + return false; + // Check for '0x' + if(!IsHexPrefix(guidString, numStart+numLen+1)) { + result.SetFailure(ParseFailureKind.Format, "Format_GuidHexPrefix", "{0xdddddddd, 0xdddd, 0xdddd, etc}"); + return false; + } + // +3 to get by ',0x' + numStart = numStart + numLen + 3; + numLen = guidString.IndexOf(',', numStart) - numStart; + if(numLen <= 0) { + result.SetFailure(ParseFailureKind.Format, "Format_GuidComma"); + return false; + } + + // Read in the number + if (!StringToShort(guidString.Substring(numStart, numLen) /*first DWORD*/, -1, ParseNumbers.IsTight, out result.parsedGuid._c, ref result)) + return false; + + // Check for '{' + if(guidString.Length <= numStart+numLen+1 || guidString[numStart+numLen+1] != '{') { + result.SetFailure(ParseFailureKind.Format, "Format_GuidBrace"); + return false; + } + + // Prepare for loop + numLen++; + byte[] bytes = new byte[8]; + + for(int i = 0; i < 8; i++) + { + // Check for '0x' + if(!IsHexPrefix(guidString, numStart+numLen+1)) { + result.SetFailure(ParseFailureKind.Format, "Format_GuidHexPrefix", "{... { ... 0xdd, ...}}"); + return false; + } + + // +3 to get by ',0x' or '{0x' for first case + numStart = numStart + numLen + 3; + + // Calculate number length + if(i < 7) // first 7 cases + { + numLen = guidString.IndexOf(',', numStart) - numStart; + if(numLen <= 0) { + result.SetFailure(ParseFailureKind.Format, "Format_GuidComma"); + return false; + } + } + else // last case ends with '}', not ',' + { + numLen = guidString.IndexOf('}', numStart) - numStart; + if(numLen <= 0) { + result.SetFailure(ParseFailureKind.Format, "Format_GuidBraceAfterLastNumber"); + return false; + } + } + + // Read in the number + uint number = (uint)Convert.ToInt32(guidString.Substring(numStart, numLen),16); + // check for overflow + if(number > 255) { + result.SetFailure(ParseFailureKind.Format, "Overflow_Byte"); + return false; + } + bytes[i] = (byte)number; + } + + result.parsedGuid._d = bytes[0]; + result.parsedGuid._e = bytes[1]; + result.parsedGuid._f = bytes[2]; + result.parsedGuid._g = bytes[3]; + result.parsedGuid._h = bytes[4]; + result.parsedGuid._i = bytes[5]; + result.parsedGuid._j = bytes[6]; + result.parsedGuid._k = bytes[7]; + + // Check for last '}' + if(numStart+numLen+1 >= guidString.Length || guidString[numStart+numLen+1] != '}') { + result.SetFailure(ParseFailureKind.Format, "Format_GuidEndBrace"); + return false; + } + + // Check if we have extra characters at the end + if( numStart+numLen+1 != guidString.Length -1) { + result.SetFailure(ParseFailureKind.Format, "Format_ExtraJunkAtEnd"); + return false; + } + + return true; + } + + // Check if it's of the form dddddddddddddddddddddddddddddddd + private static bool TryParseGuidWithNoStyle(String guidString, ref GuidResult result) { + int startPos=0; + int temp; + long templ; + int currentPos = 0; + + if(guidString.Length != 32) { + result.SetFailure(ParseFailureKind.Format, "Format_GuidInvLen"); + return false; + } + + for(int i= 0; i< guidString.Length; i++) { + char ch = guidString[i]; + if(ch >= '0' && ch <= '9') { + continue; + } + else { + char upperCaseCh = Char.ToUpper(ch, CultureInfo.InvariantCulture); + if(upperCaseCh >= 'A' && upperCaseCh <= 'F') { + continue; + } + } + + result.SetFailure(ParseFailureKind.Format, "Format_GuidInvalidChar"); + return false; + } + + if (!StringToInt(guidString.Substring(startPos, 8) /*first DWORD*/, -1, ParseNumbers.IsTight, out result.parsedGuid._a, ref result)) + return false; + + startPos += 8; + if (!StringToShort(guidString.Substring(startPos, 4), -1, ParseNumbers.IsTight, out result.parsedGuid._b, ref result)) + return false; + + startPos += 4; + if (!StringToShort(guidString.Substring(startPos, 4), -1, ParseNumbers.IsTight, out result.parsedGuid._c, ref result)) + return false; + + startPos += 4; + if (!StringToInt(guidString.Substring(startPos, 4), -1, ParseNumbers.IsTight, out temp, ref result)) + return false; + + startPos += 4; + currentPos = startPos; + + if (!StringToLong(guidString, ref currentPos, startPos /*flags*/, out templ, ref result)) + return false; + + if (currentPos - startPos!=12) { + result.SetFailure(ParseFailureKind.Format, "Format_GuidInvLen"); + return false; + } + + result.parsedGuid._d = (byte)(temp>>8); + result.parsedGuid._e = (byte)(temp); + temp = (int)(templ >> 32); + result.parsedGuid._f = (byte)(temp>>8); + result.parsedGuid._g = (byte)(temp); + temp = (int)(templ); + result.parsedGuid._h = (byte)(temp>>24); + result.parsedGuid._i = (byte)(temp>>16); + result.parsedGuid._j = (byte)(temp>>8); + result.parsedGuid._k = (byte)(temp); + + return true; + } + + + // Check if it's of the form [{|(]dddddddd-dddd-dddd-dddd-dddddddddddd[}|)] + private static bool TryParseGuidWithDashes(String guidString, ref GuidResult result) { + int startPos=0; + int temp; + long templ; + int currentPos = 0; + + // check to see that it's the proper length + if (guidString[0]=='{') { + if (guidString.Length!=38 || guidString[37]!='}') { + result.SetFailure(ParseFailureKind.Format, "Format_GuidInvLen"); + return false; + } + startPos=1; + } + else if (guidString[0]=='(') { + if (guidString.Length!=38 || guidString[37]!=')') { + result.SetFailure(ParseFailureKind.Format, "Format_GuidInvLen"); + return false; + } + startPos=1; + } + else if(guidString.Length != 36) { + result.SetFailure(ParseFailureKind.Format, "Format_GuidInvLen"); + return false; + } + + if (guidString[8+startPos] != '-' || + guidString[13+startPos] != '-' || + guidString[18+startPos] != '-' || + guidString[23+startPos] != '-') { + result.SetFailure(ParseFailureKind.Format, "Format_GuidDashes"); + return false; + } + + currentPos = startPos; + if (!StringToInt(guidString, ref currentPos, 8, ParseNumbers.NoSpace, out temp, ref result)) + return false; + result.parsedGuid._a = temp; + ++currentPos; //Increment past the '-'; + + if (!StringToInt(guidString, ref currentPos, 4, ParseNumbers.NoSpace, out temp, ref result)) + return false; + result.parsedGuid._b = (short)temp; + ++currentPos; //Increment past the '-'; + + if (!StringToInt(guidString, ref currentPos, 4, ParseNumbers.NoSpace, out temp, ref result)) + return false; + result.parsedGuid._c = (short)temp; + ++currentPos; //Increment past the '-'; + + if (!StringToInt(guidString, ref currentPos, 4, ParseNumbers.NoSpace, out temp, ref result)) + return false; + ++currentPos; //Increment past the '-'; + startPos=currentPos; + + if (!StringToLong(guidString, ref currentPos, ParseNumbers.NoSpace, out templ, ref result)) + return false; + + if (currentPos - startPos != 12) { + result.SetFailure(ParseFailureKind.Format, "Format_GuidInvLen"); + return false; + } + result.parsedGuid._d = (byte)(temp>>8); + result.parsedGuid._e = (byte)(temp); + temp = (int)(templ >> 32); + result.parsedGuid._f = (byte)(temp>>8); + result.parsedGuid._g = (byte)(temp); + temp = (int)(templ); + result.parsedGuid._h = (byte)(temp>>24); + result.parsedGuid._i = (byte)(temp>>16); + result.parsedGuid._j = (byte)(temp>>8); + result.parsedGuid._k = (byte)(temp); + + return true; + } + + + // + // StringToShort, StringToInt, and StringToLong are wrappers around COMUtilNative integer parsing routines; + + [System.Security.SecuritySafeCritical] + private static unsafe bool StringToShort(String str, int requiredLength, int flags, out short result, ref GuidResult parseResult) { + return StringToShort(str, null, requiredLength, flags, out result, ref parseResult); + } + [System.Security.SecuritySafeCritical] + private static unsafe bool StringToShort(String str, ref int parsePos, int requiredLength, int flags, out short result, ref GuidResult parseResult) { + fixed(int * ppos = &parsePos) { + return StringToShort(str, ppos, requiredLength, flags, out result, ref parseResult); + } + } + [System.Security.SecurityCritical] + private static unsafe bool StringToShort(String str, int* parsePos, int requiredLength, int flags, out short result, ref GuidResult parseResult) { + result = 0; + int x; + bool retValue = StringToInt(str, parsePos, requiredLength, flags, out x, ref parseResult); + result = (short)x; + return retValue; + } + + [System.Security.SecuritySafeCritical] + private static unsafe bool StringToInt(String str, int requiredLength, int flags, out int result, ref GuidResult parseResult) { + return StringToInt(str, null, requiredLength, flags, out result, ref parseResult); + } + [System.Security.SecuritySafeCritical] + private static unsafe bool StringToInt(String str, ref int parsePos, int requiredLength, int flags, out int result, ref GuidResult parseResult) { + fixed(int * ppos = &parsePos) { + return StringToInt(str, ppos, requiredLength, flags, out result, ref parseResult); + } + } + [System.Security.SecurityCritical] + private static unsafe bool StringToInt(String str, int* parsePos, int requiredLength, int flags, out int result, ref GuidResult parseResult) { + result = 0; + + int currStart = (parsePos == null) ? 0 : (*parsePos); + try { + result = ParseNumbers.StringToInt(str, 16, flags, parsePos); + } + catch (OverflowException ex) { + if (parseResult.throwStyle == GuidParseThrowStyle.All) { + throw; + } + else if (parseResult.throwStyle == GuidParseThrowStyle.AllButOverflow) { + throw new FormatException(Environment.GetResourceString("Format_GuidUnrecognized"), ex); + } + else { + parseResult.SetFailure(ex); + return false; + } + } + catch (Exception ex) { + if (parseResult.throwStyle == GuidParseThrowStyle.None) { + parseResult.SetFailure(ex); + return false; + } + else { + throw; + } + } + + //If we didn't parse enough characters, there's clearly an error. + if (requiredLength != -1 && parsePos != null && (*parsePos) - currStart != requiredLength) { + parseResult.SetFailure(ParseFailureKind.Format, "Format_GuidInvalidChar"); + return false; + } + return true; + } + [System.Security.SecuritySafeCritical] + private static unsafe bool StringToLong(String str, int flags, out long result, ref GuidResult parseResult) { + return StringToLong(str, null, flags, out result, ref parseResult); + } + [System.Security.SecuritySafeCritical] + private static unsafe bool StringToLong(String str, ref int parsePos, int flags, out long result, ref GuidResult parseResult) { + fixed(int * ppos = &parsePos) { + return StringToLong(str, ppos, flags, out result, ref parseResult); + } + } + [System.Security.SecuritySafeCritical] + private static unsafe bool StringToLong(String str, int* parsePos, int flags, out long result, ref GuidResult parseResult) { + result = 0; + + try { + result = ParseNumbers.StringToLong(str, 16, flags, parsePos); + } + catch (OverflowException ex) { + if (parseResult.throwStyle == GuidParseThrowStyle.All) { + throw; + } + else if (parseResult.throwStyle == GuidParseThrowStyle.AllButOverflow) { + throw new FormatException(Environment.GetResourceString("Format_GuidUnrecognized"), ex); + } + else { + parseResult.SetFailure(ex); + return false; + } + } + catch (Exception ex) { + if (parseResult.throwStyle == GuidParseThrowStyle.None) { + parseResult.SetFailure(ex); + return false; + } + else { + throw; + } + } + return true; + } + + + private static String EatAllWhitespace(String str) + { + int newLength = 0; + char[] chArr = new char[str.Length]; + char curChar; + + // Now get each char from str and if it is not whitespace add it to chArr + for(int i = 0; i < str.Length; i++) + { + curChar = str[i]; + if(!Char.IsWhiteSpace(curChar)) + { + chArr[newLength++] = curChar; + } + } + + // Return a new string based on chArr + return new String(chArr, 0, newLength); + } + + private static bool IsHexPrefix(String str, int i) + { + if(str.Length > i+1 && str[i] == '0' && (Char.ToLower(str[i+1], CultureInfo.InvariantCulture) == 'x')) + return true; + else + return false; + } + + + // Returns an unsigned byte array containing the GUID. + public byte[] ToByteArray() + { + byte[] g = new byte[16]; + + g[0] = (byte)(_a); + g[1] = (byte)(_a >> 8); + g[2] = (byte)(_a >> 16); + g[3] = (byte)(_a >> 24); + g[4] = (byte)(_b); + g[5] = (byte)(_b >> 8); + g[6] = (byte)(_c); + g[7] = (byte)(_c >> 8); + g[8] = _d; + g[9] = _e; + g[10] = _f; + g[11] = _g; + g[12] = _h; + g[13] = _i; + g[14] = _j; + g[15] = _k; + + return g; + } + + + // Returns the guid in "registry" format. + public override String ToString() + { + return ToString("D",null); + } + + public override int GetHashCode() + { + return _a ^ (((int)_b << 16) | (int)(ushort)_c) ^ (((int)_f << 24) | _k); + } + + // Returns true if and only if the guid represented + // by o is the same as this instance. + public override bool Equals(Object o) + { + Guid g; + // Check that o is a Guid first + if(o == null || !(o is Guid)) + return false; + else g = (Guid) o; + + // Now compare each of the elements + if(g._a != _a) + return false; + if(g._b != _b) + return false; + if(g._c != _c) + return false; + if (g._d != _d) + return false; + if (g._e != _e) + return false; + if (g._f != _f) + return false; + if (g._g != _g) + return false; + if (g._h != _h) + return false; + if (g._i != _i) + return false; + if (g._j != _j) + return false; + if (g._k != _k) + return false; + + return true; + } + + public bool Equals(Guid g) + { + // Now compare each of the elements + if(g._a != _a) + return false; + if(g._b != _b) + return false; + if(g._c != _c) + return false; + if (g._d != _d) + return false; + if (g._e != _e) + return false; + if (g._f != _f) + return false; + if (g._g != _g) + return false; + if (g._h != _h) + return false; + if (g._i != _i) + return false; + if (g._j != _j) + return false; + if (g._k != _k) + return false; + + return true; + } + + private int GetResult(uint me, uint them) { + if (me<them) { + return -1; + } + return 1; + } + + public int CompareTo(Object value) { + if (value == null) { + return 1; + } + if (!(value is Guid)) { + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeGuid")); + } + Guid g = (Guid)value; + + if (g._a!=this._a) { + return GetResult((uint)this._a, (uint)g._a); + } + + if (g._b!=this._b) { + return GetResult((uint)this._b, (uint)g._b); + } + + if (g._c!=this._c) { + return GetResult((uint)this._c, (uint)g._c); + } + + if (g._d!=this._d) { + return GetResult((uint)this._d, (uint)g._d); + } + + if (g._e!=this._e) { + return GetResult((uint)this._e, (uint)g._e); + } + + if (g._f!=this._f) { + return GetResult((uint)this._f, (uint)g._f); + } + + if (g._g!=this._g) { + return GetResult((uint)this._g, (uint)g._g); + } + + if (g._h!=this._h) { + return GetResult((uint)this._h, (uint)g._h); + } + + if (g._i!=this._i) { + return GetResult((uint)this._i, (uint)g._i); + } + + if (g._j!=this._j) { + return GetResult((uint)this._j, (uint)g._j); + } + + if (g._k!=this._k) { + return GetResult((uint)this._k, (uint)g._k); + } + + return 0; + } + + public int CompareTo(Guid value) + { + if (value._a!=this._a) { + return GetResult((uint)this._a, (uint)value._a); + } + + if (value._b!=this._b) { + return GetResult((uint)this._b, (uint)value._b); + } + + if (value._c!=this._c) { + return GetResult((uint)this._c, (uint)value._c); + } + + if (value._d!=this._d) { + return GetResult((uint)this._d, (uint)value._d); + } + + if (value._e!=this._e) { + return GetResult((uint)this._e, (uint)value._e); + } + + if (value._f!=this._f) { + return GetResult((uint)this._f, (uint)value._f); + } + + if (value._g!=this._g) { + return GetResult((uint)this._g, (uint)value._g); + } + + if (value._h!=this._h) { + return GetResult((uint)this._h, (uint)value._h); + } + + if (value._i!=this._i) { + return GetResult((uint)this._i, (uint)value._i); + } + + if (value._j!=this._j) { + return GetResult((uint)this._j, (uint)value._j); + } + + if (value._k!=this._k) { + return GetResult((uint)this._k, (uint)value._k); + } + + return 0; + } + + public static bool operator ==(Guid a, Guid b) + { + // Now compare each of the elements + if(a._a != b._a) + return false; + if(a._b != b._b) + return false; + if(a._c != b._c) + return false; + if(a._d != b._d) + return false; + if(a._e != b._e) + return false; + if(a._f != b._f) + return false; + if(a._g != b._g) + return false; + if(a._h != b._h) + return false; + if(a._i != b._i) + return false; + if(a._j != b._j) + return false; + if(a._k != b._k) + return false; + + return true; + } + + public static bool operator !=(Guid a, Guid b) + { + return !(a == b); + } + + // This will create a new guid. Since we've now decided that constructors should 0-init, + // we need a method that allows users to create a guid. + [System.Security.SecuritySafeCritical] // auto-generated + public static Guid NewGuid() { + // CoCreateGuid should never return Guid.Empty, since it attempts to maintain some + // uniqueness guarantees. It should also never return a known GUID, but it's unclear + // how extensively it checks for known values. + Contract.Ensures(Contract.Result<Guid>() != Guid.Empty); + + Guid guid; + Marshal.ThrowExceptionForHR(Win32Native.CoCreateGuid(out guid), new IntPtr(-1)); + return guid; + } + + public String ToString(String format) { + return ToString(format, null); + } + + private static char HexToChar(int a) + { + a = a & 0xf; + return (char) ((a > 9) ? a - 10 + 0x61 : a + 0x30); + } + + [System.Security.SecurityCritical] + unsafe private static int HexsToChars(char* guidChars, int offset, int a, int b) + { + return HexsToChars(guidChars, offset, a, b, false); + } + + [System.Security.SecurityCritical] + unsafe private static int HexsToChars(char* guidChars, int offset, int a, int b, bool hex) + { + if (hex) { + guidChars[offset++] = '0'; + guidChars[offset++] = 'x'; + } + guidChars[offset++] = HexToChar(a>>4); + guidChars[offset++] = HexToChar(a); + if (hex) { + guidChars[offset++] = ','; + guidChars[offset++] = '0'; + guidChars[offset++] = 'x'; + } + guidChars[offset++] = HexToChar(b>>4); + guidChars[offset++] = HexToChar(b); + return offset; + } + + // IFormattable interface + // We currently ignore provider + [System.Security.SecuritySafeCritical] + public String ToString(String format, IFormatProvider provider) + { + if (format == null || format.Length == 0) + format = "D"; + + string guidString; + int offset = 0; + bool dash = true; + bool hex = false; + + if( format.Length != 1) { + // all acceptable format strings are of length 1 + throw new FormatException(Environment.GetResourceString("Format_InvalidGuidFormatSpecification")); + } + + char formatCh = format[0]; + if (formatCh == 'D' || formatCh == 'd') { + guidString = string.FastAllocateString(36); + } + else if (formatCh == 'N' || formatCh == 'n') { + guidString = string.FastAllocateString(32); + dash = false; + } + else if (formatCh == 'B' || formatCh == 'b') { + guidString = string.FastAllocateString(38); + unsafe { + fixed (char* guidChars = guidString) { + guidChars[offset++] = '{'; + guidChars[37] = '}'; + } + } + } + else if (formatCh == 'P' || formatCh == 'p') { + guidString = string.FastAllocateString(38); + unsafe { + fixed (char* guidChars = guidString) { + guidChars[offset++] = '('; + guidChars[37] = ')'; + } + } + } + else if (formatCh == 'X' || formatCh == 'x') { + guidString = string.FastAllocateString(68); + unsafe { + fixed (char* guidChars = guidString) { + guidChars[offset++] = '{'; + guidChars[67] = '}'; + } + } + dash = false; + hex = true; + } + else { + throw new FormatException(Environment.GetResourceString("Format_InvalidGuidFormatSpecification")); + } + + unsafe { + fixed (char* guidChars = guidString) { + if (hex) { + // {0xdddddddd,0xdddd,0xdddd,{0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd}} + guidChars[offset++] = '0'; + guidChars[offset++] = 'x'; + offset = HexsToChars(guidChars, offset, _a >> 24, _a >> 16); + offset = HexsToChars(guidChars, offset, _a >> 8, _a); + guidChars[offset++] = ','; + guidChars[offset++] = '0'; + guidChars[offset++] = 'x'; + offset = HexsToChars(guidChars, offset, _b >> 8, _b); + guidChars[offset++] = ','; + guidChars[offset++] = '0'; + guidChars[offset++] = 'x'; + offset = HexsToChars(guidChars, offset, _c >> 8, _c); + guidChars[offset++] = ','; + guidChars[offset++] = '{'; + offset = HexsToChars(guidChars, offset, _d, _e, true); + guidChars[offset++] = ','; + offset = HexsToChars(guidChars, offset, _f, _g, true); + guidChars[offset++] = ','; + offset = HexsToChars(guidChars, offset, _h, _i, true); + guidChars[offset++] = ','; + offset = HexsToChars(guidChars, offset, _j, _k, true); + guidChars[offset++] = '}'; + } + else { + // [{|(]dddddddd[-]dddd[-]dddd[-]dddd[-]dddddddddddd[}|)] + offset = HexsToChars(guidChars, offset, _a >> 24, _a >> 16); + offset = HexsToChars(guidChars, offset, _a >> 8, _a); + if (dash) guidChars[offset++] = '-'; + offset = HexsToChars(guidChars, offset, _b >> 8, _b); + if (dash) guidChars[offset++] = '-'; + offset = HexsToChars(guidChars, offset, _c >> 8, _c); + if (dash) guidChars[offset++] = '-'; + offset = HexsToChars(guidChars, offset, _d, _e); + if (dash) guidChars[offset++] = '-'; + offset = HexsToChars(guidChars, offset, _f, _g); + offset = HexsToChars(guidChars, offset, _h, _i); + offset = HexsToChars(guidChars, offset, _j, _k); + } + } + } + return guidString; + } + } +} |