Просмотр исходного кода

2004-05-18 Sebastien Pouliot <[email protected]>

	* Buffer.cs: Added checks for null source and destination. Fix failing
	CryptoStream unit test.
	* Guid.cs: Fixed thread-safety issue. Simplified implementation to use
	pseudo-random numbers to generate GUIDs (as per section 3.4 of the
	spec). This removes the TODO to get the computer MAC address and
	the chances to get a duplicate GUID (across different machines).

svn path=/trunk/mcs/; revision=27585
Sebastien Pouliot 21 лет назад
Родитель
Сommit
75dacf7bbd
3 измененных файлов с 39 добавлено и 128 удалено
  1. 8 2
      mcs/class/corlib/System/Buffer.cs
  2. 9 0
      mcs/class/corlib/System/ChangeLog
  3. 22 126
      mcs/class/corlib/System/Guid.cs

+ 8 - 2
mcs/class/corlib/System/Buffer.cs

@@ -53,6 +53,12 @@ namespace System
 
 		public static void BlockCopy (Array src, int srcOffset, Array dest, int destOffset, int count)
 		{
+			if (src == null)
+				throw new ArgumentNullException ("src");
+
+			if (dest == null)
+				throw new ArgumentNullException ("dest");
+
 			if (srcOffset < 0)
 				throw new ArgumentOutOfRangeException ("srcOffset", Locale.GetText(
 					"Non-negative number required."));
@@ -70,8 +76,8 @@ namespace System
 			if (!res) {
 				if (srcOffset + count > ByteLength (src) || destOffset + count > ByteLength (dest))
 					throw new ArgumentException (Locale.GetText (
-																 "Offset and length were out of bounds for the array or count is greater than" + 
-																 "the number of elements from index to the end of the source collection."));
+						"Offset and length were out of bounds for the array or count is greater than" + 
+						"the number of elements from index to the end of the source collection."));
 			}
 		}
 

+ 9 - 0
mcs/class/corlib/System/ChangeLog

@@ -1,3 +1,12 @@
+2004-05-18  Sebastien Pouliot  <[email protected]>
+
+	* Buffer.cs: Added checks for null source and destination. Fix failing
+	CryptoStream unit test.
+	* Guid.cs: Fixed thread-safety issue. Simplified implementation to use
+	pseudo-random numbers to generate GUIDs (as per section 3.4 of the 
+	spec). This removes the TODO to get the computer MAC address and
+	the chances to get a duplicate GUID (across different machines).
+
 2004-05-17  Andreas Nahr <[email protected]>
 
 	* TimeSpan.cs: Only catch expected exceptions, if we get other exceptions

+ 22 - 126
mcs/class/corlib/System/Guid.cs

@@ -1,15 +1,21 @@
 //
 // System.Guid.cs
 //
-// Author:
-//   Duco Fijma ([email protected])
+// Authors:
+//	Duco Fijma ([email protected])
+//	Sebastien Pouliot ([email protected])
 //
 // (C) 2002 Duco Fijma
+// Copyright (C) 2004 Novell (http://www.novell.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 
 //
 
+using System.Runtime.InteropServices;
 using System.Security.Cryptography;
 using System.Text;
