summaryrefslogtreecommitdiff
path: root/src/mscorlib/shared
diff options
context:
space:
mode:
authorDavid Wrighton <davidwr@microsoft.com>2017-09-13 14:50:39 -0700
committerDavid Wrighton <davidwr@microsoft.com>2017-09-13 14:50:39 -0700
commitd68f0916d0a2bf3787bc85261ef4a4f1f27f1f24 (patch)
tree6c21ac239ae268096f20d98a8db16a4b80394fd9 /src/mscorlib/shared
parent96fa98525e0d64459148228cde5211c475b0c25c (diff)
parente866d072042f4ad9e0811aa36e338dac781c09a5 (diff)
downloadcoreclr-d68f0916d0a2bf3787bc85261ef4a4f1f27f1f24.tar.gz
coreclr-d68f0916d0a2bf3787bc85261ef4a4f1f27f1f24.tar.bz2
coreclr-d68f0916d0a2bf3787bc85261ef4a4f1f27f1f24.zip
Merge branch 'master' into update_from_master
Diffstat (limited to 'src/mscorlib/shared')
-rw-r--r--src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.Collation.cs2
-rw-r--r--src/mscorlib/shared/Interop/Unix/System.Native/Interop.PosixFAdvise.cs2
-rw-r--r--src/mscorlib/shared/Interop/Windows/Interop.Libraries.cs1
-rw-r--r--src/mscorlib/shared/Interop/Windows/Kernel32/Interop.CREATEFILE2_EXTENDED_PARAMETERS.cs24
-rw-r--r--src/mscorlib/shared/Interop/Windows/Kernel32/Interop.CreateFile2.cs29
-rw-r--r--src/mscorlib/shared/Interop/Windows/Kernel32/Interop.FreeLibrary.cs15
-rw-r--r--src/mscorlib/shared/Interop/Windows/Kernel32/Interop.LoadLibraryEx.cs18
-rw-r--r--src/mscorlib/shared/Interop/Windows/User32/Interop.LoadString.cs16
-rw-r--r--src/mscorlib/shared/Microsoft/Win32/SafeHandles/SafeLibraryHandle.cs16
-rw-r--r--src/mscorlib/shared/System.Private.CoreLib.Shared.projitems103
-rw-r--r--src/mscorlib/shared/System.Private.CoreLib.Shared.shproj17
-rw-r--r--src/mscorlib/shared/System/AccessViolationException.cs50
-rw-r--r--src/mscorlib/shared/System/Action.cs6
-rw-r--r--src/mscorlib/shared/System/AggregateException.cs484
-rw-r--r--src/mscorlib/shared/System/ApplicationException.cs6
-rw-r--r--src/mscorlib/shared/System/ArgumentException.cs10
-rw-r--r--src/mscorlib/shared/System/ArgumentNullException.cs8
-rw-r--r--src/mscorlib/shared/System/ArgumentOutOfRangeException.cs10
-rw-r--r--src/mscorlib/shared/System/ArithmeticException.cs6
-rw-r--r--src/mscorlib/shared/System/ArrayTypeMismatchException.cs6
-rw-r--r--src/mscorlib/shared/System/BadImageFormatException.cs12
-rw-r--r--src/mscorlib/shared/System/BitConverter.cs185
-rw-r--r--src/mscorlib/shared/System/Boolean.cs335
-rw-r--r--src/mscorlib/shared/System/Buffers/ArrayPoolEventSource.cs78
-rw-r--r--src/mscorlib/shared/System/Buffers/IRetainable.cs15
-rw-r--r--src/mscorlib/shared/System/Buffers/MemoryHandle.cs44
-rw-r--r--src/mscorlib/shared/System/Buffers/OwnedMemory.cs53
-rw-r--r--src/mscorlib/shared/System/Byte.cs298
-rw-r--r--src/mscorlib/shared/System/Collections/Generic/KeyNotFoundException.cs6
-rw-r--r--src/mscorlib/shared/System/Collections/ICollection.cs2
-rw-r--r--src/mscorlib/shared/System/Collections/ListDictionaryInternal.cs521
-rw-r--r--src/mscorlib/shared/System/Collections/ObjectModel/Collection.cs396
-rw-r--r--src/mscorlib/shared/System/Collections/ObjectModel/ReadOnlyCollection.cs279
-rw-r--r--src/mscorlib/shared/System/Convert.cs4
-rw-r--r--src/mscorlib/shared/System/DBNull.cs10
-rw-r--r--src/mscorlib/shared/System/DataMisalignedException.cs6
-rw-r--r--src/mscorlib/shared/System/DateTime.cs8
-rw-r--r--src/mscorlib/shared/System/DateTimeOffset.cs6
-rw-r--r--src/mscorlib/shared/System/DefaultBinder.cs42
-rw-r--r--src/mscorlib/shared/System/Diagnostics/Tracing/EventProvider.cs30
-rw-r--r--src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs26
-rw-r--r--src/mscorlib/shared/System/Diagnostics/Tracing/IEventProvider.cs2
-rw-r--r--src/mscorlib/shared/System/Diagnostics/Tracing/TraceLogging/EventSourceActivity.cs10
-rw-r--r--src/mscorlib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingDataType.cs2
-rw-r--r--src/mscorlib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs12
-rw-r--r--src/mscorlib/shared/System/DivideByZeroException.cs6
-rw-r--r--src/mscorlib/shared/System/DllNotFoundException.cs6
-rw-r--r--src/mscorlib/shared/System/Double.cs451
-rw-r--r--src/mscorlib/shared/System/DuplicateWaitObjectException.cs8
-rw-r--r--src/mscorlib/shared/System/EntryPointNotFoundException.cs6
-rw-r--r--src/mscorlib/shared/System/ExecutionEngineException.cs6
-rw-r--r--src/mscorlib/shared/System/FieldAccessException.cs6
-rw-r--r--src/mscorlib/shared/System/FormatException.cs6
-rw-r--r--src/mscorlib/shared/System/Globalization/DateTimeFormatInfo.cs6
-rw-r--r--src/mscorlib/shared/System/Globalization/DateTimeParse.cs321
-rw-r--r--src/mscorlib/shared/System/Globalization/EastAsianLunisolarCalendar.cs2
-rw-r--r--src/mscorlib/shared/System/Globalization/HijriCalendar.Win32.cs4
-rw-r--r--src/mscorlib/shared/System/Globalization/HijriCalendar.cs4
-rw-r--r--src/mscorlib/shared/System/Globalization/JapaneseCalendar.Win32.cs7
-rw-r--r--src/mscorlib/shared/System/Globalization/NumberFormatInfo.cs31
-rw-r--r--src/mscorlib/shared/System/Globalization/TimeSpanFormat.cs523
-rw-r--r--src/mscorlib/shared/System/Globalization/TimeSpanParse.cs1675
-rw-r--r--src/mscorlib/shared/System/Guid.cs1409
-rw-r--r--src/mscorlib/shared/System/HResults.cs126
-rw-r--r--src/mscorlib/shared/System/IO/BinaryWriter.cs36
-rw-r--r--src/mscorlib/shared/System/IO/DirectoryNotFoundException.cs6
-rw-r--r--src/mscorlib/shared/System/IO/DisableMediaInsertionPrompt.cs36
-rw-r--r--src/mscorlib/shared/System/IO/DriveNotFoundException.cs35
-rw-r--r--src/mscorlib/shared/System/IO/EndOfStreamException.cs6
-rw-r--r--src/mscorlib/shared/System/IO/FileLoadException.cs10
-rw-r--r--src/mscorlib/shared/System/IO/FileNotFoundException.cs12
-rw-r--r--src/mscorlib/shared/System/IO/FileStream.Unix.cs445
-rw-r--r--src/mscorlib/shared/System/IO/FileStream.Win32.cs45
-rw-r--r--src/mscorlib/shared/System/IO/FileStream.WinRT.cs32
-rw-r--r--src/mscorlib/shared/System/IO/FileStream.Windows.cs359
-rw-r--r--src/mscorlib/shared/System/IO/FileStream.cs170
-rw-r--r--src/mscorlib/shared/System/IO/FileStreamCompletionSource.Win32.cs59
-rw-r--r--src/mscorlib/shared/System/IO/IOException.cs41
-rw-r--r--src/mscorlib/shared/System/IO/Path.cs24
-rw-r--r--src/mscorlib/shared/System/IO/PathInternal.Windows.cs5
-rw-r--r--src/mscorlib/shared/System/IO/PathTooLongException.cs6
-rw-r--r--src/mscorlib/shared/System/IO/PinnedBufferMemoryStream.cs4
-rw-r--r--src/mscorlib/shared/System/IO/UnmanagedMemoryStream.cs156
-rw-r--r--src/mscorlib/shared/System/IO/UnmanagedMemoryStreamWrapper.cs20
-rw-r--r--src/mscorlib/shared/System/IO/Win32Marshal.cs20
-rw-r--r--src/mscorlib/shared/System/IndexOutOfRangeException.cs6
-rw-r--r--src/mscorlib/shared/System/InsufficientExecutionStackException.cs6
-rw-r--r--src/mscorlib/shared/System/Int16.cs320
-rw-r--r--src/mscorlib/shared/System/Int32.cs285
-rw-r--r--src/mscorlib/shared/System/Int64.cs262
-rw-r--r--src/mscorlib/shared/System/InvalidCastException.cs6
-rw-r--r--src/mscorlib/shared/System/InvalidOperationException.cs6
-rw-r--r--src/mscorlib/shared/System/InvalidProgramException.cs6
-rw-r--r--src/mscorlib/shared/System/Lazy.cs2
-rw-r--r--src/mscorlib/shared/System/MemberAccessException.cs6
-rw-r--r--src/mscorlib/shared/System/Memory.cs284
-rw-r--r--src/mscorlib/shared/System/MethodAccessException.cs6
-rw-r--r--src/mscorlib/shared/System/MissingMethodException.cs6
-rw-r--r--src/mscorlib/shared/System/MulticastNotSupportedException.cs6
-rw-r--r--src/mscorlib/shared/System/NonSerializedAttribute.cs14
-rw-r--r--src/mscorlib/shared/System/NotFiniteNumberException.cs12
-rw-r--r--src/mscorlib/shared/System/NotImplementedException.cs6
-rw-r--r--src/mscorlib/shared/System/NotSupportedException.cs6
-rw-r--r--src/mscorlib/shared/System/NullReferenceException.cs6
-rw-r--r--src/mscorlib/shared/System/ObjectDisposedException.cs4
-rw-r--r--src/mscorlib/shared/System/OperationCanceledException.cs6
-rw-r--r--src/mscorlib/shared/System/OverflowException.cs6
-rw-r--r--src/mscorlib/shared/System/PlatformNotSupportedException.cs6
-rw-r--r--src/mscorlib/shared/System/Random.cs38
-rw-r--r--src/mscorlib/shared/System/RankException.cs6
-rw-r--r--src/mscorlib/shared/System/ReadOnlyMemory.cs270
-rw-r--r--src/mscorlib/shared/System/ReadOnlySpan.cs50
-rw-r--r--src/mscorlib/shared/System/Reflection/AmbiguousMatchException.cs6
-rw-r--r--src/mscorlib/shared/System/Reflection/BindingFlags.cs1
-rw-r--r--src/mscorlib/shared/System/Reflection/CustomAttributeFormatException.cs2
-rw-r--r--src/mscorlib/shared/System/Reflection/IReflect.cs4
-rw-r--r--src/mscorlib/shared/System/Reflection/InvalidFilterCriteriaException.cs2
-rw-r--r--src/mscorlib/shared/System/Reflection/MethodInfo.Internal.cs17
-rw-r--r--src/mscorlib/shared/System/Reflection/MethodInfo.cs2
-rw-r--r--src/mscorlib/shared/System/Reflection/Pointer.cs2
-rw-r--r--src/mscorlib/shared/System/Reflection/ReflectionTypeLoadException.cs4
-rw-r--r--src/mscorlib/shared/System/Reflection/SignatureArrayType.cs46
-rw-r--r--src/mscorlib/shared/System/Reflection/SignatureByRefType.cs27
-rw-r--r--src/mscorlib/shared/System/Reflection/SignatureConstructedGenericType.cs73
-rw-r--r--src/mscorlib/shared/System/Reflection/SignatureGenericMethodParameterType.cs18
-rw-r--r--src/mscorlib/shared/System/Reflection/SignatureGenericParameterType.cs46
-rw-r--r--src/mscorlib/shared/System/Reflection/SignatureHasElementType.cs48
-rw-r--r--src/mscorlib/shared/System/Reflection/SignaturePointerType.cs27
-rw-r--r--src/mscorlib/shared/System/Reflection/SignatureType.cs139
-rw-r--r--src/mscorlib/shared/System/Reflection/SignatureTypeExtensions.cs227
-rw-r--r--src/mscorlib/shared/System/Reflection/TargetException.cs2
-rw-r--r--src/mscorlib/shared/System/Reflection/TargetInvocationException.cs4
-rw-r--r--src/mscorlib/shared/System/Reflection/TargetParameterCountException.cs6
-rw-r--r--src/mscorlib/shared/System/Reflection/TypeDelegator.cs1
-rw-r--r--src/mscorlib/shared/System/Resources/MissingManifestResourceException.cs6
-rw-r--r--src/mscorlib/shared/System/Resources/MissingSatelliteAssemblyException.cs8
-rw-r--r--src/mscorlib/shared/System/Runtime/CompilerServices/AsyncMethodBuilderAttribute.cs21
-rw-r--r--src/mscorlib/shared/System/Runtime/CompilerServices/AsyncValueTaskMethodBuilder.cs111
-rw-r--r--src/mscorlib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs71
-rw-r--r--src/mscorlib/shared/System/Runtime/CompilerServices/CustomConstantAttribute.cs12
-rw-r--r--src/mscorlib/shared/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs19
-rw-r--r--src/mscorlib/shared/System/Runtime/CompilerServices/DecimalConstantAttribute.cs39
-rw-r--r--src/mscorlib/shared/System/Runtime/CompilerServices/IntrinsicAttribute.cs13
-rw-r--r--src/mscorlib/shared/System/Runtime/CompilerServices/MethodImplAttribute.cs29
-rw-r--r--src/mscorlib/shared/System/Runtime/CompilerServices/RuntimeWrappedException.cs33
-rw-r--r--src/mscorlib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs37
-rw-r--r--src/mscorlib/shared/System/Runtime/ExceptionServices/HandleProcessCorruptedStateExceptionsAttribute.cs16
-rw-r--r--src/mscorlib/shared/System/Runtime/InteropServices/BestFitMappingAttribute.cs19
-rw-r--r--src/mscorlib/shared/System/Runtime/InteropServices/DefaultCharSetAttribute.cs17
-rw-r--r--src/mscorlib/shared/System/Runtime/InteropServices/DefaultDllImportSearchPathsAttribute.cs17
-rw-r--r--src/mscorlib/shared/System/Runtime/InteropServices/DllImportAttribute.cs26
-rw-r--r--src/mscorlib/shared/System/Runtime/InteropServices/DllImportSearchPath.cs18
-rw-r--r--src/mscorlib/shared/System/Runtime/InteropServices/ExternalException.cs6
-rw-r--r--src/mscorlib/shared/System/Runtime/InteropServices/FieldOffsetAttribute.cs17
-rw-r--r--src/mscorlib/shared/System/Runtime/InteropServices/InAttribute.cs14
-rw-r--r--src/mscorlib/shared/System/Runtime/InteropServices/MarshalAsAttribute.cs39
-rw-r--r--src/mscorlib/shared/System/Runtime/InteropServices/OptionalAttribute.cs14
-rw-r--r--src/mscorlib/shared/System/Runtime/InteropServices/OutAttribute.cs14
-rw-r--r--src/mscorlib/shared/System/Runtime/InteropServices/PreserveSigAttribute.cs14
-rw-r--r--src/mscorlib/shared/System/Runtime/InteropServices/StructLayoutAttribute.cs26
-rw-r--r--src/mscorlib/shared/System/Runtime/InteropServices/UnmanagedFunctionPointerAttribute.cs10
-rw-r--r--src/mscorlib/shared/System/Runtime/Serialization/SerializationException.cs6
-rw-r--r--src/mscorlib/shared/System/SByte.cs328
-rw-r--r--src/mscorlib/shared/System/Security/SecurityException.cs10
-rw-r--r--src/mscorlib/shared/System/Security/VerificationException.cs6
-rw-r--r--src/mscorlib/shared/System/SerializableAttribute.cs12
-rw-r--r--src/mscorlib/shared/System/Single.cs442
-rw-r--r--src/mscorlib/shared/System/Span.NonGeneric.cs2
-rw-r--r--src/mscorlib/shared/System/Span.cs55
-rw-r--r--src/mscorlib/shared/System/StackOverflowException.cs6
-rw-r--r--src/mscorlib/shared/System/StringSpanHelpers.cs93
-rw-r--r--src/mscorlib/shared/System/SystemException.cs6
-rw-r--r--src/mscorlib/shared/System/Text/Decoder.cs26
-rw-r--r--src/mscorlib/shared/System/Text/DecoderExceptionFallback.cs6
-rw-r--r--src/mscorlib/shared/System/Text/Encoder.cs26
-rw-r--r--src/mscorlib/shared/System/Text/EncoderExceptionFallback.cs6
-rw-r--r--src/mscorlib/shared/System/Text/Encoding.cs44
-rw-r--r--src/mscorlib/shared/System/Text/Normalization.cs15
-rw-r--r--src/mscorlib/shared/System/Text/StringBuilder.cs77
-rw-r--r--src/mscorlib/shared/System/Text/UTF32Encoding.cs7
-rw-r--r--src/mscorlib/shared/System/Text/UTF8Encoding.cs10
-rw-r--r--src/mscorlib/shared/System/Text/UnicodeEncoding.cs7
-rw-r--r--src/mscorlib/shared/System/Threading/AbandonedMutexException.cs12
-rw-r--r--src/mscorlib/shared/System/Threading/DeferredDisposableLifetime.cs2
-rw-r--r--src/mscorlib/shared/System/Threading/LazyInitializer.cs2
-rw-r--r--src/mscorlib/shared/System/Threading/ReaderWriterLockSlim.cs240
-rw-r--r--src/mscorlib/shared/System/Threading/SpinWait.cs98
-rw-r--r--src/mscorlib/shared/System/Threading/SynchronizationLockException.cs6
-rw-r--r--src/mscorlib/shared/System/Threading/Tasks/ValueTask.cs169
-rw-r--r--src/mscorlib/shared/System/Threading/ThreadAbortException.cs2
-rw-r--r--src/mscorlib/shared/System/Threading/ThreadStartException.cs4
-rw-r--r--src/mscorlib/shared/System/Threading/ThreadStateException.cs6
-rw-r--r--src/mscorlib/shared/System/Threading/TimeoutHelper.cs4
-rw-r--r--src/mscorlib/shared/System/Threading/WaitHandleCannotBeOpenedException.cs6
-rw-r--r--src/mscorlib/shared/System/TimeSpan.cs80
-rw-r--r--src/mscorlib/shared/System/TimeoutException.cs6
-rw-r--r--src/mscorlib/shared/System/Type.cs32
-rw-r--r--src/mscorlib/shared/System/TypeAccessException.cs6
-rw-r--r--src/mscorlib/shared/System/TypeInitializationException.cs6
-rw-r--r--src/mscorlib/shared/System/TypeUnloadedException.cs6
-rw-r--r--src/mscorlib/shared/System/UInt16.cs292
-rw-r--r--src/mscorlib/shared/System/UInt32.cs269
-rw-r--r--src/mscorlib/shared/System/UInt64.cs265
-rw-r--r--src/mscorlib/shared/System/UnauthorizedAccessException.cs6
-rw-r--r--src/mscorlib/shared/System/UnitySerializationHolder.cs66
-rw-r--r--src/mscorlib/shared/System/Version.cs340
206 files changed, 13933 insertions, 1530 deletions
diff --git a/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.Collation.cs b/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.Collation.cs
index 79aedd74d3..683845dbc1 100644
--- a/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.Collation.cs
+++ b/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.Collation.cs
@@ -44,7 +44,7 @@ internal static partial class Interop
internal unsafe static extern int CompareStringOrdinalIgnoreCase(char* lpStr1, int cwStr1Len, char* lpStr2, int cwStr2Len);
[DllImport(Libraries.GlobalizationInterop, EntryPoint = "GlobalizationNative_GetSortVersion")]
- internal static extern int GetSortVersion();
+ internal static extern int GetSortVersion(SafeSortHandle sortHandle);
internal class SafeSortHandle : SafeHandle
{
diff --git a/src/mscorlib/shared/Interop/Unix/System.Native/Interop.PosixFAdvise.cs b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.PosixFAdvise.cs
index 69e39b30d2..ad8b73aed2 100644
--- a/src/mscorlib/shared/Interop/Unix/System.Native/Interop.PosixFAdvise.cs
+++ b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.PosixFAdvise.cs
@@ -16,7 +16,7 @@ internal static partial class Interop
POSIX_FADV_SEQUENTIAL = 2, /* sequential I/O access */
POSIX_FADV_WILLNEED = 3, /* will need specified pages */
POSIX_FADV_DONTNEED = 4, /* don't need the specified pages */
- POSIX_FADV_NOREUSE = 5, /* data will only be acessed once */
+ POSIX_FADV_NOREUSE = 5, /* data will only be accessed once */
}
/// <summary>
diff --git a/src/mscorlib/shared/Interop/Windows/Interop.Libraries.cs b/src/mscorlib/shared/Interop/Windows/Interop.Libraries.cs
index f65e05cfdd..45d910bfcc 100644
--- a/src/mscorlib/shared/Interop/Windows/Interop.Libraries.cs
+++ b/src/mscorlib/shared/Interop/Windows/Interop.Libraries.cs
@@ -9,6 +9,7 @@ internal static partial class Interop
internal const string BCrypt = "BCrypt.dll";
internal const string Crypt32 = "crypt32.dll";
internal const string Kernel32 = "kernel32.dll";
+ internal const string Ole32 = "ole32.dll";
internal const string OleAut32 = "oleaut32.dll";
internal const string User32 = "user32.dll";
}
diff --git a/src/mscorlib/shared/Interop/Windows/Kernel32/Interop.CREATEFILE2_EXTENDED_PARAMETERS.cs b/src/mscorlib/shared/Interop/Windows/Kernel32/Interop.CREATEFILE2_EXTENDED_PARAMETERS.cs
new file mode 100644
index 0000000000..16365ee651
--- /dev/null
+++ b/src/mscorlib/shared/Interop/Windows/Kernel32/Interop.CREATEFILE2_EXTENDED_PARAMETERS.cs
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Win32.SafeHandles;
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Kernel32
+ {
+ internal unsafe struct CREATEFILE2_EXTENDED_PARAMETERS
+ {
+ internal uint dwSize;
+ internal uint dwFileAttributes;
+ internal uint dwFileFlags;
+ internal uint dwSecurityQosFlags;
+ internal SECURITY_ATTRIBUTES* lpSecurityAttributes;
+ internal IntPtr hTemplateFile;
+ }
+ }
+}
diff --git a/src/mscorlib/shared/Interop/Windows/Kernel32/Interop.CreateFile2.cs b/src/mscorlib/shared/Interop/Windows/Kernel32/Interop.CreateFile2.cs
index 0909d3a6c8..ddc18f6c42 100644
--- a/src/mscorlib/shared/Interop/Windows/Kernel32/Interop.CreateFile2.cs
+++ b/src/mscorlib/shared/Interop/Windows/Kernel32/Interop.CreateFile2.cs
@@ -3,29 +3,30 @@
// See the LICENSE file in the project root for more information.
using Microsoft.Win32.SafeHandles;
-using System;
+using System.IO;
using System.Runtime.InteropServices;
internal partial class Interop
{
internal partial class Kernel32
{
- [DllImport(Libraries.Kernel32, EntryPoint = "CreateFile2", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false)]
- internal static extern unsafe SafeFileHandle CreateFile2(
+ [DllImport(Libraries.Kernel32, EntryPoint = "CreateFile2", SetLastError = true, CharSet = CharSet.Unicode)]
+ private static extern SafeFileHandle CreateFile2Private(
string lpFileName,
int dwDesiredAccess,
- System.IO.FileShare dwShareMode,
- System.IO.FileMode dwCreationDisposition,
- CREATEFILE2_EXTENDED_PARAMETERS* pCreateExParams);
+ FileShare dwShareMode,
+ FileMode dwCreationDisposition,
+ ref Kernel32.CREATEFILE2_EXTENDED_PARAMETERS pCreateExParams);
- internal unsafe struct CREATEFILE2_EXTENDED_PARAMETERS
+ internal static SafeFileHandle CreateFile2(
+ string lpFileName,
+ int dwDesiredAccess,
+ FileShare dwShareMode,
+ FileMode dwCreationDisposition,
+ ref Kernel32.CREATEFILE2_EXTENDED_PARAMETERS pCreateExParams)
{
- internal uint dwSize;
- internal uint dwFileAttributes;
- internal uint dwFileFlags;
- internal uint dwSecurityQosFlags;
- internal SECURITY_ATTRIBUTES* lpSecurityAttributes;
- internal IntPtr hTemplateFile;
+ lpFileName = PathInternal.EnsureExtendedPrefixOverMaxPath(lpFileName);
+ return CreateFile2Private(lpFileName, dwDesiredAccess, dwShareMode, dwCreationDisposition, ref pCreateExParams);
}
}
-} \ No newline at end of file
+}
diff --git a/src/mscorlib/shared/Interop/Windows/Kernel32/Interop.FreeLibrary.cs b/src/mscorlib/shared/Interop/Windows/Kernel32/Interop.FreeLibrary.cs
new file mode 100644
index 0000000000..c70865350a
--- /dev/null
+++ b/src/mscorlib/shared/Interop/Windows/Kernel32/Interop.FreeLibrary.cs
@@ -0,0 +1,15 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Kernel32
+ {
+ [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
+ internal static extern bool FreeLibrary(IntPtr hModule);
+ }
+}
diff --git a/src/mscorlib/shared/Interop/Windows/Kernel32/Interop.LoadLibraryEx.cs b/src/mscorlib/shared/Interop/Windows/Kernel32/Interop.LoadLibraryEx.cs
new file mode 100644
index 0000000000..4eef5852fe
--- /dev/null
+++ b/src/mscorlib/shared/Interop/Windows/Kernel32/Interop.LoadLibraryEx.cs
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Win32.SafeHandles;
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Kernel32
+ {
+ internal const int LOAD_LIBRARY_AS_DATAFILE = 0x00000002;
+
+ [DllImport(Libraries.Kernel32, EntryPoint = "LoadLibraryExW", CharSet = CharSet.Unicode, SetLastError = true)]
+ internal static extern SafeLibraryHandle LoadLibraryEx(string libFilename, IntPtr reserved, int flags);
+ }
+}
diff --git a/src/mscorlib/shared/Interop/Windows/User32/Interop.LoadString.cs b/src/mscorlib/shared/Interop/Windows/User32/Interop.LoadString.cs
new file mode 100644
index 0000000000..d3d575e221
--- /dev/null
+++ b/src/mscorlib/shared/Interop/Windows/User32/Interop.LoadString.cs
@@ -0,0 +1,16 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+using System.Text;
+using Microsoft.Win32.SafeHandles;
+
+internal partial class Interop
+{
+ internal partial class User32
+ {
+ [DllImport(Libraries.User32, SetLastError = true, EntryPoint = "LoadStringW", CharSet = CharSet.Unicode)]
+ internal static extern int LoadString(SafeLibraryHandle handle, int id, [Out] StringBuilder buffer, int bufferLength);
+ }
+}
diff --git a/src/mscorlib/shared/Microsoft/Win32/SafeHandles/SafeLibraryHandle.cs b/src/mscorlib/shared/Microsoft/Win32/SafeHandles/SafeLibraryHandle.cs
new file mode 100644
index 0000000000..3be2e354ab
--- /dev/null
+++ b/src/mscorlib/shared/Microsoft/Win32/SafeHandles/SafeLibraryHandle.cs
@@ -0,0 +1,16 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Microsoft.Win32.SafeHandles
+{
+ sealed internal class SafeLibraryHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ internal SafeLibraryHandle() : base(true) { }
+
+ override protected bool ReleaseHandle()
+ {
+ return Interop.Kernel32.FreeLibrary(handle);
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System.Private.CoreLib.Shared.projitems b/src/mscorlib/shared/System.Private.CoreLib.Shared.projitems
index 07e15cf65d..a13543ea93 100644
--- a/src/mscorlib/shared/System.Private.CoreLib.Shared.projitems
+++ b/src/mscorlib/shared/System.Private.CoreLib.Shared.projitems
@@ -13,13 +13,20 @@
<TargetsUnix Condition="'$(TargetsUnix)' != 'true'">false</TargetsUnix>
<TargetsOSX Condition="'$(TargetsOSX)' != 'true'">false</TargetsOSX>
</PropertyGroup>
+ <ItemDefinitionGroup>
+ <Compile>
+ <Visible>true</Visible>
+ </Compile>
+ </ItemDefinitionGroup>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\CriticalHandleMinusOneIsInvalid.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\CriticalHandleZeroOrMinusOneIsInvalid.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeHandleMinusOneIsInvalid.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeHandleZeroOrMinusOneIsInvalid.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Action.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\AccessViolationException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ApplicationException.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\AggregateException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ArgumentException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ArgumentNullException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ArgumentOutOfRangeException.cs" />
@@ -32,10 +39,16 @@
<Compile Include="$(MSBuildThisFileDirectory)System\AttributeUsageAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\BadImageFormatException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\BitConverter.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Boolean.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Buffers\ArrayPool.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Buffers\ArrayPoolEventSource.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Buffers\ConfigurableArrayPool.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Buffers\IRetainable.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Buffers\MemoryHandle.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Buffers\OwnedMemory.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Buffers\TlsOverPerCoreLockedStacksArrayPool.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Buffers\Utilities.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Byte.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Char.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\CharEnumerator.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\CLSCompliantAttribute.cs" />
@@ -62,6 +75,9 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\IList.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\IStructuralComparable.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\IStructuralEquatable.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Collections\ListDictionaryInternal.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Collections\ObjectModel\Collection.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Collections\ObjectModel\ReadOnlyCollection.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ComponentModel\DefaultValueAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ComponentModel\EditorBrowsableAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Configuration\Assemblies\AssemblyHashAlgorithm.cs" />
@@ -80,6 +96,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Debug.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\DivideByZeroException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\DllNotFoundException.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Double.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\DuplicateWaitObjectException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\EntryPointNotFoundException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\EventArgs.cs" />
@@ -127,9 +144,13 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\TaiwanLunisolarCalendar.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\TextElementEnumerator.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\ThaiBuddhistCalendar.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Globalization\TimeSpanFormat.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Globalization\TimeSpanParse.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\TimeSpanStyles.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\UmAlQuraCalendar.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\UnicodeCategory.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Guid.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\HResults.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IAsyncResult.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ICloneable.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IComparable.cs" />
@@ -147,6 +168,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\InvalidTimeZoneException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\BinaryWriter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\DirectoryNotFoundException.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\IO\DriveNotFoundException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\EncodingCache.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\EndOfStreamException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\Error.cs" />
@@ -157,6 +179,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\IO\FileOptions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\FileShare.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\FileStream.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\IO\IOException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\Path.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\PathInternal.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\PathTooLongException.cs" />
@@ -168,15 +191,20 @@
<Compile Include="$(MSBuildThisFileDirectory)System\IObservable.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IObserver.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IProgress.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Int16.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Int32.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Int64.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Lazy.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\MarshalByRefObject.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\MemberAccessException.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Memory.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\MethodAccessException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\MidpointRounding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\MissingMethodException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\MulticastNotSupportedException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\NotFiniteNumberException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\NotImplementedException.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\NonSerializedAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\NotSupportedException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\NullReferenceException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ObjectDisposedException.cs" />
@@ -190,6 +218,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Random.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\RankException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ReadOnlySpan.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\ReadOnlyMemory.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\AmbiguousMatchException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\Assembly.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\AssemblyAlgorithmIdAttribute.cs" />
@@ -241,6 +270,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\MethodBase.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\MethodImplAttributes.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\MethodInfo.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\MethodInfo.Internal.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\Missing.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\Module.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\ModuleResolveEventHandler.cs" />
@@ -258,6 +288,15 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\ReflectionTypeLoadException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\ResourceAttributes.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\ResourceLocation.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\SignatureArrayType.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\SignatureByRefType.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\SignatureConstructedGenericType.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\SignatureGenericMethodParameterType.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\SignatureGenericParameterType.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\SignatureHasElementType.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\SignaturePointerType.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\SignatureType.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\SignatureTypeExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\StrongNameKeyPair.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\TargetException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\TargetInvocationException.cs" />
@@ -278,7 +317,9 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Resources\SatelliteContractVersionAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Resources\UltimateResourceFallbackLocation.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\AccessedThroughPropertyAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\AsyncMethodBuilderAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\AsyncStateMachineAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\AsyncValueTaskMethodBuilder.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\CallerFilePathAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\CallerLineNumberAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\CallerMemberNameAttribute.cs" />
@@ -286,6 +327,10 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\CompilationRelaxationsAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\CompilerGeneratedAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\CompilerGlobalScopeAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\ConfiguredValueTaskAwaitable.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\CustomConstantAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\DateTimeConstantAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\DecimalConstantAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\DefaultDependencyAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\DependencyAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\DisablePrivateReflectionAttribute.cs" />
@@ -298,6 +343,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\IndexerNameAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\INotifyCompletion.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\InternalsVisibleToAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\IntrinsicAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\IsConst.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\IsByRefLikeAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\IsVolatile.cs" />
@@ -305,11 +351,13 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\ITuple.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\LoadHint.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\MethodCodeType.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\MethodImplAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\MethodImplOptions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\IsReadOnlyAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\ReferenceAssemblyAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\RuntimeCompatibilityAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\RuntimeFeature.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\RuntimeWrappedException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\SpecialNameAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\StateMachineAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\StringFreezingAttribute.cs" />
@@ -319,15 +367,29 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\TypeForwardedFromAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\TypeForwardedToAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\UnsafeValueTypeAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\ValueTaskAwaiter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\ConstrainedExecution\Cer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\ConstrainedExecution\Consistency.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\ConstrainedExecution\ReliabilityContractAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\ExceptionServices\HandleProcessCorruptedStateExceptionsAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\BestFitMappingAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\CallingConvention.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\CharSet.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\ComVisibleAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\DefaultCharSetAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\DefaultDllImportSearchPathsAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\DllImportAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\DllImportSearchPath.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\ExternalException.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\FieldOffsetAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\InAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\LayoutKind.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\MarshalAsAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\OptionalAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\OutAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\PreserveSigAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\StringBuffer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\StructLayoutAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\UnmanagedFunctionPointerAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\UnmanagedType.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\VarEnum.cs" />
@@ -347,6 +409,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Serialization\StreamingContext.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Versioning\NonVersionableAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Versioning\TargetFrameworkAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\SByte.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Security\AllowPartiallyTrustedCallersAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Security\CryptographicException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Security\PartialTrustVisibilityLevel.cs" />
@@ -362,8 +425,11 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Security\SuppressUnmanagedCodeSecurityAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Security\UnverifiableCodeAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Security\VerificationException.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\SerializableAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Single.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Span.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Span.NonGeneric.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\StringSpanHelpers.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\StackOverflowException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\StringComparer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\StringComparison.cs" />
@@ -391,7 +457,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Text\StringBuilder.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Text\UnicodeEncoding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Text\UTF32Encoding.cs" />
- <Compile Include="$(MSBuildThisFileDirectory)System\Text\UTF7Encoding.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Text\UTF7Encoding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Text\UTF8Encoding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\TimeSpan.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ThreadAttributes.cs" />
@@ -415,6 +481,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Tasks\TaskCanceledException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Tasks\TaskExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Tasks\TaskSchedulerException.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Threading\Tasks\ValueTask.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\ThreadAbortException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\ThreadPriority.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\ThreadStart.cs" />
@@ -436,9 +503,13 @@
<Compile Include="$(MSBuildThisFileDirectory)System\TypeCode.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\TypeInitializationException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\TypeUnloadedException.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\UInt16.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\UInt32.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\UInt64.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\UnauthorizedAccessException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\UnhandledExceptionEventArgs.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\UnhandledExceptionEventHandler.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\UnitySerializationHolder.cs"/>
<Compile Include="$(MSBuildThisFileDirectory)System\ValueTuple.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Version.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Void.cs" />
@@ -488,19 +559,15 @@
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\BCrypt\Interop.BCryptGenRandom.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Crypt32\Interop.CryptProtectMemory.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Interop.BOOL.cs" />
- <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Interop.Errors.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Interop.Libraries.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.CancelIoEx.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.CloseHandle.cs" />
- <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.CreateFile.cs" Condition="'$(EnableWinRT)' != 'true'" />
- <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.CreateFile2.cs" Condition="'$(EnableWinRT)' == 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FileAttributes.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FILE_INFO_BY_HANDLE_CLASS.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FileTypes.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FindClose.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FindFirstFileEx.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FlushFileBuffers.cs" />
- <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FormatMessage.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FreeEnvironmentStrings.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetCPInfo.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetEnvironmentStrings.cs" />
@@ -528,25 +595,41 @@
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\OleAut32\Interop.SysAllocStringLen.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\OleAut32\Interop.SysFreeString.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\OleAut32\Interop.SysStringLen.cs" />
- <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\User32\Interop.Constants.cs" Condition="'$(EnableWinRT)' != 'true'" />
- <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\User32\Interop.SendMessageTimeout.cs" Condition="'$(EnableWinRT)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeFileHandle.Windows.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\HijriCalendar.Win32.cs" Condition="'$(EnableWinRT)' != 'true' and '$(EnableDummyGlobalizationImplementation)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\HijriCalendar.WinRT.cs" Condition="'$(EnableWinRT)' == 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\JapaneseCalendar.Win32.cs" Condition="'$(EnableWinRT)' != 'true' and '$(EnableDummyGlobalizationImplementation)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\JapaneseCalendar.WinRT.cs" Condition="'$(EnableWinRT)' == 'true'" />
- <Compile Include="$(MSBuildThisFileDirectory)System\IO\FileStream.Win32.cs" Condition="'$(EnableWinRT)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\FileStream.Windows.cs" />
- <Compile Include="$(MSBuildThisFileDirectory)System\IO\FileStream.WinRT.cs" Condition="'$(EnableWinRT)' == 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\FileStreamCompletionSource.Win32.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\Path.Windows.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\PathHelper.Windows.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\PathInternal.Windows.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\PathInternal.Windows.StringBuffer.cs" />
- <Compile Include="$(MSBuildThisFileDirectory)System\IO\Win32Marshal.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\IO\DisableMediaInsertionPrompt.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Security\SafeBSTRHandle.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Security\SecureString.Windows.cs" />
</ItemGroup>
+ <ItemGroup Condition="$(TargetsWindows) and '$(EnableWinRT)' != 'true'">
+ <Compile Include="$(MSBuildThisFileDirectory)System\IO\FileStream.Win32.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeLibraryHandle.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.LoadLibraryEx.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FreeLibrary.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.CreateFile.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\User32\Interop.Constants.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\User32\Interop.SendMessageTimeout.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\User32\Interop.LoadString.cs" />
+ </ItemGroup>
+ <ItemGroup Condition="$(TargetsWindows) and '$(EnableWinRT)' == 'true'">
+ <Compile Include="$(MSBuildThisFileDirectory)System\IO\FileStream.WinRT.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.CreateFile2.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.CREATEFILE2_EXTENDED_PARAMETERS.cs" />
+ </ItemGroup>
+ <ItemGroup Condition="$(TargetsWindows) or '$(FeaturePal)'=='true'">
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Interop.Errors.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FormatMessage.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\IO\Win32Marshal.cs" />
+ </ItemGroup>
<ItemGroup Condition="$(TargetsUnix)">
<Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\Interop.Errors.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\Interop.IOErrors.cs" />
diff --git a/src/mscorlib/shared/System.Private.CoreLib.Shared.shproj b/src/mscorlib/shared/System.Private.CoreLib.Shared.shproj
deleted file mode 100644
index 20c3de100b..0000000000
--- a/src/mscorlib/shared/System.Private.CoreLib.Shared.shproj
+++ /dev/null
@@ -1,17 +0,0 @@
-<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <!-- Set the properties to prevent any items from being excluded from the IDE view -->
- <PropertyGroup Label="Globals">
- <ProjectGuid>c5ed3c1d-b572-46f1-8f96-522a85ce1179</ProjectGuid>
- </PropertyGroup>
- <PropertyGroup>
- <TargetsWindows>true</TargetsWindows>
- <TargetsUnix>true</TargetsUnix>
- <TargetsOSX>true</TargetsOSX>
- </PropertyGroup>
- <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
- <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
- <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
- <PropertyGroup />
- <Import Project="System.Private.CoreLib.Shared.projitems" Label="Shared" />
- <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
-</Project> \ No newline at end of file
diff --git a/src/mscorlib/shared/System/AccessViolationException.cs b/src/mscorlib/shared/System/AccessViolationException.cs
new file mode 100644
index 0000000000..103a4c0a9d
--- /dev/null
+++ b/src/mscorlib/shared/System/AccessViolationException.cs
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Exception class representing an AV that was deemed unsafe and may have corrupted the application.
+**
+**
+=============================================================================*/
+
+using System;
+using System.Runtime.Serialization;
+
+namespace System
+{
+ public class AccessViolationException : SystemException
+ {
+ public AccessViolationException()
+ : base(SR.Arg_AccessViolationException)
+ {
+ HResult = HResults.E_POINTER;
+ }
+
+ public AccessViolationException(String message)
+ : base(message)
+ {
+ HResult = HResults.E_POINTER;
+ }
+
+ public AccessViolationException(String message, Exception innerException)
+ : base(message, innerException)
+ {
+ HResult = HResults.E_POINTER;
+ }
+
+ protected AccessViolationException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+#pragma warning disable 169 // Field is not used from managed.
+ private IntPtr _ip; // Address of faulting instruction.
+ private IntPtr _target; // Address that could not be accessed.
+ private int _accessType; // 0:read, 1:write
+#pragma warning restore 169
+ }
+}
diff --git a/src/mscorlib/shared/System/Action.cs b/src/mscorlib/shared/System/Action.cs
index b82c14d9dc..da6813829e 100644
--- a/src/mscorlib/shared/System/Action.cs
+++ b/src/mscorlib/shared/System/Action.cs
@@ -33,3 +33,9 @@ namespace System
public delegate bool Predicate<in T>(T obj);
}
+
+namespace System.Buffers
+{
+ public delegate void SpanAction<T, in TArg>(Span<T> span, TArg arg);
+ public delegate void ReadOnlySpanAction<T, in TArg>(ReadOnlySpan<T> span, TArg arg);
+}
diff --git a/src/mscorlib/shared/System/AggregateException.cs b/src/mscorlib/shared/System/AggregateException.cs
new file mode 100644
index 0000000000..36b9494980
--- /dev/null
+++ b/src/mscorlib/shared/System/AggregateException.cs
@@ -0,0 +1,484 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Globalization;
+using System.Runtime.ExceptionServices;
+using System.Runtime.Serialization;
+using System.Security;
+using System.Text;
+using System.Threading;
+
+namespace System
+{
+ /// <summary>Represents one or more errors that occur during application execution.</summary>
+ /// <remarks>
+ /// <see cref="AggregateException"/> is used to consolidate multiple failures into a single, throwable
+ /// exception object.
+ /// </remarks>
+ [Serializable]
+ [DebuggerDisplay("Count = {InnerExceptionCount}")]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ public class AggregateException : Exception
+ {
+ private ReadOnlyCollection<Exception> m_innerExceptions; // Complete set of exceptions. Do not rename (binary serialization)
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AggregateException"/> class.
+ /// </summary>
+ public AggregateException()
+ : base(SR.AggregateException_ctor_DefaultMessage)
+ {
+ m_innerExceptions = new ReadOnlyCollection<Exception>(Array.Empty<Exception>());
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AggregateException"/> class with
+ /// a specified error message.
+ /// </summary>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ public AggregateException(string message)
+ : base(message)
+ {
+ m_innerExceptions = new ReadOnlyCollection<Exception>(Array.Empty<Exception>());
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AggregateException"/> class with a specified error
+ /// message and a reference to the inner exception that is the cause of this exception.
+ /// </summary>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerException">The exception that is the cause of the current exception.</param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="innerException"/> argument
+ /// is null.</exception>
+ public AggregateException(string message, Exception innerException)
+ : base(message, innerException)
+ {
+ if (innerException == null)
+ {
+ throw new ArgumentNullException(nameof(innerException));
+ }
+
+ m_innerExceptions = new ReadOnlyCollection<Exception>(new Exception[] { innerException });
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AggregateException"/> class with
+ /// references to the inner exceptions that are the cause of this exception.
+ /// </summary>
+ /// <param name="innerExceptions">The exceptions that are the cause of the current exception.</param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="innerExceptions"/> argument
+ /// is null.</exception>
+ /// <exception cref="T:System.ArgumentException">An element of <paramref name="innerExceptions"/> is
+ /// null.</exception>
+ public AggregateException(IEnumerable<Exception> innerExceptions) :
+ this(SR.AggregateException_ctor_DefaultMessage, innerExceptions)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AggregateException"/> class with
+ /// references to the inner exceptions that are the cause of this exception.
+ /// </summary>
+ /// <param name="innerExceptions">The exceptions that are the cause of the current exception.</param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="innerExceptions"/> argument
+ /// is null.</exception>
+ /// <exception cref="T:System.ArgumentException">An element of <paramref name="innerExceptions"/> is
+ /// null.</exception>
+ public AggregateException(params Exception[] innerExceptions) :
+ this(SR.AggregateException_ctor_DefaultMessage, innerExceptions)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AggregateException"/> class with a specified error
+ /// message and references to the inner exceptions that are the cause of this exception.
+ /// </summary>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerExceptions">The exceptions that are the cause of the current exception.</param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="innerExceptions"/> argument
+ /// is null.</exception>
+ /// <exception cref="T:System.ArgumentException">An element of <paramref name="innerExceptions"/> is
+ /// null.</exception>
+ public AggregateException(string message, IEnumerable<Exception> innerExceptions)
+ // If it's already an IList, pass that along (a defensive copy will be made in the delegated ctor). If it's null, just pass along
+ // null typed correctly. Otherwise, create an IList from the enumerable and pass that along.
+ : this(message, innerExceptions as IList<Exception> ?? (innerExceptions == null ? (List<Exception>)null : new List<Exception>(innerExceptions)))
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AggregateException"/> class with a specified error
+ /// message and references to the inner exceptions that are the cause of this exception.
+ /// </summary>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerExceptions">The exceptions that are the cause of the current exception.</param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="innerExceptions"/> argument
+ /// is null.</exception>
+ /// <exception cref="T:System.ArgumentException">An element of <paramref name="innerExceptions"/> is
+ /// null.</exception>
+ public AggregateException(string message, params Exception[] innerExceptions) :
+ this(message, (IList<Exception>)innerExceptions)
+ {
+ }
+
+ /// <summary>
+ /// Allocates a new aggregate exception with the specified message and list of inner exceptions.
+ /// </summary>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerExceptions">The exceptions that are the cause of the current exception.</param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="innerExceptions"/> argument
+ /// is null.</exception>
+ /// <exception cref="T:System.ArgumentException">An element of <paramref name="innerExceptions"/> is
+ /// null.</exception>
+ private AggregateException(string message, IList<Exception> innerExceptions)
+ : base(message, innerExceptions != null && innerExceptions.Count > 0 ? innerExceptions[0] : null)
+ {
+ if (innerExceptions == null)
+ {
+ throw new ArgumentNullException(nameof(innerExceptions));
+ }
+
+ // Copy exceptions to our internal array and validate them. We must copy them,
+ // because we're going to put them into a ReadOnlyCollection which simply reuses
+ // the list passed in to it. We don't want callers subsequently mutating.
+ Exception[] exceptionsCopy = new Exception[innerExceptions.Count];
+
+ for (int i = 0; i < exceptionsCopy.Length; i++)
+ {
+ exceptionsCopy[i] = innerExceptions[i];
+
+ if (exceptionsCopy[i] == null)
+ {
+ throw new ArgumentException(SR.AggregateException_ctor_InnerExceptionNull);
+ }
+ }
+
+ m_innerExceptions = new ReadOnlyCollection<Exception>(exceptionsCopy);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AggregateException"/> class with
+ /// references to the inner exception dispatch info objects that represent the cause of this exception.
+ /// </summary>
+ /// <param name="innerExceptionInfos">
+ /// Information about the exceptions that are the cause of the current exception.
+ /// </param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="innerExceptionInfos"/> argument
+ /// is null.</exception>
+ /// <exception cref="T:System.ArgumentException">An element of <paramref name="innerExceptionInfos"/> is
+ /// null.</exception>
+ internal AggregateException(IEnumerable<ExceptionDispatchInfo> innerExceptionInfos) :
+ this(SR.AggregateException_ctor_DefaultMessage, innerExceptionInfos)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AggregateException"/> class with a specified error
+ /// message and references to the inner exception dispatch info objects that represent the cause of
+ /// this exception.
+ /// </summary>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerExceptionInfos">
+ /// Information about the exceptions that are the cause of the current exception.
+ /// </param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="innerExceptionInfos"/> argument
+ /// is null.</exception>
+ /// <exception cref="T:System.ArgumentException">An element of <paramref name="innerExceptionInfos"/> is
+ /// null.</exception>
+ internal AggregateException(string message, IEnumerable<ExceptionDispatchInfo> innerExceptionInfos)
+ // If it's already an IList, pass that along (a defensive copy will be made in the delegated ctor). If it's null, just pass along
+ // null typed correctly. Otherwise, create an IList from the enumerable and pass that along.
+ : this(message, innerExceptionInfos as IList<ExceptionDispatchInfo> ??
+ (innerExceptionInfos == null ?
+ (List<ExceptionDispatchInfo>)null :
+ new List<ExceptionDispatchInfo>(innerExceptionInfos)))
+ {
+ }
+
+ /// <summary>
+ /// Allocates a new aggregate exception with the specified message and list of inner
+ /// exception dispatch info objects.
+ /// </summary>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerExceptionInfos">
+ /// Information about the exceptions that are the cause of the current exception.
+ /// </param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="innerExceptionInfos"/> argument
+ /// is null.</exception>
+ /// <exception cref="T:System.ArgumentException">An element of <paramref name="innerExceptionInfos"/> is
+ /// null.</exception>
+ private AggregateException(string message, IList<ExceptionDispatchInfo> innerExceptionInfos)
+ : base(message, innerExceptionInfos != null && innerExceptionInfos.Count > 0 && innerExceptionInfos[0] != null ?
+ innerExceptionInfos[0].SourceException : null)
+ {
+ if (innerExceptionInfos == null)
+ {
+ throw new ArgumentNullException(nameof(innerExceptionInfos));
+ }
+
+ // Copy exceptions to our internal array and validate them. We must copy them,
+ // because we're going to put them into a ReadOnlyCollection which simply reuses
+ // the list passed in to it. We don't want callers subsequently mutating.
+ Exception[] exceptionsCopy = new Exception[innerExceptionInfos.Count];
+
+ for (int i = 0; i < exceptionsCopy.Length; i++)
+ {
+ var edi = innerExceptionInfos[i];
+ if (edi != null) exceptionsCopy[i] = edi.SourceException;
+
+ if (exceptionsCopy[i] == null)
+ {
+ throw new ArgumentException(SR.AggregateException_ctor_InnerExceptionNull);
+ }
+ }
+
+ m_innerExceptions = new ReadOnlyCollection<Exception>(exceptionsCopy);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AggregateException"/> class with serialized data.
+ /// </summary>
+ /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds
+ /// the serialized object data about the exception being thrown.</param>
+ /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that
+ /// contains contextual information about the source or destination. </param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> argument is null.</exception>
+ /// <exception cref="T:System.Runtime.Serialization.SerializationException">The exception could not be deserialized correctly.</exception>
+ protected AggregateException(SerializationInfo info, StreamingContext context) :
+ base(info, context)
+ {
+ if (info == null)
+ {
+ throw new ArgumentNullException(nameof(info));
+ }
+
+ Exception[] innerExceptions = info.GetValue("InnerExceptions", typeof(Exception[])) as Exception[];
+ if (innerExceptions == null)
+ {
+ throw new SerializationException(SR.AggregateException_DeserializationFailure);
+ }
+
+ m_innerExceptions = new ReadOnlyCollection<Exception>(innerExceptions);
+ }
+
+ /// <summary>
+ /// Sets the <see cref="T:System.Runtime.Serialization.SerializationInfo"/> with information about
+ /// the exception.
+ /// </summary>
+ /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds
+ /// the serialized object data about the exception being thrown.</param>
+ /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that
+ /// contains contextual information about the source or destination. </param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> argument is null.</exception>
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ base.GetObjectData(info, context);
+
+ Exception[] innerExceptions = new Exception[m_innerExceptions.Count];
+ m_innerExceptions.CopyTo(innerExceptions, 0);
+ info.AddValue("InnerExceptions", innerExceptions, typeof(Exception[]));
+ }
+
+ /// <summary>
+ /// Returns the <see cref="System.AggregateException"/> that is the root cause of this exception.
+ /// </summary>
+ public override Exception GetBaseException()
+ {
+ // Returns the first inner AggregateException that contains more or less than one inner exception
+
+ // Recursively traverse the inner exceptions as long as the inner exception of type AggregateException and has only one inner exception
+ Exception back = this;
+ AggregateException backAsAggregate = this;
+ while (backAsAggregate != null && backAsAggregate.InnerExceptions.Count == 1)
+ {
+ back = back.InnerException;
+ backAsAggregate = back as AggregateException;
+ }
+ return back;
+ }
+
+ /// <summary>
+ /// Gets a read-only collection of the <see cref="T:System.Exception"/> instances that caused the
+ /// current exception.
+ /// </summary>
+ public ReadOnlyCollection<Exception> InnerExceptions
+ {
+ get { return m_innerExceptions; }
+ }
+
+
+ /// <summary>
+ /// Invokes a handler on each <see cref="T:System.Exception"/> contained by this <see
+ /// cref="AggregateException"/>.
+ /// </summary>
+ /// <param name="predicate">The predicate to execute for each exception. The predicate accepts as an
+ /// argument the <see cref="T:System.Exception"/> to be processed and returns a Boolean to indicate
+ /// whether the exception was handled.</param>
+ /// <remarks>
+ /// Each invocation of the <paramref name="predicate"/> returns true or false to indicate whether the
+ /// <see cref="T:System.Exception"/> was handled. After all invocations, if any exceptions went
+ /// unhandled, all unhandled exceptions will be put into a new <see cref="AggregateException"/>
+ /// which will be thrown. Otherwise, the <see cref="Handle"/> method simply returns. If any
+ /// invocations of the <paramref name="predicate"/> throws an exception, it will halt the processing
+ /// of any more exceptions and immediately propagate the thrown exception as-is.
+ /// </remarks>
+ /// <exception cref="AggregateException">An exception contained by this <see
+ /// cref="AggregateException"/> was not handled.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="predicate"/> argument is
+ /// null.</exception>
+ public void Handle(Func<Exception, bool> predicate)
+ {
+ if (predicate == null)
+ {
+ throw new ArgumentNullException(nameof(predicate));
+ }
+
+ List<Exception> unhandledExceptions = null;
+ for (int i = 0; i < m_innerExceptions.Count; i++)
+ {
+ // If the exception was not handled, lazily allocate a list of unhandled
+ // exceptions (to be rethrown later) and add it.
+ if (!predicate(m_innerExceptions[i]))
+ {
+ if (unhandledExceptions == null)
+ {
+ unhandledExceptions = new List<Exception>();
+ }
+
+ unhandledExceptions.Add(m_innerExceptions[i]);
+ }
+ }
+
+ // If there are unhandled exceptions remaining, throw them.
+ if (unhandledExceptions != null)
+ {
+ throw new AggregateException(Message, unhandledExceptions);
+ }
+ }
+
+
+ /// <summary>
+ /// Flattens the inner instances of <see cref="AggregateException"/> by expanding its contained <see cref="Exception"/> instances
+ /// into a new <see cref="AggregateException"/>
+ /// </summary>
+ /// <returns>A new, flattened <see cref="AggregateException"/>.</returns>
+ /// <remarks>
+ /// If any inner exceptions are themselves instances of
+ /// <see cref="AggregateException"/>, this method will recursively flatten all of them. The
+ /// inner exceptions returned in the new <see cref="AggregateException"/>
+ /// will be the union of all of the inner exceptions from exception tree rooted at the provided
+ /// <see cref="AggregateException"/> instance.
+ /// </remarks>
+ public AggregateException Flatten()
+ {
+ // Initialize a collection to contain the flattened exceptions.
+ List<Exception> flattenedExceptions = new List<Exception>();
+
+ // Create a list to remember all aggregates to be flattened, this will be accessed like a FIFO queue
+ List<AggregateException> exceptionsToFlatten = new List<AggregateException>();
+ exceptionsToFlatten.Add(this);
+ int nDequeueIndex = 0;
+
+ // Continue removing and recursively flattening exceptions, until there are no more.
+ while (exceptionsToFlatten.Count > nDequeueIndex)
+ {
+ // dequeue one from exceptionsToFlatten
+ IList<Exception> currentInnerExceptions = exceptionsToFlatten[nDequeueIndex++].InnerExceptions;
+
+ for (int i = 0; i < currentInnerExceptions.Count; i++)
+ {
+ Exception currentInnerException = currentInnerExceptions[i];
+
+ if (currentInnerException == null)
+ {
+ continue;
+ }
+
+ AggregateException currentInnerAsAggregate = currentInnerException as AggregateException;
+
+ // If this exception is an aggregate, keep it around for later. Otherwise,
+ // simply add it to the list of flattened exceptions to be returned.
+ if (currentInnerAsAggregate != null)
+ {
+ exceptionsToFlatten.Add(currentInnerAsAggregate);
+ }
+ else
+ {
+ flattenedExceptions.Add(currentInnerException);
+ }
+ }
+ }
+
+
+ return new AggregateException(Message, flattenedExceptions);
+ }
+
+ /// <summary>Gets a message that describes the exception.</summary>
+ public override string Message
+ {
+ get
+ {
+ if (m_innerExceptions.Count == 0)
+ {
+ return base.Message;
+ }
+
+ StringBuilder sb = StringBuilderCache.Acquire();
+ sb.Append(base.Message);
+ sb.Append(' ');
+ for (int i = 0; i < m_innerExceptions.Count; i++)
+ {
+ sb.Append('(');
+ sb.Append(m_innerExceptions[i].Message);
+ sb.Append(") ");
+ }
+ sb.Length -= 1;
+ return StringBuilderCache.GetStringAndRelease(sb);
+ }
+ }
+
+ /// <summary>
+ /// Creates and returns a string representation of the current <see cref="AggregateException"/>.
+ /// </summary>
+ /// <returns>A string representation of the current exception.</returns>
+ public override string ToString()
+ {
+ StringBuilder text = new StringBuilder();
+ text.Append(base.ToString());
+
+ for (int i = 0; i < m_innerExceptions.Count; i++)
+ {
+ text.Append(Environment.NewLine);
+ text.Append("---> ");
+ text.Append(string.Format(CultureInfo.InvariantCulture, SR.AggregateException_InnerException, i));
+ text.Append(m_innerExceptions[i].ToString());
+ text.Append("<---");
+ text.Append(Environment.NewLine);
+ }
+
+ return text.ToString();
+ }
+
+ /// <summary>
+ /// This helper property is used by the DebuggerDisplay.
+ ///
+ /// Note that we don't want to remove this property and change the debugger display to {InnerExceptions.Count}
+ /// because DebuggerDisplay should be a single property access or parameterless method call, so that the debugger
+ /// can use a fast path without using the expression evaluator.
+ ///
+ /// See http://msdn.microsoft.com/en-us/library/x810d419.aspx
+ /// </summary>
+ private int InnerExceptionCount
+ {
+ get
+ {
+ return InnerExceptions.Count;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/ApplicationException.cs b/src/mscorlib/shared/System/ApplicationException.cs
index cb98902de1..83ced79876 100644
--- a/src/mscorlib/shared/System/ApplicationException.cs
+++ b/src/mscorlib/shared/System/ApplicationException.cs
@@ -31,7 +31,7 @@ namespace System
public ApplicationException()
: base(SR.Arg_ApplicationException)
{
- HResult = __HResults.COR_E_APPLICATION;
+ HResult = HResults.COR_E_APPLICATION;
}
// Creates a new ApplicationException with its message string set to
@@ -41,13 +41,13 @@ namespace System
public ApplicationException(String message)
: base(message)
{
- HResult = __HResults.COR_E_APPLICATION;
+ HResult = HResults.COR_E_APPLICATION;
}
public ApplicationException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_APPLICATION;
+ HResult = HResults.COR_E_APPLICATION;
}
protected ApplicationException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/ArgumentException.cs b/src/mscorlib/shared/System/ArgumentException.cs
index de2d775c84..fe65d6443a 100644
--- a/src/mscorlib/shared/System/ArgumentException.cs
+++ b/src/mscorlib/shared/System/ArgumentException.cs
@@ -29,7 +29,7 @@ namespace System
public ArgumentException()
: base(SR.Arg_ArgumentException)
{
- HResult = __HResults.COR_E_ARGUMENT;
+ HResult = HResults.COR_E_ARGUMENT;
}
// Creates a new ArgumentException with its message
@@ -38,27 +38,27 @@ namespace System
public ArgumentException(String message)
: base(message)
{
- HResult = __HResults.COR_E_ARGUMENT;
+ HResult = HResults.COR_E_ARGUMENT;
}
public ArgumentException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_ARGUMENT;
+ HResult = HResults.COR_E_ARGUMENT;
}
public ArgumentException(String message, String paramName, Exception innerException)
: base(message, innerException)
{
_paramName = paramName;
- HResult = __HResults.COR_E_ARGUMENT;
+ HResult = HResults.COR_E_ARGUMENT;
}
public ArgumentException(String message, String paramName)
: base(message)
{
_paramName = paramName;
- HResult = __HResults.COR_E_ARGUMENT;
+ HResult = HResults.COR_E_ARGUMENT;
}
protected ArgumentException(SerializationInfo info, StreamingContext context)
diff --git a/src/mscorlib/shared/System/ArgumentNullException.cs b/src/mscorlib/shared/System/ArgumentNullException.cs
index 74b39fed8e..9b0732b2d2 100644
--- a/src/mscorlib/shared/System/ArgumentNullException.cs
+++ b/src/mscorlib/shared/System/ArgumentNullException.cs
@@ -26,25 +26,25 @@ namespace System
: base(SR.ArgumentNull_Generic)
{
// Use E_POINTER - COM used that for null pointers. Description is "invalid pointer"
- HResult = __HResults.E_POINTER;
+ HResult = HResults.E_POINTER;
}
public ArgumentNullException(String paramName)
: base(SR.ArgumentNull_Generic, paramName)
{
- HResult = __HResults.E_POINTER;
+ HResult = HResults.E_POINTER;
}
public ArgumentNullException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.E_POINTER;
+ HResult = HResults.E_POINTER;
}
public ArgumentNullException(String paramName, String message)
: base(message, paramName)
{
- HResult = __HResults.E_POINTER;
+ HResult = HResults.E_POINTER;
}
protected ArgumentNullException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/ArgumentOutOfRangeException.cs b/src/mscorlib/shared/System/ArgumentOutOfRangeException.cs
index 4721a503b6..a25cd57763 100644
--- a/src/mscorlib/shared/System/ArgumentOutOfRangeException.cs
+++ b/src/mscorlib/shared/System/ArgumentOutOfRangeException.cs
@@ -27,25 +27,25 @@ namespace System
public ArgumentOutOfRangeException()
: base(SR.Arg_ArgumentOutOfRangeException)
{
- HResult = __HResults.COR_E_ARGUMENTOUTOFRANGE;
+ HResult = HResults.COR_E_ARGUMENTOUTOFRANGE;
}
public ArgumentOutOfRangeException(String paramName)
: base(SR.Arg_ArgumentOutOfRangeException, paramName)
{
- HResult = __HResults.COR_E_ARGUMENTOUTOFRANGE;
+ HResult = HResults.COR_E_ARGUMENTOUTOFRANGE;
}
public ArgumentOutOfRangeException(String paramName, String message)
: base(message, paramName)
{
- HResult = __HResults.COR_E_ARGUMENTOUTOFRANGE;
+ HResult = HResults.COR_E_ARGUMENTOUTOFRANGE;
}
public ArgumentOutOfRangeException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_ARGUMENTOUTOFRANGE;
+ HResult = HResults.COR_E_ARGUMENTOUTOFRANGE;
}
// We will not use this in the classlibs, but we'll provide it for
@@ -55,7 +55,7 @@ namespace System
: base(message, paramName)
{
_actualValue = actualValue;
- HResult = __HResults.COR_E_ARGUMENTOUTOFRANGE;
+ HResult = HResults.COR_E_ARGUMENTOUTOFRANGE;
}
protected ArgumentOutOfRangeException(SerializationInfo info, StreamingContext context)
diff --git a/src/mscorlib/shared/System/ArithmeticException.cs b/src/mscorlib/shared/System/ArithmeticException.cs
index 2c8abe51fa..6285c8120e 100644
--- a/src/mscorlib/shared/System/ArithmeticException.cs
+++ b/src/mscorlib/shared/System/ArithmeticException.cs
@@ -26,7 +26,7 @@ namespace System
public ArithmeticException()
: base(SR.Arg_ArithmeticException)
{
- HResult = __HResults.COR_E_ARITHMETIC;
+ HResult = HResults.COR_E_ARITHMETIC;
}
// Creates a new ArithmeticException with its message string set to
@@ -36,13 +36,13 @@ namespace System
public ArithmeticException(String message)
: base(message)
{
- HResult = __HResults.COR_E_ARITHMETIC;
+ HResult = HResults.COR_E_ARITHMETIC;
}
public ArithmeticException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_ARITHMETIC;
+ HResult = HResults.COR_E_ARITHMETIC;
}
protected ArithmeticException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/ArrayTypeMismatchException.cs b/src/mscorlib/shared/System/ArrayTypeMismatchException.cs
index d06a450603..6964b1fa12 100644
--- a/src/mscorlib/shared/System/ArrayTypeMismatchException.cs
+++ b/src/mscorlib/shared/System/ArrayTypeMismatchException.cs
@@ -26,7 +26,7 @@ namespace System
public ArrayTypeMismatchException()
: base(SR.Arg_ArrayTypeMismatchException)
{
- HResult = __HResults.COR_E_ARRAYTYPEMISMATCH;
+ HResult = HResults.COR_E_ARRAYTYPEMISMATCH;
}
// Creates a new ArrayMismatchException with its message string set to
@@ -36,13 +36,13 @@ namespace System
public ArrayTypeMismatchException(String message)
: base(message)
{
- HResult = __HResults.COR_E_ARRAYTYPEMISMATCH;
+ HResult = HResults.COR_E_ARRAYTYPEMISMATCH;
}
public ArrayTypeMismatchException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_ARRAYTYPEMISMATCH;
+ HResult = HResults.COR_E_ARRAYTYPEMISMATCH;
}
protected ArrayTypeMismatchException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/BadImageFormatException.cs b/src/mscorlib/shared/System/BadImageFormatException.cs
index adedcb2a3f..a4661fc799 100644
--- a/src/mscorlib/shared/System/BadImageFormatException.cs
+++ b/src/mscorlib/shared/System/BadImageFormatException.cs
@@ -25,31 +25,31 @@ namespace System
public BadImageFormatException()
: base(SR.Arg_BadImageFormatException)
{
- HResult = __HResults.COR_E_BADIMAGEFORMAT;
+ HResult = HResults.COR_E_BADIMAGEFORMAT;
}
public BadImageFormatException(String message)
: base(message)
{
- HResult = __HResults.COR_E_BADIMAGEFORMAT;
+ HResult = HResults.COR_E_BADIMAGEFORMAT;
}
public BadImageFormatException(String message, Exception inner)
: base(message, inner)
{
- HResult = __HResults.COR_E_BADIMAGEFORMAT;
+ HResult = HResults.COR_E_BADIMAGEFORMAT;
}
public BadImageFormatException(String message, String fileName) : base(message)
{
- HResult = __HResults.COR_E_BADIMAGEFORMAT;
+ HResult = HResults.COR_E_BADIMAGEFORMAT;
_fileName = fileName;
}
public BadImageFormatException(String message, String fileName, Exception inner)
: base(message, inner)
{
- HResult = __HResults.COR_E_BADIMAGEFORMAT;
+ HResult = HResults.COR_E_BADIMAGEFORMAT;
_fileName = fileName;
}
@@ -78,7 +78,7 @@ namespace System
if (_message == null)
{
if ((_fileName == null) &&
- (HResult == __HResults.COR_E_EXCEPTION))
+ (HResult == HResults.COR_E_EXCEPTION))
_message = SR.Arg_BadImageFormatException;
else
diff --git a/src/mscorlib/shared/System/BitConverter.cs b/src/mscorlib/shared/System/BitConverter.cs
index e19229dd37..edcdd1ec93 100644
--- a/src/mscorlib/shared/System/BitConverter.cs
+++ b/src/mscorlib/shared/System/BitConverter.cs
@@ -30,6 +30,16 @@ namespace System
return r;
}
+ // Converts a Boolean into a Span of bytes with length one.
+ public static bool TryWriteBytes(Span<byte> destination, bool value)
+ {
+ if (destination.Length < sizeof(byte))
+ return false;
+
+ Unsafe.WriteUnaligned(ref destination.DangerousGetPinnableReference(), value ? (byte)1: (byte)0);
+ return true;
+ }
+
// Converts a char into an array of bytes with length two.
public static byte[] GetBytes(char value)
{
@@ -38,6 +48,16 @@ namespace System
return bytes;
}
+ // Converts a char into a Span
+ public static bool TryWriteBytes(Span<byte> destination, char value)
+ {
+ if (destination.Length < sizeof(char))
+ return false;
+
+ Unsafe.WriteUnaligned(ref destination.DangerousGetPinnableReference(), value);
+ return true;
+ }
+
// Converts a short into an array of bytes with length
// two.
public static byte[] GetBytes(short value)
@@ -47,6 +67,16 @@ namespace System
return bytes;
}
+ // Converts a short into a Span
+ public static bool TryWriteBytes(Span<byte> destination, short value)
+ {
+ if (destination.Length < sizeof(short))
+ return false;
+
+ Unsafe.WriteUnaligned(ref destination.DangerousGetPinnableReference(), value);
+ return true;
+ }
+
// Converts an int into an array of bytes with length
// four.
public static byte[] GetBytes(int value)
@@ -56,6 +86,16 @@ namespace System
return bytes;
}
+ // Converts an int into a Span
+ public static bool TryWriteBytes(Span<byte> destination, int value)
+ {
+ if (destination.Length < sizeof(int))
+ return false;
+
+ Unsafe.WriteUnaligned(ref destination.DangerousGetPinnableReference(), value);
+ return true;
+ }
+
// Converts a long into an array of bytes with length
// eight.
public static byte[] GetBytes(long value)
@@ -65,6 +105,16 @@ namespace System
return bytes;
}
+ // Converts a long into a Span
+ public static bool TryWriteBytes(Span<byte> destination, long value)
+ {
+ if (destination.Length < sizeof(long))
+ return false;
+
+ Unsafe.WriteUnaligned(ref destination.DangerousGetPinnableReference(), value);
+ return true;
+ }
+
// Converts an ushort into an array of bytes with
// length two.
[CLSCompliant(false)]
@@ -75,6 +125,17 @@ namespace System
return bytes;
}
+ // Converts a ushort into a Span
+ [CLSCompliant(false)]
+ public static bool TryWriteBytes(Span<byte> destination, ushort value)
+ {
+ if (destination.Length < sizeof(ushort))
+ return false;
+
+ Unsafe.WriteUnaligned(ref destination.DangerousGetPinnableReference(), value);
+ return true;
+ }
+
// Converts an uint into an array of bytes with
// length four.
[CLSCompliant(false)]
@@ -85,6 +146,17 @@ namespace System
return bytes;
}
+ // Converts a uint into a Span
+ [CLSCompliant(false)]
+ public static bool TryWriteBytes(Span<byte> destination, uint value)
+ {
+ if (destination.Length < sizeof(uint))
+ return false;
+
+ Unsafe.WriteUnaligned(ref destination.DangerousGetPinnableReference(), value);
+ return true;
+ }
+
// Converts an unsigned long into an array of bytes with
// length eight.
[CLSCompliant(false)]
@@ -95,6 +167,17 @@ namespace System
return bytes;
}
+ // Converts a ulong into a Span
+ [CLSCompliant(false)]
+ public static bool TryWriteBytes(Span<byte> destination, ulong value)
+ {
+ if (destination.Length < sizeof(ulong))
+ return false;
+
+ Unsafe.WriteUnaligned(ref destination.DangerousGetPinnableReference(), value);
+ return true;
+ }
+
// Converts a float into an array of bytes with length
// four.
public static byte[] GetBytes(float value)
@@ -104,6 +187,16 @@ namespace System
return bytes;
}
+ // Converts a float into a Span
+ public static bool TryWriteBytes(Span<byte> destination, float value)
+ {
+ if (destination.Length < sizeof(float))
+ return false;
+
+ Unsafe.WriteUnaligned(ref destination.DangerousGetPinnableReference(), value);
+ return true;
+ }
+
// Converts a double into an array of bytes with length
// eight.
public static byte[] GetBytes(double value)
@@ -113,9 +206,27 @@ namespace System
return bytes;
}
+ // Converts a double into a Span
+ public static bool TryWriteBytes(Span<byte> destination, double value)
+ {
+ if (destination.Length < sizeof(double))
+ return false;
+
+ Unsafe.WriteUnaligned(ref destination.DangerousGetPinnableReference(), value);
+ return true;
+ }
+
// Converts an array of bytes into a char.
public static char ToChar(byte[] value, int startIndex) => unchecked((char)ReadInt16(value, startIndex));
+ // Converts a Span into a char
+ public static char ToChar(ReadOnlySpan<byte> value)
+ {
+ if (value.Length < sizeof(char))
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value);
+ return Unsafe.ReadUnaligned<char>(ref value.DangerousGetPinnableReference());
+ }
+
private static short ReadInt16(byte[] value, int startIndex)
{
if (value == null)
@@ -155,27 +266,78 @@ namespace System
// Converts an array of bytes into a short.
public static short ToInt16(byte[] value, int startIndex) => ReadInt16(value, startIndex);
+ // Converts a Span into a short
+ public static short ToInt16(ReadOnlySpan<byte> value)
+ {
+ if (value.Length < sizeof(short))
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value);
+ return Unsafe.ReadUnaligned<short>(ref value.DangerousGetPinnableReference());
+ }
+
// Converts an array of bytes into an int.
public static int ToInt32(byte[] value, int startIndex) => ReadInt32(value, startIndex);
+ // Converts a Span into an int
+ public static int ToInt32(ReadOnlySpan<byte> value)
+ {
+ if (value.Length < sizeof(int))
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value);
+ return Unsafe.ReadUnaligned<int>(ref value.DangerousGetPinnableReference());
+ }
+
// Converts an array of bytes into a long.
public static long ToInt64(byte[] value, int startIndex) => ReadInt64(value, startIndex);
+ // Converts a Span into a long
+ public static long ToInt64(ReadOnlySpan<byte> value)
+ {
+ if (value.Length < sizeof(long))
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value);
+ return Unsafe.ReadUnaligned<long>(ref value.DangerousGetPinnableReference());
+ }
+
// Converts an array of bytes into an ushort.
//
[CLSCompliant(false)]
public static ushort ToUInt16(byte[] value, int startIndex) => unchecked((ushort)ReadInt16(value, startIndex));
+ // Converts a Span into a ushort
+ [CLSCompliant(false)]
+ public static ushort ToUInt16(ReadOnlySpan<byte> value)
+ {
+ if (value.Length < sizeof(ushort))
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value);
+ return Unsafe.ReadUnaligned<ushort>(ref value.DangerousGetPinnableReference());
+ }
+
// Converts an array of bytes into an uint.
//
[CLSCompliant(false)]
public static uint ToUInt32(byte[] value, int startIndex) => unchecked((uint)ReadInt32(value, startIndex));
+ // Convert a Span into a uint
+ [CLSCompliant(false)]
+ public static uint ToUInt32(ReadOnlySpan<byte> value)
+ {
+ if (value.Length < sizeof(uint))
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value);
+ return Unsafe.ReadUnaligned<uint>(ref value.DangerousGetPinnableReference());
+ }
+
// Converts an array of bytes into an unsigned long.
//
[CLSCompliant(false)]
public static ulong ToUInt64(byte[] value, int startIndex) => unchecked((ulong)ReadInt64(value, startIndex));
+ // Converts a Span into an unsigned long
+ [CLSCompliant(false)]
+ public static ulong ToUInt64(ReadOnlySpan<byte> value)
+ {
+ if (value.Length < sizeof(ulong))
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value);
+ return Unsafe.ReadUnaligned<ulong>(ref value.DangerousGetPinnableReference());
+ }
+
// Converts an array of bytes into a float.
public static unsafe float ToSingle(byte[] value, int startIndex)
{
@@ -183,6 +345,14 @@ namespace System
return *(float*)&val;
}
+ // Converts a Span into a float
+ public static float ToSingle(ReadOnlySpan<byte> value)
+ {
+ if (value.Length < sizeof(float))
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value);
+ return Unsafe.ReadUnaligned<float>(ref value.DangerousGetPinnableReference());
+ }
+
// Converts an array of bytes into a double.
public static unsafe double ToDouble(byte[] value, int startIndex)
{
@@ -190,6 +360,14 @@ namespace System
return *(double*)&val;
}
+ // Converts a Span into a double
+ public static double ToDouble(ReadOnlySpan<byte> value)
+ {
+ if (value.Length < sizeof(double))
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value);
+ return Unsafe.ReadUnaligned<double>(ref value.DangerousGetPinnableReference());
+ }
+
private static char GetHexValue(int i)
{
Debug.Assert(i >= 0 && i < 16, "i is out of range.");
@@ -298,6 +476,13 @@ namespace System
return value[startIndex] != 0;
}
+ public static bool ToBoolean(ReadOnlySpan<byte> value)
+ {
+ if (value.Length < sizeof(byte))
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value);
+ return Unsafe.ReadUnaligned<byte>(ref value.DangerousGetPinnableReference()) != 0;
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe long DoubleToInt64Bits(double value)
{
diff --git a/src/mscorlib/shared/System/Boolean.cs b/src/mscorlib/shared/System/Boolean.cs
new file mode 100644
index 0000000000..a6ffb6de83
--- /dev/null
+++ b/src/mscorlib/shared/System/Boolean.cs
@@ -0,0 +1,335 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: The boolean class serves as a wrapper for the primitive
+** type boolean.
+**
+**
+===========================================================*/
+
+using System.Diagnostics.Contracts;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Runtime.Versioning;
+
+namespace System
+{
+ [Serializable]
+ [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ public struct Boolean : IComparable, IConvertible, IComparable<Boolean>, IEquatable<Boolean>
+ {
+ //
+ // Member Variables
+ //
+ private bool m_value; // Do not rename (binary serialization)
+
+ // The true value.
+ //
+ internal const int True = 1;
+
+ // The false value.
+ //
+ internal const int False = 0;
+
+
+ //
+ // Internal Constants are real consts for performance.
+ //
+
+ // The internal string representation of true.
+ //
+ internal const String TrueLiteral = "True";
+
+ // The internal string representation of false.
+ //
+ internal const String FalseLiteral = "False";
+
+
+ //
+ // Public Constants
+ //
+
+ // The public string representation of true.
+ //
+ public static readonly String TrueString = TrueLiteral;
+
+ // The public string representation of false.
+ //
+ public static readonly String FalseString = FalseLiteral;
+
+ //
+ // Overriden Instance Methods
+ //
+ /*=================================GetHashCode==================================
+ **Args: None
+ **Returns: 1 or 0 depending on whether this instance represents true or false.
+ **Exceptions: None
+ **Overriden From: Value
+ ==============================================================================*/
+ // Provides a hash code for this instance.
+ public override int GetHashCode()
+ {
+ return (m_value) ? True : False;
+ }
+
+ /*===================================ToString===================================
+ **Args: None
+ **Returns: "True" or "False" depending on the state of the boolean.
+ **Exceptions: None.
+ ==============================================================================*/
+ // Converts the boolean value of this instance to a String.
+ public override String ToString()
+ {
+ if (false == m_value)
+ {
+ return FalseLiteral;
+ }
+ return TrueLiteral;
+ }
+
+ public String ToString(IFormatProvider provider)
+ {
+ return ToString();
+ }
+
+ // Determines whether two Boolean objects are equal.
+ public override bool Equals(Object obj)
+ {
+ //If it's not a boolean, we're definitely not equal
+ if (!(obj is Boolean))
+ {
+ return false;
+ }
+
+ return (m_value == ((Boolean)obj).m_value);
+ }
+
+ [NonVersionable]
+ public bool Equals(Boolean obj)
+ {
+ return m_value == obj;
+ }
+
+ // Compares this object to another object, returning an integer that
+ // indicates the relationship. For booleans, false sorts before true.
+ // null is considered to be less than any instance.
+ // If object is not of type boolean, this method throws an ArgumentException.
+ //
+ // Returns a value less than zero if this object
+ //
+ public int CompareTo(Object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is Boolean))
+ {
+ throw new ArgumentException(SR.Arg_MustBeBoolean);
+ }
+
+ if (m_value == ((Boolean)obj).m_value)
+ {
+ return 0;
+ }
+ else if (m_value == false)
+ {
+ return -1;
+ }
+ return 1;
+ }
+
+ public int CompareTo(Boolean value)
+ {
+ if (m_value == value)
+ {
+ return 0;
+ }
+ else if (m_value == false)
+ {
+ return -1;
+ }
+ return 1;
+ }
+
+ //
+ // Static Methods
+ //
+
+ // Determines whether a String represents true or false.
+ //
+ public static Boolean Parse(String value)
+ {
+ if (value == null) throw new ArgumentNullException(nameof(value));
+ return Parse(value.AsReadOnlySpan());
+ }
+
+ public static bool Parse(ReadOnlySpan<char> value) =>
+ TryParse(value, out bool result) ? result : throw new FormatException(SR.Format_BadBoolean);
+
+ // Determines whether a String represents true or false.
+ //
+ public static Boolean TryParse(String value, out Boolean result)
+ {
+ if (value == null)
+ {
+ result = false;
+ return false;
+ }
+
+ return TryParse(value.AsReadOnlySpan(), out result);
+ }
+
+ public static bool TryParse(ReadOnlySpan<char> value, out bool result)
+ {
+ ReadOnlySpan<char> trueSpan = TrueLiteral.AsReadOnlySpan();
+ if (StringSpanHelpers.Equals(trueSpan, value, StringComparison.OrdinalIgnoreCase))
+ {
+ result = true;
+ return true;
+ }
+
+ ReadOnlySpan<char> falseSpan = FalseLiteral.AsReadOnlySpan();
+ if (StringSpanHelpers.Equals(falseSpan, value, StringComparison.OrdinalIgnoreCase))
+ {
+ result = false;
+ return true;
+ }
+
+ // Special case: Trim whitespace as well as null characters.
+ value = TrimWhiteSpaceAndNull(value);
+
+ if (StringSpanHelpers.Equals(trueSpan, value, StringComparison.OrdinalIgnoreCase))
+ {
+ result = true;
+ return true;
+ }
+
+ if (StringSpanHelpers.Equals(falseSpan, value, StringComparison.OrdinalIgnoreCase))
+ {
+ result = false;
+ return true;
+ }
+
+ result = false;
+ return false;
+ }
+
+ private static ReadOnlySpan<char> TrimWhiteSpaceAndNull(ReadOnlySpan<char> value)
+ {
+ const char nullChar = (char)0x0000;
+
+ int start = 0;
+ while (start < value.Length)
+ {
+ if (!Char.IsWhiteSpace(value[start]) && value[start] != nullChar)
+ {
+ break;
+ }
+ start++;
+ }
+
+ int end = value.Length - 1;
+ while (end >= start)
+ {
+ if (!Char.IsWhiteSpace(value[end]) && value[end] != nullChar)
+ {
+ break;
+ }
+ end--;
+ }
+
+ return value.Slice(start, end - start + 1);
+ }
+
+ //
+ // IConvertible implementation
+ //
+
+ public TypeCode GetTypeCode()
+ {
+ return TypeCode.Boolean;
+ }
+
+
+ bool IConvertible.ToBoolean(IFormatProvider provider)
+ {
+ return m_value;
+ }
+
+ char IConvertible.ToChar(IFormatProvider provider)
+ {
+ throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Boolean", "Char"));
+ }
+
+ sbyte IConvertible.ToSByte(IFormatProvider provider)
+ {
+ return Convert.ToSByte(m_value);
+ }
+
+ byte IConvertible.ToByte(IFormatProvider provider)
+ {
+ return Convert.ToByte(m_value);
+ }
+
+ short IConvertible.ToInt16(IFormatProvider provider)
+ {
+ return Convert.ToInt16(m_value);
+ }
+
+ ushort IConvertible.ToUInt16(IFormatProvider provider)
+ {
+ return Convert.ToUInt16(m_value);
+ }
+
+ int IConvertible.ToInt32(IFormatProvider provider)
+ {
+ return Convert.ToInt32(m_value);
+ }
+
+ uint IConvertible.ToUInt32(IFormatProvider provider)
+ {
+ return Convert.ToUInt32(m_value);
+ }
+
+ long IConvertible.ToInt64(IFormatProvider provider)
+ {
+ return Convert.ToInt64(m_value);
+ }
+
+ ulong IConvertible.ToUInt64(IFormatProvider provider)
+ {
+ return Convert.ToUInt64(m_value);
+ }
+
+ float IConvertible.ToSingle(IFormatProvider provider)
+ {
+ return Convert.ToSingle(m_value);
+ }
+
+ double IConvertible.ToDouble(IFormatProvider provider)
+ {
+ return Convert.ToDouble(m_value);
+ }
+
+ Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ {
+ return Convert.ToDecimal(m_value);
+ }
+
+ DateTime IConvertible.ToDateTime(IFormatProvider provider)
+ {
+ throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Boolean", "DateTime"));
+ }
+
+ Object IConvertible.ToType(Type type, IFormatProvider provider)
+ {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/Buffers/ArrayPoolEventSource.cs b/src/mscorlib/shared/System/Buffers/ArrayPoolEventSource.cs
new file mode 100644
index 0000000000..9482744144
--- /dev/null
+++ b/src/mscorlib/shared/System/Buffers/ArrayPoolEventSource.cs
@@ -0,0 +1,78 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics.Tracing;
+
+namespace System.Buffers
+{
+ [EventSource(Name = "System.Buffers.ArrayPoolEventSource")]
+ internal sealed class ArrayPoolEventSource : EventSource
+ {
+ internal readonly static ArrayPoolEventSource Log = new ArrayPoolEventSource();
+
+ /// <summary>The reason for a BufferAllocated event.</summary>
+ internal enum BufferAllocatedReason : int
+ {
+ /// <summary>The pool is allocating a buffer to be pooled in a bucket.</summary>
+ Pooled,
+ /// <summary>The requested buffer size was too large to be pooled.</summary>
+ OverMaximumSize,
+ /// <summary>The pool has already allocated for pooling as many buffers of a particular size as it's allowed.</summary>
+ PoolExhausted
+ }
+
+ /// <summary>
+ /// Event for when a buffer is rented. This is invoked once for every successful call to Rent,
+ /// regardless of whether a buffer is allocated or a buffer is taken from the pool. In a
+ /// perfect situation where all rented buffers are returned, we expect to see the number
+ /// of BufferRented events exactly match the number of BuferReturned events, with the number
+ /// of BufferAllocated events being less than or equal to those numbers (ideally significantly
+ /// less than).
+ /// </summary>
+ [Event(1, Level = EventLevel.Verbose)]
+ internal unsafe void BufferRented(int bufferId, int bufferSize, int poolId, int bucketId)
+ {
+ EventData* payload = stackalloc EventData[4];
+ payload[0].Size = sizeof(int);
+ payload[0].DataPointer = ((IntPtr)(&bufferId));
+ payload[1].Size = sizeof(int);
+ payload[1].DataPointer = ((IntPtr)(&bufferSize));
+ payload[2].Size = sizeof(int);
+ payload[2].DataPointer = ((IntPtr)(&poolId));
+ payload[3].Size = sizeof(int);
+ payload[3].DataPointer = ((IntPtr)(&bucketId));
+ WriteEventCore(1, 4, payload);
+ }
+
+ /// <summary>
+ /// Event for when a buffer is allocated by the pool. In an ideal situation, the number
+ /// of BufferAllocated events is significantly smaller than the number of BufferRented and
+ /// BufferReturned events.
+ /// </summary>
+ [Event(2, Level = EventLevel.Informational)]
+ internal unsafe void BufferAllocated(int bufferId, int bufferSize, int poolId, int bucketId, BufferAllocatedReason reason)
+ {
+ EventData* payload = stackalloc EventData[5];
+ payload[0].Size = sizeof(int);
+ payload[0].DataPointer = ((IntPtr)(&bufferId));
+ payload[1].Size = sizeof(int);
+ payload[1].DataPointer = ((IntPtr)(&bufferSize));
+ payload[2].Size = sizeof(int);
+ payload[2].DataPointer = ((IntPtr)(&poolId));
+ payload[3].Size = sizeof(int);
+ payload[3].DataPointer = ((IntPtr)(&bucketId));
+ payload[4].Size = sizeof(BufferAllocatedReason);
+ payload[4].DataPointer = ((IntPtr)(&reason));
+ WriteEventCore(2, 5, payload);
+ }
+
+ /// <summary>
+ /// Event raised when a buffer is returned to the pool. This event is raised regardless of whether
+ /// the returned buffer is stored or dropped. In an ideal situation, the number of BufferReturned
+ /// events exactly matches the number of BufferRented events.
+ /// </summary>
+ [Event(3, Level = EventLevel.Verbose)]
+ internal void BufferReturned(int bufferId, int bufferSize, int poolId) => WriteEvent(3, bufferId, bufferSize, poolId);
+ }
+}
diff --git a/src/mscorlib/shared/System/Buffers/IRetainable.cs b/src/mscorlib/shared/System/Buffers/IRetainable.cs
new file mode 100644
index 0000000000..8d71fc614a
--- /dev/null
+++ b/src/mscorlib/shared/System/Buffers/IRetainable.cs
@@ -0,0 +1,15 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime;
+using System.Runtime.CompilerServices;
+
+namespace System.Buffers
+{
+ public interface IRetainable
+ {
+ void Retain();
+ bool Release();
+ }
+} \ No newline at end of file
diff --git a/src/mscorlib/shared/System/Buffers/MemoryHandle.cs b/src/mscorlib/shared/System/Buffers/MemoryHandle.cs
new file mode 100644
index 0000000000..fcdc7fe17f
--- /dev/null
+++ b/src/mscorlib/shared/System/Buffers/MemoryHandle.cs
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime;
+using System.Runtime.InteropServices;
+
+namespace System.Buffers
+{
+ public unsafe struct MemoryHandle : IDisposable
+ {
+ private IRetainable _owner;
+ private void* _pointer;
+ private GCHandle _handle;
+
+ [CLSCompliant(false)]
+ public MemoryHandle(IRetainable owner, void* pinnedPointer = null, GCHandle handle = default(GCHandle))
+ {
+ _owner = owner;
+ _pointer = pinnedPointer;
+ _handle = handle;
+ }
+
+ [CLSCompliant(false)]
+ public void* PinnedPointer => _pointer;
+
+ public void Dispose()
+ {
+ if (_handle.IsAllocated)
+ {
+ _handle.Free();
+ }
+
+ if (_owner != null)
+ {
+ _owner.Release();
+ _owner = null;
+ }
+
+ _pointer = null;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/src/mscorlib/shared/System/Buffers/OwnedMemory.cs b/src/mscorlib/shared/System/Buffers/OwnedMemory.cs
new file mode 100644
index 0000000000..e3a89f7ef4
--- /dev/null
+++ b/src/mscorlib/shared/System/Buffers/OwnedMemory.cs
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime;
+using System.Runtime.CompilerServices;
+
+namespace System.Buffers
+{
+ public abstract class OwnedMemory<T> : IDisposable, IRetainable
+ {
+ public abstract int Length { get; }
+
+ public abstract Span<T> AsSpan();
+
+ public Memory<T> AsMemory
+ {
+ get
+ {
+ if (IsDisposed)
+ {
+ ThrowHelper.ThrowObjectDisposedException(nameof(OwnedMemory<T>), ExceptionResource.Memory_ThrowIfDisposed);
+ }
+ return new Memory<T>(this, 0, Length);
+ }
+ }
+
+ public abstract MemoryHandle Pin();
+
+ protected internal abstract bool TryGetArray(out ArraySegment<T> arraySegment);
+
+ public void Dispose()
+ {
+ if (IsRetained)
+ {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.Memory_OutstandingReferences);
+ }
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected abstract void Dispose(bool disposing);
+
+ protected abstract bool IsRetained { get; }
+
+ public abstract bool IsDisposed { get; }
+
+ public abstract void Retain();
+
+ public abstract bool Release();
+
+ }
+} \ No newline at end of file
diff --git a/src/mscorlib/shared/System/Byte.cs b/src/mscorlib/shared/System/Byte.cs
new file mode 100644
index 0000000000..a0f8ff8c29
--- /dev/null
+++ b/src/mscorlib/shared/System/Byte.cs
@@ -0,0 +1,298 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: This class will encapsulate a byte and provide an
+** Object representation of it.
+**
+**
+===========================================================*/
+
+using System.Diagnostics.Contracts;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+
+namespace System
+{
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
+ [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ public struct Byte : IComparable, IConvertible, IFormattable, IComparable<Byte>, IEquatable<Byte>
+ {
+ private byte m_value; // Do not rename (binary serialization)
+
+ // The maximum value that a Byte may represent: 255.
+ public const byte MaxValue = (byte)0xFF;
+
+ // The minimum value that a Byte may represent: 0.
+ public const byte MinValue = 0;
+
+
+ // Compares this object to another object, returning an integer that
+ // indicates the relationship.
+ // Returns a value less than zero if this object
+ // null is considered to be less than any instance.
+ // If object is not of type byte, this method throws an ArgumentException.
+ //
+ public int CompareTo(Object value)
+ {
+ if (value == null)
+ {
+ return 1;
+ }
+ if (!(value is Byte))
+ {
+ throw new ArgumentException(SR.Arg_MustBeByte);
+ }
+
+ return m_value - (((Byte)value).m_value);
+ }
+
+ public int CompareTo(Byte value)
+ {
+ return m_value - value;
+ }
+
+ // Determines whether two Byte objects are equal.
+ public override bool Equals(Object obj)
+ {
+ if (!(obj is Byte))
+ {
+ return false;
+ }
+ return m_value == ((Byte)obj).m_value;
+ }
+
+ [NonVersionable]
+ public bool Equals(Byte obj)
+ {
+ return m_value == obj;
+ }
+
+ // Gets a hash code for this instance.
+ public override int GetHashCode()
+ {
+ return m_value;
+ }
+
+ [Pure]
+ public static byte Parse(String s)
+ {
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Parse(s.AsReadOnlySpan(), NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
+ }
+
+ [Pure]
+ public static byte Parse(String s, NumberStyles style)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Parse(s.AsReadOnlySpan(), style, NumberFormatInfo.CurrentInfo);
+ }
+
+ [Pure]
+ public static byte Parse(String s, IFormatProvider provider)
+ {
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Parse(s.AsReadOnlySpan(), NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
+ }
+
+ // Parses an unsigned byte from a String in the given style. If
+ // a NumberFormatInfo isn't specified, the current culture's
+ // NumberFormatInfo is assumed.
+ [Pure]
+ public static byte Parse(String s, NumberStyles style, IFormatProvider provider)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Parse(s.AsReadOnlySpan(), style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public static byte Parse(ReadOnlySpan<char> s, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Parse(s, style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ private static byte Parse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info)
+ {
+ int i = 0;
+ try
+ {
+ i = Number.ParseInt32(s, style, info);
+ }
+ catch (OverflowException e)
+ {
+ throw new OverflowException(SR.Overflow_Byte, e);
+ }
+
+ if (i < MinValue || i > MaxValue) throw new OverflowException(SR.Overflow_Byte);
+ return (byte)i;
+ }
+
+ public static bool TryParse(String s, out Byte result)
+ {
+ if (s == null)
+ {
+ result = 0;
+ return false;
+ }
+
+ return TryParse(s.AsReadOnlySpan(), NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
+ }
+
+ public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out Byte result)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+
+ if (s == null)
+ {
+ result = 0;
+ return false;
+ }
+
+ return TryParse(s.AsReadOnlySpan(), style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ public static bool TryParse(ReadOnlySpan<char> s, out byte result, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ private static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out Byte result)
+ {
+ result = 0;
+ int i;
+ if (!Number.TryParseInt32(s, style, info, out i))
+ {
+ return false;
+ }
+ if (i < MinValue || i > MaxValue)
+ {
+ return false;
+ }
+ result = (byte)i;
+ return true;
+ }
+
+ [Pure]
+ public override String ToString()
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt32(m_value, null, NumberFormatInfo.CurrentInfo);
+ }
+
+ [Pure]
+ public String ToString(String format)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt32(m_value, format, NumberFormatInfo.CurrentInfo);
+ }
+
+ [Pure]
+ public String ToString(IFormatProvider provider)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt32(m_value, null, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [Pure]
+ public String ToString(String format, IFormatProvider provider)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt32(m_value, format, NumberFormatInfo.GetInstance(provider));
+ }
+
+ //
+ // IConvertible implementation
+ //
+ [Pure]
+ public TypeCode GetTypeCode()
+ {
+ return TypeCode.Byte;
+ }
+
+
+ bool IConvertible.ToBoolean(IFormatProvider provider)
+ {
+ return Convert.ToBoolean(m_value);
+ }
+
+ char IConvertible.ToChar(IFormatProvider provider)
+ {
+ return Convert.ToChar(m_value);
+ }
+
+ sbyte IConvertible.ToSByte(IFormatProvider provider)
+ {
+ return Convert.ToSByte(m_value);
+ }
+
+ byte IConvertible.ToByte(IFormatProvider provider)
+ {
+ return m_value;
+ }
+
+ short IConvertible.ToInt16(IFormatProvider provider)
+ {
+ return Convert.ToInt16(m_value);
+ }
+
+ ushort IConvertible.ToUInt16(IFormatProvider provider)
+ {
+ return Convert.ToUInt16(m_value);
+ }
+
+ int IConvertible.ToInt32(IFormatProvider provider)
+ {
+ return Convert.ToInt32(m_value);
+ }
+
+ uint IConvertible.ToUInt32(IFormatProvider provider)
+ {
+ return Convert.ToUInt32(m_value);
+ }
+
+ long IConvertible.ToInt64(IFormatProvider provider)
+ {
+ return Convert.ToInt64(m_value);
+ }
+
+ ulong IConvertible.ToUInt64(IFormatProvider provider)
+ {
+ return Convert.ToUInt64(m_value);
+ }
+
+ float IConvertible.ToSingle(IFormatProvider provider)
+ {
+ return Convert.ToSingle(m_value);
+ }
+
+ double IConvertible.ToDouble(IFormatProvider provider)
+ {
+ return Convert.ToDouble(m_value);
+ }
+
+ Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ {
+ return Convert.ToDecimal(m_value);
+ }
+
+ DateTime IConvertible.ToDateTime(IFormatProvider provider)
+ {
+ throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Byte", "DateTime"));
+ }
+
+ Object IConvertible.ToType(Type type, IFormatProvider provider)
+ {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/Collections/Generic/KeyNotFoundException.cs b/src/mscorlib/shared/System/Collections/Generic/KeyNotFoundException.cs
index cdd6faf030..c32bc623ba 100644
--- a/src/mscorlib/shared/System/Collections/Generic/KeyNotFoundException.cs
+++ b/src/mscorlib/shared/System/Collections/Generic/KeyNotFoundException.cs
@@ -12,19 +12,19 @@ namespace System.Collections.Generic
public KeyNotFoundException()
: base(SR.Arg_KeyNotFound)
{
- HResult = __HResults.COR_E_KEYNOTFOUND;
+ HResult = HResults.COR_E_KEYNOTFOUND;
}
public KeyNotFoundException(String message)
: base(message)
{
- HResult = __HResults.COR_E_KEYNOTFOUND;
+ HResult = HResults.COR_E_KEYNOTFOUND;
}
public KeyNotFoundException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_KEYNOTFOUND;
+ HResult = HResults.COR_E_KEYNOTFOUND;
}
protected KeyNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/Collections/ICollection.cs b/src/mscorlib/shared/System/Collections/ICollection.cs
index 80ea092363..8fd6a96b48 100644
--- a/src/mscorlib/shared/System/Collections/ICollection.cs
+++ b/src/mscorlib/shared/System/Collections/ICollection.cs
@@ -29,7 +29,7 @@ namespace System.Collections
// implementation of a collection, and use one of the internal objects
// found in that code.
//
- // In the absense of a static Synchronized method on a collection,
+ // In the absence of a static Synchronized method on a collection,
// the expected usage for SyncRoot would look like this:
//
// ICollection col = ...
diff --git a/src/mscorlib/shared/System/Collections/ListDictionaryInternal.cs b/src/mscorlib/shared/System/Collections/ListDictionaryInternal.cs
new file mode 100644
index 0000000000..681e51a329
--- /dev/null
+++ b/src/mscorlib/shared/System/Collections/ListDictionaryInternal.cs
@@ -0,0 +1,521 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: List for exceptions.
+**
+**
+===========================================================*/
+
+using System.Diagnostics.Contracts;
+
+namespace System.Collections
+{
+ /// This is a simple implementation of IDictionary using a singly linked list. This
+ /// will be smaller and faster than a Hashtable if the number of elements is 10 or less.
+ /// This should not be used if performance is important for large numbers of elements.
+ [Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+#if CORECLR
+ internal
+#else
+ public
+#endif
+ class ListDictionaryInternal : IDictionary
+ {
+ private DictionaryNode head; // Do not rename (binary serialization)
+ private int version; // Do not rename (binary serialization)
+ private int count; // Do not rename (binary serialization)
+ [NonSerialized]
+ private Object _syncRoot;
+
+ public ListDictionaryInternal()
+ {
+ }
+
+ public Object this[Object key]
+ {
+ get
+ {
+ if (key == null)
+ {
+ throw new ArgumentNullException(nameof(key), SR.ArgumentNull_Key);
+ }
+ Contract.EndContractBlock();
+ DictionaryNode node = head;
+
+ while (node != null)
+ {
+ if (node.key.Equals(key))
+ {
+ return node.value;
+ }
+ node = node.next;
+ }
+ return null;
+ }
+ set
+ {
+ if (key == null)
+ {
+ throw new ArgumentNullException(nameof(key), SR.ArgumentNull_Key);
+ }
+ Contract.EndContractBlock();
+
+
+ version++;
+ DictionaryNode last = null;
+ DictionaryNode node;
+ for (node = head; node != null; node = node.next)
+ {
+ if (node.key.Equals(key))
+ {
+ break;
+ }
+ last = node;
+ }
+ if (node != null)
+ {
+ // Found it
+ node.value = value;
+ return;
+ }
+ // Not found, so add a new one
+ DictionaryNode newNode = new DictionaryNode();
+ newNode.key = key;
+ newNode.value = value;
+ if (last != null)
+ {
+ last.next = newNode;
+ }
+ else
+ {
+ head = newNode;
+ }
+ count++;
+ }
+ }
+
+ public int Count
+ {
+ get
+ {
+ return count;
+ }
+ }
+
+ public ICollection Keys
+ {
+ get
+ {
+ return new NodeKeyValueCollection(this, true);
+ }
+ }
+
+ public bool IsReadOnly
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public bool IsFixedSize
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public bool IsSynchronized
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public Object SyncRoot
+ {
+ get
+ {
+ if (_syncRoot == null)
+ {
+ System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
+ }
+ return _syncRoot;
+ }
+ }
+
+ public ICollection Values
+ {
+ get
+ {
+ return new NodeKeyValueCollection(this, false);
+ }
+ }
+
+ public void Add(Object key, Object value)
+ {
+ if (key == null)
+ {
+ throw new ArgumentNullException(nameof(key), SR.ArgumentNull_Key);
+ }
+ Contract.EndContractBlock();
+
+
+ version++;
+ DictionaryNode last = null;
+ DictionaryNode node;
+ for (node = head; node != null; node = node.next)
+ {
+ if (node.key.Equals(key))
+ {
+ throw new ArgumentException(SR.Format(SR.Argument_AddingDuplicate__, node.key, key));
+ }
+ last = node;
+ }
+ if (node != null)
+ {
+ // Found it
+ node.value = value;
+ return;
+ }
+ // Not found, so add a new one
+ DictionaryNode newNode = new DictionaryNode();
+ newNode.key = key;
+ newNode.value = value;
+ if (last != null)
+ {
+ last.next = newNode;
+ }
+ else
+ {
+ head = newNode;
+ }
+ count++;
+ }
+
+ public void Clear()
+ {
+ count = 0;
+ head = null;
+ version++;
+ }
+
+ public bool Contains(Object key)
+ {
+ if (key == null)
+ {
+ throw new ArgumentNullException(nameof(key), SR.ArgumentNull_Key);
+ }
+ Contract.EndContractBlock();
+ for (DictionaryNode node = head; node != null; node = node.next)
+ {
+ if (node.key.Equals(key))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void CopyTo(Array array, int index)
+ {
+ if (array == null)
+ throw new ArgumentNullException(nameof(array));
+
+ if (array.Rank != 1)
+ throw new ArgumentException(SR.Arg_RankMultiDimNotSupported);
+
+ if (index < 0)
+ throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+ if (array.Length - index < this.Count)
+ throw new ArgumentException(SR.ArgumentOutOfRange_Index, nameof(index));
+ Contract.EndContractBlock();
+
+ for (DictionaryNode node = head; node != null; node = node.next)
+ {
+ array.SetValue(new DictionaryEntry(node.key, node.value), index);
+ index++;
+ }
+ }
+
+ public IDictionaryEnumerator GetEnumerator()
+ {
+ return new NodeEnumerator(this);
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return new NodeEnumerator(this);
+ }
+
+ public void Remove(Object key)
+ {
+ if (key == null)
+ {
+ throw new ArgumentNullException(nameof(key), SR.ArgumentNull_Key);
+ }
+ Contract.EndContractBlock();
+ version++;
+ DictionaryNode last = null;
+ DictionaryNode node;
+ for (node = head; node != null; node = node.next)
+ {
+ if (node.key.Equals(key))
+ {
+ break;
+ }
+ last = node;
+ }
+ if (node == null)
+ {
+ return;
+ }
+ if (node == head)
+ {
+ head = node.next;
+ }
+ else
+ {
+ last.next = node.next;
+ }
+ count--;
+ }
+
+ private class NodeEnumerator : IDictionaryEnumerator
+ {
+ private ListDictionaryInternal list;
+ private DictionaryNode current;
+ private int version;
+ private bool start;
+
+
+ public NodeEnumerator(ListDictionaryInternal list)
+ {
+ this.list = list;
+ version = list.version;
+ start = true;
+ current = null;
+ }
+
+ public Object Current
+ {
+ get
+ {
+ return Entry;
+ }
+ }
+
+ public DictionaryEntry Entry
+ {
+ get
+ {
+ if (current == null)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen);
+ }
+ return new DictionaryEntry(current.key, current.value);
+ }
+ }
+
+ public Object Key
+ {
+ get
+ {
+ if (current == null)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen);
+ }
+ return current.key;
+ }
+ }
+
+ public Object Value
+ {
+ get
+ {
+ if (current == null)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen);
+ }
+ return current.value;
+ }
+ }
+
+ public bool MoveNext()
+ {
+ if (version != list.version)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion);
+ }
+ if (start)
+ {
+ current = list.head;
+ start = false;
+ }
+ else
+ {
+ if (current != null)
+ {
+ current = current.next;
+ }
+ }
+ return (current != null);
+ }
+
+ public void Reset()
+ {
+ if (version != list.version)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion);
+ }
+ start = true;
+ current = null;
+ }
+ }
+
+
+ private class NodeKeyValueCollection : ICollection
+ {
+ private ListDictionaryInternal list;
+ private bool isKeys;
+
+ public NodeKeyValueCollection(ListDictionaryInternal list, bool isKeys)
+ {
+ this.list = list;
+ this.isKeys = isKeys;
+ }
+
+ void ICollection.CopyTo(Array array, int index)
+ {
+ if (array == null)
+ throw new ArgumentNullException(nameof(array));
+ if (array.Rank != 1)
+ throw new ArgumentException(SR.Arg_RankMultiDimNotSupported);
+ if (index < 0)
+ throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_NeedNonNegNum);
+ Contract.EndContractBlock();
+ if (array.Length - index < list.Count)
+ throw new ArgumentException(SR.ArgumentOutOfRange_Index, nameof(index));
+ for (DictionaryNode node = list.head; node != null; node = node.next)
+ {
+ array.SetValue(isKeys ? node.key : node.value, index);
+ index++;
+ }
+ }
+
+ int ICollection.Count
+ {
+ get
+ {
+ int count = 0;
+ for (DictionaryNode node = list.head; node != null; node = node.next)
+ {
+ count++;
+ }
+ return count;
+ }
+ }
+
+ bool ICollection.IsSynchronized
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ Object ICollection.SyncRoot
+ {
+ get
+ {
+ return list.SyncRoot;
+ }
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return new NodeKeyValueEnumerator(list, isKeys);
+ }
+
+
+ private class NodeKeyValueEnumerator : IEnumerator
+ {
+ private ListDictionaryInternal list;
+ private DictionaryNode current;
+ private int version;
+ private bool isKeys;
+ private bool start;
+
+ public NodeKeyValueEnumerator(ListDictionaryInternal list, bool isKeys)
+ {
+ this.list = list;
+ this.isKeys = isKeys;
+ version = list.version;
+ start = true;
+ current = null;
+ }
+
+ public Object Current
+ {
+ get
+ {
+ if (current == null)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen);
+ }
+ return isKeys ? current.key : current.value;
+ }
+ }
+
+ public bool MoveNext()
+ {
+ if (version != list.version)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion);
+ }
+ if (start)
+ {
+ current = list.head;
+ start = false;
+ }
+ else
+ {
+ if (current != null)
+ {
+ current = current.next;
+ }
+ }
+ return (current != null);
+ }
+
+ public void Reset()
+ {
+ if (version != list.version)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion);
+ }
+ start = true;
+ current = null;
+ }
+ }
+ }
+
+ [Serializable]
+ private class DictionaryNode
+ {
+ public Object key;
+ public Object value;
+ public DictionaryNode next;
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/Collections/ObjectModel/Collection.cs b/src/mscorlib/shared/System/Collections/ObjectModel/Collection.cs
new file mode 100644
index 0000000000..75e88eccb3
--- /dev/null
+++ b/src/mscorlib/shared/System/Collections/ObjectModel/Collection.cs
@@ -0,0 +1,396 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace System.Collections.ObjectModel
+{
+ [Serializable]
+ [DebuggerTypeProxy(typeof(Mscorlib_CollectionDebugView<>))]
+ [DebuggerDisplay("Count = {Count}")]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ public class Collection<T> : IList<T>, IList, IReadOnlyList<T>
+ {
+ private IList<T> items; // Do not rename (binary serialization)
+ [NonSerialized]
+ private Object _syncRoot;
+
+ public Collection()
+ {
+ items = new List<T>();
+ }
+
+ public Collection(IList<T> list)
+ {
+ if (list == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.list);
+ }
+ items = list;
+ }
+
+ public int Count
+ {
+ get { return items.Count; }
+ }
+
+ protected IList<T> Items
+ {
+ get { return items; }
+ }
+
+ public T this[int index]
+ {
+ get { return items[index]; }
+ set
+ {
+ if (items.IsReadOnly)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ if (index < 0 || index >= items.Count)
+ {
+ ThrowHelper.ThrowArgumentOutOfRange_IndexException();
+ }
+
+ SetItem(index, value);
+ }
+ }
+
+ public void Add(T item)
+ {
+ if (items.IsReadOnly)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ int index = items.Count;
+ InsertItem(index, item);
+ }
+
+ public void Clear()
+ {
+ if (items.IsReadOnly)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ ClearItems();
+ }
+
+ public void CopyTo(T[] array, int index)
+ {
+ items.CopyTo(array, index);
+ }
+
+ public bool Contains(T item)
+ {
+ return items.Contains(item);
+ }
+
+ public IEnumerator<T> GetEnumerator()
+ {
+ return items.GetEnumerator();
+ }
+
+ public int IndexOf(T item)
+ {
+ return items.IndexOf(item);
+ }
+
+ public void Insert(int index, T item)
+ {
+ if (items.IsReadOnly)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ if (index < 0 || index > items.Count)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_ListInsert);
+ }
+
+ InsertItem(index, item);
+ }
+
+ public bool Remove(T item)
+ {
+ if (items.IsReadOnly)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ int index = items.IndexOf(item);
+ if (index < 0) return false;
+ RemoveItem(index);
+ return true;
+ }
+
+ public void RemoveAt(int index)
+ {
+ if (items.IsReadOnly)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ if (index < 0 || index >= items.Count)
+ {
+ ThrowHelper.ThrowArgumentOutOfRange_IndexException();
+ }
+
+ RemoveItem(index);
+ }
+
+ protected virtual void ClearItems()
+ {
+ items.Clear();
+ }
+
+ protected virtual void InsertItem(int index, T item)
+ {
+ items.Insert(index, item);
+ }
+
+ protected virtual void RemoveItem(int index)
+ {
+ items.RemoveAt(index);
+ }
+
+ protected virtual void SetItem(int index, T item)
+ {
+ items[index] = item;
+ }
+
+ bool ICollection<T>.IsReadOnly
+ {
+ get
+ {
+ return items.IsReadOnly;
+ }
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ((IEnumerable)items).GetEnumerator();
+ }
+
+ bool ICollection.IsSynchronized
+ {
+ get { return false; }
+ }
+
+ object ICollection.SyncRoot
+ {
+ get
+ {
+ if (_syncRoot == null)
+ {
+ ICollection c = items as ICollection;
+ if (c != null)
+ {
+ _syncRoot = c.SyncRoot;
+ }
+ else
+ {
+ System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
+ }
+ }
+ return _syncRoot;
+ }
+ }
+
+ void ICollection.CopyTo(Array array, int index)
+ {
+ if (array == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+
+ if (array.Rank != 1)
+ {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
+ }
+
+ if (array.GetLowerBound(0) != 0)
+ {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
+ }
+
+ if (index < 0)
+ {
+ ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
+ }
+
+ if (array.Length - index < Count)
+ {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
+ }
+
+ T[] tArray = array as T[];
+ if (tArray != null)
+ {
+ items.CopyTo(tArray, index);
+ }
+ else
+ {
+ //
+ // Catch the obvious case assignment will fail.
+ // We can't find all possible problems by doing the check though.
+ // For example, if the element type of the Array is derived from T,
+ // we can't figure out if we can successfully copy the element beforehand.
+ //
+ Type targetType = array.GetType().GetElementType();
+ Type sourceType = typeof(T);
+ if (!(targetType.IsAssignableFrom(sourceType) || sourceType.IsAssignableFrom(targetType)))
+ {
+ ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType();
+ }
+
+ //
+ // We can't cast array of value type to object[], so we don't support
+ // widening of primitive types here.
+ //
+ object[] objects = array as object[];
+ if (objects == null)
+ {
+ ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType();
+ }
+
+ int count = items.Count;
+ try
+ {
+ for (int i = 0; i < count; i++)
+ {
+ objects[index++] = items[i];
+ }
+ }
+ catch (ArrayTypeMismatchException)
+ {
+ ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType();
+ }
+ }
+ }
+
+ object IList.this[int index]
+ {
+ get { return items[index]; }
+ set
+ {
+ ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(value, ExceptionArgument.value);
+
+ try
+ {
+ this[index] = (T)value;
+ }
+ catch (InvalidCastException)
+ {
+ ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(T));
+ }
+ }
+ }
+
+ bool IList.IsReadOnly
+ {
+ get
+ {
+ return items.IsReadOnly;
+ }
+ }
+
+ bool IList.IsFixedSize
+ {
+ get
+ {
+ // There is no IList<T>.IsFixedSize, so we must assume that only
+ // readonly collections are fixed size, if our internal item
+ // collection does not implement IList. Note that Array implements
+ // IList, and therefore T[] and U[] will be fixed-size.
+ IList list = items as IList;
+ if (list != null)
+ {
+ return list.IsFixedSize;
+ }
+ return items.IsReadOnly;
+ }
+ }
+
+ int IList.Add(object value)
+ {
+ if (items.IsReadOnly)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+ ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(value, ExceptionArgument.value);
+
+ try
+ {
+ Add((T)value);
+ }
+ catch (InvalidCastException)
+ {
+ ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(T));
+ }
+
+ return this.Count - 1;
+ }
+
+ bool IList.Contains(object value)
+ {
+ if (IsCompatibleObject(value))
+ {
+ return Contains((T)value);
+ }
+ return false;
+ }
+
+ int IList.IndexOf(object value)
+ {
+ if (IsCompatibleObject(value))
+ {
+ return IndexOf((T)value);
+ }
+ return -1;
+ }
+
+ void IList.Insert(int index, object value)
+ {
+ if (items.IsReadOnly)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+ ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(value, ExceptionArgument.value);
+
+ try
+ {
+ Insert(index, (T)value);
+ }
+ catch (InvalidCastException)
+ {
+ ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(T));
+ }
+ }
+
+ void IList.Remove(object value)
+ {
+ if (items.IsReadOnly)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ if (IsCompatibleObject(value))
+ {
+ Remove((T)value);
+ }
+ }
+
+ private static bool IsCompatibleObject(object value)
+ {
+ // Non-null values are fine. Only accept nulls if T is a class or Nullable<U>.
+ // Note that default(T) is not equal to null for value types except when T is Nullable<U>.
+ return ((value is T) || (value == null && default(T) == null));
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/Collections/ObjectModel/ReadOnlyCollection.cs b/src/mscorlib/shared/System/Collections/ObjectModel/ReadOnlyCollection.cs
new file mode 100644
index 0000000000..f1d2a0969b
--- /dev/null
+++ b/src/mscorlib/shared/System/Collections/ObjectModel/ReadOnlyCollection.cs
@@ -0,0 +1,279 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace System.Collections.ObjectModel
+{
+ [Serializable]
+ [DebuggerTypeProxy(typeof(Mscorlib_CollectionDebugView<>))]
+ [DebuggerDisplay("Count = {Count}")]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ public class ReadOnlyCollection<T> : IList<T>, IList, IReadOnlyList<T>
+ {
+ private IList<T> list; // Do not rename (binary serialization)
+ [NonSerialized]
+ private Object _syncRoot;
+
+ public ReadOnlyCollection(IList<T> list)
+ {
+ if (list == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.list);
+ }
+ this.list = list;
+ }
+
+ public int Count
+ {
+ get { return list.Count; }
+ }
+
+ public T this[int index]
+ {
+ get { return list[index]; }
+ }
+
+ public bool Contains(T value)
+ {
+ return list.Contains(value);
+ }
+
+ public void CopyTo(T[] array, int index)
+ {
+ list.CopyTo(array, index);
+ }
+
+ public IEnumerator<T> GetEnumerator()
+ {
+ return list.GetEnumerator();
+ }
+
+ public int IndexOf(T value)
+ {
+ return list.IndexOf(value);
+ }
+
+ protected IList<T> Items
+ {
+ get
+ {
+ return list;
+ }
+ }
+
+ bool ICollection<T>.IsReadOnly
+ {
+ get { return true; }
+ }
+
+ T IList<T>.this[int index]
+ {
+ get { return list[index]; }
+ set
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+ }
+
+ void ICollection<T>.Add(T value)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ void ICollection<T>.Clear()
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ void IList<T>.Insert(int index, T value)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ bool ICollection<T>.Remove(T value)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ return false;
+ }
+
+ void IList<T>.RemoveAt(int index)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ((IEnumerable)list).GetEnumerator();
+ }
+
+ bool ICollection.IsSynchronized
+ {
+ get { return false; }
+ }
+
+ object ICollection.SyncRoot
+ {
+ get
+ {
+ if (_syncRoot == null)
+ {
+ ICollection c = list as ICollection;
+ if (c != null)
+ {
+ _syncRoot = c.SyncRoot;
+ }
+ else
+ {
+ System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
+ }
+ }
+ return _syncRoot;
+ }
+ }
+
+ void ICollection.CopyTo(Array array, int index)
+ {
+ if (array == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+
+ if (array.Rank != 1)
+ {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
+ }
+
+ if (array.GetLowerBound(0) != 0)
+ {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
+ }
+
+ if (index < 0)
+ {
+ ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
+ }
+
+ if (array.Length - index < Count)
+ {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
+ }
+
+ T[] items = array as T[];
+ if (items != null)
+ {
+ list.CopyTo(items, index);
+ }
+ else
+ {
+ //
+ // Catch the obvious case assignment will fail.
+ // We can't find all possible problems by doing the check though.
+ // For example, if the element type of the Array is derived from T,
+ // we can't figure out if we can successfully copy the element beforehand.
+ //
+ Type targetType = array.GetType().GetElementType();
+ Type sourceType = typeof(T);
+ if (!(targetType.IsAssignableFrom(sourceType) || sourceType.IsAssignableFrom(targetType)))
+ {
+ ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType();
+ }
+
+ //
+ // We can't cast array of value type to object[], so we don't support
+ // widening of primitive types here.
+ //
+ object[] objects = array as object[];
+ if (objects == null)
+ {
+ ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType();
+ }
+
+ int count = list.Count;
+ try
+ {
+ for (int i = 0; i < count; i++)
+ {
+ objects[index++] = list[i];
+ }
+ }
+ catch (ArrayTypeMismatchException)
+ {
+ ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType();
+ }
+ }
+ }
+
+ bool IList.IsFixedSize
+ {
+ get { return true; }
+ }
+
+ bool IList.IsReadOnly
+ {
+ get { return true; }
+ }
+
+ object IList.this[int index]
+ {
+ get { return list[index]; }
+ set
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+ }
+
+ int IList.Add(object value)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ return -1;
+ }
+
+ void IList.Clear()
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ private static bool IsCompatibleObject(object value)
+ {
+ // Non-null values are fine. Only accept nulls if T is a class or Nullable<U>.
+ // Note that default(T) is not equal to null for value types except when T is Nullable<U>.
+ return ((value is T) || (value == null && default(T) == null));
+ }
+
+ bool IList.Contains(object value)
+ {
+ if (IsCompatibleObject(value))
+ {
+ return Contains((T)value);
+ }
+ return false;
+ }
+
+ int IList.IndexOf(object value)
+ {
+ if (IsCompatibleObject(value))
+ {
+ return IndexOf((T)value);
+ }
+ return -1;
+ }
+
+ void IList.Insert(int index, object value)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ void IList.Remove(object value)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ void IList.RemoveAt(int index)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/Convert.cs b/src/mscorlib/shared/System/Convert.cs
index 576f78f1f1..02fbbdbc3e 100644
--- a/src/mscorlib/shared/System/Convert.cs
+++ b/src/mscorlib/shared/System/Convert.cs
@@ -84,7 +84,7 @@ namespace System
// of the conversion method.
// Constant representing the database null value. This value is used in
- // database applications to indicate the absense of a known value. Note
+ // database applications to indicate the absence of a known value. Note
// that Value.DBNull is NOT the same as a null object reference, which is
// represented by Value.Empty.
//
@@ -2670,7 +2670,7 @@ namespace System
/// Converts the specified string, which encodes binary data as Base64 digits, to the equivalent byte array.
/// </summary>
/// <param name="s">The string to convert</param>
- /// <returns>The array of bytes represented by the specifed Base64 string.</returns>
+ /// <returns>The array of bytes represented by the specified Base64 string.</returns>
public static Byte[] FromBase64String(String s)
{
// "s" is an unfortunate parameter name, but we need to keep it for backward compat.
diff --git a/src/mscorlib/shared/System/DBNull.cs b/src/mscorlib/shared/System/DBNull.cs
index 4f4d64bf66..3cee2b15c8 100644
--- a/src/mscorlib/shared/System/DBNull.cs
+++ b/src/mscorlib/shared/System/DBNull.cs
@@ -6,17 +6,23 @@ using System.Runtime.Serialization;
namespace System
{
+ [Serializable]
public sealed class DBNull : ISerializable, IConvertible
{
private DBNull()
{
}
-
+
+ private DBNull(SerializationInfo info, StreamingContext context)
+ {
+ throw new NotSupportedException(SR.NotSupported_DBNullSerial);
+ }
+
public static readonly DBNull Value = new DBNull();
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
- throw new PlatformNotSupportedException();
+ UnitySerializationHolder.GetUnitySerializationInfo(info, UnitySerializationHolder.NullUnity);
}
public override string ToString()
diff --git a/src/mscorlib/shared/System/DataMisalignedException.cs b/src/mscorlib/shared/System/DataMisalignedException.cs
index ff5b29f1cf..d8d36b5cb7 100644
--- a/src/mscorlib/shared/System/DataMisalignedException.cs
+++ b/src/mscorlib/shared/System/DataMisalignedException.cs
@@ -18,19 +18,19 @@ namespace System
public DataMisalignedException()
: base(SR.Arg_DataMisalignedException)
{
- HResult = __HResults.COR_E_DATAMISALIGNED;
+ HResult = HResults.COR_E_DATAMISALIGNED;
}
public DataMisalignedException(String message)
: base(message)
{
- HResult = __HResults.COR_E_DATAMISALIGNED;
+ HResult = HResults.COR_E_DATAMISALIGNED;
}
public DataMisalignedException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_DATAMISALIGNED;
+ HResult = HResults.COR_E_DATAMISALIGNED;
}
}
}
diff --git a/src/mscorlib/shared/System/DateTime.cs b/src/mscorlib/shared/System/DateTime.cs
index 16a75fdfa6..e72654a8d6 100644
--- a/src/mscorlib/shared/System/DateTime.cs
+++ b/src/mscorlib/shared/System/DateTime.cs
@@ -129,7 +129,7 @@ namespace System
private const String TicksField = "ticks"; // Do not rename (binary serialization)
private const String DateDataField = "dateData"; // Do not rename (binary serialization)
- // The data is stored as an unsigned 64-bit integeter
+ // The data is stored as an unsigned 64-bit integer
// Bits 01-62: The value of 100-nanosecond ticks where 0 represents 1/1/0001 12:00am, up until the value
// 12/31/9999 23:59:59.9999999
// Bits 63-64: A four-state value that describes the DateTimeKind value of the date time, with a 2nd
@@ -1025,11 +1025,7 @@ namespace System
}
// Returns a DateTime representing the current date and time. The
- // resolution of the returned value depends on the system timer. For
- // Windows NT 3.5 and later the timer resolution is approximately 10ms,
- // for Windows NT 3.1 it is approximately 16ms, and for Windows 95 and 98
- // it is approximately 55ms.
- //
+ // resolution of the returned value depends on the system timer.
public static DateTime Now
{
get
diff --git a/src/mscorlib/shared/System/DateTimeOffset.cs b/src/mscorlib/shared/System/DateTimeOffset.cs
index ab35bdb0fe..e3366e2a7d 100644
--- a/src/mscorlib/shared/System/DateTimeOffset.cs
+++ b/src/mscorlib/shared/System/DateTimeOffset.cs
@@ -129,11 +129,7 @@ namespace System
}
// Returns a DateTimeOffset representing the current date and time. The
- // resolution of the returned value depends on the system timer. For
- // Windows NT 3.5 and later the timer resolution is approximately 10ms,
- // for Windows NT 3.1 it is approximately 16ms, and for Windows 95 and 98
- // it is approximately 55ms.
- //
+ // resolution of the returned value depends on the system timer.
public static DateTimeOffset Now
{
get
diff --git a/src/mscorlib/shared/System/DefaultBinder.cs b/src/mscorlib/shared/System/DefaultBinder.cs
index 9adf702a02..b6c12b121d 100644
--- a/src/mscorlib/shared/System/DefaultBinder.cs
+++ b/src/mscorlib/shared/System/DefaultBinder.cs
@@ -42,7 +42,7 @@ namespace System
state = null;
-#region Map named parameters to candidate parameter postions
+#region Map named parameters to candidate parameter positions
// We are creating an paramOrder array to act as a mapping
// between the order of the args and the actual order of the
// parameters in the method. This order may differ because
@@ -530,7 +530,7 @@ namespace System
for (i = 0; i < types.Length; i++)
{
realTypes[i] = types[i].UnderlyingSystemType;
- if (!(realTypes[i].IsRuntimeImplemented()))
+ if (!(realTypes[i].IsRuntimeImplemented() || realTypes[i] is SignatureType))
throw new ArgumentException(SR.Arg_MustBeType, nameof(types));
}
types = realTypes;
@@ -552,19 +552,30 @@ namespace System
for (j = 0; j < types.Length; j++)
{
Type pCls = par[j].ParameterType;
- if (pCls == types[j])
+ if (types[j].MatchesParameterTypeExactly(par[j]))
continue;
if (pCls == typeof(object))
continue;
+
+ Type type = types[j];
+ if (type is SignatureType signatureType)
+ {
+ if (!(candidates[i] is MethodInfo methodInfo))
+ break;
+ type = signatureType.TryResolveAgainstGenericMethod(methodInfo);
+ if (type == null)
+ break;
+ }
+
if (pCls.IsPrimitive)
{
- if (!(types[j].UnderlyingSystemType.IsRuntimeImplemented()) ||
- !CanChangePrimitive(types[j].UnderlyingSystemType, pCls.UnderlyingSystemType))
+ if (!(type.UnderlyingSystemType.IsRuntimeImplemented()) ||
+ !CanChangePrimitive(type.UnderlyingSystemType, pCls.UnderlyingSystemType))
break;
}
else
{
- if (!pCls.IsAssignableFrom(types[j]))
+ if (!pCls.IsAssignableFrom(type))
break;
}
}
@@ -918,11 +929,22 @@ namespace System
if (c1 == c2)
return 0;
- if (c1 == t)
- return 1;
+ if (t is SignatureType signatureType)
+ {
+ if (signatureType.MatchesExactly(c1))
+ return 1;
- if (c2 == t)
- return 2;
+ if (signatureType.MatchesExactly(c2))
+ return 2;
+ }
+ else
+ {
+ if (c1 == t)
+ return 1;
+
+ if (c2 == t)
+ return 2;
+ }
bool c1FromC2;
bool c2FromC1;
diff --git a/src/mscorlib/shared/System/Diagnostics/Tracing/EventProvider.cs b/src/mscorlib/shared/System/Diagnostics/Tracing/EventProvider.cs
index 5292551314..a74125a35a 100644
--- a/src/mscorlib/shared/System/Diagnostics/Tracing/EventProvider.cs
+++ b/src/mscorlib/shared/System/Diagnostics/Tracing/EventProvider.cs
@@ -87,7 +87,8 @@ namespace System.Diagnostics.Tracing
private long m_allKeywordMask; // Match all keyword
private List<SessionInfo> m_liveSessions; // current live sessions (Tuple<sessionIdBit, etwSessionId>)
private bool m_enabled; // Enabled flag from Trace callback
- private Guid m_providerId; // Control Guid
+ private string m_providerName; // Control name
+ private Guid m_providerId; // Control Guid
internal bool m_disposed; // when true provider has unregistered
[ThreadStatic]
@@ -140,16 +141,19 @@ namespace System.Diagnostics.Tracing
// <SatisfiesLinkDemand Name="Win32Exception..ctor(System.Int32)" />
// <ReferencesCritical Name="Method: EtwEnableCallBack(Guid&, Int32, Byte, Int64, Int64, Void*, Void*):Void" Ring="1" />
// </SecurityKernel>
- internal unsafe void Register(Guid providerGuid)
+ internal unsafe void Register(EventSource eventSource)
{
- m_providerId = providerGuid;
uint status;
m_etwCallback = new UnsafeNativeMethods.ManifestEtw.EtwEnableCallback(EtwEnableCallBack);
- status = EventRegister(ref m_providerId, m_etwCallback);
+ status = EventRegister(eventSource, m_etwCallback);
if (status != 0)
{
- throw new ArgumentException(Win32Native.GetMessage(unchecked((int)status)));
+#if PLATFORM_WINDOWS
+ throw new ArgumentException(Interop.Kernel32.GetMessage(unchecked((int)status)));
+#else
+ throw new ArgumentException(Convert.ToString(unchecked((int)status)));
+#endif
}
}
@@ -488,7 +492,7 @@ namespace System.Diagnostics.Tracing
// at least some of the time.
// Determine our session from what is in the registry.
- string regKey = @"\Microsoft\Windows\CurrentVersion\Winevt\Publishers\{" + m_providerId + "}";
+ string regKey = @"\Microsoft\Windows\CurrentVersion\Winevt\Publishers\{" + m_providerName + "}";
if (System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)) == 8)
regKey = @"Software" + @"\Wow6432Node" + regKey;
else
@@ -563,7 +567,7 @@ namespace System.Diagnostics.Tracing
if (filterData == null)
{
#if (!ES_BUILD_PCL && !ES_BUILD_PN && PLATFORM_WINDOWS)
- string regKey = @"\Microsoft\Windows\CurrentVersion\Winevt\Publishers\{" + m_providerId + "}";
+ string regKey = @"\Microsoft\Windows\CurrentVersion\Winevt\Publishers\{" + m_providerName + "}";
if (System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)) == 8)
regKey = @"HKEY_LOCAL_MACHINE\Software" + @"\Wow6432Node" + regKey;
else
@@ -1184,11 +1188,12 @@ namespace System.Diagnostics.Tracing
// These are look-alikes to the Manifest based ETW OS APIs that have been shimmed to work
// either with Manifest ETW or Classic ETW (if Manifest based ETW is not available).
- private unsafe uint EventRegister(ref Guid providerId, UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback)
+ private unsafe uint EventRegister(EventSource eventSource, UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback)
{
- m_providerId = providerId;
+ m_providerName = eventSource.Name;
+ m_providerId = eventSource.Guid;
m_etwCallback = enableCallback;
- return m_eventProvider.EventRegister(ref providerId, enableCallback, null, ref m_regHandle);
+ return m_eventProvider.EventRegister(eventSource, enableCallback, null, ref m_regHandle);
}
private uint EventUnregister(long registrationHandle)
@@ -1221,11 +1226,12 @@ namespace System.Diagnostics.Tracing
{
// Register an event provider.
unsafe uint IEventProvider.EventRegister(
- ref Guid providerId,
+ EventSource eventSource,
UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback,
void* callbackContext,
ref long registrationHandle)
{
+ Guid providerId = eventSource.Guid;
return UnsafeNativeMethods.ManifestEtw.EventRegister(
ref providerId,
enableCallback,
@@ -1278,7 +1284,7 @@ namespace System.Diagnostics.Tracing
internal sealed class NoOpEventProvider : IEventProvider
{
unsafe uint IEventProvider.EventRegister(
- ref Guid providerId,
+ EventSource eventSource,
UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback,
void* callbackContext,
ref long registrationHandle)
diff --git a/src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs b/src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs
index d8eec73931..4e436e7baf 100644
--- a/src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs
+++ b/src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs
@@ -265,7 +265,7 @@ namespace System.Diagnostics.Tracing
public Guid Guid { get { return m_guid; } }
/// <summary>
- /// Returns true if the eventSource has been enabled at all. This is the prefered test
+ /// Returns true if the eventSource has been enabled at all. This is the preferred test
/// to be performed before a relatively expensive EventSource operation.
/// </summary>
[SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
@@ -572,11 +572,11 @@ namespace System.Diagnostics.Tracing
/// <summary>
/// EventSources can have arbitrary string key-value pairs associated with them called Traits.
/// These traits are not interpreted by the EventSource but may be interpreted by EventListeners
- /// (e.g. like the built in ETW listener). These traits are specififed at EventSource
+ /// (e.g. like the built in ETW listener). These traits are specified at EventSource
/// construction time and can be retrieved by using this GetTrait API.
/// </summary>
/// <param name="key">The key to look up in the set of key-value pairs passed to the EventSource constructor</param>
- /// <returns>The value string associated iwth key. Will return null if there is no such key.</returns>
+ /// <returns>The value string associated with key. Will return null if there is no such key.</returns>
public string GetTrait(string key)
{
if (m_traits != null)
@@ -661,7 +661,7 @@ namespace System.Diagnostics.Tracing
///
/// Also specify a list of key-value pairs called traits (you must pass an even number of strings).
/// The first string is the key and the second is the value. These are not interpreted by EventSource
- /// itself but may be interprated the listeners. Can be fetched with GetTrait(string).
+ /// itself but may be interpreted the listeners. Can be fetched with GetTrait(string).
/// </summary>
/// <param name="settings">See EventSourceSettings for more.</param>
/// <param name="traits">A collection of key-value strings (must be an even number).</param>
@@ -1560,7 +1560,7 @@ namespace System.Diagnostics.Tracing
// Register the provider with ETW
var provider = new OverideEventProvider(this);
- provider.Register(eventSourceGuid);
+ provider.Register(this);
#endif
// Add the eventSource to the global (weak) list.
// This also sets m_id, which is the index in the list.
@@ -4942,10 +4942,10 @@ namespace System.Diagnostics.Tracing
get
{
// For contract based events we create the list lazily.
- if (m_payloadNames == null)
+ // You can have m_payloadNames be null in the TraceLogging case (EventID < 0) so only
+ // do the lazy init if you know it is contract based (EventID >= 0)
+ if (EventId >= 0 && m_payloadNames == null)
{
- // Self described events are identified by id -1.
- Debug.Assert(EventId != -1);
var names = new List<string>();
foreach (var parameter in m_eventSource.m_eventData[EventId].Parameters)
@@ -5521,7 +5521,7 @@ namespace System.Diagnostics.Tracing
/// Returns a session mask representing all sessions in which the activity
/// associated with the current thread is allowed through the activity filter.
/// If 'triggeringEvent' is true the event MAY be a triggering event. Ideally
- /// most of the time this is false as you can guarentee this event is NOT a
+ /// most of the time this is false as you can guarantee this event is NOT a
/// triggering event. If 'triggeringEvent' is true, then it checks the
/// 'EventSource' and 'eventID' of the event being logged to see if it is actually
/// a trigger. If so it activates the current activity.
@@ -5622,7 +5622,7 @@ namespace System.Diagnostics.Tracing
/// <summary>
/// For the EventListener/EtwSession associated with 'filterList', add 'childActivityid'
/// to list of active activities IF 'currentActivityId' is also active. Passing in a null
- /// value for 'currentActivityid' is an indication tha caller has already verified
+ /// value for 'currentActivityid' is an indication the caller has already verified
/// that the current activity is active.
/// </summary>
unsafe public static void FlowActivityIfNeeded(ActivityFilter filterList, Guid* currentActivityId, Guid* childActivityID)
@@ -5642,7 +5642,7 @@ namespace System.Diagnostics.Tracing
// make sure current activity is still in the set:
activeActivities[EventSource.InternalCurrentThreadActivityId] = Environment.TickCount;
}
- // add child activity to list of actives
+ // add child activity to list of activities
activeActivities[*childActivityID] = Environment.TickCount;
}
@@ -6070,11 +6070,11 @@ namespace System.Diagnostics.Tracing
/// (m_EventEnabled) for a particular EventSource X EventListener tuple
///
/// Thus a single EventListener may have many EventDispatchers (one for every EventSource
- /// that that EventListener has activate) and a Single EventSource may also have many
+ /// that EventListener has activate) and a Single EventSource may also have many
/// event Dispatchers (one for every EventListener that has activated it).
///
/// Logically a particular EventDispatcher belongs to exactly one EventSource and exactly
- /// one EventListener (alhtough EventDispatcher does not 'remember' the EventSource it is
+ /// one EventListener (although EventDispatcher does not 'remember' the EventSource it is
/// associated with.
/// </summary>
internal class EventDispatcher
diff --git a/src/mscorlib/shared/System/Diagnostics/Tracing/IEventProvider.cs b/src/mscorlib/shared/System/Diagnostics/Tracing/IEventProvider.cs
index 71a2fe4d44..966dac2fef 100644
--- a/src/mscorlib/shared/System/Diagnostics/Tracing/IEventProvider.cs
+++ b/src/mscorlib/shared/System/Diagnostics/Tracing/IEventProvider.cs
@@ -15,7 +15,7 @@ namespace System.Diagnostics.Tracing
{
// Register an event provider.
unsafe uint EventRegister(
- ref Guid providerId,
+ EventSource eventSource,
UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback,
void* callbackContext,
ref long registrationHandle);
diff --git a/src/mscorlib/shared/System/Diagnostics/Tracing/TraceLogging/EventSourceActivity.cs b/src/mscorlib/shared/System/Diagnostics/Tracing/TraceLogging/EventSourceActivity.cs
index 38c1767462..acc3eeb233 100644
--- a/src/mscorlib/shared/System/Diagnostics/Tracing/TraceLogging/EventSourceActivity.cs
+++ b/src/mscorlib/shared/System/Diagnostics/Tracing/TraceLogging/EventSourceActivity.cs
@@ -77,8 +77,8 @@ namespace System.Diagnostics.Tracing
/// <summary>
/// Writes a Start event with the specified name and data. If the start event is not active (because the provider
- /// is not on or keyword-level indiates the event is off, then the returned activity is simply the 'this' poitner
- /// and it is effectively like the Start d
+ /// is not on or keyword-level indicates the event is off, then the returned activity is simply the 'this' pointer
+ /// and it is effectively like start did not get called.
///
/// A new activityID GUID is generated and the returned
/// EventSourceActivity remembers this activity and will mark every event (including the start stop and any writes)
@@ -139,7 +139,7 @@ namespace System.Diagnostics.Tracing
}
/// <summary>
/// Used if you wish to use the non-default stop name (which is the start name with Start replace with 'Stop')
- /// This can be useful to indicate unusual ways of stoping (but it is still STRONGLY recommeded that
+ /// This can be useful to indicate unusual ways of stopping (but it is still STRONGLY recommended that
/// you start with the same prefix used for the start event and you end with the 'Stop' suffix.
/// </summary>
public void Stop<T>(string eventName)
@@ -149,7 +149,7 @@ namespace System.Diagnostics.Tracing
}
/// <summary>
/// Used if you wish to use the non-default stop name (which is the start name with Start replace with 'Stop')
- /// This can be useful to indicate unusual ways of stoping (but it is still STRONGLY recommeded that
+ /// This can be useful to indicate unusual ways of stopping (but it is still STRONGLY recommended that
/// you start with the same prefix used for the start event and you end with the 'Stop' suffix.
/// </summary>
public void Stop<T>(string eventName, T data)
@@ -158,7 +158,7 @@ namespace System.Diagnostics.Tracing
}
/// <summary>
- /// Writes an event associated with this activity to the eventSource associted with this activity.
+ /// Writes an event associated with this activity to the eventSource associated with this activity.
/// May only be called when the activity is in the Started state.
/// </summary>
/// <param name="eventName">
diff --git a/src/mscorlib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingDataType.cs b/src/mscorlib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingDataType.cs
index 529948daf8..cc416a96d9 100644
--- a/src/mscorlib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingDataType.cs
+++ b/src/mscorlib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingDataType.cs
@@ -182,7 +182,7 @@ namespace System.Diagnostics.Tracing
/// <summary>
/// Core type.
- /// Special case: Struct indicates that this field plus the the
+ /// Special case: Struct indicates that this field plus the
/// subsequent N logical fields are to be considered as one logical
/// field (i.e. a nested structure). The OutType is used to encode N.
/// The maximum value for N is 127. This field has no payload by
diff --git a/src/mscorlib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs b/src/mscorlib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs
index aba1671ae2..a1218d1a7f 100644
--- a/src/mscorlib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs
+++ b/src/mscorlib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs
@@ -80,7 +80,7 @@ namespace System.Diagnostics.Tracing
///
/// Also specify a list of key-value pairs called traits (you must pass an even number of strings).
/// The first string is the key and the second is the value. These are not interpreted by EventSource
- /// itself but may be interprated the listeners. Can be fetched with GetTrait(string).
+ /// itself but may be interpreted the listeners. Can be fetched with GetTrait(string).
/// </summary>
/// <param name="eventSourceName">
/// The name of the event source. Must not be null.
@@ -442,7 +442,10 @@ namespace System.Diagnostics.Tracing
var pinCount = eventTypes.pinCount;
var scratch = stackalloc byte[eventTypes.scratchSize];
var descriptors = stackalloc EventData[eventTypes.dataCount + 3];
+
var pins = stackalloc GCHandle[pinCount];
+ for (int i = 0; i < pinCount; i++)
+ pins[i] = default(GCHandle);
fixed (byte*
pMetadata0 = this.providerMetadata,
@@ -619,7 +622,10 @@ namespace System.Diagnostics.Tracing
var pinCount = eventTypes.pinCount;
var scratch = stackalloc byte[eventTypes.scratchSize];
var descriptors = stackalloc EventData[eventTypes.dataCount + 3];
+
var pins = stackalloc GCHandle[pinCount];
+ for (int i = 0; i < pinCount; i++)
+ pins[i] = default(GCHandle);
fixed (byte*
pMetadata0 = this.providerMetadata,
@@ -744,9 +750,9 @@ namespace System.Diagnostics.Tracing
{
DataCollector.ThreadInstance.Disable();
- for (int i = 0; i != cPins; i++)
+ for (int i = 0; i < cPins; i++)
{
- if (IntPtr.Zero != (IntPtr)pPins[i])
+ if (pPins[i].IsAllocated)
{
pPins[i].Free();
}
diff --git a/src/mscorlib/shared/System/DivideByZeroException.cs b/src/mscorlib/shared/System/DivideByZeroException.cs
index 0fad2f8d56..ad74bde0fd 100644
--- a/src/mscorlib/shared/System/DivideByZeroException.cs
+++ b/src/mscorlib/shared/System/DivideByZeroException.cs
@@ -20,19 +20,19 @@ namespace System
public DivideByZeroException()
: base(SR.Arg_DivideByZero)
{
- HResult = __HResults.COR_E_DIVIDEBYZERO;
+ HResult = HResults.COR_E_DIVIDEBYZERO;
}
public DivideByZeroException(String message)
: base(message)
{
- HResult = __HResults.COR_E_DIVIDEBYZERO;
+ HResult = HResults.COR_E_DIVIDEBYZERO;
}
public DivideByZeroException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_DIVIDEBYZERO;
+ HResult = HResults.COR_E_DIVIDEBYZERO;
}
protected DivideByZeroException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/DllNotFoundException.cs b/src/mscorlib/shared/System/DllNotFoundException.cs
index 8c69e45eda..82d5bdd0c5 100644
--- a/src/mscorlib/shared/System/DllNotFoundException.cs
+++ b/src/mscorlib/shared/System/DllNotFoundException.cs
@@ -21,19 +21,19 @@ namespace System
public DllNotFoundException()
: base(SR.Arg_DllNotFoundException)
{
- HResult = __HResults.COR_E_DLLNOTFOUND;
+ HResult = HResults.COR_E_DLLNOTFOUND;
}
public DllNotFoundException(String message)
: base(message)
{
- HResult = __HResults.COR_E_DLLNOTFOUND;
+ HResult = HResults.COR_E_DLLNOTFOUND;
}
public DllNotFoundException(String message, Exception inner)
: base(message, inner)
{
- HResult = __HResults.COR_E_DLLNOTFOUND;
+ HResult = HResults.COR_E_DLLNOTFOUND;
}
protected DllNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/Double.cs b/src/mscorlib/shared/System/Double.cs
new file mode 100644
index 0000000000..7ee52027f3
--- /dev/null
+++ b/src/mscorlib/shared/System/Double.cs
@@ -0,0 +1,451 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: A representation of an IEEE double precision
+** floating point number.
+**
+**
+===========================================================*/
+
+using System.Diagnostics.Contracts;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+
+namespace System
+{
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
+ [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ public struct Double : IComparable, IConvertible, IFormattable, IComparable<Double>, IEquatable<Double>
+ {
+ private double m_value; // Do not rename (binary serialization)
+
+ //
+ // Public Constants
+ //
+ public const double MinValue = -1.7976931348623157E+308;
+ public const double MaxValue = 1.7976931348623157E+308;
+
+ // Note Epsilon should be a double whose hex representation is 0x1
+ // on little endian machines.
+ public const double Epsilon = 4.9406564584124654E-324;
+ public const double NegativeInfinity = (double)-1.0 / (double)(0.0);
+ public const double PositiveInfinity = (double)1.0 / (double)(0.0);
+ public const double NaN = (double)0.0 / (double)0.0;
+
+ // We use this explicit definition to avoid the confusion between 0.0 and -0.0.
+ internal const double NegativeZero = -0.0;
+
+ /// <summary>Determines whether the specified value is finite (zero, subnormal, or normal).</summary>
+ [Pure]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe static bool IsFinite(double d)
+ {
+ var bits = BitConverter.DoubleToInt64Bits(d);
+ return (bits & 0x7FFFFFFFFFFFFFFF) < 0x7FF0000000000000;
+ }
+
+ /// <summary>Determines whether the specified value is infinite.</summary>
+ [Pure]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe static bool IsInfinity(double d)
+ {
+ var bits = BitConverter.DoubleToInt64Bits(d);
+ return (bits & 0x7FFFFFFFFFFFFFFF) == 0x7FF0000000000000;
+ }
+
+ /// <summary>Determines whether the specified value is NaN.</summary>
+ [Pure]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe static bool IsNaN(double d)
+ {
+ var bits = BitConverter.DoubleToInt64Bits(d);
+ return (bits & 0x7FFFFFFFFFFFFFFF) > 0x7FF0000000000000;
+ }
+
+ /// <summary>Determines whether the specified value is negative.</summary>
+ [Pure]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe static bool IsNegative(double d)
+ {
+ var bits = unchecked((ulong)BitConverter.DoubleToInt64Bits(d));
+ return (bits & 0x8000000000000000) == 0x8000000000000000;
+ }
+
+ /// <summary>Determines whether the specified value is negative infinity.</summary>
+ [Pure]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool IsNegativeInfinity(double d)
+ {
+ return (d == double.NegativeInfinity);
+ }
+
+ /// <summary>Determines whether the specified value is normal.</summary>
+ [Pure]
+ [NonVersionable]
+ // This is probably not worth inlining, it has branches and should be rarely called
+ public unsafe static bool IsNormal(double d)
+ {
+ var bits = BitConverter.DoubleToInt64Bits(d);
+ bits &= 0x7FFFFFFFFFFFFFFF;
+ return (bits < 0x7FF0000000000000) && (bits != 0) && ((bits & 0x7FF0000000000000) != 0);
+ }
+
+ /// <summary>Determines whether the specified value is positive infinity.</summary>
+ [Pure]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool IsPositiveInfinity(double d)
+ {
+ return (d == double.PositiveInfinity);
+ }
+
+ /// <summary>Determines whether the specified value is subnormal.</summary>
+ [Pure]
+ [NonVersionable]
+ // This is probably not worth inlining, it has branches and should be rarely called
+ public unsafe static bool IsSubnormal(double d)
+ {
+ var bits = BitConverter.DoubleToInt64Bits(d);
+ bits &= 0x7FFFFFFFFFFFFFFF;
+ return (bits < 0x7FF0000000000000) && (bits != 0) && ((bits & 0x7FF0000000000000) == 0);
+ }
+
+ // Compares this object to another object, returning an instance of System.Relation.
+ // Null is considered less than any instance.
+ //
+ // If object is not of type Double, this method throws an ArgumentException.
+ //
+ // Returns a value less than zero if this object
+ //
+ public int CompareTo(Object value)
+ {
+ if (value == null)
+ {
+ return 1;
+ }
+ if (value is Double)
+ {
+ double d = (double)value;
+ if (m_value < d) return -1;
+ if (m_value > d) return 1;
+ if (m_value == d) return 0;
+
+ // At least one of the values is NaN.
+ if (IsNaN(m_value))
+ return (IsNaN(d) ? 0 : -1);
+ else
+ return 1;
+ }
+ throw new ArgumentException(SR.Arg_MustBeDouble);
+ }
+
+ public int CompareTo(Double value)
+ {
+ if (m_value < value) return -1;
+ if (m_value > value) return 1;
+ if (m_value == value) return 0;
+
+ // At least one of the values is NaN.
+ if (IsNaN(m_value))
+ return (IsNaN(value) ? 0 : -1);
+ else
+ return 1;
+ }
+
+ // True if obj is another Double with the same value as the current instance. This is
+ // a method of object equality, that only returns true if obj is also a double.
+ public override bool Equals(Object obj)
+ {
+ if (!(obj is Double))
+ {
+ return false;
+ }
+ double temp = ((Double)obj).m_value;
+ // This code below is written this way for performance reasons i.e the != and == check is intentional.
+ if (temp == m_value)
+ {
+ return true;
+ }
+ return IsNaN(temp) && IsNaN(m_value);
+ }
+
+ [NonVersionable]
+ public static bool operator ==(Double left, Double right)
+ {
+ return left == right;
+ }
+
+ [NonVersionable]
+ public static bool operator !=(Double left, Double right)
+ {
+ return left != right;
+ }
+
+ [NonVersionable]
+ public static bool operator <(Double left, Double right)
+ {
+ return left < right;
+ }
+
+ [NonVersionable]
+ public static bool operator >(Double left, Double right)
+ {
+ return left > right;
+ }
+
+ [NonVersionable]
+ public static bool operator <=(Double left, Double right)
+ {
+ return left <= right;
+ }
+
+ [NonVersionable]
+ public static bool operator >=(Double left, Double right)
+ {
+ return left >= right;
+ }
+
+ public bool Equals(Double obj)
+ {
+ if (obj == m_value)
+ {
+ return true;
+ }
+ return IsNaN(obj) && IsNaN(m_value);
+ }
+
+ //The hashcode for a double is the absolute value of the integer representation
+ //of that double.
+ //
+ public unsafe override int GetHashCode()
+ {
+ double d = m_value;
+ if (d == 0)
+ {
+ // Ensure that 0 and -0 have the same hash code
+ return 0;
+ }
+ long value = *(long*)(&d);
+ return unchecked((int)value) ^ ((int)(value >> 32));
+ }
+
+ public override String ToString()
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatDouble(m_value, null, NumberFormatInfo.CurrentInfo);
+ }
+
+ public String ToString(String format)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatDouble(m_value, format, NumberFormatInfo.CurrentInfo);
+ }
+
+ public String ToString(IFormatProvider provider)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatDouble(m_value, null, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public String ToString(String format, IFormatProvider provider)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatDouble(m_value, format, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public static double Parse(String s)
+ {
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseDouble(s.AsReadOnlySpan(), NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo);
+ }
+
+ public static double Parse(String s, NumberStyles style)
+ {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseDouble(s.AsReadOnlySpan(), style, NumberFormatInfo.CurrentInfo);
+ }
+
+ public static double Parse(String s, IFormatProvider provider)
+ {
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseDouble(s.AsReadOnlySpan(), NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public static double Parse(String s, NumberStyles style, IFormatProvider provider)
+ {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseDouble(s.AsReadOnlySpan(), style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ // Parses a double from a String in the given style. If
+ // a NumberFormatInfo isn't specified, the current culture's
+ // NumberFormatInfo is assumed.
+ //
+ // This method will not throw an OverflowException, but will return
+ // PositiveInfinity or NegativeInfinity for a number that is too
+ // large or too small.
+
+ public static double Parse(ReadOnlySpan<char> s, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null)
+ {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ return Number.ParseDouble(s, style, NumberFormatInfo.GetInstance(provider));
+ }
+
+
+
+ public static bool TryParse(String s, out double result)
+ {
+ if (s == null)
+ {
+ result = 0;
+ return false;
+ }
+
+ return TryParse(s.AsReadOnlySpan(), NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo, out result);
+ }
+
+ public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out double result)
+ {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+
+ if (s == null)
+ {
+ result = 0;
+ return false;
+ }
+
+ return TryParse(s.AsReadOnlySpan(), style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ public static bool TryParse(ReadOnlySpan<char> s, out double result, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null)
+ {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ private static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out double result)
+ {
+ bool success = Number.TryParseDouble(s, style, info, out result);
+ if (!success)
+ {
+ ReadOnlySpan<char> sTrim = StringSpanHelpers.Trim(s);
+ if (StringSpanHelpers.Equals(sTrim, info.PositiveInfinitySymbol))
+ {
+ result = PositiveInfinity;
+ }
+ else if (StringSpanHelpers.Equals(sTrim, info.NegativeInfinitySymbol))
+ {
+ result = NegativeInfinity;
+ }
+ else if (StringSpanHelpers.Equals(sTrim, info.NaNSymbol))
+ {
+ result = NaN;
+ }
+ else
+ {
+ return false; // We really failed
+ }
+ }
+ return true;
+ }
+
+ //
+ // IConvertible implementation
+ //
+
+ public TypeCode GetTypeCode()
+ {
+ return TypeCode.Double;
+ }
+
+ bool IConvertible.ToBoolean(IFormatProvider provider)
+ {
+ return Convert.ToBoolean(m_value);
+ }
+
+ char IConvertible.ToChar(IFormatProvider provider)
+ {
+ throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Double", "Char"));
+ }
+
+ sbyte IConvertible.ToSByte(IFormatProvider provider)
+ {
+ return Convert.ToSByte(m_value);
+ }
+
+ byte IConvertible.ToByte(IFormatProvider provider)
+ {
+ return Convert.ToByte(m_value);
+ }
+
+ short IConvertible.ToInt16(IFormatProvider provider)
+ {
+ return Convert.ToInt16(m_value);
+ }
+
+ ushort IConvertible.ToUInt16(IFormatProvider provider)
+ {
+ return Convert.ToUInt16(m_value);
+ }
+
+ int IConvertible.ToInt32(IFormatProvider provider)
+ {
+ return Convert.ToInt32(m_value);
+ }
+
+ uint IConvertible.ToUInt32(IFormatProvider provider)
+ {
+ return Convert.ToUInt32(m_value);
+ }
+
+ long IConvertible.ToInt64(IFormatProvider provider)
+ {
+ return Convert.ToInt64(m_value);
+ }
+
+ ulong IConvertible.ToUInt64(IFormatProvider provider)
+ {
+ return Convert.ToUInt64(m_value);
+ }
+
+ float IConvertible.ToSingle(IFormatProvider provider)
+ {
+ return Convert.ToSingle(m_value);
+ }
+
+ double IConvertible.ToDouble(IFormatProvider provider)
+ {
+ return m_value;
+ }
+
+ Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ {
+ return Convert.ToDecimal(m_value);
+ }
+
+ DateTime IConvertible.ToDateTime(IFormatProvider provider)
+ {
+ throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Double", "DateTime"));
+ }
+
+ Object IConvertible.ToType(Type type, IFormatProvider provider)
+ {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/DuplicateWaitObjectException.cs b/src/mscorlib/shared/System/DuplicateWaitObjectException.cs
index 7eadead8c7..95bdedd526 100644
--- a/src/mscorlib/shared/System/DuplicateWaitObjectException.cs
+++ b/src/mscorlib/shared/System/DuplicateWaitObjectException.cs
@@ -37,25 +37,25 @@ namespace System
public DuplicateWaitObjectException()
: base(DuplicateWaitObjectMessage)
{
- HResult = __HResults.COR_E_DUPLICATEWAITOBJECT;
+ HResult = HResults.COR_E_DUPLICATEWAITOBJECT;
}
public DuplicateWaitObjectException(String parameterName)
: base(DuplicateWaitObjectMessage, parameterName)
{
- HResult = __HResults.COR_E_DUPLICATEWAITOBJECT;
+ HResult = HResults.COR_E_DUPLICATEWAITOBJECT;
}
public DuplicateWaitObjectException(String parameterName, String message)
: base(message, parameterName)
{
- HResult = __HResults.COR_E_DUPLICATEWAITOBJECT;
+ HResult = HResults.COR_E_DUPLICATEWAITOBJECT;
}
public DuplicateWaitObjectException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_DUPLICATEWAITOBJECT;
+ HResult = HResults.COR_E_DUPLICATEWAITOBJECT;
}
protected DuplicateWaitObjectException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/EntryPointNotFoundException.cs b/src/mscorlib/shared/System/EntryPointNotFoundException.cs
index 0b881cec05..e62ca0e11d 100644
--- a/src/mscorlib/shared/System/EntryPointNotFoundException.cs
+++ b/src/mscorlib/shared/System/EntryPointNotFoundException.cs
@@ -21,19 +21,19 @@ namespace System
public EntryPointNotFoundException()
: base(SR.Arg_EntryPointNotFoundException)
{
- HResult = __HResults.COR_E_ENTRYPOINTNOTFOUND;
+ HResult = HResults.COR_E_ENTRYPOINTNOTFOUND;
}
public EntryPointNotFoundException(String message)
: base(message)
{
- HResult = __HResults.COR_E_ENTRYPOINTNOTFOUND;
+ HResult = HResults.COR_E_ENTRYPOINTNOTFOUND;
}
public EntryPointNotFoundException(String message, Exception inner)
: base(message, inner)
{
- HResult = __HResults.COR_E_ENTRYPOINTNOTFOUND;
+ HResult = HResults.COR_E_ENTRYPOINTNOTFOUND;
}
protected EntryPointNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/ExecutionEngineException.cs b/src/mscorlib/shared/System/ExecutionEngineException.cs
index b89f6d9a8d..c33435875e 100644
--- a/src/mscorlib/shared/System/ExecutionEngineException.cs
+++ b/src/mscorlib/shared/System/ExecutionEngineException.cs
@@ -26,19 +26,19 @@ namespace System
public ExecutionEngineException()
: base(SR.Arg_ExecutionEngineException)
{
- HResult = __HResults.COR_E_EXECUTIONENGINE;
+ HResult = HResults.COR_E_EXECUTIONENGINE;
}
public ExecutionEngineException(String message)
: base(message)
{
- HResult = __HResults.COR_E_EXECUTIONENGINE;
+ HResult = HResults.COR_E_EXECUTIONENGINE;
}
public ExecutionEngineException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_EXECUTIONENGINE;
+ HResult = HResults.COR_E_EXECUTIONENGINE;
}
}
}
diff --git a/src/mscorlib/shared/System/FieldAccessException.cs b/src/mscorlib/shared/System/FieldAccessException.cs
index b56d749771..883bbd8bc2 100644
--- a/src/mscorlib/shared/System/FieldAccessException.cs
+++ b/src/mscorlib/shared/System/FieldAccessException.cs
@@ -18,19 +18,19 @@ namespace System
public FieldAccessException()
: base(SR.Arg_FieldAccessException)
{
- HResult = __HResults.COR_E_FIELDACCESS;
+ HResult = HResults.COR_E_FIELDACCESS;
}
public FieldAccessException(String message)
: base(message)
{
- HResult = __HResults.COR_E_FIELDACCESS;
+ HResult = HResults.COR_E_FIELDACCESS;
}
public FieldAccessException(String message, Exception inner)
: base(message, inner)
{
- HResult = __HResults.COR_E_FIELDACCESS;
+ HResult = HResults.COR_E_FIELDACCESS;
}
protected FieldAccessException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/FormatException.cs b/src/mscorlib/shared/System/FormatException.cs
index 9baaac2353..4af45cdd94 100644
--- a/src/mscorlib/shared/System/FormatException.cs
+++ b/src/mscorlib/shared/System/FormatException.cs
@@ -20,19 +20,19 @@ namespace System
public FormatException()
: base(SR.Arg_FormatException)
{
- HResult = __HResults.COR_E_FORMAT;
+ HResult = HResults.COR_E_FORMAT;
}
public FormatException(String message)
: base(message)
{
- HResult = __HResults.COR_E_FORMAT;
+ HResult = HResults.COR_E_FORMAT;
}
public FormatException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_FORMAT;
+ HResult = HResults.COR_E_FORMAT;
}
protected FormatException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/Globalization/DateTimeFormatInfo.cs b/src/mscorlib/shared/System/Globalization/DateTimeFormatInfo.cs
index 5d3239ebfc..9f8c072c93 100644
--- a/src/mscorlib/shared/System/Globalization/DateTimeFormatInfo.cs
+++ b/src/mscorlib/shared/System/Globalization/DateTimeFormatInfo.cs
@@ -31,7 +31,7 @@ namespace System.Globalization
// This is an internal flag.
//
// This flag is different from MonthNameStyles because this flag
- // can be expanded to accomodate parsing behaviors like CJK month names
+ // can be expanded to accommodate parsing behaviors like CJK month names
// or alternative month names, etc.
[Flags]
@@ -2645,7 +2645,7 @@ namespace System.Globalization
{
String str;
// We have to call public methods here to work with inherited DTFI.
- // Insert the month name first, so that they are at the front of abbrevaited
+ // Insert the month name first, so that they are at the front of abbreviated
// month names.
str = InvariantInfo.GetMonthName(i);
InsertHash(temp, str, TokenType.MonthToken, i);
@@ -2688,7 +2688,7 @@ namespace System.Globalization
String str;
//str = internalGetMonthName(i, MonthNameStyles.Regular, false);
// We have to call public methods here to work with inherited DTFI.
- // Insert the month name first, so that they are at the front of abbrevaited
+ // Insert the month name first, so that they are at the front of abbreviated
// month names.
str = GetMonthName(i);
if (str.Length > 0)
diff --git a/src/mscorlib/shared/System/Globalization/DateTimeParse.cs b/src/mscorlib/shared/System/Globalization/DateTimeParse.cs
index 910fbf2ff0..f821a95412 100644
--- a/src/mscorlib/shared/System/Globalization/DateTimeParse.cs
+++ b/src/mscorlib/shared/System/Globalization/DateTimeParse.cs
@@ -81,23 +81,23 @@ namespace System
{
if (s == null)
{
- result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, nameof(s));
+ result.SetFailure(ParseFailureKind.ArgumentNull, nameof(SR.ArgumentNull_String), null, nameof(s));
return false;
}
if (format == null)
{
- result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, nameof(format));
+ result.SetFailure(ParseFailureKind.ArgumentNull, nameof(SR.ArgumentNull_String), null, nameof(format));
return false;
}
if (s.Length == 0)
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
if (format.Length == 0)
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadFormatSpecifier", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadFormatSpecifier), null);
return false;
}
@@ -177,24 +177,24 @@ namespace System
{
if (s == null)
{
- result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, nameof(s));
+ result.SetFailure(ParseFailureKind.ArgumentNull, nameof(SR.ArgumentNull_String), null, nameof(s));
return false;
}
if (formats == null)
{
- result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, nameof(formats));
+ result.SetFailure(ParseFailureKind.ArgumentNull, nameof(SR.ArgumentNull_String), null, nameof(formats));
return false;
}
if (s.Length == 0)
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
if (formats.Length == 0)
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadFormatSpecifier", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadFormatSpecifier), null);
return false;
}
@@ -208,7 +208,7 @@ namespace System
{
if (formats[i] == null || formats[i].Length == 0)
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadFormatSpecifier", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadFormatSpecifier), null);
return false;
}
// Create a new result each time to ensure the runs are independent. Carry through
@@ -223,7 +223,7 @@ namespace System
return (true);
}
}
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return (false);
}
@@ -605,13 +605,13 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if ((result.flags & ParseFlags.TimeZoneUsed) != 0)
{
// Should not have two timezone offsets.
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
result.flags |= ParseFlags.TimeZoneUsed;
if (!ParseTimeZone(ref str, ref result.timeZoneOffset))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
}
@@ -657,7 +657,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
case TokenType.YearNumberToken:
if (raw.numCount == 3 || tokenValue == -1)
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
LexTraceExit("0010", dps);
return false;
}
@@ -724,7 +724,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
else
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
LexTraceExit("0030 (TM.AM/TM.PM Happened more than 1x)", dps);
}
break;
@@ -737,7 +737,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
case TokenType.SEP_Time:
if (!raw.hasSameDateAndTimeSeparators)
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
LexTraceExit("0040 (Invalid separator after number)", dps);
return false;
}
@@ -775,7 +775,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
break;
default:
// Invalid separator after number number.
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
LexTraceExit("0040 (Invalid separator after number)", dps);
return false;
}
@@ -785,7 +785,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
LexTraceExit("0050 (success)", dps);
return true;
}
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
LexTraceExit("0060", dps);
return false;
}
@@ -818,7 +818,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
else
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
break;
}
if (dps == DS.T_NNt || dps == DS.T_Nt)
@@ -873,7 +873,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
catch (ArgumentOutOfRangeException e)
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", e);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), e);
LexTraceExit("0075 (Calendar.ToFourDigitYear failed)", dps);
return false;
}
@@ -897,7 +897,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
break;
default:
// Invalid separator after number number.
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
LexTraceExit("0080", dps);
return false;
}
@@ -935,7 +935,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
goto default;
default:
// Invalid separator after number number.
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
LexTraceExit("0090", dps);
return false;
}
@@ -943,7 +943,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
else
{
// Invalid separator after number number.
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
LexTraceExit("0100", dps);
return false;
}
@@ -984,7 +984,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
break;
default:
// Invalid separator after number number.
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
LexTraceExit("0110", dps);
return false;
}
@@ -1001,7 +1001,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
else
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
LexTraceExit("0120 (DayOfWeek seen more than 1x)", dps);
return false;
}
@@ -1026,7 +1026,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
case TokenType.SEP_Time:
if (!raw.hasSameDateAndTimeSeparators)
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
LexTraceExit("0130 (Invalid separator after month name)", dps);
return false;
}
@@ -1052,7 +1052,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
break;
default:
//Invalid separator after month name
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
LexTraceExit("0130 (Invalid separator after month name)", dps);
return false;
}
@@ -1060,7 +1060,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
else
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
LexTraceExit("0140 (MonthToken seen more than 1x)", dps);
return false;
}
@@ -1073,7 +1073,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
else
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
LexTraceExit("0150 (EraToken seen when result.era already set)", dps);
return false;
}
@@ -1089,7 +1089,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
else
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
LexTraceExit("0160 (JapaneseEraToken seen when result.era already set)", dps);
return false;
}
@@ -1104,7 +1104,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
else
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
LexTraceExit("0170 (TEraToken seen when result.era already set)", dps);
return false;
}
@@ -1118,7 +1118,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if ((result.flags & ParseFlags.TimeZoneUsed) != 0)
{
// Should not have two timezone offsets.
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
LexTraceExit("0180 (seen GMT or Z more than 1x)", dps);
return false;
}
@@ -1142,7 +1142,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
else
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
LexTraceExit("0190 (AM/PM timeMark already set)", dps);
return false;
}
@@ -1150,7 +1150,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
case TokenType.UnknownToken:
if (Char.IsLetter(str.m_current))
{
- result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_UnknowDateTimeWord", str.Index);
+ result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_UnknowDateTimeWord), str.Index);
LexTraceExit("0200", dps);
return (false);
}
@@ -1180,7 +1180,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true;
}
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
LexTraceExit("0240", dps);
return false;
}
@@ -1573,7 +1573,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if ((result.flags & ParseFlags.HaveDate) != 0)
{
// Multiple dates in the input string
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
@@ -1585,7 +1585,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
int order;
if (!GetMonthDayOrder(dtfi.MonthDayPattern, dtfi, out order))
{
- result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.MonthDayPattern);
+ result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadDatePattern), dtfi.MonthDayPattern);
return false;
}
@@ -1606,7 +1606,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true;
}
}
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
@@ -1616,7 +1616,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if ((result.flags & ParseFlags.HaveDate) != 0)
{
// Multiple dates in the input string
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
@@ -1627,7 +1627,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
int order;
if (!GetYearMonthDayOrder(dtfi.ShortDatePattern, dtfi, out order))
{
- result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.ShortDatePattern);
+ result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadDatePattern), dtfi.ShortDatePattern);
return false;
}
int year;
@@ -1664,7 +1664,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true;
}
}
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
@@ -1673,7 +1673,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if ((result.flags & ParseFlags.HaveDate) != 0)
{
// Multiple dates in the input string
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
@@ -1692,7 +1692,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
int monthDayOrder;
if (!GetMonthDayOrder(dtfi.MonthDayPattern, dtfi, out monthDayOrder))
{
- result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.MonthDayPattern);
+ result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadDatePattern), dtfi.MonthDayPattern);
return false;
}
if (monthDayOrder == ORDER_DM)
@@ -1700,7 +1700,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
int yearMonthOrder;
if (!GetYearMonthOrder(dtfi.YearMonthPattern, dtfi, out yearMonthOrder))
{
- result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.YearMonthPattern);
+ result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadDatePattern), dtfi.YearMonthPattern);
return false;
}
if (yearMonthOrder == ORDER_MY)
@@ -1708,7 +1708,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
int year;
if (!TryAdjustYear(ref result, raw.GetNumber(0), out year) || !SetDateYMD(ref result, year, raw.month, 1))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
return true;
@@ -1718,7 +1718,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
GetDefaultYear(ref result, ref styles);
if (!SetDateYMD(ref result, result.Year, raw.month, raw.GetNumber(0)))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
return true;
@@ -1735,7 +1735,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
int monthDayOrder;
if (!GetMonthDayOrder(dtfi.MonthDayPattern, dtfi, out monthDayOrder))
{
- result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.MonthDayPattern);
+ result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadDatePattern), dtfi.MonthDayPattern);
return false;
}
result.Month = raw.month;
@@ -1747,7 +1747,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true;
}
}
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
@@ -1756,7 +1756,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if ((result.flags & ParseFlags.HaveDate) != 0)
{
// Multiple dates in the input string
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
@@ -1775,7 +1775,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
int monthDayOrder;
if (!GetMonthDayOrder(dtfi.MonthDayPattern, dtfi, out monthDayOrder))
{
- result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.MonthDayPattern);
+ result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadDatePattern), dtfi.MonthDayPattern);
return false;
}
if (monthDayOrder == ORDER_MD)
@@ -1783,7 +1783,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
int yearMonthOrder;
if (!GetYearMonthOrder(dtfi.YearMonthPattern, dtfi, out yearMonthOrder))
{
- result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.YearMonthPattern);
+ result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadDatePattern), dtfi.YearMonthPattern);
return false;
}
if (yearMonthOrder == ORDER_YM)
@@ -1791,7 +1791,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
int year;
if (!TryAdjustYear(ref result, raw.GetNumber(0), out year) || !SetDateYMD(ref result, year, raw.month, 1))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
return true;
@@ -1801,7 +1801,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
GetDefaultYear(ref result, ref styles);
if (!SetDateYMD(ref result, result.Year, raw.month, raw.GetNumber(0)))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
return true;
@@ -1812,7 +1812,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if ((result.flags & ParseFlags.HaveDate) != 0)
{
// Multiple dates in the input string
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
@@ -1822,7 +1822,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
int order;
if (!GetYearMonthDayOrder(dtfi.ShortDatePattern, dtfi, out order))
{
- result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.ShortDatePattern);
+ result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadDatePattern), dtfi.ShortDatePattern);
return false;
}
int year;
@@ -1873,7 +1873,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
}
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
@@ -1882,7 +1882,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if ((result.flags & ParseFlags.HaveDate) != 0)
{
// Multiple dates in the input string
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
@@ -1908,7 +1908,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true; // Year + MD
}
}
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
@@ -1917,7 +1917,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if ((result.flags & ParseFlags.HaveDate) != 0)
{
// Multiple dates in the input string
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
@@ -1927,7 +1927,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
int order;
if (!GetYearMonthDayOrder(dtfi.ShortDatePattern, dtfi, out order))
{
- result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.ShortDatePattern);
+ result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadDatePattern), dtfi.ShortDatePattern);
return false;
}
@@ -1947,7 +1947,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true; // DM + Year
}
}
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
@@ -1957,7 +1957,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if ((result.flags & ParseFlags.HaveDate) != 0)
{
// Multiple dates in the input string
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
@@ -1966,7 +1966,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
result.flags |= ParseFlags.HaveDate;
return true;
}
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
@@ -1975,7 +1975,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if ((result.flags & ParseFlags.HaveDate) != 0)
{
// Multiple dates in the input string
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
@@ -1984,7 +1984,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
result.flags |= ParseFlags.HaveDate;
return true;
}
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
@@ -1993,7 +1993,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if ((result.flags & ParseFlags.HaveDate) != 0)
{
// Multiple dates in the input string
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
@@ -2002,7 +2002,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
result.flags |= ParseFlags.HaveDate;
return true;
}
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
@@ -2065,7 +2065,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if ((result.flags & ParseFlags.HaveTime) != 0)
{
// Multiple times in the input string
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
//
@@ -2073,7 +2073,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
if (raw.timeMark == TM.NotSet)
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
result.Hour = raw.GetNumber(0);
@@ -2087,7 +2087,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if ((result.flags & ParseFlags.HaveTime) != 0)
{
// Multiple times in the input string
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
@@ -2102,7 +2102,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if ((result.flags & ParseFlags.HaveTime) != 0)
{
// Multiple times in the input string
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
Debug.Assert(raw.numCount >= 3, "raw.numCount >= 3");
@@ -2120,7 +2120,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
if (raw.numCount != 1 || result.Day != -1)
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
result.Day = raw.GetNumber(0);
@@ -2132,19 +2132,19 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if (result.Month == -1)
{
//Should have a month suffix
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
if (result.Year != -1)
{
// Aleady has a year suffix
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
if (!TryAdjustYear(ref result, raw.GetNumber(0), out result.Year))
{
// the year value is out of range
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
result.Day = 1;
@@ -2174,7 +2174,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
int order;
if (!GetYearMonthDayOrder(dtfi.ShortDatePattern, dtfi, out order))
{
- result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.ShortDatePattern);
+ result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadDatePattern), dtfi.ShortDatePattern);
return false;
}
int year;
@@ -2194,7 +2194,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
}
}
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
@@ -2275,7 +2275,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
raw.year = raw.GetNumber(1);
if (!dtfi.YearMonthAdjustment(ref raw.year, ref raw.month, true))
{
- result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null);
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar), null);
return false;
}
if (!GetDayOfMNN(ref result, ref raw, dtfi))
@@ -2287,7 +2287,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// Deal with the default long/short date format when the year number is NOT ambigous (i.e. year >= 100).
if (!dtfi.YearMonthAdjustment(ref raw.year, ref raw.month, true))
{
- result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null);
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar), null);
return false;
}
if (!GetDayOfYMN(ref result, ref raw, dtfi))
@@ -2295,13 +2295,30 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return false;
}
break;
+ case DS.DX_NNY:
+ // When formatting, we only format up to the hundred digit of the Hebrew year, although Hebrew year is now over 5000.
+ // E.g. if the year is 5763, we only format as 763. so we do the reverse when parsing.
+ if (raw.year < 1000)
+ {
+ raw.year += 5000;
+ }
+ if (!GetDayOfNNY(ref result, ref raw, dtfi))
+ {
+ return false;
+ }
+ if (!dtfi.YearMonthAdjustment(ref result.Year, ref raw.month, true))
+ {
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar), null);
+ return false;
+ }
+ break;
case DS.DX_NM:
case DS.DX_MN:
// Deal with Month/Day pattern.
GetDefaultYear(ref result, ref styles);
if (!dtfi.YearMonthAdjustment(ref result.Year, ref raw.month, true))
{
- result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null);
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar), null);
return false;
}
if (!GetHebrewDayOfNM(ref result, ref raw, dtfi))
@@ -2313,7 +2330,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// Deal with Year/Month pattern.
if (!dtfi.YearMonthAdjustment(ref raw.year, ref raw.month, true))
{
- result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null);
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar), null);
return false;
}
if (!GetDayOfYM(ref result, ref raw, dtfi))
@@ -2341,7 +2358,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
break;
default:
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
if (dps > DS.ERROR)
@@ -2505,12 +2522,12 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
if (s == null)
{
- result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, nameof(s));
+ result.SetFailure(ParseFailureKind.ArgumentNull, nameof(SR.ArgumentNull_String), null, nameof(s));
return false;
}
if (s.Length == 0)
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
@@ -2579,7 +2596,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
if (!ProcessDateTimeSuffix(ref result, ref raw, ref dtok))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
TPTraceExit("0010", dps);
return false;
}
@@ -2598,7 +2615,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
else
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
TPTraceExit("0030", dps);
return false;
}
@@ -2643,7 +2660,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if (dps == DS.ERROR)
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
TPTraceExit("0040 (invalid state transition)", dps);
return false;
}
@@ -2679,7 +2696,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if (!reachTerminalState)
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
TPTraceExit("0070 (did not reach terminal state)", dps);
return false;
}
@@ -2687,7 +2704,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
AdjustTimeMark(dtfi, ref raw);
if (!AdjustHour(ref result.Hour, raw.timeMark))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
TPTraceExit("0080 (AdjustHour)", dps);
return false;
}
@@ -2708,7 +2725,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if (!result.calendar.TryToDateTime(result.Year, result.Month, result.Day,
result.Hour, result.Minute, result.Second, 0, result.era, out time))
{
- result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null);
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar), null);
TPTraceExit("0100 (result.calendar.TryToDateTime)", dps);
return false;
}
@@ -2728,7 +2745,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
if (raw.dayOfWeek != (int)result.calendar.GetDayOfWeek(time))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDayOfWeek", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDayOfWeek), null);
TPTraceExit("0110 (dayOfWeek check)", dps);
return false;
}
@@ -2762,7 +2779,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// the DateTime offset must be within +- 14:00 hours.
if (offsetTicks < DateTimeOffset.MinOffset || offsetTicks > DateTimeOffset.MaxOffset)
{
- result.SetFailure(ParseFailureKind.Format, "Format_OffsetOutOfRange", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_OffsetOutOfRange), null);
return false;
}
}
@@ -2853,14 +2870,14 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// of a DateTime instance.
if (utcTicks < DateTime.MinTicks || utcTicks > DateTime.MaxTicks)
{
- result.SetFailure(ParseFailureKind.Format, "Format_UTCOutOfRange", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_UTCOutOfRange), null);
return false;
}
// the offset must be within +- 14:00 hours.
if (offsetTicks < DateTimeOffset.MinOffset || offsetTicks > DateTimeOffset.MaxOffset)
{
- result.SetFailure(ParseFailureKind.Format, "Format_OffsetOutOfRange", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_OffsetOutOfRange), null);
return false;
}
@@ -2903,7 +2920,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if (resultTicks < DateTime.MinTicks || resultTicks > DateTime.MaxTicks)
{
- result.SetFailure(ParseFailureKind.Format, "Format_DateOutOfRange", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_DateOutOfRange), null);
return false;
}
result.parsedDate = new DateTime(resultTicks, DateTimeKind.Utc);
@@ -2960,7 +2977,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if (resultTicks < DateTime.MinTicks || resultTicks > DateTime.MaxTicks)
{
result.parsedDate = DateTime.MinValue;
- result.SetFailure(ParseFailureKind.Format, "Format_DateOutOfRange", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_DateOutOfRange), null);
return false;
}
result.parsedDate = new DateTime(resultTicks, DateTimeKind.Local, isAmbiguousLocalDst);
@@ -2984,19 +3001,19 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
str.SkipWhiteSpaces();
if (!ParseDigits(ref str, 2, out hour))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
str.SkipWhiteSpaces();
if (!str.Match(':'))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
str.SkipWhiteSpaces();
if (!ParseDigits(ref str, 2, out minute))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
str.SkipWhiteSpaces();
@@ -3005,14 +3022,14 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
str.SkipWhiteSpaces();
if (!ParseDigits(ref str, 2, out second))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
if (str.Match('.'))
{
if (!ParseFraction(ref str, out partSecond))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
str.Index--;
@@ -3027,7 +3044,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
result.flags |= ParseFlags.TimeZoneUsed;
if (!ParseTimeZone(ref str, ref result.timeZoneOffset))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
}
@@ -3046,7 +3063,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
if (!VerifyValidPunctuation(ref str))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
str.SkipWhiteSpaces();
@@ -3055,14 +3072,14 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
if (!VerifyValidPunctuation(ref str))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
}
if (str.GetNext())
{
// If this is true, there were non-white space characters remaining in the DateTime
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
}
@@ -3072,7 +3089,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if (!calendar.TryToDateTime(raw.year, raw.GetNumber(0), raw.GetNumber(1),
hour, minute, second, 0, result.era, out time))
{
- result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null);
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar), null);
return false;
}
@@ -3658,7 +3675,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
if (newValue != currentValue)
{
- result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", patternChar);
+ result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_RepeatDateTimePattern), patternChar);
return (false);
}
}
@@ -3702,7 +3719,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if (((result.Month != -1) || (result.Day != -1))
&& ((result.Year == -1 || ((result.flags & ParseFlags.YearDefault) != 0)) && (result.flags & ParseFlags.TimeZoneUsed) != 0))
{
- result.SetFailure(ParseFailureKind.Format, "Format_MissingIncompleteDate", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_MissingIncompleteDate), null);
return false;
}
}
@@ -3885,7 +3902,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
if (!parseResult)
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return (false);
}
if (!CheckNewValue(ref result.Year, tempYear, ch, ref result))
@@ -3902,7 +3919,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if (!parseInfo.fCustomNumberParser ||
!parseInfo.parseNumberDelegate(ref str, tokenLen, out tempMonth))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return (false);
}
}
@@ -3913,7 +3930,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
if (!MatchAbbreviatedMonthName(ref str, dtfi, ref tempMonth))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return (false);
}
}
@@ -3921,7 +3938,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
if (!MatchMonthName(ref str, dtfi, ref tempMonth))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return (false);
}
}
@@ -3944,7 +3961,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if (!parseInfo.fCustomNumberParser ||
!parseInfo.parseNumberDelegate(ref str, tokenLen, out tempDay))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return (false);
}
}
@@ -3960,7 +3977,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// "ddd"
if (!MatchAbbreviatedDayName(ref str, dtfi, ref tempDayOfWeek))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return (false);
}
}
@@ -3969,7 +3986,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// "dddd*"
if (!MatchDayName(ref str, dtfi, ref tempDayOfWeek))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return (false);
}
}
@@ -3984,7 +4001,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// Put the era value in result.era.
if (!MatchEraName(ref str, dtfi, ref result.era))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return (false);
}
break;
@@ -3993,7 +4010,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
tokenLen = format.GetRepeatCount();
if (!ParseDigits(ref str, (tokenLen < 2 ? 1 : 2), out tempHour))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return (false);
}
if (!CheckNewValue(ref result.Hour, tempHour, ch, ref result))
@@ -4005,7 +4022,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
tokenLen = format.GetRepeatCount();
if (!ParseDigits(ref str, (tokenLen < 2 ? 1 : 2), out tempHour))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return (false);
}
if (!CheckNewValue(ref result.Hour, tempHour, ch, ref result))
@@ -4017,7 +4034,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
tokenLen = format.GetRepeatCount();
if (!ParseDigits(ref str, (tokenLen < 2 ? 1 : 2), out tempMinute))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return (false);
}
if (!CheckNewValue(ref result.Minute, tempMinute, ch, ref result))
@@ -4029,7 +4046,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
tokenLen = format.GetRepeatCount();
if (!ParseDigits(ref str, (tokenLen < 2 ? 1 : 2), out tempSecond))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return (false);
}
if (!CheckNewValue(ref result.Second, tempSecond, ch, ref result))
@@ -4046,7 +4063,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
if (ch == 'f')
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return (false);
}
}
@@ -4058,14 +4075,14 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
if (tempFraction != result.fraction)
{
- result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", ch);
+ result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_RepeatDateTimePattern), ch);
return (false);
}
}
}
else
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return (false);
}
break;
@@ -4076,7 +4093,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
if (!MatchAbbreviatedTimeMark(ref str, dtfi, ref tempTimeMark))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return (false);
}
}
@@ -4084,7 +4101,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
if (!MatchTimeMark(ref str, dtfi, ref tempTimeMark))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return (false);
}
}
@@ -4097,7 +4114,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
if (parseInfo.timeMark != tempTimeMark)
{
- result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", ch);
+ result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_RepeatDateTimePattern), ch);
return (false);
}
}
@@ -4109,12 +4126,12 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
TimeSpan tempTimeZoneOffset = new TimeSpan(0);
if (!ParseTimeZoneOffset(ref str, tokenLen, ref tempTimeZoneOffset))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return (false);
}
if ((result.flags & ParseFlags.TimeZoneUsed) != 0 && tempTimeZoneOffset != result.timeZoneOffset)
{
- result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", 'z');
+ result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_RepeatDateTimePattern), 'z');
return (false);
}
result.timeZoneOffset = tempTimeZoneOffset;
@@ -4124,7 +4141,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
case 'Z':
if ((result.flags & ParseFlags.TimeZoneUsed) != 0 && result.timeZoneOffset != TimeSpan.Zero)
{
- result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", 'Z');
+ result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_RepeatDateTimePattern), 'Z');
return (false);
}
@@ -4139,7 +4156,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
str.Index++;
if (!GetTimeZoneName(ref str))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
str.Index--;
@@ -4150,7 +4167,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
if ((result.flags & ParseFlags.TimeZoneUsed) != 0 && result.timeZoneOffset != TimeSpan.Zero)
{
- result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", 'K');
+ result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_RepeatDateTimePattern), 'K');
return (false);
}
@@ -4164,12 +4181,12 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
TimeSpan tempTimeZoneOffset = new TimeSpan(0);
if (!ParseTimeZoneOffset(ref str, 3, ref tempTimeZoneOffset))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return (false);
}
if ((result.flags & ParseFlags.TimeZoneUsed) != 0 && tempTimeZoneOffset != result.timeZoneOffset)
{
- result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", 'K');
+ result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_RepeatDateTimePattern), 'K');
return (false);
}
result.timeZoneOffset = tempTimeZoneOffset;
@@ -4184,7 +4201,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
!str.Match(dtfi.TimeSeparator))
{
// A time separator is expected.
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
break;
@@ -4195,7 +4212,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
!str.Match(dtfi.DateSeparator))
{
// A date separator is expected.
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
break;
@@ -4205,7 +4222,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// Use ParseQuoteString so that we can handle escape characters within the quoted string.
if (!TryParseQuoteString(format.Value, format.Index, enquotedString, out tokenLen))
{
- result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadQuote", ch);
+ result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadQuote), ch);
return (false);
}
format.Index += tokenLen - 1;
@@ -4224,7 +4241,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
else if (!str.Match(quotedStr[i]))
{
// Can not find the matching quoted string.
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
}
@@ -4255,7 +4272,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// Make sure the next character is not a '%' again.
if (format.Index >= format.Value.Length - 1 || format.Value[format.Index + 1] == '%')
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadFormatSpecifier", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadFormatSpecifier), null);
return false;
}
break;
@@ -4268,13 +4285,13 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if (!str.Match(format.GetChar()))
{
// Can not find a match for the escaped character.
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
}
else
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadFormatSpecifier", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadFormatSpecifier), null);
return false;
}
break;
@@ -4291,7 +4308,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
break;
}
}
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
break;
@@ -4326,7 +4343,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
}
}
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
// Found a macth.
@@ -4343,14 +4360,14 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
result.timeZoneOffset = TimeSpan.Zero;
if (!str.Match(GMTName))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
}
else if (!str.Match(ch))
{
// ch is expected.
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
}
@@ -4461,7 +4478,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if (((result.flags & ParseFlags.CaptureOffset) != 0) && formatParam[0] == 'U')
{
// The 'U' format is not allowed for DateTimeOffset
- result.SetFailure(ParseFailureKind.Format, "Format_BadFormatSpecifier", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadFormatSpecifier), null);
return false;
}
formatParam = ExpandPredefinedFormat(formatParam, ref dtfi, ref parseInfo, ref result);
@@ -4518,7 +4535,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if (str.Index < str.Value.Length - 1)
{
// There are still remaining character in str.
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
@@ -4527,7 +4544,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// A two digit year value is expected. Check if the parsed year value is valid.
if (result.Year >= 100)
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
try
@@ -4536,7 +4553,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
catch (ArgumentOutOfRangeException e)
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", e);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), e);
return false;
}
}
@@ -4555,7 +4572,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if (result.Hour > 12)
{
// AM/PM is used, but the value for HH is too big.
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
if (parseInfo.timeMark == TM.AM)
@@ -4579,7 +4596,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if ((parseInfo.timeMark == TM.AM && result.Hour >= 12)
|| (parseInfo.timeMark == TM.PM && result.Hour < 12))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
return false;
}
}
@@ -4596,14 +4613,14 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
if (!dtfi.YearMonthAdjustment(ref result.Year, ref result.Month, ((result.flags & ParseFlags.ParsedMonthName) != 0)))
{
- result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null);
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar), null);
return false;
}
}
if (!parseInfo.calendar.TryToDateTime(result.Year, result.Month, result.Day,
result.Hour, result.Minute, result.Second, 0, result.era, out result.parsedDate))
{
- result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null);
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar), null);
return false;
}
if (result.fraction > 0)
@@ -4623,7 +4640,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
if (parseInfo.dayOfWeek != (int)parseInfo.calendar.GetDayOfWeek(result.parsedDate))
{
- result.SetFailure(ParseFailureKind.Format, "Format_BadDayOfWeek", null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDayOfWeek), null);
return false;
}
}
diff --git a/src/mscorlib/shared/System/Globalization/EastAsianLunisolarCalendar.cs b/src/mscorlib/shared/System/Globalization/EastAsianLunisolarCalendar.cs
index 0697b602db..383e0cd17c 100644
--- a/src/mscorlib/shared/System/Globalization/EastAsianLunisolarCalendar.cs
+++ b/src/mscorlib/shared/System/Globalization/EastAsianLunisolarCalendar.cs
@@ -67,7 +67,7 @@ namespace System.Globalization
return ((sexagenaryYear - 1) % 10) + 1;
}
- // Return the Terrestial Branch from the the 60-year cycle.
+ // Return the Terrestial Branch from the 60-year cycle.
// The returned value is from 1 ~ 12.
//
diff --git a/src/mscorlib/shared/System/Globalization/HijriCalendar.Win32.cs b/src/mscorlib/shared/System/Globalization/HijriCalendar.Win32.cs
index 869b809bff..09b1f20c48 100644
--- a/src/mscorlib/shared/System/Globalization/HijriCalendar.Win32.cs
+++ b/src/mscorlib/shared/System/Globalization/HijriCalendar.Win32.cs
@@ -45,7 +45,6 @@ namespace System.Globalization
try
{
// Open in read-only mode.
- // Use InternalOpenSubKey so that we avoid the security check.
key = RegistryKey.GetBaseKey(RegistryKey.HKEY_CURRENT_USER).OpenSubKey(InternationalRegKey, false);
}
//If this fails for any reason, we'll just return 0.
@@ -68,10 +67,9 @@ namespace System.Globalization
hijriAdvance = -1;
else
{
- str = str.Substring(HijriAdvanceRegKeyEntry.Length);
try
{
- int advance = Int32.Parse(str.ToString(), CultureInfo.InvariantCulture);
+ int advance = Int32.Parse(str.AsReadOnlySpan().Slice(HijriAdvanceRegKeyEntry.Length), provider:CultureInfo.InvariantCulture);
if ((advance >= MinAdvancedHijri) && (advance <= MaxAdvancedHijri))
{
hijriAdvance = advance;
diff --git a/src/mscorlib/shared/System/Globalization/HijriCalendar.cs b/src/mscorlib/shared/System/Globalization/HijriCalendar.cs
index 125248a685..59b354f534 100644
--- a/src/mscorlib/shared/System/Globalization/HijriCalendar.cs
+++ b/src/mscorlib/shared/System/Globalization/HijriCalendar.cs
@@ -187,7 +187,7 @@ namespace System.Globalization
set
{
- // NOTE: Check the value of Min/MaxAdavncedHijri with Arabic speakers to see if the assumption is good.
+ // NOTE: Check the value of Min/MaxAdvancedHijri with Arabic speakers to see if the assumption is good.
if (value < MinAdvancedHijri || value > MaxAdvancedHijri)
{
throw new ArgumentOutOfRangeException(
@@ -303,7 +303,7 @@ namespace System.Globalization
//
HijriYear = (int)(((NumDays - 227013) * 30) / 10631) + 1;
- long daysToHijriYear = DaysUpToHijriYear(HijriYear); // The absoulte date for HijriYear
+ long daysToHijriYear = DaysUpToHijriYear(HijriYear); // The absolute date for HijriYear
long daysOfHijriYear = GetDaysInYear(HijriYear, CurrentEra); // The number of days for (HijriYear+1) year.
if (NumDays < daysToHijriYear)
diff --git a/src/mscorlib/shared/System/Globalization/JapaneseCalendar.Win32.cs b/src/mscorlib/shared/System/Globalization/JapaneseCalendar.Win32.cs
index a83c4fad9e..94e0668de1 100644
--- a/src/mscorlib/shared/System/Globalization/JapaneseCalendar.Win32.cs
+++ b/src/mscorlib/shared/System/Globalization/JapaneseCalendar.Win32.cs
@@ -159,9 +159,10 @@ namespace System.Globalization
int month;
int day;
- if (!Int32.TryParse(value.Substring(0, 4), NumberStyles.None, NumberFormatInfo.InvariantInfo, out year) ||
- !Int32.TryParse(value.Substring(5, 2), NumberStyles.None, NumberFormatInfo.InvariantInfo, out month) ||
- !Int32.TryParse(value.Substring(8, 2), NumberStyles.None, NumberFormatInfo.InvariantInfo, out day))
+ ReadOnlySpan<char> valueSpan = value.AsReadOnlySpan();
+ if (!Int32.TryParse(valueSpan.Slice(0, 4), out year, style:NumberStyles.None, provider: NumberFormatInfo.InvariantInfo) ||
+ !Int32.TryParse(valueSpan.Slice(5, 2), out month, style:NumberStyles.None, provider: NumberFormatInfo.InvariantInfo) ||
+ !Int32.TryParse(valueSpan.Slice(8, 2), out day, style:NumberStyles.None, provider: NumberFormatInfo.InvariantInfo))
{
// Couldn't convert integer, fail
return null;
diff --git a/src/mscorlib/shared/System/Globalization/NumberFormatInfo.cs b/src/mscorlib/shared/System/Globalization/NumberFormatInfo.cs
index 9fea694cca..d7412bfcf3 100644
--- a/src/mscorlib/shared/System/Globalization/NumberFormatInfo.cs
+++ b/src/mscorlib/shared/System/Globalization/NumberFormatInfo.cs
@@ -238,35 +238,30 @@ namespace System.Globalization
public static NumberFormatInfo GetInstance(IFormatProvider formatProvider)
{
- // Fast case for a regular CultureInfo
- NumberFormatInfo info;
- CultureInfo cultureProvider = formatProvider as CultureInfo;
- if (cultureProvider != null && !cultureProvider._isInherited)
+ if (formatProvider != null)
{
- info = cultureProvider.numInfo;
- if (info != null)
+ // Fast case for a regular CultureInfo
+ NumberFormatInfo info;
+ CultureInfo cultureProvider = formatProvider as CultureInfo;
+ if (cultureProvider != null && !cultureProvider._isInherited)
{
- return info;
+ return cultureProvider.numInfo ?? cultureProvider.NumberFormat;
}
- else
+
+ // Fast case for an NFI;
+ info = formatProvider as NumberFormatInfo;
+ if (info != null)
{
- return cultureProvider.NumberFormat;
+ return info;
}
- }
- // Fast case for an NFI;
- info = formatProvider as NumberFormatInfo;
- if (info != null)
- {
- return info;
- }
- if (formatProvider != null)
- {
+
info = formatProvider.GetFormat(typeof(NumberFormatInfo)) as NumberFormatInfo;
if (info != null)
{
return info;
}
}
+
return CurrentInfo;
}
diff --git a/src/mscorlib/shared/System/Globalization/TimeSpanFormat.cs b/src/mscorlib/shared/System/Globalization/TimeSpanFormat.cs
new file mode 100644
index 0000000000..6801ea8e1b
--- /dev/null
+++ b/src/mscorlib/shared/System/Globalization/TimeSpanFormat.cs
@@ -0,0 +1,523 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Text;
+using System.Diagnostics;
+
+namespace System.Globalization
+{
+ internal static class TimeSpanFormat
+ {
+ private static unsafe void AppendNonNegativeInt32(StringBuilder sb, int n, int digits)
+ {
+ Debug.Assert(n >= 0);
+ uint value = (uint)n;
+
+ const int MaxUInt32Digits = 10;
+ char* buffer = stackalloc char[MaxUInt32Digits];
+
+ int index = 0;
+ do
+ {
+ uint div = value / 10;
+ buffer[index++] = (char)(value - (div * 10) + '0');
+ value = div;
+ }
+ while (value != 0);
+ Debug.Assert(index <= MaxUInt32Digits);
+
+ for (int i = digits - index; i > 0; --i) sb.Append('0');
+ for (int i = index - 1; i >= 0; --i) sb.Append(buffer[i]);
+ }
+
+ internal static readonly FormatLiterals PositiveInvariantFormatLiterals = TimeSpanFormat.FormatLiterals.InitInvariant(isNegative: false);
+ internal static readonly FormatLiterals NegativeInvariantFormatLiterals = TimeSpanFormat.FormatLiterals.InitInvariant(isNegative: true);
+
+ internal enum Pattern
+ {
+ None = 0,
+ Minimum = 1,
+ Full = 2,
+ }
+
+ /// <summary>Main method called from TimeSpan.ToString.</summary>
+ internal static string Format(TimeSpan value, string format, IFormatProvider formatProvider) =>
+ StringBuilderCache.GetStringAndRelease(FormatToBuilder(value, format, formatProvider));
+
+ /// <summary>Main method called from TimeSpan.TryFormat.</summary>
+ internal static bool TryFormat(TimeSpan value, Span<char> destination, out int charsWritten, string format, IFormatProvider formatProvider)
+ {
+ StringBuilder sb = FormatToBuilder(value, format, formatProvider);
+ if (sb.Length <= destination.Length)
+ {
+ charsWritten = sb.Length;
+ sb.CopyTo(0, destination, sb.Length);
+ StringBuilderCache.Release(sb);
+ return true;
+ }
+ else
+ {
+ StringBuilderCache.Release(sb);
+ charsWritten = 0;
+ return false;
+ }
+ }
+
+ private static StringBuilder FormatToBuilder(TimeSpan value, string format, IFormatProvider formatProvider)
+ {
+ if (format == null || format.Length == 0)
+ {
+ format = "c";
+ }
+
+ // Standard formats
+ if (format.Length == 1)
+ {
+ char f = format[0];
+ switch (f)
+ {
+ case 'c':
+ case 't':
+ case 'T':
+ return FormatStandard(
+ value,
+ isInvariant: true,
+ format: format,
+ pattern: Pattern.Minimum);
+
+ case 'g':
+ case 'G':
+ DateTimeFormatInfo dtfi = DateTimeFormatInfo.GetInstance(formatProvider);
+ return FormatStandard(
+ value,
+ isInvariant: false,
+ format: value.Ticks < 0 ? dtfi.FullTimeSpanNegativePattern : dtfi.FullTimeSpanPositivePattern,
+ pattern: f == 'g' ? Pattern.Minimum : Pattern.Full);
+
+ default:
+ throw new FormatException(SR.Format_InvalidString);
+ }
+ }
+
+ // Custom formats
+ return FormatCustomized(value, format, DateTimeFormatInfo.GetInstance(formatProvider));
+ }
+
+ /// <summary>Format the TimeSpan instance using the specified format.</summary>
+ private static StringBuilder FormatStandard(TimeSpan value, bool isInvariant, string format, Pattern pattern)
+ {
+ StringBuilder sb = StringBuilderCache.Acquire(InternalGlobalizationHelper.StringBuilderDefaultCapacity);
+ int day = (int)(value.Ticks / TimeSpan.TicksPerDay);
+ long time = value.Ticks % TimeSpan.TicksPerDay;
+
+ if (value.Ticks < 0)
+ {
+ day = -day;
+ time = -time;
+ }
+ int hours = (int)(time / TimeSpan.TicksPerHour % 24);
+ int minutes = (int)(time / TimeSpan.TicksPerMinute % 60);
+ int seconds = (int)(time / TimeSpan.TicksPerSecond % 60);
+ int fraction = (int)(time % TimeSpan.TicksPerSecond);
+
+ FormatLiterals literal;
+ if (isInvariant)
+ {
+ literal = value.Ticks < 0 ?
+ NegativeInvariantFormatLiterals :
+ PositiveInvariantFormatLiterals;
+ }
+ else
+ {
+ literal = new FormatLiterals();
+ literal.Init(format, pattern == Pattern.Full);
+ }
+
+ if (fraction != 0)
+ {
+ // truncate the partial second to the specified length
+ fraction = (int)(fraction / TimeSpanParse.Pow10(DateTimeFormat.MaxSecondsFractionDigits - literal.ff));
+ }
+
+ // Pattern.Full: [-]dd.hh:mm:ss.fffffff
+ // Pattern.Minimum: [-][d.]hh:mm:ss[.fffffff]
+
+ sb.Append(literal.Start); // [-]
+ if (pattern == Pattern.Full || day != 0)
+ {
+ sb.Append(day); // [dd]
+ sb.Append(literal.DayHourSep); // [.]
+ } //
+ AppendNonNegativeInt32(sb, hours, literal.hh); // hh
+ sb.Append(literal.HourMinuteSep); // :
+ AppendNonNegativeInt32(sb, minutes, literal.mm); // mm
+ sb.Append(literal.MinuteSecondSep); // :
+ AppendNonNegativeInt32(sb, seconds, literal.ss); // ss
+ if (!isInvariant && pattern == Pattern.Minimum)
+ {
+ int effectiveDigits = literal.ff;
+ while (effectiveDigits > 0)
+ {
+ if (fraction % 10 == 0)
+ {
+ fraction = fraction / 10;
+ effectiveDigits--;
+ }
+ else
+ {
+ break;
+ }
+ }
+ if (effectiveDigits > 0)
+ {
+ sb.Append(literal.SecondFractionSep); // [.FFFFFFF]
+ sb.Append((fraction).ToString(DateTimeFormat.fixedNumberFormats[effectiveDigits - 1], CultureInfo.InvariantCulture));
+ }
+ }
+ else if (pattern == Pattern.Full || fraction != 0)
+ {
+ sb.Append(literal.SecondFractionSep); // [.]
+ AppendNonNegativeInt32(sb, fraction, literal.ff); // [fffffff]
+ }
+ sb.Append(literal.End);
+
+ return sb;
+ }
+
+ /// <summary>Format the TimeSpan instance using the specified format.</summary>
+ private static StringBuilder FormatCustomized(TimeSpan value, string format, DateTimeFormatInfo dtfi)
+ {
+ Debug.Assert(dtfi != null);
+
+ int day = (int)(value.Ticks / TimeSpan.TicksPerDay);
+ long time = value.Ticks % TimeSpan.TicksPerDay;
+
+ if (value.Ticks < 0)
+ {
+ day = -day;
+ time = -time;
+ }
+ int hours = (int)(time / TimeSpan.TicksPerHour % 24);
+ int minutes = (int)(time / TimeSpan.TicksPerMinute % 60);
+ int seconds = (int)(time / TimeSpan.TicksPerSecond % 60);
+ int fraction = (int)(time % TimeSpan.TicksPerSecond);
+
+ long tmp = 0;
+ int i = 0;
+ int tokenLen;
+ StringBuilder result = StringBuilderCache.Acquire(InternalGlobalizationHelper.StringBuilderDefaultCapacity);
+
+ while (i < format.Length)
+ {
+ char ch = format[i];
+ int nextChar;
+ switch (ch)
+ {
+ case 'h':
+ tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
+ if (tokenLen > 2)
+ {
+ throw new FormatException(SR.Format_InvalidString);
+ }
+ DateTimeFormat.FormatDigits(result, hours, tokenLen);
+ break;
+ case 'm':
+ tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
+ if (tokenLen > 2)
+ {
+ throw new FormatException(SR.Format_InvalidString);
+ }
+ DateTimeFormat.FormatDigits(result, minutes, tokenLen);
+ break;
+ case 's':
+ tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
+ if (tokenLen > 2)
+ {
+ throw new FormatException(SR.Format_InvalidString);
+ }
+ DateTimeFormat.FormatDigits(result, seconds, tokenLen);
+ break;
+ case 'f':
+ //
+ // The fraction of a second in single-digit precision. The remaining digits are truncated.
+ //
+ tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
+ if (tokenLen > DateTimeFormat.MaxSecondsFractionDigits)
+ {
+ throw new FormatException(SR.Format_InvalidString);
+ }
+
+ tmp = fraction;
+ tmp /= TimeSpanParse.Pow10(DateTimeFormat.MaxSecondsFractionDigits - tokenLen);
+ result.Append((tmp).ToString(DateTimeFormat.fixedNumberFormats[tokenLen - 1], CultureInfo.InvariantCulture));
+ break;
+ case 'F':
+ //
+ // Displays the most significant digit of the seconds fraction. Nothing is displayed if the digit is zero.
+ //
+ tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
+ if (tokenLen > DateTimeFormat.MaxSecondsFractionDigits)
+ {
+ throw new FormatException(SR.Format_InvalidString);
+ }
+
+ tmp = fraction;
+ tmp /= TimeSpanParse.Pow10(DateTimeFormat.MaxSecondsFractionDigits - tokenLen);
+ int effectiveDigits = tokenLen;
+ while (effectiveDigits > 0)
+ {
+ if (tmp % 10 == 0)
+ {
+ tmp = tmp / 10;
+ effectiveDigits--;
+ }
+ else
+ {
+ break;
+ }
+ }
+ if (effectiveDigits > 0)
+ {
+ result.Append((tmp).ToString(DateTimeFormat.fixedNumberFormats[effectiveDigits - 1], CultureInfo.InvariantCulture));
+ }
+ break;
+ case 'd':
+ //
+ // tokenLen == 1 : Day as digits with no leading zero.
+ // tokenLen == 2+: Day as digits with leading zero for single-digit days.
+ //
+ tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
+ if (tokenLen > 8)
+ {
+ throw new FormatException(SR.Format_InvalidString);
+ }
+
+ DateTimeFormat.FormatDigits(result, day, tokenLen, true);
+ break;
+ case '\'':
+ case '\"':
+ tokenLen = DateTimeFormat.ParseQuoteString(format, i, result);
+ break;
+ case '%':
+ // Optional format character.
+ // For example, format string "%d" will print day
+ // Most of the cases, "%" can be ignored.
+ nextChar = DateTimeFormat.ParseNextChar(format, i);
+ // nextChar will be -1 if we already reach the end of the format string.
+ // Besides, we will not allow "%%" appear in the pattern.
+ if (nextChar >= 0 && nextChar != (int)'%')
+ {
+ result.Append(TimeSpanFormat.FormatCustomized(value, ((char)nextChar).ToString(), dtfi));
+ tokenLen = 2;
+ }
+ else
+ {
+ //
+ // This means that '%' is at the end of the format string or
+ // "%%" appears in the format string.
+ //
+ throw new FormatException(SR.Format_InvalidString);
+ }
+ break;
+ case '\\':
+ // Escaped character. Can be used to insert character into the format string.
+ // For example, "\d" will insert the character 'd' into the string.
+ //
+ nextChar = DateTimeFormat.ParseNextChar(format, i);
+ if (nextChar >= 0)
+ {
+ result.Append(((char)nextChar));
+ tokenLen = 2;
+ }
+ else
+ {
+ //
+ // This means that '\' is at the end of the formatting string.
+ //
+ throw new FormatException(SR.Format_InvalidString);
+ }
+ break;
+ default:
+ throw new FormatException(SR.Format_InvalidString);
+ }
+ i += tokenLen;
+ }
+ return result;
+ }
+
+ internal struct FormatLiterals
+ {
+ internal string AppCompatLiteral;
+ internal int dd;
+ internal int hh;
+ internal int mm;
+ internal int ss;
+ internal int ff;
+
+ private string[] _literals;
+
+ internal string Start => _literals[0];
+ internal string DayHourSep => _literals[1];
+ internal string HourMinuteSep => _literals[2];
+ internal string MinuteSecondSep => _literals[3];
+ internal string SecondFractionSep => _literals[4];
+ internal string End => _literals[5];
+
+ /* factory method for static invariant FormatLiterals */
+ internal static FormatLiterals InitInvariant(bool isNegative)
+ {
+ FormatLiterals x = new FormatLiterals();
+ x._literals = new string[6];
+ x._literals[0] = isNegative ? "-" : string.Empty;
+ x._literals[1] = ".";
+ x._literals[2] = ":";
+ x._literals[3] = ":";
+ x._literals[4] = ".";
+ x._literals[5] = string.Empty;
+ x.AppCompatLiteral = ":."; // MinuteSecondSep+SecondFractionSep;
+ x.dd = 2;
+ x.hh = 2;
+ x.mm = 2;
+ x.ss = 2;
+ x.ff = DateTimeFormat.MaxSecondsFractionDigits;
+ return x;
+ }
+
+ // For the "v1" TimeSpan localized patterns, the data is simply literal field separators with
+ // the constants guaranteed to include DHMSF ordered greatest to least significant.
+ // Once the data becomes more complex than this we will need to write a proper tokenizer for
+ // parsing and formatting
+ internal void Init(string format, bool useInvariantFieldLengths)
+ {
+ dd = hh = mm = ss = ff = 0;
+ _literals = new string[6];
+ for (int i = 0; i < _literals.Length; i++)
+ {
+ _literals[i] = string.Empty;
+ }
+
+ StringBuilder sb = StringBuilderCache.Acquire(InternalGlobalizationHelper.StringBuilderDefaultCapacity);
+ bool inQuote = false;
+ char quote = '\'';
+ int field = 0;
+
+ for (int i = 0; i < format.Length; i++)
+ {
+ switch (format[i])
+ {
+ case '\'':
+ case '\"':
+ if (inQuote && (quote == format[i]))
+ {
+ /* we were in a quote and found a matching exit quote, so we are outside a quote now */
+ if (field >= 0 && field <= 5)
+ {
+ _literals[field] = sb.ToString();
+ sb.Length = 0;
+ inQuote = false;
+ }
+ else
+ {
+ Debug.Fail($"Unexpected field value: {field}");
+ return; // how did we get here?
+ }
+ }
+ else if (!inQuote)
+ {
+ /* we are at the start of a new quote block */
+ quote = format[i];
+ inQuote = true;
+ }
+ else
+ {
+ /* we were in a quote and saw the other type of quote character, so we are still in a quote */
+ }
+ break;
+ case '%':
+ Debug.Fail("Unexpected special token '%', Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
+ goto default;
+ case '\\':
+ if (!inQuote)
+ {
+ i++; /* skip next character that is escaped by this backslash or percent sign */
+ break;
+ }
+ goto default;
+ case 'd':
+ if (!inQuote)
+ {
+ Debug.Assert((field == 0 && sb.Length == 0) || field == 1, "field == 0 || field == 1, Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
+ field = 1; // DayHourSep
+ dd++;
+ }
+ break;
+ case 'h':
+ if (!inQuote)
+ {
+ Debug.Assert((field == 1 && sb.Length == 0) || field == 2, "field == 1 || field == 2, Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
+ field = 2; // HourMinuteSep
+ hh++;
+ }
+ break;
+ case 'm':
+ if (!inQuote)
+ {
+ Debug.Assert((field == 2 && sb.Length == 0) || field == 3, "field == 2 || field == 3, Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
+ field = 3; // MinuteSecondSep
+ mm++;
+ }
+ break;
+ case 's':
+ if (!inQuote)
+ {
+ Debug.Assert((field == 3 && sb.Length == 0) || field == 4, "field == 3 || field == 4, Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
+ field = 4; // SecondFractionSep
+ ss++;
+ }
+ break;
+ case 'f':
+ case 'F':
+ if (!inQuote)
+ {
+ Debug.Assert((field == 4 && sb.Length == 0) || field == 5, "field == 4 || field == 5, Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
+ field = 5; // End
+ ff++;
+ }
+ break;
+ default:
+ sb.Append(format[i]);
+ break;
+ }
+ }
+
+ Debug.Assert(field == 5);
+ AppCompatLiteral = MinuteSecondSep + SecondFractionSep;
+
+ Debug.Assert(0 < dd && dd < 3, "0 < dd && dd < 3, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
+ Debug.Assert(0 < hh && hh < 3, "0 < hh && hh < 3, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
+ Debug.Assert(0 < mm && mm < 3, "0 < mm && mm < 3, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
+ Debug.Assert(0 < ss && ss < 3, "0 < ss && ss < 3, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
+ Debug.Assert(0 < ff && ff < 8, "0 < ff && ff < 8, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
+
+ if (useInvariantFieldLengths)
+ {
+ dd = 2;
+ hh = 2;
+ mm = 2;
+ ss = 2;
+ ff = DateTimeFormat.MaxSecondsFractionDigits;
+ }
+ else
+ {
+ if (dd < 1 || dd > 2) dd = 2; // The DTFI property has a problem. let's try to make the best of the situation.
+ if (hh < 1 || hh > 2) hh = 2;
+ if (mm < 1 || mm > 2) mm = 2;
+ if (ss < 1 || ss > 2) ss = 2;
+ if (ff < 1 || ff > 7) ff = 7;
+ }
+ StringBuilderCache.Release(sb);
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/Globalization/TimeSpanParse.cs b/src/mscorlib/shared/System/Globalization/TimeSpanParse.cs
new file mode 100644
index 0000000000..f8443a1ea6
--- /dev/null
+++ b/src/mscorlib/shared/System/Globalization/TimeSpanParse.cs
@@ -0,0 +1,1675 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////
+//
+// Purpose: Used by TimeSpan to parse a time interval string.
+//
+// Standard Format:
+// -=-=-=-=-=-=-=-
+// "c": Constant format. [-][d'.']hh':'mm':'ss['.'fffffff]
+// Not culture sensitive. Default format (and null/empty format string) map to this format.
+//
+// "g": General format, short: [-][d':']h':'mm':'ss'.'FFFFFFF
+// Only print what's needed. Localized (if you want Invariant, pass in Invariant).
+// The fractional seconds separator is localized, equal to the culture's DecimalSeparator.
+//
+// "G": General format, long: [-]d':'hh':'mm':'ss'.'fffffff
+// Always print days and 7 fractional digits. Localized (if you want Invariant, pass in Invariant).
+// The fractional seconds separator is localized, equal to the culture's DecimalSeparator.
+//
+// * "TryParseTimeSpan" is the main method for Parse/TryParse
+//
+// - TimeSpanTokenizer.GetNextToken() is used to split the input string into number and literal tokens.
+// - TimeSpanRawInfo.ProcessToken() adds the next token into the parsing intermediary state structure
+// - ProcessTerminalState() uses the fully initialized TimeSpanRawInfo to find a legal parse match.
+// The terminal states are attempted as follows:
+// foreach (+InvariantPattern, -InvariantPattern, +LocalizedPattern, -LocalizedPattern) try
+// 1 number => d
+// 2 numbers => h:m
+// 3 numbers => h:m:s | d.h:m | h:m:.f
+// 4 numbers => h:m:s.f | d.h:m:s | d.h:m:.f
+// 5 numbers => d.h:m:s.f
+//
+// Custom Format:
+// -=-=-=-=-=-=-=
+//
+// * "TryParseExactTimeSpan" is the main method for ParseExact/TryParseExact methods
+// * "TryParseExactMultipleTimeSpan" is the main method for ParseExact/TryparseExact
+// methods that take a string[] of formats
+//
+// - For single-letter formats "TryParseTimeSpan" is called (see above)
+// - For multi-letter formats "TryParseByFormat" is called
+// - TryParseByFormat uses helper methods (ParseExactLiteral, ParseExactDigits, etc)
+// which drive the underlying TimeSpanTokenizer. However, unlike standard formatting which
+// operates on whole-tokens, ParseExact operates at the character-level. As such,
+// TimeSpanTokenizer.NextChar and TimeSpanTokenizer.BackOne() are called directly.
+//
+////////////////////////////////////////////////////////////////////////////
+
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Text;
+
+namespace System.Globalization
+{
+ internal static class TimeSpanParse
+ {
+ private const int MaxFractionDigits = 7;
+ private const int MaxDays = 10675199;
+ private const int MaxHours = 23;
+ private const int MaxMinutes = 59;
+ private const int MaxSeconds = 59;
+ private const int MaxFraction = 9999999;
+
+ private enum ParseFailureKind : byte
+ {
+ None = 0,
+ ArgumentNull = 1,
+ Format = 2,
+ FormatWithParameter = 3,
+ Overflow = 4,
+ }
+
+ [Flags]
+ private enum TimeSpanStandardStyles : byte
+ {
+ // Standard Format Styles
+ None = 0x00000000,
+ Invariant = 0x00000001, //Allow Invariant Culture
+ Localized = 0x00000002, //Allow Localized Culture
+ RequireFull = 0x00000004, //Require the input to be in DHMSF format
+ Any = Invariant | Localized,
+ }
+
+ // TimeSpan Token Types
+ private enum TTT : byte
+ {
+ None = 0, // None of the TimeSpanToken fields are set
+ End = 1, // '\0'
+ Num = 2, // Number
+ Sep = 3, // literal
+ NumOverflow = 4, // Number that overflowed
+ }
+
+ [IsByRefLike]
+ private struct TimeSpanToken
+ {
+ internal TTT _ttt;
+ internal int _num; // Store the number that we are parsing (if any)
+ internal int _zeroes; // Store the number of leading zeroes (if any)
+ internal ReadOnlySpan<char> _sep; // Store the literal that we are parsing (if any)
+
+ public TimeSpanToken(TTT type) : this(type, 0, 0, default(ReadOnlySpan<char>)) { }
+
+ public TimeSpanToken(int number) : this(TTT.Num, number, 0, default(ReadOnlySpan<char>)) { }
+
+ public TimeSpanToken(int number, int leadingZeroes) : this(TTT.Num, number, leadingZeroes, default(ReadOnlySpan<char>)) { }
+
+ public TimeSpanToken(TTT type, int number, int leadingZeroes, ReadOnlySpan<char> separator)
+ {
+ _ttt = type;
+ _num = number;
+ _zeroes = leadingZeroes;
+ _sep = separator;
+ }
+
+ public bool IsInvalidFraction()
+ {
+ Debug.Assert(_ttt == TTT.Num);
+ Debug.Assert(_num > -1);
+
+ if (_num > MaxFraction || _zeroes > MaxFractionDigits)
+ return true;
+
+ if (_num == 0 || _zeroes == 0)
+ return false;
+
+ // num > 0 && zeroes > 0 && num <= maxValue && zeroes <= maxPrecision
+ return _num >= MaxFraction / Pow10(_zeroes - 1);
+ }
+ }
+
+ [IsByRefLike]
+ private struct TimeSpanTokenizer
+ {
+ private ReadOnlySpan<char> _value;
+ private int _pos;
+
+ internal TimeSpanTokenizer(ReadOnlySpan<char> input) : this(input, 0) { }
+
+ internal TimeSpanTokenizer(ReadOnlySpan<char> input, int startPosition)
+ {
+ _value = input;
+ _pos = startPosition;
+ }
+
+ /// <summary>Returns the next token in the input string</summary>
+ /// <remarks>Used by the parsing routines that operate on standard-formats.</remarks>
+ internal TimeSpanToken GetNextToken()
+ {
+ // Get the position of the next character to be processed. If there is no
+ // next character, we're at the end.
+ int pos = _pos;
+ Debug.Assert(pos > -1);
+ if (pos >= _value.Length)
+ {
+ return new TimeSpanToken(TTT.End);
+ }
+
+ // Now retrieve that character. If it's a digit, we're processing a number.
+ int num = _value[pos] - '0';
+ if ((uint)num <= 9)
+ {
+ int zeroes = 0;
+ if (num == 0)
+ {
+ // Read all leading zeroes.
+ zeroes = 1;
+ while (true)
+ {
+ int digit;
+ if (++_pos >= _value.Length || (uint)(digit = _value[_pos] - '0') > 9)
+ {
+ return new TimeSpanToken(TTT.Num, 0, zeroes, default(ReadOnlySpan<char>));
+ }
+
+ if (digit == 0)
+ {
+ zeroes++;
+ continue;
+ }
+
+ num = digit;
+ break;
+ }
+ }
+
+ // Continue to read as long as we're reading digits.
+ while (++_pos < _value.Length)
+ {
+ int digit = _value[_pos] - '0';
+ if ((uint)digit > 9)
+ {
+ break;
+ }
+
+ num = num * 10 + digit;
+ if ((num & 0xF0000000) != 0)
+ {
+ return new TimeSpanToken(TTT.NumOverflow);
+ }
+ }
+
+ return new TimeSpanToken(TTT.Num, num, zeroes, default(ReadOnlySpan<char>));
+ }
+
+ // Otherwise, we're processing a separator, and we've already processed the first
+ // character of it. Continue processing characters as long as they're not digits.
+ int length = 1;
+ while (true)
+ {
+ if (++_pos >= _value.Length || (uint)(_value[_pos] - '0') <= 9)
+ {
+ break;
+ }
+ length++;
+ }
+
+ // Return the separator.
+ return new TimeSpanToken(TTT.Sep, 0, 0, _value.Slice(pos, length));
+ }
+
+ internal bool EOL => _pos >= (_value.Length - 1);
+
+ internal void BackOne()
+ {
+ if (_pos > 0) --_pos;
+ }
+
+ internal char NextChar
+ {
+ get
+ {
+ int pos = ++_pos;
+ return (uint)pos < (uint)_value.Length ?
+ _value[pos] :
+ (char)0;
+ }
+ }
+ }
+
+ /// <summary>Stores intermediary parsing state for the standard formats.</summary>
+ [IsByRefLike]
+ private struct TimeSpanRawInfo
+ {
+ internal TimeSpanFormat.FormatLiterals PositiveInvariant => TimeSpanFormat.PositiveInvariantFormatLiterals;
+ internal TimeSpanFormat.FormatLiterals NegativeInvariant => TimeSpanFormat.NegativeInvariantFormatLiterals;
+
+ internal TimeSpanFormat.FormatLiterals PositiveLocalized
+ {
+ get
+ {
+ if (!_posLocInit)
+ {
+ _posLoc = new TimeSpanFormat.FormatLiterals();
+ _posLoc.Init(_fullPosPattern, false);
+ _posLocInit = true;
+ }
+ return _posLoc;
+ }
+ }
+
+ internal TimeSpanFormat.FormatLiterals NegativeLocalized
+ {
+ get
+ {
+ if (!_negLocInit)
+ {
+ _negLoc = new TimeSpanFormat.FormatLiterals();
+ _negLoc.Init(_fullNegPattern, false);
+ _negLocInit = true;
+ }
+ return _negLoc;
+ }
+ }
+
+ internal bool FullAppCompatMatch(TimeSpanFormat.FormatLiterals pattern) =>
+ _sepCount == 5
+ && _numCount == 4
+ && StringSpanHelpers.Equals(_literals0, pattern.Start)
+ && StringSpanHelpers.Equals(_literals1, pattern.DayHourSep)
+ && StringSpanHelpers.Equals(_literals2, pattern.HourMinuteSep)
+ && StringSpanHelpers.Equals(_literals3, pattern.AppCompatLiteral)
+ && StringSpanHelpers.Equals(_literals4, pattern.End);
+
+ internal bool PartialAppCompatMatch(TimeSpanFormat.FormatLiterals pattern) =>
+ _sepCount == 4
+ && _numCount == 3
+ && StringSpanHelpers.Equals(_literals0, pattern.Start)
+ && StringSpanHelpers.Equals(_literals1, pattern.HourMinuteSep)
+ && StringSpanHelpers.Equals(_literals2, pattern.AppCompatLiteral)
+ && StringSpanHelpers.Equals(_literals3, pattern.End);
+
+ /// <summary>DHMSF (all values matched)</summary>
+ internal bool FullMatch(TimeSpanFormat.FormatLiterals pattern) =>
+ _sepCount == MaxLiteralTokens
+ && _numCount == MaxNumericTokens
+ && StringSpanHelpers.Equals(_literals0, pattern.Start)
+ && StringSpanHelpers.Equals(_literals1, pattern.DayHourSep)
+ && StringSpanHelpers.Equals(_literals2, pattern.HourMinuteSep)
+ && StringSpanHelpers.Equals(_literals3, pattern.MinuteSecondSep)
+ && StringSpanHelpers.Equals(_literals4, pattern.SecondFractionSep)
+ && StringSpanHelpers.Equals(_literals5, pattern.End);
+
+ /// <summary>D (no hours, minutes, seconds, or fractions)</summary>
+ internal bool FullDMatch(TimeSpanFormat.FormatLiterals pattern) =>
+ _sepCount == 2
+ && _numCount == 1
+ && StringSpanHelpers.Equals(_literals0, pattern.Start)
+ && StringSpanHelpers.Equals(_literals1, pattern.End);
+
+ /// <summary>HM (no days, seconds, or fractions)</summary>
+ internal bool FullHMMatch(TimeSpanFormat.FormatLiterals pattern) =>
+ _sepCount == 3
+ && _numCount == 2
+ && StringSpanHelpers.Equals(_literals0, pattern.Start)
+ && StringSpanHelpers.Equals(_literals1, pattern.HourMinuteSep)
+ && StringSpanHelpers.Equals(_literals2, pattern.End);
+
+ /// <summary>DHM (no seconds or fraction)</summary>
+ internal bool FullDHMMatch(TimeSpanFormat.FormatLiterals pattern) =>
+ _sepCount == 4
+ && _numCount == 3
+ && StringSpanHelpers.Equals(_literals0, pattern.Start)
+ && StringSpanHelpers.Equals(_literals1, pattern.DayHourSep)
+ && StringSpanHelpers.Equals(_literals2, pattern.HourMinuteSep)
+ && StringSpanHelpers.Equals(_literals3, pattern.End);
+
+ /// <summary>HMS (no days or fraction)</summary>
+ internal bool FullHMSMatch(TimeSpanFormat.FormatLiterals pattern) =>
+ _sepCount == 4
+ && _numCount == 3
+ && StringSpanHelpers.Equals(_literals0, pattern.Start)
+ && StringSpanHelpers.Equals(_literals1, pattern.HourMinuteSep)
+ && StringSpanHelpers.Equals(_literals2, pattern.MinuteSecondSep)
+ && StringSpanHelpers.Equals(_literals3, pattern.End);
+
+ /// <summary>DHMS (no fraction)</summary>
+ internal bool FullDHMSMatch(TimeSpanFormat.FormatLiterals pattern) =>
+ _sepCount == 5
+ && _numCount == 4
+ && StringSpanHelpers.Equals(_literals0, pattern.Start)
+ && StringSpanHelpers.Equals(_literals1, pattern.DayHourSep)
+ && StringSpanHelpers.Equals(_literals2, pattern.HourMinuteSep)
+ && StringSpanHelpers.Equals(_literals3, pattern.MinuteSecondSep)
+ && StringSpanHelpers.Equals(_literals4, pattern.End);
+
+ /// <summary>HMSF (no days)</summary>
+ internal bool FullHMSFMatch(TimeSpanFormat.FormatLiterals pattern) =>
+ _sepCount == 5
+ && _numCount == 4
+ && StringSpanHelpers.Equals(_literals0, pattern.Start)
+ && StringSpanHelpers.Equals(_literals1, pattern.HourMinuteSep)
+ && StringSpanHelpers.Equals(_literals2, pattern.MinuteSecondSep)
+ && StringSpanHelpers.Equals(_literals3, pattern.SecondFractionSep)
+ && StringSpanHelpers.Equals(_literals4, pattern.End);
+
+ internal TTT _lastSeenTTT;
+ internal int _tokenCount;
+ internal int _sepCount;
+ internal int _numCount;
+
+ private TimeSpanFormat.FormatLiterals _posLoc;
+ private TimeSpanFormat.FormatLiterals _negLoc;
+ private bool _posLocInit;
+ private bool _negLocInit;
+ private string _fullPosPattern;
+ private string _fullNegPattern;
+
+ private const int MaxTokens = 11;
+ private const int MaxLiteralTokens = 6;
+ private const int MaxNumericTokens = 5;
+
+ internal TimeSpanToken _numbers0, _numbers1, _numbers2, _numbers3, _numbers4; // MaxNumbericTokens = 5
+ internal ReadOnlySpan<char> _literals0, _literals1, _literals2, _literals3, _literals4, _literals5; // MaxLiteralTokens=6
+
+ internal void Init(DateTimeFormatInfo dtfi)
+ {
+ Debug.Assert(dtfi != null);
+
+ _lastSeenTTT = TTT.None;
+ _tokenCount = 0;
+ _sepCount = 0;
+ _numCount = 0;
+
+ _fullPosPattern = dtfi.FullTimeSpanPositivePattern;
+ _fullNegPattern = dtfi.FullTimeSpanNegativePattern;
+ _posLocInit = false;
+ _negLocInit = false;
+ }
+
+ internal bool ProcessToken(ref TimeSpanToken tok, ref TimeSpanResult result)
+ {
+ switch (tok._ttt)
+ {
+ case TTT.Num:
+ if ((_tokenCount == 0 && !AddSep(default(ReadOnlySpan<char>), ref result)) || !AddNum(tok, ref result))
+ {
+ return false;
+ }
+ break;
+
+ case TTT.Sep:
+ if (!AddSep(tok._sep, ref result))
+ {
+ return false;
+ }
+ break;
+
+ case TTT.NumOverflow:
+ return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+
+ default:
+ // Some unknown token or a repeat token type in the input
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ }
+
+ _lastSeenTTT = tok._ttt;
+ Debug.Assert(_tokenCount == (_sepCount + _numCount), "tokenCount == (SepCount + NumCount)");
+ return true;
+ }
+
+ private bool AddSep(ReadOnlySpan<char> sep, ref TimeSpanResult result)
+ {
+ if (_sepCount >= MaxLiteralTokens || _tokenCount >= MaxTokens)
+ {
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ }
+
+ switch (_sepCount++)
+ {
+ case 0: _literals0 = sep; break;
+ case 1: _literals1 = sep; break;
+ case 2: _literals2 = sep; break;
+ case 3: _literals3 = sep; break;
+ case 4: _literals4 = sep; break;
+ default: _literals5 = sep; break;
+ }
+
+ _tokenCount++;
+ return true;
+ }
+ private bool AddNum(TimeSpanToken num, ref TimeSpanResult result)
+ {
+ if (_numCount >= MaxNumericTokens || _tokenCount >= MaxTokens)
+ {
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ }
+
+ switch (_numCount++)
+ {
+ case 0: _numbers0 = num; break;
+ case 1: _numbers1 = num; break;
+ case 2: _numbers2 = num; break;
+ case 3: _numbers3 = num; break;
+ default: _numbers4 = num; break;
+ }
+
+ _tokenCount++;
+ return true;
+ }
+ }
+
+ /// <summary>Store the result of the parsing.</summary>
+ private struct TimeSpanResult
+ {
+ internal TimeSpan parsedTimeSpan;
+ private readonly bool _throwOnFailure;
+
+ internal TimeSpanResult(bool throwOnFailure)
+ {
+ parsedTimeSpan = default(TimeSpan);
+ _throwOnFailure = throwOnFailure;
+ }
+
+ internal bool SetFailure(ParseFailureKind kind, string resourceKey, object messageArgument = null, string argumentName = null)
+ {
+ if (!_throwOnFailure)
+ {
+ return false;
+ }
+
+ string message = SR.GetResourceString(resourceKey);
+ switch (kind)
+ {
+ case ParseFailureKind.ArgumentNull:
+ Debug.Assert(argumentName != null);
+ throw new ArgumentNullException(argumentName, message);
+
+ case ParseFailureKind.FormatWithParameter:
+ throw new FormatException(SR.Format(message, messageArgument));
+
+ case ParseFailureKind.Overflow:
+ throw new OverflowException(message);
+
+ default:
+ Debug.Assert(kind == ParseFailureKind.Format, $"Unexpected failure {kind}");
+ throw new FormatException(message);
+ }
+ }
+ }
+
+ internal static long Pow10(int pow)
+ {
+ switch (pow)
+ {
+ case 0: return 1;
+ case 1: return 10;
+ case 2: return 100;
+ case 3: return 1000;
+ case 4: return 10000;
+ case 5: return 100000;
+ case 6: return 1000000;
+ case 7: return 10000000;
+ default: return (long)Math.Pow(10, pow);
+ }
+ }
+
+ private static bool TryTimeToTicks(bool positive, TimeSpanToken days, TimeSpanToken hours, TimeSpanToken minutes, TimeSpanToken seconds, TimeSpanToken fraction, out long result)
+ {
+ if (days._num > MaxDays ||
+ hours._num > MaxHours ||
+ minutes._num > MaxMinutes ||
+ seconds._num > MaxSeconds ||
+ fraction.IsInvalidFraction())
+ {
+ result = 0;
+ return false;
+ }
+
+ long ticks = ((long)days._num * 3600 * 24 + (long)hours._num * 3600 + (long)minutes._num * 60 + seconds._num) * 1000;
+ if (ticks > InternalGlobalizationHelper.MaxMilliSeconds || ticks < InternalGlobalizationHelper.MinMilliSeconds)
+ {
+ result = 0;
+ return false;
+ }
+
+ // Normalize the fraction component
+ //
+ // string representation => (zeroes,num) => resultant fraction ticks
+ // --------------------- ------------ ------------------------
+ // ".9999999" => (0,9999999) => 9,999,999 ticks (same as constant maxFraction)
+ // ".1" => (0,1) => 1,000,000 ticks
+ // ".01" => (1,1) => 100,000 ticks
+ // ".001" => (2,1) => 10,000 ticks
+ long f = fraction._num;
+ if (f != 0)
+ {
+ long lowerLimit = InternalGlobalizationHelper.TicksPerTenthSecond;
+ if (fraction._zeroes > 0)
+ {
+ long divisor = Pow10(fraction._zeroes);
+ lowerLimit = lowerLimit / divisor;
+ }
+
+ while (f < lowerLimit)
+ {
+ f *= 10;
+ }
+ }
+
+ result = ticks * TimeSpan.TicksPerMillisecond + f;
+ if (positive && result < 0)
+ {
+ result = 0;
+ return false;
+ }
+
+ return true;
+ }
+
+ internal static TimeSpan Parse(ReadOnlySpan<char> input, IFormatProvider formatProvider)
+ {
+ var parseResult = new TimeSpanResult(throwOnFailure: true);
+ bool success = TryParseTimeSpan(input, TimeSpanStandardStyles.Any, formatProvider, ref parseResult);
+ Debug.Assert(success, "Should have thrown on failure");
+ return parseResult.parsedTimeSpan;
+ }
+
+ internal static bool TryParse(ReadOnlySpan<char> input, IFormatProvider formatProvider, out TimeSpan result)
+ {
+ var parseResult = new TimeSpanResult(throwOnFailure: false);
+
+ if (TryParseTimeSpan(input, TimeSpanStandardStyles.Any, formatProvider, ref parseResult))
+ {
+ result = parseResult.parsedTimeSpan;
+ return true;
+ }
+
+ result = default(TimeSpan);
+ return false;
+ }
+
+ internal static TimeSpan ParseExact(ReadOnlySpan<char> input, string format, IFormatProvider formatProvider, TimeSpanStyles styles)
+ {
+ var parseResult = new TimeSpanResult(throwOnFailure: true);
+ bool success = TryParseExactTimeSpan(input, format, formatProvider, styles, ref parseResult);
+ Debug.Assert(success, "Should have thrown on failure");
+ return parseResult.parsedTimeSpan;
+ }
+
+ internal static bool TryParseExact(ReadOnlySpan<char> input, string format, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result)
+ {
+ var parseResult = new TimeSpanResult(throwOnFailure: false);
+
+ if (TryParseExactTimeSpan(input, format, formatProvider, styles, ref parseResult))
+ {
+ result = parseResult.parsedTimeSpan;
+ return true;
+ }
+
+ result = default(TimeSpan);
+ return false;
+ }
+
+ internal static TimeSpan ParseExactMultiple(ReadOnlySpan<char> input, string[] formats, IFormatProvider formatProvider, TimeSpanStyles styles)
+ {
+ var parseResult = new TimeSpanResult(throwOnFailure: true);
+ bool success = TryParseExactMultipleTimeSpan(input, formats, formatProvider, styles, ref parseResult);
+ Debug.Assert(success, "Should have thrown on failure");
+ return parseResult.parsedTimeSpan;
+ }
+
+ internal static bool TryParseExactMultiple(ReadOnlySpan<char> input, string[] formats, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result)
+ {
+ var parseResult = new TimeSpanResult(throwOnFailure: false);
+
+ if (TryParseExactMultipleTimeSpan(input, formats, formatProvider, styles, ref parseResult))
+ {
+ result = parseResult.parsedTimeSpan;
+ return true;
+ }
+
+ result = default(TimeSpan);
+ return false;
+ }
+
+ /// <summary>Common private Parse method called by both Parse and TryParse.</summary>
+ private static bool TryParseTimeSpan(ReadOnlySpan<char> input, TimeSpanStandardStyles style, IFormatProvider formatProvider, ref TimeSpanResult result)
+ {
+ input = input.Trim();
+ if (input.IsEmpty)
+ {
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ }
+
+ var tokenizer = new TimeSpanTokenizer(input);
+
+ var raw = new TimeSpanRawInfo();
+ raw.Init(DateTimeFormatInfo.GetInstance(formatProvider));
+
+ TimeSpanToken tok = tokenizer.GetNextToken();
+
+ // The following loop will break out when we reach the end of the str or
+ // when we can determine that the input is invalid.
+ while (tok._ttt != TTT.End)
+ {
+ if (!raw.ProcessToken(ref tok, ref result))
+ {
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ }
+ tok = tokenizer.GetNextToken();
+ }
+ Debug.Assert(tokenizer.EOL);
+
+ if (!ProcessTerminalState(ref raw, style, ref result))
+ {
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// Validate the terminal state of a standard format parse.
+ /// Sets result.parsedTimeSpan on success.
+ /// Calculates the resultant TimeSpan from the TimeSpanRawInfo.
+ /// </summary>
+ /// <remarks>
+ /// try => +InvariantPattern, -InvariantPattern, +LocalizedPattern, -LocalizedPattern
+ /// 1) Verify Start matches
+ /// 2) Verify End matches
+ /// 3) 1 number => d
+ /// 2 numbers => h:m
+ /// 3 numbers => h:m:s | d.h:m | h:m:.f
+ /// 4 numbers => h:m:s.f | d.h:m:s | d.h:m:.f
+ /// 5 numbers => d.h:m:s.f
+ /// </remarks>
+ private static bool ProcessTerminalState(ref TimeSpanRawInfo raw, TimeSpanStandardStyles style, ref TimeSpanResult result)
+ {
+ if (raw._lastSeenTTT == TTT.Num)
+ {
+ TimeSpanToken tok = new TimeSpanToken();
+ tok._ttt = TTT.Sep;
+ if (!raw.ProcessToken(ref tok, ref result))
+ {
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ }
+ }
+
+ switch (raw._numCount)
+ {
+ case 1: return ProcessTerminal_D(ref raw, style, ref result);
+ case 2: return ProcessTerminal_HM(ref raw, style, ref result);
+ case 3: return ProcessTerminal_HM_S_D(ref raw, style, ref result);
+ case 4: return ProcessTerminal_HMS_F_D(ref raw, style, ref result);
+ case 5: return ProcessTerminal_DHMSF(ref raw, style, ref result);
+ default: return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ }
+ }
+
+ /// <summary>Validate the 5-number "Days.Hours:Minutes:Seconds.Fraction" terminal case.</summary>
+ private static bool ProcessTerminal_DHMSF(ref TimeSpanRawInfo raw, TimeSpanStandardStyles style, ref TimeSpanResult result)
+ {
+ if (raw._sepCount != 6)
+ {
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ }
+ Debug.Assert(raw._numCount == 5);
+
+ bool inv = (style & TimeSpanStandardStyles.Invariant) != 0;
+ bool loc = (style & TimeSpanStandardStyles.Localized) != 0;
+ bool positive = false;
+ bool match = false;
+
+ if (inv)
+ {
+ if (raw.FullMatch(raw.PositiveInvariant))
+ {
+ match = true;
+ positive = true;
+ }
+ if (!match && raw.FullMatch(raw.NegativeInvariant))
+ {
+ match = true;
+ positive = false;
+ }
+ }
+
+ if (loc)
+ {
+ if (!match && raw.FullMatch(raw.PositiveLocalized))
+ {
+ match = true;
+ positive = true;
+ }
+ if (!match && raw.FullMatch(raw.NegativeLocalized))
+ {
+ match = true;
+ positive = false;
+ }
+ }
+
+ if (match)
+ {
+ long ticks;
+
+ if (!TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, raw._numbers3, raw._numbers4, out ticks))
+ {
+ return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ }
+
+ if (!positive)
+ {
+ ticks = -ticks;
+ if (ticks > 0)
+ {
+ return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ }
+ }
+
+ result.parsedTimeSpan._ticks = ticks;
+ return true;
+ }
+
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ }
+
+
+ /// <summary>
+ /// Validate the ambiguous 4-number "Hours:Minutes:Seconds.Fraction", "Days.Hours:Minutes:Seconds",
+ /// or "Days.Hours:Minutes:.Fraction" terminal case.
+ /// </summary>
+ private static bool ProcessTerminal_HMS_F_D(ref TimeSpanRawInfo raw, TimeSpanStandardStyles style, ref TimeSpanResult result)
+ {
+ if (raw._sepCount != 5 || (style & TimeSpanStandardStyles.RequireFull) != 0)
+ {
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ }
+ Debug.Assert(raw._numCount == 4);
+
+ bool inv = ((style & TimeSpanStandardStyles.Invariant) != 0);
+ bool loc = ((style & TimeSpanStandardStyles.Localized) != 0);
+
+ long ticks = 0;
+ bool positive = false, match = false, overflow = false;
+ var zero = new TimeSpanToken(0);
+
+ if (inv)
+ {
+ if (raw.FullHMSFMatch(raw.PositiveInvariant))
+ {
+ positive = true;
+ match = TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, raw._numbers2, raw._numbers3, out ticks);
+ overflow = overflow || !match;
+ }
+
+ if (!match && raw.FullDHMSMatch(raw.PositiveInvariant))
+ {
+ positive = true;
+ match = TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, raw._numbers3, zero, out ticks);
+ overflow = overflow || !match;
+ }
+
+ if (!match && raw.FullAppCompatMatch(raw.PositiveInvariant))
+ {
+ positive = true;
+ match = TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, zero, raw._numbers3, out ticks);
+ overflow = overflow || !match;
+ }
+
+ if (!match && raw.FullHMSFMatch(raw.NegativeInvariant))
+ {
+ positive = false;
+ match = TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, raw._numbers2, raw._numbers3, out ticks);
+ overflow = overflow || !match;
+ }
+
+ if (!match && raw.FullDHMSMatch(raw.NegativeInvariant))
+ {
+ positive = false;
+ match = TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, raw._numbers3, zero, out ticks);
+ overflow = overflow || !match;
+ }
+
+ if (!match && raw.FullAppCompatMatch(raw.NegativeInvariant))
+ {
+ positive = false;
+ match = TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, zero, raw._numbers3, out ticks);
+ overflow = overflow || !match;
+ }
+ }
+
+ if (loc)
+ {
+ if (!match && raw.FullHMSFMatch(raw.PositiveLocalized))
+ {
+ positive = true;
+ match = TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, raw._numbers2, raw._numbers3, out ticks);
+ overflow = overflow || !match;
+ }
+
+ if (!match && raw.FullDHMSMatch(raw.PositiveLocalized))
+ {
+ positive = true;
+ match = TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, raw._numbers3, zero, out ticks);
+ overflow = overflow || !match;
+ }
+
+ if (!match && raw.FullAppCompatMatch(raw.PositiveLocalized))
+ {
+ positive = true;
+ match = TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, zero, raw._numbers3, out ticks);
+ overflow = overflow || !match;
+ }
+
+ if (!match && raw.FullHMSFMatch(raw.NegativeLocalized))
+ {
+ positive = false;
+ match = TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, raw._numbers2, raw._numbers3, out ticks);
+ overflow = overflow || !match;
+ }
+
+ if (!match && raw.FullDHMSMatch(raw.NegativeLocalized))
+ {
+ positive = false;
+ match = TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, raw._numbers3, zero, out ticks);
+ overflow = overflow || !match;
+ }
+
+ if (!match && raw.FullAppCompatMatch(raw.NegativeLocalized))
+ {
+ positive = false;
+ match = TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, zero, raw._numbers3, out ticks);
+ overflow = overflow || !match;
+ }
+ }
+
+ if (match)
+ {
+ if (!positive)
+ {
+ ticks = -ticks;
+ if (ticks > 0)
+ {
+ return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ }
+ }
+
+ result.parsedTimeSpan._ticks = ticks;
+ return true;
+ }
+
+ return overflow ?
+ result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge)) : // we found at least one literal pattern match but the numbers just didn't fit
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan)); // we couldn't find a thing
+ }
+
+ /// <summary>Validate the ambiguous 3-number "Hours:Minutes:Seconds", "Days.Hours:Minutes", or "Hours:Minutes:.Fraction" terminal case.</summary>
+ private static bool ProcessTerminal_HM_S_D(ref TimeSpanRawInfo raw, TimeSpanStandardStyles style, ref TimeSpanResult result)
+ {
+ if (raw._sepCount != 4 || (style & TimeSpanStandardStyles.RequireFull) != 0)
+ {
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ }
+ Debug.Assert(raw._numCount == 3);
+
+ bool inv = ((style & TimeSpanStandardStyles.Invariant) != 0);
+ bool loc = ((style & TimeSpanStandardStyles.Localized) != 0);
+
+ bool positive = false, match = false, overflow = false;
+ var zero = new TimeSpanToken(0);
+ long ticks = 0;
+
+ if (inv)
+ {
+ if (raw.FullHMSMatch(raw.PositiveInvariant))
+ {
+ positive = true;
+ match = TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, raw._numbers2, zero, out ticks);
+ overflow = overflow || !match;
+ }
+
+ if (!match && raw.FullDHMMatch(raw.PositiveInvariant))
+ {
+ positive = true;
+ match = TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, zero, zero, out ticks);
+ overflow = overflow || !match;
+ }
+
+ if (!match && raw.PartialAppCompatMatch(raw.PositiveInvariant))
+ {
+ positive = true;
+ match = TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, zero, raw._numbers2, out ticks);
+ overflow = overflow || !match;
+ }
+
+ if (!match && raw.FullHMSMatch(raw.NegativeInvariant))
+ {
+ positive = false;
+ match = TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, raw._numbers2, zero, out ticks);
+ overflow = overflow || !match;
+ }
+
+ if (!match && raw.FullDHMMatch(raw.NegativeInvariant))
+ {
+ positive = false;
+ match = TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, zero, zero, out ticks);
+ overflow = overflow || !match;
+ }
+
+ if (!match && raw.PartialAppCompatMatch(raw.NegativeInvariant))
+ {
+ positive = false;
+ match = TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, zero, raw._numbers2, out ticks);
+ overflow = overflow || !match;
+ }
+ }
+
+ if (loc)
+ {
+ if (!match && raw.FullHMSMatch(raw.PositiveLocalized))
+ {
+ positive = true;
+ match = TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, raw._numbers2, zero, out ticks);
+ overflow = overflow || !match;
+ }
+
+ if (!match && raw.FullDHMMatch(raw.PositiveLocalized))
+ {
+ positive = true;
+ match = TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, zero, zero, out ticks);
+ overflow = overflow || !match;
+ }
+
+ if (!match && raw.PartialAppCompatMatch(raw.PositiveLocalized))
+ {
+ positive = true;
+ match = TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, zero, raw._numbers2, out ticks);
+ overflow = overflow || !match;
+ }
+
+ if (!match && raw.FullHMSMatch(raw.NegativeLocalized))
+ {
+ positive = false;
+ match = TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, raw._numbers2, zero, out ticks);
+ overflow = overflow || !match;
+ }
+
+ if (!match && raw.FullDHMMatch(raw.NegativeLocalized))
+ {
+ positive = false;
+ match = TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, zero, zero, out ticks);
+ overflow = overflow || !match;
+ }
+
+ if (!match && raw.PartialAppCompatMatch(raw.NegativeLocalized))
+ {
+ positive = false;
+ match = TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, zero, raw._numbers2, out ticks);
+ overflow = overflow || !match;
+ }
+ }
+
+ if (match)
+ {
+ if (!positive)
+ {
+ ticks = -ticks;
+ if (ticks > 0)
+ {
+ return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ }
+ }
+
+ result.parsedTimeSpan._ticks = ticks;
+ return true;
+ }
+
+ return overflow ?
+ result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge)) : // we found at least one literal pattern match but the numbers just didn't fit
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan)); // we couldn't find a thing
+ }
+
+ /// <summary>Validate the 2-number "Hours:Minutes" terminal case.</summary>
+ private static bool ProcessTerminal_HM(ref TimeSpanRawInfo raw, TimeSpanStandardStyles style, ref TimeSpanResult result)
+ {
+ if (raw._sepCount != 3 || (style & TimeSpanStandardStyles.RequireFull) != 0)
+ {
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ }
+ Debug.Assert(raw._numCount == 2);
+
+ bool inv = ((style & TimeSpanStandardStyles.Invariant) != 0);
+ bool loc = ((style & TimeSpanStandardStyles.Localized) != 0);
+
+ bool positive = false, match = false;
+
+ if (inv)
+ {
+ if (raw.FullHMMatch(raw.PositiveInvariant))
+ {
+ match = true;
+ positive = true;
+ }
+
+ if (!match && raw.FullHMMatch(raw.NegativeInvariant))
+ {
+ match = true;
+ positive = false;
+ }
+ }
+
+ if (loc)
+ {
+ if (!match && raw.FullHMMatch(raw.PositiveLocalized))
+ {
+ match = true;
+ positive = true;
+ }
+
+ if (!match && raw.FullHMMatch(raw.NegativeLocalized))
+ {
+ match = true;
+ positive = false;
+ }
+ }
+
+ if (match)
+ {
+ long ticks = 0;
+ var zero = new TimeSpanToken(0);
+
+ if (!TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, zero, zero, out ticks))
+ {
+ return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ }
+
+ if (!positive)
+ {
+ ticks = -ticks;
+ if (ticks > 0)
+ {
+ return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ }
+ }
+
+ result.parsedTimeSpan._ticks = ticks;
+ return true;
+ }
+
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ }
+
+ /// <summary>Validate the 1-number "Days" terminal case.</summary>
+ private static bool ProcessTerminal_D(ref TimeSpanRawInfo raw, TimeSpanStandardStyles style, ref TimeSpanResult result)
+ {
+ if (raw._sepCount != 2 || (style & TimeSpanStandardStyles.RequireFull) != 0)
+ {
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ }
+ Debug.Assert(raw._numCount == 1);
+
+ bool inv = ((style & TimeSpanStandardStyles.Invariant) != 0);
+ bool loc = ((style & TimeSpanStandardStyles.Localized) != 0);
+
+ bool positive = false, match = false;
+
+ if (inv)
+ {
+ if (raw.FullDMatch(raw.PositiveInvariant))
+ {
+ match = true;
+ positive = true;
+ }
+
+ if (!match && raw.FullDMatch(raw.NegativeInvariant))
+ {
+ match = true;
+ positive = false;
+ }
+ }
+
+ if (loc)
+ {
+ if (!match && raw.FullDMatch(raw.PositiveLocalized))
+ {
+ match = true;
+ positive = true;
+ }
+
+ if (!match && raw.FullDMatch(raw.NegativeLocalized))
+ {
+ match = true;
+ positive = false;
+ }
+ }
+
+ if (match)
+ {
+ long ticks = 0;
+ var zero = new TimeSpanToken(0);
+
+ if (!TryTimeToTicks(positive, raw._numbers0, zero, zero, zero, zero, out ticks))
+ {
+ return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ }
+
+ if (!positive)
+ {
+ ticks = -ticks;
+ if (ticks > 0)
+ {
+ return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ }
+ }
+
+ result.parsedTimeSpan._ticks = ticks;
+ return true;
+ }
+
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ }
+
+ /// <summary>Common private ParseExact method called by both ParseExact and TryParseExact.</summary>
+ private static bool TryParseExactTimeSpan(ReadOnlySpan<char> input, string format, IFormatProvider formatProvider, TimeSpanStyles styles, ref TimeSpanResult result)
+ {
+ if (format == null)
+ {
+ return result.SetFailure(ParseFailureKind.ArgumentNull, nameof(SR.ArgumentNull_String), argumentName: nameof(format));
+ }
+
+ if (format.Length == 0)
+ {
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadFormatSpecifier));
+ }
+
+ if (format.Length == 1)
+ {
+ switch (format[0])
+ {
+ case 'c':
+ case 't':
+ case 'T':
+ return TryParseTimeSpanConstant(input, ref result); // fast path for legacy style TimeSpan formats.
+
+ case 'g':
+ return TryParseTimeSpan(input, TimeSpanStandardStyles.Localized, formatProvider, ref result);
+
+ case 'G':
+ return TryParseTimeSpan(input, TimeSpanStandardStyles.Localized | TimeSpanStandardStyles.RequireFull, formatProvider, ref result);
+
+ default:
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadFormatSpecifier));
+ }
+ }
+
+ return TryParseByFormat(input, format, styles, ref result);
+ }
+
+ /// <summary>Parse the TimeSpan instance using the specified format. Used by TryParseExactTimeSpan.</summary>
+ private static bool TryParseByFormat(ReadOnlySpan<char> input, string format, TimeSpanStyles styles, ref TimeSpanResult result)
+ {
+ Debug.Assert(format != null, "format != null");
+
+ bool seenDD = false; // already processed days?
+ bool seenHH = false; // already processed hours?
+ bool seenMM = false; // already processed minutes?
+ bool seenSS = false; // already processed seconds?
+ bool seenFF = false; // already processed fraction?
+
+ int dd = 0; // parsed days
+ int hh = 0; // parsed hours
+ int mm = 0; // parsed minutes
+ int ss = 0; // parsed seconds
+ int leadingZeroes = 0; // number of leading zeroes in the parsed fraction
+ int ff = 0; // parsed fraction
+ int i = 0; // format string position
+ int tokenLen = 0; // length of current format token, used to update index 'i'
+
+ var tokenizer = new TimeSpanTokenizer(input, -1);
+
+ while (i < format.Length)
+ {
+ char ch = format[i];
+ int nextFormatChar;
+ switch (ch)
+ {
+ case 'h':
+ tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
+ if (tokenLen > 2 || seenHH || !ParseExactDigits(ref tokenizer, tokenLen, out hh))
+ {
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ }
+ seenHH = true;
+ break;
+
+ case 'm':
+ tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
+ if (tokenLen > 2 || seenMM || !ParseExactDigits(ref tokenizer, tokenLen, out mm))
+ {
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ }
+ seenMM = true;
+ break;
+
+ case 's':
+ tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
+ if (tokenLen > 2 || seenSS || !ParseExactDigits(ref tokenizer, tokenLen, out ss))
+ {
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ }
+ seenSS = true;
+ break;
+
+ case 'f':
+ tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
+ if (tokenLen > DateTimeFormat.MaxSecondsFractionDigits || seenFF || !ParseExactDigits(ref tokenizer, tokenLen, tokenLen, out leadingZeroes, out ff))
+ {
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ }
+ seenFF = true;
+ break;
+
+ case 'F':
+ tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
+ if (tokenLen > DateTimeFormat.MaxSecondsFractionDigits || seenFF)
+ {
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ }
+ ParseExactDigits(ref tokenizer, tokenLen, tokenLen, out leadingZeroes, out ff);
+ seenFF = true;
+ break;
+
+ case 'd':
+ tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
+ int tmp = 0;
+ if (tokenLen > 8 || seenDD || !ParseExactDigits(ref tokenizer, (tokenLen < 2) ? 1 : tokenLen, (tokenLen < 2) ? 8 : tokenLen, out tmp, out dd))
+ {
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ }
+ seenDD = true;
+ break;
+
+ case '\'':
+ case '\"':
+ StringBuilder enquotedString = new StringBuilder();
+ if (!DateTimeParse.TryParseQuoteString(format, i, enquotedString, out tokenLen))
+ {
+ return result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadQuote), ch);
+ }
+ if (!ParseExactLiteral(ref tokenizer, enquotedString))
+ {
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ }
+ break;
+
+ case '%':
+ // Optional format character.
+ // For example, format string "%d" will print day
+ // Most of the cases, "%" can be ignored.
+ nextFormatChar = DateTimeFormat.ParseNextChar(format, i);
+
+ // nextFormatChar will be -1 if we already reach the end of the format string.
+ // Besides, we will not allow "%%" appear in the pattern.
+ if (nextFormatChar >= 0 && nextFormatChar != '%')
+ {
+ tokenLen = 1; // skip the '%' and process the format character
+ break;
+ }
+ else
+ {
+ // This means that '%' is at the end of the format string or
+ // "%%" appears in the format string.
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ }
+
+ case '\\':
+ // Escaped character. Can be used to insert character into the format string.
+ // For example, "\d" will insert the character 'd' into the string.
+ //
+ nextFormatChar = DateTimeFormat.ParseNextChar(format, i);
+ if (nextFormatChar >= 0 && tokenizer.NextChar == (char)nextFormatChar)
+ {
+ tokenLen = 2;
+ }
+ else
+ {
+ // This means that '\' is at the end of the format string or the literal match failed.
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ }
+ break;
+
+ default:
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ }
+
+ i += tokenLen;
+ }
+
+
+ if (!tokenizer.EOL)
+ {
+ // the custom format didn't consume the entire input
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ }
+
+ bool positive = (styles & TimeSpanStyles.AssumeNegative) == 0;
+ if (TryTimeToTicks(positive, new TimeSpanToken(dd),
+ new TimeSpanToken(hh),
+ new TimeSpanToken(mm),
+ new TimeSpanToken(ss),
+ new TimeSpanToken(ff, leadingZeroes),
+ out long ticks))
+ {
+ if (!positive)
+ {
+ ticks = -ticks;
+ }
+
+ result.parsedTimeSpan._ticks = ticks;
+ return true;
+ }
+ else
+ {
+ return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ }
+ }
+
+ private static bool ParseExactDigits(ref TimeSpanTokenizer tokenizer, int minDigitLength, out int result)
+ {
+ result = 0;
+ int zeroes = 0;
+ int maxDigitLength = (minDigitLength == 1) ? 2 : minDigitLength;
+ return ParseExactDigits(ref tokenizer, minDigitLength, maxDigitLength, out zeroes, out result);
+ }
+
+ private static bool ParseExactDigits(ref TimeSpanTokenizer tokenizer, int minDigitLength, int maxDigitLength, out int zeroes, out int result)
+ {
+ int tmpResult = 0, tmpZeroes = 0;
+
+ int tokenLength = 0;
+ while (tokenLength < maxDigitLength)
+ {
+ char ch = tokenizer.NextChar;
+ if (ch < '0' || ch > '9')
+ {
+ tokenizer.BackOne();
+ break;
+ }
+
+ tmpResult = tmpResult * 10 + (ch - '0');
+ if (tmpResult == 0) tmpZeroes++;
+ tokenLength++;
+ }
+
+ zeroes = tmpZeroes;
+ result = tmpResult;
+ return tokenLength >= minDigitLength;
+ }
+
+ private static bool ParseExactLiteral(ref TimeSpanTokenizer tokenizer, StringBuilder enquotedString)
+ {
+ for (int i = 0; i < enquotedString.Length; i++)
+ {
+ if (enquotedString[i] != tokenizer.NextChar)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// Parses the "c" (constant) format. This code is 100% identical to the non-globalized v1.0-v3.5 TimeSpan.Parse() routine
+ /// and exists for performance/appcompat with legacy callers who cannot move onto the globalized Parse overloads.
+ /// </summary>
+ private static bool TryParseTimeSpanConstant(ReadOnlySpan<char> input, ref TimeSpanResult result) =>
+ new StringParser().TryParse(input, ref result);
+
+ [IsByRefLike]
+ private struct StringParser
+ {
+ private ReadOnlySpan<char> _str;
+ private char _ch;
+ private int _pos;
+ private int _len;
+
+ internal void NextChar()
+ {
+ if (_pos < _len)
+ {
+ _pos++;
+ }
+
+ _ch = _pos < _len ?
+ _str[_pos] :
+ (char)0;
+ }
+
+ internal char NextNonDigit()
+ {
+ int i = _pos;
+ while (i < _len)
+ {
+ char ch = _str[i];
+ if (ch < '0' || ch > '9') return ch;
+ i++;
+ }
+
+ return (char)0;
+ }
+
+ internal bool TryParse(ReadOnlySpan<char> input, ref TimeSpanResult result)
+ {
+ result.parsedTimeSpan._ticks = 0;
+
+ _str = input;
+ _len = input.Length;
+ _pos = -1;
+ NextChar();
+ SkipBlanks();
+
+ bool negative = false;
+ if (_ch == '-')
+ {
+ negative = true;
+ NextChar();
+ }
+
+ long time;
+ if (NextNonDigit() == ':')
+ {
+ if (!ParseTime(out time, ref result))
+ {
+ return false;
+ };
+ }
+ else
+ {
+ int days;
+ if (!ParseInt((int)(0x7FFFFFFFFFFFFFFFL / TimeSpan.TicksPerDay), out days, ref result))
+ {
+ return false;
+ }
+
+ time = days * TimeSpan.TicksPerDay;
+
+ if (_ch == '.')
+ {
+ NextChar();
+ long remainingTime;
+ if (!ParseTime(out remainingTime, ref result))
+ {
+ return false;
+ };
+ time += remainingTime;
+ }
+ }
+
+ if (negative)
+ {
+ time = -time;
+ // Allow -0 as well
+ if (time > 0)
+ {
+ return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ }
+ }
+ else
+ {
+ if (time < 0)
+ {
+ return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ }
+ }
+
+ SkipBlanks();
+
+ if (_pos < _len)
+ {
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ }
+
+ result.parsedTimeSpan._ticks = time;
+ return true;
+ }
+
+ internal bool ParseInt(int max, out int i, ref TimeSpanResult result)
+ {
+ i = 0;
+ int p = _pos;
+ while (_ch >= '0' && _ch <= '9')
+ {
+ if ((i & 0xF0000000) != 0)
+ {
+ return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ }
+
+ i = i * 10 + _ch - '0';
+ if (i < 0)
+ {
+ return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ }
+
+ NextChar();
+ }
+
+ if (p == _pos)
+ {
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ }
+
+ if (i > max)
+ {
+ return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ }
+
+ return true;
+ }
+
+ internal bool ParseTime(out long time, ref TimeSpanResult result)
+ {
+ time = 0;
+ int unit;
+
+ if (!ParseInt(23, out unit, ref result))
+ {
+ return false;
+ }
+
+ time = unit * TimeSpan.TicksPerHour;
+ if (_ch != ':')
+ {
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ }
+
+ NextChar();
+
+ if (!ParseInt(59, out unit, ref result))
+ {
+ return false;
+ }
+
+ time += unit * TimeSpan.TicksPerMinute;
+
+ if (_ch == ':')
+ {
+ NextChar();
+
+ // allow seconds with the leading zero
+ if (_ch != '.')
+ {
+ if (!ParseInt(59, out unit, ref result))
+ {
+ return false;
+ }
+ time += unit * TimeSpan.TicksPerSecond;
+ }
+
+ if (_ch == '.')
+ {
+ NextChar();
+ int f = (int)TimeSpan.TicksPerSecond;
+ while (f > 1 && _ch >= '0' && _ch <= '9')
+ {
+ f /= 10;
+ time += (_ch - '0') * f;
+ NextChar();
+ }
+ }
+ }
+
+ return true;
+ }
+
+ internal void SkipBlanks()
+ {
+ while (_ch == ' ' || _ch == '\t') NextChar();
+ }
+ }
+
+ /// <summary>Common private ParseExactMultiple method called by both ParseExactMultiple and TryParseExactMultiple.</summary>
+ private static bool TryParseExactMultipleTimeSpan(ReadOnlySpan<char> input, string[] formats, IFormatProvider formatProvider, TimeSpanStyles styles, ref TimeSpanResult result)
+ {
+ if (formats == null)
+ {
+ return result.SetFailure(ParseFailureKind.ArgumentNull, nameof(SR.ArgumentNull_String), argumentName: nameof(formats));
+ }
+
+ if (input.Length == 0)
+ {
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ }
+
+ if (formats.Length == 0)
+ {
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadFormatSpecifier));
+ }
+
+ // Do a loop through the provided formats and see if we can parse succesfully in
+ // one of the formats.
+ for (int i = 0; i < formats.Length; i++)
+ {
+ if (formats[i] == null || formats[i].Length == 0)
+ {
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadFormatSpecifier));
+ }
+
+ // Create a new non-throwing result each time to ensure the runs are independent.
+ TimeSpanResult innerResult = new TimeSpanResult(throwOnFailure: false);
+
+ if (TryParseExactTimeSpan(input, formats[i], formatProvider, styles, ref innerResult))
+ {
+ result.parsedTimeSpan = innerResult.parsedTimeSpan;
+ return true;
+ }
+ }
+
+ return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/Guid.cs b/src/mscorlib/shared/System/Guid.cs
new file mode 100644
index 0000000000..b8b4dd5f0f
--- /dev/null
+++ b/src/mscorlib/shared/System/Guid.cs
@@ -0,0 +1,1409 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+
+namespace System
+{
+ // Represents a Globally Unique Identifier.
+ [StructLayout(LayoutKind.Sequential)]
+ [Serializable]
+ [Runtime.Versioning.NonVersionable] // This only applies to field layout
+ [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ public partial struct Guid : IFormattable, IComparable, IComparable<Guid>, IEquatable<Guid>
+ {
+ public static readonly Guid Empty = new Guid();
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Member variables
+ ////////////////////////////////////////////////////////////////////////////////
+ private int _a; // Do not rename (binary serialization)
+ private short _b; // Do not rename (binary serialization)
+ private short _c; // Do not rename (binary serialization)
+ private byte _d; // Do not rename (binary serialization)
+ private byte _e; // Do not rename (binary serialization)
+ private byte _f; // Do not rename (binary serialization)
+ private byte _g; // Do not rename (binary serialization)
+ private byte _h; // Do not rename (binary serialization)
+ private byte _i; // Do not rename (binary serialization)
+ private byte _j; // Do not rename (binary serialization)
+ private byte _k; // Do not rename (binary serialization)
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Constructors
+ ////////////////////////////////////////////////////////////////////////////////
+
+ // Creates a new guid from an array of bytes.
+ public Guid(byte[] b) :
+ this(new ReadOnlySpan<byte>(b ?? throw new ArgumentNullException(nameof(b))))
+ {
+ }
+
+ // Creates a new guid from a read-only span.
+ public Guid(ReadOnlySpan<byte> b)
+ {
+ if (b.Length != 16)
+ throw new ArgumentException(SR.Format(SR.Arg_GuidArrayCtor, "16"), nameof(b));
+
+ _a = b[3] << 24 | b[2] << 16 | b[1] << 8 | b[0];
+ _b = (short)(b[5] << 8 | b[4]);
+ _c = (short)(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(nameof(d));
+ // Check that array is not too big
+ if (d.Length != 8)
+ throw new ArgumentException(SR.Format(SR.Arg_GuidArrayCtor, "8"), nameof(d));
+ 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;
+
+ private ParseFailureKind _failure;
+ private string _failureMessageID;
+ private object _failureMessageFormatArgument;
+ private string _failureArgumentName;
+ private Exception _innerException;
+
+ internal void Init(GuidParseThrowStyle canThrow)
+ {
+ _throwStyle = canThrow;
+ }
+
+ internal void SetFailure(Exception nativeException)
+ {
+ _failure = ParseFailureKind.NativeException;
+ _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)
+ {
+ Debug.Assert(failure != ParseFailureKind.NativeException, "ParseFailureKind.NativeException should not be used with this overload");
+ _failure = failure;
+ _failureMessageID = failureMessageID;
+ _failureMessageFormatArgument = failureMessageFormatArgument;
+ _failureArgumentName = failureArgumentName;
+ _innerException = innerException;
+ if (_throwStyle != GuidParseThrowStyle.None)
+ {
+ throw GetGuidParseException();
+ }
+ }
+
+ internal Exception GetGuidParseException()
+ {
+ switch (_failure)
+ {
+ case ParseFailureKind.ArgumentNull:
+ return new ArgumentNullException(_failureArgumentName, SR.GetResourceString(_failureMessageID));
+
+ case ParseFailureKind.FormatWithInnerException:
+ return new FormatException(SR.GetResourceString(_failureMessageID), _innerException);
+
+ case ParseFailureKind.FormatWithParameter:
+ return new FormatException(SR.Format(SR.GetResourceString(_failureMessageID), _failureMessageFormatArgument));
+
+ case ParseFailureKind.Format:
+ return new FormatException(SR.GetResourceString(_failureMessageID));
+
+ case ParseFailureKind.NativeException:
+ return _innerException;
+
+ default:
+ Debug.Assert(false, "Unknown GuidParseFailure: " + _failure);
+ return new FormatException(SR.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(nameof(g));
+ }
+ Contract.EndContractBlock();
+
+ 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(nameof(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 = Empty;
+ return false;
+ }
+ }
+
+ public static Guid ParseExact(string input, string format)
+ {
+ if (input == null)
+ throw new ArgumentNullException(nameof(input));
+
+ if (format == null)
+ throw new ArgumentNullException(nameof(format));
+
+ if (format.Length != 1)
+ {
+ // all acceptable format strings are of length 1
+ throw new FormatException(SR.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(SR.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 = 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 = Empty;
+ return false;
+ }
+
+ GuidResult parseResult = new GuidResult();
+ parseResult.Init(GuidParseThrowStyle.None);
+ if (TryParseGuid(input, style, ref parseResult))
+ {
+ result = parseResult._parsedGuid;
+ return true;
+ }
+ else
+ {
+ result = Empty;
+ return false;
+ }
+ }
+
+ private static bool TryParseGuid(string g, GuidStyles flags, ref GuidResult result)
+ {
+ if (g == null)
+ {
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_GuidUnrecognized));
+ return false;
+ }
+ string guidString = g.Trim(); //Remove Whitespace
+
+ if (guidString.Length == 0)
+ {
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.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, nameof(SR.Format_GuidUnrecognized));
+ return false;
+ }
+ }
+ else
+ {
+ if ((flags & GuidStyles.RequireDashes) != 0)
+ {
+ // dashes are required
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.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, nameof(SR.Format_GuidUnrecognized));
+ return false;
+ }
+ }
+ else
+ {
+ if ((flags & GuidStyles.RequireBraces) != 0)
+ {
+ // braces are required
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.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, nameof(SR.Format_GuidUnrecognized));
+ return false;
+ }
+ }
+ else
+ {
+ if ((flags & GuidStyles.RequireParenthesis) != 0)
+ {
+ // parenthesis are required
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.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, nameof(SR.Format_GuidUnrecognized), null, null, ex);
+ return false;
+ }
+ catch (ArgumentException ex)
+ {
+ result.SetFailure(ParseFailureKind.FormatWithInnerException, nameof(SR.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, nameof(SR.Format_GuidBrace));
+ return false;
+ }
+
+ // Check for '0x'
+ if (!IsHexPrefix(guidString, 1))
+ {
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.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, nameof(SR.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, nameof(SR.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, nameof(SR.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, nameof(SR.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, nameof(SR.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, nameof(SR.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, nameof(SR.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, nameof(SR.Format_GuidComma));
+ return false;
+ }
+ }
+ else // last case ends with '}', not ','
+ {
+ numLen = guidString.IndexOf('}', numStart) - numStart;
+ if (numLen <= 0)
+ {
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_GuidBraceAfterLastNumber));
+ return false;
+ }
+ }
+
+ // Read in the number
+ int signedNumber;
+ if (!StringToInt(guidString.Substring(numStart, numLen), -1, ParseNumbers.IsTight, out signedNumber, ref result))
+ {
+ return false;
+ }
+ uint number = (uint)signedNumber;
+
+ // check for overflow
+ if (number > 255)
+ {
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.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, nameof(SR.Format_GuidEndBrace));
+ return false;
+ }
+
+ // Check if we have extra characters at the end
+ if (numStart + numLen + 1 != guidString.Length - 1)
+ {
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.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, nameof(SR.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.ToUpperInvariant(ch);
+ if (upperCaseCh >= 'A' && upperCaseCh <= 'F')
+ {
+ continue;
+ }
+ }
+
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.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, ParseNumbers.NoSpace, out templ, ref result))
+ return false;
+
+ if (currentPos - startPos != 12)
+ {
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.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, nameof(SR.Format_GuidInvLen));
+ return false;
+ }
+ startPos = 1;
+ }
+ else if (guidString[0] == '(')
+ {
+ if (guidString.Length != 38 || guidString[37] != ')')
+ {
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_GuidInvLen));
+ return false;
+ }
+ startPos = 1;
+ }
+ else if (guidString.Length != 36)
+ {
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_GuidInvLen));
+ return false;
+ }
+
+ if (guidString[8 + startPos] != '-' ||
+ guidString[13 + startPos] != '-' ||
+ guidString[18 + startPos] != '-' ||
+ guidString[23 + startPos] != '-')
+ {
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.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, nameof(SR.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;
+ }
+
+ private static bool StringToShort(string str, int requiredLength, int flags, out short result, ref GuidResult parseResult)
+ {
+ int parsePos = 0;
+ return StringToShort(str, ref parsePos, requiredLength, flags, out result, ref parseResult);
+ }
+
+ private static bool StringToShort(string str, ref int parsePos, int requiredLength, int flags, out short result, ref GuidResult parseResult)
+ {
+ result = 0;
+ int x;
+ bool retValue = StringToInt(str, ref parsePos, requiredLength, flags, out x, ref parseResult);
+ result = (short)x;
+ return retValue;
+ }
+
+ private static bool StringToInt(string str, int requiredLength, int flags, out int result, ref GuidResult parseResult)
+ {
+ int parsePos = 0;
+ return StringToInt(str, ref parsePos, requiredLength, flags, out result, ref parseResult);
+ }
+
+ private static bool StringToInt(string str, ref int parsePos, int requiredLength, int flags, out int result, ref GuidResult parseResult)
+ {
+ result = 0;
+
+ int currStart = parsePos;
+ try
+ {
+ result = ParseNumbers.StringToInt(str, 16, flags, ref parsePos);
+ }
+ catch (OverflowException ex)
+ {
+ if (parseResult._throwStyle == GuidParseThrowStyle.All)
+ {
+ throw;
+ }
+ else if (parseResult._throwStyle == GuidParseThrowStyle.AllButOverflow)
+ {
+ throw new FormatException(SR.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 - currStart != requiredLength)
+ {
+ parseResult.SetFailure(ParseFailureKind.Format, nameof(SR.Format_GuidInvalidChar));
+ return false;
+ }
+ return true;
+ }
+
+ private static unsafe bool StringToLong(string str, ref int parsePos, int flags, out long result, ref GuidResult parseResult)
+ {
+ result = 0;
+
+ try
+ {
+ result = ParseNumbers.StringToLong(str, 16, flags, ref parsePos);
+ }
+ catch (OverflowException ex)
+ {
+ if (parseResult._throwStyle == GuidParseThrowStyle.All)
+ {
+ throw;
+ }
+ else if (parseResult._throwStyle == GuidParseThrowStyle.AllButOverflow)
+ {
+ throw new FormatException(SR.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.ToLowerInvariant(str[i + 1]) == 'x'))
+ return true;
+ else
+ return false;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private void WriteByteHelper(Span<byte> destination)
+ {
+ destination[0] = (byte)(_a);
+ destination[1] = (byte)(_a >> 8);
+ destination[2] = (byte)(_a >> 16);
+ destination[3] = (byte)(_a >> 24);
+ destination[4] = (byte)(_b);
+ destination[5] = (byte)(_b >> 8);
+ destination[6] = (byte)(_c);
+ destination[7] = (byte)(_c >> 8);
+ destination[8] = _d;
+ destination[9] = _e;
+ destination[10] = _f;
+ destination[11] = _g;
+ destination[12] = _h;
+ destination[13] = _i;
+ destination[14] = _j;
+ destination[15] = _k;
+ }
+
+ // Returns an unsigned byte array containing the GUID.
+ public byte[] ToByteArray()
+ {
+ var g = new byte[16];
+ WriteByteHelper(g);
+ return g;
+ }
+
+ // Returns whether bytes are sucessfully written to given span.
+ public bool TryWriteBytes(Span<byte> destination)
+ {
+ if (destination.Length < 16)
+ return false;
+
+ WriteByteHelper(destination);
+ return true;
+ }
+
+ // Returns the guid in "registry" format.
+ public override string ToString()
+ {
+ return ToString("D", null);
+ }
+
+ public override int GetHashCode()
+ {
+ // Simply XOR all the bits of the GUID 32 bits at a time.
+ return _a ^ Unsafe.Add(ref _a, 1) ^ Unsafe.Add(ref _a, 2) ^ Unsafe.Add(ref _a, 3);
+ }
+
+ // 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
+ return g._a == _a &&
+ Unsafe.Add(ref g._a, 1) == Unsafe.Add(ref _a, 1) &&
+ Unsafe.Add(ref g._a, 2) == Unsafe.Add(ref _a, 2) &&
+ Unsafe.Add(ref g._a, 3) == Unsafe.Add(ref _a, 3);
+ }
+
+ public bool Equals(Guid g)
+ {
+ // Now compare each of the elements
+ return g._a == _a &&
+ Unsafe.Add(ref g._a, 1) == Unsafe.Add(ref _a, 1) &&
+ Unsafe.Add(ref g._a, 2) == Unsafe.Add(ref _a, 2) &&
+ Unsafe.Add(ref g._a, 3) == Unsafe.Add(ref _a, 3);
+ }
+
+ 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(SR.Arg_MustBeGuid, nameof(value));
+ }
+ Guid g = (Guid)value;
+
+ if (g._a != _a)
+ {
+ return GetResult((uint)_a, (uint)g._a);
+ }
+
+ if (g._b != _b)
+ {
+ return GetResult((uint)_b, (uint)g._b);
+ }
+
+ if (g._c != _c)
+ {
+ return GetResult((uint)_c, (uint)g._c);
+ }
+
+ if (g._d != _d)
+ {
+ return GetResult(_d, g._d);
+ }
+
+ if (g._e != _e)
+ {
+ return GetResult(_e, g._e);
+ }
+
+ if (g._f != _f)
+ {
+ return GetResult(_f, g._f);
+ }
+
+ if (g._g != _g)
+ {
+ return GetResult(_g, g._g);
+ }
+
+ if (g._h != _h)
+ {
+ return GetResult(_h, g._h);
+ }
+
+ if (g._i != _i)
+ {
+ return GetResult(_i, g._i);
+ }
+
+ if (g._j != _j)
+ {
+ return GetResult(_j, g._j);
+ }
+
+ if (g._k != _k)
+ {
+ return GetResult(_k, g._k);
+ }
+
+ return 0;
+ }
+
+ public int CompareTo(Guid value)
+ {
+ if (value._a != _a)
+ {
+ return GetResult((uint)_a, (uint)value._a);
+ }
+
+ if (value._b != _b)
+ {
+ return GetResult((uint)_b, (uint)value._b);
+ }
+
+ if (value._c != _c)
+ {
+ return GetResult((uint)_c, (uint)value._c);
+ }
+
+ if (value._d != _d)
+ {
+ return GetResult(_d, value._d);
+ }
+
+ if (value._e != _e)
+ {
+ return GetResult(_e, value._e);
+ }
+
+ if (value._f != _f)
+ {
+ return GetResult(_f, value._f);
+ }
+
+ if (value._g != _g)
+ {
+ return GetResult(_g, value._g);
+ }
+
+ if (value._h != _h)
+ {
+ return GetResult(_h, value._h);
+ }
+
+ if (value._i != _i)
+ {
+ return GetResult(_i, value._i);
+ }
+
+ if (value._j != _j)
+ {
+ return GetResult(_j, value._j);
+ }
+
+ if (value._k != _k)
+ {
+ return GetResult(_k, value._k);
+ }
+
+ return 0;
+ }
+
+ public static bool operator ==(Guid a, Guid b)
+ {
+ // Now compare each of the elements
+ return a._a == b._a &&
+ Unsafe.Add(ref a._a, 1) == Unsafe.Add(ref b._a, 1) &&
+ Unsafe.Add(ref a._a, 2) == Unsafe.Add(ref b._a, 2) &&
+ Unsafe.Add(ref a._a, 3) == Unsafe.Add(ref b._a, 3);
+ }
+
+ public static bool operator !=(Guid a, Guid b)
+ {
+ // Now compare each of the elements
+ return a._a != b._a ||
+ Unsafe.Add(ref a._a, 1) != Unsafe.Add(ref b._a, 1) ||
+ Unsafe.Add(ref a._a, 2) != Unsafe.Add(ref b._a, 2) ||
+ Unsafe.Add(ref a._a, 3) != Unsafe.Add(ref b._a, 3);
+ }
+
+ public string ToString(string format)
+ {
+ return ToString(format, null);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static char HexToChar(int a)
+ {
+ a = a & 0xf;
+ return (char)((a > 9) ? a - 10 + 0x61 : a + 0x30);
+ }
+
+ unsafe private static int HexsToChars(char* guidChars, int a, int b)
+ {
+ guidChars[0] = HexToChar(a >> 4);
+ guidChars[1] = HexToChar(a);
+
+ guidChars[2] = HexToChar(b >> 4);
+ guidChars[3] = HexToChar(b);
+
+ return 4;
+ }
+
+ unsafe private static int HexsToCharsHexOutput(char* guidChars, int a, int b)
+ {
+ guidChars[0] = '0';
+ guidChars[1] = 'x';
+
+ guidChars[2] = HexToChar(a >> 4);
+ guidChars[3] = HexToChar(a);
+
+ guidChars[4] = ',';
+ guidChars[5] = '0';
+ guidChars[6] = 'x';
+
+ guidChars[7] = HexToChar(b >> 4);
+ guidChars[8] = HexToChar(b);
+
+ return 9;
+ }
+
+ // IFormattable interface
+ // We currently ignore provider
+ public string ToString(string format, IFormatProvider provider)
+ {
+ if (format == null || format.Length == 0)
+ format = "D";
+
+ // all acceptable format strings are of length 1
+ if (format.Length != 1)
+ throw new FormatException(SR.Format_InvalidGuidFormatSpecification);
+
+ int guidSize;
+ switch (format[0])
+ {
+ case 'D':
+ case 'd':
+ guidSize = 36;
+ break;
+ case 'N':
+ case 'n':
+ guidSize = 32;
+ break;
+ case 'B':
+ case 'b':
+ case 'P':
+ case 'p':
+ guidSize = 38;
+ break;
+ case 'X':
+ case 'x':
+ guidSize = 68;
+ break;
+ default:
+ throw new FormatException(SR.Format_InvalidGuidFormatSpecification);
+ }
+
+ string guidString = string.FastAllocateString(guidSize);
+
+ int bytesWritten;
+ bool result = TryFormat(new Span<char>(ref guidString.GetRawStringData(), guidString.Length), out bytesWritten, format);
+ Debug.Assert(result && bytesWritten == guidString.Length, "Formatting guid should have succeeded.");
+
+ return guidString;
+ }
+
+ // Returns whether the guid is successfully formatted as a span.
+ public bool TryFormat(Span<char> destination, out int charsWritten, string format = null)
+ {
+ if (format == null || format.Length == 0)
+ format = "D";
+
+ // all acceptable format strings are of length 1
+ if (format.Length != 1)
+ throw new FormatException(SR.Format_InvalidGuidFormatSpecification);
+
+ bool dash = true;
+ bool hex = false;
+ int braces = 0;
+
+ int guidSize;
+
+ switch (format[0])
+ {
+ case 'D':
+ case 'd':
+ guidSize = 36;
+ break;
+ case 'N':
+ case 'n':
+ dash = false;
+ guidSize = 32;
+ break;
+ case 'B':
+ case 'b':
+ braces = '{' + ('}' << 16);
+ guidSize = 38;
+ break;
+ case 'P':
+ case 'p':
+ braces = '(' + (')' << 16);
+ guidSize = 38;
+ break;
+ case 'X':
+ case 'x':
+ braces = '{' + ('}' << 16);
+ dash = false;
+ hex = true;
+ guidSize = 68;
+ break;
+ default:
+ throw new FormatException(SR.Format_InvalidGuidFormatSpecification);
+ }
+
+ if (destination.Length < guidSize)
+ {
+ charsWritten = 0;
+ return false;
+ }
+
+ unsafe
+ {
+ fixed (char* guidChars = &destination.DangerousGetPinnableReference())
+ {
+ char * p = guidChars;
+
+ if (braces != 0)
+ *p++ = (char)braces;
+
+ if (hex)
+ {
+ // {0xdddddddd,0xdddd,0xdddd,{0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd}}
+ *p++ = '0';
+ *p++ = 'x';
+ p += HexsToChars(p, _a >> 24, _a >> 16);
+ p += HexsToChars(p, _a >> 8, _a);
+ *p++ = ',';
+ *p++ = '0';
+ *p++ = 'x';
+ p += HexsToChars(p, _b >> 8, _b);
+ *p++ = ',';
+ *p++ = '0';
+ *p++ = 'x';
+ p += HexsToChars(p, _c >> 8, _c);
+ *p++ = ',';
+ *p++ = '{';
+ p += HexsToCharsHexOutput(p, _d, _e);
+ *p++ = ',';
+ p += HexsToCharsHexOutput(p, _f, _g);
+ *p++ = ',';
+ p += HexsToCharsHexOutput(p, _h, _i);
+ *p++ = ',';
+ p += HexsToCharsHexOutput(p, _j, _k);
+ *p++ = '}';
+ }
+ else
+ {
+ // [{|(]dddddddd[-]dddd[-]dddd[-]dddd[-]dddddddddddd[}|)]
+ p += HexsToChars(p, _a >> 24, _a >> 16);
+ p += HexsToChars(p, _a >> 8, _a);
+ if (dash)
+ *p++ = '-';
+ p += HexsToChars(p, _b >> 8, _b);
+ if (dash)
+ *p++ = '-';
+ p += HexsToChars(p, _c >> 8, _c);
+ if (dash)
+ *p++ = '-';
+ p += HexsToChars(p, _d, _e);
+ if (dash)
+ *p++ = '-';
+ p += HexsToChars(p, _f, _g);
+ p += HexsToChars(p, _h, _i);
+ p += HexsToChars(p, _j, _k);
+ }
+
+ if (braces != 0)
+ *p++ = (char)(braces >> 16);
+
+ Debug.Assert(p - guidChars == guidSize);
+ }
+ }
+
+ charsWritten = guidSize;
+ return true;
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/HResults.cs b/src/mscorlib/shared/System/HResults.cs
new file mode 100644
index 0000000000..ffc47d85bf
--- /dev/null
+++ b/src/mscorlib/shared/System/HResults.cs
@@ -0,0 +1,126 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//=============================================================================
+//
+//
+// Purpose: Define HResult constants. Every exception has one of these.
+//
+//
+//===========================================================================*/
+// Note: FACILITY_URT is defined as 0x13 (0x8013xxxx). Within that
+// range, 0x1yyy is for Runtime errors (used for Security, Metadata, etc).
+// In that subrange, 0x15zz and 0x16zz have been allocated for classlib-type
+// HResults. Also note that some of our HResults have to map to certain
+// COM HR's, etc.
+
+// Reflection will use 0x1600 -> 0x161f. IO will use 0x1620 -> 0x163f.
+// Security will use 0x1640 -> 0x165f
+
+
+using System;
+
+namespace System
+{
+ internal static partial class HResults
+ {
+ internal const int COR_E_ABANDONEDMUTEX = unchecked((int)0x8013152D);
+ internal const int COR_E_AMBIGUOUSMATCH = unchecked((int)0x8000211D);
+ internal const int COR_E_APPDOMAINUNLOADED = unchecked((int)0x80131014);
+ internal const int COR_E_APPLICATION = unchecked((int)0x80131600);
+ internal const int COR_E_ARGUMENT = unchecked((int)0x80070057);
+ internal const int COR_E_ARGUMENTOUTOFRANGE = unchecked((int)0x80131502);
+ internal const int COR_E_ARITHMETIC = unchecked((int)0x80070216);
+ internal const int COR_E_ARRAYTYPEMISMATCH = unchecked((int)0x80131503);
+ internal const int COR_E_BADEXEFORMAT = unchecked((int)0x800700C1);
+ internal const int COR_E_BADIMAGEFORMAT = unchecked((int)0x8007000B);
+ internal const int COR_E_CANNOTUNLOADAPPDOMAIN = unchecked((int)0x80131015);
+ internal const int COR_E_COMEMULATE = unchecked((int)0x80131535);
+ internal const int COR_E_CONTEXTMARSHAL = unchecked((int)0x80131504);
+ internal const int COR_E_CUSTOMATTRIBUTEFORMAT = unchecked((int)0x80131605);
+ internal const int COR_E_DATAMISALIGNED = unchecked((int)0x80131541);
+ internal const int COR_E_DIRECTORYNOTFOUND = unchecked((int)0x80070003);
+ internal const int COR_E_DIVIDEBYZERO = unchecked((int)0x80020012); // DISP_E_DIVBYZERO
+ internal const int COR_E_DLLNOTFOUND = unchecked((int)0x80131524);
+ internal const int COR_E_DUPLICATEWAITOBJECT = unchecked((int)0x80131529);
+ internal const int COR_E_ENDOFSTREAM = unchecked((int)0x80070026); // OS defined
+ internal const int COR_E_ENTRYPOINTNOTFOUND = unchecked((int)0x80131523);
+ internal const int COR_E_EXCEPTION = unchecked((int)0x80131500);
+ internal const int COR_E_EXECUTIONENGINE = unchecked((int)0x80131506);
+ internal const int COR_E_FIELDACCESS = unchecked((int)0x80131507);
+ internal const int COR_E_FILELOAD = unchecked((int)0x80131621);
+ internal const int COR_E_FILENOTFOUND = unchecked((int)0x80070002);
+ internal const int COR_E_FORMAT = unchecked((int)0x80131537);
+ internal const int COR_E_HOSTPROTECTION = unchecked((int)0x80131640);
+ internal const int COR_E_INDEXOUTOFRANGE = unchecked((int)0x80131508);
+ internal const int COR_E_INSUFFICIENTEXECUTIONSTACK = unchecked((int)0x80131578);
+ internal const int COR_E_INSUFFICIENTMEMORY = unchecked((int)0x8013153D);
+ internal const int COR_E_INVALIDCAST = unchecked((int)0x80004002);
+ internal const int COR_E_INVALIDCOMOBJECT = unchecked((int)0x80131527);
+ internal const int COR_E_INVALIDFILTERCRITERIA = unchecked((int)0x80131601);
+ internal const int COR_E_INVALIDOLEVARIANTTYPE = unchecked((int)0x80131531);
+ internal const int COR_E_INVALIDOPERATION = unchecked((int)0x80131509);
+ internal const int COR_E_INVALIDPROGRAM = unchecked((int)0x8013153A);
+ internal const int COR_E_IO = unchecked((int)0x80131620);
+ internal const int COR_E_KEYNOTFOUND = unchecked((int)0x80131577);
+ internal const int COR_E_MARSHALDIRECTIVE = unchecked((int)0x80131535);
+ internal const int COR_E_MEMBERACCESS = unchecked((int)0x8013151A);
+ internal const int COR_E_METHODACCESS = unchecked((int)0x80131510);
+ internal const int COR_E_MISSINGFIELD = unchecked((int)0x80131511);
+ internal const int COR_E_MISSINGMANIFESTRESOURCE = unchecked((int)0x80131532);
+ internal const int COR_E_MISSINGMEMBER = unchecked((int)0x80131512);
+ internal const int COR_E_MISSINGMETHOD = unchecked((int)0x80131513);
+ internal const int COR_E_MISSINGSATELLITEASSEMBLY = unchecked((int)0x80131536);
+ internal const int COR_E_MULTICASTNOTSUPPORTED = unchecked((int)0x80131514);
+ internal const int COR_E_NOTFINITENUMBER = unchecked((int)0x80131528);
+ internal const int COR_E_NOTSUPPORTED = unchecked((int)0x80131515);
+ internal const int COR_E_NULLREFERENCE = unchecked((int)0x80004003);
+ internal const int COR_E_OBJECTDISPOSED = unchecked((int)0x80131622);
+ internal const int COR_E_OPERATIONCANCELED = unchecked((int)0x8013153B);
+ internal const int COR_E_OUTOFMEMORY = unchecked((int)0x8007000E);
+ internal const int COR_E_OVERFLOW = unchecked((int)0x80131516);
+ internal const int COR_E_PATHTOOLONG = unchecked((int)0x800700CE);
+ internal const int COR_E_PLATFORMNOTSUPPORTED = unchecked((int)0x80131539);
+ internal const int COR_E_RANK = unchecked((int)0x80131517);
+ internal const int COR_E_REFLECTIONTYPELOAD = unchecked((int)0x80131602);
+ internal const int COR_E_RUNTIMEWRAPPED = unchecked((int)0x8013153E);
+ internal const int COR_E_SAFEARRAYRANKMISMATCH = unchecked((int)0x80131538);
+ internal const int COR_E_SAFEARRAYTYPEMISMATCH = unchecked((int)0x80131533);
+ internal const int COR_E_SAFEHANDLEMISSINGATTRIBUTE = unchecked((int)0x80131623);
+ internal const int COR_E_SECURITY = unchecked((int)0x8013150A);
+ internal const int COR_E_SEMAPHOREFULL = unchecked((int)0x8013152B);
+ internal const int COR_E_SERIALIZATION = unchecked((int)0x8013150C);
+ internal const int COR_E_STACKOVERFLOW = unchecked((int)0x800703E9);
+ internal const int COR_E_SYNCHRONIZATIONLOCK = unchecked((int)0x80131518);
+ internal const int COR_E_SYSTEM = unchecked((int)0x80131501);
+ internal const int COR_E_TARGET = unchecked((int)0x80131603);
+ internal const int COR_E_TARGETINVOCATION = unchecked((int)0x80131604);
+ internal const int COR_E_TARGETPARAMCOUNT = unchecked((int)0x8002000E);
+ internal const int COR_E_THREADABORTED = unchecked((int)0x80131530);
+ internal const int COR_E_THREADINTERRUPTED = unchecked((int)0x80131519);
+ internal const int COR_E_THREADSTART = unchecked((int)0x80131525);
+ internal const int COR_E_THREADSTATE = unchecked((int)0x80131520);
+ internal const int COR_E_THREADSTOP = unchecked((int)0x80131521);
+ internal const int COR_E_TIMEOUT = unchecked((int)0x80131505);
+ internal const int COR_E_TYPEACCESS = unchecked((int)0x80131543);
+ internal const int COR_E_TYPEINITIALIZATION = unchecked((int)0x80131534);
+ internal const int COR_E_TYPELOAD = unchecked((int)0x80131522);
+ internal const int COR_E_TYPEUNLOADED = unchecked((int)0x80131013);
+ internal const int COR_E_UNAUTHORIZEDACCESS = unchecked((int)0x80070005);
+ internal const int COR_E_UNSUPPORTEDFORMAT = unchecked((int)0x80131523);
+ internal const int COR_E_VERIFICATION = unchecked((int)0x8013150D);
+ internal const int COR_E_WAITHANDLECANNOTBEOPENED = unchecked((int)0x8013152C);
+ internal const int DISP_E_OVERFLOW = unchecked((int)0x8002000A);
+ internal const int E_BOUNDS = unchecked((int)0x8000000B);
+ internal const int E_CHANGED_STATE = unchecked((int)0x8000000C);
+ internal const int E_FAIL = unchecked((int)0x80004005);
+ internal const int E_HANDLE = unchecked((int)0x80070006);
+ internal const int E_INVALIDARG = unchecked((int)0x80070057);
+ internal const int E_NOTIMPL = unchecked((int)0x80004001);
+ internal const int E_POINTER = unchecked((int)0x80004003);
+ internal const int ERROR_MRM_MAP_NOT_FOUND = unchecked((int)0x80073B1F);
+ internal const int RO_E_CLOSED = unchecked((int)0x80000013);
+ internal const int TYPE_E_TYPEMISMATCH = unchecked((int)0x80028CA0);
+ }
+}
diff --git a/src/mscorlib/shared/System/IO/BinaryWriter.cs b/src/mscorlib/shared/System/IO/BinaryWriter.cs
index 90b920854f..675e80922e 100644
--- a/src/mscorlib/shared/System/IO/BinaryWriter.cs
+++ b/src/mscorlib/shared/System/IO/BinaryWriter.cs
@@ -4,6 +4,7 @@
using System.Text;
using System.Diagnostics;
+using System.Buffers;
namespace System.IO
{
@@ -389,6 +390,41 @@ namespace System.IO
}
}
+ public virtual void Write(ReadOnlySpan<byte> value)
+ {
+ if (GetType() == typeof(BinaryWriter))
+ {
+ OutStream.Write(value);
+ }
+ else
+ {
+ byte[] buffer = ArrayPool<byte>.Shared.Rent(value.Length);
+ try
+ {
+ value.CopyTo(buffer);
+ Write(buffer, 0, value.Length);
+ }
+ finally
+ {
+ ArrayPool<byte>.Shared.Return(buffer);
+ }
+ }
+ }
+
+ public virtual void Write(ReadOnlySpan<char> value)
+ {
+ byte[] bytes = ArrayPool<byte>.Shared.Rent(_encoding.GetMaxByteCount(value.Length));
+ try
+ {
+ int bytesWritten = _encoding.GetBytes(value, bytes);
+ Write(bytes, 0, bytesWritten);
+ }
+ finally
+ {
+ ArrayPool<byte>.Shared.Return(bytes);
+ }
+ }
+
protected void Write7BitEncodedInt(int value)
{
// Write out an int 7 bits at a time. The high bit of the byte,
diff --git a/src/mscorlib/shared/System/IO/DirectoryNotFoundException.cs b/src/mscorlib/shared/System/IO/DirectoryNotFoundException.cs
index de09760fcb..87e610b86e 100644
--- a/src/mscorlib/shared/System/IO/DirectoryNotFoundException.cs
+++ b/src/mscorlib/shared/System/IO/DirectoryNotFoundException.cs
@@ -17,19 +17,19 @@ namespace System.IO
public DirectoryNotFoundException()
: base(SR.Arg_DirectoryNotFoundException)
{
- HResult = __HResults.COR_E_DIRECTORYNOTFOUND;
+ HResult = HResults.COR_E_DIRECTORYNOTFOUND;
}
public DirectoryNotFoundException(string message)
: base(message)
{
- HResult = __HResults.COR_E_DIRECTORYNOTFOUND;
+ HResult = HResults.COR_E_DIRECTORYNOTFOUND;
}
public DirectoryNotFoundException(string message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_DIRECTORYNOTFOUND;
+ HResult = HResults.COR_E_DIRECTORYNOTFOUND;
}
protected DirectoryNotFoundException(SerializationInfo info, StreamingContext context)
diff --git a/src/mscorlib/shared/System/IO/DisableMediaInsertionPrompt.cs b/src/mscorlib/shared/System/IO/DisableMediaInsertionPrompt.cs
new file mode 100644
index 0000000000..aa10e8d883
--- /dev/null
+++ b/src/mscorlib/shared/System/IO/DisableMediaInsertionPrompt.cs
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.IO
+{
+ /// <summary>
+ /// Simple wrapper to safely disable the normal media insertion prompt for
+ /// removable media (floppies, cds, memory cards, etc.)
+ /// </summary>
+ /// <remarks>
+ /// Note that removable media file systems lazily load. After starting the OS
+ /// they won't be loaded until you have media in the drive- and as such the
+ /// prompt won't happen. You have to have had media in at least once to get
+ /// the file system to load and then have removed it.
+ /// </remarks>
+ internal struct DisableMediaInsertionPrompt : IDisposable
+ {
+ private bool _disableSuccess;
+ private uint _oldMode;
+
+ public static DisableMediaInsertionPrompt Create()
+ {
+ DisableMediaInsertionPrompt prompt = new DisableMediaInsertionPrompt();
+ prompt._disableSuccess = Interop.Kernel32.SetThreadErrorMode(Interop.Kernel32.SEM_FAILCRITICALERRORS, out prompt._oldMode);
+ return prompt;
+ }
+
+ public void Dispose()
+ {
+ uint ignore;
+ if (_disableSuccess)
+ Interop.Kernel32.SetThreadErrorMode(_oldMode, out ignore);
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/IO/DriveNotFoundException.cs b/src/mscorlib/shared/System/IO/DriveNotFoundException.cs
new file mode 100644
index 0000000000..c0f8c55af8
--- /dev/null
+++ b/src/mscorlib/shared/System/IO/DriveNotFoundException.cs
@@ -0,0 +1,35 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.Serialization;
+
+namespace System.IO
+{
+ //Thrown when trying to access a drive that is not available.
+ internal class DriveNotFoundException : IOException
+ {
+ public DriveNotFoundException()
+ : base(SR.Arg_DriveNotFoundException)
+ {
+ HResult = HResults.COR_E_DIRECTORYNOTFOUND;
+ }
+
+ public DriveNotFoundException(string message)
+ : base(message)
+ {
+ HResult = HResults.COR_E_DIRECTORYNOTFOUND;
+ }
+
+ public DriveNotFoundException(string message, Exception innerException)
+ : base(message, innerException)
+ {
+ HResult = HResults.COR_E_DIRECTORYNOTFOUND;
+ }
+
+ protected DriveNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ throw new PlatformNotSupportedException();
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/IO/EndOfStreamException.cs b/src/mscorlib/shared/System/IO/EndOfStreamException.cs
index 68e1b2c882..ee37818dc5 100644
--- a/src/mscorlib/shared/System/IO/EndOfStreamException.cs
+++ b/src/mscorlib/shared/System/IO/EndOfStreamException.cs
@@ -11,19 +11,19 @@ namespace System.IO
public EndOfStreamException()
: base(SR.Arg_EndOfStreamException)
{
- HResult = __HResults.COR_E_ENDOFSTREAM;
+ HResult = HResults.COR_E_ENDOFSTREAM;
}
public EndOfStreamException(string message)
: base(message)
{
- HResult = __HResults.COR_E_ENDOFSTREAM;
+ HResult = HResults.COR_E_ENDOFSTREAM;
}
public EndOfStreamException(string message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_ENDOFSTREAM;
+ HResult = HResults.COR_E_ENDOFSTREAM;
}
protected EndOfStreamException(SerializationInfo info, StreamingContext context)
diff --git a/src/mscorlib/shared/System/IO/FileLoadException.cs b/src/mscorlib/shared/System/IO/FileLoadException.cs
index 6fdf2d58cf..b126424c22 100644
--- a/src/mscorlib/shared/System/IO/FileLoadException.cs
+++ b/src/mscorlib/shared/System/IO/FileLoadException.cs
@@ -11,31 +11,31 @@ namespace System.IO
public FileLoadException()
: base(SR.IO_FileLoad)
{
- HResult = __HResults.COR_E_FILELOAD;
+ HResult = HResults.COR_E_FILELOAD;
}
public FileLoadException(string message)
: base(message)
{
- HResult = __HResults.COR_E_FILELOAD;
+ HResult = HResults.COR_E_FILELOAD;
}
public FileLoadException(string message, Exception inner)
: base(message, inner)
{
- HResult = __HResults.COR_E_FILELOAD;
+ HResult = HResults.COR_E_FILELOAD;
}
public FileLoadException(string message, string fileName) : base(message)
{
- HResult = __HResults.COR_E_FILELOAD;
+ HResult = HResults.COR_E_FILELOAD;
FileName = fileName;
}
public FileLoadException(string message, string fileName, Exception inner)
: base(message, inner)
{
- HResult = __HResults.COR_E_FILELOAD;
+ HResult = HResults.COR_E_FILELOAD;
FileName = fileName;
}
diff --git a/src/mscorlib/shared/System/IO/FileNotFoundException.cs b/src/mscorlib/shared/System/IO/FileNotFoundException.cs
index 374c976055..dc1ccf577a 100644
--- a/src/mscorlib/shared/System/IO/FileNotFoundException.cs
+++ b/src/mscorlib/shared/System/IO/FileNotFoundException.cs
@@ -12,32 +12,32 @@ namespace System.IO
public FileNotFoundException()
: base(SR.IO_FileNotFound)
{
- HResult = __HResults.COR_E_FILENOTFOUND;
+ HResult = HResults.COR_E_FILENOTFOUND;
}
public FileNotFoundException(string message)
: base(message)
{
- HResult = __HResults.COR_E_FILENOTFOUND;
+ HResult = HResults.COR_E_FILENOTFOUND;
}
public FileNotFoundException(string message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_FILENOTFOUND;
+ HResult = HResults.COR_E_FILENOTFOUND;
}
public FileNotFoundException(string message, string fileName)
: base(message)
{
- HResult = __HResults.COR_E_FILENOTFOUND;
+ HResult = HResults.COR_E_FILENOTFOUND;
FileName = fileName;
}
public FileNotFoundException(string message, string fileName, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_FILENOTFOUND;
+ HResult = HResults.COR_E_FILENOTFOUND;
FileName = fileName;
}
@@ -55,7 +55,7 @@ namespace System.IO
if (_message == null)
{
if ((FileName == null) &&
- (HResult == System.__HResults.COR_E_EXCEPTION))
+ (HResult == System.HResults.COR_E_EXCEPTION))
_message = SR.IO_FileNotFound;
else if (FileName != null)
diff --git a/src/mscorlib/shared/System/IO/FileStream.Unix.cs b/src/mscorlib/shared/System/IO/FileStream.Unix.cs
index ad68a001cf..8499595361 100644
--- a/src/mscorlib/shared/System/IO/FileStream.Unix.cs
+++ b/src/mscorlib/shared/System/IO/FileStream.Unix.cs
@@ -286,13 +286,20 @@ namespace System.IO
}
}
+ private void FlushWriteBufferForWriteByte()
+ {
+ _asyncState?.Wait();
+ try { FlushWriteBuffer(); }
+ finally { _asyncState?.Release(); }
+ }
+
/// <summary>Writes any data in the write buffer to the underlying stream and resets the buffer.</summary>
private void FlushWriteBuffer()
{
AssertBufferInvariants();
if (_writePos > 0)
{
- WriteNative(GetBuffer(), 0, _writePos);
+ WriteNative(new ReadOnlySpan<byte>(GetBuffer(), 0, _writePos));
_writePos = 0;
}
}
@@ -375,44 +382,7 @@ namespace System.IO
}
/// <summary>Reads a block of bytes from the stream and writes the data in a given buffer.</summary>
- /// <param name="array">
- /// When this method returns, contains the specified byte array with the values between offset and
- /// (offset + count - 1) replaced by the bytes read from the current source.
- /// </param>
- /// <param name="offset">The byte offset in array at which the read bytes will be placed.</param>
- /// <param name="count">The maximum number of bytes to read. </param>
- /// <returns>
- /// The total number of bytes read into the buffer. This might be less than the number of bytes requested
- /// if that number of bytes are not currently available, or zero if the end of the stream is reached.
- /// </returns>
- public override int Read(byte[] array, int offset, int count)
- {
- ValidateReadWriteArgs(array, offset, count);
-
- if (_useAsyncIO)
- {
- _asyncState.Wait();
- try { return ReadCore(array, offset, count); }
- finally { _asyncState.Release(); }
- }
- else
- {
- return ReadCore(array, offset, count);
- }
- }
-
- /// <summary>Reads a block of bytes from the stream and writes the data in a given buffer.</summary>
- /// <param name="array">
- /// When this method returns, contains the specified byte array with the values between offset and
- /// (offset + count - 1) replaced by the bytes read from the current source.
- /// </param>
- /// <param name="offset">The byte offset in array at which the read bytes will be placed.</param>
- /// <param name="count">The maximum number of bytes to read. </param>
- /// <returns>
- /// The total number of bytes read into the buffer. This might be less than the number of bytes requested
- /// if that number of bytes are not currently available, or zero if the end of the stream is reached.
- /// </returns>
- private int ReadCore(byte[] array, int offset, int count)
+ private int ReadSpan(Span<byte> destination)
{
PrepareForReading();
@@ -429,16 +399,16 @@ namespace System.IO
// If we're not able to seek, then we're not able to rewind the stream (i.e. flushing
// a read buffer), in which case we don't want to use a read buffer. Similarly, if
// the user has asked for more data than we can buffer, we also want to skip the buffer.
- if (!CanSeek || (count >= _bufferLength))
+ if (!CanSeek || (destination.Length >= _bufferLength))
{
// Read directly into the user's buffer
_readPos = _readLength = 0;
- return ReadNative(array, offset, count);
+ return ReadNative(destination);
}
else
{
// Read into our buffer.
- _readLength = numBytesAvailable = ReadNative(GetBuffer(), 0, _bufferLength);
+ _readLength = numBytesAvailable = ReadNative(GetBuffer());
_readPos = 0;
if (numBytesAvailable == 0)
{
@@ -454,8 +424,8 @@ namespace System.IO
// Now that we know there's data in the buffer, read from it into the user's buffer.
Debug.Assert(numBytesAvailable > 0, "Data must be in the buffer to be here");
- int bytesRead = Math.Min(numBytesAvailable, count);
- Buffer.BlockCopy(GetBuffer(), _readPos, array, offset, bytesRead);
+ int bytesRead = Math.Min(numBytesAvailable, destination.Length);
+ new Span<byte>(GetBuffer(), _readPos, bytesRead).CopyTo(destination);
_readPos += bytesRead;
// We may not have had enough data in the buffer to completely satisfy the user's request.
@@ -466,38 +436,33 @@ namespace System.IO
// behavior, we do the same thing here on Unix. Note that we may still get less the requested
// amount, as the OS may give us back fewer than we request, either due to reaching the end of
// file, or due to its own whims.
- if (!readFromOS && bytesRead < count)
+ if (!readFromOS && bytesRead < destination.Length)
{
- Debug.Assert(_readPos == _readLength, "bytesToRead should only be < count if numBytesAvailable < count");
+ Debug.Assert(_readPos == _readLength, "bytesToRead should only be < destination.Length if numBytesAvailable < destination.Length");
_readPos = _readLength = 0; // no data left in the read buffer
- bytesRead += ReadNative(array, offset + bytesRead, count - bytesRead);
+ bytesRead += ReadNative(destination.Slice(bytesRead));
}
return bytesRead;
}
- /// <summary>Unbuffered, reads a block of bytes from the stream and writes the data in a given buffer.</summary>
- /// <param name="array">
- /// When this method returns, contains the specified byte array with the values between offset and
- /// (offset + count - 1) replaced by the bytes read from the current source.
- /// </param>
- /// <param name="offset">The byte offset in array at which the read bytes will be placed.</param>
- /// <param name="count">The maximum number of bytes to read. </param>
+ /// <summary>Unbuffered, reads a block of bytes from the file handle into the given buffer.</summary>
+ /// <param name="buffer">The buffer into which data from the file is read.</param>
/// <returns>
/// The total number of bytes read into the buffer. This might be less than the number of bytes requested
/// if that number of bytes are not currently available, or zero if the end of the stream is reached.
/// </returns>
- private unsafe int ReadNative(byte[] array, int offset, int count)
+ private unsafe int ReadNative(Span<byte> buffer)
{
FlushWriteBuffer(); // we're about to read; dump the write buffer
VerifyOSHandlePosition();
int bytesRead;
- fixed (byte* bufPtr = array)
+ fixed (byte* bufPtr = &buffer.DangerousGetPinnableReference())
{
- bytesRead = CheckFileCall(Interop.Sys.Read(_fileHandle, bufPtr + offset, count));
- Debug.Assert(bytesRead <= count);
+ bytesRead = CheckFileCall(Interop.Sys.Read(_fileHandle, bufPtr, buffer.Length));
+ Debug.Assert(bytesRead <= buffer.Length);
}
_filePosition += bytesRead;
return bytesRead;
@@ -507,135 +472,97 @@ namespace System.IO
/// Asynchronously reads a sequence of bytes from the current stream and advances
/// the position within the stream by the number of bytes read.
/// </summary>
- /// <param name="buffer">The buffer to write the data into.</param>
- /// <param name="offset">The byte offset in buffer at which to begin writing data from the stream.</param>
- /// <param name="count">The maximum number of bytes to read.</param>
+ /// <param name="destination">The buffer to write the data into.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
+ /// <param name="synchronousResult">If the operation completes synchronously, the number of bytes read.</param>
/// <returns>A task that represents the asynchronous read operation.</returns>
- private Task<int> ReadAsyncInternal(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ private Task<int> ReadAsyncInternal(Memory<byte> destination, CancellationToken cancellationToken, out int synchronousResult)
{
- if (_useAsyncIO)
+ Debug.Assert(_useAsyncIO);
+
+ if (!CanRead) // match Windows behavior; this gets thrown synchronously
{
- if (!CanRead) // match Windows behavior; this gets thrown synchronously
- {
- throw Error.GetReadNotSupported();
- }
+ throw Error.GetReadNotSupported();
+ }
- // Serialize operations using the semaphore.
- Task waitTask = _asyncState.WaitAsync();
+ // Serialize operations using the semaphore.
+ Task waitTask = _asyncState.WaitAsync();
- // If we got ownership immediately, and if there's enough data in our buffer
- // to satisfy the full request of the caller, hand back the buffered data.
- // While it would be a legal implementation of the Read contract, we don't
- // hand back here less than the amount requested so as to match the behavior
- // in ReadCore that will make a native call to try to fulfill the remainder
- // of the request.
- if (waitTask.Status == TaskStatus.RanToCompletion)
+ // If we got ownership immediately, and if there's enough data in our buffer
+ // to satisfy the full request of the caller, hand back the buffered data.
+ // While it would be a legal implementation of the Read contract, we don't
+ // hand back here less than the amount requested so as to match the behavior
+ // in ReadCore that will make a native call to try to fulfill the remainder
+ // of the request.
+ if (waitTask.Status == TaskStatus.RanToCompletion)
+ {
+ int numBytesAvailable = _readLength - _readPos;
+ if (numBytesAvailable >= destination.Length)
{
- int numBytesAvailable = _readLength - _readPos;
- if (numBytesAvailable >= count)
+ try
{
- try
- {
- PrepareForReading();
-
- Buffer.BlockCopy(GetBuffer(), _readPos, buffer, offset, count);
- _readPos += count;
-
- return _asyncState._lastSuccessfulReadTask != null && _asyncState._lastSuccessfulReadTask.Result == count ?
- _asyncState._lastSuccessfulReadTask :
- (_asyncState._lastSuccessfulReadTask = Task.FromResult(count));
- }
- catch (Exception exc)
- {
- return Task.FromException<int>(exc);
- }
- finally
- {
- _asyncState.Release();
- }
- }
- }
+ PrepareForReading();
- // Otherwise, issue the whole request asynchronously.
- _asyncState.Update(buffer, offset, count);
- return waitTask.ContinueWith((t, s) =>
- {
- // The options available on Unix for writing asynchronously to an arbitrary file
- // handle typically amount to just using another thread to do the synchronous write,
- // which is exactly what this implementation does. This does mean there are subtle
- // differences in certain FileStream behaviors between Windows and Unix when multiple
- // asynchronous operations are issued against the stream to execute concurrently; on
- // Unix the operations will be serialized due to the usage of a semaphore, but the
- // position /length information won't be updated until after the write has completed,
- // whereas on Windows it may happen before the write has completed.
-
- Debug.Assert(t.Status == TaskStatus.RanToCompletion);
- var thisRef = (FileStream)s;
- try
+ new Span<byte>(GetBuffer(), _readPos, destination.Length).CopyTo(destination.Span);
+ _readPos += destination.Length;
+
+ synchronousResult = destination.Length;
+ return null;
+ }
+ catch (Exception exc)
{
- byte[] b = thisRef._asyncState._buffer;
- thisRef._asyncState._buffer = null; // remove reference to user's buffer
- return thisRef.ReadCore(b, thisRef._asyncState._offset, thisRef._asyncState._count);
+ synchronousResult = 0;
+ return Task.FromException<int>(exc);
}
- finally { thisRef._asyncState.Release(); }
- }, this, CancellationToken.None, TaskContinuationOptions.DenyChildAttach, TaskScheduler.Default);
- }
- else
- {
- return base.ReadAsync(buffer, offset, count, cancellationToken);
+ finally
+ {
+ _asyncState.Release();
+ }
+ }
}
- }
- /// <summary>
- /// Reads a byte from the stream and advances the position within the stream
- /// by one byte, or returns -1 if at the end of the stream.
- /// </summary>
- /// <returns>The unsigned byte cast to an Int32, or -1 if at the end of the stream.</returns>
- public override int ReadByte()
- {
- if (_useAsyncIO)
- {
- _asyncState.Wait();
- try { return ReadByteCore(); }
- finally { _asyncState.Release(); }
- }
- else
+ // Otherwise, issue the whole request asynchronously.
+ synchronousResult = 0;
+ _asyncState.Memory = destination;
+ return waitTask.ContinueWith((t, s) =>
{
- return ReadByteCore();
- }
+ // The options available on Unix for writing asynchronously to an arbitrary file
+ // handle typically amount to just using another thread to do the synchronous write,
+ // which is exactly what this implementation does. This does mean there are subtle
+ // differences in certain FileStream behaviors between Windows and Unix when multiple
+ // asynchronous operations are issued against the stream to execute concurrently; on
+ // Unix the operations will be serialized due to the usage of a semaphore, but the
+ // position /length information won't be updated until after the write has completed,
+ // whereas on Windows it may happen before the write has completed.
+
+ Debug.Assert(t.Status == TaskStatus.RanToCompletion);
+ var thisRef = (FileStream)s;
+ try
+ {
+ Memory<byte> memory = thisRef._asyncState.Memory;
+ thisRef._asyncState.Memory = default(Memory<byte>);
+ return thisRef.ReadSpan(memory.Span);
+ }
+ finally { thisRef._asyncState.Release(); }
+ }, this, CancellationToken.None, TaskContinuationOptions.DenyChildAttach, TaskScheduler.Default);
}
- /// <summary>Writes a block of bytes to the file stream.</summary>
- /// <param name="array">The buffer containing data to write to the stream.</param>
- /// <param name="offset">The zero-based byte offset in array from which to begin copying bytes to the stream.</param>
- /// <param name="count">The maximum number of bytes to write.</param>
- public override void Write(byte[] array, int offset, int count)
+ /// <summary>Reads from the file handle into the buffer, overwriting anything in it.</summary>
+ private int FillReadBufferForReadByte()
{
- ValidateReadWriteArgs(array, offset, count);
-
- if (_useAsyncIO)
- {
- _asyncState.Wait();
- try { WriteCore(array, offset, count); }
- finally { _asyncState.Release(); }
- }
- else
- {
- WriteCore(array, offset, count);
- }
+ _asyncState?.Wait();
+ try { return ReadNative(_buffer); }
+ finally { _asyncState?.Release(); }
}
/// <summary>Writes a block of bytes to the file stream.</summary>
- /// <param name="array">The buffer containing data to write to the stream.</param>
- /// <param name="offset">The zero-based byte offset in array from which to begin copying bytes to the stream.</param>
- /// <param name="count">The maximum number of bytes to write.</param>
- private void WriteCore(byte[] array, int offset, int count)
+ /// <param name="source">The buffer containing data to write to the stream.</param>
+ private void WriteSpan(ReadOnlySpan<byte> source)
{
PrepareForWriting();
// If no data is being written, nothing more to do.
- if (count == 0)
+ if (source.Length == 0)
{
return;
}
@@ -647,21 +574,17 @@ namespace System.IO
// If there's space remaining in the buffer, then copy as much as
// we can from the user's buffer into ours.
int spaceRemaining = _bufferLength - _writePos;
- if (spaceRemaining > 0)
+ if (spaceRemaining >= source.Length)
{
- int bytesToCopy = Math.Min(spaceRemaining, count);
- Buffer.BlockCopy(array, offset, GetBuffer(), _writePos, bytesToCopy);
- _writePos += bytesToCopy;
-
- // If we've successfully copied all of the user's data, we're done.
- if (count == bytesToCopy)
- {
- return;
- }
-
- // Otherwise, keep track of how much more data needs to be handled.
- offset += bytesToCopy;
- count -= bytesToCopy;
+ source.CopyTo(new Span<byte>(GetBuffer()).Slice(_writePos));
+ _writePos += source.Length;
+ return;
+ }
+ else if (spaceRemaining > 0)
+ {
+ source.Slice(0, spaceRemaining).CopyTo(new Span<byte>(GetBuffer()).Slice(_writePos));
+ _writePos += spaceRemaining;
+ source = source.Slice(spaceRemaining);
}
// At this point, the buffer is full, so flush it out.
@@ -672,35 +595,33 @@ namespace System.IO
// the user's looking to write more data than we can store in the buffer),
// skip the buffer. Otherwise, put the remaining data into the buffer.
Debug.Assert(_writePos == 0);
- if (count >= _bufferLength)
+ if (source.Length >= _bufferLength)
{
- WriteNative(array, offset, count);
+ WriteNative(source);
}
else
{
- Buffer.BlockCopy(array, offset, GetBuffer(), _writePos, count);
- _writePos = count;
+ source.CopyTo(new Span<byte>(GetBuffer()));
+ _writePos = source.Length;
}
}
/// <summary>Unbuffered, writes a block of bytes to the file stream.</summary>
- /// <param name="array">The buffer containing data to write to the stream.</param>
- /// <param name="offset">The zero-based byte offset in array from which to begin copying bytes to the stream.</param>
- /// <param name="count">The maximum number of bytes to write.</param>
- private unsafe void WriteNative(byte[] array, int offset, int count)
+ /// <param name="source">The buffer containing data to write to the stream.</param>
+ private unsafe void WriteNative(ReadOnlySpan<byte> source)
{
VerifyOSHandlePosition();
- fixed (byte* bufPtr = array)
+ fixed (byte* bufPtr = &source.DangerousGetPinnableReference())
{
+ int offset = 0;
+ int count = source.Length;
while (count > 0)
{
int bytesWritten = CheckFileCall(Interop.Sys.Write(_fileHandle, bufPtr + offset, count));
- Debug.Assert(bytesWritten <= count);
-
_filePosition += bytesWritten;
- count -= bytesWritten;
offset += bytesWritten;
+ count -= bytesWritten;
}
}
}
@@ -710,103 +631,77 @@ namespace System.IO
/// the current position within this stream by the number of bytes written, and
/// monitors cancellation requests.
/// </summary>
- /// <param name="buffer">The buffer to write data from.</param>
- /// <param name="offset">The zero-based byte offset in buffer from which to begin copying bytes to the stream.</param>
- /// <param name="count">The maximum number of bytes to write.</param>
+ /// <param name="source">The buffer to write data from.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A task that represents the asynchronous write operation.</returns>
- private Task WriteAsyncInternal(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ private Task WriteAsyncInternal(ReadOnlyMemory<byte> source, CancellationToken cancellationToken)
{
+ Debug.Assert(_useAsyncIO);
+
if (cancellationToken.IsCancellationRequested)
return Task.FromCanceled(cancellationToken);
if (_fileHandle.IsClosed)
throw Error.GetFileNotOpen();
- if (_useAsyncIO)
+ if (!CanWrite) // match Windows behavior; this gets thrown synchronously
{
- if (!CanWrite) // match Windows behavior; this gets thrown synchronously
- {
- throw Error.GetWriteNotSupported();
- }
+ throw Error.GetWriteNotSupported();
+ }
- // Serialize operations using the semaphore.
- Task waitTask = _asyncState.WaitAsync();
+ // Serialize operations using the semaphore.
+ Task waitTask = _asyncState.WaitAsync();
- // If we got ownership immediately, and if there's enough space in our buffer
- // to buffer the entire write request, then do so and we're done.
- if (waitTask.Status == TaskStatus.RanToCompletion)
+ // If we got ownership immediately, and if there's enough space in our buffer
+ // to buffer the entire write request, then do so and we're done.
+ if (waitTask.Status == TaskStatus.RanToCompletion)
+ {
+ int spaceRemaining = _bufferLength - _writePos;
+ if (spaceRemaining >= source.Length)
{
- int spaceRemaining = _bufferLength - _writePos;
- if (spaceRemaining >= count)
+ try
{
- try
- {
- PrepareForWriting();
-
- Buffer.BlockCopy(buffer, offset, GetBuffer(), _writePos, count);
- _writePos += count;
-
- return Task.CompletedTask;
- }
- catch (Exception exc)
- {
- return Task.FromException(exc);
- }
- finally
- {
- _asyncState.Release();
- }
- }
- }
+ PrepareForWriting();
- // Otherwise, issue the whole request asynchronously.
- _asyncState.Update(buffer, offset, count);
- return waitTask.ContinueWith((t, s) =>
- {
- // The options available on Unix for writing asynchronously to an arbitrary file
- // handle typically amount to just using another thread to do the synchronous write,
- // which is exactly what this implementation does. This does mean there are subtle
- // differences in certain FileStream behaviors between Windows and Unix when multiple
- // asynchronous operations are issued against the stream to execute concurrently; on
- // Unix the operations will be serialized due to the usage of a semaphore, but the
- // position /length information won't be updated until after the write has completed,
- // whereas on Windows it may happen before the write has completed.
-
- Debug.Assert(t.Status == TaskStatus.RanToCompletion);
- var thisRef = (FileStream)s;
- try
+ source.Span.CopyTo(new Span<byte>(GetBuffer(), _writePos, source.Length));
+ _writePos += source.Length;
+
+ return Task.CompletedTask;
+ }
+ catch (Exception exc)
{
- byte[] b = thisRef._asyncState._buffer;
- thisRef._asyncState._buffer = null; // remove reference to user's buffer
- thisRef.WriteCore(b, thisRef._asyncState._offset, thisRef._asyncState._count);
+ return Task.FromException(exc);
}
- finally { thisRef._asyncState.Release(); }
- }, this, CancellationToken.None, TaskContinuationOptions.DenyChildAttach, TaskScheduler.Default);
- }
- else
- {
- return base.WriteAsync(buffer, offset, count, cancellationToken);
+ finally
+ {
+ _asyncState.Release();
+ }
+ }
}
- }
- /// <summary>
- /// Writes a byte to the current position in the stream and advances the position
- /// within the stream by one byte.
- /// </summary>
- /// <param name="value">The byte to write to the stream.</param>
- public override void WriteByte(byte value) // avoids an array allocation in the base implementation
- {
- if (_useAsyncIO)
+ // Otherwise, issue the whole request asynchronously.
+ _asyncState.ReadOnlyMemory = source;
+ return waitTask.ContinueWith((t, s) =>
{
- _asyncState.Wait();
- try { WriteByteCore(value); }
- finally { _asyncState.Release(); }
- }
- else
- {
- WriteByteCore(value);
- }
+ // The options available on Unix for writing asynchronously to an arbitrary file
+ // handle typically amount to just using another thread to do the synchronous write,
+ // which is exactly what this implementation does. This does mean there are subtle
+ // differences in certain FileStream behaviors between Windows and Unix when multiple
+ // asynchronous operations are issued against the stream to execute concurrently; on
+ // Unix the operations will be serialized due to the usage of a semaphore, but the
+ // position/length information won't be updated until after the write has completed,
+ // whereas on Windows it may happen before the write has completed.
+
+ Debug.Assert(t.Status == TaskStatus.RanToCompletion);
+ var thisRef = (FileStream)s;
+ try
+ {
+ ReadOnlyMemory<byte> readOnlyMemory = thisRef._asyncState.ReadOnlyMemory;
+ thisRef._asyncState.ReadOnlyMemory = default(ReadOnlyMemory<byte>);
+ thisRef.WriteSpan(readOnlyMemory.Span);
+ }
+ finally { thisRef._asyncState.Release(); }
+ }, this, CancellationToken.None, TaskContinuationOptions.DenyChildAttach, TaskScheduler.Default);
}
/// <summary>Sets the current position of this stream to the given value.</summary>
@@ -907,25 +802,11 @@ namespace System.IO
/// <summary>State used when the stream is in async mode.</summary>
private sealed class AsyncState : SemaphoreSlim
{
- /// <summary>The caller's buffer currently being used by the active async operation.</summary>
- internal byte[] _buffer;
- /// <summary>The caller's offset currently being used by the active async operation.</summary>
- internal int _offset;
- /// <summary>The caller's count currently being used by the active async operation.</summary>
- internal int _count;
- /// <summary>The last task successfully, synchronously returned task from ReadAsync.</summary>
- internal Task<int> _lastSuccessfulReadTask;
+ internal ReadOnlyMemory<byte> ReadOnlyMemory;
+ internal Memory<byte> Memory;
/// <summary>Initialize the AsyncState.</summary>
internal AsyncState() : base(initialCount: 1, maxCount: 1) { }
-
- /// <summary>Sets the active buffer, offset, and count.</summary>
- internal void Update(byte[] buffer, int offset, int count)
- {
- _buffer = buffer;
- _offset = offset;
- _count = count;
- }
}
}
}
diff --git a/src/mscorlib/shared/System/IO/FileStream.Win32.cs b/src/mscorlib/shared/System/IO/FileStream.Win32.cs
index 61cd007895..4b75ad6dad 100644
--- a/src/mscorlib/shared/System/IO/FileStream.Win32.cs
+++ b/src/mscorlib/shared/System/IO/FileStream.Win32.cs
@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using Microsoft.Win32.SafeHandles;
-using System.Runtime.InteropServices;
namespace System.IO
{
@@ -11,6 +10,11 @@ namespace System.IO
{
private SafeFileHandle OpenHandle(FileMode mode, FileShare share, FileOptions options)
{
+ return CreateFileOpenHandle(mode, share, options);
+ }
+
+ private unsafe SafeFileHandle CreateFileOpenHandle(FileMode mode, FileShare share, FileOptions options)
+ {
Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share);
int fAccess =
@@ -30,44 +34,13 @@ namespace System.IO
// For mitigating local elevation of privilege attack through named pipes
// make sure we always call CreateFile with SECURITY_ANONYMOUS so that the
// named pipe server can't impersonate a high privileged client security context
+ // (note that this is the effective default on CreateFile2)
flagsAndAttributes |= (Interop.Kernel32.SecurityOptions.SECURITY_SQOS_PRESENT | Interop.Kernel32.SecurityOptions.SECURITY_ANONYMOUS);
- // Don't pop up a dialog for reading from an empty floppy drive
- uint oldMode;
- bool success = Interop.Kernel32.SetThreadErrorMode(Interop.Kernel32.SEM_FAILCRITICALERRORS, out oldMode);
- try
- {
- SafeFileHandle fileHandle = Interop.Kernel32.CreateFile(_path, fAccess, share, ref secAttrs, mode, flagsAndAttributes, IntPtr.Zero);
- fileHandle.IsAsync = _useAsyncIO;
-
- if (fileHandle.IsInvalid)
- {
- // Return a meaningful exception with the full path.
-
- // NT5 oddity - when trying to open "C:\" as a Win32FileStream,
- // we usually get ERROR_PATH_NOT_FOUND from the OS. We should
- // probably be consistent w/ every other directory.
- int errorCode = Marshal.GetLastWin32Error();
-
- if (errorCode == Interop.Errors.ERROR_PATH_NOT_FOUND && _path.Length == PathInternal.GetRootLength(_path))
- errorCode = Interop.Errors.ERROR_ACCESS_DENIED;
-
- throw Win32Marshal.GetExceptionForWin32Error(errorCode, _path);
- }
-
- int fileType = Interop.Kernel32.GetFileType(fileHandle);
- if (fileType != Interop.Kernel32.FileTypes.FILE_TYPE_DISK)
- {
- fileHandle.Dispose();
- throw new NotSupportedException(SR.NotSupported_FileStreamOnNonFiles);
- }
-
- return fileHandle;
- }
- finally
+ using (DisableMediaInsertionPrompt.Create())
{
- if (success)
- Interop.Kernel32.SetThreadErrorMode(oldMode, out oldMode);
+ return ValidateFileHandle(
+ Interop.Kernel32.CreateFile(_path, fAccess, share, ref secAttrs, mode, flagsAndAttributes, IntPtr.Zero));
}
}
}
diff --git a/src/mscorlib/shared/System/IO/FileStream.WinRT.cs b/src/mscorlib/shared/System/IO/FileStream.WinRT.cs
index b9a9f8a783..304088eea7 100644
--- a/src/mscorlib/shared/System/IO/FileStream.WinRT.cs
+++ b/src/mscorlib/shared/System/IO/FileStream.WinRT.cs
@@ -13,7 +13,7 @@ namespace System.IO
{
Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share);
- int fAccess =
+ int access =
((_access & FileAccess.Read) == FileAccess.Read ? GENERIC_READ : 0) |
((_access & FileAccess.Write) == FileAccess.Write ? GENERIC_WRITE : 0);
@@ -30,31 +30,15 @@ namespace System.IO
parameters.dwFileFlags = (uint)options;
parameters.lpSecurityAttributes = &secAttrs;
- SafeFileHandle fileHandle = Interop.Kernel32.CreateFile2(
- lpFileName: _path,
- dwDesiredAccess: fAccess,
- dwShareMode: share,
- dwCreationDisposition: mode,
- pCreateExParams: &parameters);
-
- fileHandle.IsAsync = _useAsyncIO;
-
- if (fileHandle.IsInvalid)
+ using (DisableMediaInsertionPrompt.Create())
{
- // Return a meaningful exception with the full path.
-
- // NT5 oddity - when trying to open "C:\" as a Win32FileStream,
- // we usually get ERROR_PATH_NOT_FOUND from the OS. We should
- // probably be consistent w/ every other directory.
- int errorCode = Marshal.GetLastWin32Error();
-
- if (errorCode == Interop.Errors.ERROR_PATH_NOT_FOUND && _path.Length == PathInternal.GetRootLength(_path))
- errorCode = Interop.Errors.ERROR_ACCESS_DENIED;
-
- throw Win32Marshal.GetExceptionForWin32Error(errorCode, _path);
+ return ValidateFileHandle(Interop.Kernel32.CreateFile2(
+ lpFileName: _path,
+ dwDesiredAccess: access,
+ dwShareMode: share,
+ dwCreationDisposition: mode,
+ pCreateExParams: ref parameters));
}
-
- return fileHandle;
}
}
}
diff --git a/src/mscorlib/shared/System/IO/FileStream.Windows.cs b/src/mscorlib/shared/System/IO/FileStream.Windows.cs
index cdf1cb092e..eec11b4b13 100644
--- a/src/mscorlib/shared/System/IO/FileStream.Windows.cs
+++ b/src/mscorlib/shared/System/IO/FileStream.Windows.cs
@@ -48,7 +48,6 @@ namespace System.IO
private static unsafe IOCompletionCallback s_ioCallback = FileStreamCompletionSource.IOCallback;
- private Task<int> _lastSynchronouslyCompletedTask = null; // cached task for read ops that complete synchronously
private Task _activeBufferOperation = null; // tracks in-progress async ops using the buffer
private PreAllocatedOverlapped _preallocatedOverlapped; // optimization for async ops to avoid per-op allocations
private FileStreamCompletionSource _currentOverlappedOwner; // async op currently using the preallocated overlapped
@@ -313,7 +312,7 @@ namespace System.IO
// If the buffer is already flushed, don't spin up the OS write
if (_writePos == 0) return Task.CompletedTask;
- Task flushTask = WriteInternalCoreAsync(GetBuffer(), 0, _writePos, cancellationToken);
+ Task flushTask = WriteAsyncInternalCore(new ReadOnlyMemory<byte>(GetBuffer(), 0, _writePos), cancellationToken);
_writePos = 0;
// Update the active buffer operation
@@ -324,6 +323,8 @@ namespace System.IO
return flushTask;
}
+ private void FlushWriteBufferForWriteByte() => FlushWriteBuffer();
+
// Writes are buffered. Anytime the buffer fills up
// (_writePos + delta > _bufferSize) or the buffer switches to reading
// and there is left over data (_writePos > 0), this function must be called.
@@ -355,7 +356,7 @@ namespace System.IO
}
else
{
- WriteCore(GetBuffer(), 0, _writePos);
+ WriteCore(new ReadOnlySpan<byte>(GetBuffer(), 0, _writePos));
}
_writePos = 0;
@@ -411,14 +412,9 @@ namespace System.IO
// accessing its fields by ref. This avoids a compiler warning.
private FileStreamCompletionSource CompareExchangeCurrentOverlappedOwner(FileStreamCompletionSource newSource, FileStreamCompletionSource existingSource) => Interlocked.CompareExchange(ref _currentOverlappedOwner, newSource, existingSource);
- public override int Read(byte[] array, int offset, int count)
- {
- ValidateReadWriteArgs(array, offset, count);
- return ReadCore(array, offset, count);
- }
-
- private int ReadCore(byte[] array, int offset, int count)
+ private int ReadSpan(Span<byte> destination)
{
+ Debug.Assert(!_useAsyncIO, "Must only be used when in synchronous mode");
Debug.Assert((_readPos == 0 && _readLength == 0 && _writePos >= 0) || (_writePos == 0 && _readPos <= _readLength),
"We're either reading or writing, but not both.");
@@ -430,23 +426,23 @@ namespace System.IO
{
if (!CanRead) throw Error.GetReadNotSupported();
if (_writePos > 0) FlushWriteBuffer();
- if (!CanSeek || (count >= _bufferLength))
+ if (!CanSeek || (destination.Length >= _bufferLength))
{
- n = ReadNative(array, offset, count);
+ n = ReadNative(destination);
// Throw away read buffer.
_readPos = 0;
_readLength = 0;
return n;
}
- n = ReadNative(GetBuffer(), 0, _bufferLength);
+ n = ReadNative(GetBuffer());
if (n == 0) return 0;
isBlocked = n < _bufferLength;
_readPos = 0;
_readLength = n;
}
// Now copy min of count or numBytesAvailable (i.e. near EOF) to array.
- if (n > count) n = count;
- Buffer.BlockCopy(GetBuffer(), _readPos, array, offset, n);
+ if (n > destination.Length) n = destination.Length;
+ new ReadOnlySpan<byte>(GetBuffer(), _readPos, n).CopyTo(destination);
_readPos += n;
// We may have read less than the number of bytes the user asked
@@ -466,10 +462,10 @@ namespace System.IO
// read some more from the underlying stream. However, if we got
// fewer bytes from the underlying stream than we asked for (i.e. we're
// probably blocked), don't ask for more bytes.
- if (n < count && !isBlocked)
+ if (n < destination.Length && !isBlocked)
{
Debug.Assert(_readPos == _readLength, "Read buffer should be empty!");
- int moreBytesRead = ReadNative(array, offset + n, count - n);
+ int moreBytesRead = ReadNative(destination.Slice(n));
n += moreBytesRead;
// We've just made our buffer inconsistent with our position
// pointer. We must throw away the read buffer.
@@ -482,28 +478,28 @@ namespace System.IO
}
[Conditional("DEBUG")]
- private void AssertCanRead(byte[] buffer, int offset, int count)
+ private void AssertCanRead()
{
Debug.Assert(!_fileHandle.IsClosed, "!_fileHandle.IsClosed");
Debug.Assert(CanRead, "CanRead");
- Debug.Assert(buffer != null, "buffer != null");
- Debug.Assert(_writePos == 0, "_writePos == 0");
- Debug.Assert(offset >= 0, "offset is negative");
- Debug.Assert(count >= 0, "count is negative");
}
- private unsafe int ReadNative(byte[] buffer, int offset, int count)
- {
- AssertCanRead(buffer, offset, count);
+ /// <summary>Reads from the file handle into the buffer, overwriting anything in it.</summary>
+ private int FillReadBufferForReadByte() =>
+ _useAsyncIO ?
+ ReadNativeAsync(new Memory<byte>(_buffer), 0, CancellationToken.None).GetAwaiter().GetResult() :
+ ReadNative(_buffer);
- if (_useAsyncIO)
- return ReadNativeAsync(buffer, offset, count, 0, CancellationToken.None).GetAwaiter().GetResult();
+ private unsafe int ReadNative(Span<byte> buffer)
+ {
+ Debug.Assert(!_useAsyncIO, $"{nameof(ReadNative)} doesn't work on asynchronous file streams.");
+ AssertCanRead();
// Make sure we are reading from the right spot
VerifyOSHandlePosition();
int errorCode = 0;
- int r = ReadFileNative(_fileHandle, buffer, offset, count, null, out errorCode);
+ int r = ReadFileNative(_fileHandle, buffer, null, out errorCode);
if (r == -1)
{
@@ -579,7 +575,6 @@ namespace System.IO
{
if (_readPos > 0)
{
- //Console.WriteLine("Seek: seeked for 0, adjusting buffer back by: "+_readPos+" _readLen: "+_readLen);
Buffer.BlockCopy(GetBuffer(), _readPos, GetBuffer(), 0, _readLength - _readPos);
_readLength -= _readPos;
_readPos = 0;
@@ -592,7 +587,6 @@ namespace System.IO
else if (oldPos - _readPos < pos && pos < oldPos + _readLength - _readPos)
{
int diff = (int)(pos - oldPos);
- //Console.WriteLine("Seek: diff was "+diff+", readpos was "+_readPos+" adjusting buffer - shrinking by "+ (_readPos + diff));
Buffer.BlockCopy(GetBuffer(), _readPos + diff, GetBuffer(), 0, _readLength - (_readPos + diff));
_readLength -= (_readPos + diff);
_readPos = 0;
@@ -646,9 +640,9 @@ namespace System.IO
_preallocatedOverlapped = new PreAllocatedOverlapped(s_ioCallback, this, _buffer);
}
- public override void Write(byte[] array, int offset, int count)
+ private void WriteSpan(ReadOnlySpan<byte> source)
{
- ValidateReadWriteArgs(array, offset, count);
+ Debug.Assert(!_useAsyncIO, "Must only be used when in synchronous mode");
if (_writePos == 0)
{
@@ -672,65 +666,56 @@ namespace System.IO
int numBytes = _bufferLength - _writePos; // space left in buffer
if (numBytes > 0)
{
- if (numBytes > count)
- numBytes = count;
- Buffer.BlockCopy(array, offset, GetBuffer(), _writePos, numBytes);
- _writePos += numBytes;
- if (count == numBytes) return;
- offset += numBytes;
- count -= numBytes;
+ if (numBytes >= source.Length)
+ {
+ source.CopyTo(new Span<byte>(GetBuffer()).Slice(_writePos));
+ _writePos += source.Length;
+ return;
+ }
+ else
+ {
+ source.Slice(0, numBytes).CopyTo(new Span<byte>(GetBuffer()).Slice(_writePos));
+ _writePos += numBytes;
+ source = source.Slice(numBytes);
+ }
}
// Reset our buffer. We essentially want to call FlushWrite
// without calling Flush on the underlying Stream.
- if (_useAsyncIO)
- {
- WriteInternalCoreAsync(GetBuffer(), 0, _writePos, CancellationToken.None).GetAwaiter().GetResult();
- }
- else
- {
- WriteCore(GetBuffer(), 0, _writePos);
- }
+ WriteCore(new ReadOnlySpan<byte>(GetBuffer(), 0, _writePos));
_writePos = 0;
}
+
// If the buffer would slow writes down, avoid buffer completely.
- if (count >= _bufferLength)
+ if (source.Length >= _bufferLength)
{
Debug.Assert(_writePos == 0, "FileStream cannot have buffered data to write here! Your stream will be corrupted.");
- WriteCore(array, offset, count);
+ WriteCore(source);
return;
}
- else if (count == 0)
+ else if (source.Length == 0)
{
return; // Don't allocate a buffer then call memcpy for 0 bytes.
}
// Copy remaining bytes into buffer, to write at a later date.
- Buffer.BlockCopy(array, offset, GetBuffer(), _writePos, count);
- _writePos = count;
+ source.CopyTo(new Span<byte>(GetBuffer()).Slice(_writePos));
+ _writePos = source.Length;
return;
}
- private unsafe void WriteCore(byte[] buffer, int offset, int count)
+ private unsafe void WriteCore(ReadOnlySpan<byte> source)
{
+ Debug.Assert(!_useAsyncIO);
Debug.Assert(!_fileHandle.IsClosed, "!_handle.IsClosed");
Debug.Assert(CanWrite, "_parent.CanWrite");
-
- Debug.Assert(buffer != null, "buffer != null");
Debug.Assert(_readPos == _readLength, "_readPos == _readLen");
- Debug.Assert(offset >= 0, "offset is negative");
- Debug.Assert(count >= 0, "count is negative");
- if (_useAsyncIO)
- {
- WriteInternalCoreAsync(buffer, offset, count, CancellationToken.None).GetAwaiter().GetResult();
- return;
- }
// Make sure we are writing to the position that we think we are
VerifyOSHandlePosition();
int errorCode = 0;
- int r = WriteFileNative(_fileHandle, buffer, offset, count, null, out errorCode);
+ int r = WriteFileNative(_fileHandle, source, null, out errorCode);
if (r == -1)
{
@@ -742,9 +727,8 @@ namespace System.IO
else
{
// ERROR_INVALID_PARAMETER may be returned for writes
- // where the position is too large (i.e. writing at Int64.MaxValue
- // on Win9x) OR for synchronous writes to a handle opened
- // asynchronously.
+ // where the position is too large or for synchronous writes
+ // to a handle opened asynchronously.
if (errorCode == ERROR_INVALID_PARAMETER)
throw new IOException(SR.IO_FileTooLongOrHandleNotSync);
throw Win32Marshal.GetExceptionForWin32Error(errorCode);
@@ -755,15 +739,9 @@ namespace System.IO
return;
}
- private Task<int> ReadAsyncInternal(byte[] array, int offset, int numBytes, CancellationToken cancellationToken)
+ private Task<int> ReadAsyncInternal(Memory<byte> destination, CancellationToken cancellationToken, out int synchronousResult)
{
- // If async IO is not supported on this platform or
- // if this Win32FileStream was not opened with FileOptions.Asynchronous.
- if (!_useAsyncIO)
- {
- return base.ReadAsync(array, offset, numBytes, cancellationToken);
- }
-
+ Debug.Assert(_useAsyncIO);
if (!CanRead) throw Error.GetReadNotSupported();
Debug.Assert((_readPos == 0 && _readLength == 0 && _writePos >= 0) || (_writePos == 0 && _readPos <= _readLength), "We're either reading or writing, but not both.");
@@ -785,18 +763,17 @@ namespace System.IO
// pipes. But don't completely ignore buffered data either.
if (_readPos < _readLength)
{
- int n = _readLength - _readPos;
- if (n > numBytes) n = numBytes;
- Buffer.BlockCopy(GetBuffer(), _readPos, array, offset, n);
+ int n = Math.Min(_readLength - _readPos, destination.Length);
+ new Span<byte>(GetBuffer(), _readPos, n).CopyTo(destination.Span);
_readPos += n;
-
- // Return a completed task
- return TaskFromResultOrCache(n);
+ synchronousResult = n;
+ return null;
}
else
{
Debug.Assert(_writePos == 0, "Win32FileStream must not have buffered write data here! Pipes should be unidirectional.");
- return ReadNativeAsync(array, offset, numBytes, 0, cancellationToken);
+ synchronousResult = 0;
+ return ReadNativeAsync(destination, 0, cancellationToken);
}
}
@@ -817,17 +794,16 @@ namespace System.IO
// problem, and any async read less than 64K gets turned into a
// synchronous read by NT anyways... --
- if (numBytes < _bufferLength)
+ if (destination.Length < _bufferLength)
{
- Task<int> readTask = ReadNativeAsync(GetBuffer(), 0, _bufferLength, 0, cancellationToken);
+ Task<int> readTask = ReadNativeAsync(new Memory<byte>(GetBuffer()), 0, cancellationToken);
_readLength = readTask.GetAwaiter().GetResult();
- int n = _readLength;
- if (n > numBytes) n = numBytes;
- Buffer.BlockCopy(GetBuffer(), 0, array, offset, n);
+ int n = Math.Min(_readLength, destination.Length);
+ new Span<byte>(GetBuffer(), 0, n).CopyTo(destination.Span);
_readPos = n;
- // Return a completed task (recycling the one above if possible)
- return (_readLength == n ? readTask : TaskFromResultOrCache(n));
+ synchronousResult = n;
+ return null;
}
else
{
@@ -835,20 +811,21 @@ namespace System.IO
// with our read buffer. Throw away the read buffer's contents.
_readPos = 0;
_readLength = 0;
- return ReadNativeAsync(array, offset, numBytes, 0, cancellationToken);
+ synchronousResult = 0;
+ return ReadNativeAsync(destination, 0, cancellationToken);
}
}
else
{
- int n = _readLength - _readPos;
- if (n > numBytes) n = numBytes;
- Buffer.BlockCopy(GetBuffer(), _readPos, array, offset, n);
+ int n = Math.Min(_readLength - _readPos, destination.Length);
+ new Span<byte>(GetBuffer(), _readPos, n).CopyTo(destination.Span);
_readPos += n;
- if (n >= numBytes)
+ if (n == destination.Length)
{
// Return a completed task
- return TaskFromResultOrCache(n);
+ synchronousResult = n;
+ return null;
}
else
{
@@ -859,19 +836,21 @@ namespace System.IO
// Throw away read buffer.
_readPos = 0;
_readLength = 0;
- return ReadNativeAsync(array, offset + n, numBytes - n, n, cancellationToken);
+ synchronousResult = 0;
+ return ReadNativeAsync(destination.Slice(n), n, cancellationToken);
}
}
}
- unsafe private Task<int> ReadNativeAsync(byte[] bytes, int offset, int numBytes, int numBufferedBytesRead, CancellationToken cancellationToken)
+ unsafe private Task<int> ReadNativeAsync(Memory<byte> destination, int numBufferedBytesRead, CancellationToken cancellationToken)
{
- AssertCanRead(bytes, offset, numBytes);
+ AssertCanRead();
Debug.Assert(_useAsyncIO, "ReadNativeAsync doesn't work on synchronous file streams!");
// Create and store async stream class library specific data in the async result
-
- FileStreamCompletionSource completionSource = new FileStreamCompletionSource(this, numBufferedBytesRead, bytes, cancellationToken);
+ FileStreamCompletionSource completionSource = destination.TryGetArray(out ArraySegment<byte> memoryArray) ?
+ new FileStreamCompletionSource(this, numBufferedBytesRead, memoryArray.Array) :
+ new MemoryFileStreamCompletionSource(this, numBufferedBytesRead, destination);
NativeOverlapped* intOverlapped = completionSource.Overlapped;
// Calculate position in the file we should be at after the read is done
@@ -882,12 +861,16 @@ namespace System.IO
// Make sure we are reading from the position that we think we are
VerifyOSHandlePosition();
- if (_filePosition + numBytes > len)
+ if (_filePosition + destination.Length > len)
{
if (_filePosition <= len)
- numBytes = (int)(len - _filePosition);
+ {
+ destination = destination.Slice(0, (int)(len - _filePosition));
+ }
else
- numBytes = 0;
+ {
+ destination = default(Memory<byte>);
+ }
}
// Now set the position to read from in the NativeOverlapped struct
@@ -904,12 +887,13 @@ namespace System.IO
// the file pointer when writing to a UNC path!
// So changed the code below to seek to an absolute
// location, not a relative one. ReadFile seems consistent though.
- SeekCore(_fileHandle, numBytes, SeekOrigin.Current);
+ SeekCore(_fileHandle, destination.Length, SeekOrigin.Current);
}
// queue an async ReadFile operation and pass in a packed overlapped
int errorCode = 0;
- int r = ReadFileNative(_fileHandle, bytes, offset, numBytes, intOverlapped, out errorCode);
+ int r = ReadFileNative(_fileHandle, destination.Span, intOverlapped, out errorCode);
+
// ReadFile, the OS version, will return 0 on failure. But
// my ReadFileNative wrapper returns -1. My wrapper will return
// the following:
@@ -920,7 +904,7 @@ namespace System.IO
// read back from this call when using overlapped structures! You must
// not pass in a non-null lpNumBytesRead to ReadFile when using
// overlapped structures! This is by design NT behavior.
- if (r == -1 && numBytes != -1)
+ if (r == -1)
{
// For pipes, when they hit EOF, they will come here.
if (errorCode == ERROR_BROKEN_PIPE)
@@ -951,10 +935,10 @@ namespace System.IO
throw Win32Marshal.GetExceptionForWin32Error(errorCode);
}
}
- else
+ else if (cancellationToken.CanBeCanceled) // ERROR_IO_PENDING
{
// Only once the IO is pending do we register for cancellation
- completionSource.RegisterForCancellation();
+ completionSource.RegisterForCancellation(cancellationToken);
}
}
else
@@ -966,33 +950,19 @@ namespace System.IO
// synchronously or asynchronously. We absolutely must not
// set asyncResult._numBytes here, since will never have correct
// results.
- //Console.WriteLine("ReadFile returned: "+r+" (0x"+Int32.Format(r, "x")+") The IO completed synchronously, but the user callback was called on a separate thread");
}
return completionSource.Task;
}
- // Reads a byte from the file stream. Returns the byte cast to an int
- // or -1 if reading from the end of the stream.
- public override int ReadByte()
+ private Task WriteAsyncInternal(ReadOnlyMemory<byte> source, CancellationToken cancellationToken)
{
- return ReadByteCore();
- }
-
- private Task WriteAsyncInternal(byte[] array, int offset, int numBytes, CancellationToken cancellationToken)
- {
- // If async IO is not supported on this platform or
- // if this Win32FileStream was not opened with FileOptions.Asynchronous.
- if (!_useAsyncIO)
- {
- return base.WriteAsync(array, offset, numBytes, cancellationToken);
- }
-
- if (!CanWrite) throw Error.GetWriteNotSupported();
-
+ Debug.Assert(_useAsyncIO);
Debug.Assert((_readPos == 0 && _readLength == 0 && _writePos >= 0) || (_writePos == 0 && _readPos <= _readLength), "We're either reading or writing, but not both.");
Debug.Assert(!_isPipe || (_readPos == 0 && _readLength == 0), "Win32FileStream must not have buffered data here! Pipes should be unidirectional.");
+ if (!CanWrite) throw Error.GetWriteNotSupported();
+
bool writeDataStoredInBuffer = false;
if (!_isPipe) // avoid async buffering with pipes, as doing so can lead to deadlocks (see comments in ReadInternalAsyncCore)
{
@@ -1016,10 +986,10 @@ namespace System.IO
// - There's no active flush operation, such that we don't have to worry about the existing buffer being in use.
// - And the data we're trying to write fits in the buffer, meaning it wasn't already filled by previous writes.
// In that case, just store it in the buffer.
- if (numBytes < _bufferLength && !HasActiveBufferOperation && numBytes <= remainingBuffer)
+ if (source.Length < _bufferLength && !HasActiveBufferOperation && source.Length <= remainingBuffer)
{
- Buffer.BlockCopy(array, offset, GetBuffer(), _writePos, numBytes);
- _writePos += numBytes;
+ source.Span.CopyTo(new Span<byte>(GetBuffer(), _writePos, source.Length));
+ _writePos += source.Length;
writeDataStoredInBuffer = true;
// There is one special-but-common case, common because devs often use
@@ -1028,7 +998,7 @@ namespace System.IO
// then we're done and can return a completed task now. But if we filled the buffer
// completely, we want to do the asynchronous flush/write as part of this operation
// rather than waiting until the next write that fills the buffer.
- if (numBytes != remainingBuffer)
+ if (source.Length != remainingBuffer)
return Task.CompletedTask;
Debug.Assert(_writePos == _bufferLength);
@@ -1084,40 +1054,37 @@ namespace System.IO
// Finally, issue the write asynchronously, and return a Task that logically
// represents the write operation, including any flushing done.
- Task writeTask = WriteInternalCoreAsync(array, offset, numBytes, cancellationToken);
+ Task writeTask = WriteAsyncInternalCore(source, cancellationToken);
return
(flushTask == null || flushTask.Status == TaskStatus.RanToCompletion) ? writeTask :
(writeTask.Status == TaskStatus.RanToCompletion) ? flushTask :
Task.WhenAll(flushTask, writeTask);
}
- private unsafe Task WriteInternalCoreAsync(byte[] bytes, int offset, int numBytes, CancellationToken cancellationToken)
+ private unsafe Task WriteAsyncInternalCore(ReadOnlyMemory<byte> source, CancellationToken cancellationToken)
{
Debug.Assert(!_fileHandle.IsClosed, "!_handle.IsClosed");
Debug.Assert(CanWrite, "_parent.CanWrite");
- Debug.Assert(bytes != null, "bytes != null");
Debug.Assert(_readPos == _readLength, "_readPos == _readLen");
Debug.Assert(_useAsyncIO, "WriteInternalCoreAsync doesn't work on synchronous file streams!");
- Debug.Assert(offset >= 0, "offset is negative");
- Debug.Assert(numBytes >= 0, "numBytes is negative");
// Create and store async stream class library specific data in the async result
- FileStreamCompletionSource completionSource = new FileStreamCompletionSource(this, 0, bytes, cancellationToken);
+ FileStreamCompletionSource completionSource = source.DangerousTryGetArray(out ArraySegment<byte> array) ?
+ new FileStreamCompletionSource(this, 0, array.Array) :
+ new MemoryFileStreamCompletionSource(this, 0, source);
NativeOverlapped* intOverlapped = completionSource.Overlapped;
if (CanSeek)
{
// Make sure we set the length of the file appropriately.
long len = Length;
- //Console.WriteLine("WriteInternalCoreAsync - Calculating end pos. pos: "+pos+" len: "+len+" numBytes: "+numBytes);
// Make sure we are writing to the position that we think we are
VerifyOSHandlePosition();
- if (_filePosition + numBytes > len)
+ if (_filePosition + source.Length > len)
{
- //Console.WriteLine("WriteInternalCoreAsync - Setting length to: "+(pos + numBytes));
- SetLengthCore(_filePosition + numBytes);
+ SetLengthCore(_filePosition + source.Length);
}
// Now set the position to read from in the NativeOverlapped struct
@@ -1128,14 +1095,12 @@ namespace System.IO
// When using overlapped IO, the OS is not supposed to
// touch the file pointer location at all. We will adjust it
// ourselves. This isn't threadsafe.
- SeekCore(_fileHandle, numBytes, SeekOrigin.Current);
+ SeekCore(_fileHandle, source.Length, SeekOrigin.Current);
}
- //Console.WriteLine("WriteInternalCoreAsync finishing. pos: "+pos+" numBytes: "+numBytes+" _pos: "+_pos+" Position: "+Position);
-
int errorCode = 0;
// queue an async WriteFile operation and pass in a packed overlapped
- int r = WriteFileNative(_fileHandle, bytes, offset, numBytes, intOverlapped, out errorCode);
+ int r = WriteFileNative(_fileHandle, source.Span, intOverlapped, out errorCode);
// WriteFile, the OS version, will return 0 on failure. But
// my WriteFileNative wrapper returns -1. My wrapper will return
@@ -1147,10 +1112,8 @@ namespace System.IO
// written back from this call when using overlapped IO! You must
// not pass in a non-null lpNumBytesWritten to WriteFile when using
// overlapped structures! This is ByDesign NT behavior.
- if (r == -1 && numBytes != -1)
+ if (r == -1)
{
- //Console.WriteLine("WriteFile returned 0; Write will complete asynchronously (if errorCode==3e5) errorCode: 0x{0:x}", errorCode);
-
// For pipes, when they are closed on the other side, they will come here.
if (errorCode == ERROR_NO_DATA)
{
@@ -1177,10 +1140,10 @@ namespace System.IO
throw Win32Marshal.GetExceptionForWin32Error(errorCode);
}
}
- else // ERROR_IO_PENDING
+ else if (cancellationToken.CanBeCanceled) // ERROR_IO_PENDING
{
// Only once the IO is pending do we register for cancellation
- completionSource.RegisterForCancellation();
+ completionSource.RegisterForCancellation(cancellationToken);
}
}
else
@@ -1192,17 +1155,11 @@ namespace System.IO
// synchronously or asynchronously. We absolutely must not
// set asyncResult._numBytes here, since will never have correct
// results.
- //Console.WriteLine("WriteFile returned: "+r+" (0x"+Int32.Format(r, "x")+") The IO completed synchronously, but the user callback was called on another thread.");
}
return completionSource.Task;
}
- public override void WriteByte(byte value)
- {
- WriteByteCore(value);
- }
-
// Windows API definitions, from winbase.h and others
private const int FILE_ATTRIBUTE_NORMAL = 0x00000080;
@@ -1223,35 +1180,19 @@ namespace System.IO
private const int ERROR_IO_PENDING = 997;
// __ConsoleStream also uses this code.
- private unsafe int ReadFileNative(SafeFileHandle handle, byte[] bytes, int offset, int count, NativeOverlapped* overlapped, out int errorCode)
+ private unsafe int ReadFileNative(SafeFileHandle handle, Span<byte> bytes, NativeOverlapped* overlapped, out int errorCode)
{
Debug.Assert(handle != null, "handle != null");
- Debug.Assert(offset >= 0, "offset >= 0");
- Debug.Assert(count >= 0, "count >= 0");
- Debug.Assert(bytes != null, "bytes != null");
- // Don't corrupt memory when multiple threads are erroneously writing
- // to this stream simultaneously.
- if (bytes.Length - offset < count)
- throw new IndexOutOfRangeException(SR.IndexOutOfRange_IORaceCondition);
-
Debug.Assert((_useAsyncIO && overlapped != null) || (!_useAsyncIO && overlapped == null), "Async IO and overlapped parameters inconsistent in call to ReadFileNative.");
- // You can't use the fixed statement on an array of length 0.
- if (bytes.Length == 0)
- {
- errorCode = 0;
- return 0;
- }
-
- int r = 0;
+ int r;
int numBytesRead = 0;
- fixed (byte* p = &bytes[0])
+ fixed (byte* p = &bytes.DangerousGetPinnableReference())
{
- if (_useAsyncIO)
- r = Interop.Kernel32.ReadFile(handle, p + offset, count, IntPtr.Zero, overlapped);
- else
- r = Interop.Kernel32.ReadFile(handle, p + offset, count, out numBytesRead, IntPtr.Zero);
+ r = _useAsyncIO ?
+ Interop.Kernel32.ReadFile(handle, p, bytes.Length, IntPtr.Zero, overlapped) :
+ Interop.Kernel32.ReadFile(handle, p, bytes.Length, out numBytesRead, IntPtr.Zero);
}
if (r == 0)
@@ -1266,37 +1207,19 @@ namespace System.IO
}
}
- private unsafe int WriteFileNative(SafeFileHandle handle, byte[] bytes, int offset, int count, NativeOverlapped* overlapped, out int errorCode)
+ private unsafe int WriteFileNative(SafeFileHandle handle, ReadOnlySpan<byte> buffer, NativeOverlapped* overlapped, out int errorCode)
{
Debug.Assert(handle != null, "handle != null");
- Debug.Assert(offset >= 0, "offset >= 0");
- Debug.Assert(count >= 0, "count >= 0");
- Debug.Assert(bytes != null, "bytes != null");
- // Don't corrupt memory when multiple threads are erroneously writing
- // to this stream simultaneously. (the OS is reading from
- // the array we pass to WriteFile, but if we read beyond the end and
- // that memory isn't allocated, we could get an AV.)
- if (bytes.Length - offset < count)
- throw new IndexOutOfRangeException(SR.IndexOutOfRange_IORaceCondition);
-
Debug.Assert((_useAsyncIO && overlapped != null) || (!_useAsyncIO && overlapped == null), "Async IO and overlapped parameters inconsistent in call to WriteFileNative.");
- // You can't use the fixed statement on an array of length 0.
- if (bytes.Length == 0)
- {
- errorCode = 0;
- return 0;
- }
-
int numBytesWritten = 0;
- int r = 0;
+ int r;
- fixed (byte* p = &bytes[0])
+ fixed (byte* p = &buffer.DangerousGetPinnableReference())
{
- if (_useAsyncIO)
- r = Interop.Kernel32.WriteFile(handle, p + offset, count, IntPtr.Zero, overlapped);
- else
- r = Interop.Kernel32.WriteFile(handle, p + offset, count, out numBytesWritten, IntPtr.Zero);
+ r = _useAsyncIO ?
+ Interop.Kernel32.WriteFile(handle, p, buffer.Length, IntPtr.Zero, overlapped) :
+ Interop.Kernel32.WriteFile(handle, p, buffer.Length, out numBytesWritten, IntPtr.Zero);
}
if (r == 0)
@@ -1472,7 +1395,7 @@ namespace System.IO
}
// Kick off the read.
- synchronousSuccess = ReadFileNative(_fileHandle, copyBuffer, 0, copyBuffer.Length, readAwaitable._nativeOverlapped, out errorCode) >= 0;
+ synchronousSuccess = ReadFileNative(_fileHandle, copyBuffer, readAwaitable._nativeOverlapped, out errorCode) >= 0;
}
// If the operation did not synchronously succeed, it either failed or initiated the asynchronous operation.
@@ -1696,20 +1619,6 @@ namespace System.IO
}
}
- private Task<int> TaskFromResultOrCache(int result)
- {
- Task<int> completedTask = _lastSynchronouslyCompletedTask;
- Debug.Assert(completedTask == null || completedTask.Status == TaskStatus.RanToCompletion, "Cached task should have completed successfully");
-
- if ((completedTask == null) || (completedTask.Result != result))
- {
- completedTask = Task.FromResult(result);
- _lastSynchronouslyCompletedTask = completedTask;
- }
-
- return completedTask;
- }
-
private void LockInternal(long position, long length)
{
int positionLow = unchecked((int)(position));
@@ -1735,5 +1644,25 @@ namespace System.IO
throw Win32Marshal.GetExceptionForLastWin32Error();
}
}
+ private SafeFileHandle ValidateFileHandle(SafeFileHandle fileHandle)
+ {
+ if (fileHandle.IsInvalid)
+ {
+ // Return a meaningful exception with the full path.
+
+ // NT5 oddity - when trying to open "C:\" as a Win32FileStream,
+ // we usually get ERROR_PATH_NOT_FOUND from the OS. We should
+ // probably be consistent w/ every other directory.
+ int errorCode = Marshal.GetLastWin32Error();
+
+ if (errorCode == Interop.Errors.ERROR_PATH_NOT_FOUND && _path.Length == PathInternal.GetRootLength(_path))
+ errorCode = Interop.Errors.ERROR_ACCESS_DENIED;
+
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode, _path);
+ }
+
+ fileHandle.IsAsync = _useAsyncIO;
+ return fileHandle;
+ }
}
}
diff --git a/src/mscorlib/shared/System/IO/FileStream.cs b/src/mscorlib/shared/System/IO/FileStream.cs
index 39f7b60d12..65c63bcc53 100644
--- a/src/mscorlib/shared/System/IO/FileStream.cs
+++ b/src/mscorlib/shared/System/IO/FileStream.cs
@@ -51,6 +51,9 @@ namespace System.IO
/// </summary>
private readonly bool _useAsyncIO;
+ /// <summary>cached task for read ops that complete synchronously</summary>
+ private Task<int> _lastSynchronouslyCompletedTask = null;
+
/// <summary>
/// Currently cached position in the stream. This should always mirror the underlying file's actual position,
/// and should only ever be out of sync if another stream with access to this same file manipulates it, at which
@@ -292,6 +295,36 @@ namespace System.IO
return FlushAsyncInternal(cancellationToken);
}
+ public override int Read(byte[] array, int offset, int count)
+ {
+ ValidateReadWriteArgs(array, offset, count);
+ return _useAsyncIO ?
+ ReadAsyncTask(array, offset, count, CancellationToken.None).GetAwaiter().GetResult() :
+ ReadSpan(new Span<byte>(array, offset, count));
+ }
+
+ public override int Read(Span<byte> destination)
+ {
+ if (GetType() == typeof(FileStream) && !_useAsyncIO)
+ {
+ if (_fileHandle.IsClosed)
+ {
+ throw Error.GetFileNotOpen();
+ }
+ return ReadSpan(destination);
+ }
+ else
+ {
+ // This type is derived from FileStream and/or the stream is in async mode. If this is a
+ // derived type, it may have overridden Read(byte[], int, int) prior to this Read(Span<byte>)
+ // overload being introduced. In that case, this Read(Span<byte>) overload should use the behavior
+ // of Read(byte[],int,int) overload. Or if the stream is in async mode, we can't call the
+ // synchronous ReadSpan, so we similarly call the base Read, which will turn delegate to
+ // Read(byte[],int,int), which will do the right thing if we're in async mode.
+ return base.Read(destination);
+ }
+ }
+
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
if (buffer == null)
@@ -304,10 +337,12 @@ namespace System.IO
throw new ArgumentException(SR.Argument_InvalidOffLen /*, no good single parameter name to pass*/);
// If we have been inherited into a subclass, the following implementation could be incorrect
- // since it does not call through to Read() or ReadAsync() which a subclass might have overridden.
+ // since it does not call through to Read() which a subclass might have overridden.
// To be safe we will only use this implementation in cases where we know it is safe to do so,
// and delegate to our base class (which will call into Read/ReadAsync) when we are not sure.
- if (GetType() != typeof(FileStream))
+ // Similarly, if we weren't opened for asynchronous I/O, call to the base implementation so that
+ // Read is invoked asynchronously.
+ if (GetType() != typeof(FileStream) || !_useAsyncIO)
return base.ReadAsync(buffer, offset, count, cancellationToken);
if (cancellationToken.IsCancellationRequested)
@@ -316,7 +351,86 @@ namespace System.IO
if (IsClosed)
throw Error.GetFileNotOpen();
- return ReadAsyncInternal(buffer, offset, count, cancellationToken);
+ return ReadAsyncTask(buffer, offset, count, cancellationToken);
+ }
+
+ public override ValueTask<int> ReadAsync(Memory<byte> destination, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (!_useAsyncIO || GetType() != typeof(FileStream))
+ {
+ // If we're not using async I/O, delegate to the base, which will queue a call to Read.
+ // Or if this isn't a concrete FileStream, a derived type may have overridden ReadAsync(byte[],...),
+ // which was introduced first, so delegate to the base which will delegate to that.
+ return base.ReadAsync(destination, cancellationToken);
+ }
+
+ if (cancellationToken.IsCancellationRequested)
+ {
+ return new ValueTask<int>(Task.FromCanceled<int>(cancellationToken));
+ }
+
+ if (IsClosed)
+ {
+ throw Error.GetFileNotOpen();
+ }
+
+ Task<int> t = ReadAsyncInternal(destination, cancellationToken, out int synchronousResult);
+ return t != null ?
+ new ValueTask<int>(t) :
+ new ValueTask<int>(synchronousResult);
+ }
+
+ private Task<int> ReadAsyncTask(byte[] array, int offset, int count, CancellationToken cancellationToken)
+ {
+ Task<int> t = ReadAsyncInternal(new Memory<byte>(array, offset, count), cancellationToken, out int synchronousResult);
+
+ if (t == null)
+ {
+ t = _lastSynchronouslyCompletedTask;
+ Debug.Assert(t == null || t.IsCompletedSuccessfully, "Cached task should have completed successfully");
+
+ if (t == null || t.Result != synchronousResult)
+ {
+ _lastSynchronouslyCompletedTask = t = Task.FromResult(synchronousResult);
+ }
+ }
+
+ return t;
+ }
+
+ public override void Write(byte[] array, int offset, int count)
+ {
+ ValidateReadWriteArgs(array, offset, count);
+ if (_useAsyncIO)
+ {
+ WriteAsyncInternal(new ReadOnlyMemory<byte>(array, offset, count), CancellationToken.None).GetAwaiter().GetResult();
+ }
+ else
+ {
+ WriteSpan(new ReadOnlySpan<byte>(array, offset, count));
+ }
+ }
+
+ public override void Write(ReadOnlySpan<byte> destination)
+ {
+ if (GetType() == typeof(FileStream) && !_useAsyncIO)
+ {
+ if (_fileHandle.IsClosed)
+ {
+ throw Error.GetFileNotOpen();
+ }
+ WriteSpan(destination);
+ }
+ else
+ {
+ // This type is derived from FileStream and/or the stream is in async mode. If this is a
+ // derived type, it may have overridden Write(byte[], int, int) prior to this Write(ReadOnlySpan<byte>)
+ // overload being introduced. In that case, this Write(ReadOnlySpan<byte>) overload should use the behavior
+ // of Write(byte[],int,int) overload. Or if the stream is in async mode, we can't call the
+ // synchronous WriteSpan, so we similarly call the base Write, which will turn delegate to
+ // Write(byte[],int,int), which will do the right thing if we're in async mode.
+ base.Write(destination);
+ }
}
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
@@ -334,7 +448,7 @@ namespace System.IO
// since it does not call through to Write() or WriteAsync() which a subclass might have overridden.
// To be safe we will only use this implementation in cases where we know it is safe to do so,
// and delegate to our base class (which will call into Write/WriteAsync) when we are not sure.
- if (GetType() != typeof(FileStream))
+ if (!_useAsyncIO || GetType() != typeof(FileStream))
return base.WriteAsync(buffer, offset, count, cancellationToken);
if (cancellationToken.IsCancellationRequested)
@@ -343,7 +457,30 @@ namespace System.IO
if (IsClosed)
throw Error.GetFileNotOpen();
- return WriteAsyncInternal(buffer, offset, count, cancellationToken);
+ return WriteAsyncInternal(new ReadOnlyMemory<byte>(buffer, offset, count), cancellationToken);
+ }
+
+ public override Task WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (!_useAsyncIO || GetType() != typeof(FileStream))
+ {
+ // If we're not using async I/O, delegate to the base, which will queue a call to Write.
+ // Or if this isn't a concrete FileStream, a derived type may have overridden WriteAsync(byte[],...),
+ // which was introduced first, so delegate to the base which will delegate to that.
+ return base.WriteAsync(source, cancellationToken);
+ }
+
+ if (cancellationToken.IsCancellationRequested)
+ {
+ return Task.FromCanceled<int>(cancellationToken);
+ }
+
+ if (IsClosed)
+ {
+ throw Error.GetFileNotOpen();
+ }
+
+ return WriteAsyncInternal(source, cancellationToken);
}
/// <summary>
@@ -594,7 +731,11 @@ namespace System.IO
_readPos = _readLength = 0;
}
- private int ReadByteCore()
+ /// <summary>
+ /// Reads a byte from the file stream. Returns the byte cast to an int
+ /// or -1 if reading from the end of the stream.
+ /// </summary>
+ public override int ReadByte()
{
PrepareForReading();
@@ -602,9 +743,7 @@ namespace System.IO
if (_readPos == _readLength)
{
FlushWriteBuffer();
- Debug.Assert(_bufferLength > 0, "_bufferSize > 0");
-
- _readLength = ReadNative(buffer, 0, _bufferLength);
+ _readLength = FillReadBufferForReadByte();
_readPos = 0;
if (_readLength == 0)
{
@@ -615,13 +754,18 @@ namespace System.IO
return buffer[_readPos++];
}
- private void WriteByteCore(byte value)
+ /// <summary>
+ /// Writes a byte to the current position in the stream and advances the position
+ /// within the stream by one byte.
+ /// </summary>
+ /// <param name="value">The byte to write to the stream.</param>
+ public override void WriteByte(byte value)
{
PrepareForWriting();
// Flush the write buffer if it's full
if (_writePos == _bufferLength)
- FlushWriteBuffer();
+ FlushWriteBufferForWriteByte();
// We now have space in the buffer. Store the byte.
GetBuffer()[_writePos++] = value;
@@ -672,7 +816,7 @@ namespace System.IO
if (!IsAsync)
return base.BeginRead(array, offset, numBytes, callback, state);
else
- return TaskToApm.Begin(ReadAsyncInternal(array, offset, numBytes, CancellationToken.None), callback, state);
+ return TaskToApm.Begin(ReadAsyncTask(array, offset, numBytes, CancellationToken.None), callback, state);
}
public override IAsyncResult BeginWrite(byte[] array, int offset, int numBytes, AsyncCallback callback, object state)
@@ -692,7 +836,7 @@ namespace System.IO
if (!IsAsync)
return base.BeginWrite(array, offset, numBytes, callback, state);
else
- return TaskToApm.Begin(WriteAsyncInternal(array, offset, numBytes, CancellationToken.None), callback, state);
+ return TaskToApm.Begin(WriteAsyncInternal(new ReadOnlyMemory<byte>(array, offset, numBytes), CancellationToken.None), callback, state);
}
public override int EndRead(IAsyncResult asyncResult)
diff --git a/src/mscorlib/shared/System/IO/FileStreamCompletionSource.Win32.cs b/src/mscorlib/shared/System/IO/FileStreamCompletionSource.Win32.cs
index 7dca13335e..e3871bcd6c 100644
--- a/src/mscorlib/shared/System/IO/FileStreamCompletionSource.Win32.cs
+++ b/src/mscorlib/shared/System/IO/FileStreamCompletionSource.Win32.cs
@@ -2,11 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Security;
+using System.Buffers;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
-using System.Runtime.InteropServices;
-using System.Diagnostics;
namespace System.IO
{
@@ -15,7 +15,7 @@ namespace System.IO
// This is an internal object extending TaskCompletionSource with fields
// for all of the relevant data necessary to complete the IO operation.
// This is used by IOCallback and all of the async methods.
- unsafe private sealed class FileStreamCompletionSource : TaskCompletionSource<int>
+ private unsafe class FileStreamCompletionSource : TaskCompletionSource<int>
{
private const long NoResult = 0;
private const long ResultSuccess = (long)1 << 32;
@@ -28,7 +28,6 @@ namespace System.IO
private readonly FileStream _stream;
private readonly int _numBufferedBytes;
- private readonly CancellationToken _cancellationToken;
private CancellationTokenRegistration _cancellationRegistration;
#if DEBUG
private bool _cancellationHasBeenRegistered;
@@ -37,20 +36,19 @@ namespace System.IO
private long _result; // Using long since this needs to be used in Interlocked APIs
// Using RunContinuationsAsynchronously for compat reasons (old API used Task.Factory.StartNew for continuations)
- internal FileStreamCompletionSource(FileStream stream, int numBufferedBytes, byte[] bytes, CancellationToken cancellationToken)
+ internal FileStreamCompletionSource(FileStream stream, int numBufferedBytes, byte[] bytes)
: base(TaskCreationOptions.RunContinuationsAsynchronously)
{
_numBufferedBytes = numBufferedBytes;
_stream = stream;
_result = NoResult;
- _cancellationToken = cancellationToken;
- // Create the native overlapped. We try to use the preallocated overlapped if possible:
- // it's possible if the byte buffer is the same one that's associated with the preallocated overlapped
- // and if no one else is currently using the preallocated overlapped. This is the fast-path for cases
- // where the user-provided buffer is smaller than the FileStream's buffer (such that the FileStream's
+ // Create the native overlapped. We try to use the preallocated overlapped if possible: it's possible if the byte
+ // buffer is null (there's nothing to pin) or the same one that's associated with the preallocated overlapped (and
+ // thus is already pinned) and if no one else is currently using the preallocated overlapped. This is the fast-path
+ // for cases where the user-provided buffer is smaller than the FileStream's buffer (such that the FileStream's
// buffer is used) and where operations on the FileStream are not being performed concurrently.
- _overlapped = ReferenceEquals(bytes, _stream._buffer) && _stream.CompareExchangeCurrentOverlappedOwner(this, null) == null ?
+ _overlapped = (bytes == null || ReferenceEquals(bytes, _stream._buffer)) && _stream.CompareExchangeCurrentOverlappedOwner(this, null) == null ?
_stream._fileHandle.ThreadPoolBinding.AllocateNativeOverlapped(_stream._preallocatedOverlapped) :
_stream._fileHandle.ThreadPoolBinding.AllocateNativeOverlapped(s_ioCallback, this, bytes);
Debug.Assert(_overlapped != null, "AllocateNativeOverlapped returned null");
@@ -67,15 +65,16 @@ namespace System.IO
TrySetResult(numBytes + _numBufferedBytes);
}
- public void RegisterForCancellation()
+ public void RegisterForCancellation(CancellationToken cancellationToken)
{
#if DEBUG
+ Debug.Assert(cancellationToken.CanBeCanceled);
Debug.Assert(!_cancellationHasBeenRegistered, "Cannot register for cancellation twice");
_cancellationHasBeenRegistered = true;
#endif
- // Quick check to make sure that the cancellation token supports cancellation, and that the IO hasn't completed
- if ((_cancellationToken.CanBeCanceled) && (_overlapped != null))
+ // Quick check to make sure the IO hasn't completed
+ if (_overlapped != null)
{
var cancelCallback = s_cancelCallback;
if (cancelCallback == null) s_cancelCallback = cancelCallback = Cancel;
@@ -84,7 +83,7 @@ namespace System.IO
long packedResult = Interlocked.CompareExchange(ref _result, RegisteringCancellation, NoResult);
if (packedResult == NoResult)
{
- _cancellationRegistration = _cancellationToken.Register(cancelCallback, this);
+ _cancellationRegistration = cancellationToken.Register(cancelCallback, this);
// Switch the result, just in case IO completed while we were setting the registration
packedResult = Interlocked.Exchange(ref _result, NoResult);
@@ -104,7 +103,7 @@ namespace System.IO
}
}
- internal void ReleaseNativeResource()
+ internal virtual void ReleaseNativeResource()
{
// Ensure that cancellation has been completed and cleaned up.
_cancellationRegistration.Dispose();
@@ -172,6 +171,7 @@ namespace System.IO
private void CompleteCallback(ulong packedResult)
{
// Free up the native resource and cancellation registration
+ CancellationToken cancellationToken = _cancellationRegistration.Token; // access before disposing registration
ReleaseNativeResource();
// Unpack the result and send it to the user
@@ -181,7 +181,7 @@ namespace System.IO
int errorCode = unchecked((int)(packedResult & uint.MaxValue));
if (errorCode == Interop.Errors.ERROR_OPERATION_ABORTED)
{
- TrySetCanceled(_cancellationToken.IsCancellationRequested ? _cancellationToken : new CancellationToken(true));
+ TrySetCanceled(cancellationToken.IsCancellationRequested ? cancellationToken : new CancellationToken(true));
}
else
{
@@ -218,5 +218,28 @@ namespace System.IO
}
}
}
+
+ /// <summary>
+ /// Extends <see cref="FileStreamCompletionSource"/> with to support disposing of a
+ /// <see cref="MemoryHandle"/> when the operation has completed. This should only be used
+ /// when memory doesn't wrap a byte[].
+ /// </summary>
+ private sealed class MemoryFileStreamCompletionSource : FileStreamCompletionSource
+ {
+ private MemoryHandle _handle; // mutable struct; do not make this readonly
+
+ internal MemoryFileStreamCompletionSource(FileStream stream, int numBufferedBytes, ReadOnlyMemory<byte> memory) :
+ base(stream, numBufferedBytes, bytes: null) // this type handles the pinning, so null is passed for bytes
+ {
+ Debug.Assert(!memory.DangerousTryGetArray(out ArraySegment<byte> array), "The base should be used directly if we can get the array.");
+ _handle = memory.Retain(pin: true);
+ }
+
+ internal override void ReleaseNativeResource()
+ {
+ _handle.Dispose();
+ base.ReleaseNativeResource();
+ }
+ }
}
}
diff --git a/src/mscorlib/shared/System/IO/IOException.cs b/src/mscorlib/shared/System/IO/IOException.cs
new file mode 100644
index 0000000000..1fbd352613
--- /dev/null
+++ b/src/mscorlib/shared/System/IO/IOException.cs
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Serialization;
+
+namespace System.IO
+{
+ public class IOException : SystemException
+ {
+ public IOException()
+ : base(SR.Arg_IOException)
+ {
+ HResult = HResults.COR_E_IO;
+ }
+
+ public IOException(String message)
+ : base(message)
+ {
+ HResult = HResults.COR_E_IO;
+ }
+
+ public IOException(String message, int hresult)
+ : base(message)
+ {
+ HResult = hresult;
+ }
+
+ public IOException(String message, Exception innerException)
+ : base(message, innerException)
+ {
+ HResult = HResults.COR_E_IO;
+ }
+
+ protected IOException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ throw new PlatformNotSupportedException();
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/IO/Path.cs b/src/mscorlib/shared/System/IO/Path.cs
index 135bb42881..2676f0d2fe 100644
--- a/src/mscorlib/shared/System/IO/Path.cs
+++ b/src/mscorlib/shared/System/IO/Path.cs
@@ -166,6 +166,30 @@ namespace System.IO
return new string(pRandomFileName, 0, RandomFileNameLength);
}
+ /// <summary>
+ /// Returns true if the path is fixed to a specific drive or UNC path. This method does no
+ /// validation of the path (URIs will be returned as relative as a result).
+ /// Returns false if the path specified is relative to the current drive or working directory.
+ /// </summary>
+ /// <remarks>
+ /// Handles paths that use the alternate directory separator. It is a frequent mistake to
+ /// assume that rooted paths <see cref="Path.IsPathRooted(string)"/> are not relative. This isn't the case.
+ /// "C:a" is drive relative- meaning that it will be resolved against the current directory
+ /// for C: (rooted, but relative). "C:\a" is rooted and not relative (the current directory
+ /// will not be used to modify the path).
+ /// </remarks>
+ /// <exception cref="ArgumentNullException">
+ /// Thrown if <paramref name="path"/> is null.
+ /// </exception>
+ public static bool IsPathFullyQualified(string path)
+ {
+ if (path == null)
+ {
+ throw new ArgumentNullException(nameof(path));
+ }
+ return !PathInternal.IsPartiallyQualified(path);
+ }
+
// Tests if a path includes a file extension. The result is
// true if the characters that follow the last directory
// separator ('\\' or '/') or volume separator (':') in the path include
diff --git a/src/mscorlib/shared/System/IO/PathInternal.Windows.cs b/src/mscorlib/shared/System/IO/PathInternal.Windows.cs
index 01069e757c..2ab3928608 100644
--- a/src/mscorlib/shared/System/IO/PathInternal.Windows.cs
+++ b/src/mscorlib/shared/System/IO/PathInternal.Windows.cs
@@ -437,11 +437,6 @@ namespace System.IO
return IsDirectorySeparator(ch) || VolumeSeparatorChar == ch;
}
- internal static string TrimEndingDirectorySeparator(string path) =>
- EndsInDirectorySeparator(path) ?
- path.Substring(0, path.Length - 1) :
- path;
-
/// <summary>
/// Returns true if the path is effectively empty for the current OS.
/// For unix, this is empty or null. For Windows, this is empty, null, or
diff --git a/src/mscorlib/shared/System/IO/PathTooLongException.cs b/src/mscorlib/shared/System/IO/PathTooLongException.cs
index 64c8e6c7e6..15f282ebf6 100644
--- a/src/mscorlib/shared/System/IO/PathTooLongException.cs
+++ b/src/mscorlib/shared/System/IO/PathTooLongException.cs
@@ -13,19 +13,19 @@ namespace System.IO
public PathTooLongException()
: base(SR.IO_PathTooLong)
{
- HResult = __HResults.COR_E_PATHTOOLONG;
+ HResult = HResults.COR_E_PATHTOOLONG;
}
public PathTooLongException(string message)
: base(message)
{
- HResult = __HResults.COR_E_PATHTOOLONG;
+ HResult = HResults.COR_E_PATHTOOLONG;
}
public PathTooLongException(string message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_PATHTOOLONG;
+ HResult = HResults.COR_E_PATHTOOLONG;
}
protected PathTooLongException(SerializationInfo info, StreamingContext context)
diff --git a/src/mscorlib/shared/System/IO/PinnedBufferMemoryStream.cs b/src/mscorlib/shared/System/IO/PinnedBufferMemoryStream.cs
index c8e720b7ac..e8f74dd05c 100644
--- a/src/mscorlib/shared/System/IO/PinnedBufferMemoryStream.cs
+++ b/src/mscorlib/shared/System/IO/PinnedBufferMemoryStream.cs
@@ -46,6 +46,10 @@ namespace System.IO
Initialize(ptr, len, len, FileAccess.Read);
}
+ public override int Read(Span<byte> destination) => ReadCore(destination);
+
+ public override void Write(ReadOnlySpan<byte> source) => WriteCore(source);
+
~PinnedBufferMemoryStream()
{
Dispose(false);
diff --git a/src/mscorlib/shared/System/IO/UnmanagedMemoryStream.cs b/src/mscorlib/shared/System/IO/UnmanagedMemoryStream.cs
index b78f50fe7b..b899951ba7 100644
--- a/src/mscorlib/shared/System/IO/UnmanagedMemoryStream.cs
+++ b/src/mscorlib/shared/System/IO/UnmanagedMemoryStream.cs
@@ -361,8 +361,27 @@ namespace System.IO
throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
if (buffer.Length - offset < count)
throw new ArgumentException(SR.Argument_InvalidOffLen);
- Contract.EndContractBlock(); // Keep this in sync with contract validation in ReadAsync
+ return ReadCore(new Span<byte>(buffer, offset, count));
+ }
+
+ public override int Read(Span<byte> destination)
+ {
+ if (GetType() == typeof(UnmanagedMemoryStream))
+ {
+ return ReadCore(destination);
+ }
+ else
+ {
+ // UnmanagedMemoryStream is not sealed, and a derived type may have overridden Read(byte[], int, int) prior
+ // to this Read(Span<byte>) overload being introduced. In that case, this Read(Span<byte>) overload
+ // should use the behavior of Read(byte[],int,int) overload.
+ return base.Read(destination);
+ }
+ }
+
+ internal int ReadCore(Span<byte> destination)
+ {
if (!_isOpen) throw Error.GetStreamIsClosed();
if (!CanRead) throw Error.GetReadNotSupported();
@@ -370,20 +389,22 @@ namespace System.IO
// changes our position after we decide we can read some bytes.
long pos = Interlocked.Read(ref _position);
long len = Interlocked.Read(ref _length);
- long n = len - pos;
- if (n > count)
- n = count;
+ long n = Math.Min(len - pos, destination.Length);
if (n <= 0)
+ {
return 0;
+ }
int nInt = (int)n; // Safe because n <= count, which is an Int32
if (nInt < 0)
+ {
return 0; // _position could be beyond EOF
+ }
Debug.Assert(pos + nInt >= 0, "_position + n >= 0"); // len is less than 2^63 -1.
unsafe
{
- fixed (byte* pBuffer = buffer)
+ fixed (byte* pBuffer = &destination.DangerousGetPinnableReference())
{
if (_buffer != null)
{
@@ -393,7 +414,7 @@ namespace System.IO
try
{
_buffer.AcquirePointer(ref pointer);
- Buffer.Memcpy(pBuffer + offset, pointer + pos + _offset, nInt);
+ Buffer.Memcpy(pBuffer, pointer + pos + _offset, nInt);
}
finally
{
@@ -405,7 +426,7 @@ namespace System.IO
}
else
{
- Buffer.Memcpy(pBuffer + offset, _mem + pos, nInt);
+ Buffer.Memcpy(pBuffer, _mem + pos, nInt);
}
}
}
@@ -450,6 +471,28 @@ namespace System.IO
}
/// <summary>
+ /// Reads bytes from stream and puts them into the buffer
+ /// </summary>
+ /// <param name="destination">Buffer to read the bytes to.</param>
+ /// <param name="cancellationToken">Token that can be used to cancel this operation.</param>
+ public override ValueTask<int> ReadAsync(Memory<byte> destination, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (cancellationToken.IsCancellationRequested)
+ {
+ return new ValueTask<int>(Task.FromCanceled<int>(cancellationToken));
+ }
+
+ try
+ {
+ return new ValueTask<int>(Read(destination.Span));
+ }
+ catch (Exception ex)
+ {
+ return new ValueTask<int>(Task.FromException<int>(ex));
+ }
+ }
+
+ /// <summary>
/// Returns the byte at the stream current Position and advances the Position.
/// </summary>
/// <returns></returns>
@@ -583,17 +626,38 @@ namespace System.IO
throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
if (buffer.Length - offset < count)
throw new ArgumentException(SR.Argument_InvalidOffLen);
- Contract.EndContractBlock(); // Keep contract validation in sync with WriteAsync(..)
+ WriteCore(new Span<byte>(buffer, offset, count));
+ }
+
+ public override void Write(ReadOnlySpan<byte> source)
+ {
+ if (GetType() == typeof(UnmanagedMemoryStream))
+ {
+ WriteCore(source);
+ }
+ else
+ {
+ // UnmanagedMemoryStream is not sealed, and a derived type may have overridden Write(byte[], int, int) prior
+ // to this Write(Span<byte>) overload being introduced. In that case, this Write(Span<byte>) overload
+ // should use the behavior of Write(byte[],int,int) overload.
+ base.Write(source);
+ }
+ }
+
+ internal unsafe void WriteCore(ReadOnlySpan<byte> source)
+ {
if (!_isOpen) throw Error.GetStreamIsClosed();
if (!CanWrite) throw Error.GetWriteNotSupported();
long pos = Interlocked.Read(ref _position); // Use a local to avoid a race condition
long len = Interlocked.Read(ref _length);
- long n = pos + count;
+ long n = pos + source.Length;
// Check for overflow
if (n < 0)
+ {
throw new IOException(SR.IO_StreamTooLong);
+ }
if (n > _capacity)
{
@@ -606,10 +670,7 @@ namespace System.IO
// zero any memory in the middle.
if (pos > len)
{
- unsafe
- {
- Buffer.ZeroMemory(_mem + len, pos - len);
- }
+ Buffer.ZeroMemory(_mem + len, pos - len);
}
// set length after zeroing memory to avoid race condition of accessing unzeroed memory
@@ -619,39 +680,37 @@ namespace System.IO
}
}
- unsafe
+ fixed (byte* pBuffer = &source.DangerousGetPinnableReference())
{
- fixed (byte* pBuffer = buffer)
+ if (_buffer != null)
{
- if (_buffer != null)
+ long bytesLeft = _capacity - pos;
+ if (bytesLeft < source.Length)
{
- long bytesLeft = _capacity - pos;
- if (bytesLeft < count)
- {
- throw new ArgumentException(SR.Arg_BufferTooSmall);
- }
+ throw new ArgumentException(SR.Arg_BufferTooSmall);
+ }
- byte* pointer = null;
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- _buffer.AcquirePointer(ref pointer);
- Buffer.Memcpy(pointer + pos + _offset, pBuffer + offset, count);
- }
- finally
- {
- if (pointer != null)
- {
- _buffer.ReleasePointer();
- }
- }
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ _buffer.AcquirePointer(ref pointer);
+ Buffer.Memcpy(pointer + pos + _offset, pBuffer, source.Length);
}
- else
+ finally
{
- Buffer.Memcpy(_mem + pos, pBuffer + offset, count);
+ if (pointer != null)
+ {
+ _buffer.ReleasePointer();
+ }
}
}
+ else
+ {
+ Buffer.Memcpy(_mem + pos, pBuffer, source.Length);
+ }
}
+
Interlocked.Exchange(ref _position, n);
return;
}
@@ -692,6 +751,29 @@ namespace System.IO
}
/// <summary>
+ /// Writes buffer into the stream. The operation completes synchronously.
+ /// </summary>
+ /// <param name="buffer">Buffer that will be written.</param>
+ /// <param name="cancellationToken">Token that can be used to cancel the operation.</param>
+ public override Task WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (cancellationToken.IsCancellationRequested)
+ {
+ return Task.FromCanceled(cancellationToken);
+ }
+
+ try
+ {
+ Write(source.Span);
+ return Task.CompletedTask;
+ }
+ catch (Exception ex)
+ {
+ return Task.FromException(ex);
+ }
+ }
+
+ /// <summary>
/// Writes a byte to the stream and advances the current Position.
/// </summary>
/// <param name="value"></param>
diff --git a/src/mscorlib/shared/System/IO/UnmanagedMemoryStreamWrapper.cs b/src/mscorlib/shared/System/IO/UnmanagedMemoryStreamWrapper.cs
index d547e771d7..2699912ea1 100644
--- a/src/mscorlib/shared/System/IO/UnmanagedMemoryStreamWrapper.cs
+++ b/src/mscorlib/shared/System/IO/UnmanagedMemoryStreamWrapper.cs
@@ -114,6 +114,11 @@ namespace System.IO
return _unmanagedStream.Read(buffer, offset, count);
}
+ public override int Read(Span<byte> destination)
+ {
+ return _unmanagedStream.Read(destination);
+ }
+
public override int ReadByte()
{
return _unmanagedStream.ReadByte();
@@ -136,6 +141,11 @@ namespace System.IO
_unmanagedStream.Write(buffer, offset, count);
}
+ public override void Write(ReadOnlySpan<byte> source)
+ {
+ _unmanagedStream.Write(source);
+ }
+
public override void WriteByte(byte value)
{
_unmanagedStream.WriteByte(value);
@@ -200,11 +210,21 @@ namespace System.IO
return _unmanagedStream.ReadAsync(buffer, offset, count, cancellationToken);
}
+ public override ValueTask<int> ReadAsync(Memory<byte> destination, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return _unmanagedStream.ReadAsync(destination, cancellationToken);
+ }
+
public override Task WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
{
return _unmanagedStream.WriteAsync(buffer, offset, count, cancellationToken);
}
+
+ public override Task WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return _unmanagedStream.WriteAsync(source, cancellationToken);
+ }
} // class UnmanagedMemoryStreamWrapper
} // namespace
diff --git a/src/mscorlib/shared/System/IO/Win32Marshal.cs b/src/mscorlib/shared/System/IO/Win32Marshal.cs
index a24409ed03..14a064a700 100644
--- a/src/mscorlib/shared/System/IO/Win32Marshal.cs
+++ b/src/mscorlib/shared/System/IO/Win32Marshal.cs
@@ -63,10 +63,16 @@ namespace System.IO
return new IOException(SR.Format(SR.IO_AlreadyExists_Name, path), MakeHRFromErrorCode(errorCode));
case Interop.Errors.ERROR_FILENAME_EXCED_RANGE:
- return new PathTooLongException(SR.Format(SR.IO_PathTooLong_Path, path));
+ if (path.Length == 0)
+ return new PathTooLongException(SR.IO_PathTooLong);
+ else
+ return new PathTooLongException(SR.Format(SR.IO_PathTooLong_Path, path));
+
+ case Interop.Errors.ERROR_INVALID_DRIVE:
+ throw new DriveNotFoundException(SR.Format(SR.IO_DriveNotFound_Drive, path));
case Interop.Errors.ERROR_INVALID_PARAMETER:
- return new IOException(GetMessage(errorCode), MakeHRFromErrorCode(errorCode));
+ return new IOException(Interop.Kernel32.GetMessage(errorCode), MakeHRFromErrorCode(errorCode));
case Interop.Errors.ERROR_SHARING_VIOLATION:
if (path.Length == 0)
@@ -84,7 +90,7 @@ namespace System.IO
return new OperationCanceledException();
default:
- return new IOException(GetMessage(errorCode), MakeHRFromErrorCode(errorCode));
+ return new IOException(Interop.Kernel32.GetMessage(errorCode), MakeHRFromErrorCode(errorCode));
}
}
@@ -97,13 +103,5 @@ namespace System.IO
return unchecked(((int)0x80070000) | errorCode);
}
-
- /// <summary>
- /// Returns a string message for the specified Win32 error code.
- /// </summary>
- internal static string GetMessage(int errorCode)
- {
- return Interop.Kernel32.GetMessage(errorCode);
- }
}
}
diff --git a/src/mscorlib/shared/System/IndexOutOfRangeException.cs b/src/mscorlib/shared/System/IndexOutOfRangeException.cs
index d5b24b35d5..bec63d73d6 100644
--- a/src/mscorlib/shared/System/IndexOutOfRangeException.cs
+++ b/src/mscorlib/shared/System/IndexOutOfRangeException.cs
@@ -20,19 +20,19 @@ namespace System
public IndexOutOfRangeException()
: base(SR.Arg_IndexOutOfRangeException)
{
- HResult = __HResults.COR_E_INDEXOUTOFRANGE;
+ HResult = HResults.COR_E_INDEXOUTOFRANGE;
}
public IndexOutOfRangeException(String message)
: base(message)
{
- HResult = __HResults.COR_E_INDEXOUTOFRANGE;
+ HResult = HResults.COR_E_INDEXOUTOFRANGE;
}
public IndexOutOfRangeException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_INDEXOUTOFRANGE;
+ HResult = HResults.COR_E_INDEXOUTOFRANGE;
}
}
}
diff --git a/src/mscorlib/shared/System/InsufficientExecutionStackException.cs b/src/mscorlib/shared/System/InsufficientExecutionStackException.cs
index 41df3ae970..a14cb67150 100644
--- a/src/mscorlib/shared/System/InsufficientExecutionStackException.cs
+++ b/src/mscorlib/shared/System/InsufficientExecutionStackException.cs
@@ -11,19 +11,19 @@ namespace System
public InsufficientExecutionStackException()
: base(SR.Arg_InsufficientExecutionStackException)
{
- HResult = __HResults.COR_E_INSUFFICIENTEXECUTIONSTACK;
+ HResult = HResults.COR_E_INSUFFICIENTEXECUTIONSTACK;
}
public InsufficientExecutionStackException(String message)
: base(message)
{
- HResult = __HResults.COR_E_INSUFFICIENTEXECUTIONSTACK;
+ HResult = HResults.COR_E_INSUFFICIENTEXECUTIONSTACK;
}
public InsufficientExecutionStackException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_INSUFFICIENTEXECUTIONSTACK;
+ HResult = HResults.COR_E_INSUFFICIENTEXECUTIONSTACK;
}
}
}
diff --git a/src/mscorlib/shared/System/Int16.cs b/src/mscorlib/shared/System/Int16.cs
new file mode 100644
index 0000000000..6aaf4280d3
--- /dev/null
+++ b/src/mscorlib/shared/System/Int16.cs
@@ -0,0 +1,320 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: This class will encapsulate a short and provide an
+** Object representation of it.
+**
+**
+===========================================================*/
+
+using System.Diagnostics.Contracts;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+
+namespace System
+{
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
+ [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ public struct Int16 : IComparable, IConvertible, IFormattable, IComparable<Int16>, IEquatable<Int16>
+ {
+ private short m_value; // Do not rename (binary serialization)
+
+ public const short MaxValue = (short)0x7FFF;
+ public const short MinValue = unchecked((short)0x8000);
+
+ // Compares this object to another object, returning an integer that
+ // indicates the relationship.
+ // Returns a value less than zero if this object
+ // null is considered to be less than any instance.
+ // If object is not of type Int16, this method throws an ArgumentException.
+ //
+ public int CompareTo(Object value)
+ {
+ if (value == null)
+ {
+ return 1;
+ }
+
+ if (value is Int16)
+ {
+ return m_value - ((Int16)value).m_value;
+ }
+
+ throw new ArgumentException(SR.Arg_MustBeInt16);
+ }
+
+ public int CompareTo(Int16 value)
+ {
+ return m_value - value;
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (!(obj is Int16))
+ {
+ return false;
+ }
+ return m_value == ((Int16)obj).m_value;
+ }
+
+ [NonVersionable]
+ public bool Equals(Int16 obj)
+ {
+ return m_value == obj;
+ }
+
+ // Returns a HashCode for the Int16
+ public override int GetHashCode()
+ {
+ return ((int)((ushort)m_value) | (((int)m_value) << 16));
+ }
+
+
+ public override String ToString()
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt32(m_value, null, NumberFormatInfo.CurrentInfo);
+ }
+
+ public String ToString(IFormatProvider provider)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt32(m_value, null, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public String ToString(String format)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return ToString(format, NumberFormatInfo.CurrentInfo);
+ }
+
+ public String ToString(String format, IFormatProvider provider)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return ToString(format, NumberFormatInfo.GetInstance(provider));
+ }
+
+ private String ToString(String format, NumberFormatInfo info)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+
+ if (m_value < 0 && format != null && format.Length > 0 && (format[0] == 'X' || format[0] == 'x'))
+ {
+ uint temp = (uint)(m_value & 0x0000FFFF);
+ return Number.FormatUInt32(temp, format, info);
+ }
+ return Number.FormatInt32(m_value, format, info);
+ }
+
+ public static short Parse(String s)
+ {
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Parse(s.AsReadOnlySpan(), NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
+ }
+
+ public static short Parse(String s, NumberStyles style)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Parse(s.AsReadOnlySpan(), style, NumberFormatInfo.CurrentInfo);
+ }
+
+ public static short Parse(String s, IFormatProvider provider)
+ {
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Parse(s.AsReadOnlySpan(), NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public static short Parse(String s, NumberStyles style, IFormatProvider provider)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Parse(s.AsReadOnlySpan(), style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public static short Parse(ReadOnlySpan<char> s, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Parse(s, style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ private static short Parse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info)
+ {
+ int i = 0;
+ try
+ {
+ i = Number.ParseInt32(s, style, info);
+ }
+ catch (OverflowException e)
+ {
+ throw new OverflowException(SR.Overflow_Int16, e);
+ }
+
+ // We need this check here since we don't allow signs to specified in hex numbers. So we fixup the result
+ // for negative numbers
+ if ((style & NumberStyles.AllowHexSpecifier) != 0)
+ { // We are parsing a hexadecimal number
+ if ((i < 0) || (i > UInt16.MaxValue))
+ {
+ throw new OverflowException(SR.Overflow_Int16);
+ }
+ return (short)i;
+ }
+
+ if (i < MinValue || i > MaxValue) throw new OverflowException(SR.Overflow_Int16);
+ return (short)i;
+ }
+
+ public static bool TryParse(String s, out Int16 result)
+ {
+ if (s == null)
+ {
+ result = 0;
+ return false;
+ }
+
+ return TryParse(s.AsReadOnlySpan(), NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
+ }
+
+ public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out Int16 result)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+
+ if (s == null)
+ {
+ result = 0;
+ return false;
+ }
+
+ return TryParse(s.AsReadOnlySpan(), style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ public static bool TryParse(ReadOnlySpan<char> s, out Int16 result, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ private static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out Int16 result)
+ {
+ result = 0;
+ int i;
+ if (!Number.TryParseInt32(s, style, info, out i))
+ {
+ return false;
+ }
+
+ // We need this check here since we don't allow signs to specified in hex numbers. So we fixup the result
+ // for negative numbers
+ if ((style & NumberStyles.AllowHexSpecifier) != 0)
+ { // We are parsing a hexadecimal number
+ if ((i < 0) || i > UInt16.MaxValue)
+ {
+ return false;
+ }
+ result = (Int16)i;
+ return true;
+ }
+
+ if (i < MinValue || i > MaxValue)
+ {
+ return false;
+ }
+ result = (Int16)i;
+ return true;
+ }
+
+ //
+ // IConvertible implementation
+ //
+
+ public TypeCode GetTypeCode()
+ {
+ return TypeCode.Int16;
+ }
+
+
+ bool IConvertible.ToBoolean(IFormatProvider provider)
+ {
+ return Convert.ToBoolean(m_value);
+ }
+
+ char IConvertible.ToChar(IFormatProvider provider)
+ {
+ return Convert.ToChar(m_value);
+ }
+
+ sbyte IConvertible.ToSByte(IFormatProvider provider)
+ {
+ return Convert.ToSByte(m_value);
+ }
+
+ byte IConvertible.ToByte(IFormatProvider provider)
+ {
+ return Convert.ToByte(m_value);
+ }
+
+ short IConvertible.ToInt16(IFormatProvider provider)
+ {
+ return m_value;
+ }
+
+ ushort IConvertible.ToUInt16(IFormatProvider provider)
+ {
+ return Convert.ToUInt16(m_value);
+ }
+
+ int IConvertible.ToInt32(IFormatProvider provider)
+ {
+ return Convert.ToInt32(m_value);
+ }
+
+ uint IConvertible.ToUInt32(IFormatProvider provider)
+ {
+ return Convert.ToUInt32(m_value);
+ }
+
+ long IConvertible.ToInt64(IFormatProvider provider)
+ {
+ return Convert.ToInt64(m_value);
+ }
+
+ ulong IConvertible.ToUInt64(IFormatProvider provider)
+ {
+ return Convert.ToUInt64(m_value);
+ }
+
+ float IConvertible.ToSingle(IFormatProvider provider)
+ {
+ return Convert.ToSingle(m_value);
+ }
+
+ double IConvertible.ToDouble(IFormatProvider provider)
+ {
+ return Convert.ToDouble(m_value);
+ }
+
+ Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ {
+ return Convert.ToDecimal(m_value);
+ }
+
+ DateTime IConvertible.ToDateTime(IFormatProvider provider)
+ {
+ throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Int16", "DateTime"));
+ }
+
+ Object IConvertible.ToType(Type type, IFormatProvider provider)
+ {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/Int32.cs b/src/mscorlib/shared/System/Int32.cs
new file mode 100644
index 0000000000..f5e832a274
--- /dev/null
+++ b/src/mscorlib/shared/System/Int32.cs
@@ -0,0 +1,285 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: A representation of a 32 bit 2's complement
+** integer.
+**
+**
+===========================================================*/
+
+using System.Diagnostics.Contracts;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+
+namespace System
+{
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
+ [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ public struct Int32 : IComparable, IConvertible, IFormattable, IComparable<Int32>, IEquatable<Int32>
+ {
+ private int m_value; // Do not rename (binary serialization)
+
+ public const int MaxValue = 0x7fffffff;
+ public const int MinValue = unchecked((int)0x80000000);
+
+ // Compares this object to another object, returning an integer that
+ // indicates the relationship.
+ // Returns :
+ // 0 if the values are equal
+ // Negative number if _value is less than value
+ // Positive number if _value is more than value
+ // null is considered to be less than any instance, hence returns positive number
+ // If object is not of type Int32, this method throws an ArgumentException.
+ //
+ public int CompareTo(Object value)
+ {
+ if (value == null)
+ {
+ return 1;
+ }
+ if (value is Int32)
+ {
+ // NOTE: Cannot use return (_value - value) as this causes a wrap
+ // around in cases where _value - value > MaxValue.
+ int i = (int)value;
+ if (m_value < i) return -1;
+ if (m_value > i) return 1;
+ return 0;
+ }
+ throw new ArgumentException(SR.Arg_MustBeInt32);
+ }
+
+ public int CompareTo(int value)
+ {
+ // NOTE: Cannot use return (_value - value) as this causes a wrap
+ // around in cases where _value - value > MaxValue.
+ if (m_value < value) return -1;
+ if (m_value > value) return 1;
+ return 0;
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (!(obj is Int32))
+ {
+ return false;
+ }
+ return m_value == ((Int32)obj).m_value;
+ }
+
+ [NonVersionable]
+ public bool Equals(Int32 obj)
+ {
+ return m_value == obj;
+ }
+
+ // The absolute value of the int contained.
+ public override int GetHashCode()
+ {
+ return m_value;
+ }
+
+ [Pure]
+ public override String ToString()
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt32(m_value, null, NumberFormatInfo.CurrentInfo);
+ }
+
+ [Pure]
+ public String ToString(String format)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt32(m_value, format, NumberFormatInfo.CurrentInfo);
+ }
+
+ [Pure]
+ public String ToString(IFormatProvider provider)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt32(m_value, null, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [Pure]
+ public String ToString(String format, IFormatProvider provider)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt32(m_value, format, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [Pure]
+ public static int Parse(String s)
+ {
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseInt32(s.AsReadOnlySpan(), NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
+ }
+
+ [Pure]
+ public static int Parse(String s, NumberStyles style)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseInt32(s.AsReadOnlySpan(), style, NumberFormatInfo.CurrentInfo);
+ }
+
+ // Parses an integer from a String in the given style. If
+ // a NumberFormatInfo isn't specified, the current culture's
+ // NumberFormatInfo is assumed.
+ //
+ [Pure]
+ public static int Parse(String s, IFormatProvider provider)
+ {
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseInt32(s.AsReadOnlySpan(), NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
+ }
+
+ // Parses an integer from a String in the given style. If
+ // a NumberFormatInfo isn't specified, the current culture's
+ // NumberFormatInfo is assumed.
+ //
+ [Pure]
+ public static int Parse(String s, NumberStyles style, IFormatProvider provider)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseInt32(s.AsReadOnlySpan(), style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public static int Parse(ReadOnlySpan<char> s, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Number.ParseInt32(s, style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ // Parses an integer from a String. Returns false rather
+ // than throwing exceptin if input is invalid
+ //
+ [Pure]
+ public static bool TryParse(String s, out Int32 result)
+ {
+ if (s == null)
+ {
+ result = 0;
+ return false;
+ }
+
+ return Number.TryParseInt32(s.AsReadOnlySpan(), NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
+ }
+
+ // Parses an integer from a String in the given style. Returns false rather
+ // than throwing exceptin if input is invalid
+ //
+ [Pure]
+ public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out Int32 result)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+
+ if (s == null)
+ {
+ result = 0;
+ return false;
+ }
+
+ return Number.TryParseInt32(s.AsReadOnlySpan(), style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ public static bool TryParse(ReadOnlySpan<char> s, out int result, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Number.TryParseInt32(s, style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ //
+ // IConvertible implementation
+ //
+
+ [Pure]
+ public TypeCode GetTypeCode()
+ {
+ return TypeCode.Int32;
+ }
+
+ bool IConvertible.ToBoolean(IFormatProvider provider)
+ {
+ return Convert.ToBoolean(m_value);
+ }
+
+ char IConvertible.ToChar(IFormatProvider provider)
+ {
+ return Convert.ToChar(m_value);
+ }
+
+ sbyte IConvertible.ToSByte(IFormatProvider provider)
+ {
+ return Convert.ToSByte(m_value);
+ }
+
+ byte IConvertible.ToByte(IFormatProvider provider)
+ {
+ return Convert.ToByte(m_value);
+ }
+
+ short IConvertible.ToInt16(IFormatProvider provider)
+ {
+ return Convert.ToInt16(m_value);
+ }
+
+ ushort IConvertible.ToUInt16(IFormatProvider provider)
+ {
+ return Convert.ToUInt16(m_value);
+ }
+
+ int IConvertible.ToInt32(IFormatProvider provider)
+ {
+ return m_value;
+ }
+
+ uint IConvertible.ToUInt32(IFormatProvider provider)
+ {
+ return Convert.ToUInt32(m_value);
+ }
+
+ long IConvertible.ToInt64(IFormatProvider provider)
+ {
+ return Convert.ToInt64(m_value);
+ }
+
+ ulong IConvertible.ToUInt64(IFormatProvider provider)
+ {
+ return Convert.ToUInt64(m_value);
+ }
+
+ float IConvertible.ToSingle(IFormatProvider provider)
+ {
+ return Convert.ToSingle(m_value);
+ }
+
+ double IConvertible.ToDouble(IFormatProvider provider)
+ {
+ return Convert.ToDouble(m_value);
+ }
+
+ Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ {
+ return Convert.ToDecimal(m_value);
+ }
+
+ DateTime IConvertible.ToDateTime(IFormatProvider provider)
+ {
+ throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Int32", "DateTime"));
+ }
+
+ Object IConvertible.ToType(Type type, IFormatProvider provider)
+ {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/Int64.cs b/src/mscorlib/shared/System/Int64.cs
new file mode 100644
index 0000000000..785fa39fa5
--- /dev/null
+++ b/src/mscorlib/shared/System/Int64.cs
@@ -0,0 +1,262 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: This class will encapsulate a long and provide an
+** Object representation of it.
+**
+**
+===========================================================*/
+
+using System.Diagnostics.Contracts;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+
+namespace System
+{
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
+ [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ public struct Int64 : IComparable, IConvertible, IFormattable, IComparable<Int64>, IEquatable<Int64>
+ {
+ private long m_value; // Do not rename (binary serialization)
+
+ public const long MaxValue = 0x7fffffffffffffffL;
+ public const long MinValue = unchecked((long)0x8000000000000000L);
+
+ // Compares this object to another object, returning an integer that
+ // indicates the relationship.
+ // Returns a value less than zero if this object
+ // null is considered to be less than any instance.
+ // If object is not of type Int64, this method throws an ArgumentException.
+ //
+ public int CompareTo(Object value)
+ {
+ if (value == null)
+ {
+ return 1;
+ }
+ if (value is Int64)
+ {
+ // Need to use compare because subtraction will wrap
+ // to positive for very large neg numbers, etc.
+ long i = (long)value;
+ if (m_value < i) return -1;
+ if (m_value > i) return 1;
+ return 0;
+ }
+ throw new ArgumentException(SR.Arg_MustBeInt64);
+ }
+
+ public int CompareTo(Int64 value)
+ {
+ // Need to use compare because subtraction will wrap
+ // to positive for very large neg numbers, etc.
+ if (m_value < value) return -1;
+ if (m_value > value) return 1;
+ return 0;
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (!(obj is Int64))
+ {
+ return false;
+ }
+ return m_value == ((Int64)obj).m_value;
+ }
+
+ [NonVersionable]
+ public bool Equals(Int64 obj)
+ {
+ return m_value == obj;
+ }
+
+ // The value of the lower 32 bits XORed with the uppper 32 bits.
+ public override int GetHashCode()
+ {
+ return (unchecked((int)((long)m_value)) ^ (int)(m_value >> 32));
+ }
+
+ public override String ToString()
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt64(m_value, null, NumberFormatInfo.CurrentInfo);
+ }
+
+ public String ToString(IFormatProvider provider)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt64(m_value, null, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public String ToString(String format)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt64(m_value, format, NumberFormatInfo.CurrentInfo);
+ }
+
+ public String ToString(String format, IFormatProvider provider)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt64(m_value, format, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public static long Parse(String s)
+ {
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseInt64(s.AsReadOnlySpan(), NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
+ }
+
+ public static long Parse(String s, NumberStyles style)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseInt64(s.AsReadOnlySpan(), style, NumberFormatInfo.CurrentInfo);
+ }
+
+ public static long Parse(String s, IFormatProvider provider)
+ {
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseInt64(s.AsReadOnlySpan(), NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
+ }
+
+
+ // Parses a long from a String in the given style. If
+ // a NumberFormatInfo isn't specified, the current culture's
+ // NumberFormatInfo is assumed.
+ //
+ public static long Parse(String s, NumberStyles style, IFormatProvider provider)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseInt64(s.AsReadOnlySpan(), style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public static long Parse(ReadOnlySpan<char> s, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Number.ParseInt64(s, style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public static Boolean TryParse(String s, out Int64 result)
+ {
+ if (s == null)
+ {
+ result = 0;
+ return false;
+ }
+
+ return Number.TryParseInt64(s.AsReadOnlySpan(), NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
+ }
+
+ public static Boolean TryParse(String s, NumberStyles style, IFormatProvider provider, out Int64 result)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+
+ if (s == null)
+ {
+ result = 0;
+ return false;
+ }
+
+ return Number.TryParseInt64(s.AsReadOnlySpan(), style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ public static bool TryParse(ReadOnlySpan<char> s, out long result, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Number.TryParseInt64(s, style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ //
+ // IConvertible implementation
+ //
+
+ public TypeCode GetTypeCode()
+ {
+ return TypeCode.Int64;
+ }
+
+ bool IConvertible.ToBoolean(IFormatProvider provider)
+ {
+ return Convert.ToBoolean(m_value);
+ }
+
+ char IConvertible.ToChar(IFormatProvider provider)
+ {
+ return Convert.ToChar(m_value);
+ }
+
+ sbyte IConvertible.ToSByte(IFormatProvider provider)
+ {
+ return Convert.ToSByte(m_value);
+ }
+
+ byte IConvertible.ToByte(IFormatProvider provider)
+ {
+ return Convert.ToByte(m_value);
+ }
+
+ short IConvertible.ToInt16(IFormatProvider provider)
+ {
+ return Convert.ToInt16(m_value);
+ }
+
+ ushort IConvertible.ToUInt16(IFormatProvider provider)
+ {
+ return Convert.ToUInt16(m_value);
+ }
+
+ int IConvertible.ToInt32(IFormatProvider provider)
+ {
+ return Convert.ToInt32(m_value);
+ }
+
+ uint IConvertible.ToUInt32(IFormatProvider provider)
+ {
+ return Convert.ToUInt32(m_value);
+ }
+
+ long IConvertible.ToInt64(IFormatProvider provider)
+ {
+ return m_value;
+ }
+
+ ulong IConvertible.ToUInt64(IFormatProvider provider)
+ {
+ return Convert.ToUInt64(m_value);
+ }
+
+ float IConvertible.ToSingle(IFormatProvider provider)
+ {
+ return Convert.ToSingle(m_value);
+ }
+
+ double IConvertible.ToDouble(IFormatProvider provider)
+ {
+ return Convert.ToDouble(m_value);
+ }
+
+ Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ {
+ return Convert.ToDecimal(m_value);
+ }
+
+ DateTime IConvertible.ToDateTime(IFormatProvider provider)
+ {
+ throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Int64", "DateTime"));
+ }
+
+ Object IConvertible.ToType(Type type, IFormatProvider provider)
+ {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/InvalidCastException.cs b/src/mscorlib/shared/System/InvalidCastException.cs
index cf359ac0b5..00b393c60e 100644
--- a/src/mscorlib/shared/System/InvalidCastException.cs
+++ b/src/mscorlib/shared/System/InvalidCastException.cs
@@ -17,19 +17,19 @@ namespace System
public InvalidCastException()
: base(SR.Arg_InvalidCastException)
{
- HResult = __HResults.COR_E_INVALIDCAST;
+ HResult = HResults.COR_E_INVALIDCAST;
}
public InvalidCastException(String message)
: base(message)
{
- HResult = __HResults.COR_E_INVALIDCAST;
+ HResult = HResults.COR_E_INVALIDCAST;
}
public InvalidCastException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_INVALIDCAST;
+ HResult = HResults.COR_E_INVALIDCAST;
}
public InvalidCastException(String message, int errorCode)
diff --git a/src/mscorlib/shared/System/InvalidOperationException.cs b/src/mscorlib/shared/System/InvalidOperationException.cs
index ad743e05ff..74a4ffd74a 100644
--- a/src/mscorlib/shared/System/InvalidOperationException.cs
+++ b/src/mscorlib/shared/System/InvalidOperationException.cs
@@ -21,19 +21,19 @@ namespace System
public InvalidOperationException()
: base(SR.Arg_InvalidOperationException)
{
- HResult = __HResults.COR_E_INVALIDOPERATION;
+ HResult = HResults.COR_E_INVALIDOPERATION;
}
public InvalidOperationException(String message)
: base(message)
{
- HResult = __HResults.COR_E_INVALIDOPERATION;
+ HResult = HResults.COR_E_INVALIDOPERATION;
}
public InvalidOperationException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_INVALIDOPERATION;
+ HResult = HResults.COR_E_INVALIDOPERATION;
}
protected InvalidOperationException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/InvalidProgramException.cs b/src/mscorlib/shared/System/InvalidProgramException.cs
index 47e7325836..e3521574ea 100644
--- a/src/mscorlib/shared/System/InvalidProgramException.cs
+++ b/src/mscorlib/shared/System/InvalidProgramException.cs
@@ -20,19 +20,19 @@ namespace System
public InvalidProgramException()
: base(SR.InvalidProgram_Default)
{
- HResult = __HResults.COR_E_INVALIDPROGRAM;
+ HResult = HResults.COR_E_INVALIDPROGRAM;
}
public InvalidProgramException(String message)
: base(message)
{
- HResult = __HResults.COR_E_INVALIDPROGRAM;
+ HResult = HResults.COR_E_INVALIDPROGRAM;
}
public InvalidProgramException(String message, Exception inner)
: base(message, inner)
{
- HResult = __HResults.COR_E_INVALIDPROGRAM;
+ HResult = HResults.COR_E_INVALIDPROGRAM;
}
}
}
diff --git a/src/mscorlib/shared/System/Lazy.cs b/src/mscorlib/shared/System/Lazy.cs
index 5d68714c7e..2ef3cd2e5f 100644
--- a/src/mscorlib/shared/System/Lazy.cs
+++ b/src/mscorlib/shared/System/Lazy.cs
@@ -261,7 +261,7 @@ namespace System
/// Initializes a new instance of the <see cref="T:System.Threading.Lazy{T}"/>
/// class that uses <typeparamref name="T"/>'s default constructor and a specified thread-safety mode.
/// </summary>
- /// <param name="mode">The lazy thread-safety mode mode</param>
+ /// <param name="mode">The lazy thread-safety mode</param>
/// <exception cref="System.ArgumentOutOfRangeException"><paramref name="mode"/> mode contains an invalid valuee</exception>
public Lazy(LazyThreadSafetyMode mode) :
this(null, mode, useDefaultConstructor:true)
diff --git a/src/mscorlib/shared/System/MemberAccessException.cs b/src/mscorlib/shared/System/MemberAccessException.cs
index abca952f19..bb26d9e3c4 100644
--- a/src/mscorlib/shared/System/MemberAccessException.cs
+++ b/src/mscorlib/shared/System/MemberAccessException.cs
@@ -23,7 +23,7 @@ namespace System
public MemberAccessException()
: base(SR.Arg_AccessException)
{
- HResult = __HResults.COR_E_MEMBERACCESS;
+ HResult = HResults.COR_E_MEMBERACCESS;
}
// Creates a new MemberAccessException with its message string set to
@@ -33,13 +33,13 @@ namespace System
public MemberAccessException(String message)
: base(message)
{
- HResult = __HResults.COR_E_MEMBERACCESS;
+ HResult = HResults.COR_E_MEMBERACCESS;
}
public MemberAccessException(String message, Exception inner)
: base(message, inner)
{
- HResult = __HResults.COR_E_MEMBERACCESS;
+ HResult = HResults.COR_E_MEMBERACCESS;
}
protected MemberAccessException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/Memory.cs b/src/mscorlib/shared/System/Memory.cs
new file mode 100644
index 0000000000..270f88e4bc
--- /dev/null
+++ b/src/mscorlib/shared/System/Memory.cs
@@ -0,0 +1,284 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Buffers;
+using EditorBrowsableAttribute = System.ComponentModel.EditorBrowsableAttribute;
+using EditorBrowsableState = System.ComponentModel.EditorBrowsableState;
+using System.Diagnostics;
+using System.Runtime;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace System
+{
+ public struct Memory<T>
+ {
+ // The highest order bit of _index is used to discern whether _arrayOrOwnedMemory is an array or an owned memory
+ // if (_index >> 31) == 1, object _arrayOrOwnedMemory is an OwnedMemory<T>
+ // else, object _arrayOrOwnedMemory is a T[]
+ private readonly object _arrayOrOwnedMemory;
+ private readonly int _index;
+ private readonly int _length;
+
+ private const int RemoveOwnedFlagBitMask = 0x7FFFFFFF;
+
+ /// <summary>
+ /// Creates a new memory over the entirety of the target array.
+ /// </summary>
+ /// <param name="array">The target array.</param>
+ /// <exception cref="System.ArgumentNullException">Thrown when <paramref name="array"/> is a null
+ /// reference (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant and array's type is not exactly T[].</exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Memory(T[] array)
+ {
+ if (array == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ if (default(T) == null && array.GetType() != typeof(T[]))
+ ThrowHelper.ThrowArrayTypeMismatchException();
+
+ _arrayOrOwnedMemory = array;
+ _index = 0;
+ _length = array.Length;
+ }
+
+ /// <summary>
+ /// Creates a new memory over the portion of the target array beginning
+ /// at 'start' index and ending at 'end' index (exclusive).
+ /// </summary>
+ /// <param name="array">The target array.</param>
+ /// <param name="start">The index at which to begin the memory.</param>
+ /// <param name="length">The number of items in the memory.</param>
+ /// <exception cref="System.ArgumentNullException">Thrown when <paramref name="array"/> is a null
+ /// reference (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant and array's type is not exactly T[].</exception>
+ /// <exception cref="System.ArgumentOutOfRangeException">
+ /// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;=Length).
+ /// </exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Memory(T[] array, int start, int length)
+ {
+ if (array == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ if (default(T) == null && array.GetType() != typeof(T[]))
+ ThrowHelper.ThrowArrayTypeMismatchException();
+ if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start))
+ ThrowHelper.ThrowArgumentOutOfRangeException();
+
+ _arrayOrOwnedMemory = array;
+ _index = start;
+ _length = length;
+ }
+
+ // Constructor for internal use only.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal Memory(OwnedMemory<T> owner, int index, int length)
+ {
+ if (owner == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.ownedMemory);
+ if (index < 0 || length < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException();
+
+ _arrayOrOwnedMemory = owner;
+ _index = index | (1 << 31); // Before using _index, check if _index < 0, then 'and' it with RemoveOwnedFlagBitMask
+ _length = length;
+ }
+
+ /// <summary>
+ /// Defines an implicit conversion of an array to a <see cref="Memory{T}"/>
+ /// </summary>
+ public static implicit operator Memory<T>(T[] array) => new Memory<T>(array);
+
+ /// <summary>
+ /// Defines an implicit conversion of a <see cref="ArraySegment{T}"/> to a <see cref="Memory{T}"/>
+ /// </summary>
+ public static implicit operator Memory<T>(ArraySegment<T> arraySegment) => new Memory<T>(arraySegment.Array, arraySegment.Offset, arraySegment.Count);
+
+ /// <summary>
+ /// Defines an implicit conversion of a <see cref="Memory{T}"/> to a <see cref="ReadOnlyMemory{T}"/>
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator ReadOnlyMemory<T>(Memory<T> memory)
+ {
+ if (memory._index < 0)
+ return new ReadOnlyMemory<T>((OwnedMemory<T>)memory._arrayOrOwnedMemory, memory._index & RemoveOwnedFlagBitMask, memory._length);
+ return new ReadOnlyMemory<T>((T[])memory._arrayOrOwnedMemory, memory._index, memory._length);
+ }
+
+ /// <summary>
+ /// Returns an empty <see cref="Memory{T}"/>
+ /// </summary>
+ public static Memory<T> Empty { get; } = Array.Empty<T>();
+
+ /// <summary>
+ /// The number of items in the memory.
+ /// </summary>
+ public int Length => _length;
+
+ /// <summary>
+ /// Returns true if Length is 0.
+ /// </summary>
+ public bool IsEmpty => _length == 0;
+
+ /// <summary>
+ /// Forms a slice out of the given memory, beginning at 'start'.
+ /// </summary>
+ /// <param name="start">The index at which to begin this slice.</param>
+ /// <exception cref="System.ArgumentOutOfRangeException">
+ /// Thrown when the specified <paramref name="start"/> index is not in range (&lt;0 or &gt;=Length).
+ /// </exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Memory<T> Slice(int start)
+ {
+ if ((uint)start > (uint)_length)
+ ThrowHelper.ThrowArgumentOutOfRangeException();
+
+ if (_index < 0)
+ return new Memory<T>((OwnedMemory<T>)_arrayOrOwnedMemory, (_index & RemoveOwnedFlagBitMask) + start, _length - start);
+ return new Memory<T>((T[])_arrayOrOwnedMemory, _index + start, _length - start);
+ }
+
+ /// <summary>
+ /// Forms a slice out of the given memory, beginning at 'start', of given length
+ /// </summary>
+ /// <param name="start">The index at which to begin this slice.</param>
+ /// <param name="length">The desired length for the slice (exclusive).</param>
+ /// <exception cref="System.ArgumentOutOfRangeException">
+ /// Thrown when the specified <paramref name="start"/> or end index is not in range (&lt;0 or &gt;=Length).
+ /// </exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Memory<T> Slice(int start, int length)
+ {
+ if ((uint)start > (uint)_length || (uint)length > (uint)(_length - start))
+ ThrowHelper.ThrowArgumentOutOfRangeException();
+
+ if (_index < 0)
+ return new Memory<T>((OwnedMemory<T>)_arrayOrOwnedMemory, (_index & RemoveOwnedFlagBitMask) + start, length);
+ return new Memory<T>((T[])_arrayOrOwnedMemory, _index + start, length);
+ }
+
+ /// <summary>
+ /// Returns a span from the memory.
+ /// </summary>
+ public Span<T> Span
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ if (_index < 0)
+ return ((OwnedMemory<T>)_arrayOrOwnedMemory).AsSpan().Slice(_index & RemoveOwnedFlagBitMask, _length);
+ return new Span<T>((T[])_arrayOrOwnedMemory, _index, _length);
+ }
+ }
+
+ public unsafe MemoryHandle Retain(bool pin = false)
+ {
+ MemoryHandle memoryHandle;
+ if (pin)
+ {
+ if (_index < 0)
+ {
+ memoryHandle = ((OwnedMemory<T>)_arrayOrOwnedMemory).Pin();
+ }
+ else
+ {
+ var array = (T[])_arrayOrOwnedMemory;
+ var handle = GCHandle.Alloc(array, GCHandleType.Pinned);
+ void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref array.GetRawSzArrayData()), _index);
+ memoryHandle = new MemoryHandle(null, pointer, handle);
+ }
+ }
+ else
+ {
+ if (_index < 0)
+ {
+ ((OwnedMemory<T>)_arrayOrOwnedMemory).Retain();
+ memoryHandle = new MemoryHandle((OwnedMemory<T>)_arrayOrOwnedMemory);
+ }
+ else
+ {
+ memoryHandle = new MemoryHandle(null);
+ }
+ }
+ return memoryHandle;
+ }
+
+ /// <summary>
+ /// Get an array segment from the underlying memory.
+ /// If unable to get the array segment, return false with a default array segment.
+ /// </summary>
+ public bool TryGetArray(out ArraySegment<T> arraySegment)
+ {
+ if (_index < 0)
+ {
+ if (((OwnedMemory<T>)_arrayOrOwnedMemory).TryGetArray(out var segment))
+ {
+ arraySegment = new ArraySegment<T>(segment.Array, segment.Offset + (_index & RemoveOwnedFlagBitMask), _length);
+ return true;
+ }
+ }
+ else
+ {
+ arraySegment = new ArraySegment<T>((T[])_arrayOrOwnedMemory, _index, _length);
+ return true;
+ }
+
+ arraySegment = default(ArraySegment<T>);
+ return false;
+ }
+
+ /// <summary>
+ /// Copies the contents from the memory into a new array. This heap
+ /// allocates, so should generally be avoided, however it is sometimes
+ /// necessary to bridge the gap with APIs written in terms of arrays.
+ /// </summary>
+ public T[] ToArray() => Span.ToArray();
+
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public override bool Equals(object obj)
+ {
+ if (obj is ReadOnlyMemory<T>)
+ {
+ return ((ReadOnlyMemory<T>)obj).Equals(this);
+ }
+ else if (obj is Memory<T> memory)
+ {
+ return Equals(memory);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Returns true if the memory points to the same array and has the same length. Note that
+ /// this does *not* check to see if the *contents* are equal.
+ /// </summary>
+ public bool Equals(Memory<T> other)
+ {
+ return
+ _arrayOrOwnedMemory == other._arrayOrOwnedMemory &&
+ _index == other._index &&
+ _length == other._length;
+ }
+
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public override int GetHashCode()
+ {
+ return CombineHashCodes(_arrayOrOwnedMemory.GetHashCode(), (_index & RemoveOwnedFlagBitMask).GetHashCode(), _length.GetHashCode());
+ }
+
+ private static int CombineHashCodes(int left, int right)
+ {
+ return ((left << 5) + left) ^ right;
+ }
+
+ private static int CombineHashCodes(int h1, int h2, int h3)
+ {
+ return CombineHashCodes(CombineHashCodes(h1, h2), h3);
+ }
+
+ }
+} \ No newline at end of file
diff --git a/src/mscorlib/shared/System/MethodAccessException.cs b/src/mscorlib/shared/System/MethodAccessException.cs
index 2c9c998c15..12691386c5 100644
--- a/src/mscorlib/shared/System/MethodAccessException.cs
+++ b/src/mscorlib/shared/System/MethodAccessException.cs
@@ -18,19 +18,19 @@ namespace System
public MethodAccessException()
: base(SR.Arg_MethodAccessException)
{
- HResult = __HResults.COR_E_METHODACCESS;
+ HResult = HResults.COR_E_METHODACCESS;
}
public MethodAccessException(String message)
: base(message)
{
- HResult = __HResults.COR_E_METHODACCESS;
+ HResult = HResults.COR_E_METHODACCESS;
}
public MethodAccessException(String message, Exception inner)
: base(message, inner)
{
- HResult = __HResults.COR_E_METHODACCESS;
+ HResult = HResults.COR_E_METHODACCESS;
}
protected MethodAccessException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/MissingMethodException.cs b/src/mscorlib/shared/System/MissingMethodException.cs
index 967f434302..4f5e8b6562 100644
--- a/src/mscorlib/shared/System/MissingMethodException.cs
+++ b/src/mscorlib/shared/System/MissingMethodException.cs
@@ -20,19 +20,19 @@ namespace System
public MissingMethodException()
: base(SR.Arg_MissingMethodException)
{
- HResult = __HResults.COR_E_MISSINGMETHOD;
+ HResult = HResults.COR_E_MISSINGMETHOD;
}
public MissingMethodException(string message)
: base(message)
{
- HResult = __HResults.COR_E_MISSINGMETHOD;
+ HResult = HResults.COR_E_MISSINGMETHOD;
}
public MissingMethodException(string message, Exception inner)
: base(message, inner)
{
- HResult = __HResults.COR_E_MISSINGMETHOD;
+ HResult = HResults.COR_E_MISSINGMETHOD;
}
public MissingMethodException(string className, string methodName)
diff --git a/src/mscorlib/shared/System/MulticastNotSupportedException.cs b/src/mscorlib/shared/System/MulticastNotSupportedException.cs
index 493671e227..56a3ec9c00 100644
--- a/src/mscorlib/shared/System/MulticastNotSupportedException.cs
+++ b/src/mscorlib/shared/System/MulticastNotSupportedException.cs
@@ -16,19 +16,19 @@ namespace System
public MulticastNotSupportedException()
: base(SR.Arg_MulticastNotSupportedException)
{
- HResult = __HResults.COR_E_MULTICASTNOTSUPPORTED;
+ HResult = HResults.COR_E_MULTICASTNOTSUPPORTED;
}
public MulticastNotSupportedException(String message)
: base(message)
{
- HResult = __HResults.COR_E_MULTICASTNOTSUPPORTED;
+ HResult = HResults.COR_E_MULTICASTNOTSUPPORTED;
}
public MulticastNotSupportedException(String message, Exception inner)
: base(message, inner)
{
- HResult = __HResults.COR_E_MULTICASTNOTSUPPORTED;
+ HResult = HResults.COR_E_MULTICASTNOTSUPPORTED;
}
}
}
diff --git a/src/mscorlib/shared/System/NonSerializedAttribute.cs b/src/mscorlib/shared/System/NonSerializedAttribute.cs
new file mode 100644
index 0000000000..cabd5a2aa2
--- /dev/null
+++ b/src/mscorlib/shared/System/NonSerializedAttribute.cs
@@ -0,0 +1,14 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System
+{
+ [AttributeUsage(AttributeTargets.Field, Inherited = false)]
+ public sealed class NonSerializedAttribute : Attribute
+ {
+ public NonSerializedAttribute()
+ {
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/NotFiniteNumberException.cs b/src/mscorlib/shared/System/NotFiniteNumberException.cs
index 99882b9eb2..ca47a21e5c 100644
--- a/src/mscorlib/shared/System/NotFiniteNumberException.cs
+++ b/src/mscorlib/shared/System/NotFiniteNumberException.cs
@@ -14,41 +14,41 @@ namespace System
: base(SR.Arg_NotFiniteNumberException)
{
_offendingNumber = 0;
- HResult = __HResults.COR_E_NOTFINITENUMBER;
+ HResult = HResults.COR_E_NOTFINITENUMBER;
}
public NotFiniteNumberException(double offendingNumber)
: base()
{
_offendingNumber = offendingNumber;
- HResult = __HResults.COR_E_NOTFINITENUMBER;
+ HResult = HResults.COR_E_NOTFINITENUMBER;
}
public NotFiniteNumberException(String message)
: base(message)
{
_offendingNumber = 0;
- HResult = __HResults.COR_E_NOTFINITENUMBER;
+ HResult = HResults.COR_E_NOTFINITENUMBER;
}
public NotFiniteNumberException(String message, double offendingNumber)
: base(message)
{
_offendingNumber = offendingNumber;
- HResult = __HResults.COR_E_NOTFINITENUMBER;
+ HResult = HResults.COR_E_NOTFINITENUMBER;
}
public NotFiniteNumberException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_NOTFINITENUMBER;
+ HResult = HResults.COR_E_NOTFINITENUMBER;
}
public NotFiniteNumberException(String message, double offendingNumber, Exception innerException)
: base(message, innerException)
{
_offendingNumber = offendingNumber;
- HResult = __HResults.COR_E_NOTFINITENUMBER;
+ HResult = HResults.COR_E_NOTFINITENUMBER;
}
protected NotFiniteNumberException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/NotImplementedException.cs b/src/mscorlib/shared/System/NotImplementedException.cs
index ae62527fac..98976c19db 100644
--- a/src/mscorlib/shared/System/NotImplementedException.cs
+++ b/src/mscorlib/shared/System/NotImplementedException.cs
@@ -21,17 +21,17 @@ namespace System
public NotImplementedException()
: base(SR.Arg_NotImplementedException)
{
- HResult = __HResults.E_NOTIMPL;
+ HResult = HResults.E_NOTIMPL;
}
public NotImplementedException(String message)
: base(message)
{
- HResult = __HResults.E_NOTIMPL;
+ HResult = HResults.E_NOTIMPL;
}
public NotImplementedException(String message, Exception inner)
: base(message, inner)
{
- HResult = __HResults.E_NOTIMPL;
+ HResult = HResults.E_NOTIMPL;
}
protected NotImplementedException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/NotSupportedException.cs b/src/mscorlib/shared/System/NotSupportedException.cs
index 8532e5ad2f..dc43261fbd 100644
--- a/src/mscorlib/shared/System/NotSupportedException.cs
+++ b/src/mscorlib/shared/System/NotSupportedException.cs
@@ -20,19 +20,19 @@ namespace System
public NotSupportedException()
: base(SR.Arg_NotSupportedException)
{
- HResult = __HResults.COR_E_NOTSUPPORTED;
+ HResult = HResults.COR_E_NOTSUPPORTED;
}
public NotSupportedException(String message)
: base(message)
{
- HResult = __HResults.COR_E_NOTSUPPORTED;
+ HResult = HResults.COR_E_NOTSUPPORTED;
}
public NotSupportedException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_NOTSUPPORTED;
+ HResult = HResults.COR_E_NOTSUPPORTED;
}
protected NotSupportedException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/NullReferenceException.cs b/src/mscorlib/shared/System/NullReferenceException.cs
index f689345654..eb6d709dbf 100644
--- a/src/mscorlib/shared/System/NullReferenceException.cs
+++ b/src/mscorlib/shared/System/NullReferenceException.cs
@@ -20,19 +20,19 @@ namespace System
public NullReferenceException()
: base(SR.Arg_NullReferenceException)
{
- HResult = __HResults.COR_E_NULLREFERENCE;
+ HResult = HResults.COR_E_NULLREFERENCE;
}
public NullReferenceException(String message)
: base(message)
{
- HResult = __HResults.COR_E_NULLREFERENCE;
+ HResult = HResults.COR_E_NULLREFERENCE;
}
public NullReferenceException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_NULLREFERENCE;
+ HResult = HResults.COR_E_NULLREFERENCE;
}
protected NullReferenceException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/ObjectDisposedException.cs b/src/mscorlib/shared/System/ObjectDisposedException.cs
index 6e8e6b2d74..3d7ba5df15 100644
--- a/src/mscorlib/shared/System/ObjectDisposedException.cs
+++ b/src/mscorlib/shared/System/ObjectDisposedException.cs
@@ -28,14 +28,14 @@ namespace System
public ObjectDisposedException(String objectName, String message) : base(message)
{
- HResult = __HResults.COR_E_OBJECTDISPOSED;
+ HResult = HResults.COR_E_OBJECTDISPOSED;
_objectName = objectName;
}
public ObjectDisposedException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_OBJECTDISPOSED;
+ HResult = HResults.COR_E_OBJECTDISPOSED;
}
protected ObjectDisposedException(SerializationInfo info, StreamingContext context)
diff --git a/src/mscorlib/shared/System/OperationCanceledException.cs b/src/mscorlib/shared/System/OperationCanceledException.cs
index 2c7654854f..44a0427c58 100644
--- a/src/mscorlib/shared/System/OperationCanceledException.cs
+++ b/src/mscorlib/shared/System/OperationCanceledException.cs
@@ -31,19 +31,19 @@ namespace System
public OperationCanceledException()
: base(SR.OperationCanceled)
{
- HResult = __HResults.COR_E_OPERATIONCANCELED;
+ HResult = HResults.COR_E_OPERATIONCANCELED;
}
public OperationCanceledException(String message)
: base(message)
{
- HResult = __HResults.COR_E_OPERATIONCANCELED;
+ HResult = HResults.COR_E_OPERATIONCANCELED;
}
public OperationCanceledException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_OPERATIONCANCELED;
+ HResult = HResults.COR_E_OPERATIONCANCELED;
}
diff --git a/src/mscorlib/shared/System/OverflowException.cs b/src/mscorlib/shared/System/OverflowException.cs
index 4052e41a18..bf6676ca2c 100644
--- a/src/mscorlib/shared/System/OverflowException.cs
+++ b/src/mscorlib/shared/System/OverflowException.cs
@@ -20,19 +20,19 @@ namespace System
public OverflowException()
: base(SR.Arg_OverflowException)
{
- HResult = __HResults.COR_E_OVERFLOW;
+ HResult = HResults.COR_E_OVERFLOW;
}
public OverflowException(String message)
: base(message)
{
- HResult = __HResults.COR_E_OVERFLOW;
+ HResult = HResults.COR_E_OVERFLOW;
}
public OverflowException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_OVERFLOW;
+ HResult = HResults.COR_E_OVERFLOW;
}
protected OverflowException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/PlatformNotSupportedException.cs b/src/mscorlib/shared/System/PlatformNotSupportedException.cs
index f679ac9454..4403c1da06 100644
--- a/src/mscorlib/shared/System/PlatformNotSupportedException.cs
+++ b/src/mscorlib/shared/System/PlatformNotSupportedException.cs
@@ -20,19 +20,19 @@ namespace System
public PlatformNotSupportedException()
: base(SR.Arg_PlatformNotSupported)
{
- HResult = __HResults.COR_E_PLATFORMNOTSUPPORTED;
+ HResult = HResults.COR_E_PLATFORMNOTSUPPORTED;
}
public PlatformNotSupportedException(String message)
: base(message)
{
- HResult = __HResults.COR_E_PLATFORMNOTSUPPORTED;
+ HResult = HResults.COR_E_PLATFORMNOTSUPPORTED;
}
public PlatformNotSupportedException(String message, Exception inner)
: base(message, inner)
{
- HResult = __HResults.COR_E_PLATFORMNOTSUPPORTED;
+ HResult = HResults.COR_E_PLATFORMNOTSUPPORTED;
}
protected PlatformNotSupportedException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/Random.cs b/src/mscorlib/shared/System/Random.cs
index 4affed8a1a..20f035e2e8 100644
--- a/src/mscorlib/shared/System/Random.cs
+++ b/src/mscorlib/shared/System/Random.cs
@@ -2,20 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-/*============================================================
-**
-**
-** Purpose: A random number generator.
-**
-**
-===========================================================*/
-
-using System;
-using System.Runtime;
-using System.Runtime.CompilerServices;
-using System.Globalization;
-using System.Diagnostics.Contracts;
-
namespace System
{
public class Random
@@ -23,11 +9,10 @@ namespace System
//
// Private Constants
//
- private const int MBIG = Int32.MaxValue;
+ private const int MBIG = int.MaxValue;
private const int MSEED = 161803398;
private const int MZ = 0;
-
//
// Member Variables
//
@@ -64,7 +49,7 @@ namespace System
int mj, mk;
//Initialize our Seed array.
- int subtraction = (Seed == Int32.MinValue) ? Int32.MaxValue : Math.Abs(Seed);
+ int subtraction = (Seed == int.MinValue) ? int.MaxValue : Math.Abs(Seed);
mj = MSEED - subtraction;
_seedArray[55] = mj;
mk = 1;
@@ -195,8 +180,8 @@ namespace System
result = -result;
}
double d = result;
- d += (Int32.MaxValue - 1); // get a number in range [0 .. 2 * Int32MaxValue - 1)
- d /= 2 * (uint)Int32.MaxValue - 1;
+ d += (int.MaxValue - 1); // get a number in range [0 .. 2 * Int32MaxValue - 1)
+ d /= 2 * (uint)int.MaxValue - 1;
return d;
}
@@ -213,10 +198,9 @@ namespace System
{
throw new ArgumentOutOfRangeException(nameof(minValue), SR.Format(SR.Argument_MinMaxValue, nameof(minValue), nameof(maxValue)));
}
- Contract.EndContractBlock();
long range = (long)maxValue - minValue;
- if (range <= (long)Int32.MaxValue)
+ if (range <= int.MaxValue)
{
return ((int)(Sample() * range) + minValue);
}
@@ -238,7 +222,6 @@ namespace System
{
throw new ArgumentOutOfRangeException(nameof(maxValue), SR.Format(SR.ArgumentOutOfRange_MustBePositive, nameof(maxValue)));
}
- Contract.EndContractBlock();
return (int)(Sample() * maxValue);
}
@@ -263,10 +246,17 @@ namespace System
public virtual void NextBytes(byte[] buffer)
{
if (buffer == null) throw new ArgumentNullException(nameof(buffer));
- Contract.EndContractBlock();
for (int i = 0; i < buffer.Length; i++)
{
- buffer[i] = (byte)(InternalSample() % (Byte.MaxValue + 1));
+ buffer[i] = (byte)InternalSample();
+ }
+ }
+
+ public virtual void NextBytes(Span<byte> buffer)
+ {
+ for (int i = 0; i < buffer.Length; i++)
+ {
+ buffer[i] = (byte)Next();
}
}
}
diff --git a/src/mscorlib/shared/System/RankException.cs b/src/mscorlib/shared/System/RankException.cs
index 15759ea75d..f2c5d06548 100644
--- a/src/mscorlib/shared/System/RankException.cs
+++ b/src/mscorlib/shared/System/RankException.cs
@@ -21,19 +21,19 @@ namespace System
public RankException()
: base(SR.Arg_RankException)
{
- HResult = __HResults.COR_E_RANK;
+ HResult = HResults.COR_E_RANK;
}
public RankException(String message)
: base(message)
{
- HResult = __HResults.COR_E_RANK;
+ HResult = HResults.COR_E_RANK;
}
public RankException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_RANK;
+ HResult = HResults.COR_E_RANK;
}
protected RankException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/ReadOnlyMemory.cs b/src/mscorlib/shared/System/ReadOnlyMemory.cs
new file mode 100644
index 0000000000..8153d02fa3
--- /dev/null
+++ b/src/mscorlib/shared/System/ReadOnlyMemory.cs
@@ -0,0 +1,270 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Buffers;
+using EditorBrowsableAttribute = System.ComponentModel.EditorBrowsableAttribute;
+using EditorBrowsableState = System.ComponentModel.EditorBrowsableState;
+using System.Diagnostics;
+using System.Runtime;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace System
+{
+ public struct ReadOnlyMemory<T>
+ {
+ // The highest order bit of _index is used to discern whether _arrayOrOwnedMemory is an array or an owned memory
+ // if (_index >> 31) == 1, object _arrayOrOwnedMemory is an OwnedMemory<T>
+ // else, object _arrayOrOwnedMemory is a T[]
+ private readonly object _arrayOrOwnedMemory;
+ private readonly int _index;
+ private readonly int _length;
+
+ private const int RemoveOwnedFlagBitMask = 0x7FFFFFFF;
+
+ /// <summary>
+ /// Creates a new memory over the entirety of the target array.
+ /// </summary>
+ /// <param name="array">The target array.</param>
+ /// <exception cref="System.ArgumentNullException">Thrown when <paramref name="array"/> is a null
+ /// reference (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant and array's type is not exactly T[].</exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public ReadOnlyMemory(T[] array)
+ {
+ if (array == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+
+ _arrayOrOwnedMemory = array;
+ _index = 0;
+ _length = array.Length;
+ }
+
+ /// <summary>
+ /// Creates a new memory over the portion of the target array beginning
+ /// at 'start' index and ending at 'end' index (exclusive).
+ /// </summary>
+ /// <param name="array">The target array.</param>
+ /// <param name="start">The index at which to begin the memory.</param>
+ /// <param name="length">The number of items in the memory.</param>
+ /// <exception cref="System.ArgumentNullException">Thrown when <paramref name="array"/> is a null
+ /// reference (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant and array's type is not exactly T[].</exception>
+ /// <exception cref="System.ArgumentOutOfRangeException">
+ /// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;=Length).
+ /// </exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public ReadOnlyMemory(T[] array, int start, int length)
+ {
+ if (array == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start))
+ ThrowHelper.ThrowArgumentOutOfRangeException();
+
+ _arrayOrOwnedMemory = array;
+ _index = start;
+ _length = length;
+ }
+
+ // Constructor for internal use only.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal ReadOnlyMemory(OwnedMemory<T> owner, int index, int length)
+ {
+ if (owner == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.ownedMemory);
+ if (index < 0 || length < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException();
+
+ _arrayOrOwnedMemory = owner;
+ _index = index | (1 << 31); // Before using _index, check if _index < 0, then 'and' it with RemoveOwnedFlagBitMask
+ _length = length;
+ }
+
+ /// <summary>
+ /// Defines an implicit conversion of an array to a <see cref="Memory{T}"/>
+ /// </summary>
+ public static implicit operator ReadOnlyMemory<T>(T[] array) => new ReadOnlyMemory<T>(array);
+
+ /// <summary>
+ /// Defines an implicit conversion of a <see cref="ArraySegment{T}"/> to a <see cref="Memory{T}"/>
+ /// </summary>
+ public static implicit operator ReadOnlyMemory<T>(ArraySegment<T> arraySegment) => new ReadOnlyMemory<T>(arraySegment.Array, arraySegment.Offset, arraySegment.Count);
+
+ /// <summary>
+ /// Returns an empty <see cref="Memory{T}"/>
+ /// </summary>
+ public static ReadOnlyMemory<T> Empty { get; } = Array.Empty<T>();
+
+ /// <summary>
+ /// The number of items in the memory.
+ /// </summary>
+ public int Length => _length;
+
+ /// <summary>
+ /// Returns true if Length is 0.
+ /// </summary>
+ public bool IsEmpty => _length == 0;
+
+ /// <summary>
+ /// Forms a slice out of the given memory, beginning at 'start'.
+ /// </summary>
+ /// <param name="start">The index at which to begin this slice.</param>
+ /// <exception cref="System.ArgumentOutOfRangeException">
+ /// Thrown when the specified <paramref name="start"/> index is not in range (&lt;0 or &gt;=Length).
+ /// </exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public ReadOnlyMemory<T> Slice(int start)
+ {
+ if ((uint)start > (uint)_length)
+ ThrowHelper.ThrowArgumentOutOfRangeException();
+
+ if (_index < 0)
+ return new ReadOnlyMemory<T>((OwnedMemory<T>)_arrayOrOwnedMemory, (_index & RemoveOwnedFlagBitMask) + start, _length - start);
+ return new ReadOnlyMemory<T>((T[])_arrayOrOwnedMemory, _index + start, _length - start);
+ }
+
+ /// <summary>
+ /// Forms a slice out of the given memory, beginning at 'start', of given length
+ /// </summary>
+ /// <param name="start">The index at which to begin this slice.</param>
+ /// <param name="length">The desired length for the slice (exclusive).</param>
+ /// <exception cref="System.ArgumentOutOfRangeException">
+ /// Thrown when the specified <paramref name="start"/> or end index is not in range (&lt;0 or &gt;=Length).
+ /// </exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public ReadOnlyMemory<T> Slice(int start, int length)
+ {
+ if ((uint)start > (uint)_length || (uint)length > (uint)(_length - start))
+ ThrowHelper.ThrowArgumentOutOfRangeException();
+
+ if (_index < 0)
+ return new ReadOnlyMemory<T>((OwnedMemory<T>)_arrayOrOwnedMemory, (_index & RemoveOwnedFlagBitMask) + start, length);
+ return new ReadOnlyMemory<T>((T[])_arrayOrOwnedMemory, _index + start, length);
+ }
+
+ /// <summary>
+ /// Returns a span from the memory.
+ /// </summary>
+ public ReadOnlySpan<T> Span
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ if (_index < 0)
+ return ((OwnedMemory<T>)_arrayOrOwnedMemory).AsSpan().Slice(_index & RemoveOwnedFlagBitMask, _length);
+ return new ReadOnlySpan<T>((T[])_arrayOrOwnedMemory, _index, _length);
+ }
+ }
+
+ public unsafe MemoryHandle Retain(bool pin = false)
+ {
+ MemoryHandle memoryHandle;
+ if (pin)
+ {
+ if (_index < 0)
+ {
+ memoryHandle = ((OwnedMemory<T>)_arrayOrOwnedMemory).Pin();
+ }
+ else
+ {
+ var array = (T[])_arrayOrOwnedMemory;
+ var handle = GCHandle.Alloc(array, GCHandleType.Pinned);
+ void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref array.GetRawSzArrayData()), _index);
+ memoryHandle = new MemoryHandle(null, pointer, handle);
+ }
+ }
+ else
+ {
+ if (_index < 0)
+ {
+ ((OwnedMemory<T>)_arrayOrOwnedMemory).Retain();
+ memoryHandle = new MemoryHandle((OwnedMemory<T>)_arrayOrOwnedMemory);
+ }
+ else
+ {
+ memoryHandle = new MemoryHandle(null);
+ }
+ }
+ return memoryHandle;
+ }
+
+ /// <summary>
+ /// Get an array segment from the underlying memory.
+ /// If unable to get the array segment, return false with a default array segment.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public bool DangerousTryGetArray(out ArraySegment<T> arraySegment)
+ {
+ if (_index < 0)
+ {
+ if (((OwnedMemory<T>)_arrayOrOwnedMemory).TryGetArray(out var segment))
+ {
+ arraySegment = new ArraySegment<T>(segment.Array, segment.Offset + (_index & RemoveOwnedFlagBitMask), _length);
+ return true;
+ }
+ }
+ else
+ {
+ arraySegment = new ArraySegment<T>((T[])_arrayOrOwnedMemory, _index, _length);
+ return true;
+ }
+
+ arraySegment = default(ArraySegment<T>);
+ return false;
+ }
+
+ /// <summary>
+ /// Copies the contents from the memory into a new array. This heap
+ /// allocates, so should generally be avoided, however it is sometimes
+ /// necessary to bridge the gap with APIs written in terms of arrays.
+ /// </summary>
+ public T[] ToArray() => Span.ToArray();
+
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public override bool Equals(object obj)
+ {
+ if (obj is ReadOnlyMemory<T> readOnlyMemory)
+ {
+ return Equals(readOnlyMemory);
+ }
+ else if (obj is Memory<T> memory)
+ {
+ return Equals(memory);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Returns true if the memory points to the same array and has the same length. Note that
+ /// this does *not* check to see if the *contents* are equal.
+ /// </summary>
+ public bool Equals(ReadOnlyMemory<T> other)
+ {
+ return
+ _arrayOrOwnedMemory == other._arrayOrOwnedMemory &&
+ _index == other._index &&
+ _length == other._length;
+ }
+
+ [EditorBrowsable( EditorBrowsableState.Never)]
+ public override int GetHashCode()
+ {
+ return CombineHashCodes(_arrayOrOwnedMemory.GetHashCode(), (_index & RemoveOwnedFlagBitMask).GetHashCode(), _length.GetHashCode());
+ }
+
+ private static int CombineHashCodes(int left, int right)
+ {
+ return ((left << 5) + left) ^ right;
+ }
+
+ private static int CombineHashCodes(int h1, int h2, int h3)
+ {
+ return CombineHashCodes(CombineHashCodes(h1, h2), h3);
+ }
+
+ }
+} \ No newline at end of file
diff --git a/src/mscorlib/shared/System/ReadOnlySpan.cs b/src/mscorlib/shared/System/ReadOnlySpan.cs
index ae49f59269..bcf1697e88 100644
--- a/src/mscorlib/shared/System/ReadOnlySpan.cs
+++ b/src/mscorlib/shared/System/ReadOnlySpan.cs
@@ -2,10 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
-using EditorBrowsableState = System.ComponentModel.EditorBrowsableState;
-using EditorBrowsableAttribute = System.ComponentModel.EditorBrowsableAttribute;
+using System.Runtime.Versioning;
#pragma warning disable 0809 //warning CS0809: Obsolete member 'Span<T>.Equals(object)' overrides non-obsolete member 'object.Equals(object)'
@@ -15,7 +15,9 @@ namespace System
/// ReadOnlySpan represents a contiguous region of arbitrary memory. Unlike arrays, it can point to either managed
/// or native memory, or to memory allocated on the stack. It is type- and memory-safe.
/// </summary>
+ [IsReadOnly]
[IsByRefLike]
+ [NonVersionable]
public struct ReadOnlySpan<T>
{
/// <summary>A byref or a native ptr.</summary>
@@ -44,29 +46,6 @@ namespace System
/// <summary>
/// Creates a new read-only span over the portion of the target array beginning
- /// at 'start' index and covering the remainder of the array.
- /// </summary>
- /// <param name="array">The target array.</param>
- /// <param name="start">The index at which to begin the read-only span.</param>
- /// <exception cref="System.ArgumentNullException">Thrown when <paramref name="array"/> is a null
- /// reference (Nothing in Visual Basic).</exception>
- /// <exception cref="System.ArgumentOutOfRangeException">
- /// Thrown when the specified <paramref name="start"/> is not in the range (&lt;0 or &gt;=Length).
- /// </exception>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public ReadOnlySpan(T[] array, int start)
- {
- if (array == null)
- ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
- if ((uint)start > (uint)array.Length)
- ThrowHelper.ThrowArgumentOutOfRangeException();
-
- _pointer = new ByReference<T>(ref Unsafe.Add(ref Unsafe.As<byte, T>(ref array.GetRawSzArrayData()), start));
- _length = array.Length - start;
- }
-
- /// <summary>
- /// Creates a new read-only span over the portion of the target array beginning
/// at 'start' index and ending at 'end' index (exclusive).
/// </summary>
/// <param name="array">The target array.</param>
@@ -126,6 +105,7 @@ namespace System
/// <param name="objectData">A reference to data within that object.</param>
/// <param name="length">The number of <typeparamref name="T"/> elements the memory contains.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [EditorBrowsable(EditorBrowsableState.Never)]
public static ReadOnlySpan<T> DangerousCreate(object obj, ref T objectData, int length) => new ReadOnlySpan<T>(ref objectData, length);
// Constructor for internal use only.
@@ -143,6 +123,7 @@ namespace System
/// would have been stored. Such a reference can be used for pinning but must never be dereferenced.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [EditorBrowsable(EditorBrowsableState.Never)]
public ref T DangerousGetPinnableReference()
{
return ref _pointer.Value;
@@ -151,12 +132,26 @@ namespace System
/// <summary>
/// The number of items in the read-only span.
/// </summary>
- public int Length => _length;
+ public int Length
+ {
+ [NonVersionable]
+ get
+ {
+ return _length;
+ }
+ }
/// <summary>
/// Returns true if Length is 0.
/// </summary>
- public bool IsEmpty => _length == 0;
+ public bool IsEmpty
+ {
+ [NonVersionable]
+ get
+ {
+ return _length == 0;
+ }
+ }
/// <summary>
/// Returns the specified element of the read-only span.
@@ -179,6 +174,7 @@ namespace System
[Intrinsic]
#endif
[MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [NonVersionable]
get
{
if ((uint)index >= (uint)_length)
diff --git a/src/mscorlib/shared/System/Reflection/AmbiguousMatchException.cs b/src/mscorlib/shared/System/Reflection/AmbiguousMatchException.cs
index a0075bbc0b..c4aeca704d 100644
--- a/src/mscorlib/shared/System/Reflection/AmbiguousMatchException.cs
+++ b/src/mscorlib/shared/System/Reflection/AmbiguousMatchException.cs
@@ -11,19 +11,19 @@ namespace System.Reflection
public AmbiguousMatchException()
: base(SR.RFLCT_Ambiguous)
{
- HResult = __HResults.COR_E_AMBIGUOUSMATCH;
+ HResult = HResults.COR_E_AMBIGUOUSMATCH;
}
public AmbiguousMatchException(string message)
: base(message)
{
- HResult = __HResults.COR_E_AMBIGUOUSMATCH;
+ HResult = HResults.COR_E_AMBIGUOUSMATCH;
}
public AmbiguousMatchException(string message, Exception inner)
: base(message, inner)
{
- HResult = __HResults.COR_E_AMBIGUOUSMATCH;
+ HResult = HResults.COR_E_AMBIGUOUSMATCH;
}
}
}
diff --git a/src/mscorlib/shared/System/Reflection/BindingFlags.cs b/src/mscorlib/shared/System/Reflection/BindingFlags.cs
index 26c875d0f9..7ba83e20da 100644
--- a/src/mscorlib/shared/System/Reflection/BindingFlags.cs
+++ b/src/mscorlib/shared/System/Reflection/BindingFlags.cs
@@ -46,5 +46,6 @@ namespace System.Reflection
// These are a couple of misc attributes used
IgnoreReturn = 0x01000000, // This is used in COM Interop
+ DoNotWrapExceptions = 0x02000000, // Disables wrapping exceptions in TargetInvocationException
}
}
diff --git a/src/mscorlib/shared/System/Reflection/CustomAttributeFormatException.cs b/src/mscorlib/shared/System/Reflection/CustomAttributeFormatException.cs
index 13766ae8d0..ae67158a53 100644
--- a/src/mscorlib/shared/System/Reflection/CustomAttributeFormatException.cs
+++ b/src/mscorlib/shared/System/Reflection/CustomAttributeFormatException.cs
@@ -21,7 +21,7 @@ namespace System.Reflection
public CustomAttributeFormatException(string message, Exception inner)
: base(message, inner)
{
- HResult = __HResults.COR_E_CUSTOMATTRIBUTEFORMAT;
+ HResult = HResults.COR_E_CUSTOMATTRIBUTEFORMAT;
}
protected CustomAttributeFormatException(SerializationInfo info, StreamingContext context)
diff --git a/src/mscorlib/shared/System/Reflection/IReflect.cs b/src/mscorlib/shared/System/Reflection/IReflect.cs
index 51141ae47c..a7e84b6168 100644
--- a/src/mscorlib/shared/System/Reflection/IReflect.cs
+++ b/src/mscorlib/shared/System/Reflection/IReflect.cs
@@ -47,7 +47,7 @@ namespace System.Reflection
MemberInfo[] GetMembers(BindingFlags bindingAttr);
// Description of the Binding Process.
- // We must invoke a method that is accessable and for which the provided
+ // We must invoke a method that is accessible and for which the provided
// parameters have the most specific match. A method may be called if
// 1. The number of parameters in the method declaration equals the number of
// arguments provided to the invocation
@@ -59,7 +59,7 @@ namespace System.Reflection
// of methods is filtered by the name, number of arguments and a set of search modifiers
// defined in the Binder.
//
- // After the method is selected, it will be invoked. Accessability is checked
+ // After the method is selected, it will be invoked. Accessibility is checked
// at that point. The search may be control which set of methods are searched based
// upon the accessibility attribute associated with the method.
//
diff --git a/src/mscorlib/shared/System/Reflection/InvalidFilterCriteriaException.cs b/src/mscorlib/shared/System/Reflection/InvalidFilterCriteriaException.cs
index 07880a768d..85a447707c 100644
--- a/src/mscorlib/shared/System/Reflection/InvalidFilterCriteriaException.cs
+++ b/src/mscorlib/shared/System/Reflection/InvalidFilterCriteriaException.cs
@@ -21,7 +21,7 @@ namespace System.Reflection
public InvalidFilterCriteriaException(string message, Exception inner)
: base(message, inner)
{
- HResult = __HResults.COR_E_INVALIDFILTERCRITERIA;
+ HResult = HResults.COR_E_INVALIDFILTERCRITERIA;
}
protected InvalidFilterCriteriaException(SerializationInfo info, StreamingContext context)
diff --git a/src/mscorlib/shared/System/Reflection/MethodInfo.Internal.cs b/src/mscorlib/shared/System/Reflection/MethodInfo.Internal.cs
new file mode 100644
index 0000000000..a36ef900da
--- /dev/null
+++ b/src/mscorlib/shared/System/Reflection/MethodInfo.Internal.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Reflection
+{
+ public abstract partial class MethodInfo : MethodBase
+ {
+#if CORECLR
+ internal
+#else
+ // Not an api but needs to be public so that Reflection.Core can access it.
+ public
+#endif
+ virtual int GenericParameterCount => GetGenericArguments().Length;
+ }
+}
diff --git a/src/mscorlib/shared/System/Reflection/MethodInfo.cs b/src/mscorlib/shared/System/Reflection/MethodInfo.cs
index 3f60149e87..95c62ba7f0 100644
--- a/src/mscorlib/shared/System/Reflection/MethodInfo.cs
+++ b/src/mscorlib/shared/System/Reflection/MethodInfo.cs
@@ -4,7 +4,7 @@
namespace System.Reflection
{
- public abstract class MethodInfo : MethodBase
+ public abstract partial class MethodInfo : MethodBase
{
protected MethodInfo() { }
diff --git a/src/mscorlib/shared/System/Reflection/Pointer.cs b/src/mscorlib/shared/System/Reflection/Pointer.cs
index 55376c66c0..e1a9990cf0 100644
--- a/src/mscorlib/shared/System/Reflection/Pointer.cs
+++ b/src/mscorlib/shared/System/Reflection/Pointer.cs
@@ -46,6 +46,6 @@ namespace System.Reflection
}
internal Type GetPointerType() => _ptrType;
- internal object GetPointerValue() => (IntPtr)_ptr;
+ internal IntPtr GetPointerValue() => (IntPtr)_ptr;
}
}
diff --git a/src/mscorlib/shared/System/Reflection/ReflectionTypeLoadException.cs b/src/mscorlib/shared/System/Reflection/ReflectionTypeLoadException.cs
index ca0c6ab0db..0e86d34056 100644
--- a/src/mscorlib/shared/System/Reflection/ReflectionTypeLoadException.cs
+++ b/src/mscorlib/shared/System/Reflection/ReflectionTypeLoadException.cs
@@ -13,7 +13,7 @@ namespace System.Reflection
{
Types = classes;
LoaderExceptions = exceptions;
- HResult = __HResults.COR_E_REFLECTIONTYPELOAD;
+ HResult = HResults.COR_E_REFLECTIONTYPELOAD;
}
public ReflectionTypeLoadException(Type[] classes, Exception[] exceptions, string message)
@@ -21,7 +21,7 @@ namespace System.Reflection
{
Types = classes;
LoaderExceptions = exceptions;
- HResult = __HResults.COR_E_REFLECTIONTYPELOAD;
+ HResult = HResults.COR_E_REFLECTIONTYPELOAD;
}
public override void GetObjectData(SerializationInfo info, StreamingContext context)
diff --git a/src/mscorlib/shared/System/Reflection/SignatureArrayType.cs b/src/mscorlib/shared/System/Reflection/SignatureArrayType.cs
new file mode 100644
index 0000000000..52011b8a9d
--- /dev/null
+++ b/src/mscorlib/shared/System/Reflection/SignatureArrayType.cs
@@ -0,0 +1,46 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+
+namespace System.Reflection
+{
+ internal sealed class SignatureArrayType : SignatureHasElementType
+ {
+ internal SignatureArrayType(SignatureType elementType, int rank, bool isMultiDim)
+ : base(elementType)
+ {
+ Debug.Assert(rank > 0);
+ Debug.Assert(rank == 1 || isMultiDim);
+
+ _rank = rank;
+ _isMultiDim = isMultiDim;
+ }
+
+ protected sealed override bool IsArrayImpl() => true;
+ protected sealed override bool IsByRefImpl() => false;
+ protected sealed override bool IsPointerImpl() => false;
+
+ public sealed override bool IsSZArray => !_isMultiDim;
+ public sealed override bool IsVariableBoundArray => _isMultiDim;
+
+ public sealed override int GetArrayRank() => _rank;
+
+ protected sealed override string Suffix
+ {
+ get
+ {
+ if (!_isMultiDim)
+ return "[]";
+ else if (_rank == 1)
+ return "[*]";
+ else
+ return "[" + new string(',', _rank - 1) + "]";
+ }
+ }
+
+ private readonly int _rank;
+ private readonly bool _isMultiDim;
+ }
+}
diff --git a/src/mscorlib/shared/System/Reflection/SignatureByRefType.cs b/src/mscorlib/shared/System/Reflection/SignatureByRefType.cs
new file mode 100644
index 0000000000..eb5f6de42e
--- /dev/null
+++ b/src/mscorlib/shared/System/Reflection/SignatureByRefType.cs
@@ -0,0 +1,27 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace System.Reflection
+{
+ internal sealed class SignatureByRefType : SignatureHasElementType
+ {
+ internal SignatureByRefType(SignatureType elementType)
+ : base(elementType)
+ {
+ }
+
+ protected sealed override bool IsArrayImpl() => false;
+ protected sealed override bool IsByRefImpl() => true;
+ protected sealed override bool IsPointerImpl() => false;
+
+ public sealed override bool IsSZArray => false;
+ public sealed override bool IsVariableBoundArray => false;
+
+ public sealed override int GetArrayRank() => throw new ArgumentException(SR.Argument_HasToBeArrayClass);
+
+ protected sealed override string Suffix => "&";
+ }
+}
diff --git a/src/mscorlib/shared/System/Reflection/SignatureConstructedGenericType.cs b/src/mscorlib/shared/System/Reflection/SignatureConstructedGenericType.cs
new file mode 100644
index 0000000000..afcdfda352
--- /dev/null
+++ b/src/mscorlib/shared/System/Reflection/SignatureConstructedGenericType.cs
@@ -0,0 +1,73 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Text;
+using System.Diagnostics;
+
+namespace System.Reflection
+{
+ internal sealed class SignatureConstructedGenericType : SignatureType
+ {
+ internal SignatureConstructedGenericType(Type genericTypeDefinition, Type[] genericTypeArguments)
+ {
+ Debug.Assert(genericTypeDefinition != null && genericTypeArguments != null);
+ _genericTypeDefinition = genericTypeDefinition;
+ _genericTypeArguments = (Type[])(genericTypeArguments.Clone());
+ }
+
+ public sealed override bool IsTypeDefinition => false;
+ public sealed override bool IsGenericTypeDefinition => false;
+ protected sealed override bool HasElementTypeImpl() => false;
+ protected sealed override bool IsArrayImpl() => false;
+ protected sealed override bool IsByRefImpl() => false;
+ public sealed override bool IsByRefLike => _genericTypeDefinition.IsByRefLike;
+ protected sealed override bool IsPointerImpl() => false;
+ public sealed override bool IsSZArray => false;
+ public sealed override bool IsVariableBoundArray => false;
+ public sealed override bool IsConstructedGenericType => true;
+ public sealed override bool IsGenericParameter => false;
+ public sealed override bool IsGenericMethodParameter => false;
+ public sealed override bool ContainsGenericParameters
+ {
+ get
+ {
+ for (int i = 0; i < _genericTypeArguments.Length; i++)
+ {
+ if (_genericTypeArguments[i].ContainsGenericParameters)
+ return true;
+ }
+ return false;
+ }
+ }
+
+ internal sealed override SignatureType ElementType => null;
+ public sealed override int GetArrayRank() => throw new ArgumentException(SR.Argument_HasToBeArrayClass);
+ public sealed override Type GetGenericTypeDefinition() => _genericTypeDefinition;
+ public sealed override Type[] GetGenericArguments() => GenericTypeArguments;
+ public sealed override Type[] GenericTypeArguments => (Type[])(_genericTypeArguments.Clone());
+ public sealed override int GenericParameterPosition => throw new InvalidOperationException(SR.Arg_NotGenericParameter);
+
+ public sealed override string Name => _genericTypeDefinition.Name;
+ public sealed override string Namespace => _genericTypeDefinition.Namespace;
+
+ public sealed override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append(_genericTypeDefinition.ToString());
+ sb.Append('[');
+ for (int i = 0; i < _genericTypeArguments.Length; i++)
+ {
+ if (i != 0)
+ sb.Append(',');
+ sb.Append(_genericTypeArguments[i].ToString());
+ }
+ sb.Append(']');
+ return sb.ToString();
+ }
+
+ private readonly Type _genericTypeDefinition;
+ private readonly Type[] _genericTypeArguments;
+ }
+}
diff --git a/src/mscorlib/shared/System/Reflection/SignatureGenericMethodParameterType.cs b/src/mscorlib/shared/System/Reflection/SignatureGenericMethodParameterType.cs
new file mode 100644
index 0000000000..ae73272ab7
--- /dev/null
+++ b/src/mscorlib/shared/System/Reflection/SignatureGenericMethodParameterType.cs
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Reflection
+{
+ internal sealed class SignatureGenericMethodParameterType : SignatureGenericParameterType
+ {
+ internal SignatureGenericMethodParameterType(int position)
+ : base(position)
+ {
+ }
+
+ public sealed override bool IsGenericMethodParameter => true;
+
+ public sealed override string Name => "!!" + GenericParameterPosition;
+ }
+}
diff --git a/src/mscorlib/shared/System/Reflection/SignatureGenericParameterType.cs b/src/mscorlib/shared/System/Reflection/SignatureGenericParameterType.cs
new file mode 100644
index 0000000000..fee7bce353
--- /dev/null
+++ b/src/mscorlib/shared/System/Reflection/SignatureGenericParameterType.cs
@@ -0,0 +1,46 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics;
+
+namespace System.Reflection
+{
+ internal abstract class SignatureGenericParameterType : SignatureType
+ {
+ protected SignatureGenericParameterType(int position)
+ {
+ Debug.Assert(position >= 0);
+ _position = position;
+ }
+
+ public sealed override bool IsTypeDefinition => false;
+ public sealed override bool IsGenericTypeDefinition => false;
+ protected sealed override bool HasElementTypeImpl() => false;
+ protected sealed override bool IsArrayImpl() => false;
+ protected sealed override bool IsByRefImpl() => false;
+ public sealed override bool IsByRefLike => false;
+ protected sealed override bool IsPointerImpl() => false;
+ public sealed override bool IsSZArray => false;
+ public sealed override bool IsVariableBoundArray => false;
+ public sealed override bool IsConstructedGenericType => false;
+ public sealed override bool IsGenericParameter => true;
+ public abstract override bool IsGenericMethodParameter { get; }
+ public sealed override bool ContainsGenericParameters => true;
+
+ internal sealed override SignatureType ElementType => null;
+ public sealed override int GetArrayRank() => throw new ArgumentException(SR.Argument_HasToBeArrayClass);
+ public sealed override Type GetGenericTypeDefinition() => throw new InvalidOperationException(SR.InvalidOperation_NotGenericType);
+ public sealed override Type[] GetGenericArguments() => Array.Empty<Type>();
+ public sealed override Type[] GenericTypeArguments => Array.Empty<Type>();
+ public sealed override int GenericParameterPosition => _position;
+
+ public abstract override string Name { get; }
+ public sealed override string Namespace => null;
+
+ public sealed override string ToString() => Name;
+
+ private readonly int _position;
+ }
+}
diff --git a/src/mscorlib/shared/System/Reflection/SignatureHasElementType.cs b/src/mscorlib/shared/System/Reflection/SignatureHasElementType.cs
new file mode 100644
index 0000000000..e1aa6c3584
--- /dev/null
+++ b/src/mscorlib/shared/System/Reflection/SignatureHasElementType.cs
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics;
+
+namespace System.Reflection
+{
+ internal abstract class SignatureHasElementType : SignatureType
+ {
+ protected SignatureHasElementType(SignatureType elementType)
+ {
+ Debug.Assert(elementType != null);
+ _elementType = elementType;
+ }
+
+ public sealed override bool IsTypeDefinition => false;
+ public sealed override bool IsGenericTypeDefinition => false;
+ protected sealed override bool HasElementTypeImpl() => true;
+ protected abstract override bool IsArrayImpl();
+ protected abstract override bool IsByRefImpl();
+ public sealed override bool IsByRefLike => false;
+ protected abstract override bool IsPointerImpl();
+ public abstract override bool IsSZArray { get; }
+ public abstract override bool IsVariableBoundArray { get; }
+ public sealed override bool IsConstructedGenericType => false;
+ public sealed override bool IsGenericParameter => false;
+ public sealed override bool IsGenericMethodParameter => false;
+ public sealed override bool ContainsGenericParameters => _elementType.ContainsGenericParameters;
+
+ internal sealed override SignatureType ElementType => _elementType;
+ public abstract override int GetArrayRank();
+ public sealed override Type GetGenericTypeDefinition() => throw new InvalidOperationException(SR.InvalidOperation_NotGenericType);
+ public sealed override Type[] GetGenericArguments() => Array.Empty<Type>();
+ public sealed override Type[] GenericTypeArguments => Array.Empty<Type>();
+ public sealed override int GenericParameterPosition => throw new InvalidOperationException(SR.Arg_NotGenericParameter);
+
+ public sealed override string Name => _elementType.Name + Suffix;
+ public sealed override string Namespace => _elementType.Namespace;
+
+ public sealed override string ToString() => _elementType.ToString() + Suffix;
+
+ protected abstract string Suffix { get; }
+
+ private readonly SignatureType _elementType;
+ }
+}
diff --git a/src/mscorlib/shared/System/Reflection/SignaturePointerType.cs b/src/mscorlib/shared/System/Reflection/SignaturePointerType.cs
new file mode 100644
index 0000000000..a75a208165
--- /dev/null
+++ b/src/mscorlib/shared/System/Reflection/SignaturePointerType.cs
@@ -0,0 +1,27 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace System.Reflection
+{
+ internal sealed class SignaturePointerType : SignatureHasElementType
+ {
+ internal SignaturePointerType(SignatureType elementType)
+ : base(elementType)
+ {
+ }
+
+ protected sealed override bool IsArrayImpl() => false;
+ protected sealed override bool IsByRefImpl() => false;
+ protected sealed override bool IsPointerImpl() => true;
+
+ public sealed override bool IsSZArray => false;
+ public sealed override bool IsVariableBoundArray => false;
+
+ public sealed override int GetArrayRank() => throw new ArgumentException(SR.Argument_HasToBeArrayClass);
+
+ protected sealed override string Suffix => "*";
+ }
+}
diff --git a/src/mscorlib/shared/System/Reflection/SignatureType.cs b/src/mscorlib/shared/System/Reflection/SignatureType.cs
new file mode 100644
index 0000000000..c3dfc49174
--- /dev/null
+++ b/src/mscorlib/shared/System/Reflection/SignatureType.cs
@@ -0,0 +1,139 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Globalization;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+namespace System.Reflection
+{
+ //
+ // Signature Types are highly restricted Type objects that can be passed in the Type[] parameter to Type.GetMethod(). Their primary
+ // use is to pass types representing generic parameters defined by the method, or types composed from them. Passing in the normal
+ // generic parameter Type obtained from MethodInfo.GetGenericArguments() is usually impractical (if you had the method, you wouldn't
+ // be looking for it!)
+ //
+ internal abstract class SignatureType : Type
+ {
+ public sealed override bool IsSignatureType => true;
+
+ // Type flavor predicates
+ public abstract override bool IsTypeDefinition { get; }
+ protected abstract override bool HasElementTypeImpl();
+ protected abstract override bool IsArrayImpl();
+ public abstract override bool IsSZArray { get; }
+ public abstract override bool IsVariableBoundArray { get; }
+ protected abstract override bool IsByRefImpl();
+ public abstract override bool IsByRefLike { get; }
+ protected abstract override bool IsPointerImpl();
+ public sealed override bool IsGenericType => IsGenericTypeDefinition || IsConstructedGenericType;
+ public abstract override bool IsGenericTypeDefinition { get; }
+ public abstract override bool IsConstructedGenericType { get; }
+ public abstract override bool IsGenericParameter { get; }
+ public abstract bool IsGenericMethodParameter { get; }
+ public abstract override bool ContainsGenericParameters { get; }
+ public sealed override MemberTypes MemberType => MemberTypes.TypeInfo;
+
+ // Compositors
+ public sealed override Type MakeArrayType() => new SignatureArrayType(this, rank: 1, isMultiDim: false);
+ public sealed override Type MakeArrayType(int rank)
+ {
+ if (rank <= 0)
+ throw new IndexOutOfRangeException();
+ return new SignatureArrayType(this, rank: rank, isMultiDim: true);
+ }
+ public sealed override Type MakeByRefType() => new SignatureByRefType(this);
+ public sealed override Type MakePointerType() => new SignaturePointerType(this);
+ public sealed override Type MakeGenericType(params Type[] typeArguments) => throw new NotSupportedException(SR.NotSupported_SignatureType); // There is no SignatureType for type definition types so it would never be legal to call this.
+
+ // Dissectors
+ public sealed override Type GetElementType() => ElementType;
+ public abstract override int GetArrayRank();
+ public abstract override Type GetGenericTypeDefinition();
+ public abstract override Type[] GenericTypeArguments { get; }
+ public abstract override Type[] GetGenericArguments();
+ public abstract override int GenericParameterPosition { get; }
+ internal abstract SignatureType ElementType { get; }
+
+ // Identity
+#if DEBUG
+ public sealed override bool Equals(object o) => base.Equals(o);
+ public sealed override bool Equals(Type o) => base.Equals(o);
+ public sealed override int GetHashCode() => base.GetHashCode();
+#endif
+ public sealed override Type UnderlyingSystemType => this; // Equals(Type) depends on this.
+
+ // Naming and diagnostics
+ public abstract override string Name { get; }
+ public abstract override string Namespace { get; }
+ public sealed override string FullName => null;
+ public sealed override string AssemblyQualifiedName => null;
+ public abstract override string ToString();
+
+ // Not supported on Signature Types
+ public sealed override Assembly Assembly => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override Module Module => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override Type ReflectedType => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override Type BaseType => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override Type[] GetInterfaces() => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override bool IsAssignableFrom(Type c) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override int MetadataToken => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override bool HasSameMetadataDefinitionAs(MemberInfo other) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override Type DeclaringType => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override MethodBase DeclaringMethod => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override Type[] GetGenericParameterConstraints() => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override GenericParameterAttributes GenericParameterAttributes => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override bool IsEnumDefined(object value) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override string GetEnumName(object value) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override string[] GetEnumNames() => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override Type GetEnumUnderlyingType() => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override Array GetEnumValues() => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override Guid GUID => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ protected sealed override TypeCode GetTypeCodeImpl() => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ protected sealed override TypeAttributes GetAttributeFlagsImpl() => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override EventInfo GetEvent(string name, BindingFlags bindingAttr) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override EventInfo[] GetEvents(BindingFlags bindingAttr) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override FieldInfo GetField(string name, BindingFlags bindingAttr) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override FieldInfo[] GetFields(BindingFlags bindingAttr) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override MemberInfo[] GetMembers(BindingFlags bindingAttr) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override MethodInfo[] GetMethods(BindingFlags bindingAttr) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override Type GetNestedType(string name, BindingFlags bindingAttr) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override Type[] GetNestedTypes(BindingFlags bindingAttr) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override PropertyInfo[] GetProperties(BindingFlags bindingAttr) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ protected sealed override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ protected sealed override MethodInfo GetMethodImpl(string name, int genericParameterCount, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ protected sealed override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override MemberInfo[] FindMembers(MemberTypes memberType, BindingFlags bindingAttr, MemberFilter filter, object filterCriteria) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override MemberInfo[] GetMember(string name, BindingFlags bindingAttr) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override MemberInfo[] GetDefaultMembers() => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override EventInfo[] GetEvents() => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override object[] GetCustomAttributes(bool inherit) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override object[] GetCustomAttributes(Type attributeType, bool inherit) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override bool IsDefined(Type attributeType, bool inherit) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override IList<CustomAttributeData> GetCustomAttributesData() => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override Type GetInterface(string name, bool ignoreCase) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ protected sealed override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ protected sealed override bool IsCOMObjectImpl() => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ protected sealed override bool IsPrimitiveImpl() => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override IEnumerable<CustomAttributeData> CustomAttributes => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override Type[] FindInterfaces(TypeFilter filter, object filterCriteria) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override InterfaceMapping GetInterfaceMap(Type interfaceType) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ protected sealed override bool IsContextfulImpl() => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override bool IsEnum => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override bool IsEquivalentTo(Type other) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override bool IsInstanceOfType(object o) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ protected sealed override bool IsMarshalByRefImpl() => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override bool IsSecurityCritical => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override bool IsSecuritySafeCritical => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override bool IsSecurityTransparent => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override bool IsSerializable => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override bool IsSubclassOf(Type c) => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ protected sealed override bool IsValueTypeImpl() => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override StructLayoutAttribute StructLayoutAttribute => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ public sealed override RuntimeTypeHandle TypeHandle => throw new NotSupportedException(SR.NotSupported_SignatureType);
+ }
+}
diff --git a/src/mscorlib/shared/System/Reflection/SignatureTypeExtensions.cs b/src/mscorlib/shared/System/Reflection/SignatureTypeExtensions.cs
new file mode 100644
index 0000000000..b30da50073
--- /dev/null
+++ b/src/mscorlib/shared/System/Reflection/SignatureTypeExtensions.cs
@@ -0,0 +1,227 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Reflection;
+using System.Diagnostics;
+
+namespace System.Reflection
+{
+#if CORECLR
+ internal
+#else
+ public // Needs to be public so that Reflection.Core can see it.
+#endif
+ static class SignatureTypeExtensions
+ {
+ /// <summary>
+ /// This is semantically identical to
+ ///
+ /// parameter.ParameterType == pattern.TryResolveAgainstGenericMethod(parameter.Member)
+ ///
+ /// but without the allocation overhead of TryResolve.
+ /// </summary>
+ public static bool MatchesParameterTypeExactly(this Type pattern, ParameterInfo parameter)
+ {
+ if (pattern is SignatureType signatureType)
+ return signatureType.MatchesExactly(parameter.ParameterType);
+ else
+ return pattern == (object)(parameter.ParameterType);
+ }
+
+ /// <summary>
+ /// This is semantically identical to
+ ///
+ /// actual == pattern.TryResolveAgainstGenericMethod(parameterMember)
+ ///
+ /// but without the allocation overhead of TryResolve.
+ /// </summary>
+ internal static bool MatchesExactly(this SignatureType pattern, Type actual)
+ {
+ if (pattern.IsSZArray)
+ {
+ return actual.IsSZArray && pattern.ElementType.MatchesExactly(actual.GetElementType());
+ }
+ else if (pattern.IsVariableBoundArray)
+ {
+ return actual.IsVariableBoundArray && pattern.GetArrayRank() == actual.GetArrayRank() && pattern.ElementType.MatchesExactly(actual.GetElementType());
+ }
+ else if (pattern.IsByRef)
+ {
+ return actual.IsByRef && pattern.ElementType.MatchesExactly(actual.GetElementType());
+ }
+ else if (pattern.IsPointer)
+ {
+ return actual.IsPointer && pattern.ElementType.MatchesExactly(actual.GetElementType());
+ }
+ else if (pattern.IsConstructedGenericType)
+ {
+ if (!actual.IsConstructedGenericType)
+ return false;
+ if (!(pattern.GetGenericTypeDefinition() == actual.GetGenericTypeDefinition()))
+ return false;
+ Type[] patternGenericTypeArguments = pattern.GenericTypeArguments;
+ Type[] actualGenericTypeArguments = actual.GenericTypeArguments;
+ int count = patternGenericTypeArguments.Length;
+ if (count != actualGenericTypeArguments.Length)
+ return false;
+ for (int i = 0; i < count; i++)
+ {
+ Type patternGenericTypeArgument = patternGenericTypeArguments[i];
+ if (patternGenericTypeArgument is SignatureType signatureType)
+ {
+ if (!signatureType.MatchesExactly(actualGenericTypeArguments[i]))
+ return false;
+ }
+ else
+ {
+ if (patternGenericTypeArgument != actualGenericTypeArguments[i])
+ return false;
+ }
+ }
+ return true;
+ }
+ else if (pattern.IsGenericMethodParameter)
+ {
+ if (!(actual.IsGenericParameter && actual.DeclaringMethod != null))
+ return false;
+ if (pattern.GenericParameterPosition != actual.GenericParameterPosition)
+ return false;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Translates a SignatureType into its equivalent resolved Type by recursively substituting all generic parameter references
+ /// with its corresponding generic parameter definition. This is slow so MatchesExactly or MatchesParameterTypeExactly should be
+ /// substituted instead whenever possible. This is only used by the DefaultBinder when its fast-path checks have been exhausted and
+ /// it needs to call non-trivial methods like IsAssignableFrom which SignatureTypes will never support.
+ ///
+ /// Because this method is used to eliminate method candidates in a GetMethod() lookup, it is entirely possible that the Type
+ /// might not be creatable due to conflicting generic constraints. Since this merely implies that this candidate is not
+ /// the method we're looking for, we return null rather than let the TypeLoadException bubble up. The DefaultBinder will catch
+ /// the null and continue its search for a better candidate.
+ /// </summary>
+ internal static Type TryResolveAgainstGenericMethod(this SignatureType signatureType, MethodInfo genericMethod)
+ {
+ return signatureType.TryResolve(genericMethod.GetGenericArguments());
+ }
+
+ private static Type TryResolve(this SignatureType signatureType, Type[] genericMethodParameters)
+ {
+ if (signatureType.IsSZArray)
+ {
+ return signatureType.ElementType.TryResolve(genericMethodParameters)?.TryMakeArrayType();
+ }
+ else if (signatureType.IsVariableBoundArray)
+ {
+ return signatureType.ElementType.TryResolve(genericMethodParameters)?.TryMakeArrayType(signatureType.GetArrayRank());
+ }
+ else if (signatureType.IsByRef)
+ {
+ return signatureType.ElementType.TryResolve(genericMethodParameters)?.TryMakeByRefType();
+ }
+ else if (signatureType.IsPointer)
+ {
+ return signatureType.ElementType.TryResolve(genericMethodParameters)?.TryMakePointerType();
+ }
+ else if (signatureType.IsConstructedGenericType)
+ {
+ Type[] genericTypeArguments = signatureType.GenericTypeArguments;
+ int count = genericTypeArguments.Length;
+ Type[] newGenericTypeArguments = new Type[count];
+ for (int i = 0; i < count; i++)
+ {
+ Type genericTypeArgument = genericTypeArguments[i];
+ if (genericTypeArgument is SignatureType signatureGenericTypeArgument)
+ {
+ newGenericTypeArguments[i] = signatureGenericTypeArgument.TryResolve(genericMethodParameters);
+ if (newGenericTypeArguments[i] == null)
+ return null;
+ }
+ else
+ {
+ newGenericTypeArguments[i] = genericTypeArgument;
+ }
+ }
+ return signatureType.GetGenericTypeDefinition().TryMakeGenericType(newGenericTypeArguments);
+ }
+ else if (signatureType.IsGenericMethodParameter)
+ {
+ int position = signatureType.GenericParameterPosition;
+ if (position >= genericMethodParameters.Length)
+ return null;
+ return genericMethodParameters[position];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ private static Type TryMakeArrayType(this Type type)
+ {
+ try
+ {
+ return type.MakeArrayType();
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ private static Type TryMakeArrayType(this Type type, int rank)
+ {
+ try
+ {
+ return type.MakeArrayType(rank);
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ private static Type TryMakeByRefType(this Type type)
+ {
+ try
+ {
+ return type.MakeByRefType();
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ private static Type TryMakePointerType(this Type type)
+ {
+ try
+ {
+ return type.MakePointerType();
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ private static Type TryMakeGenericType(this Type type, Type[] instantiation)
+ {
+ try
+ {
+ return type.MakeGenericType(instantiation);
+ }
+ catch
+ {
+ return null;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/Reflection/TargetException.cs b/src/mscorlib/shared/System/Reflection/TargetException.cs
index 6e43f56fa4..2309daace1 100644
--- a/src/mscorlib/shared/System/Reflection/TargetException.cs
+++ b/src/mscorlib/shared/System/Reflection/TargetException.cs
@@ -21,7 +21,7 @@ namespace System.Reflection
public TargetException(string message, Exception inner)
: base(message, inner)
{
- HResult = __HResults.COR_E_TARGET;
+ HResult = HResults.COR_E_TARGET;
}
protected TargetException(SerializationInfo info, StreamingContext context)
diff --git a/src/mscorlib/shared/System/Reflection/TargetInvocationException.cs b/src/mscorlib/shared/System/Reflection/TargetInvocationException.cs
index 8d0bfef40d..7c4f60a03e 100644
--- a/src/mscorlib/shared/System/Reflection/TargetInvocationException.cs
+++ b/src/mscorlib/shared/System/Reflection/TargetInvocationException.cs
@@ -11,13 +11,13 @@ namespace System.Reflection
public TargetInvocationException(Exception inner)
: base(SR.Arg_TargetInvocationException, inner)
{
- HResult = __HResults.COR_E_TARGETINVOCATION;
+ HResult = HResults.COR_E_TARGETINVOCATION;
}
public TargetInvocationException(string message, Exception inner)
: base(message, inner)
{
- HResult = __HResults.COR_E_TARGETINVOCATION;
+ HResult = HResults.COR_E_TARGETINVOCATION;
}
}
}
diff --git a/src/mscorlib/shared/System/Reflection/TargetParameterCountException.cs b/src/mscorlib/shared/System/Reflection/TargetParameterCountException.cs
index e200cdb94f..f31758b7ba 100644
--- a/src/mscorlib/shared/System/Reflection/TargetParameterCountException.cs
+++ b/src/mscorlib/shared/System/Reflection/TargetParameterCountException.cs
@@ -11,19 +11,19 @@ namespace System.Reflection
public TargetParameterCountException()
: base(SR.Arg_TargetParameterCountException)
{
- HResult = __HResults.COR_E_TARGETPARAMCOUNT;
+ HResult = HResults.COR_E_TARGETPARAMCOUNT;
}
public TargetParameterCountException(string message)
: base(message)
{
- HResult = __HResults.COR_E_TARGETPARAMCOUNT;
+ HResult = HResults.COR_E_TARGETPARAMCOUNT;
}
public TargetParameterCountException(string message, Exception inner)
: base(message, inner)
{
- HResult = __HResults.COR_E_TARGETPARAMCOUNT;
+ HResult = HResults.COR_E_TARGETPARAMCOUNT;
}
}
}
diff --git a/src/mscorlib/shared/System/Reflection/TypeDelegator.cs b/src/mscorlib/shared/System/Reflection/TypeDelegator.cs
index bcbff05d62..1dba278893 100644
--- a/src/mscorlib/shared/System/Reflection/TypeDelegator.cs
+++ b/src/mscorlib/shared/System/Reflection/TypeDelegator.cs
@@ -108,6 +108,7 @@ namespace System.Reflection
protected override bool IsPointerImpl() => typeImpl.IsPointer;
protected override bool IsValueTypeImpl() => typeImpl.IsValueType;
protected override bool IsCOMObjectImpl() => typeImpl.IsCOMObject;
+ public override bool IsByRefLike => typeImpl.IsByRefLike;
public override bool IsConstructedGenericType => typeImpl.IsConstructedGenericType;
public override Type GetElementType() => typeImpl.GetElementType();
protected override bool HasElementTypeImpl() => typeImpl.HasElementType;
diff --git a/src/mscorlib/shared/System/Resources/MissingManifestResourceException.cs b/src/mscorlib/shared/System/Resources/MissingManifestResourceException.cs
index ec814393d0..e11d15d200 100644
--- a/src/mscorlib/shared/System/Resources/MissingManifestResourceException.cs
+++ b/src/mscorlib/shared/System/Resources/MissingManifestResourceException.cs
@@ -12,19 +12,19 @@ namespace System.Resources
public MissingManifestResourceException()
: base(SR.Arg_MissingManifestResourceException)
{
- HResult = System.__HResults.COR_E_MISSINGMANIFESTRESOURCE;
+ HResult = System.HResults.COR_E_MISSINGMANIFESTRESOURCE;
}
public MissingManifestResourceException(string message)
: base(message)
{
- HResult = System.__HResults.COR_E_MISSINGMANIFESTRESOURCE;
+ HResult = System.HResults.COR_E_MISSINGMANIFESTRESOURCE;
}
public MissingManifestResourceException(string message, Exception inner)
: base(message, inner)
{
- HResult = System.__HResults.COR_E_MISSINGMANIFESTRESOURCE;
+ HResult = System.HResults.COR_E_MISSINGMANIFESTRESOURCE;
}
protected MissingManifestResourceException(SerializationInfo info, StreamingContext context)
diff --git a/src/mscorlib/shared/System/Resources/MissingSatelliteAssemblyException.cs b/src/mscorlib/shared/System/Resources/MissingSatelliteAssemblyException.cs
index d2ddc992ac..615aed6a8c 100644
--- a/src/mscorlib/shared/System/Resources/MissingSatelliteAssemblyException.cs
+++ b/src/mscorlib/shared/System/Resources/MissingSatelliteAssemblyException.cs
@@ -27,26 +27,26 @@ namespace System.Resources
public MissingSatelliteAssemblyException()
: base(SR.MissingSatelliteAssembly_Default)
{
- HResult = System.__HResults.COR_E_MISSINGSATELLITEASSEMBLY;
+ HResult = System.HResults.COR_E_MISSINGSATELLITEASSEMBLY;
}
public MissingSatelliteAssemblyException(string message)
: base(message)
{
- HResult = System.__HResults.COR_E_MISSINGSATELLITEASSEMBLY;
+ HResult = System.HResults.COR_E_MISSINGSATELLITEASSEMBLY;
}
public MissingSatelliteAssemblyException(string message, String cultureName)
: base(message)
{
- HResult = System.__HResults.COR_E_MISSINGSATELLITEASSEMBLY;
+ HResult = System.HResults.COR_E_MISSINGSATELLITEASSEMBLY;
_cultureName = cultureName;
}
public MissingSatelliteAssemblyException(string message, Exception inner)
: base(message, inner)
{
- HResult = System.__HResults.COR_E_MISSINGSATELLITEASSEMBLY;
+ HResult = System.HResults.COR_E_MISSINGSATELLITEASSEMBLY;
}
protected MissingSatelliteAssemblyException(SerializationInfo info, StreamingContext context)
diff --git a/src/mscorlib/shared/System/Runtime/CompilerServices/AsyncMethodBuilderAttribute.cs b/src/mscorlib/shared/System/Runtime/CompilerServices/AsyncMethodBuilderAttribute.cs
new file mode 100644
index 0000000000..688a3a01ba
--- /dev/null
+++ b/src/mscorlib/shared/System/Runtime/CompilerServices/AsyncMethodBuilderAttribute.cs
@@ -0,0 +1,21 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+ /// <summary>
+ /// Indicates the type of the async method builder that should be used by a language compiler to
+ /// build the attributed type when used as the return type of an async method.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface | AttributeTargets.Delegate | AttributeTargets.Enum, Inherited = false, AllowMultiple = false)]
+ public sealed class AsyncMethodBuilderAttribute : Attribute
+ {
+ /// <summary>Initializes the <see cref="AsyncMethodBuilderAttribute"/>.</summary>
+ /// <param name="builderType">The <see cref="Type"/> of the associated builder.</param>
+ public AsyncMethodBuilderAttribute(Type builderType) => BuilderType = builderType;
+
+ /// <summary>Gets the <see cref="Type"/> of the associated builder.</summary>
+ public Type BuilderType { get; }
+ }
+}
diff --git a/src/mscorlib/shared/System/Runtime/CompilerServices/AsyncValueTaskMethodBuilder.cs b/src/mscorlib/shared/System/Runtime/CompilerServices/AsyncValueTaskMethodBuilder.cs
new file mode 100644
index 0000000000..813d9e5cd7
--- /dev/null
+++ b/src/mscorlib/shared/System/Runtime/CompilerServices/AsyncValueTaskMethodBuilder.cs
@@ -0,0 +1,111 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Threading.Tasks;
+
+namespace System.Runtime.CompilerServices
+{
+ /// <summary>Represents a builder for asynchronous methods that returns a <see cref="ValueTask{TResult}"/>.</summary>
+ /// <typeparam name="TResult">The type of the result.</typeparam>
+ [StructLayout(LayoutKind.Auto)]
+ public struct AsyncValueTaskMethodBuilder<TResult>
+ {
+ /// <summary>The <see cref="AsyncTaskMethodBuilder{TResult}"/> to which most operations are delegated.</summary>
+ private AsyncTaskMethodBuilder<TResult> _methodBuilder; // mutable struct; do not make it readonly
+ /// <summary>The result for this builder, if it's completed before any awaits occur.</summary>
+ private TResult _result;
+ /// <summary>true if <see cref="_result"/> contains the synchronous result for the async method; otherwise, false.</summary>
+ private bool _haveResult;
+ /// <summary>true if the builder should be used for setting/getting the result; otherwise, false.</summary>
+ private bool _useBuilder;
+
+ /// <summary>Creates an instance of the <see cref="AsyncValueTaskMethodBuilder{TResult}"/> struct.</summary>
+ /// <returns>The initialized instance.</returns>
+ public static AsyncValueTaskMethodBuilder<TResult> Create() =>
+#if CORECLR
+ // _methodBuilder should be initialized to AsyncTaskMethodBuilder<TResult>.Create(), but on coreclr
+ // that Create() is a nop, so we can just return the default here.
+ default(AsyncValueTaskMethodBuilder<TResult>);
+#else
+ // corert's AsyncTaskMethodBuilder<TResult>.Create() currently does additional debugger-related
+ // work, so we need to delegate to it.
+ new AsyncValueTaskMethodBuilder<TResult>() { _methodBuilder = AsyncTaskMethodBuilder<TResult>.Create() };
+#endif
+
+ /// <summary>Begins running the builder with the associated state machine.</summary>
+ /// <typeparam name="TStateMachine">The type of the state machine.</typeparam>
+ /// <param name="stateMachine">The state machine instance, passed by reference.</param>
+ public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine =>
+ _methodBuilder.Start(ref stateMachine); // will provide the right ExecutionContext semantics
+
+ /// <summary>Associates the builder with the specified state machine.</summary>
+ /// <param name="stateMachine">The state machine instance to associate with the builder.</param>
+ public void SetStateMachine(IAsyncStateMachine stateMachine) => _methodBuilder.SetStateMachine(stateMachine);
+
+ /// <summary>Marks the task as successfully completed.</summary>
+ /// <param name="result">The result to use to complete the task.</param>
+ public void SetResult(TResult result)
+ {
+ if (_useBuilder)
+ {
+ _methodBuilder.SetResult(result);
+ }
+ else
+ {
+ _result = result;
+ _haveResult = true;
+ }
+ }
+
+ /// <summary>Marks the task as failed and binds the specified exception to the task.</summary>
+ /// <param name="exception">The exception to bind to the task.</param>
+ public void SetException(Exception exception) => _methodBuilder.SetException(exception);
+
+ /// <summary>Gets the task for this builder.</summary>
+ public ValueTask<TResult> Task
+ {
+ get
+ {
+ if (_haveResult)
+ {
+ return new ValueTask<TResult>(_result);
+ }
+ else
+ {
+ _useBuilder = true;
+ return new ValueTask<TResult>(_methodBuilder.Task);
+ }
+ }
+ }
+
+ /// <summary>Schedules the state machine to proceed to the next action when the specified awaiter completes.</summary>
+ /// <typeparam name="TAwaiter">The type of the awaiter.</typeparam>
+ /// <typeparam name="TStateMachine">The type of the state machine.</typeparam>
+ /// <param name="awaiter">the awaiter</param>
+ /// <param name="stateMachine">The state machine.</param>
+ public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
+ where TAwaiter : INotifyCompletion
+ where TStateMachine : IAsyncStateMachine
+ {
+ _useBuilder = true;
+ _methodBuilder.AwaitOnCompleted(ref awaiter, ref stateMachine);
+ }
+
+ /// <summary>Schedules the state machine to proceed to the next action when the specified awaiter completes.</summary>
+ /// <typeparam name="TAwaiter">The type of the awaiter.</typeparam>
+ /// <typeparam name="TStateMachine">The type of the state machine.</typeparam>
+ /// <param name="awaiter">the awaiter</param>
+ /// <param name="stateMachine">The state machine.</param>
+ [SecuritySafeCritical]
+ public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
+ where TAwaiter : ICriticalNotifyCompletion
+ where TStateMachine : IAsyncStateMachine
+ {
+ _useBuilder = true;
+ _methodBuilder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs b/src/mscorlib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs
new file mode 100644
index 0000000000..4ec931c4af
--- /dev/null
+++ b/src/mscorlib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs
@@ -0,0 +1,71 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+using System.Threading.Tasks;
+
+namespace System.Runtime.CompilerServices
+{
+ /// <summary>Provides an awaitable type that enables configured awaits on a <see cref="ValueTask{TResult}"/>.</summary>
+ /// <typeparam name="TResult">The type of the result produced.</typeparam>
+ [StructLayout(LayoutKind.Auto)]
+ public struct ConfiguredValueTaskAwaitable<TResult>
+ {
+ /// <summary>The wrapped <see cref="ValueTask{TResult}"/>.</summary>
+ private readonly ValueTask<TResult> _value;
+ /// <summary>true to attempt to marshal the continuation back to the original context captured; otherwise, false.</summary>
+ private readonly bool _continueOnCapturedContext;
+
+ /// <summary>Initializes the awaitable.</summary>
+ /// <param name="value">The wrapped <see cref="ValueTask{TResult}"/>.</param>
+ /// <param name="continueOnCapturedContext">
+ /// true to attempt to marshal the continuation back to the original synchronization context captured; otherwise, false.
+ /// </param>
+ internal ConfiguredValueTaskAwaitable(ValueTask<TResult> value, bool continueOnCapturedContext)
+ {
+ _value = value;
+ _continueOnCapturedContext = continueOnCapturedContext;
+ }
+
+ /// <summary>Returns an awaiter for this <see cref="ConfiguredValueTaskAwaitable{TResult}"/> instance.</summary>
+ public ConfiguredValueTaskAwaiter GetAwaiter() =>
+ new ConfiguredValueTaskAwaiter(_value, _continueOnCapturedContext);
+
+ /// <summary>Provides an awaiter for a <see cref="ConfiguredValueTaskAwaitable{TResult}"/>.</summary>
+ [StructLayout(LayoutKind.Auto)]
+ public struct ConfiguredValueTaskAwaiter : ICriticalNotifyCompletion
+ {
+ /// <summary>The value being awaited.</summary>
+ private ValueTask<TResult> _value; // Methods are called on this; avoid making it readonly so as to avoid unnecessary copies
+ /// <summary>The value to pass to ConfigureAwait.</summary>
+ private readonly bool _continueOnCapturedContext;
+
+ /// <summary>Initializes the awaiter.</summary>
+ /// <param name="value">The value to be awaited.</param>
+ /// <param name="continueOnCapturedContext">The value to pass to ConfigureAwait.</param>
+ internal ConfiguredValueTaskAwaiter(ValueTask<TResult> value, bool continueOnCapturedContext)
+ {
+ _value = value;
+ _continueOnCapturedContext = continueOnCapturedContext;
+ }
+
+ /// <summary>Gets whether the <see cref="ConfiguredValueTaskAwaitable{TResult}"/> has completed.</summary>
+ public bool IsCompleted => _value.IsCompleted;
+
+ /// <summary>Gets the result of the ValueTask.</summary>
+ public TResult GetResult() =>
+ _value._task == null ?
+ _value._result :
+ _value._task.GetAwaiter().GetResult();
+
+ /// <summary>Schedules the continuation action for the <see cref="ConfiguredValueTaskAwaitable{TResult}"/>.</summary>
+ public void OnCompleted(Action continuation) =>
+ _value.AsTask().ConfigureAwait(_continueOnCapturedContext).GetAwaiter().OnCompleted(continuation);
+
+ /// <summary>Schedules the continuation action for the <see cref="ConfiguredValueTaskAwaitable{TResult}"/>.</summary>
+ public void UnsafeOnCompleted(Action continuation) =>
+ _value.AsTask().ConfigureAwait(_continueOnCapturedContext).GetAwaiter().UnsafeOnCompleted(continuation);
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/Runtime/CompilerServices/CustomConstantAttribute.cs b/src/mscorlib/shared/System/Runtime/CompilerServices/CustomConstantAttribute.cs
new file mode 100644
index 0000000000..f75693eb40
--- /dev/null
+++ b/src/mscorlib/shared/System/Runtime/CompilerServices/CustomConstantAttribute.cs
@@ -0,0 +1,12 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+ [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)]
+ public abstract class CustomConstantAttribute : Attribute
+ {
+ public abstract Object Value { get; }
+ }
+}
diff --git a/src/mscorlib/shared/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs b/src/mscorlib/shared/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs
new file mode 100644
index 0000000000..813e6803bf
--- /dev/null
+++ b/src/mscorlib/shared/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+ [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)]
+ public sealed class DateTimeConstantAttribute : CustomConstantAttribute
+ {
+ private DateTime _date;
+
+ public DateTimeConstantAttribute(long ticks)
+ {
+ _date = new DateTime(ticks);
+ }
+
+ public override Object Value => _date;
+ }
+}
diff --git a/src/mscorlib/shared/System/Runtime/CompilerServices/DecimalConstantAttribute.cs b/src/mscorlib/shared/System/Runtime/CompilerServices/DecimalConstantAttribute.cs
new file mode 100644
index 0000000000..19db84eb43
--- /dev/null
+++ b/src/mscorlib/shared/System/Runtime/CompilerServices/DecimalConstantAttribute.cs
@@ -0,0 +1,39 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// Note: If you add a new ctor overloads you need to update ParameterInfo.RawDefaultValue
+
+namespace System.Runtime.CompilerServices
+{
+ [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)]
+ public sealed class DecimalConstantAttribute : Attribute
+ {
+ private Decimal _dec;
+
+ [CLSCompliant(false)]
+ public DecimalConstantAttribute(
+ byte scale,
+ byte sign,
+ uint hi,
+ uint mid,
+ uint low
+ )
+ {
+ _dec = new Decimal((int)low, (int)mid, (int)hi, (sign != 0), scale);
+ }
+
+ public DecimalConstantAttribute(
+ byte scale,
+ byte sign,
+ int hi,
+ int mid,
+ int low
+ )
+ {
+ _dec = new Decimal(low, mid, hi, (sign != 0), scale);
+ }
+
+ public Decimal Value => _dec;
+ }
+}
diff --git a/src/mscorlib/shared/System/Runtime/CompilerServices/IntrinsicAttribute.cs b/src/mscorlib/shared/System/Runtime/CompilerServices/IntrinsicAttribute.cs
new file mode 100644
index 0000000000..dd01bacc49
--- /dev/null
+++ b/src/mscorlib/shared/System/Runtime/CompilerServices/IntrinsicAttribute.cs
@@ -0,0 +1,13 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+ // Calls to methods or references to fields marked with this attribute may be replaced at
+ // some call sites with jit intrinsic expansions.
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Field, Inherited = false)]
+ internal sealed class IntrinsicAttribute : Attribute
+ {
+ }
+}
diff --git a/src/mscorlib/shared/System/Runtime/CompilerServices/MethodImplAttribute.cs b/src/mscorlib/shared/System/Runtime/CompilerServices/MethodImplAttribute.cs
new file mode 100644
index 0000000000..8e8f93c268
--- /dev/null
+++ b/src/mscorlib/shared/System/Runtime/CompilerServices/MethodImplAttribute.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+ // Custom attribute to specify additional method properties.
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor, Inherited = false)]
+ sealed public class MethodImplAttribute : Attribute
+ {
+ public MethodCodeType MethodCodeType;
+
+ public MethodImplAttribute(MethodImplOptions methodImplOptions)
+ {
+ Value = methodImplOptions;
+ }
+
+ public MethodImplAttribute(short value)
+ {
+ Value = (MethodImplOptions)value;
+ }
+
+ public MethodImplAttribute()
+ {
+ }
+
+ public MethodImplOptions Value { get; }
+ }
+}
diff --git a/src/mscorlib/shared/System/Runtime/CompilerServices/RuntimeWrappedException.cs b/src/mscorlib/shared/System/Runtime/CompilerServices/RuntimeWrappedException.cs
new file mode 100644
index 0000000000..e4af9be678
--- /dev/null
+++ b/src/mscorlib/shared/System/Runtime/CompilerServices/RuntimeWrappedException.cs
@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Serialization;
+
+namespace System.Runtime.CompilerServices
+{
+ /// <summary>
+ /// Exception used to wrap all non-CLS compliant exceptions.
+ /// </summary>
+ public sealed class RuntimeWrappedException : Exception
+ {
+ private Object _wrappedException; // EE expects this name
+
+ // Not an api but has to be public as System.Linq.Expression invokes this through Reflection when an expression
+ // throws an object that doesn't derive from Exception.
+ public RuntimeWrappedException(Object thrownObject)
+ : base(SR.RuntimeWrappedException)
+ {
+ HResult = HResults.COR_E_RUNTIMEWRAPPED;
+ _wrappedException = thrownObject;
+ }
+
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ base.GetObjectData(info, context);
+ }
+
+ public Object WrappedException => _wrappedException;
+ }
+}
diff --git a/src/mscorlib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs b/src/mscorlib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs
new file mode 100644
index 0000000000..c419482521
--- /dev/null
+++ b/src/mscorlib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+using System.Threading.Tasks;
+
+namespace System.Runtime.CompilerServices
+{
+ /// <summary>Provides an awaiter for a <see cref="ValueTask{TResult}"/>.</summary>
+ public struct ValueTaskAwaiter<TResult> : ICriticalNotifyCompletion
+ {
+ /// <summary>The value being awaited.</summary>
+ private ValueTask<TResult> _value; // Methods are called on this; avoid making it readonly so as to avoid unnecessary copies
+
+ /// <summary>Initializes the awaiter.</summary>
+ /// <param name="value">The value to be awaited.</param>
+ internal ValueTaskAwaiter(ValueTask<TResult> value) => _value = value;
+
+ /// <summary>Gets whether the <see cref="ValueTask{TResult}"/> has completed.</summary>
+ public bool IsCompleted => _value.IsCompleted;
+
+ /// <summary>Gets the result of the ValueTask.</summary>
+ public TResult GetResult() =>
+ _value._task == null ?
+ _value._result :
+ _value._task.GetAwaiter().GetResult();
+
+ /// <summary>Schedules the continuation action for this ValueTask.</summary>
+ public void OnCompleted(Action continuation) =>
+ _value.AsTask().ConfigureAwait(continueOnCapturedContext: true).GetAwaiter().OnCompleted(continuation);
+
+ /// <summary>Schedules the continuation action for this ValueTask.</summary>
+ public void UnsafeOnCompleted(Action continuation) =>
+ _value.AsTask().ConfigureAwait(continueOnCapturedContext: true).GetAwaiter().UnsafeOnCompleted(continuation);
+ }
+}
diff --git a/src/mscorlib/shared/System/Runtime/ExceptionServices/HandleProcessCorruptedStateExceptionsAttribute.cs b/src/mscorlib/shared/System/Runtime/ExceptionServices/HandleProcessCorruptedStateExceptionsAttribute.cs
new file mode 100644
index 0000000000..cc1bc81e5a
--- /dev/null
+++ b/src/mscorlib/shared/System/Runtime/ExceptionServices/HandleProcessCorruptedStateExceptionsAttribute.cs
@@ -0,0 +1,16 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.ExceptionServices
+{
+ // This attribute can be applied to methods to indicate that ProcessCorruptedState
+ // Exceptions should be delivered to them.
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
+ public sealed class HandleProcessCorruptedStateExceptionsAttribute : Attribute
+ {
+ public HandleProcessCorruptedStateExceptionsAttribute()
+ {
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/Runtime/InteropServices/BestFitMappingAttribute.cs b/src/mscorlib/shared/System/Runtime/InteropServices/BestFitMappingAttribute.cs
new file mode 100644
index 0000000000..4ebee1538c
--- /dev/null
+++ b/src/mscorlib/shared/System/Runtime/InteropServices/BestFitMappingAttribute.cs
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices
+{
+ [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct, Inherited = false)]
+ public sealed class BestFitMappingAttribute : Attribute
+ {
+ public BestFitMappingAttribute(bool BestFitMapping)
+ {
+ this.BestFitMapping = BestFitMapping;
+ }
+
+ public bool BestFitMapping { get; }
+
+ public bool ThrowOnUnmappableChar;
+ }
+}
diff --git a/src/mscorlib/shared/System/Runtime/InteropServices/DefaultCharSetAttribute.cs b/src/mscorlib/shared/System/Runtime/InteropServices/DefaultCharSetAttribute.cs
new file mode 100644
index 0000000000..7a486f7017
--- /dev/null
+++ b/src/mscorlib/shared/System/Runtime/InteropServices/DefaultCharSetAttribute.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices
+{
+ [AttributeUsage(AttributeTargets.Module, Inherited = false)]
+ public sealed class DefaultCharSetAttribute : Attribute
+ {
+ public DefaultCharSetAttribute(CharSet charSet)
+ {
+ CharSet = charSet;
+ }
+
+ public CharSet CharSet { get; }
+ }
+}
diff --git a/src/mscorlib/shared/System/Runtime/InteropServices/DefaultDllImportSearchPathsAttribute.cs b/src/mscorlib/shared/System/Runtime/InteropServices/DefaultDllImportSearchPathsAttribute.cs
new file mode 100644
index 0000000000..1ff27fbbd5
--- /dev/null
+++ b/src/mscorlib/shared/System/Runtime/InteropServices/DefaultDllImportSearchPathsAttribute.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices
+{
+ [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Method, AllowMultiple = false)]
+ public sealed class DefaultDllImportSearchPathsAttribute : Attribute
+ {
+ public DefaultDllImportSearchPathsAttribute(DllImportSearchPath paths)
+ {
+ Paths = paths;
+ }
+
+ public DllImportSearchPath Paths { get; }
+ }
+}
diff --git a/src/mscorlib/shared/System/Runtime/InteropServices/DllImportAttribute.cs b/src/mscorlib/shared/System/Runtime/InteropServices/DllImportAttribute.cs
new file mode 100644
index 0000000000..97f870d49c
--- /dev/null
+++ b/src/mscorlib/shared/System/Runtime/InteropServices/DllImportAttribute.cs
@@ -0,0 +1,26 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices
+{
+ [AttributeUsage(AttributeTargets.Method, Inherited = false)]
+ public sealed class DllImportAttribute : Attribute
+ {
+ public DllImportAttribute(string dllName)
+ {
+ Value = dllName;
+ }
+
+ public string Value { get; }
+
+ public string EntryPoint;
+ public CharSet CharSet;
+ public bool SetLastError;
+ public bool ExactSpelling;
+ public CallingConvention CallingConvention;
+ public bool BestFitMapping;
+ public bool PreserveSig;
+ public bool ThrowOnUnmappableChar;
+ }
+}
diff --git a/src/mscorlib/shared/System/Runtime/InteropServices/DllImportSearchPath.cs b/src/mscorlib/shared/System/Runtime/InteropServices/DllImportSearchPath.cs
new file mode 100644
index 0000000000..8dbdb40be9
--- /dev/null
+++ b/src/mscorlib/shared/System/Runtime/InteropServices/DllImportSearchPath.cs
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices
+{
+ [Flags]
+ public enum DllImportSearchPath
+ {
+ UseDllDirectoryForDependencies = 0x100,
+ ApplicationDirectory = 0x200,
+ UserDirectories = 0x400,
+ System32 = 0x800,
+ SafeDirectories = 0x1000,
+ AssemblyDirectory = 0x2,
+ LegacyBehavior = 0x0
+ }
+}
diff --git a/src/mscorlib/shared/System/Runtime/InteropServices/ExternalException.cs b/src/mscorlib/shared/System/Runtime/InteropServices/ExternalException.cs
index 81b9a46928..0861d19362 100644
--- a/src/mscorlib/shared/System/Runtime/InteropServices/ExternalException.cs
+++ b/src/mscorlib/shared/System/Runtime/InteropServices/ExternalException.cs
@@ -26,19 +26,19 @@ namespace System.Runtime.InteropServices
public ExternalException()
: base(SR.Arg_ExternalException)
{
- HResult = __HResults.E_FAIL;
+ HResult = HResults.E_FAIL;
}
public ExternalException(string message)
: base(message)
{
- HResult = __HResults.E_FAIL;
+ HResult = HResults.E_FAIL;
}
public ExternalException(string message, Exception inner)
: base(message, inner)
{
- HResult = __HResults.E_FAIL;
+ HResult = HResults.E_FAIL;
}
public ExternalException(string message, int errorCode)
diff --git a/src/mscorlib/shared/System/Runtime/InteropServices/FieldOffsetAttribute.cs b/src/mscorlib/shared/System/Runtime/InteropServices/FieldOffsetAttribute.cs
new file mode 100644
index 0000000000..27e1097749
--- /dev/null
+++ b/src/mscorlib/shared/System/Runtime/InteropServices/FieldOffsetAttribute.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices
+{
+ [AttributeUsage(AttributeTargets.Field, Inherited = false)]
+ public sealed class FieldOffsetAttribute : Attribute
+ {
+ public FieldOffsetAttribute(int offset)
+ {
+ Value = offset;
+ }
+
+ public int Value { get; }
+ }
+}
diff --git a/src/mscorlib/shared/System/Runtime/InteropServices/InAttribute.cs b/src/mscorlib/shared/System/Runtime/InteropServices/InAttribute.cs
new file mode 100644
index 0000000000..39f5a958bc
--- /dev/null
+++ b/src/mscorlib/shared/System/Runtime/InteropServices/InAttribute.cs
@@ -0,0 +1,14 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices
+{
+ [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
+ public sealed class InAttribute : Attribute
+ {
+ public InAttribute()
+ {
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/Runtime/InteropServices/MarshalAsAttribute.cs b/src/mscorlib/shared/System/Runtime/InteropServices/MarshalAsAttribute.cs
new file mode 100644
index 0000000000..4a64050ed1
--- /dev/null
+++ b/src/mscorlib/shared/System/Runtime/InteropServices/MarshalAsAttribute.cs
@@ -0,0 +1,39 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices
+{
+ [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.ReturnValue, Inherited = false)]
+ public sealed class MarshalAsAttribute : Attribute
+ {
+ public MarshalAsAttribute(UnmanagedType unmanagedType)
+ {
+ Value = unmanagedType;
+ }
+ public MarshalAsAttribute(short unmanagedType)
+ {
+ Value = (UnmanagedType)unmanagedType;
+ }
+
+ public UnmanagedType Value { get; }
+
+ // Fields used with SubType = SafeArray.
+ public VarEnum SafeArraySubType;
+ public Type SafeArrayUserDefinedSubType;
+
+ // Field used with iid_is attribute (interface pointers).
+ public int IidParameterIndex;
+
+ // Fields used with SubType = ByValArray and LPArray.
+ // Array size = parameter(PI) * PM + C
+ public UnmanagedType ArraySubType;
+ public short SizeParamIndex; // param index PI
+ public int SizeConst; // constant C
+
+ // Fields used with SubType = CustomMarshaler
+ public string MarshalType; // Name of marshaler class
+ public Type MarshalTypeRef; // Type of marshaler class
+ public string MarshalCookie; // cookie to pass to marshaler
+ }
+}
diff --git a/src/mscorlib/shared/System/Runtime/InteropServices/OptionalAttribute.cs b/src/mscorlib/shared/System/Runtime/InteropServices/OptionalAttribute.cs
new file mode 100644
index 0000000000..5ac75d7b3e
--- /dev/null
+++ b/src/mscorlib/shared/System/Runtime/InteropServices/OptionalAttribute.cs
@@ -0,0 +1,14 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices
+{
+ [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
+ public sealed class OptionalAttribute : Attribute
+ {
+ public OptionalAttribute()
+ {
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/Runtime/InteropServices/OutAttribute.cs b/src/mscorlib/shared/System/Runtime/InteropServices/OutAttribute.cs
new file mode 100644
index 0000000000..338ceac91e
--- /dev/null
+++ b/src/mscorlib/shared/System/Runtime/InteropServices/OutAttribute.cs
@@ -0,0 +1,14 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices
+{
+ [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
+ public sealed class OutAttribute : Attribute
+ {
+ public OutAttribute()
+ {
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/Runtime/InteropServices/PreserveSigAttribute.cs b/src/mscorlib/shared/System/Runtime/InteropServices/PreserveSigAttribute.cs
new file mode 100644
index 0000000000..464e1abcbe
--- /dev/null
+++ b/src/mscorlib/shared/System/Runtime/InteropServices/PreserveSigAttribute.cs
@@ -0,0 +1,14 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices
+{
+ [AttributeUsage(AttributeTargets.Method, Inherited = false)]
+ public sealed class PreserveSigAttribute : Attribute
+ {
+ public PreserveSigAttribute()
+ {
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/Runtime/InteropServices/StructLayoutAttribute.cs b/src/mscorlib/shared/System/Runtime/InteropServices/StructLayoutAttribute.cs
new file mode 100644
index 0000000000..c4cce9956e
--- /dev/null
+++ b/src/mscorlib/shared/System/Runtime/InteropServices/StructLayoutAttribute.cs
@@ -0,0 +1,26 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices
+{
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false)]
+ public sealed class StructLayoutAttribute : Attribute
+ {
+ public StructLayoutAttribute(LayoutKind layoutKind)
+ {
+ Value = layoutKind;
+ }
+
+ public StructLayoutAttribute(short layoutKind)
+ {
+ Value = (LayoutKind)layoutKind;
+ }
+
+ public LayoutKind Value { get; }
+
+ public int Pack;
+ public int Size;
+ public CharSet CharSet;
+ }
+}
diff --git a/src/mscorlib/shared/System/Runtime/InteropServices/UnmanagedFunctionPointerAttribute.cs b/src/mscorlib/shared/System/Runtime/InteropServices/UnmanagedFunctionPointerAttribute.cs
index 2d69c95afe..c4f96903ee 100644
--- a/src/mscorlib/shared/System/Runtime/InteropServices/UnmanagedFunctionPointerAttribute.cs
+++ b/src/mscorlib/shared/System/Runtime/InteropServices/UnmanagedFunctionPointerAttribute.cs
@@ -7,11 +7,6 @@ namespace System.Runtime.InteropServices
[AttributeUsage(AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
public sealed class UnmanagedFunctionPointerAttribute : Attribute
{
- public bool BestFitMapping;
- public bool SetLastError;
- public bool ThrowOnUnmappableChar;
- public CharSet CharSet;
-
public UnmanagedFunctionPointerAttribute()
{
CallingConvention = CallingConvention.Winapi;
@@ -23,5 +18,10 @@ namespace System.Runtime.InteropServices
}
public CallingConvention CallingConvention { get; }
+
+ public bool BestFitMapping;
+ public bool SetLastError;
+ public bool ThrowOnUnmappableChar;
+ public CharSet CharSet;
}
}
diff --git a/src/mscorlib/shared/System/Runtime/Serialization/SerializationException.cs b/src/mscorlib/shared/System/Runtime/Serialization/SerializationException.cs
index bfe3313659..3e0af092c0 100644
--- a/src/mscorlib/shared/System/Runtime/Serialization/SerializationException.cs
+++ b/src/mscorlib/shared/System/Runtime/Serialization/SerializationException.cs
@@ -15,19 +15,19 @@ namespace System.Runtime.Serialization
public SerializationException()
: base(s_nullMessage)
{
- HResult = __HResults.COR_E_SERIALIZATION;
+ HResult = HResults.COR_E_SERIALIZATION;
}
public SerializationException(String message)
: base(message)
{
- HResult = __HResults.COR_E_SERIALIZATION;
+ HResult = HResults.COR_E_SERIALIZATION;
}
public SerializationException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_SERIALIZATION;
+ HResult = HResults.COR_E_SERIALIZATION;
}
protected SerializationException(SerializationInfo info, StreamingContext context)
diff --git a/src/mscorlib/shared/System/SByte.cs b/src/mscorlib/shared/System/SByte.cs
new file mode 100644
index 0000000000..c984767336
--- /dev/null
+++ b/src/mscorlib/shared/System/SByte.cs
@@ -0,0 +1,328 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics.Contracts;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+
+namespace System
+{
+ [Serializable]
+ [CLSCompliant(false)] [StructLayout(LayoutKind.Sequential)]
+ [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ public struct SByte : IComparable, IConvertible, IFormattable, IComparable<SByte>, IEquatable<SByte>
+ {
+ private sbyte m_value; // Do not rename (binary serialization)
+
+ // The maximum value that a Byte may represent: 127.
+ public const sbyte MaxValue = (sbyte)0x7F;
+
+ // The minimum value that a Byte may represent: -128.
+ public const sbyte MinValue = unchecked((sbyte)0x80);
+
+
+ // Compares this object to another object, returning an integer that
+ // indicates the relationship.
+ // Returns a value less than zero if this object
+ // null is considered to be less than any instance.
+ // If object is not of type SByte, this method throws an ArgumentException.
+ //
+ public int CompareTo(Object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is SByte))
+ {
+ throw new ArgumentException(SR.Arg_MustBeSByte);
+ }
+ return m_value - ((SByte)obj).m_value;
+ }
+
+ public int CompareTo(SByte value)
+ {
+ return m_value - value;
+ }
+
+ // Determines whether two Byte objects are equal.
+ public override bool Equals(Object obj)
+ {
+ if (!(obj is SByte))
+ {
+ return false;
+ }
+ return m_value == ((SByte)obj).m_value;
+ }
+
+ [NonVersionable]
+ public bool Equals(SByte obj)
+ {
+ return m_value == obj;
+ }
+
+ // Gets a hash code for this instance.
+ public override int GetHashCode()
+ {
+ return ((int)m_value ^ (int)m_value << 8);
+ }
+
+
+ // Provides a string representation of a byte.
+ public override String ToString()
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt32(m_value, null, NumberFormatInfo.CurrentInfo);
+ }
+
+ public String ToString(IFormatProvider provider)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt32(m_value, null, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public String ToString(String format)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return ToString(format, NumberFormatInfo.CurrentInfo);
+ }
+
+ public String ToString(String format, IFormatProvider provider)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return ToString(format, NumberFormatInfo.GetInstance(provider));
+ }
+
+ private String ToString(String format, NumberFormatInfo info)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+
+ if (m_value < 0 && format != null && format.Length > 0 && (format[0] == 'X' || format[0] == 'x'))
+ {
+ uint temp = (uint)(m_value & 0x000000FF);
+ return Number.FormatUInt32(temp, format, info);
+ }
+ return Number.FormatInt32(m_value, format, info);
+ }
+
+ [CLSCompliant(false)]
+ public static sbyte Parse(String s)
+ {
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Parse(s.AsReadOnlySpan(), NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
+ }
+
+ [CLSCompliant(false)]
+ public static sbyte Parse(String s, NumberStyles style)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Parse(s.AsReadOnlySpan(), style, NumberFormatInfo.CurrentInfo);
+ }
+
+ [CLSCompliant(false)]
+ public static sbyte Parse(String s, IFormatProvider provider)
+ {
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Parse(s.AsReadOnlySpan(), NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
+ }
+
+ // Parses a signed byte from a String in the given style. If
+ // a NumberFormatInfo isn't specified, the current culture's
+ // NumberFormatInfo is assumed.
+ //
+ [CLSCompliant(false)]
+ public static sbyte Parse(String s, NumberStyles style, IFormatProvider provider)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Parse(s.AsReadOnlySpan(), style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [CLSCompliant(false)]
+ public static sbyte Parse(ReadOnlySpan<char> s, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Parse(s, style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ private static sbyte Parse(String s, NumberStyles style, NumberFormatInfo info)
+ {
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Parse(s.AsReadOnlySpan(), style, info);
+ }
+
+ private static sbyte Parse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info)
+ {
+ int i = 0;
+ try
+ {
+ i = Number.ParseInt32(s, style, info);
+ }
+ catch (OverflowException e)
+ {
+ throw new OverflowException(SR.Overflow_SByte, e);
+ }
+
+ if ((style & NumberStyles.AllowHexSpecifier) != 0)
+ { // We are parsing a hexadecimal number
+ if ((i < 0) || i > Byte.MaxValue)
+ {
+ throw new OverflowException(SR.Overflow_SByte);
+ }
+ return (sbyte)i;
+ }
+
+ if (i < MinValue || i > MaxValue) throw new OverflowException(SR.Overflow_SByte);
+ return (sbyte)i;
+ }
+
+ [CLSCompliant(false)]
+ public static bool TryParse(String s, out SByte result)
+ {
+ if (s == null)
+ {
+ result = 0;
+ return false;
+ }
+
+ return TryParse(s.AsReadOnlySpan(), NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
+ }
+
+ [CLSCompliant(false)]
+ public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out SByte result)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+
+ if (s == null)
+ {
+ result = 0;
+ return false;
+ }
+
+ return TryParse(s.AsReadOnlySpan(), style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ [CLSCompliant(false)]
+ public static bool TryParse(ReadOnlySpan<char> s, out sbyte result, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ private static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out SByte result)
+ {
+ result = 0;
+ int i;
+ if (!Number.TryParseInt32(s, style, info, out i))
+ {
+ return false;
+ }
+
+ if ((style & NumberStyles.AllowHexSpecifier) != 0)
+ { // We are parsing a hexadecimal number
+ if ((i < 0) || i > Byte.MaxValue)
+ {
+ return false;
+ }
+ result = (sbyte)i;
+ return true;
+ }
+
+ if (i < MinValue || i > MaxValue)
+ {
+ return false;
+ }
+ result = (sbyte)i;
+ return true;
+ }
+
+ //
+ // IConvertible implementation
+ //
+
+ public TypeCode GetTypeCode()
+ {
+ return TypeCode.SByte;
+ }
+
+
+ bool IConvertible.ToBoolean(IFormatProvider provider)
+ {
+ return Convert.ToBoolean(m_value);
+ }
+
+ char IConvertible.ToChar(IFormatProvider provider)
+ {
+ return Convert.ToChar(m_value);
+ }
+
+ sbyte IConvertible.ToSByte(IFormatProvider provider)
+ {
+ return m_value;
+ }
+
+ byte IConvertible.ToByte(IFormatProvider provider)
+ {
+ return Convert.ToByte(m_value);
+ }
+
+ short IConvertible.ToInt16(IFormatProvider provider)
+ {
+ return Convert.ToInt16(m_value);
+ }
+
+ ushort IConvertible.ToUInt16(IFormatProvider provider)
+ {
+ return Convert.ToUInt16(m_value);
+ }
+
+ int IConvertible.ToInt32(IFormatProvider provider)
+ {
+ return m_value;
+ }
+
+ uint IConvertible.ToUInt32(IFormatProvider provider)
+ {
+ return Convert.ToUInt32(m_value);
+ }
+
+ long IConvertible.ToInt64(IFormatProvider provider)
+ {
+ return Convert.ToInt64(m_value);
+ }
+
+ ulong IConvertible.ToUInt64(IFormatProvider provider)
+ {
+ return Convert.ToUInt64(m_value);
+ }
+
+ float IConvertible.ToSingle(IFormatProvider provider)
+ {
+ return Convert.ToSingle(m_value);
+ }
+
+ double IConvertible.ToDouble(IFormatProvider provider)
+ {
+ return Convert.ToDouble(m_value);
+ }
+
+ Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ {
+ return Convert.ToDecimal(m_value);
+ }
+
+ DateTime IConvertible.ToDateTime(IFormatProvider provider)
+ {
+ throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "SByte", "DateTime"));
+ }
+
+ Object IConvertible.ToType(Type type, IFormatProvider provider)
+ {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/Security/SecurityException.cs b/src/mscorlib/shared/System/Security/SecurityException.cs
index 538f475343..2866a4780c 100644
--- a/src/mscorlib/shared/System/Security/SecurityException.cs
+++ b/src/mscorlib/shared/System/Security/SecurityException.cs
@@ -12,32 +12,32 @@ namespace System.Security
public SecurityException()
: base(SR.Arg_SecurityException)
{
- HResult = __HResults.COR_E_SECURITY;
+ HResult = HResults.COR_E_SECURITY;
}
public SecurityException(string message)
: base(message)
{
- HResult = __HResults.COR_E_SECURITY;
+ HResult = HResults.COR_E_SECURITY;
}
public SecurityException(string message, Exception inner)
: base(message, inner)
{
- HResult = __HResults.COR_E_SECURITY;
+ HResult = HResults.COR_E_SECURITY;
}
public SecurityException(string message, Type type)
: base(message)
{
- HResult = __HResults.COR_E_SECURITY;
+ HResult = HResults.COR_E_SECURITY;
PermissionType = type;
}
public SecurityException(string message, Type type, string state)
: base(message)
{
- HResult = __HResults.COR_E_SECURITY;
+ HResult = HResults.COR_E_SECURITY;
PermissionType = type;
PermissionState = state;
}
diff --git a/src/mscorlib/shared/System/Security/VerificationException.cs b/src/mscorlib/shared/System/Security/VerificationException.cs
index ea5a75906e..bd095f3df4 100644
--- a/src/mscorlib/shared/System/Security/VerificationException.cs
+++ b/src/mscorlib/shared/System/Security/VerificationException.cs
@@ -11,19 +11,19 @@ namespace System.Security
public VerificationException()
: base(SR.Verification_Exception)
{
- HResult = __HResults.COR_E_VERIFICATION;
+ HResult = HResults.COR_E_VERIFICATION;
}
public VerificationException(string message)
: base(message)
{
- HResult = __HResults.COR_E_VERIFICATION;
+ HResult = HResults.COR_E_VERIFICATION;
}
public VerificationException(string message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_VERIFICATION;
+ HResult = HResults.COR_E_VERIFICATION;
}
protected VerificationException(SerializationInfo info, StreamingContext context)
diff --git a/src/mscorlib/shared/System/SerializableAttribute.cs b/src/mscorlib/shared/System/SerializableAttribute.cs
new file mode 100644
index 0000000000..c256931373
--- /dev/null
+++ b/src/mscorlib/shared/System/SerializableAttribute.cs
@@ -0,0 +1,12 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System
+{
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Delegate, Inherited = false)]
+ public sealed class SerializableAttribute : Attribute
+ {
+ public SerializableAttribute() { }
+ }
+}
diff --git a/src/mscorlib/shared/System/Single.cs b/src/mscorlib/shared/System/Single.cs
new file mode 100644
index 0000000000..0be8cfbc37
--- /dev/null
+++ b/src/mscorlib/shared/System/Single.cs
@@ -0,0 +1,442 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: A wrapper class for the primitive type float.
+**
+**
+===========================================================*/
+
+using System.Diagnostics.Contracts;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+
+namespace System
+{
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
+ [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ public struct Single : IComparable, IConvertible, IFormattable, IComparable<Single>, IEquatable<Single>
+ {
+ private float m_value; // Do not rename (binary serialization)
+
+ //
+ // Public constants
+ //
+ public const float MinValue = (float)-3.40282346638528859e+38;
+ public const float Epsilon = (float)1.4e-45;
+ public const float MaxValue = (float)3.40282346638528859e+38;
+ public const float PositiveInfinity = (float)1.0 / (float)0.0;
+ public const float NegativeInfinity = (float)-1.0 / (float)0.0;
+ public const float NaN = (float)0.0 / (float)0.0;
+
+ // We use this explicit definition to avoid the confusion between 0.0 and -0.0.
+ internal const float NegativeZero = (float)-0.0;
+
+ /// <summary>Determines whether the specified value is finite (zero, subnormal, or normal).</summary>
+ [Pure]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool IsFinite(float f)
+ {
+ var bits = BitConverter.SingleToInt32Bits(f);
+ return (bits & 0x7FFFFFFF) < 0x7F800000;
+ }
+
+ /// <summary>Determines whether the specified value is infinite.</summary>
+ [Pure]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe static bool IsInfinity(float f)
+ {
+ var bits = BitConverter.SingleToInt32Bits(f);
+ return (bits & 0x7FFFFFFF) == 0x7F800000;
+ }
+
+ /// <summary>Determines whether the specified value is NaN.</summary>
+ [Pure]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe static bool IsNaN(float f)
+ {
+ var bits = BitConverter.SingleToInt32Bits(f);
+ return (bits & 0x7FFFFFFF) > 0x7F800000;
+ }
+
+ /// <summary>Determines whether the specified value is negative.</summary>
+ [Pure]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe static bool IsNegative(float f)
+ {
+ var bits = unchecked((uint)BitConverter.SingleToInt32Bits(f));
+ return (bits & 0x80000000) == 0x80000000;
+ }
+
+ /// <summary>Determines whether the specified value is negative infinity.</summary>
+ [Pure]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe static bool IsNegativeInfinity(float f)
+ {
+ return (f == float.NegativeInfinity);
+ }
+
+ /// <summary>Determines whether the specified value is normal.</summary>
+ [Pure]
+ [NonVersionable]
+ // This is probably not worth inlining, it has branches and should be rarely called
+ public unsafe static bool IsNormal(float f)
+ {
+ var bits = BitConverter.SingleToInt32Bits(f);
+ bits &= 0x7FFFFFFF;
+ return (bits < 0x7F800000) && (bits != 0) && ((bits & 0x7F800000) != 0);
+ }
+
+ /// <summary>Determines whether the specified value is positive infinity.</summary>
+ [Pure]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe static bool IsPositiveInfinity(float f)
+ {
+ return (f == float.PositiveInfinity);
+ }
+
+ /// <summary>Determines whether the specified value is subnormal.</summary>
+ [Pure]
+ [NonVersionable]
+ // This is probably not worth inlining, it has branches and should be rarely called
+ public unsafe static bool IsSubnormal(float f)
+ {
+ var bits = BitConverter.SingleToInt32Bits(f);
+ bits &= 0x7FFFFFFF;
+ return (bits < 0x7F800000) && (bits != 0) && ((bits & 0x7F800000) == 0);
+ }
+
+ // Compares this object to another object, returning an integer that
+ // indicates the relationship.
+ // Returns a value less than zero if this object
+ // null is considered to be less than any instance.
+ // If object is not of type Single, this method throws an ArgumentException.
+ //
+ public int CompareTo(Object value)
+ {
+ if (value == null)
+ {
+ return 1;
+ }
+ if (value is Single)
+ {
+ float f = (float)value;
+ if (m_value < f) return -1;
+ if (m_value > f) return 1;
+ if (m_value == f) return 0;
+
+ // At least one of the values is NaN.
+ if (IsNaN(m_value))
+ return (IsNaN(f) ? 0 : -1);
+ else // f is NaN.
+ return 1;
+ }
+ throw new ArgumentException(SR.Arg_MustBeSingle);
+ }
+
+
+ public int CompareTo(Single value)
+ {
+ if (m_value < value) return -1;
+ if (m_value > value) return 1;
+ if (m_value == value) return 0;
+
+ // At least one of the values is NaN.
+ if (IsNaN(m_value))
+ return (IsNaN(value) ? 0 : -1);
+ else // f is NaN.
+ return 1;
+ }
+
+ [NonVersionable]
+ public static bool operator ==(Single left, Single right)
+ {
+ return left == right;
+ }
+
+ [NonVersionable]
+ public static bool operator !=(Single left, Single right)
+ {
+ return left != right;
+ }
+
+ [NonVersionable]
+ public static bool operator <(Single left, Single right)
+ {
+ return left < right;
+ }
+
+ [NonVersionable]
+ public static bool operator >(Single left, Single right)
+ {
+ return left > right;
+ }
+
+ [NonVersionable]
+ public static bool operator <=(Single left, Single right)
+ {
+ return left <= right;
+ }
+
+ [NonVersionable]
+ public static bool operator >=(Single left, Single right)
+ {
+ return left >= right;
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (!(obj is Single))
+ {
+ return false;
+ }
+ float temp = ((Single)obj).m_value;
+ if (temp == m_value)
+ {
+ return true;
+ }
+
+ return IsNaN(temp) && IsNaN(m_value);
+ }
+
+ public bool Equals(Single obj)
+ {
+ if (obj == m_value)
+ {
+ return true;
+ }
+
+ return IsNaN(obj) && IsNaN(m_value);
+ }
+
+ public unsafe override int GetHashCode()
+ {
+ float f = m_value;
+ if (f == 0)
+ {
+ // Ensure that 0 and -0 have the same hash code
+ return 0;
+ }
+ int v = *(int*)(&f);
+ return v;
+ }
+
+ public override String ToString()
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatSingle(m_value, null, NumberFormatInfo.CurrentInfo);
+ }
+
+ public String ToString(IFormatProvider provider)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatSingle(m_value, null, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public String ToString(String format)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatSingle(m_value, format, NumberFormatInfo.CurrentInfo);
+ }
+
+ public String ToString(String format, IFormatProvider provider)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatSingle(m_value, format, NumberFormatInfo.GetInstance(provider));
+ }
+
+ // Parses a float from a String in the given style. If
+ // a NumberFormatInfo isn't specified, the current culture's
+ // NumberFormatInfo is assumed.
+ //
+ // This method will not throw an OverflowException, but will return
+ // PositiveInfinity or NegativeInfinity for a number that is too
+ // large or too small.
+ //
+ public static float Parse(String s)
+ {
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseSingle(s.AsReadOnlySpan(), NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo);
+ }
+
+ public static float Parse(String s, NumberStyles style)
+ {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseSingle(s.AsReadOnlySpan(), style, NumberFormatInfo.CurrentInfo);
+ }
+
+ public static float Parse(String s, IFormatProvider provider)
+ {
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseSingle(s.AsReadOnlySpan(), NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public static float Parse(String s, NumberStyles style, IFormatProvider provider)
+ {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseSingle(s.AsReadOnlySpan(), style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public static float Parse(ReadOnlySpan<char> s, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null)
+ {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ return Number.ParseSingle(s, style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public static Boolean TryParse(String s, out Single result)
+ {
+ if (s == null)
+ {
+ result = 0;
+ return false;
+ }
+
+ return TryParse(s.AsReadOnlySpan(), NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo, out result);
+ }
+
+ public static Boolean TryParse(String s, NumberStyles style, IFormatProvider provider, out Single result)
+ {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+
+ if (s == null)
+ {
+ result = 0;
+ return false;
+ }
+
+ return TryParse(s.AsReadOnlySpan(), style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ public static Boolean TryParse(ReadOnlySpan<char> s, out Single result, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null)
+ {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ private static Boolean TryParse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out Single result)
+ {
+ bool success = Number.TryParseSingle(s, style, info, out result);
+ if (!success)
+ {
+ ReadOnlySpan<char> sTrim = s.Trim();
+ if (StringSpanHelpers.Equals(sTrim, info.PositiveInfinitySymbol))
+ {
+ result = PositiveInfinity;
+ }
+ else if (StringSpanHelpers.Equals(sTrim, info.NegativeInfinitySymbol))
+ {
+ result = NegativeInfinity;
+ }
+ else if (StringSpanHelpers.Equals(sTrim, info.NaNSymbol))
+ {
+ result = NaN;
+ }
+ else
+ {
+ return false; // We really failed
+ }
+ }
+ return true;
+ }
+
+ //
+ // IConvertible implementation
+ //
+
+ public TypeCode GetTypeCode()
+ {
+ return TypeCode.Single;
+ }
+
+
+ bool IConvertible.ToBoolean(IFormatProvider provider)
+ {
+ return Convert.ToBoolean(m_value);
+ }
+
+ char IConvertible.ToChar(IFormatProvider provider)
+ {
+ throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Single", "Char"));
+ }
+
+ sbyte IConvertible.ToSByte(IFormatProvider provider)
+ {
+ return Convert.ToSByte(m_value);
+ }
+
+ byte IConvertible.ToByte(IFormatProvider provider)
+ {
+ return Convert.ToByte(m_value);
+ }
+
+ short IConvertible.ToInt16(IFormatProvider provider)
+ {
+ return Convert.ToInt16(m_value);
+ }
+
+ ushort IConvertible.ToUInt16(IFormatProvider provider)
+ {
+ return Convert.ToUInt16(m_value);
+ }
+
+ int IConvertible.ToInt32(IFormatProvider provider)
+ {
+ return Convert.ToInt32(m_value);
+ }
+
+ uint IConvertible.ToUInt32(IFormatProvider provider)
+ {
+ return Convert.ToUInt32(m_value);
+ }
+
+ long IConvertible.ToInt64(IFormatProvider provider)
+ {
+ return Convert.ToInt64(m_value);
+ }
+
+ ulong IConvertible.ToUInt64(IFormatProvider provider)
+ {
+ return Convert.ToUInt64(m_value);
+ }
+
+ float IConvertible.ToSingle(IFormatProvider provider)
+ {
+ return m_value;
+ }
+
+ double IConvertible.ToDouble(IFormatProvider provider)
+ {
+ return Convert.ToDouble(m_value);
+ }
+
+ Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ {
+ return Convert.ToDecimal(m_value);
+ }
+
+ DateTime IConvertible.ToDateTime(IFormatProvider provider)
+ {
+ throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Single", "DateTime"));
+ }
+
+ Object IConvertible.ToType(Type type, IFormatProvider provider)
+ {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/Span.NonGeneric.cs b/src/mscorlib/shared/System/Span.NonGeneric.cs
index 62b6faa8ec..0e8bfaa994 100644
--- a/src/mscorlib/shared/System/Span.NonGeneric.cs
+++ b/src/mscorlib/shared/System/Span.NonGeneric.cs
@@ -118,7 +118,7 @@ namespace System
/// <exception cref="System.ArgumentNullException">Thrown when <paramref name="text"/> is a null
/// reference (Nothing in Visual Basic).</exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ReadOnlySpan<char> AsSpan(this string text)
+ public static ReadOnlySpan<char> AsReadOnlySpan(this string text)
{
if (text == null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.text);
diff --git a/src/mscorlib/shared/System/Span.cs b/src/mscorlib/shared/System/Span.cs
index 88612eb28b..de6787d09d 100644
--- a/src/mscorlib/shared/System/Span.cs
+++ b/src/mscorlib/shared/System/Span.cs
@@ -2,11 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System.ComponentModel;
using System.Diagnostics;
-using System.Runtime;
using System.Runtime.CompilerServices;
-using EditorBrowsableState = System.ComponentModel.EditorBrowsableState;
-using EditorBrowsableAttribute = System.ComponentModel.EditorBrowsableAttribute;
+using System.Runtime.Versioning;
#pragma warning disable 0809 //warning CS0809: Obsolete member 'Span<T>.Equals(object)' overrides non-obsolete member 'object.Equals(object)'
@@ -22,7 +21,9 @@ namespace System
/// Span represents a contiguous region of arbitrary memory. Unlike arrays, it can point to either managed
/// or native memory, or to memory allocated on the stack. It is type- and memory-safe.
/// </summary>
+ [IsReadOnly]
[IsByRefLike]
+ [NonVersionable]
public struct Span<T>
{
/// <summary>A byref or a native ptr.</summary>
@@ -54,32 +55,6 @@ namespace System
/// <summary>
/// Creates a new span over the portion of the target array beginning
- /// at 'start' index and covering the remainder of the array.
- /// </summary>
- /// <param name="array">The target array.</param>
- /// <param name="start">The index at which to begin the span.</param>
- /// <exception cref="System.ArgumentNullException">Thrown when <paramref name="array"/> is a null
- /// reference (Nothing in Visual Basic).</exception>
- /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant and array's type is not exactly T[].</exception>
- /// <exception cref="System.ArgumentOutOfRangeException">
- /// Thrown when the specified <paramref name="start"/> is not in the range (&lt;0 or &gt;=Length).
- /// </exception>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Span(T[] array, int start)
- {
- if (array == null)
- ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
- if (default(T) == null && array.GetType() != typeof(T[]))
- ThrowHelper.ThrowArrayTypeMismatchException();
- if ((uint)start > (uint)array.Length)
- ThrowHelper.ThrowArgumentOutOfRangeException();
-
- _pointer = new ByReference<T>(ref Unsafe.Add(ref Unsafe.As<byte, T>(ref array.GetRawSzArrayData()), start));
- _length = array.Length - start;
- }
-
- /// <summary>
- /// Creates a new span over the portion of the target array beginning
/// at 'start' index and ending at 'end' index (exclusive).
/// </summary>
/// <param name="array">The target array.</param>
@@ -142,6 +117,7 @@ namespace System
/// <param name="objectData">A reference to data within that object.</param>
/// <param name="length">The number of <typeparamref name="T"/> elements the memory contains.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [EditorBrowsable(EditorBrowsableState.Never)]
public static Span<T> DangerousCreate(object obj, ref T objectData, int length) => new Span<T>(ref objectData, length);
// Constructor for internal use only.
@@ -158,6 +134,8 @@ namespace System
/// Returns a reference to the 0th element of the Span. If the Span is empty, returns a reference to the location where the 0th element
/// would have been stored. Such a reference can be used for pinning but must never be dereferenced.
/// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [EditorBrowsable(EditorBrowsableState.Never)]
public ref T DangerousGetPinnableReference()
{
return ref _pointer.Value;
@@ -166,12 +144,26 @@ namespace System
/// <summary>
/// The number of items in the span.
/// </summary>
- public int Length => _length;
+ public int Length
+ {
+ [NonVersionable]
+ get
+ {
+ return _length;
+ }
+ }
/// <summary>
/// Returns true if Length is 0.
/// </summary>
- public bool IsEmpty => _length == 0;
+ public bool IsEmpty
+ {
+ [NonVersionable]
+ get
+ {
+ return _length == 0;
+ }
+ }
/// <summary>
/// Returns a reference to specified element of the Span.
@@ -194,6 +186,7 @@ namespace System
[Intrinsic]
#endif
[MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [NonVersionable]
get
{
if ((uint)index >= (uint)_length)
diff --git a/src/mscorlib/shared/System/StackOverflowException.cs b/src/mscorlib/shared/System/StackOverflowException.cs
index fb0e88246c..8b21eb769a 100644
--- a/src/mscorlib/shared/System/StackOverflowException.cs
+++ b/src/mscorlib/shared/System/StackOverflowException.cs
@@ -20,19 +20,19 @@ namespace System
public StackOverflowException()
: base(SR.Arg_StackOverflowException)
{
- HResult = __HResults.COR_E_STACKOVERFLOW;
+ HResult = HResults.COR_E_STACKOVERFLOW;
}
public StackOverflowException(String message)
: base(message)
{
- HResult = __HResults.COR_E_STACKOVERFLOW;
+ HResult = HResults.COR_E_STACKOVERFLOW;
}
public StackOverflowException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_STACKOVERFLOW;
+ HResult = HResults.COR_E_STACKOVERFLOW;
}
}
}
diff --git a/src/mscorlib/shared/System/StringSpanHelpers.cs b/src/mscorlib/shared/System/StringSpanHelpers.cs
new file mode 100644
index 0000000000..bdfd965641
--- /dev/null
+++ b/src/mscorlib/shared/System/StringSpanHelpers.cs
@@ -0,0 +1,93 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Globalization;
+
+namespace System
+{
+ /// <summary>Helpers for string-like operations on spans of chars.</summary>
+ internal static class StringSpanHelpers
+ {
+ // TODO https://github.com/dotnet/corefx/issues/21395: Provide public, efficient implementations
+
+ public static bool Equals(this ReadOnlySpan<char> left, ReadOnlySpan<char> right, StringComparison comparisonType) =>
+ comparisonType == StringComparison.Ordinal ? Equals(left, right) :
+ comparisonType == StringComparison.OrdinalIgnoreCase ? EqualsOrdinalIgnoreCase(left, right) :
+ throw new ArgumentOutOfRangeException(nameof(comparisonType));
+
+ public static bool Equals(this ReadOnlySpan<char> left, string right) =>
+ Equals(left, right.AsReadOnlySpan());
+
+ public static bool Equals(this ReadOnlySpan<char> left, ReadOnlySpan<char> right)
+ {
+ if (left.Length != right.Length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i < left.Length; i++)
+ {
+ if (left[i] != right[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static bool EqualsOrdinalIgnoreCase(this ReadOnlySpan<char> left, ReadOnlySpan<char> right)
+ {
+ if (left.Length != right.Length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i < left.Length; i++)
+ {
+ char x = left[i], y = right[i];
+ if (x != y &&
+ TextInfo.ToUpperAsciiInvariant(x) != TextInfo.ToUpperAsciiInvariant(y))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static ReadOnlySpan<char> Trim(this ReadOnlySpan<char> source)
+ {
+ int startIndex = 0, endIndex = source.Length - 1;
+
+ while (startIndex <= endIndex && char.IsWhiteSpace(source[startIndex]))
+ {
+ startIndex++;
+ }
+
+ while (endIndex >= startIndex && char.IsWhiteSpace(source[endIndex]))
+ {
+ endIndex--;
+ }
+
+ return source.Slice(startIndex, endIndex - startIndex + 1);
+ }
+
+ public static int IndexOf(this ReadOnlySpan<char> source, char value) =>
+ IndexOf(source, value, 0);
+
+ public static int IndexOf(this ReadOnlySpan<char> source, char value, int startIndex)
+ {
+ for (int i = startIndex; i < source.Length; i++)
+ {
+ if (source[i] == value)
+ {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/SystemException.cs b/src/mscorlib/shared/System/SystemException.cs
index d5bcde7efc..64a4b9ca31 100644
--- a/src/mscorlib/shared/System/SystemException.cs
+++ b/src/mscorlib/shared/System/SystemException.cs
@@ -11,19 +11,19 @@ namespace System
public SystemException()
: base(SR.Arg_SystemException)
{
- HResult = __HResults.COR_E_SYSTEM;
+ HResult = HResults.COR_E_SYSTEM;
}
public SystemException(String message)
: base(message)
{
- HResult = __HResults.COR_E_SYSTEM;
+ HResult = HResults.COR_E_SYSTEM;
}
public SystemException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_SYSTEM;
+ HResult = HResults.COR_E_SYSTEM;
}
protected SystemException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/Text/Decoder.cs b/src/mscorlib/shared/System/Text/Decoder.cs
index f109f3db49..82d33d518c 100644
--- a/src/mscorlib/shared/System/Text/Decoder.cs
+++ b/src/mscorlib/shared/System/Text/Decoder.cs
@@ -134,6 +134,14 @@ namespace System.Text
return GetCharCount(arrbyte, 0, count);
}
+ public virtual unsafe int GetCharCount(ReadOnlySpan<byte> bytes, bool flush)
+ {
+ fixed (byte* bytesPtr = &bytes.DangerousGetPinnableReference())
+ {
+ return GetCharCount(bytesPtr, bytes.Length, flush);
+ }
+ }
+
// Decodes a range of bytes in a byte array into a range of characters
// in a character array. The method decodes byteCount bytes from
// bytes starting at index byteIndex, storing the resulting
@@ -220,6 +228,15 @@ namespace System.Text
return charCount;
}
+ public virtual unsafe int GetChars(ReadOnlySpan<byte> bytes, Span<char> chars, bool flush)
+ {
+ fixed (byte* bytesPtr = &bytes.DangerousGetPinnableReference())
+ fixed (char* charsPtr = &chars.DangerousGetPinnableReference())
+ {
+ return GetChars(bytesPtr, bytes.Length, charsPtr, chars.Length, flush);
+ }
+ }
+
// This method is used when the output buffer might not be large enough.
// It will decode until it runs out of bytes, and then it will return
// true if it the entire input was converted. In either case it
@@ -326,5 +343,14 @@ namespace System.Text
// Oops, we didn't have anything, we'll have to throw an overflow
throw new ArgumentException(SR.Argument_ConversionOverflow);
}
+
+ public virtual unsafe void Convert(ReadOnlySpan<byte> bytes, Span<char> chars, bool flush, out int bytesUsed, out int charsUsed, out bool completed)
+ {
+ fixed (byte* bytesPtr = &bytes.DangerousGetPinnableReference())
+ fixed (char* charsPtr = &chars.DangerousGetPinnableReference())
+ {
+ Convert(bytesPtr, bytes.Length, charsPtr, chars.Length, flush, out bytesUsed, out charsUsed, out completed);
+ }
+ }
}
}
diff --git a/src/mscorlib/shared/System/Text/DecoderExceptionFallback.cs b/src/mscorlib/shared/System/Text/DecoderExceptionFallback.cs
index b465aa68ef..26d604a919 100644
--- a/src/mscorlib/shared/System/Text/DecoderExceptionFallback.cs
+++ b/src/mscorlib/shared/System/Text/DecoderExceptionFallback.cs
@@ -106,19 +106,19 @@ namespace System.Text
public DecoderFallbackException()
: base(SR.Arg_ArgumentException)
{
- HResult = __HResults.COR_E_ARGUMENT;
+ HResult = HResults.COR_E_ARGUMENT;
}
public DecoderFallbackException(String message)
: base(message)
{
- HResult = __HResults.COR_E_ARGUMENT;
+ HResult = HResults.COR_E_ARGUMENT;
}
public DecoderFallbackException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_ARGUMENT;
+ HResult = HResults.COR_E_ARGUMENT;
}
public DecoderFallbackException(String message, byte[] bytesUnknown, int index)
diff --git a/src/mscorlib/shared/System/Text/Encoder.cs b/src/mscorlib/shared/System/Text/Encoder.cs
index b0602f3cce..79a633f1ff 100644
--- a/src/mscorlib/shared/System/Text/Encoder.cs
+++ b/src/mscorlib/shared/System/Text/Encoder.cs
@@ -132,6 +132,14 @@ namespace System.Text
return GetByteCount(arrChar, 0, count, flush);
}
+ public virtual unsafe int GetByteCount(ReadOnlySpan<char> chars, bool flush)
+ {
+ fixed (char* charsPtr = &chars.DangerousGetPinnableReference())
+ {
+ return GetByteCount(charsPtr, chars.Length, flush);
+ }
+ }
+
// Encodes a range of characters in a character array into a range of bytes
// in a byte array. The method encodes charCount characters from
// chars starting at index charIndex, storing the resulting
@@ -214,6 +222,15 @@ namespace System.Text
return byteCount;
}
+ public virtual unsafe int GetBytes(ReadOnlySpan<char> chars, Span<byte> bytes, bool flush)
+ {
+ fixed (char* charsPtr = &chars.DangerousGetPinnableReference())
+ fixed (byte* bytesPtr = &bytes.DangerousGetPinnableReference())
+ {
+ return GetBytes(charsPtr, chars.Length, bytesPtr, bytes.Length, flush);
+ }
+ }
+
// This method is used to avoid running out of output buffer space.
// It will encode until it runs out of chars, and then it will return
// true if it the entire input was converted. In either case it
@@ -320,6 +337,15 @@ namespace System.Text
// Oops, we didn't have anything, we'll have to throw an overflow
throw new ArgumentException(SR.Argument_ConversionOverflow);
}
+
+ public virtual unsafe void Convert(ReadOnlySpan<char> chars, Span<byte> bytes, bool flush, out int charsUsed, out int bytesUsed, out bool completed)
+ {
+ fixed (char* charsPtr = &chars.DangerousGetPinnableReference())
+ fixed (byte* bytesPtr = &bytes.DangerousGetPinnableReference())
+ {
+ Convert(charsPtr, chars.Length, bytesPtr, bytes.Length, flush, out charsUsed, out bytesUsed, out completed);
+ }
+ }
}
}
diff --git a/src/mscorlib/shared/System/Text/EncoderExceptionFallback.cs b/src/mscorlib/shared/System/Text/EncoderExceptionFallback.cs
index 98eff25b94..71426e5f31 100644
--- a/src/mscorlib/shared/System/Text/EncoderExceptionFallback.cs
+++ b/src/mscorlib/shared/System/Text/EncoderExceptionFallback.cs
@@ -108,19 +108,19 @@ namespace System.Text
public EncoderFallbackException()
: base(SR.Arg_ArgumentException)
{
- HResult = __HResults.COR_E_ARGUMENT;
+ HResult = HResults.COR_E_ARGUMENT;
}
public EncoderFallbackException(String message)
: base(message)
{
- HResult = __HResults.COR_E_ARGUMENT;
+ HResult = HResults.COR_E_ARGUMENT;
}
public EncoderFallbackException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_ARGUMENT;
+ HResult = HResults.COR_E_ARGUMENT;
}
internal EncoderFallbackException(
diff --git a/src/mscorlib/shared/System/Text/Encoding.cs b/src/mscorlib/shared/System/Text/Encoding.cs
index 4f23d2a4a7..bf8cb03db2 100644
--- a/src/mscorlib/shared/System/Text/Encoding.cs
+++ b/src/mscorlib/shared/System/Text/Encoding.cs
@@ -382,6 +382,8 @@ namespace System.Text
return Array.Empty<byte>();
}
+ public virtual ReadOnlySpan<byte> Preamble => GetPreamble();
+
private void GetDataItem()
{
if (_dataItem == null)
@@ -733,6 +735,14 @@ namespace System.Text
return GetByteCount(arrChar, 0, count);
}
+ public virtual unsafe int GetByteCount(ReadOnlySpan<char> chars)
+ {
+ fixed (char* charsPtr = &chars.DangerousGetPinnableReference())
+ {
+ return GetByteCount(charsPtr, chars.Length);
+ }
+ }
+
// For NLS Encodings, workhorse takes an encoder (may be null)
// Always validate parameters before calling internal version, which will only assert.
internal virtual unsafe int GetByteCount(char* chars, int count, EncoderNLS encoder)
@@ -916,6 +926,15 @@ namespace System.Text
return byteCount;
}
+ public virtual unsafe int GetBytes(ReadOnlySpan<char> chars, Span<byte> bytes)
+ {
+ fixed (char* charsPtr = &chars.DangerousGetPinnableReference())
+ fixed (byte* bytesPtr = &bytes.DangerousGetPinnableReference())
+ {
+ return GetBytes(charsPtr, chars.Length, bytesPtr, bytes.Length);
+ }
+ }
+
// Returns the number of characters produced by decoding the given byte
// array.
//
@@ -962,6 +981,14 @@ namespace System.Text
return GetCharCount(arrbyte, 0, count);
}
+ public virtual unsafe int GetCharCount(ReadOnlySpan<byte> bytes)
+ {
+ fixed (byte* bytesPtr = &bytes.DangerousGetPinnableReference())
+ {
+ return GetCharCount(bytesPtr, bytes.Length);
+ }
+ }
+
// This is our internal workhorse
// Always validate parameters before calling internal version, which will only assert.
internal virtual unsafe int GetCharCount(byte* bytes, int count, DecoderNLS decoder)
@@ -1070,6 +1097,14 @@ namespace System.Text
return charCount;
}
+ public virtual unsafe int GetChars(ReadOnlySpan<byte> bytes, Span<char> chars)
+ {
+ fixed (byte* bytesPtr = &bytes.DangerousGetPinnableReference())
+ fixed (char* charsPtr = &chars.DangerousGetPinnableReference())
+ {
+ return GetChars(bytesPtr, bytes.Length, charsPtr, chars.Length);
+ }
+ }
// This is our internal workhorse
// Always validate parameters before calling internal version, which will only assert.
@@ -1093,6 +1128,15 @@ namespace System.Text
return String.CreateStringFromEncoding(bytes, byteCount, this);
}
+ public unsafe string GetString(ReadOnlySpan<byte> bytes)
+ {
+ fixed (byte* bytesPtr = &bytes.DangerousGetPinnableReference())
+ {
+ return GetString(bytesPtr, bytes.Length);
+ }
+ }
+
+
// Returns the code page identifier of this encoding. The returned value is
// an integer between 0 and 65535 if the encoding has a code page
// identifier, or -1 if the encoding does not represent a code page.
diff --git a/src/mscorlib/shared/System/Text/Normalization.cs b/src/mscorlib/shared/System/Text/Normalization.cs
index dc8bc2af71..976756251a 100644
--- a/src/mscorlib/shared/System/Text/Normalization.cs
+++ b/src/mscorlib/shared/System/Text/Normalization.cs
@@ -4,7 +4,6 @@
namespace System.Text
{
- // This is the enumeration for Normalization Forms
public enum NormalizationForm
{
FormC = 1,
@@ -12,18 +11,4 @@ namespace System.Text
FormKC = 5,
FormKD = 6
}
-
- internal enum ExtendedNormalizationForms
- {
- FormC = 1,
- FormD = 2,
- FormKC = 5,
- FormKD = 6,
- FormIdna = 0xd,
- FormCDisallowUnassigned = 0x101,
- FormDDisallowUnassigned = 0x102,
- FormKCDisallowUnassigned = 0x105,
- FormKDDisallowUnassigned = 0x106,
- FormIdnaDisallowUnassigned = 0x10d
- }
}
diff --git a/src/mscorlib/shared/System/Text/StringBuilder.cs b/src/mscorlib/shared/System/Text/StringBuilder.cs
index 34533a92ca..a73e6757d4 100644
--- a/src/mscorlib/shared/System/Text/StringBuilder.cs
+++ b/src/mscorlib/shared/System/Text/StringBuilder.cs
@@ -822,11 +822,6 @@ namespace System.Text
throw new ArgumentNullException(nameof(destination));
}
- if (count < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(count), SR.Arg_NegativeArgCount);
- }
-
if (destinationIndex < 0)
{
throw new ArgumentOutOfRangeException(nameof(destinationIndex), SR.Format(SR.ArgumentOutOfRange_MustBeNonNegNum, nameof(destinationIndex)));
@@ -836,6 +831,17 @@ namespace System.Text
{
throw new ArgumentException(SR.ArgumentOutOfRange_OffsetOut);
}
+ Contract.EndContractBlock();
+
+ CopyTo(sourceIndex, new Span<char>(destination).Slice(destinationIndex), count);
+ }
+
+ public void CopyTo(int sourceIndex, Span<char> destination, int count)
+ {
+ if (count < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(count), SR.Arg_NegativeArgCount);
+ }
if ((uint)sourceIndex > (uint)Length)
{
@@ -852,7 +858,7 @@ namespace System.Text
StringBuilder chunk = this;
int sourceEndIndex = sourceIndex + count;
- int curDestIndex = destinationIndex + count;
+ int curDestIndex = count;
while (count > 0)
{
int chunkEndIndex = sourceEndIndex - chunk.m_ChunkOffset;
@@ -1033,6 +1039,21 @@ namespace System.Text
return this;
}
+ public StringBuilder Append(ReadOnlySpan<char> value)
+ {
+ if (value.Length > 0)
+ {
+ unsafe
+ {
+ fixed (char* valueChars = &value.DangerousGetPinnableReference())
+ {
+ Append(valueChars, value.Length);
+ }
+ }
+ }
+ return this;
+ }
+
#region AppendJoin
public unsafe StringBuilder AppendJoin(string separator, params object[] values)
@@ -1263,6 +1284,27 @@ namespace System.Text
public StringBuilder Insert(int index, Object value) => (value == null) ? this : Insert(index, value.ToString(), 1);
+ public StringBuilder Insert(int index, ReadOnlySpan<char> value)
+ {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ Contract.EndContractBlock();
+
+ if ((uint)index > (uint)Length)
+ {
+ throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index);
+ }
+
+ if (value.Length > 0)
+ {
+ unsafe
+ {
+ fixed (char* sourcePtr = &value.DangerousGetPinnableReference())
+ Insert(index, sourcePtr, value.Length);
+ }
+ }
+ return this;
+ }
+
public StringBuilder AppendFormat(String format, Object arg0) => AppendFormatHelper(null, format, new ParamsArray(arg0));
public StringBuilder AppendFormat(String format, Object arg0, Object arg1) => AppendFormatHelper(null, format, new ParamsArray(arg0, arg1));
@@ -1884,7 +1926,7 @@ namespace System.Text
Debug.Assert(gapEnd <= sourceChunk.m_ChunkLength, "gap too big");
if (delta != 0) // can skip the sliding of gaps if source an target string are the same size.
{
- // Copy the gap data between the current replacement and the the next replacement
+ // Copy the gap data between the current replacement and the next replacement
fixed (char* sourcePtr = &sourceChunk.m_ChunkChars[gapStart])
ReplaceInPlaceAtChunk(ref targetChunk, ref targetIndexInChunk, sourcePtr, gapEnd - gapStart);
}
@@ -1944,7 +1986,7 @@ namespace System.Text
/// </summary>
/// <param name="chunk">
/// The chunk in which to start replacing characters.
- /// Receieves the chunk in which character replacement ends.
+ /// Receives the chunk in which character replacement ends.
/// </param>
/// <param name="indexInChunk">
/// The index in <paramref name="chunk"/> to start replacing characters at.
@@ -2001,22 +2043,23 @@ namespace System.Text
}
}
- private static void ThreadSafeCopy(char[] source, int sourceIndex, char[] destination, int destinationIndex, int count)
+ private static unsafe void ThreadSafeCopy(char[] source, int sourceIndex, Span<char> destination, int destinationIndex, int count)
{
if (count > 0)
{
- if ((uint)sourceIndex <= (uint)source.Length && (sourceIndex + count) <= source.Length)
+ if ((uint)sourceIndex > (uint)source.Length || count > source.Length - sourceIndex)
{
- unsafe
- {
- fixed (char* sourcePtr = &source[sourceIndex])
- ThreadSafeCopy(sourcePtr, destination, destinationIndex, count);
- }
+ throw new ArgumentOutOfRangeException(nameof(sourceIndex), SR.ArgumentOutOfRange_Index);
}
- else
+
+ if ((uint)destinationIndex > (uint)destination.Length || count > destination.Length - destinationIndex)
{
- throw new ArgumentOutOfRangeException(nameof(sourceIndex), SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(destinationIndex), SR.ArgumentOutOfRange_Index);
}
+
+ fixed (char* sourcePtr = &source[sourceIndex])
+ fixed (char* destinationPtr = &destination.DangerousGetPinnableReference())
+ string.wstrcpy(destinationPtr + destinationIndex, sourcePtr, count);
}
}
diff --git a/src/mscorlib/shared/System/Text/UTF32Encoding.cs b/src/mscorlib/shared/System/Text/UTF32Encoding.cs
index 10161d193e..260518e21c 100644
--- a/src/mscorlib/shared/System/Text/UTF32Encoding.cs
+++ b/src/mscorlib/shared/System/Text/UTF32Encoding.cs
@@ -39,6 +39,9 @@ namespace System.Text
internal static readonly UTF32Encoding s_default = new UTF32Encoding(bigEndian: false, byteOrderMark: true);
internal static readonly UTF32Encoding s_bigEndianDefault = new UTF32Encoding(bigEndian: true, byteOrderMark: true);
+ private static readonly byte[] s_bigEndianPreamble = new byte[4] { 0x00, 0x00, 0xFE, 0xFF };
+ private static readonly byte[] s_littleEndianPreamble = new byte[4] { 0xFF, 0xFE, 0x00, 0x00 };
+
private bool _emitUTF32ByteOrderMark = false;
private bool _isThrowException = false;
private bool _bigEndian = false;
@@ -1177,6 +1180,10 @@ namespace System.Text
return Array.Empty<byte>();
}
+ public override ReadOnlySpan<byte> Preamble =>
+ GetType() != typeof(UTF32Encoding) ? GetPreamble() : // in case a derived UTF32Encoding overrode GetPreamble
+ _emitUTF32ByteOrderMark ? (_bigEndian ? s_bigEndianPreamble : s_littleEndianPreamble) :
+ Array.Empty<byte>();
public override bool Equals(Object value)
{
diff --git a/src/mscorlib/shared/System/Text/UTF8Encoding.cs b/src/mscorlib/shared/System/Text/UTF8Encoding.cs
index 02b18935e4..974bf75650 100644
--- a/src/mscorlib/shared/System/Text/UTF8Encoding.cs
+++ b/src/mscorlib/shared/System/Text/UTF8Encoding.cs
@@ -54,15 +54,19 @@ namespace System.Text
internal sealed class UTF8EncodingSealed : UTF8Encoding
{
public UTF8EncodingSealed(bool encoderShouldEmitUTF8Identifier) : base(encoderShouldEmitUTF8Identifier) { }
+
+ public override ReadOnlySpan<byte> Preamble => _emitUTF8Identifier ? s_preamble : Array.Empty<byte>();
}
// Used by Encoding.UTF8 for lazy initialization
// The initialization code will not be run until a static member of the class is referenced
internal static readonly UTF8EncodingSealed s_default = new UTF8EncodingSealed(encoderShouldEmitUTF8Identifier: true);
+ internal static readonly byte[] s_preamble = new byte[3] { 0xEF, 0xBB, 0xBF };
+
// Yes, the idea of emitting U+FEFF as a UTF-8 identifier has made it into
// the standard.
- private bool _emitUTF8Identifier = false;
+ internal readonly bool _emitUTF8Identifier = false;
private bool _isThrowException = false;
@@ -2497,6 +2501,10 @@ namespace System.Text
return Array.Empty<byte>();
}
+ public override ReadOnlySpan<byte> Preamble =>
+ GetType() != typeof(UTF8Encoding) ? GetPreamble() : // in case a derived UTF8Encoding overrode GetPreamble
+ _emitUTF8Identifier ? s_preamble :
+ Array.Empty<byte>();
public override bool Equals(Object value)
{
diff --git a/src/mscorlib/shared/System/Text/UnicodeEncoding.cs b/src/mscorlib/shared/System/Text/UnicodeEncoding.cs
index 8e44317ce2..78355299c1 100644
--- a/src/mscorlib/shared/System/Text/UnicodeEncoding.cs
+++ b/src/mscorlib/shared/System/Text/UnicodeEncoding.cs
@@ -20,6 +20,9 @@ namespace System.Text
internal static readonly UnicodeEncoding s_bigEndianDefault = new UnicodeEncoding(bigEndian: true, byteOrderMark: true);
internal static readonly UnicodeEncoding s_littleEndianDefault = new UnicodeEncoding(bigEndian: false, byteOrderMark: true);
+ private static readonly byte[] s_bigEndianPreamble = new byte[2] { 0xfe, 0xff };
+ private static readonly byte[] s_littleEndianPreamble = new byte[2] { 0xff, 0xfe };
+
internal bool isThrowException = false;
internal bool bigEndian = false;
@@ -1898,6 +1901,10 @@ namespace System.Text
return Array.Empty<Byte>();
}
+ public override ReadOnlySpan<byte> Preamble =>
+ GetType() != typeof(UnicodeEncoding) ? GetPreamble() : // in case a derived UnicodeEncoding overrode GetPreamble
+ byteOrderMark ? (bigEndian ? s_bigEndianPreamble : s_littleEndianPreamble) :
+ Array.Empty<byte>();
public override int GetMaxByteCount(int charCount)
{
diff --git a/src/mscorlib/shared/System/Threading/AbandonedMutexException.cs b/src/mscorlib/shared/System/Threading/AbandonedMutexException.cs
index 15bc5a7341..c43148d22a 100644
--- a/src/mscorlib/shared/System/Threading/AbandonedMutexException.cs
+++ b/src/mscorlib/shared/System/Threading/AbandonedMutexException.cs
@@ -22,39 +22,39 @@ namespace System.Threading
public AbandonedMutexException()
: base(SR.Threading_AbandonedMutexException)
{
- HResult = __HResults.COR_E_ABANDONEDMUTEX;
+ HResult = HResults.COR_E_ABANDONEDMUTEX;
}
public AbandonedMutexException(String message)
: base(message)
{
- HResult = __HResults.COR_E_ABANDONEDMUTEX;
+ HResult = HResults.COR_E_ABANDONEDMUTEX;
}
public AbandonedMutexException(String message, Exception inner)
: base(message, inner)
{
- HResult = __HResults.COR_E_ABANDONEDMUTEX;
+ HResult = HResults.COR_E_ABANDONEDMUTEX;
}
public AbandonedMutexException(int location, WaitHandle handle)
: base(SR.Threading_AbandonedMutexException)
{
- HResult = __HResults.COR_E_ABANDONEDMUTEX;
+ HResult = HResults.COR_E_ABANDONEDMUTEX;
SetupException(location, handle);
}
public AbandonedMutexException(String message, int location, WaitHandle handle)
: base(message)
{
- HResult = __HResults.COR_E_ABANDONEDMUTEX;
+ HResult = HResults.COR_E_ABANDONEDMUTEX;
SetupException(location, handle);
}
public AbandonedMutexException(String message, Exception inner, int location, WaitHandle handle)
: base(message, inner)
{
- HResult = __HResults.COR_E_ABANDONEDMUTEX;
+ HResult = HResults.COR_E_ABANDONEDMUTEX;
SetupException(location, handle);
}
diff --git a/src/mscorlib/shared/System/Threading/DeferredDisposableLifetime.cs b/src/mscorlib/shared/System/Threading/DeferredDisposableLifetime.cs
index 89380fee60..e2b1eb983b 100644
--- a/src/mscorlib/shared/System/Threading/DeferredDisposableLifetime.cs
+++ b/src/mscorlib/shared/System/Threading/DeferredDisposableLifetime.cs
@@ -18,7 +18,7 @@ namespace System.Threading
/// Indicates whether the object has been disposed.
/// </param>
/// <remarks>
- /// If the refount reaches zero before the object is disposed, this method will be called with
+ /// If the refcount reaches zero before the object is disposed, this method will be called with
/// <paramref name="disposed"/> set to false. If the object is then disposed, this method will be
/// called again, with <paramref name="disposed"/> set to true. If the refcount reaches zero
/// after the object has already been disposed, this will be called a single time, with
diff --git a/src/mscorlib/shared/System/Threading/LazyInitializer.cs b/src/mscorlib/shared/System/Threading/LazyInitializer.cs
index b03d1db302..f422ab9172 100644
--- a/src/mscorlib/shared/System/Threading/LazyInitializer.cs
+++ b/src/mscorlib/shared/System/Threading/LazyInitializer.cs
@@ -25,7 +25,7 @@ namespace System.Threading
/// Initializes a target reference type with the type's default constructor if the target has not
/// already been initialized.
/// </summary>
- /// <typeparam name="T">The refence type of the reference to be initialized.</typeparam>
+ /// <typeparam name="T">The reference type of the reference to be initialized.</typeparam>
/// <param name="target">A reference of type <typeparamref name="T"/> to initialize if it has not
/// already been initialized.</param>
/// <returns>The initialized reference of type <typeparamref name="T"/>.</returns>
diff --git a/src/mscorlib/shared/System/Threading/ReaderWriterLockSlim.cs b/src/mscorlib/shared/System/Threading/ReaderWriterLockSlim.cs
index 98517ad85f..1b2147e6e1 100644
--- a/src/mscorlib/shared/System/Threading/ReaderWriterLockSlim.cs
+++ b/src/mscorlib/shared/System/Threading/ReaderWriterLockSlim.cs
@@ -4,7 +4,6 @@
using Internal.Runtime.Augments;
using System.Diagnostics; // for TraceInformation
-using System.Threading;
using System.Runtime.CompilerServices;
namespace System.Threading
@@ -54,8 +53,10 @@ namespace System.Threading
/// </summary>
public class ReaderWriterLockSlim : IDisposable
{
+ private static readonly int ProcessorCount = Environment.ProcessorCount;
+
//Specifying if locked can be reacquired recursively.
- private bool _fIsReentrant;
+ private readonly bool _fIsReentrant;
// Lock specification for myLock: This lock protects exactly the local fields associated with this
// instance of ReaderWriterLockSlim. It does NOT protect the memory associated with
@@ -74,8 +75,7 @@ namespace System.Threading
private uint _numWriteUpgradeWaiters; // maximum number of threads that can be doing a WaitOne on the upgradeEvent (at most 1).
private uint _numUpgradeWaiters;
- //Variable used for quick check when there are no waiters.
- private bool _fNoWaiters;
+ private WaiterStates _waiterStates;
private int _upgradeLockOwnerId;
private int _writeLockOwnerId;
@@ -146,10 +146,37 @@ namespace System.Threading
_fIsReentrant = true;
}
InitializeThreadCounts();
- _fNoWaiters = true;
+ _waiterStates = WaiterStates.NoWaiters;
_lockID = Interlocked.Increment(ref s_nextLockID);
}
+ private bool HasNoWaiters
+ {
+ get
+ {
+#if DEBUG
+ Debug.Assert(MyLockHeld);
+#endif
+
+ return (_waiterStates & WaiterStates.NoWaiters) != WaiterStates.None;
+ }
+ set
+ {
+#if DEBUG
+ Debug.Assert(MyLockHeld);
+#endif
+
+ if (value)
+ {
+ _waiterStates |= WaiterStates.NoWaiters;
+ }
+ else
+ {
+ _waiterStates &= ~WaiterStates.NoWaiters;
+ }
+ }
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool IsRWEntryEmpty(ReaderWriterCount rwc)
{
@@ -352,8 +379,7 @@ namespace System.Threading
}
bool retVal = true;
-
- int spincount = 0;
+ int spinCount = 0;
for (; ;)
{
@@ -368,13 +394,17 @@ namespace System.Threading
break;
}
- if (spincount < MaxSpinCount)
+ if (timeout.IsExpired)
{
ExitMyLock();
- if (timeout.IsExpired)
- return false;
- spincount++;
- SpinWait(spincount);
+ return false;
+ }
+
+ if (spinCount < MaxSpinCount && ShouldSpinForEnterAnyRead())
+ {
+ ExitMyLock();
+ spinCount++;
+ SpinWait(spinCount);
EnterMyLock();
//The per-thread structure may have been recycled as the lock is acquired (due to message pumping), load again.
if (IsRwHashEntryChanged(lrwc))
@@ -391,7 +421,13 @@ namespace System.Threading
continue; // since we left the lock, start over.
}
- retVal = WaitOnEvent(_readEvent, ref _numReadWaiters, timeout, isWriteWaiter: false);
+ retVal =
+ WaitOnEvent(
+ _readEvent,
+ ref _numReadWaiters,
+ timeout,
+ isWriteWaiter: false,
+ waiterSignaledState: WaiterStates.None);
if (!retVal)
{
return false;
@@ -480,8 +516,8 @@ namespace System.Threading
}
}
- int spincount = 0;
bool retVal = true;
+ int spinCount = 0;
for (; ;)
{
@@ -528,13 +564,17 @@ namespace System.Threading
}
}
- if (spincount < MaxSpinCount)
+ if (timeout.IsExpired)
{
ExitMyLock();
- if (timeout.IsExpired)
- return false;
- spincount++;
- SpinWait(spincount);
+ return false;
+ }
+
+ if (spinCount < MaxSpinCount && ShouldSpinForEnterAnyWrite(upgradingToWrite))
+ {
+ ExitMyLock();
+ spinCount++;
+ SpinWait(spinCount);
EnterMyLock();
continue;
}
@@ -549,7 +589,13 @@ namespace System.Threading
Debug.Assert(_numWriteUpgradeWaiters == 0, "There can be at most one thread with the upgrade lock held.");
- retVal = WaitOnEvent(_waitUpgradeEvent, ref _numWriteUpgradeWaiters, timeout, isWriteWaiter: true);
+ retVal =
+ WaitOnEvent(
+ _waitUpgradeEvent,
+ ref _numWriteUpgradeWaiters,
+ timeout,
+ isWriteWaiter: true,
+ waiterSignaledState: WaiterStates.None);
//The lock is not held in case of failure.
if (!retVal)
@@ -564,7 +610,13 @@ namespace System.Threading
continue; // since we left the lock, start over.
}
- retVal = WaitOnEvent(_writeEvent, ref _numWriteWaiters, timeout, isWriteWaiter: true);
+ retVal =
+ WaitOnEvent(
+ _writeEvent,
+ ref _numWriteWaiters,
+ timeout,
+ isWriteWaiter: true,
+ waiterSignaledState: WaiterStates.WriteWaiterSignaled);
//The lock is not held in case of failure.
if (!retVal)
return false;
@@ -671,8 +723,7 @@ namespace System.Threading
}
bool retVal = true;
-
- int spincount = 0;
+ int spinCount = 0;
for (; ;)
{
@@ -686,13 +737,17 @@ namespace System.Threading
break;
}
- if (spincount < MaxSpinCount)
+ if (timeout.IsExpired)
{
ExitMyLock();
- if (timeout.IsExpired)
- return false;
- spincount++;
- SpinWait(spincount);
+ return false;
+ }
+
+ if (spinCount < MaxSpinCount && ShouldSpinForEnterAnyRead())
+ {
+ ExitMyLock();
+ spinCount++;
+ SpinWait(spinCount);
EnterMyLock();
continue;
}
@@ -705,7 +760,13 @@ namespace System.Threading
}
//Only one thread with the upgrade lock held can proceed.
- retVal = WaitOnEvent(_upgradeEvent, ref _numUpgradeWaiters, timeout, isWriteWaiter: false);
+ retVal =
+ WaitOnEvent(
+ _upgradeEvent,
+ ref _numUpgradeWaiters,
+ timeout,
+ isWriteWaiter: false,
+ waiterSignaledState: WaiterStates.UpgradeableReadWaiterSignaled);
if (!retVal)
return false;
}
@@ -890,14 +951,20 @@ namespace System.Threading
EventWaitHandle waitEvent,
ref uint numWaiters,
TimeoutTracker timeout,
- bool isWriteWaiter)
+ bool isWriteWaiter,
+ WaiterStates waiterSignaledState)
{
#if DEBUG
Debug.Assert(MyLockHeld);
#endif
+ Debug.Assert(
+ waiterSignaledState == WaiterStates.None ||
+ waiterSignaledState == WaiterStates.WriteWaiterSignaled ||
+ waiterSignaledState == WaiterStates.UpgradeableReadWaiterSignaled);
+
waitEvent.Reset();
numWaiters++;
- _fNoWaiters = false;
+ HasNoWaiters = false;
//Setting these bits will prevent new readers from getting in.
if (_numWriteWaiters == 1)
@@ -917,8 +984,19 @@ namespace System.Threading
EnterMyLock();
--numWaiters;
+ if (waitSuccessful && waiterSignaledState != WaiterStates.None)
+ {
+ // Indicate that a signaled waiter of this type has woken. Since non-read waiters are signaled to wake one
+ // at a time, we avoid waking up more than one waiter of that type upon successive enter/exit loops until
+ // the signaled thread actually wakes up. For example, if there are multiple write waiters and one thread is
+ // repeatedly entering and exiting a write lock, every exit would otherwise signal a different write waiter
+ // to wake up unnecessarily when only one woken waiter may actually succeed in entering the write lock.
+ Debug.Assert((_waiterStates & waiterSignaledState) != WaiterStates.None);
+ _waiterStates &= ~waiterSignaledState;
+ }
+
if (_numWriteWaiters == 0 && _numWriteUpgradeWaiters == 0 && _numUpgradeWaiters == 0 && _numReadWaiters == 0)
- _fNoWaiters = true;
+ HasNoWaiters = true;
if (_numWriteWaiters == 0)
ClearWritersWaiting();
@@ -948,7 +1026,7 @@ namespace System.Threading
#if DEBUG
Debug.Assert(MyLockHeld);
#endif
- if (_fNoWaiters)
+ if (HasNoWaiters)
{
ExitMyLock();
return;
@@ -984,8 +1062,20 @@ namespace System.Threading
}
else if (readercount == 0 && _numWriteWaiters > 0)
{
+ // Check if a waiter of the same type has already been signaled but hasn't woken yet. If so, avoid signaling
+ // and waking another waiter unnecessarily.
+ WaiterStates signaled = _waiterStates & WaiterStates.WriteWaiterSignaled;
+ if (signaled == WaiterStates.None)
+ {
+ _waiterStates |= WaiterStates.WriteWaiterSignaled;
+ }
+
ExitMyLock(); // Exit before signaling to improve efficiency (wakee will need the lock)
- _writeEvent.Set(); // release one writer.
+
+ if (signaled == WaiterStates.None)
+ {
+ _writeEvent.Set(); // release one writer.
+ }
}
else
{
@@ -999,7 +1089,7 @@ namespace System.Threading
Debug.Assert(MyLockHeld);
#endif
- if (_numWriteWaiters != 0 || _numWriteUpgradeWaiters != 0 || _fNoWaiters)
+ if (_numWriteWaiters != 0 || _numWriteUpgradeWaiters != 0 || HasNoWaiters)
{
ExitMyLock();
return;
@@ -1009,6 +1099,19 @@ namespace System.Threading
bool setReadEvent = _numReadWaiters != 0;
bool setUpgradeEvent = _numUpgradeWaiters != 0 && _upgradeLockOwnerId == -1;
+ if (setUpgradeEvent)
+ {
+ // Check if a waiter of the same type has already been signaled but hasn't woken yet. If so, avoid signaling
+ // and waking another waiter unnecessarily.
+ if ((_waiterStates & WaiterStates.UpgradeableReadWaiterSignaled) == WaiterStates.None)
+ {
+ _waiterStates |= WaiterStates.UpgradeableReadWaiterSignaled;
+ }
+ else
+ {
+ setUpgradeEvent = false;
+ }
+ }
ExitMyLock(); // Exit before signaling to improve efficiency (wakee will need the lock)
@@ -1059,33 +1162,62 @@ namespace System.Threading
return _owners & READER_MASK;
}
+ private bool ShouldSpinForEnterAnyRead()
+ {
+ // If there is a write waiter or write upgrade waiter, the waiter would block a reader from acquiring the RW lock
+ // because the waiter takes precedence. In that case, the reader is not likely to make progress by spinning.
+ // Although another thread holding a write lock would prevent this thread from acquiring a read lock, it is by
+ // itself not a good enough reason to skip spinning.
+ return HasNoWaiters || (_numWriteWaiters == 0 && _numWriteUpgradeWaiters == 0);
+ }
+
+ private bool ShouldSpinForEnterAnyWrite(bool isUpgradeToWrite)
+ {
+ // If there is a write upgrade waiter, the waiter would block a writer from acquiring the RW lock because the waiter
+ // holds a read lock. In that case, the writer is not likely to make progress by spinning. Regarding upgrading to a
+ // write lock, there is no type of waiter that would block the upgrade from happening. Although another thread
+ // holding a read or write lock would prevent this thread from acquiring the write lock, it is by itself not a good
+ // enough reason to skip spinning.
+ return isUpgradeToWrite || _numWriteUpgradeWaiters == 0;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private bool TryEnterMyLock()
+ {
+ return Interlocked.CompareExchange(ref _myLock, 1, 0) == 0;
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void EnterMyLock()
{
- if (Interlocked.CompareExchange(ref _myLock, 1, 0) != 0)
+ if (!TryEnterMyLock())
+ {
EnterMyLockSpin();
+ }
}
private void EnterMyLockSpin()
{
- int pc = Environment.ProcessorCount;
- for (int i = 0; ; i++)
+ int processorCount = ProcessorCount;
+ for (int spinIndex = 0; ; spinIndex++)
{
- if (i < LockSpinCount && pc > 1)
+ if (spinIndex < LockSpinCount && processorCount > 1)
{
- RuntimeThread.SpinWait(LockSpinCycles * (i + 1)); // Wait a few dozen instructions to let another processor release lock.
+ RuntimeThread.SpinWait(LockSpinCycles * (spinIndex + 1)); // Wait a few dozen instructions to let another processor release lock.
}
- else if (i < (LockSpinCount + LockSleep0Count))
+ else if (spinIndex < (LockSpinCount + LockSleep0Count))
{
- RuntimeThread.Sleep(0); // Give up my quantum.
+ RuntimeThread.Sleep(0); // Give up my quantum.
}
else
{
- RuntimeThread.Sleep(1); // Give up my quantum.
+ RuntimeThread.Sleep(1); // Give up my quantum.
}
- if (_myLock == 0 && Interlocked.CompareExchange(ref _myLock, 1, 0) == 0)
+ if (_myLock == 0 && TryEnterMyLock())
+ {
return;
+ }
}
}
@@ -1099,12 +1231,12 @@ namespace System.Threading
private bool MyLockHeld { get { return _myLock != 0; } }
#endif
- private static void SpinWait(int SpinCount)
+ private static void SpinWait(int spinCount)
{
//Exponential back-off
- if ((SpinCount < 5) && (Environment.ProcessorCount > 1))
+ if ((spinCount < 5) && (ProcessorCount > 1))
{
- RuntimeThread.SpinWait(LockSpinCycles * SpinCount);
+ RuntimeThread.SpinWait(LockSpinCycles * spinCount);
}
else
{
@@ -1307,5 +1439,19 @@ namespace System.Threading
return (int)_numWriteWaiters;
}
}
+
+ [Flags]
+ private enum WaiterStates : byte
+ {
+ None = 0x0,
+
+ // Used for quick check when there are no waiters
+ NoWaiters = 0x1,
+
+ // Used to avoid signaling more than one waiter to wake up when only one can make progress, see WaitOnEvent
+ WriteWaiterSignaled = 0x2,
+ UpgradeableReadWaiterSignaled = 0x4
+ // Write upgrade waiters are excluded because there can only be one at any given time
+ }
}
}
diff --git a/src/mscorlib/shared/System/Threading/SpinWait.cs b/src/mscorlib/shared/System/Threading/SpinWait.cs
index d25d54f26f..414ad1852f 100644
--- a/src/mscorlib/shared/System/Threading/SpinWait.cs
+++ b/src/mscorlib/shared/System/Threading/SpinWait.cs
@@ -69,9 +69,26 @@ namespace System.Threading
// numbers may seem fairly arbitrary, but were derived with at least some
// thought in the design document. I fully expect they will need to change
// over time as we gain more experience with performance.
- internal const int YIELD_THRESHOLD = 10; // When to switch over to a true yield.
- internal const int SLEEP_0_EVERY_HOW_MANY_TIMES = 5; // After how many yields should we Sleep(0)?
- internal const int SLEEP_1_EVERY_HOW_MANY_TIMES = 20; // After how many yields should we Sleep(1)?
+ internal const int YieldThreshold = 10; // When to switch over to a true yield.
+ private const int Sleep0EveryHowManyYields = 5; // After how many yields should we Sleep(0)?
+ internal const int DefaultSleep1Threshold = 20; // After how many yields should we Sleep(1) frequently?
+
+ /// <summary>
+ /// A suggested number of spin iterations before doing a proper wait, such as waiting on an event that becomes signaled
+ /// when the resource becomes available.
+ /// </summary>
+ /// <remarks>
+ /// These numbers were arrived at by experimenting with different numbers in various cases that currently use it. It's
+ /// only a suggested value and typically works well when the proper wait is something like an event.
+ ///
+ /// Spinning less can lead to early waiting and more context switching, spinning more can decrease latency but may use
+ /// up some CPU time unnecessarily. Depends on the situation too, for instance SemaphoreSlim uses more iterations
+ /// because the waiting there is currently a lot more expensive (involves more spinning, taking a lock, etc.). It also
+ /// depends on the likelihood of the spin being successful and how long the wait would be but those are not accounted
+ /// for here.
+ /// </remarks>
+ internal static readonly int SpinCountforSpinBeforeWait = PlatformHelper.IsSingleProcessor ? 1 : 35;
+ internal const int Sleep1ThresholdForSpinBeforeWait = 40; // should be greater than SpinCountforSpinBeforeWait
// The number of times we've spun already.
private int _count;
@@ -81,7 +98,12 @@ namespace System.Threading
/// </summary>
public int Count
{
- get { return _count; }
+ get => _count;
+ internal set
+ {
+ Debug.Assert(value >= 0);
+ _count = value;
+ }
}
/// <summary>
@@ -94,10 +116,7 @@ namespace System.Threading
/// On a single-CPU machine, <see cref="SpinOnce"/> always yields the processor. On machines with
/// multiple CPUs, <see cref="SpinOnce"/> may yield after an unspecified number of calls.
/// </remarks>
- public bool NextSpinWillYield
- {
- get { return _count > YIELD_THRESHOLD || PlatformHelper.IsSingleProcessor; }
- }
+ public bool NextSpinWillYield => _count >= YieldThreshold || PlatformHelper.IsSingleProcessor;
/// <summary>
/// Performs a single spin.
@@ -108,7 +127,27 @@ namespace System.Threading
/// </remarks>
public void SpinOnce()
{
- if (NextSpinWillYield)
+ SpinOnce(DefaultSleep1Threshold);
+ }
+
+ internal void SpinOnce(int sleep1Threshold)
+ {
+ Debug.Assert(sleep1Threshold >= YieldThreshold || PlatformHelper.IsSingleProcessor); // so that NextSpinWillYield behaves as requested
+
+ // (_count - YieldThreshold) % 2 == 0: The purpose of this check is to interleave Thread.Yield/Sleep(0) with
+ // Thread.SpinWait. Otherwise, the following issues occur:
+ // - When there are no threads to switch to, Yield and Sleep(0) become no-op and it turns the spin loop into a
+ // busy-spin that may quickly reach the max spin count and cause the thread to enter a wait state, or may
+ // just busy-spin for longer than desired before a Sleep(1). Completing the spin loop too early can cause
+ // excessive context switcing if a wait follows, and entering the Sleep(1) stage too early can cause
+ // excessive delays.
+ // - If there are multiple threads doing Yield and Sleep(0) (typically from the same spin loop due to
+ // contention), they may switch between one another, delaying work that can make progress.
+ if ((
+ _count >= YieldThreshold &&
+ (_count >= sleep1Threshold || (_count - YieldThreshold) % 2 == 0)
+ ) ||
+ PlatformHelper.IsSingleProcessor)
{
//
// We must yield.
@@ -125,19 +164,21 @@ namespace System.Threading
// configured to use the (default) coarse-grained system timer.
//
- int yieldsSoFar = (_count >= YIELD_THRESHOLD ? _count - YIELD_THRESHOLD : _count);
-
- if ((yieldsSoFar % SLEEP_1_EVERY_HOW_MANY_TIMES) == (SLEEP_1_EVERY_HOW_MANY_TIMES - 1))
+ if (_count >= sleep1Threshold)
{
RuntimeThread.Sleep(1);
}
- else if ((yieldsSoFar % SLEEP_0_EVERY_HOW_MANY_TIMES) == (SLEEP_0_EVERY_HOW_MANY_TIMES - 1))
- {
- RuntimeThread.Sleep(0);
- }
else
{
- RuntimeThread.Yield();
+ int yieldsSoFar = _count >= YieldThreshold ? (_count - YieldThreshold) / 2 : _count;
+ if ((yieldsSoFar % Sleep0EveryHowManyYields) == (Sleep0EveryHowManyYields - 1))
+ {
+ RuntimeThread.Sleep(0);
+ }
+ else
+ {
+ RuntimeThread.Yield();
+ }
}
}
else
@@ -153,11 +194,24 @@ namespace System.Threading
// number of spins we are willing to tolerate to reduce delay to the caller,
// since we expect most callers will eventually block anyway.
//
- RuntimeThread.SpinWait(4 << _count);
+ // Also, cap the maximum spin count to a value such that many thousands of CPU cycles would not be wasted doing
+ // the equivalent of YieldProcessor(), as that that point SwitchToThread/Sleep(0) are more likely to be able to
+ // allow other useful work to run. Long YieldProcessor() loops can help to reduce contention, but Sleep(1) is
+ // usually better for that.
+ //
+ // RuntimeThread.OptimalMaxSpinWaitsPerSpinIteration:
+ // - See Thread::InitializeYieldProcessorNormalized(), which describes and calculates this value.
+ //
+ int n = RuntimeThread.OptimalMaxSpinWaitsPerSpinIteration;
+ if (_count <= 30 && (1 << _count) < n)
+ {
+ n = 1 << _count;
+ }
+ RuntimeThread.SpinWait(n);
}
// Finally, increment our spin counter.
- _count = (_count == int.MaxValue ? YIELD_THRESHOLD : _count + 1);
+ _count = (_count == int.MaxValue ? YieldThreshold : _count + 1);
}
/// <summary>
@@ -299,9 +353,7 @@ namespace System.Threading
/// <summary>
/// Gets whether the current machine has only a single processor.
/// </summary>
- internal static bool IsSingleProcessor
- {
- get { return ProcessorCount == 1; }
- }
+ /// <remarks>This typically does not change on a machine, so it's checked only once.</remarks>
+ internal static readonly bool IsSingleProcessor = ProcessorCount == 1;
}
}
diff --git a/src/mscorlib/shared/System/Threading/SynchronizationLockException.cs b/src/mscorlib/shared/System/Threading/SynchronizationLockException.cs
index c64fc9ced8..5ab186ec9a 100644
--- a/src/mscorlib/shared/System/Threading/SynchronizationLockException.cs
+++ b/src/mscorlib/shared/System/Threading/SynchronizationLockException.cs
@@ -21,19 +21,19 @@ namespace System.Threading
public SynchronizationLockException()
: base(SR.Arg_SynchronizationLockException)
{
- HResult = __HResults.COR_E_SYNCHRONIZATIONLOCK;
+ HResult = HResults.COR_E_SYNCHRONIZATIONLOCK;
}
public SynchronizationLockException(String message)
: base(message)
{
- HResult = __HResults.COR_E_SYNCHRONIZATIONLOCK;
+ HResult = HResults.COR_E_SYNCHRONIZATIONLOCK;
}
public SynchronizationLockException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_SYNCHRONIZATIONLOCK;
+ HResult = HResults.COR_E_SYNCHRONIZATIONLOCK;
}
protected SynchronizationLockException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/Threading/Tasks/ValueTask.cs b/src/mscorlib/shared/System/Threading/Tasks/ValueTask.cs
new file mode 100644
index 0000000000..384e4a8ab3
--- /dev/null
+++ b/src/mscorlib/shared/System/Threading/Tasks/ValueTask.cs
@@ -0,0 +1,169 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace System.Threading.Tasks
+{
+ /// <summary>
+ /// Provides a value type that wraps a <see cref="Task{TResult}"/> and a <typeparamref name="TResult"/>,
+ /// only one of which is used.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result.</typeparam>
+ /// <remarks>
+ /// <para>
+ /// Methods may return an instance of this value type when it's likely that the result of their
+ /// operations will be available synchronously and when the method is expected to be invoked so
+ /// frequently that the cost of allocating a new <see cref="Task{TResult}"/> for each call will
+ /// be prohibitive.
+ /// </para>
+ /// <para>
+ /// There are tradeoffs to using a <see cref="ValueTask{TResult}"/> instead of a <see cref="Task{TResult}"/>.
+ /// For example, while a <see cref="ValueTask{TResult}"/> can help avoid an allocation in the case where the
+ /// successful result is available synchronously, it also contains two fields whereas a <see cref="Task{TResult}"/>
+ /// as a reference type is a single field. This means that a method call ends up returning two fields worth of
+ /// data instead of one, which is more data to copy. It also means that if a method that returns one of these
+ /// is awaited within an async method, the state machine for that async method will be larger due to needing
+ /// to store the struct that's two fields instead of a single reference.
+ /// </para>
+ /// <para>
+ /// Further, for uses other than consuming the result of an asynchronous operation via await,
+ /// <see cref="ValueTask{TResult}"/> can lead to a more convoluted programming model, which can in turn actually
+ /// lead to more allocations. For example, consider a method that could return either a <see cref="Task{TResult}"/>
+ /// with a cached task as a common result or a <see cref="ValueTask{TResult}"/>. If the consumer of the result
+ /// wants to use it as a <see cref="Task{TResult}"/>, such as to use with in methods like Task.WhenAll and Task.WhenAny,
+ /// the <see cref="ValueTask{TResult}"/> would first need to be converted into a <see cref="Task{TResult}"/> using
+ /// <see cref="ValueTask{TResult}.AsTask"/>, which leads to an allocation that would have been avoided if a cached
+ /// <see cref="Task{TResult}"/> had been used in the first place.
+ /// </para>
+ /// <para>
+ /// As such, the default choice for any asynchronous method should be to return a <see cref="Task"/> or
+ /// <see cref="Task{TResult}"/>. Only if performance analysis proves it worthwhile should a <see cref="ValueTask{TResult}"/>
+ /// be used instead of <see cref="Task{TResult}"/>. There is no non-generic version of <see cref="ValueTask{TResult}"/>
+ /// as the Task.CompletedTask property may be used to hand back a successfully completed singleton in the case where
+ /// a <see cref="Task"/>-returning method completes synchronously and successfully.
+ /// </para>
+ /// </remarks>
+ [AsyncMethodBuilder(typeof(AsyncValueTaskMethodBuilder<>))]
+ [StructLayout(LayoutKind.Auto)]
+ public struct ValueTask<TResult> : IEquatable<ValueTask<TResult>>
+ {
+ /// <summary>The task to be used if the operation completed asynchronously or if it completed synchronously but non-successfully.</summary>
+ internal readonly Task<TResult> _task;
+ /// <summary>The result to be used if the operation completed successfully synchronously.</summary>
+ internal readonly TResult _result;
+
+ /// <summary>Initialize the <see cref="ValueTask{TResult}"/> with the result of the successful operation.</summary>
+ /// <param name="result">The result.</param>
+ public ValueTask(TResult result)
+ {
+ _task = null;
+ _result = result;
+ }
+
+ /// <summary>
+ /// Initialize the <see cref="ValueTask{TResult}"/> with a <see cref="Task{TResult}"/> that represents the operation.
+ /// </summary>
+ /// <param name="task">The task.</param>
+ public ValueTask(Task<TResult> task)
+ {
+ if (task == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.task);
+ }
+
+ _task = task;
+ _result = default(TResult);
+ }
+
+ /// <summary>Returns the hash code for this instance.</summary>
+ public override int GetHashCode() =>
+ _task != null ? _task.GetHashCode() :
+ _result != null ? _result.GetHashCode() :
+ 0;
+
+ /// <summary>Returns a value indicating whether this value is equal to a specified <see cref="object"/>.</summary>
+ public override bool Equals(object obj) =>
+ obj is ValueTask<TResult> &&
+ Equals((ValueTask<TResult>)obj);
+
+ /// <summary>Returns a value indicating whether this value is equal to a specified <see cref="ValueTask{TResult}"/> value.</summary>
+ public bool Equals(ValueTask<TResult> other) =>
+ _task != null || other._task != null ?
+ _task == other._task :
+ EqualityComparer<TResult>.Default.Equals(_result, other._result);
+
+ /// <summary>Returns a value indicating whether two <see cref="ValueTask{TResult}"/> values are equal.</summary>
+ public static bool operator==(ValueTask<TResult> left, ValueTask<TResult> right) =>
+ left.Equals(right);
+
+ /// <summary>Returns a value indicating whether two <see cref="ValueTask{TResult}"/> values are not equal.</summary>
+ public static bool operator!=(ValueTask<TResult> left, ValueTask<TResult> right) =>
+ !left.Equals(right);
+
+ /// <summary>
+ /// Gets a <see cref="Task{TResult}"/> object to represent this ValueTask. It will
+ /// either return the wrapped task object if one exists, or it'll manufacture a new
+ /// task object to represent the result.
+ /// </summary>
+ public Task<TResult> AsTask() =>
+ // Return the task if we were constructed from one, otherwise manufacture one. We don't
+ // cache the generated task into _task as it would end up changing both equality comparison
+ // and the hash code we generate in GetHashCode.
+ _task ?? AsyncTaskMethodBuilder<TResult>.GetTaskForResult(_result);
+
+ /// <summary>Gets whether the <see cref="ValueTask{TResult}"/> represents a completed operation.</summary>
+ public bool IsCompleted => _task == null || _task.IsCompleted;
+
+ /// <summary>Gets whether the <see cref="ValueTask{TResult}"/> represents a successfully completed operation.</summary>
+ public bool IsCompletedSuccessfully => _task == null || _task.IsCompletedSuccessfully;
+
+ /// <summary>Gets whether the <see cref="ValueTask{TResult}"/> represents a failed operation.</summary>
+ public bool IsFaulted => _task != null && _task.IsFaulted;
+
+ /// <summary>Gets whether the <see cref="ValueTask{TResult}"/> represents a canceled operation.</summary>
+ public bool IsCanceled => _task != null && _task.IsCanceled;
+
+ /// <summary>Gets the result.</summary>
+ public TResult Result => _task == null ? _result : _task.GetAwaiter().GetResult();
+
+ /// <summary>Gets an awaiter for this value.</summary>
+ public ValueTaskAwaiter<TResult> GetAwaiter() => new ValueTaskAwaiter<TResult>(this);
+
+ /// <summary>Configures an awaiter for this value.</summary>
+ /// <param name="continueOnCapturedContext">
+ /// true to attempt to marshal the continuation back to the captured context; otherwise, false.
+ /// </param>
+ public ConfiguredValueTaskAwaitable<TResult> ConfigureAwait(bool continueOnCapturedContext) =>
+ new ConfiguredValueTaskAwaitable<TResult>(this, continueOnCapturedContext);
+
+ /// <summary>Gets a string-representation of this <see cref="ValueTask{TResult}"/>.</summary>
+ public override string ToString()
+ {
+ if (_task != null)
+ {
+ return _task.IsCompletedSuccessfully && _task.Result != null ?
+ _task.Result.ToString() :
+ string.Empty;
+ }
+ else
+ {
+ return _result != null ?
+ _result.ToString() :
+ string.Empty;
+ }
+ }
+
+ // TODO https://github.com/dotnet/corefx/issues/22171:
+ // Remove CreateAsyncMethodBuilder once the C# compiler relies on the AsyncBuilder attribute.
+
+ /// <summary>Creates a method builder for use with an async method.</summary>
+ /// <returns>The created builder.</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)] // intended only for compiler consumption
+ public static AsyncValueTaskMethodBuilder<TResult> CreateAsyncMethodBuilder() => AsyncValueTaskMethodBuilder<TResult>.Create();
+ }
+}
diff --git a/src/mscorlib/shared/System/Threading/ThreadAbortException.cs b/src/mscorlib/shared/System/Threading/ThreadAbortException.cs
index ebbc29a702..01fdf1317b 100644
--- a/src/mscorlib/shared/System/Threading/ThreadAbortException.cs
+++ b/src/mscorlib/shared/System/Threading/ThreadAbortException.cs
@@ -22,7 +22,7 @@ namespace System.Threading
{
internal ThreadAbortException()
{
- HResult = __HResults.COR_E_THREADABORTED;
+ HResult = HResults.COR_E_THREADABORTED;
}
public object ExceptionState => null;
diff --git a/src/mscorlib/shared/System/Threading/ThreadStartException.cs b/src/mscorlib/shared/System/Threading/ThreadStartException.cs
index 7a87943ed1..35930d1d2d 100644
--- a/src/mscorlib/shared/System/Threading/ThreadStartException.cs
+++ b/src/mscorlib/shared/System/Threading/ThreadStartException.cs
@@ -11,13 +11,13 @@ namespace System.Threading
internal ThreadStartException()
: base(SR.Arg_ThreadStartException)
{
- HResult = __HResults.COR_E_THREADSTART;
+ HResult = HResults.COR_E_THREADSTART;
}
internal ThreadStartException(Exception reason)
: base(SR.Arg_ThreadStartException, reason)
{
- HResult = __HResults.COR_E_THREADSTART;
+ HResult = HResults.COR_E_THREADSTART;
}
}
}
diff --git a/src/mscorlib/shared/System/Threading/ThreadStateException.cs b/src/mscorlib/shared/System/Threading/ThreadStateException.cs
index 9477cb1ae4..d8f97a4f3b 100644
--- a/src/mscorlib/shared/System/Threading/ThreadStateException.cs
+++ b/src/mscorlib/shared/System/Threading/ThreadStateException.cs
@@ -21,19 +21,19 @@ namespace System.Threading
public ThreadStateException()
: base(SR.Arg_ThreadStateException)
{
- HResult = __HResults.COR_E_THREADSTATE;
+ HResult = HResults.COR_E_THREADSTATE;
}
public ThreadStateException(String message)
: base(message)
{
- HResult = __HResults.COR_E_THREADSTATE;
+ HResult = HResults.COR_E_THREADSTATE;
}
public ThreadStateException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_THREADSTATE;
+ HResult = HResults.COR_E_THREADSTATE;
}
protected ThreadStateException(SerializationInfo info, StreamingContext context)
diff --git a/src/mscorlib/shared/System/Threading/TimeoutHelper.cs b/src/mscorlib/shared/System/Threading/TimeoutHelper.cs
index c66c9add92..c96a4d00d6 100644
--- a/src/mscorlib/shared/System/Threading/TimeoutHelper.cs
+++ b/src/mscorlib/shared/System/Threading/TimeoutHelper.cs
@@ -13,7 +13,7 @@ namespace System.Threading
internal static class TimeoutHelper
{
/// <summary>
- /// Returns the Environment.TickCount as a start time in milliseconds as a uint, TickCount tools over from postive to negative every ~ 25 days
+ /// Returns the Environment.TickCount as a start time in milliseconds as a uint, TickCount tools over from positive to negative every ~ 25 days
/// then ~25 days to back to positive again, uint is sued to ignore the sign and double the range to 50 days
/// </summary>
/// <returns></returns>
@@ -26,7 +26,7 @@ namespace System.Threading
/// Helper function to measure and update the elapsed time
/// </summary>
/// <param name="startTime"> The first time (in milliseconds) observed when the wait started</param>
- /// <param name="originalWaitMillisecondsTimeout">The orginal wait timeoutout in milliseconds</param>
+ /// <param name="originalWaitMillisecondsTimeout">The original wait timeout in milliseconds</param>
/// <returns>The new wait time in milliseconds, -1 if the time expired</returns>
public static int UpdateTimeOut(uint startTime, int originalWaitMillisecondsTimeout)
{
diff --git a/src/mscorlib/shared/System/Threading/WaitHandleCannotBeOpenedException.cs b/src/mscorlib/shared/System/Threading/WaitHandleCannotBeOpenedException.cs
index 770e70d7ab..47e127191d 100644
--- a/src/mscorlib/shared/System/Threading/WaitHandleCannotBeOpenedException.cs
+++ b/src/mscorlib/shared/System/Threading/WaitHandleCannotBeOpenedException.cs
@@ -10,17 +10,17 @@ namespace System.Threading
{
public WaitHandleCannotBeOpenedException() : base(SR.Threading_WaitHandleCannotBeOpenedException)
{
- HResult = __HResults.COR_E_WAITHANDLECANNOTBEOPENED;
+ HResult = HResults.COR_E_WAITHANDLECANNOTBEOPENED;
}
public WaitHandleCannotBeOpenedException(String message) : base(message)
{
- HResult = __HResults.COR_E_WAITHANDLECANNOTBEOPENED;
+ HResult = HResults.COR_E_WAITHANDLECANNOTBEOPENED;
}
public WaitHandleCannotBeOpenedException(String message, Exception innerException) : base(message, innerException)
{
- HResult = __HResults.COR_E_WAITHANDLECANNOTBEOPENED;
+ HResult = HResults.COR_E_WAITHANDLECANNOTBEOPENED;
}
protected WaitHandleCannotBeOpenedException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/TimeSpan.cs b/src/mscorlib/shared/System/TimeSpan.cs
index 39be059362..263a0a5824 100644
--- a/src/mscorlib/shared/System/TimeSpan.cs
+++ b/src/mscorlib/shared/System/TimeSpan.cs
@@ -316,55 +316,119 @@ namespace System
}
public static TimeSpan Parse(String s)
{
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
/* Constructs a TimeSpan from a string. Leading and trailing white space characters are allowed. */
- return TimeSpanParse.Parse(s, null);
+ return TimeSpanParse.Parse(s.AsReadOnlySpan(), null);
}
public static TimeSpan Parse(String input, IFormatProvider formatProvider)
{
+ if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
+ return TimeSpanParse.Parse(input.AsReadOnlySpan(), formatProvider);
+ }
+ public static TimeSpan Parse(ReadOnlySpan<char> input, IFormatProvider formatProvider = null)
+ {
return TimeSpanParse.Parse(input, formatProvider);
}
public static TimeSpan ParseExact(String input, String format, IFormatProvider formatProvider)
{
- return TimeSpanParse.ParseExact(input, format, formatProvider, TimeSpanStyles.None);
+ if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
+ return TimeSpanParse.ParseExact(input.AsReadOnlySpan(), format, formatProvider, TimeSpanStyles.None);
}
public static TimeSpan ParseExact(String input, String[] formats, IFormatProvider formatProvider)
{
- return TimeSpanParse.ParseExactMultiple(input, formats, formatProvider, TimeSpanStyles.None);
+ if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
+ return TimeSpanParse.ParseExactMultiple(input.AsReadOnlySpan(), formats, formatProvider, TimeSpanStyles.None);
}
public static TimeSpan ParseExact(String input, String format, IFormatProvider formatProvider, TimeSpanStyles styles)
{
ValidateStyles(styles, nameof(styles));
+ if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
+ return TimeSpanParse.ParseExact(input.AsReadOnlySpan(), format, formatProvider, styles);
+ }
+ public static TimeSpan ParseExact(ReadOnlySpan<char> input, string format, IFormatProvider formatProvider, TimeSpanStyles styles = TimeSpanStyles.None)
+ {
+ ValidateStyles(styles, nameof(styles));
return TimeSpanParse.ParseExact(input, format, formatProvider, styles);
}
public static TimeSpan ParseExact(String input, String[] formats, IFormatProvider formatProvider, TimeSpanStyles styles)
{
ValidateStyles(styles, nameof(styles));
+ if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
+ return TimeSpanParse.ParseExactMultiple(input.AsReadOnlySpan(), formats, formatProvider, styles);
+ }
+ public static TimeSpan ParseExact(ReadOnlySpan<char> input, string[] formats, IFormatProvider formatProvider, TimeSpanStyles styles = TimeSpanStyles.None)
+ {
+ ValidateStyles(styles, nameof(styles));
return TimeSpanParse.ParseExactMultiple(input, formats, formatProvider, styles);
}
public static Boolean TryParse(String s, out TimeSpan result)
{
- return TimeSpanParse.TryParse(s, null, out result);
+ if (s == null)
+ {
+ result = default(TimeSpan);
+ return false;
+ }
+ return TimeSpanParse.TryParse(s.AsReadOnlySpan(), null, out result);
}
public static Boolean TryParse(String input, IFormatProvider formatProvider, out TimeSpan result)
{
+ if (input == null)
+ {
+ result = default(TimeSpan);
+ return false;
+ }
+ return TimeSpanParse.TryParse(input.AsReadOnlySpan(), formatProvider, out result);
+ }
+ public static bool TryParse(ReadOnlySpan<char> input, out TimeSpan result, IFormatProvider formatProvider = null)
+ {
return TimeSpanParse.TryParse(input, formatProvider, out result);
}
public static Boolean TryParseExact(String input, String format, IFormatProvider formatProvider, out TimeSpan result)
{
- return TimeSpanParse.TryParseExact(input, format, formatProvider, TimeSpanStyles.None, out result);
+ if (input == null)
+ {
+ result = default(TimeSpan);
+ return false;
+ }
+ return TimeSpanParse.TryParseExact(input.AsReadOnlySpan(), format, formatProvider, TimeSpanStyles.None, out result);
}
public static Boolean TryParseExact(String input, String[] formats, IFormatProvider formatProvider, out TimeSpan result)
{
- return TimeSpanParse.TryParseExactMultiple(input, formats, formatProvider, TimeSpanStyles.None, out result);
+ if (input == null)
+ {
+ result = default(TimeSpan);
+ return false;
+ }
+ return TimeSpanParse.TryParseExactMultiple(input.AsReadOnlySpan(), formats, formatProvider, TimeSpanStyles.None, out result);
}
public static Boolean TryParseExact(String input, String format, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result)
{
ValidateStyles(styles, nameof(styles));
+ if (input == null)
+ {
+ result = default(TimeSpan);
+ return false;
+ }
+ return TimeSpanParse.TryParseExact(input.AsReadOnlySpan(), format, formatProvider, styles, out result);
+ }
+ public static bool TryParseExact(ReadOnlySpan<char> input, string format, IFormatProvider formatProvider, out TimeSpan result, TimeSpanStyles styles = TimeSpanStyles.None)
+ {
+ ValidateStyles(styles, nameof(styles));
return TimeSpanParse.TryParseExact(input, format, formatProvider, styles, out result);
}
public static Boolean TryParseExact(String input, String[] formats, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result)
{
ValidateStyles(styles, nameof(styles));
+ if (input == null)
+ {
+ result = default(TimeSpan);
+ return false;
+ }
+ return TimeSpanParse.TryParseExactMultiple(input.AsReadOnlySpan(), formats, formatProvider, styles, out result);
+ }
+ public static bool TryParseExact(ReadOnlySpan<char> input, string[] formats, IFormatProvider formatProvider, out TimeSpan result, TimeSpanStyles styles = TimeSpanStyles.None)
+ {
+ ValidateStyles(styles, nameof(styles));
return TimeSpanParse.TryParseExactMultiple(input, formats, formatProvider, styles, out result);
}
public override String ToString()
@@ -379,6 +443,10 @@ namespace System
{
return TimeSpanFormat.Format(this, format, formatProvider);
}
+ public bool TryFormat(Span<char> destination, out int charsWritten, string format = null, IFormatProvider formatProvider = null)
+ {
+ return TimeSpanFormat.TryFormat(this, destination, out charsWritten, format, formatProvider);
+ }
#endregion
public static TimeSpan operator -(TimeSpan t)
diff --git a/src/mscorlib/shared/System/TimeoutException.cs b/src/mscorlib/shared/System/TimeoutException.cs
index 4ba95bc47b..b50ae2f902 100644
--- a/src/mscorlib/shared/System/TimeoutException.cs
+++ b/src/mscorlib/shared/System/TimeoutException.cs
@@ -20,19 +20,19 @@ namespace System
public TimeoutException()
: base(SR.Arg_TimeoutException)
{
- HResult = __HResults.COR_E_TIMEOUT;
+ HResult = HResults.COR_E_TIMEOUT;
}
public TimeoutException(String message)
: base(message)
{
- HResult = __HResults.COR_E_TIMEOUT;
+ HResult = HResults.COR_E_TIMEOUT;
}
public TimeoutException(String message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_TIMEOUT;
+ HResult = HResults.COR_E_TIMEOUT;
}
protected TimeoutException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/Type.cs b/src/mscorlib/shared/System/Type.cs
index 2ba58918a0..ab3d55bc66 100644
--- a/src/mscorlib/shared/System/Type.cs
+++ b/src/mscorlib/shared/System/Type.cs
@@ -47,6 +47,8 @@ namespace System
public virtual bool IsSZArray { get { throw NotImplemented.ByDesign; } }
public virtual bool IsVariableBoundArray => IsArray && !IsSZArray;
+ public virtual bool IsByRefLike => throw new NotSupportedException(SR.NotSupported_SubclassOverride);
+
public bool HasElementType => HasElementTypeImpl();
protected abstract bool HasElementTypeImpl();
public abstract Type GetElementType();
@@ -106,6 +108,8 @@ namespace System
public bool IsValueType => IsValueTypeImpl();
protected virtual bool IsValueTypeImpl() => IsSubclassOf(typeof(ValueType));
+ public virtual bool IsSignatureType => false;
+
public virtual bool IsSecurityCritical { get { throw NotImplemented.ByDesign; } }
public virtual bool IsSecuritySafeCritical { get { throw NotImplemented.ByDesign; } }
public virtual bool IsSecurityTransparent { get { throw NotImplemented.ByDesign; } }
@@ -177,6 +181,27 @@ namespace System
protected abstract MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers);
+ public MethodInfo GetMethod(string name, int genericParameterCount, Type[] types) => GetMethod(name, genericParameterCount, types, null);
+ public MethodInfo GetMethod(string name, int genericParameterCount, Type[] types, ParameterModifier[] modifiers) => GetMethod(name, genericParameterCount, Type.DefaultLookup, null, types, modifiers);
+ public MethodInfo GetMethod(string name, int genericParameterCount, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers) => GetMethod(name, genericParameterCount, bindingAttr, binder, CallingConventions.Any, types, modifiers);
+ public MethodInfo GetMethod(string name, int genericParameterCount, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
+ {
+ if (name == null)
+ throw new ArgumentNullException(nameof(name));
+ if (genericParameterCount < 0)
+ throw new ArgumentException(SR.ArgumentOutOfRange_NeedNonNegNum, nameof(genericParameterCount));
+ if (types == null)
+ throw new ArgumentNullException(nameof(types));
+ for (int i = 0; i < types.Length; i++)
+ {
+ if (types[i] == null)
+ throw new ArgumentNullException(nameof(types));
+ }
+ return GetMethodImpl(name, genericParameterCount, bindingAttr, binder, callConvention, types, modifiers);
+ }
+
+ protected virtual MethodInfo GetMethodImpl(string name, int genericParameterCount, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) => throw new NotSupportedException();
+
public MethodInfo[] GetMethods() => GetMethods(Type.DefaultLookup);
public abstract MethodInfo[] GetMethods(BindingFlags bindingAttr);
@@ -317,6 +342,13 @@ namespace System
public virtual Type MakeGenericType(params Type[] typeArguments) { throw new NotSupportedException(SR.NotSupported_SubclassOverride); }
public virtual Type MakePointerType() { throw new NotSupportedException(); }
+ public static Type MakeGenericMethodParameter(int position)
+ {
+ if (position < 0)
+ throw new ArgumentException(SR.ArgumentOutOfRange_MustBeNonNegNum, nameof(position));
+ return new SignatureGenericMethodParameterType(position);
+ }
+
public override string ToString() => "Type: " + Name; // Why do we add the "Type: " prefix?
public override bool Equals(object o) => o == null ? false : Equals(o as Type);
diff --git a/src/mscorlib/shared/System/TypeAccessException.cs b/src/mscorlib/shared/System/TypeAccessException.cs
index 302dcb1ac1..ff081582b6 100644
--- a/src/mscorlib/shared/System/TypeAccessException.cs
+++ b/src/mscorlib/shared/System/TypeAccessException.cs
@@ -13,19 +13,19 @@ namespace System
public TypeAccessException()
: base(SR.Arg_TypeAccessException)
{
- HResult = __HResults.COR_E_TYPEACCESS;
+ HResult = HResults.COR_E_TYPEACCESS;
}
public TypeAccessException(string message)
: base(message)
{
- HResult = __HResults.COR_E_TYPEACCESS;
+ HResult = HResults.COR_E_TYPEACCESS;
}
public TypeAccessException(string message, Exception inner)
: base(message, inner)
{
- HResult = __HResults.COR_E_TYPEACCESS;
+ HResult = HResults.COR_E_TYPEACCESS;
}
protected TypeAccessException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/TypeInitializationException.cs b/src/mscorlib/shared/System/TypeInitializationException.cs
index 8d0b8a9f79..03a1bad3a7 100644
--- a/src/mscorlib/shared/System/TypeInitializationException.cs
+++ b/src/mscorlib/shared/System/TypeInitializationException.cs
@@ -28,7 +28,7 @@ namespace System
private TypeInitializationException()
: base(SR.TypeInitialization_Default)
{
- HResult = __HResults.COR_E_TYPEINITIALIZATION;
+ HResult = HResults.COR_E_TYPEINITIALIZATION;
}
@@ -41,14 +41,14 @@ namespace System
// for Interop only, though it's not particularly useful.
internal TypeInitializationException(String message) : base(message)
{
- HResult = __HResults.COR_E_TYPEINITIALIZATION;
+ HResult = HResults.COR_E_TYPEINITIALIZATION;
}
internal TypeInitializationException(String fullTypeName, String message, Exception innerException)
: base(message, innerException)
{
_typeName = fullTypeName;
- HResult = __HResults.COR_E_TYPEINITIALIZATION;
+ HResult = HResults.COR_E_TYPEINITIALIZATION;
}
public override void GetObjectData(SerializationInfo info, StreamingContext context)
diff --git a/src/mscorlib/shared/System/TypeUnloadedException.cs b/src/mscorlib/shared/System/TypeUnloadedException.cs
index c7ed71c9cb..97039bb8f1 100644
--- a/src/mscorlib/shared/System/TypeUnloadedException.cs
+++ b/src/mscorlib/shared/System/TypeUnloadedException.cs
@@ -11,19 +11,19 @@ namespace System
public TypeUnloadedException()
: base(SR.Arg_TypeUnloadedException)
{
- HResult = __HResults.COR_E_TYPEUNLOADED;
+ HResult = HResults.COR_E_TYPEUNLOADED;
}
public TypeUnloadedException(string message)
: base(message)
{
- HResult = __HResults.COR_E_TYPEUNLOADED;
+ HResult = HResults.COR_E_TYPEUNLOADED;
}
public TypeUnloadedException(string message, Exception innerException)
: base(message, innerException)
{
- HResult = __HResults.COR_E_TYPEUNLOADED;
+ HResult = HResults.COR_E_TYPEUNLOADED;
}
protected TypeUnloadedException(SerializationInfo info, StreamingContext context)
diff --git a/src/mscorlib/shared/System/UInt16.cs b/src/mscorlib/shared/System/UInt16.cs
new file mode 100644
index 0000000000..4cd290bc45
--- /dev/null
+++ b/src/mscorlib/shared/System/UInt16.cs
@@ -0,0 +1,292 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+** Purpose: This class will encapsulate a short and provide an
+** Object representation of it.
+**
+**
+===========================================================*/
+
+using System.Diagnostics.Contracts;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+
+namespace System
+{
+ [Serializable]
+ [CLSCompliant(false)]
+ [StructLayout(LayoutKind.Sequential)]
+ [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ public struct UInt16 : IComparable, IConvertible, IFormattable, IComparable<UInt16>, IEquatable<UInt16>
+ {
+ private ushort m_value; // Do not rename (binary serialization)
+
+ public const ushort MaxValue = (ushort)0xFFFF;
+ public const ushort MinValue = 0;
+
+
+ // Compares this object to another object, returning an integer that
+ // indicates the relationship.
+ // Returns a value less than zero if this object
+ // null is considered to be less than any instance.
+ // If object is not of type UInt16, this method throws an ArgumentException.
+ //
+ public int CompareTo(Object value)
+ {
+ if (value == null)
+ {
+ return 1;
+ }
+ if (value is UInt16)
+ {
+ return ((int)m_value - (int)(((UInt16)value).m_value));
+ }
+ throw new ArgumentException(SR.Arg_MustBeUInt16);
+ }
+
+ public int CompareTo(UInt16 value)
+ {
+ return ((int)m_value - (int)value);
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (!(obj is UInt16))
+ {
+ return false;
+ }
+ return m_value == ((UInt16)obj).m_value;
+ }
+
+ [NonVersionable]
+ public bool Equals(UInt16 obj)
+ {
+ return m_value == obj;
+ }
+
+ // Returns a HashCode for the UInt16
+ public override int GetHashCode()
+ {
+ return (int)m_value;
+ }
+
+ // Converts the current value to a String in base-10 with no extra padding.
+ public override String ToString()
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatUInt32(m_value, null, NumberFormatInfo.CurrentInfo);
+ }
+
+ public String ToString(IFormatProvider provider)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatUInt32(m_value, null, NumberFormatInfo.GetInstance(provider));
+ }
+
+
+ public String ToString(String format)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatUInt32(m_value, format, NumberFormatInfo.CurrentInfo);
+ }
+
+ public String ToString(String format, IFormatProvider provider)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatUInt32(m_value, format, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [CLSCompliant(false)]
+ public static ushort Parse(String s)
+ {
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Parse(s.AsReadOnlySpan(), NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
+ }
+
+ [CLSCompliant(false)]
+ public static ushort Parse(String s, NumberStyles style)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Parse(s.AsReadOnlySpan(), style, NumberFormatInfo.CurrentInfo);
+ }
+
+
+ [CLSCompliant(false)]
+ public static ushort Parse(String s, IFormatProvider provider)
+ {
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Parse(s.AsReadOnlySpan(), NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [CLSCompliant(false)]
+ public static ushort Parse(String s, NumberStyles style, IFormatProvider provider)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Parse(s.AsReadOnlySpan(), style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [CLSCompliant(false)]
+ public static ushort Parse(ReadOnlySpan<char> s, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Parse(s, style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ private static ushort Parse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info)
+ {
+ uint i = 0;
+ try
+ {
+ i = Number.ParseUInt32(s, style, info);
+ }
+ catch (OverflowException e)
+ {
+ throw new OverflowException(SR.Overflow_UInt16, e);
+ }
+
+ if (i > MaxValue) throw new OverflowException(SR.Overflow_UInt16);
+ return (ushort)i;
+ }
+
+ [CLSCompliant(false)]
+ public static bool TryParse(String s, out UInt16 result)
+ {
+ if (s == null)
+ {
+ result = 0;
+ return false;
+ }
+
+ return TryParse(s.AsReadOnlySpan(), NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
+ }
+
+ [CLSCompliant(false)]
+ public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out UInt16 result)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+
+ if (s == null)
+ {
+ result = 0;
+ return false;
+ }
+
+ return TryParse(s.AsReadOnlySpan(), style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ [CLSCompliant(false)]
+ public static bool TryParse(ReadOnlySpan<char> s, out ushort result, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ private static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out UInt16 result)
+ {
+ result = 0;
+ UInt32 i;
+ if (!Number.TryParseUInt32(s, style, info, out i))
+ {
+ return false;
+ }
+ if (i > MaxValue)
+ {
+ return false;
+ }
+ result = (UInt16)i;
+ return true;
+ }
+
+ //
+ // IConvertible implementation
+ //
+
+ public TypeCode GetTypeCode()
+ {
+ return TypeCode.UInt16;
+ }
+
+ bool IConvertible.ToBoolean(IFormatProvider provider)
+ {
+ return Convert.ToBoolean(m_value);
+ }
+
+ char IConvertible.ToChar(IFormatProvider provider)
+ {
+ return Convert.ToChar(m_value);
+ }
+
+ sbyte IConvertible.ToSByte(IFormatProvider provider)
+ {
+ return Convert.ToSByte(m_value);
+ }
+
+ byte IConvertible.ToByte(IFormatProvider provider)
+ {
+ return Convert.ToByte(m_value);
+ }
+
+ short IConvertible.ToInt16(IFormatProvider provider)
+ {
+ return Convert.ToInt16(m_value);
+ }
+
+ ushort IConvertible.ToUInt16(IFormatProvider provider)
+ {
+ return m_value;
+ }
+
+ int IConvertible.ToInt32(IFormatProvider provider)
+ {
+ return Convert.ToInt32(m_value);
+ }
+
+ uint IConvertible.ToUInt32(IFormatProvider provider)
+ {
+ return Convert.ToUInt32(m_value);
+ }
+
+ long IConvertible.ToInt64(IFormatProvider provider)
+ {
+ return Convert.ToInt64(m_value);
+ }
+
+ ulong IConvertible.ToUInt64(IFormatProvider provider)
+ {
+ return Convert.ToUInt64(m_value);
+ }
+
+ float IConvertible.ToSingle(IFormatProvider provider)
+ {
+ return Convert.ToSingle(m_value);
+ }
+
+ double IConvertible.ToDouble(IFormatProvider provider)
+ {
+ return Convert.ToDouble(m_value);
+ }
+
+ Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ {
+ return Convert.ToDecimal(m_value);
+ }
+
+ DateTime IConvertible.ToDateTime(IFormatProvider provider)
+ {
+ throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "UInt16", "DateTime"));
+ }
+
+ Object IConvertible.ToType(Type type, IFormatProvider provider)
+ {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/UInt32.cs b/src/mscorlib/shared/System/UInt32.cs
new file mode 100644
index 0000000000..49835613b2
--- /dev/null
+++ b/src/mscorlib/shared/System/UInt32.cs
@@ -0,0 +1,269 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: This class will encapsulate an uint and
+** provide an Object representation of it.
+**
+**
+===========================================================*/
+
+using System.Diagnostics.Contracts;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+
+namespace System
+{
+ [Serializable]
+ [CLSCompliant(false)]
+ [StructLayout(LayoutKind.Sequential)]
+ [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ public struct UInt32 : IComparable, IConvertible, IFormattable, IComparable<UInt32>, IEquatable<UInt32>
+ {
+ private uint m_value; // Do not rename (binary serialization)
+
+ public const uint MaxValue = (uint)0xffffffff;
+ public const uint MinValue = 0U;
+
+
+ // Compares this object to another object, returning an integer that
+ // indicates the relationship.
+ // Returns a value less than zero if this object
+ // null is considered to be less than any instance.
+ // If object is not of type UInt32, this method throws an ArgumentException.
+ //
+ public int CompareTo(Object value)
+ {
+ if (value == null)
+ {
+ return 1;
+ }
+ if (value is UInt32)
+ {
+ // Need to use compare because subtraction will wrap
+ // to positive for very large neg numbers, etc.
+ uint i = (uint)value;
+ if (m_value < i) return -1;
+ if (m_value > i) return 1;
+ return 0;
+ }
+ throw new ArgumentException(SR.Arg_MustBeUInt32);
+ }
+
+ public int CompareTo(UInt32 value)
+ {
+ // Need to use compare because subtraction will wrap
+ // to positive for very large neg numbers, etc.
+ if (m_value < value) return -1;
+ if (m_value > value) return 1;
+ return 0;
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (!(obj is UInt32))
+ {
+ return false;
+ }
+ return m_value == ((UInt32)obj).m_value;
+ }
+
+ [NonVersionable]
+ public bool Equals(UInt32 obj)
+ {
+ return m_value == obj;
+ }
+
+ // The absolute value of the int contained.
+ public override int GetHashCode()
+ {
+ return ((int)m_value);
+ }
+
+ // The base 10 representation of the number with no extra padding.
+ public override String ToString()
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatUInt32(m_value, null, NumberFormatInfo.CurrentInfo);
+ }
+
+ public String ToString(IFormatProvider provider)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatUInt32(m_value, null, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public String ToString(String format)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatUInt32(m_value, format, NumberFormatInfo.CurrentInfo);
+ }
+
+ public String ToString(String format, IFormatProvider provider)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatUInt32(m_value, format, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [CLSCompliant(false)]
+ public static uint Parse(String s)
+ {
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseUInt32(s.AsReadOnlySpan(), NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
+ }
+
+ [CLSCompliant(false)]
+ public static uint Parse(String s, NumberStyles style)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseUInt32(s.AsReadOnlySpan(), style, NumberFormatInfo.CurrentInfo);
+ }
+
+
+ [CLSCompliant(false)]
+ public static uint Parse(String s, IFormatProvider provider)
+ {
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseUInt32(s.AsReadOnlySpan(), NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [CLSCompliant(false)]
+ public static uint Parse(String s, NumberStyles style, IFormatProvider provider)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseUInt32(s.AsReadOnlySpan(), style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [CLSCompliant(false)]
+ public static uint Parse(ReadOnlySpan<char> s, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Number.ParseUInt32(s, style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [CLSCompliant(false)]
+ public static bool TryParse(String s, out UInt32 result)
+ {
+ if (s == null)
+ {
+ result = 0;
+ return false;
+ }
+
+ return Number.TryParseUInt32(s.AsReadOnlySpan(), NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
+ }
+
+ [CLSCompliant(false)]
+ public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out UInt32 result)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+
+ if (s == null)
+ {
+ result = 0;
+ return false;
+ }
+
+ return Number.TryParseUInt32(s.AsReadOnlySpan(), style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ [CLSCompliant(false)]
+ public static bool TryParse(ReadOnlySpan<char> s, out UInt32 result, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Number.TryParseUInt32(s, style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ //
+ // IConvertible implementation
+ //
+
+ public TypeCode GetTypeCode()
+ {
+ return TypeCode.UInt32;
+ }
+
+ bool IConvertible.ToBoolean(IFormatProvider provider)
+ {
+ return Convert.ToBoolean(m_value);
+ }
+
+ char IConvertible.ToChar(IFormatProvider provider)
+ {
+ return Convert.ToChar(m_value);
+ }
+
+ sbyte IConvertible.ToSByte(IFormatProvider provider)
+ {
+ return Convert.ToSByte(m_value);
+ }
+
+ byte IConvertible.ToByte(IFormatProvider provider)
+ {
+ return Convert.ToByte(m_value);
+ }
+
+ short IConvertible.ToInt16(IFormatProvider provider)
+ {
+ return Convert.ToInt16(m_value);
+ }
+
+ ushort IConvertible.ToUInt16(IFormatProvider provider)
+ {
+ return Convert.ToUInt16(m_value);
+ }
+
+ int IConvertible.ToInt32(IFormatProvider provider)
+ {
+ return Convert.ToInt32(m_value);
+ }
+
+ uint IConvertible.ToUInt32(IFormatProvider provider)
+ {
+ return m_value;
+ }
+
+ long IConvertible.ToInt64(IFormatProvider provider)
+ {
+ return Convert.ToInt64(m_value);
+ }
+
+ ulong IConvertible.ToUInt64(IFormatProvider provider)
+ {
+ return Convert.ToUInt64(m_value);
+ }
+
+ float IConvertible.ToSingle(IFormatProvider provider)
+ {
+ return Convert.ToSingle(m_value);
+ }
+
+ double IConvertible.ToDouble(IFormatProvider provider)
+ {
+ return Convert.ToDouble(m_value);
+ }
+
+ Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ {
+ return Convert.ToDecimal(m_value);
+ }
+
+ DateTime IConvertible.ToDateTime(IFormatProvider provider)
+ {
+ throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "UInt32", "DateTime"));
+ }
+
+ Object IConvertible.ToType(Type type, IFormatProvider provider)
+ {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/UInt64.cs b/src/mscorlib/shared/System/UInt64.cs
new file mode 100644
index 0000000000..424d48b8b1
--- /dev/null
+++ b/src/mscorlib/shared/System/UInt64.cs
@@ -0,0 +1,265 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+** Purpose: This class will encapsulate an unsigned long and
+** provide an Object representation of it.
+**
+**
+===========================================================*/
+
+using System.Diagnostics.Contracts;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+
+namespace System
+{
+ [Serializable]
+ [CLSCompliant(false)]
+ [StructLayout(LayoutKind.Sequential)]
+ [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ public struct UInt64 : IComparable, IConvertible, IFormattable, IComparable<UInt64>, IEquatable<UInt64>
+ {
+ private ulong m_value; // Do not rename (binary serialization)
+
+ public const ulong MaxValue = (ulong)0xffffffffffffffffL;
+ public const ulong MinValue = 0x0;
+
+ // Compares this object to another object, returning an integer that
+ // indicates the relationship.
+ // Returns a value less than zero if this object
+ // null is considered to be less than any instance.
+ // If object is not of type UInt64, this method throws an ArgumentException.
+ //
+ public int CompareTo(Object value)
+ {
+ if (value == null)
+ {
+ return 1;
+ }
+ if (value is UInt64)
+ {
+ // Need to use compare because subtraction will wrap
+ // to positive for very large neg numbers, etc.
+ ulong i = (ulong)value;
+ if (m_value < i) return -1;
+ if (m_value > i) return 1;
+ return 0;
+ }
+ throw new ArgumentException(SR.Arg_MustBeUInt64);
+ }
+
+ public int CompareTo(UInt64 value)
+ {
+ // Need to use compare because subtraction will wrap
+ // to positive for very large neg numbers, etc.
+ if (m_value < value) return -1;
+ if (m_value > value) return 1;
+ return 0;
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (!(obj is UInt64))
+ {
+ return false;
+ }
+ return m_value == ((UInt64)obj).m_value;
+ }
+
+ [NonVersionable]
+ public bool Equals(UInt64 obj)
+ {
+ return m_value == obj;
+ }
+
+ // The value of the lower 32 bits XORed with the uppper 32 bits.
+ public override int GetHashCode()
+ {
+ return ((int)m_value) ^ (int)(m_value >> 32);
+ }
+
+ public override String ToString()
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatUInt64(m_value, null, NumberFormatInfo.CurrentInfo);
+ }
+
+ public String ToString(IFormatProvider provider)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatUInt64(m_value, null, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public String ToString(String format)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatUInt64(m_value, format, NumberFormatInfo.CurrentInfo);
+ }
+
+ public String ToString(String format, IFormatProvider provider)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatUInt64(m_value, format, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [CLSCompliant(false)]
+ public static ulong Parse(String s)
+ {
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseUInt64(s.AsReadOnlySpan(), NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
+ }
+
+ [CLSCompliant(false)]
+ public static ulong Parse(String s, NumberStyles style)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseUInt64(s.AsReadOnlySpan(), style, NumberFormatInfo.CurrentInfo);
+ }
+
+ [CLSCompliant(false)]
+ public static ulong Parse(string s, IFormatProvider provider)
+ {
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseUInt64(s.AsReadOnlySpan(), NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [CLSCompliant(false)]
+ public static ulong Parse(String s, NumberStyles style, IFormatProvider provider)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseUInt64(s.AsReadOnlySpan(), style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [CLSCompliant(false)]
+ public static ulong Parse(ReadOnlySpan<char> s, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Number.ParseUInt64(s, style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [CLSCompliant(false)]
+ public static Boolean TryParse(String s, out UInt64 result)
+ {
+ if (s == null)
+ {
+ result = 0;
+ return false;
+ }
+
+ return Number.TryParseUInt64(s.AsReadOnlySpan(), NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
+ }
+
+ [CLSCompliant(false)]
+ public static Boolean TryParse(String s, NumberStyles style, IFormatProvider provider, out UInt64 result)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+
+ if (s == null)
+ {
+ result = 0;
+ return false;
+ }
+
+ return Number.TryParseUInt64(s.AsReadOnlySpan(), style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ [CLSCompliant(false)]
+ public static Boolean TryParse(ReadOnlySpan<char> s, out UInt64 result, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null)
+ {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Number.TryParseUInt64(s, style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ //
+ // IConvertible implementation
+ //
+
+ public TypeCode GetTypeCode()
+ {
+ return TypeCode.UInt64;
+ }
+
+ bool IConvertible.ToBoolean(IFormatProvider provider)
+ {
+ return Convert.ToBoolean(m_value);
+ }
+
+ char IConvertible.ToChar(IFormatProvider provider)
+ {
+ return Convert.ToChar(m_value);
+ }
+
+ sbyte IConvertible.ToSByte(IFormatProvider provider)
+ {
+ return Convert.ToSByte(m_value);
+ }
+
+ byte IConvertible.ToByte(IFormatProvider provider)
+ {
+ return Convert.ToByte(m_value);
+ }
+
+ short IConvertible.ToInt16(IFormatProvider provider)
+ {
+ return Convert.ToInt16(m_value);
+ }
+
+ ushort IConvertible.ToUInt16(IFormatProvider provider)
+ {
+ return Convert.ToUInt16(m_value);
+ }
+
+ int IConvertible.ToInt32(IFormatProvider provider)
+ {
+ return Convert.ToInt32(m_value);
+ }
+
+ uint IConvertible.ToUInt32(IFormatProvider provider)
+ {
+ return Convert.ToUInt32(m_value);
+ }
+
+ long IConvertible.ToInt64(IFormatProvider provider)
+ {
+ return Convert.ToInt64(m_value);
+ }
+
+ ulong IConvertible.ToUInt64(IFormatProvider provider)
+ {
+ return m_value;
+ }
+
+ float IConvertible.ToSingle(IFormatProvider provider)
+ {
+ return Convert.ToSingle(m_value);
+ }
+
+ double IConvertible.ToDouble(IFormatProvider provider)
+ {
+ return Convert.ToDouble(m_value);
+ }
+
+ Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ {
+ return Convert.ToDecimal(m_value);
+ }
+
+ DateTime IConvertible.ToDateTime(IFormatProvider provider)
+ {
+ throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "UInt64", "DateTime"));
+ }
+
+ Object IConvertible.ToType(Type type, IFormatProvider provider)
+ {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/UnauthorizedAccessException.cs b/src/mscorlib/shared/System/UnauthorizedAccessException.cs
index 667d576292..679a1a762d 100644
--- a/src/mscorlib/shared/System/UnauthorizedAccessException.cs
+++ b/src/mscorlib/shared/System/UnauthorizedAccessException.cs
@@ -24,19 +24,19 @@ namespace System
public UnauthorizedAccessException()
: base(SR.Arg_UnauthorizedAccessException)
{
- HResult = __HResults.COR_E_UNAUTHORIZEDACCESS;
+ HResult = HResults.COR_E_UNAUTHORIZEDACCESS;
}
public UnauthorizedAccessException(String message)
: base(message)
{
- HResult = __HResults.COR_E_UNAUTHORIZEDACCESS;
+ HResult = HResults.COR_E_UNAUTHORIZEDACCESS;
}
public UnauthorizedAccessException(String message, Exception inner)
: base(message, inner)
{
- HResult = __HResults.COR_E_UNAUTHORIZEDACCESS;
+ HResult = HResults.COR_E_UNAUTHORIZEDACCESS;
}
protected UnauthorizedAccessException(SerializationInfo info, StreamingContext context) : base(info, context)
diff --git a/src/mscorlib/shared/System/UnitySerializationHolder.cs b/src/mscorlib/shared/System/UnitySerializationHolder.cs
new file mode 100644
index 0000000000..bbfebff8a6
--- /dev/null
+++ b/src/mscorlib/shared/System/UnitySerializationHolder.cs
@@ -0,0 +1,66 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.Serialization;
+
+namespace System
+{
+ /// <summary>
+ /// Holds Null class for which we guarantee that there is only ever one instance of.
+ /// This only exists for compatibility with .NET Framework.
+ /// </summary>
+ [Serializable]
+#if CORECLR
+ internal
+#else
+ public // On CoreRT this must be public.
+#endif
+ sealed class UnitySerializationHolder : ISerializable, IObjectReference
+ {
+ internal const int NullUnity = 0x0002;
+ private readonly int _unityType;
+ private readonly string _data;
+
+ /// <summary>
+ /// A helper method that returns the SerializationInfo that a class utilizing
+ /// UnitySerializationHelper should return from a call to GetObjectData. It contains
+ /// the unityType (defined above) and any optional data (used only for the reflection types).
+ /// </summary>
+ internal static void GetUnitySerializationInfo(SerializationInfo info, int unityType)
+ {
+ info.SetType(typeof(UnitySerializationHolder));
+ info.AddValue("Data", null, typeof(string));
+ info.AddValue("UnityType", unityType);
+ info.AddValue("AssemblyName", string.Empty);
+ }
+
+ public UnitySerializationHolder(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ {
+ throw new ArgumentNullException(nameof(info));
+ }
+
+ // We are ignoring any other serialization input as we are only concerned about DBNull.
+ // We also store data and use it for erorr logging.
+ _unityType = info.GetInt32("UnityType");
+ _data = info.GetString("Data");
+ }
+
+ public void GetObjectData(SerializationInfo info, StreamingContext context) =>
+ throw new NotSupportedException(SR.NotSupported_UnitySerHolder);
+
+ public object GetRealObject(StreamingContext context)
+ {
+ // We are only support deserializing DBNull and throwing for everything else.
+ if (_unityType != NullUnity)
+ {
+ throw new ArgumentException(SR.Format(SR.Argument_InvalidUnity, _data ?? "UnityType"));
+ }
+
+ // We are always returning the same DBNull instance.
+ return DBNull.Value;
+ }
+ }
+}
diff --git a/src/mscorlib/shared/System/Version.cs b/src/mscorlib/shared/System/Version.cs
index a2140ab137..9c66d9b904 100644
--- a/src/mscorlib/shared/System/Version.cs
+++ b/src/mscorlib/shared/System/Version.cs
@@ -197,82 +197,118 @@ namespace System
return accumulator;
}
- public override String ToString()
+ public override string ToString() =>
+ ToString(DefaultFormatFieldCount);
+
+ public string ToString(int fieldCount) =>
+ fieldCount == 0 ? string.Empty :
+ fieldCount == 1 ? _Major.ToString() :
+ StringBuilderCache.GetStringAndRelease(ToCachedStringBuilder(fieldCount));
+
+ public bool TryFormat(Span<char> destination, out int charsWritten) =>
+ TryFormat(destination, DefaultFormatFieldCount, out charsWritten);
+
+ public bool TryFormat(Span<char> destination, int fieldCount, out int charsWritten)
{
- if (_Build == -1) return (ToString(2));
- if (_Revision == -1) return (ToString(3));
- return (ToString(4));
+ if (fieldCount == 0)
+ {
+ charsWritten = 0;
+ return true;
+ }
+
+ // TODO https://github.com/dotnet/corefx/issues/22403: fieldCount==1 can just use int.TryFormat
+
+ StringBuilder sb = ToCachedStringBuilder(fieldCount);
+ if (sb.Length <= destination.Length)
+ {
+ sb.CopyTo(0, destination, sb.Length);
+ StringBuilderCache.Release(sb);
+ charsWritten = sb.Length;
+ return true;
+ }
+
+ StringBuilderCache.Release(sb);
+ charsWritten = 0;
+ return false;
}
- public String ToString(int fieldCount)
+ private int DefaultFormatFieldCount =>
+ _Build == -1 ? 2 :
+ _Revision == -1 ? 3 :
+ 4;
+
+ private StringBuilder ToCachedStringBuilder(int fieldCount)
{
- StringBuilder sb;
- switch (fieldCount)
+ if (fieldCount == 1)
{
- case 0:
- return (String.Empty);
- case 1:
- return (_Major.ToString());
- case 2:
- sb = StringBuilderCache.Acquire();
- AppendPositiveNumber(_Major, sb);
- sb.Append('.');
- AppendPositiveNumber(_Minor, sb);
- return StringBuilderCache.GetStringAndRelease(sb);
- default:
- if (_Build == -1)
- throw new ArgumentException(SR.Format(SR.ArgumentOutOfRange_Bounds_Lower_Upper, "0", "2"), nameof(fieldCount));
+ StringBuilder sb = StringBuilderCache.Acquire();
+ AppendNonNegativeNumber(_Major, sb);
+ return sb;
+ }
+ else if (fieldCount == 2)
+ {
+ StringBuilder sb = StringBuilderCache.Acquire();
+ AppendNonNegativeNumber(_Major, sb);
+ sb.Append('.');
+ AppendNonNegativeNumber(_Minor, sb);
+ return sb;
+ }
+ else
+ {
+ if (_Build == -1)
+ {
+ throw new ArgumentException(SR.Format(SR.ArgumentOutOfRange_Bounds_Lower_Upper, "0", "2"), nameof(fieldCount));
+ }
- if (fieldCount == 3)
- {
- sb = StringBuilderCache.Acquire();
- AppendPositiveNumber(_Major, sb);
- sb.Append('.');
- AppendPositiveNumber(_Minor, sb);
- sb.Append('.');
- AppendPositiveNumber(_Build, sb);
- return StringBuilderCache.GetStringAndRelease(sb);
- }
+ if (fieldCount == 3)
+ {
+ StringBuilder sb = StringBuilderCache.Acquire();
+ AppendNonNegativeNumber(_Major, sb);
+ sb.Append('.');
+ AppendNonNegativeNumber(_Minor, sb);
+ sb.Append('.');
+ AppendNonNegativeNumber(_Build, sb);
+ return sb;
+ }
- if (_Revision == -1)
- throw new ArgumentException(SR.Format(SR.ArgumentOutOfRange_Bounds_Lower_Upper, "0", "3"), nameof(fieldCount));
+ if (_Revision == -1)
+ {
+ throw new ArgumentException(SR.Format(SR.ArgumentOutOfRange_Bounds_Lower_Upper, "0", "3"), nameof(fieldCount));
+ }
- if (fieldCount == 4)
- {
- sb = StringBuilderCache.Acquire();
- AppendPositiveNumber(_Major, sb);
- sb.Append('.');
- AppendPositiveNumber(_Minor, sb);
- sb.Append('.');
- AppendPositiveNumber(_Build, sb);
- sb.Append('.');
- AppendPositiveNumber(_Revision, sb);
- return StringBuilderCache.GetStringAndRelease(sb);
- }
+ if (fieldCount == 4)
+ {
+ StringBuilder sb = StringBuilderCache.Acquire();
+ AppendNonNegativeNumber(_Major, sb);
+ sb.Append('.');
+ AppendNonNegativeNumber(_Minor, sb);
+ sb.Append('.');
+ AppendNonNegativeNumber(_Build, sb);
+ sb.Append('.');
+ AppendNonNegativeNumber(_Revision, sb);
+ return sb;
+ }
- throw new ArgumentException(SR.Format(SR.ArgumentOutOfRange_Bounds_Lower_Upper, "0", "4"), nameof(fieldCount));
+ throw new ArgumentException(SR.Format(SR.ArgumentOutOfRange_Bounds_Lower_Upper, "0", "4"), nameof(fieldCount));
}
}
+ // TODO https://github.com/dotnet/corefx/issues/22616:
+ // Use StringBuilder.Append(int) once it's been updated to use spans internally.
//
- // AppendPositiveNumber is an optimization to append a number to a StringBuilder object without
+ // AppendNonNegativeNumber is an optimization to append a number to a StringBuilder object without
// doing any boxing and not even creating intermediate string.
// Note: as we always have positive numbers then it is safe to convert the number to string
// regardless of the current culture as we'll not have any punctuation marks in the number
- //
- private const int ZERO_CHAR_VALUE = (int)'0';
- private static void AppendPositiveNumber(int num, StringBuilder sb)
+ private static void AppendNonNegativeNumber(int num, StringBuilder sb)
{
Debug.Assert(num >= 0, "AppendPositiveNumber expect positive numbers");
int index = sb.Length;
- int reminder;
-
do
{
- reminder = num % 10;
- num = num / 10;
- sb.Insert(index, (char)(ZERO_CHAR_VALUE + reminder));
+ num = Math.DivRem(num, 10, out int remainder);
+ sb.Insert(index, (char)('0' + remainder));
} while (num > 0);
}
@@ -282,104 +318,108 @@ namespace System
{
throw new ArgumentNullException(nameof(input));
}
- Contract.EndContractBlock();
- VersionResult r = new VersionResult();
- r.Init(nameof(input), true);
- if (!TryParseVersion(input, ref r))
- {
- throw r.GetVersionParseException();
- }
- return r.m_parsedVersion;
+ return ParseVersion(input.AsReadOnlySpan(), throwOnFailure: true);
}
- public static bool TryParse(string input, out Version result)
- {
- VersionResult r = new VersionResult();
- r.Init(nameof(input), false);
- bool b = TryParseVersion(input, ref r);
- result = r.m_parsedVersion;
- return b;
- }
+ public static Version Parse(ReadOnlySpan<char> input) =>
+ ParseVersion(input, throwOnFailure: true);
- private static bool TryParseVersion(string version, ref VersionResult result)
+ public static bool TryParse(string input, out Version result)
{
- int major, minor, build, revision;
-
- if ((Object)version == null)
+ if (input == null)
{
- result.SetFailure(ParseFailureKind.ArgumentNullException);
+ result = null;
return false;
}
- String[] parsedComponents = version.Split('.');
- int parsedComponentsLength = parsedComponents.Length;
- if ((parsedComponentsLength < 2) || (parsedComponentsLength > 4))
+ return (result = ParseVersion(input.AsReadOnlySpan(), throwOnFailure: false)) != null;
+ }
+
+ public static bool TryParse(ReadOnlySpan<char> input, out Version result) =>
+ (result = ParseVersion(input, throwOnFailure: false)) != null;
+
+ private static Version ParseVersion(ReadOnlySpan<char> input, bool throwOnFailure)
+ {
+ // Find the separator between major and minor. It must exist.
+ int majorEnd = input.IndexOf('.');
+ if (majorEnd < 0)
{
- result.SetFailure(ParseFailureKind.ArgumentException);
- return false;
+ if (throwOnFailure) throw new ArgumentException(SR.Arg_VersionString, nameof(input));
+ return null;
}
- if (!TryParseComponent(parsedComponents[0], nameof(version), ref result, out major))
+ // Find the ends of the optional minor and build portions.
+ // We musn't have any separators after build.
+ int buildEnd = -1;
+ int minorEnd = input.IndexOf('.', majorEnd + 1);
+ if (minorEnd != -1)
{
- return false;
+ buildEnd = input.IndexOf('.', minorEnd + 1);
+ if (buildEnd != -1)
+ {
+ if (input.IndexOf('.', buildEnd + 1) != -1)
+ {
+ if (throwOnFailure) throw new ArgumentException(SR.Arg_VersionString, nameof(input));
+ return null;
+ }
+ }
}
- if (!TryParseComponent(parsedComponents[1], nameof(version), ref result, out minor))
+ int major, minor, build, revision;
+
+ // Parse the major version
+ if (!TryParseComponent(input.Slice(0, majorEnd), nameof(input), throwOnFailure, out major))
{
- return false;
+ return null;
}
- parsedComponentsLength -= 2;
-
- if (parsedComponentsLength > 0)
+ if (minorEnd != -1)
{
- if (!TryParseComponent(parsedComponents[2], "build", ref result, out build))
+ // If there's more than a major and minor, parse the minor, too.
+ if (!TryParseComponent(input.Slice(majorEnd + 1, minorEnd - majorEnd - 1), nameof(input), throwOnFailure, out minor))
{
- return false;
+ return null;
}
- parsedComponentsLength--;
-
- if (parsedComponentsLength > 0)
+ if (buildEnd != -1)
{
- if (!TryParseComponent(parsedComponents[3], "revision", ref result, out revision))
- {
- return false;
- }
- else
- {
- result.m_parsedVersion = new Version(major, minor, build, revision);
- }
+ // major.minor.build.revision
+ return
+ TryParseComponent(input.Slice(minorEnd + 1, buildEnd - minorEnd - 1), nameof(build), throwOnFailure, out build) &&
+ TryParseComponent(input.Slice(buildEnd + 1), nameof(revision), throwOnFailure, out revision) ?
+ new Version(major, minor, build, revision) :
+ null;
}
else
{
- result.m_parsedVersion = new Version(major, minor, build);
+ // major.minor.build
+ return TryParseComponent(input.Slice(minorEnd + 1), nameof(build), throwOnFailure, out build) ?
+ new Version(major, minor, build) :
+ null;
}
}
else
{
- result.m_parsedVersion = new Version(major, minor);
+ // major.minor
+ return TryParseComponent(input.Slice(majorEnd + 1), nameof(input), throwOnFailure, out minor) ?
+ new Version(major, minor) :
+ null;
}
-
- return true;
}
- private static bool TryParseComponent(string component, string componentName, ref VersionResult result, out int parsedComponent)
+ private static bool TryParseComponent(ReadOnlySpan<char> component, string componentName, bool throwOnFailure, out int parsedComponent)
{
- if (!Int32.TryParse(component, NumberStyles.Integer, CultureInfo.InvariantCulture, out parsedComponent))
+ if (throwOnFailure)
{
- result.SetFailure(ParseFailureKind.FormatException, component);
- return false;
- }
-
- if (parsedComponent < 0)
- {
- result.SetFailure(ParseFailureKind.ArgumentOutOfRangeException, componentName);
- return false;
+ if ((parsedComponent = int.Parse(component, NumberStyles.Integer, CultureInfo.InvariantCulture)) < 0)
+ {
+ throw new ArgumentOutOfRangeException(componentName, SR.ArgumentOutOfRange_Version);
+ }
+ return true;
}
- return true;
+ return int.TryParse(component, out parsedComponent, NumberStyles.Integer, CultureInfo.InvariantCulture) && parsedComponent >= 0;
}
public static bool operator ==(Version v1, Version v2)
@@ -422,75 +462,5 @@ namespace System
{
return (v2 <= v1);
}
-
- internal enum ParseFailureKind
- {
- ArgumentNullException,
- ArgumentException,
- ArgumentOutOfRangeException,
- FormatException
- }
-
- internal struct VersionResult
- {
- internal Version m_parsedVersion;
- internal ParseFailureKind m_failure;
- internal string m_exceptionArgument;
- internal string m_argumentName;
- internal bool m_canThrow;
-
- internal void Init(string argumentName, bool canThrow)
- {
- m_canThrow = canThrow;
- m_argumentName = argumentName;
- }
-
- internal void SetFailure(ParseFailureKind failure)
- {
- SetFailure(failure, String.Empty);
- }
-
- internal void SetFailure(ParseFailureKind failure, string argument)
- {
- m_failure = failure;
- m_exceptionArgument = argument;
- if (m_canThrow)
- {
- throw GetVersionParseException();
- }
- }
-
- internal Exception GetVersionParseException()
- {
- switch (m_failure)
- {
- case ParseFailureKind.ArgumentNullException:
- return new ArgumentNullException(m_argumentName);
- case ParseFailureKind.ArgumentException:
- return new ArgumentException(SR.Arg_VersionString);
- case ParseFailureKind.ArgumentOutOfRangeException:
- return new ArgumentOutOfRangeException(m_exceptionArgument, SR.ArgumentOutOfRange_Version);
- case ParseFailureKind.FormatException:
- // Regenerate the FormatException as would be thrown by Int32.Parse()
- try
- {
- Int32.Parse(m_exceptionArgument, CultureInfo.InvariantCulture);
- }
- catch (FormatException e)
- {
- return e;
- }
- catch (OverflowException e)
- {
- return e;
- }
- Debug.Assert(false, "Int32.Parse() did not throw exception but TryParse failed: " + m_exceptionArgument);
- return new FormatException(SR.Format_InvalidString);
- default:
- Debug.Assert(false, "Unmatched case in Version.GetVersionParseException() for value: " + m_failure);
- return new ArgumentException(SR.Arg_VersionString);
- }
- }
- }
}
}