-using System.Runtime.InteropServices;
 
 namespace System
 {
@@ -29,92 +35,6 @@ namespace System
 		private byte _node4;
 		private byte _node5;
 
-		internal class GuidState
-		{
-			protected Random _prnd; // Pseudo RNG
-			protected RandomNumberGenerator _rnd; // Strong RNG
-			protected bool _usePRnd; // 'true' for pseudo RNG
-			protected ushort _clockSeq;
-			protected ulong _lastTimestamp;
-			protected byte[] _mac;
-
-			public int NextInt(uint x)
-			 {
-				if (_usePRnd) {
-					return _prnd.Next ((int) x);
-				}
-				else {
-					byte[] b = new byte[4];
-					_rnd.GetBytes (b);
-	
-					uint res = BitConverter.ToUInt32 (b, 0);
-					res = (res % x);
-					return (int) res;
-				}
-			}
-
-			public void NextBytes(byte[] b)
-			{
-				if ( _usePRnd ) {
-					_prnd . NextBytes (b);
-				}
-				else {
-					_rnd . GetBytes (b);
-				}
-			}
-
-			[MonoTODO("Get real MAC address")]
-			public GuidState (bool usePRnd)
-			{
-				_usePRnd = usePRnd;
-				if ( _usePRnd ) {
-					_prnd = new Random (unchecked((int) DateTime.Now.Ticks));
-				}
-				else {
-					_rnd = RandomNumberGenerator.Create ();
-				}
-				_clockSeq = (ushort) NextInt (0x4000); // 14 bits
-				_lastTimestamp = 0ul;
-				_mac = new byte[6];
-				NextBytes (_mac);
-				_mac[0] |= 0x80;
-			}
-
-			public ulong NewTimestamp ()
-			{
-				ulong timestamp;
-	
-				do {
-					timestamp = (ulong) (DateTime.UtcNow - new DateTime (1582, 10, 15, 0, 0, 0)).Ticks;
-					if (timestamp < _lastTimestamp) {
-						// clock moved backwards!
-						_clockSeq++;
-						_clockSeq = (ushort) (_clockSeq & 0x3fff);
-						return timestamp;
-					}
-					if (timestamp > _lastTimestamp) {
-						_lastTimestamp = timestamp;
-						return timestamp;
-					}
-				}
-				while (true);
-			}
-	
-			public ushort ClockSeq {
-				get {
-					return _clockSeq;
-				}
-			}
-
-			public byte[] MAC {
-				get {
-					return _mac;
-				}
-				
-			}
-			
-		};
-
 		internal class GuidParser
 		{
 			private string _src;
@@ -299,7 +219,7 @@ namespace System
 			}
 		}
 	
-		private static GuidState _guidState = new GuidState ( true /* use pseudo RNG? */ );
+		private static RandomNumberGenerator _rng = RandomNumberGenerator.Create ();
 
 		private static void CheckNull (object o)
 		{
@@ -472,36 +392,22 @@ namespace System
 			return res;
 		}
 
-		private static Guid NewTimeGuid ()
+		private static char ToHex (int b)
 		{
-			ulong timestamp = _guidState.NewTimestamp ();
-
-			// Bit [31..0] (32 bits) for timeLow
-			uint timeLow = (uint) (timestamp & 0x00000000fffffffful);
-			// Bit [47..32] (16 bits) for timeMid
-			ushort timeMid = (ushort) ((timestamp & 0x0000ffff00000000ul) >> 32); 
-			// Bit [59..48] (12 bits) for timeHi
-			ushort timeHi = (ushort) ((timestamp & 0x0fff000000000000ul) >> 48);
-			// Bit [7..0] (8 bits) for clockSeqLo
-			byte clockSeqLow = (byte) (Guid._guidState.ClockSeq & 0x00ffu);
-			// Bit [13..8] (6 bits) for clockSeqHi
-			byte clockSeqHi = (byte) ((Guid._guidState.ClockSeq & 0x3f00u) >> 8);
-			byte[] mac = _guidState.MAC;
-	
-			clockSeqHi = (byte) (clockSeqHi | 0x80u); // Bit[7] = 1, Bit[6] = 0 (Variant)
-			timeHi = (ushort) (timeHi | 0x1000u); // Bit[15..13] = 1 (Guid is time-based)
-	
-			return new Guid (timeLow, timeMid, timeHi, clockSeqHi, clockSeqLow,
-				mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+			return (char)((b<0xA)?('0' + b):('a' + b - 0xA));
 		}
-	
-		private static Guid NewRandomGuid ()
+
+		// generated as per section 3.4 of the specification
+		public static Guid NewGuid ()
 		{
-			byte[] b = new byte[16];
-	
-			_guidState.NextBytes (b);
+			byte[] b = new byte [16];
+
+			// access the prng
+			lock (_rng) {
+				_rng.GetBytes (b);
+			}
 	
-			Guid res = new Guid(b);
+			Guid res = new Guid (b);
 			// Mask in Variant 1-0 in Bit[7..6]
 			res._clockSeqHiAndReserved = (byte) ((res._clockSeqHiAndReserved & 0x3fu) | 0x80u);
 			// Mask in Version 4 (random based Guid) in Bits[15..13]
@@ -509,16 +415,6 @@ namespace System
 			return res;
 		}
 
-		private static char ToHex (int b)
-		{
-			return (char)((b<0xA)?('0' + b):('a' + b - 0xA));
-		}
-
-		public static Guid NewGuid ()
-		{
-			return NewRandomGuid();
-		}
-
 		public byte[] ToByteArray ()
 		{
 			byte[] res = new byte[16];