diff --git a/.gitignore b/.gitignore index 7c5113e..77f64d0 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ *.userprefs *.xml *.nupkg +*.svn diff --git a/ChangeLog.txt b/ChangeLog.txt new file mode 100644 index 0000000..d969f02 --- /dev/null +++ b/ChangeLog.txt @@ -0,0 +1,231 @@ +Major changes from v0.2.5 to v0.2.6 + +dna: + +* Command line parameters are now passed to the .NET executable, in the args[] array to Main(). + +* When calling a method on a null reference, a NullReferenceException is now thrown, + rather than crashing. However - note that internally thrown exceptions don't act quite + as expected, as their constructors are not yet called. + +------------------------------------------------------------------------------ + +Major changes from v0.2.4 to v0.2.5 + +All Visual Studio solutions have been upgraded to VS2008. + +dna: + +* Fixed bug with static fields in generic types. The memory location for the field + was not being initialised properly. + +* Fixed bug with overridding virtual methods in generic types. Virtual method table + indexes were being generated for partially defined generic types, which shouldn't + be done as virtual method tables are not available for these types. + +* Fixed bug where generic method type arguments were not propogated through the type + system correctly. (In fact, at all). + +* Fixed bug in finding generic methods in another assembly. The generic method + signature was not being checked correctly. + +* Fixed bug in MetaData_LoadTables() where the blob index size was being read incorrecty. + Thanks to Patrick Levesque for report and fix. + +* Fixed bug in casting to nullable types. + +* Fixed bug in using typeof() on generic arguments. + +* Fixed bug in Array.GetValue() and Array.SetValue() when using nullable types. + +* Improved error reporting for missing methods. Now shows the correct containing type. + +* Improved conversion operations. All conversions are now supported, with more efficient + runtime operation. However, checked conversions run as unchecked conversions. + +* Implemented all the unsigned branch instructions, long versions. + +corlib: + +* Added IComparer[T], IComparer and Comparer. + +* Added IEqualityComparer[T], IEqualityComparer and EqualityComparer. + +* Dictionary[TKey, TValue], List[T] and ArrayList re-implemented and improved. + +* Fixed missing functionality in Nullable[T].Equals() method. + +* Implemented Enum.GetNames(). + +System.Core: + +* Added System.Core.dll, containing: + - Most LINQ to Objects extension methods. + - Func[...] and Action[...] delegates. + +------------------------------------------------------------------------------ + +Major changes from v0.2.3 to v0.2.4 + +All parts of this project are now licensed under the MIT license. + +------------------------------------------------------------------------------ + +Major changes from v0.2.2 to v0.2.3 + +dna: + +* Improved time resolution of DateTime.UtcNow + +* Added code to selectively generate combined-opcode versions often-used methods. + It is disabled by default, but may be enabled in config.h + It currently has the following major problems: + - It doesn't appear to actually speed up execution very much (~5% in testing). + - It leaks some memory when 'de-optimizing' methods that are no longer + frequently used. This won't be too difficult to fix. + +* Added support for static fields containing value-types. + +* Added support for casting from Int64 to Double. + +corlib: + +* DateTimeFormatInfo implemented + +* Calendar and GregorianCalendar very basically implemented. Enough that DateTime + formatting now works. + +* DateTime.ToString() now works properly (except for timezones). + +* More of Math class implemented. + +* Implemented IComparable, IComparable[T] and IEquatable[T] on Int16, Int32, + Int64, Single, Double, UInt16 ,UInt32, UInt64, Byte, SByte and Boolean. + +System.Drawing: + +* Region is very basically implemented. Only infinite and rectangular regions + are supported. + +* Added clipping support to Graphics. + +* Graphics.MeasureString() has some overloads implemented. + +* Graphics.DrawEllipse() and FillEllipse() with int and rect arguments implemented. + +* Fixed bug with line drawing. + +libIGraph: + +* Implemented native parts of region. + +* Implemented native clipping support for all Graphics operations. + +* Implemented native parts of MeasureString(). + +* Implemented ellipse drawing and filling. + +System: + +* Stack[T] class added. + +------------------------------------------------------------------------------ + +Major changes from v0.2.1 to v0.2.2 + +dna: + +* Added native code for DNS class + +* Added native code for System.Threading.Interlocked class + +corlib: + +* Added all System.Threading.Interlocked methods that operate on Int32 values. + Enumerators defined using yield return therefore now work - they need + CompareExchange(). + +* Added delegates: Action[T], Predicate[T] + +* Added TimeSpan - complete except for Parse() and TryParse() + +* Added DateTime - DateTime.Now is not implemented, DateTime.UtcNow is. + Add simple operations are implemented, but not more complex/obscure stuff, + e.g. ToFileTime(). ToString() is only crudely implemented, not taking + any notice of formatting specified, or culture. It is always shown in + UK format (dd/mm/yyyy hh:mm:ss). + +System: + +* Added the beginnings of the Dns class. It is now possible to get the IPv4 + address for a host-name. + +------------------------------------------------------------------------------ + +Major changes from v0.2.0 to v0.2.1 + +dna: + +* Fixed bug in constrained virtual calls. + +* Fixed bug with how Single and Double types were handled. + +* Added array functionality for floating-point types. + +* Improved how internal calls are looked up. + +* Updated the VS2005 build config for release, to place the executable + in the correct place. + +* Implemented Nullable types. + +* Implemented basic native socket functionality. + +* A little more reflection implemented. + +* Misc other bug-fixes and improvements. + +System: + +* Implemented Nullable and Nullable[T] classes. + +* Implemented the Socket class (and friends). Only the very basic operations + are currently implemented. A socket can be created, used to listen or connect + and can send and receive data. Only IPv4 is supported and at the moment only + TCP is support (UDP to be added later). More will be implemented later. + +corlib: + +* A little more reflection implemented. + +------------------------------------------------------------------------------ + +Major changes from v0.1 to v0.2.0 + +The Interpreter: + +* The main interpreter loop has changed from a 'loop with switch' +to use direct threading (see http://en.wikipedia.org/wiki/Threaded_code +for details). This gives a performance advantage, although not on Windows +as having __asm code in a function appears to stop all other optimizations. +The assembler code is only required on non-GNU compilers as GNU provides +the computed goto statement. + +* A dynamic code generator (strictly, just a combiner) has been +implemented, which dynamically generates multi-opcode instructions. +However, it is disabled by default because it currently generates +dynamic code for all JITted methods, which uses large amounts of +memory, and is not always faster (due to code caching). An algorithm +to selectively re-JIT frequently-used methods is being worked on. + +* Split out the configuration into a seperate Config.h file. + +* Misc other bug-fixes and improvements. + +System.Drawing: + +* Implmented LinearGradiantBrush + +* Fixed bug in HatchBrush that caused all hatches to be drawn 90 +degrees rotated. + diff --git a/Managed.sln b/Managed.sln new file mode 100644 index 0000000..719c666 --- /dev/null +++ b/Managed.sln @@ -0,0 +1,63 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "corlib", "corlib\corlib.csproj", "{6A77A7C0-FB66-4CAA-94EE-142DBA20655D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Drawing", "System.Drawing\System.Drawing.csproj", "{0F7F935F-E3F5-40AD-BD22-0BA43721560F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System", "System\System.csproj", "{388F5D73-0211-4A64-B501-92CDC4E32ACF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Snake", "Snake\Snake.csproj", "{C26A3309-7A61-40B6-9998-69B78CF226C1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomDevice", "CustomDevice\CustomDevice.csproj", "{43619745-0A80-499E-907C-E733FF3DA2BE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Core", "System.Core\System.Core.csproj", "{2D656D44-7857-4A48-A46D-0DB5EFBC3A46}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + LocalTest|Any CPU = LocalTest|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6A77A7C0-FB66-4CAA-94EE-142DBA20655D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6A77A7C0-FB66-4CAA-94EE-142DBA20655D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6A77A7C0-FB66-4CAA-94EE-142DBA20655D}.LocalTest|Any CPU.ActiveCfg = LocalTest|Any CPU + {6A77A7C0-FB66-4CAA-94EE-142DBA20655D}.LocalTest|Any CPU.Build.0 = LocalTest|Any CPU + {6A77A7C0-FB66-4CAA-94EE-142DBA20655D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6A77A7C0-FB66-4CAA-94EE-142DBA20655D}.Release|Any CPU.Build.0 = Release|Any CPU + {0F7F935F-E3F5-40AD-BD22-0BA43721560F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0F7F935F-E3F5-40AD-BD22-0BA43721560F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0F7F935F-E3F5-40AD-BD22-0BA43721560F}.LocalTest|Any CPU.ActiveCfg = Release|Any CPU + {0F7F935F-E3F5-40AD-BD22-0BA43721560F}.LocalTest|Any CPU.Build.0 = Release|Any CPU + {0F7F935F-E3F5-40AD-BD22-0BA43721560F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0F7F935F-E3F5-40AD-BD22-0BA43721560F}.Release|Any CPU.Build.0 = Release|Any CPU + {388F5D73-0211-4A64-B501-92CDC4E32ACF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {388F5D73-0211-4A64-B501-92CDC4E32ACF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {388F5D73-0211-4A64-B501-92CDC4E32ACF}.LocalTest|Any CPU.ActiveCfg = Release|Any CPU + {388F5D73-0211-4A64-B501-92CDC4E32ACF}.LocalTest|Any CPU.Build.0 = Release|Any CPU + {388F5D73-0211-4A64-B501-92CDC4E32ACF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {388F5D73-0211-4A64-B501-92CDC4E32ACF}.Release|Any CPU.Build.0 = Release|Any CPU + {C26A3309-7A61-40B6-9998-69B78CF226C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C26A3309-7A61-40B6-9998-69B78CF226C1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C26A3309-7A61-40B6-9998-69B78CF226C1}.LocalTest|Any CPU.ActiveCfg = Release|Any CPU + {C26A3309-7A61-40B6-9998-69B78CF226C1}.LocalTest|Any CPU.Build.0 = Release|Any CPU + {C26A3309-7A61-40B6-9998-69B78CF226C1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C26A3309-7A61-40B6-9998-69B78CF226C1}.Release|Any CPU.Build.0 = Release|Any CPU + {43619745-0A80-499E-907C-E733FF3DA2BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {43619745-0A80-499E-907C-E733FF3DA2BE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {43619745-0A80-499E-907C-E733FF3DA2BE}.LocalTest|Any CPU.ActiveCfg = Release|Any CPU + {43619745-0A80-499E-907C-E733FF3DA2BE}.LocalTest|Any CPU.Build.0 = Release|Any CPU + {43619745-0A80-499E-907C-E733FF3DA2BE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {43619745-0A80-499E-907C-E733FF3DA2BE}.Release|Any CPU.Build.0 = Release|Any CPU + {2D656D44-7857-4A48-A46D-0DB5EFBC3A46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2D656D44-7857-4A48-A46D-0DB5EFBC3A46}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2D656D44-7857-4A48-A46D-0DB5EFBC3A46}.LocalTest|Any CPU.ActiveCfg = Release|Any CPU + {2D656D44-7857-4A48-A46D-0DB5EFBC3A46}.LocalTest|Any CPU.Build.0 = Release|Any CPU + {2D656D44-7857-4A48-A46D-0DB5EFBC3A46}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2D656D44-7857-4A48-A46D-0DB5EFBC3A46}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/System.Core/Properties/AssemblyInfo.cs b/System.Core/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..4ae1f29 --- /dev/null +++ b/System.Core/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("System.Core")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("EnviroMotive")] +[assembly: AssemblyProduct("System.Core")] +[assembly: AssemblyCopyright("Copyright © EnviroMotive 2009")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("526d494e-2534-46ed-aa0a-4f4b4b3132e8")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/System.Core/System.Collections.Generic/HashSet.cs b/System.Core/System.Collections.Generic/HashSet.cs new file mode 100644 index 0000000..9964c9d --- /dev/null +++ b/System.Core/System.Collections.Generic/HashSet.cs @@ -0,0 +1,155 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace System.Collections.Generic { + + public class HashSet : ICollection, IEnumerable, IEnumerable { + + public struct Enumerator : IEnumerator, IEnumerator, IDisposable { + + internal Enumerator(HashSet hashSet) { + this.en = hashSet.dict.Keys.GetEnumerator(); + } + + private IEnumerator en; + + public T Current { + get { + return this.en.Current; + } + } + + public void Dispose() { + } + + object IEnumerator.Current { + get { + return this.en.Current; + } + } + + public bool MoveNext() { + return this.en.MoveNext(); + } + + public void Reset() { + this.en.Reset(); + } + + } + + private Dictionary dict; + + public HashSet() { + this.dict = new Dictionary(); + } + + public HashSet(IEnumerable collection) : this(collection, null) { } + + public HashSet(IEqualityComparer comparer) { + this.dict = new Dictionary(comparer); + } + + public HashSet(IEnumerable collection, IEqualityComparer comparer) { + if (collection == null) { + throw new ArgumentNullException(); + } + this.dict = new Dictionary(comparer); + foreach (T item in collection) { + this.dict[item] = null; + } + } + + public bool Add(T item) { + bool ret = !this.dict.ContainsKey(item); + this.dict[item] = null; + return ret; + } + + public void Clear() { + this.dict.Clear(); + } + + public bool Contains(T item) { + return this.dict.ContainsKey(item); + } + + public void CopyTo(T[] array) { + throw new NotImplementedException(); + } + + public void CopyTo(T[] array, int arrayIndex) { + throw new NotImplementedException(); + } + + public void CopyTo(T[] array, int arrayIndex, int count) { + throw new NotImplementedException(); + } + + public Enumerator GetEnumerator() { + return new Enumerator(this); + } + + public bool Remove(T item) { + return this.dict.Remove(item); + } + + public IEqualityComparer Comparer { + get { + return this.dict.Comparer; + } + } + + public int Count { + get { + return this.dict.Count; + } + } + + + #region Interface Members + + void ICollection.Add(T item) { + this.Add(item); + } + + bool ICollection.IsReadOnly { + get { + return false; + } + } + + IEnumerator IEnumerable.GetEnumerator() { + return new Enumerator(this); + } + + IEnumerator IEnumerable.GetEnumerator() { + return new Enumerator(this); + } + + #endregion + } + +} diff --git a/System.Core/System.Core.csproj b/System.Core/System.Core.csproj new file mode 100644 index 0000000..c1bb441 --- /dev/null +++ b/System.Core/System.Core.csproj @@ -0,0 +1,63 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {2D656D44-7857-4A48-A46D-0DB5EFBC3A46} + Library + Properties + System.Core + System.Core + v3.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + copy $(TargetPath) $(SolutionDir)\Builds\$(ConfigurationName)\ + + \ No newline at end of file diff --git a/System.Core/System.Linq/Enumerable.cs b/System.Core/System.Linq/Enumerable.cs new file mode 100644 index 0000000..1c4e659 --- /dev/null +++ b/System.Core/System.Linq/Enumerable.cs @@ -0,0 +1,1405 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Collections; + +namespace System.Linq { + public static class Enumerable { + + private static class Funcs { + public static readonly Func True = x => true; + public static readonly Func Identity = x => x; + } + + #region Aggregate + + public static T Aggregate(this IEnumerable source, Func func) { + Check(source, func); + using (var en = source.GetEnumerator()) { + if (!en.MoveNext()) { + throw new InvalidOperationException(); + } + T value = en.Current; + while (en.MoveNext()) { + value = func(value, en.Current); + } + return value; + } + } + + public static TAcc Aggregate(this IEnumerable source, TAcc seed, Func func) { + return source.Aggregate(seed, func, Funcs.Identity); + } + + public static TResult Aggregate + (this IEnumerable source, TAcc seed, Func func, Func resultSelector) { + Check(source, func, resultSelector); + foreach (var item in source) { + seed = func(seed, item); + } + return resultSelector(seed); + } + + #endregion + + #region All + + public static bool All(this IEnumerable source, Func predicate) { + Check(source); + foreach (T item in source) { + if (!predicate(item)) { + return false; + } + } + return true; + } + + #endregion + + #region Any + + public static bool Any(this IEnumerable source) { + return source.Any(Funcs.True); + } + + public static bool Any(this IEnumerable source, Func predicate) { + Check(source, predicate); + foreach (T item in source) { + if (predicate(item)) { + return true; + } + } + return false; + } + + #endregion + + #region Average + + public static double Average(this IEnumerable source) { + return Avg(source, (a, v) => a + v, (a, c) => (double)a / (double)c); + } + + public static double? Average(this IEnumerable source) { + return AvgNullable(source, (a, v) => a + v, (a, c) => (double)a / (double)c); + } + + public static double Average(this IEnumerable source) { + return Avg(source, (a, v) => a + v, (a, c) => (double)a / (double)c); + } + + public static double? Average(this IEnumerable source) { + return AvgNullable(source, (a, v) => a + v, (a, c) => (double)a / (double)c); + } + + public static float Average(this IEnumerable source) { + return Avg(source, (a, v) => a + v, (a, c) => a / c); + } + + public static float? Average(this IEnumerable source) { + return AvgNullable(source, (a, v) => a + v, (a, c) => a / c); + } + + public static double Average(this IEnumerable source) { + return Avg(source, (a, v) => a + v, (a, c) => a / c); + } + + public static double? Average(this IEnumerable source) { + return AvgNullable(source, (a, v) => a + v, (a, c) => a / c); + } + + public static Decimal Average(this IEnumerable source) { + throw new NotImplementedException(); + } + + public static Decimal? Average(this IEnumerable source) { + throw new NotImplementedException(); + } + + public static double Average(this IEnumerable source, Func selector) { + return Avg(source.Select(selector), (a, v) => a + v, (a, c) => (double)a / (double)c); + } + + public static double? Average(this IEnumerable source, Func selector) { + return AvgNullable(source.Select(selector), (a, v) => a + v, (a, c) => (double)a / (double)c); + } + + public static double Average(this IEnumerable source, Func selector) { + return Avg(source.Select(selector), (a, v) => a + v, (a, c) => (double)a / (double)c); + } + + public static double? Average(this IEnumerable source, Func selector) { + return AvgNullable(source.Select(selector), (a, v) => a + v, (a, c) => (double)a / (double)c); + } + + public static float Average(this IEnumerable source, Func selector) { + return Avg(source.Select(selector), (a, v) => a + v, (a, c) => a / c); + } + + public static float? Average(this IEnumerable source, Func selector) { + return AvgNullable(source.Select(selector), (a, v) => a + v, (a, c) => a / c); + } + + public static double Average(this IEnumerable source, Func selector) { + return Avg(source.Select(selector), (a, v) => a + v, (a, c) => a / c); + } + + public static double? Average(this IEnumerable source, Func selector) { + return AvgNullable(source.Select(selector), (a, v) => a + v, (a, c) => a / c); + } + + public static Decimal Average(this IEnumerable source, Func selector) { + throw new NotImplementedException(); + } + + public static Decimal? Average(this IEnumerable source, Func selector) { + throw new NotImplementedException(); + } + + private static TRes Avg(IEnumerable source, + Func accFn, Func resFn) { + Check(source); + TAcc acc = default(TAcc); + int counter = 0; + foreach (var item in source) { + acc = accFn(acc, item); + counter++; + } + if (counter == 0) { + throw new InvalidOperationException(); + } + return resFn(acc, counter); + } + + private static TRes? AvgNullable(IEnumerable source, + Func accFn, Func resFn) + where T : struct + where TRes : struct { + Check(source); + TAcc acc = default(TAcc); + int counter = 0; + foreach (var item in source) { + if (item != null) { + acc = accFn(acc, item.Value); + counter++; + } + } + if (counter == 0) { + return null; + } + return resFn(acc, counter); + } + + #endregion + + #region AsEnumerable + + public static IEnumerable AsEnumerable(this IEnumerable source) { + return source; + } + + #endregion + + #region Cast + + public static IEnumerable Cast(IEnumerable source) { + Check(source); + return CastIterator(source); + } + + private static IEnumerable CastIterator(IEnumerable source) { + foreach (T item in source) { + yield return item; + } + } + + #endregion + + #region Concat + + public static IEnumerable Concat + (this IEnumerable first, IEnumerable second) { + Check(first, second); + return ConcatIterator(first, second); + } + + private static IEnumerable ConcatIterator + (IEnumerable first, IEnumerable second) { + foreach (T item in first) { + yield return item; + } + foreach (T item in second) { + yield return item; + } + } + + #endregion + + #region Contains + + public static bool Contains(this IEnumerable source, T value) { + return source.Contains(value, null); + } + + public static bool Contains + (this IEnumerable source, T value, IEqualityComparer comparer) { + Check(source); + if (comparer == null) { + comparer = EqualityComparer.Default; + } + foreach (T item in source) { + if (comparer.Equals(item, value)) { + return true; + } + } + return false; + } + + #endregion + + #region Count, LongCount + + public static int Count(this IEnumerable source) { + Check(source); + ICollection collection = source as ICollection; + if (collection != null) { + return collection.Count; + } else { + return source.Count(Funcs.True); + } + } + + public static int Count(this IEnumerable source, Func predicate) { + Check(source, predicate); + int count = 0; + foreach (T item in source) { + if (predicate(item)) { + count++; + } + } + return count; + } + + public static long LongCount(this IEnumerable source) { + return (long)Count(source); + } + + public static long LongCount(this IEnumerable source, Func predicate) { + return (long)Count(source, predicate); + } + + #endregion + + #region DefaultIfEmpty + + public static IEnumerable DefaultIfEmpty(this IEnumerable source) { + return source.DefaultIfEmpty(default(T)); + } + + public static IEnumerable DefaultIfEmpty(this IEnumerable source, T defaultValue) { + Check(source); + return DefaultIfEmptyIterator(source, defaultValue); + } + + private static IEnumerable DefaultIfEmptyIterator(IEnumerable source, T defaultValue) { + using (IEnumerator en = source.GetEnumerator()) { + if (en.MoveNext()) { + do { + yield return en.Current; + } while (en.MoveNext()); + } else { + yield return defaultValue; + } + } + } + + #endregion + + #region Distinct + + public static IEnumerable Distinct(this IEnumerable source) { + return Distinct(source, null); + } + + public static IEnumerable Distinct(this IEnumerable source, IEqualityComparer comparer) { + return DistinctIterator(source, comparer); + } + + private static IEnumerable DistinctIterator(IEnumerable source, IEqualityComparer comparer) { + HashSet h = new HashSet(comparer); + foreach (T item in source) { + if (h.Add(item)) { + yield return item; + } + } + } + + #endregion + + #region ElementAt, ElementAtOrDefault + + public static T ElementAt(IEnumerable source, int index) { + return ElementAt(source, index, false); + } + + public static T ElementAtOrDefault(IEnumerable source, int index) { + return ElementAt(source, index, true); + } + + private static T ElementAt(IEnumerable source, int index, bool orDefault) { + Check(source); + if (index >= 0) { + IList list = source as IList; + if (list != null) { + if (index < list.Count) { + return list[index]; + } + } else { + int count = 0; + foreach (T item in source) { + if (count == index) { + return item; + } + count++; + } + } + } + if (orDefault) { + return default(T); + } else { + throw new ArgumentOutOfRangeException(); + } + } + + #endregion + + #region Empty + + public static IEnumerable Empty() { + return new T[0]; + } + + #endregion + + #region Except + + public static IEnumerable Except(this IEnumerable first, IEnumerable second) { + return Except(first, second, null); + } + + public static IEnumerable Except + (this IEnumerable first, IEnumerable second, IEqualityComparer comparer) { + Check(first, second); + return ExceptIterator(first, second, comparer); + } + + private static IEnumerable ExceptIterator + (IEnumerable first, IEnumerable second, IEqualityComparer comparer) { + HashSet h = new HashSet(second, comparer); + foreach (T item in first) { + if (!h.Contains(item)) { + yield return item; + } + } + } + + #endregion + + #region First, FirstOrDefault, Single, SingleOrDefault + + private static T FirstSingle(IEnumerable source, Func predicate, bool single, bool retDefault) { + Check(source, predicate); + using (var en = source.Where(predicate).GetEnumerator()) { + if (en.MoveNext()) { + T value = en.Current; + if (single) { + if (en.MoveNext()) { + throw new InvalidOperationException(); + } + } + return value; + } else { + if (retDefault) { + return default(T); + } else { + throw new InvalidOperationException(); + } + } + } + } + + public static T First(this IEnumerable source) { + return FirstSingle(source, Funcs.True, false, false); + } + + public static T First(this IEnumerable source, Func predicate) { + return FirstSingle(source, predicate, false, false); + } + + public static T FirstOrDefault(this IEnumerable source) { + return FirstSingle(source, Funcs.True, false, true); + } + + public static T FirstOrDefault(this IEnumerable source, Func predicate) { + return FirstSingle(source, predicate, false, true); + } + + public static T Single(this IEnumerable source) { + return FirstSingle(source, Funcs.True, true, false); + } + + public static T Single(this IEnumerable source, Func predicate) { + return FirstSingle(source, predicate, true, false); + } + + public static T SingleOrDefault(this IEnumerable source) { + return FirstSingle(source, Funcs.True, true, true); + } + + public static T SingleOrDefault(this IEnumerable source, Func predicate) { + return FirstSingle(source, predicate, true, true); + } + + #endregion + + #region GroupBy + + public static IEnumerable> GroupBy + (this IEnumerable source, Func keySelector) { + return source.GroupBy(keySelector, null); + } + + public static IEnumerable> GroupBy + (this IEnumerable source, Func keySelector, + IEqualityComparer comparer) { + return source.GroupBy(keySelector, Funcs.Identity, comparer); + } + + public static IEnumerable> GroupBy + (this IEnumerable source, Func keySelector, + Func elementSelector) { + return source.GroupBy(keySelector, elementSelector, null); + } + + public static IEnumerable> GroupBy + (this IEnumerable source, Func keySelector, + Func elementSelector, IEqualityComparer comparer) { + return source.GroupBy(keySelector, elementSelector, + (key, elements) => (IGrouping)new Grouping(key, elements), + comparer); + } + + public static IEnumerable GroupBy + (this IEnumerable source, Func keySelector, + Func, TResult> resultSelector) { + return source.GroupBy(keySelector, resultSelector, null); + } + + public static IEnumerable GroupBy + (this IEnumerable source, Func keySelector, + Func, TResult> resultSelector, IEqualityComparer comparer) { + return source.GroupBy(keySelector, Funcs.Identity, resultSelector, comparer); + } + + public static IEnumerable GroupBy + (this IEnumerable source, Func keySelector, + Func elementSelector, Func, TResult> resultSelector) { + return source.GroupBy(keySelector, elementSelector, resultSelector, null); + } + + public static IEnumerable GroupBy + (this IEnumerable source, Func keySelector, + Func elementSelector, Func, TResult> resultSelector, + IEqualityComparer comparer) { + Check(source, keySelector, elementSelector); + Check(resultSelector); + return GroupByIterator(source, keySelector, elementSelector, resultSelector, comparer); + } + + private static IEnumerable GroupByIterator + (IEnumerable source, Func keySelector, + Func elementSelector, Func, TResult> resultSelector, + IEqualityComparer comparer) { + Dictionary> groups = new Dictionary>(comparer); + foreach (var item in source) { + TKey key = keySelector(item); + TElement element = elementSelector(item); + List itemsInGroup; + if (!groups.TryGetValue(key, out itemsInGroup)) { + itemsInGroup = new List(); + groups.Add(key, itemsInGroup); + } + itemsInGroup.Add(element); + } + foreach (var group in groups) { + yield return resultSelector(group.Key, group.Value); + } + } + + #endregion + + #region GroupJoin + + public static IEnumerable GroupJoin + (this IEnumerable outer, IEnumerable inner, + Func outerKeySelector, Func innerKeySelector, + Func, TResult> resultSelector) { + return outer.GroupJoin(inner, outerKeySelector, innerKeySelector, resultSelector, null); + } + + public static IEnumerable GroupJoin + (this IEnumerable outer, IEnumerable inner, + Func outerKeySelector, Func innerKeySelector, + Func, TResult> resultSelector, + IEqualityComparer comparer) { + Check(outer, inner, outerKeySelector); + Check(innerKeySelector, resultSelector); + return GroupJoinIterator(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer); + } + + public static IEnumerable GroupJoinIterator + (IEnumerable outer, IEnumerable inner, + Func outerKeySelector, Func innerKeySelector, + Func, TResult> resultSelector, + IEqualityComparer comparer) { + var innerLookup = inner.ToLookup(innerKeySelector, comparer); + foreach (var outerItem in outer) { + TKey outerKey = outerKeySelector(outerItem); + yield return resultSelector(outerItem, + innerLookup.Contains(outerKey) ? innerLookup[outerKey] : Empty()); + } + } + #endregion + + #region Intersect + + public static IEnumerable Intersect(this IEnumerable first, IEnumerable second) { + return first.Intersect(second, null); + } + + public static IEnumerable Intersect(this IEnumerable first, IEnumerable second, + IEqualityComparer comparer) { + Check(first, second); + return IntersectIterator(first, second, comparer); + } + + private static IEnumerable IntersectIterator(IEnumerable first, IEnumerable second, + IEqualityComparer comparer) { + HashSet hash = new HashSet(first, comparer); + foreach (var item in second.Distinct(comparer)) { + if (hash.Contains(item)) { + yield return item; + } + } + } + + #endregion + + #region Join + + public static IEnumerable Join + (this IEnumerable outer, IEnumerable inner, + Func outerKeySelector, Func innerKeySelector, + Func resultSelector) { + return outer.Join(inner, outerKeySelector, innerKeySelector, resultSelector, null); + } + + public static IEnumerable Join + (this IEnumerable outer, IEnumerable inner, + Func outerKeySelector, Func innerKeySelector, + Func resultSelector, IEqualityComparer comparer) { + Check(outer, inner); + Check(outerKeySelector, innerKeySelector, resultSelector); + return JoinIterator(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer); + } + + private static IEnumerable JoinIterator + (IEnumerable outer, IEnumerable inner, + Func outerKeySelector, Func innerKeySelector, + Func resultSelector, IEqualityComparer comparer) { + var outerLookup = outer.ToLookup(outerKeySelector, comparer); + foreach (TInner innerItem in inner) { + TKey innerKey = innerKeySelector(innerItem); + if (outerLookup.Contains(innerKey)) { + foreach (TOuter outerItem in outerLookup[innerKey]) { + yield return resultSelector(outerItem, innerItem); + } + } + } + } + + #endregion + + #region Last, LastOrDefault + + private static T LastOrDefault(IEnumerable source, Func predicate, bool retDefault) { + Check(source, predicate); + T last = default(T); + bool empty = true; + foreach (T item in source) { + if (predicate(item)) { + empty = false; + last = item; + } + } + if (empty && !retDefault) { + throw new InvalidOperationException(); + } + return last; + } + + public static T Last(this IEnumerable source) { + return LastOrDefault(source, Funcs.True, false); + } + + public static T Last(this IEnumerable source, Func predicate) { + return LastOrDefault(source, predicate, false); + } + + public static T LastOrDefault(this IEnumerable source) { + return LastOrDefault(source, Funcs.True, true); + } + + public static T LastOrDefault(this IEnumerable source, Func predicate) { + return LastOrDefault(source, predicate, true); + } + + #endregion + + #region Max + + public static int Max(this IEnumerable source) { + return GenProc(source, (a, b) => Math.Max(a, b), false); + } + + public static int? Max(this IEnumerable source) { + return GenProcNullable(source, (a, b) => Math.Max(a, b)); + } + + public static long Max(this IEnumerable source) { + return GenProc(source, (a, b) => Math.Max(a, b), false); + } + + public static long? Max(this IEnumerable source) { + return GenProcNullable(source, (a, b) => Math.Max(a, b)); + } + + public static float Max(this IEnumerable source) { + return GenProc(source, (a, b) => Math.Max(a, b), false); + } + + public static float? Max(this IEnumerable source) { + return GenProcNullable(source, (a, b) => Math.Max(a, b)); + } + + public static double Max(this IEnumerable source) { + return GenProc(source, (a, b) => Math.Max(a, b), false); + } + + public static double? Max(this IEnumerable source) { + return GenProcNullable(source, (a, b) => Math.Max(a, b)); + } + + public static Decimal Max(this IEnumerable source) { + throw new NotImplementedException(); + } + + public static Decimal? Max(this IEnumerable source) { + throw new NotImplementedException(); + } + + public static T Max(this IEnumerable source) { + Comparer comparer = Comparer.Default; + return GenProc(source, (a, b) => comparer.Compare(a, b) > 0 ? a : b, true); + } + + public static TResult Max(this IEnumerable source, Func selector) { + return Max(source.Select(selector)); + } + + public static int Max(this IEnumerable source, Func selector) { + return Max(source.Select(selector)); + } + + public static int? Max(this IEnumerable source, Func selector) { + return Max(source.Select(selector)); + } + + public static long Max(this IEnumerable source, Func selector) { + return Max(source.Select(selector)); + } + + public static long? Max(this IEnumerable source, Func selector) { + return Max(source.Select(selector)); + } + + public static float Max(this IEnumerable source, Func selector) { + return Max(source.Select(selector)); + } + + public static float? Max(this IEnumerable source, Func selector) { + return Max(source.Select(selector)); + } + + public static double Max(this IEnumerable source, Func selector) { + return Max(source.Select(selector)); + } + + public static double? Max(this IEnumerable source, Func selector) { + return Max(source.Select(selector)); + } + + public static Decimal Max(this IEnumerable source, Func selector) { + return Max(source.Select(selector)); + } + + public static Decimal? Max(this IEnumerable source, Func selector) { + return Max(source.Select(selector)); + } + + #endregion + + #region Min + + public static int Min(this IEnumerable source) { + return GenProc(source, (a, b) => Math.Min(a, b), false); + } + + public static int? Min(this IEnumerable source) { + return GenProcNullable(source, (a, b) => Math.Min(a, b)); + } + + public static long Min(this IEnumerable source) { + return GenProc(source, (a, b) => Math.Min(a, b), false); + } + + public static long? Min(this IEnumerable source) { + return GenProcNullable(source, (a, b) => Math.Min(a, b)); + } + + public static float Min(this IEnumerable source) { + return GenProc(source, (a, b) => Math.Min(a, b), false); + } + + public static float? Min(this IEnumerable source) { + return GenProcNullable(source, (a, b) => Math.Min(a, b)); + } + + public static double Min(this IEnumerable source) { + return GenProc(source, (a, b) => Math.Min(a, b), false); + } + + public static double? Min(this IEnumerable source) { + return GenProcNullable(source, (a, b) => Math.Min(a, b)); + } + + public static Decimal Min(this IEnumerable source) { + throw new NotImplementedException(); + } + + public static Decimal? Min(this IEnumerable source) { + throw new NotImplementedException(); + } + + public static T Min(this IEnumerable source) { + Comparer comparer = Comparer.Default; + return GenProc(source, (a, b) => comparer.Compare(a, b) < 0 ? a : b, true); + } + + public static TResult Min(this IEnumerable source, Func selector) { + return Min(source.Select(selector)); + } + + public static int Min(this IEnumerable source, Func selector) { + return Min(source.Select(selector)); + } + + public static int? Min(this IEnumerable source, Func selector) { + return Min(source.Select(selector)); + } + + public static long Min(this IEnumerable source, Func selector) { + return Min(source.Select(selector)); + } + + public static long? Min(this IEnumerable source, Func selector) { + return Min(source.Select(selector)); + } + + public static float Min(this IEnumerable source, Func selector) { + return Min(source.Select(selector)); + } + + public static float? Min(this IEnumerable source, Func selector) { + return Min(source.Select(selector)); + } + + public static double Min(this IEnumerable source, Func selector) { + return Min(source.Select(selector)); + } + + public static double? Min(this IEnumerable source, Func selector) { + return Min(source.Select(selector)); + } + + public static Decimal Min(this IEnumerable source, Func selector) { + return Min(source.Select(selector)); + } + + public static Decimal? Min(this IEnumerable source, Func selector) { + return Min(source.Select(selector)); + } + + private static T GenProc(IEnumerable source, Func fn, bool allowEmpty) { + Check(source); + using (var en = source.GetEnumerator()) { + if (!en.MoveNext()) { + if (allowEmpty) { + return default(T); + } else { + throw new InvalidOperationException(); + } + } + T value = en.Current; + while (en.MoveNext()) { + value = fn(value, en.Current); + } + return value; + } + } + + private static T? GenProcNullable(IEnumerable source, Func fn) where T : struct { + T? value = null; + foreach (T? item in source) { + if (value == null) { + value = item; + } else if (item != null) { + value = fn(value.Value, item.Value); + } + } + return value; + } + + #endregion + + #region OfType + + public static IEnumerable OfType(this IEnumerable source) { + Check(source); + return OfTypeIterator(source); + } + + private static IEnumerable OfTypeIterator(IEnumerable source) { + foreach (object item in source) { + if (item is T) { + yield return (T)item; + } + } + } + + #endregion + + #region OrderBy, OrderByDescending + + public static IOrderedEnumerable OrderBy( + this IEnumerable source, + Func selector, + IComparer comparer) { + Check(source, selector); + return new OrderedEnumerable(source, selector, comparer, true); + } + + public static IOrderedEnumerable OrderBy( + this IEnumerable source, + Func selector) { + Check(source, selector); + return new OrderedEnumerable(source, selector, null, true); + } + + public static IOrderedEnumerable OrderByDescending( + this IEnumerable source, + Func selector, + IComparer comparer) { + Check(source, selector); + return new OrderedEnumerable(source, selector, comparer, false); + } + + public static IOrderedEnumerable OrderByDescending( + this IEnumerable source, + Func selector) { + Check(source, selector); + return new OrderedEnumerable(source, selector, null, false); + } + + #endregion + + #region Range + + public static IEnumerable Range(int start, int count) { + if (count < 0) { + throw new ArgumentOutOfRangeException("count"); + } + return RangeIterator(start, count); + } + + private static IEnumerable RangeIterator(int start, int count) { + int end = start + count; + for (int i = start; i < end; i++) { + yield return i; + } + } + + #endregion + + #region Repeat + + public static IEnumerable Repeat(TResult element, int count) { + if (count < 0) { + throw new ArgumentOutOfRangeException("count"); + } + return RepeatIterator(element, count); + } + + private static IEnumerable RepeatIterator(TResult element, int count) { + for (int i = 0; i < count; i++) { + yield return element; + } + } + + #endregion + + #region Reverse + + public static IEnumerable Reverse(this IEnumerable source) { + Check(source); + IList list = source as IList ?? new List(source); + return ReverseIterator(list); + } + + private static IEnumerable ReverseIterator(IList source) { + for (int i = source.Count - 1; i >= 0; i--) { + yield return source[i]; + } + } + + #endregion + + #region Select + + public static IEnumerable Select + (this IEnumerable source, Func selector) { + Check(source, selector); + return SelectIterator(source, selector); + } + + private static IEnumerable SelectIterator + (IEnumerable source, Func selector) { + foreach (T item in source) { + yield return selector(item); + } + } + + public static IEnumerable Select + (this IEnumerable source, Func selector) { + Check(source, selector); + return SelectIterator(source, selector); + } + + private static IEnumerable SelectIterator + (IEnumerable source, Func selector) { + int count = 0; + foreach (T item in source) { + yield return selector(item, count); + count++; + } + } + + #endregion + + #region SelectMany + + public static IEnumerable SelectMany + (this IEnumerable source, Func> selector) { + return source.SelectMany((s, i) => selector(s)); + } + + public static IEnumerable SelectMany + (this IEnumerable source, Func> selector) { + return source.SelectMany(selector, (s, c) => c); + } + + public static IEnumerable SelectMany + (this IEnumerable source, Func> collectionSelector, + Func resultSelector) { + return source.SelectMany((s, i) => collectionSelector(s), resultSelector); + } + + public static IEnumerable SelectMany + (this IEnumerable source, Func> collectionSelector, + Func resultSelector) { + Check(source, collectionSelector, resultSelector); + return SelectManyIterator(source, collectionSelector, resultSelector); + } + + private static IEnumerable SelectManyIterator + (IEnumerable source, Func> collectionSelector, + Func resultSelector) { + int count = 0; + foreach (TSource item in source) { + foreach (TCollection col in collectionSelector(item, count)) { + yield return resultSelector(item, col); + } + count++; + } + } + + #endregion + + #region SequenceEqual + + public static bool SequenceEqual(this IEnumerable first, IEnumerable second) { + return first.SequenceEqual(second, null); + } + + public static bool SequenceEqual(this IEnumerable first, IEnumerable second, IEqualityComparer comparer) { + Check(first, second); + if (comparer == null) { + comparer = EqualityComparer.Default; + } + using (IEnumerator en1 = first.GetEnumerator(), en2 = second.GetEnumerator()) { + while (en1.MoveNext()) { + if (!en2.MoveNext()) { + return false; + } + if (!comparer.Equals(en1.Current, en2.Current)) { + return false; + } + } + return !en2.MoveNext(); + } + } + + #endregion + + #region Skip + + public static IEnumerable Skip(this IEnumerable source, int count) { + Check(source); + return SkipIterator(source, count); + } + + private static IEnumerable SkipIterator(IEnumerable source, int count) { + foreach (T item in source) { + if (count <= 0) { + yield return item; + } + count--; + } + } + + #endregion + + #region SkipWhile + + public static IEnumerable SkipWhile(this IEnumerable source, Func predicate) { + Check(source, predicate); + return SkipWhileIterator(source, predicate); + } + + public static IEnumerable SkipWhileIterator(IEnumerable source, Func predicate) { + bool skip = true; + foreach (T item in source) { + if (skip) { + if (!predicate(item)) { + skip = false; + yield return item; + } + } else { + yield return item; + } + } + } + + public static IEnumerable SkipWhile(this IEnumerable source, Func predicate) { + Check(source, predicate); + return SkipWhileIterator(source, predicate); + } + + public static IEnumerable SkipWhileIterator(IEnumerable source, Func predicate) { + bool skip = true; + int count = 0; + foreach (T item in source) { + if (skip) { + if (!predicate(item, count)) { + skip = false; + yield return item; + } + } else { + yield return item; + } + count++; + } + } + + #endregion + + #region Take + + public static IEnumerable Take(this IEnumerable source, int count) { + Check(source); + return TakeIterator(source, count); + } + + private static IEnumerable TakeIterator(IEnumerable source, int count) { + if (count <= 0) { + yield break; + } + foreach (T item in source) { + yield return item; + count--; + if (count == 0) { + yield break; + } + } + } + + #endregion + + #region TakeWhile + + public static IEnumerable TakeWhile(this IEnumerable source, Func predicate) { + Check(source, predicate); + return TakeWhileIterator(source, predicate); + } + + private static IEnumerable TakeWhileIterator(IEnumerable source, Func predicate) { + foreach (T item in source) { + if (!predicate(item)) { + yield break; + } + yield return item; + } + } + + public static IEnumerable TakeWhile(this IEnumerable source, Func predicate) { + Check(source, predicate); + return TakeWhileIterator(source, predicate); + } + + private static IEnumerable TakeWhileIterator(IEnumerable source, Func predicate) { + int count = 0; + foreach (T item in source) { + if (!predicate(item, count)) { + yield break; + } + yield return item; + count++; + } + } + + #endregion + + #region ThenBy, ThenByDescending + + //public static IOrderedEnumerable ThenBy(this IOrderedEnumerable source, + // Func keySelector) { + // return source.ThenBy(keySelector, null); + //} + + //public static IOrderedEnumerable ThenBy(this IOrderedEnumerable source, + // Func keySelector, IComparer comparer) { + // Check(source, keySelector); + // return source.CreateOrderedEnumerable(keySelector, comparer, false); + //} + + //public static IOrderedEnumerable ThenByDescending(this IOrderedEnumerable source, + // Func keySelector) { + // return source.ThenByDescending(keySelector, null); + //} + + //public static IOrderedEnumerable ThenByDescending(this IOrderedEnumerable source, + // Func keySelector, IComparer comparer) { + // Check(source, keySelector); + // return source.CreateOrderedEnumerable(keySelector, comparer, true); + //} + + #endregion + + #region Union + + public static IEnumerable Union(this IEnumerable first, IEnumerable second) { + return Union(first, second, null); + } + + public static IEnumerable Union + (this IEnumerable first, IEnumerable second, IEqualityComparer comparer) { + // Check not needed, as Concat() will do it + return DistinctIterator(first.Concat(second), comparer); + } + + #endregion + + #region Where + + public static IEnumerable Where + (this IEnumerable source, Func predicate) { + Check(source, predicate); + return WhereIterator(source, predicate); + } + + private static IEnumerable WhereIterator + (IEnumerable source, Func predicate) { + foreach (T item in source) { + if (predicate(item)) { + yield return item; + } + } + } + + public static IEnumerable Where + (this IEnumerable source, Func predicate) { + Check(source, predicate); + return WhereIterator(source, predicate); + } + + private static IEnumerable WhereIterator + (IEnumerable source, Func predicate) { + int count = 0; + foreach (T item in source) { + if (predicate(item, count)) { + yield return item; + } + count++; + } + } + + #endregion + + #region ToList, ToArray, ToDictionary, ToLookup + + public static List ToList(this IEnumerable source) { + Check(source); + return new List(source); + } + + public static T[] ToArray(this IEnumerable source) { + Check(source); + ICollection collection = + source as ICollection ?? new List(source); + T[] result = new T[collection.Count]; + collection.CopyTo(result, 0); + return result; + } + + public static Dictionary ToDictionary( + this IEnumerable source, Func keySelector) { + return source.ToDictionary(keySelector, Funcs.Identity, null); + } + + public static Dictionary ToDictionary( + this IEnumerable source, Func keySelector, + IEqualityComparer comparer) { + return source.ToDictionary(keySelector, Funcs.Identity, comparer); + } + + public static Dictionary ToDictionary( + this IEnumerable source, Func keySelector, + Func elementSelector) { + return source.ToDictionary(keySelector, elementSelector, null); + } + + public static Dictionary ToDictionary( + this IEnumerable source, Func keySelector, + Func elementSelector, IEqualityComparer comparer) { + Check(source, keySelector, elementSelector); + Dictionary dict = new Dictionary(comparer); + foreach (TSource item in source) { + dict.Add(keySelector(item), elementSelector(item)); + } + return dict; + } + + public static ILookup ToLookup( + this IEnumerable source, Func keySelector) { + return source.ToLookup(keySelector, Funcs.Identity, null); + } + + public static ILookup ToLookup( + this IEnumerable source, Func keySelector, + IEqualityComparer comparer) { + return source.ToLookup(keySelector, Funcs.Identity, comparer); + } + + public static ILookup ToLookup( + this IEnumerable source, Func keySelector, + Func elementSelector) { + return source.ToLookup(keySelector, elementSelector, null); + } + + public static ILookup ToLookup( + this IEnumerable source, Func keySelector, + Func elementSelector, IEqualityComparer comparer) { + Check(source, keySelector, elementSelector); + var lookup = new Dictionary>(comparer); + foreach (TSource item in source) { + TKey key = keySelector(item); + if (key == null) { + throw new ArgumentNullException(); + } + List list; + if (!lookup.TryGetValue(key, out list)) { + list = new List(); + lookup.Add(key, list); + } + list.Add(elementSelector(item)); + } + return new Lookup(lookup); + } + + #endregion + + #region Checks + + private static void Check(object o) { + if (o == null) { + throw new ArgumentNullException(); + } + } + + private static void Check(object o1, object o2) { + if (o1 == null || o2 == null) { + throw new ArgumentNullException(); + } + } + + private static void Check(object o1, object o2, object o3) { + if (o1 == null || o2 == null || o3 == null) { + throw new ArgumentNullException(); + } + } + + #endregion + + } +} diff --git a/System.Core/System.Linq/Grouping.cs b/System.Core/System.Linq/Grouping.cs new file mode 100644 index 0000000..d0d2bd5 --- /dev/null +++ b/System.Core/System.Linq/Grouping.cs @@ -0,0 +1,53 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Collections; + +namespace System.Linq { + class Grouping : IGrouping { + + public Grouping(TKey key, IEnumerable elements) { + this.key = key; + this.elements = elements; + } + + private TKey key; + private IEnumerable elements; + + public TKey Key { + get { + return this.key; + } + } + + public IEnumerator GetEnumerator() { + return this.elements.GetEnumerator(); + } + + IEnumerator System.Collections.IEnumerable.GetEnumerator() { + return this.elements.GetEnumerator(); + } + + } +} diff --git a/System.Core/System.Linq/IGrouping.cs b/System.Core/System.Linq/IGrouping.cs new file mode 100644 index 0000000..e38769d --- /dev/null +++ b/System.Core/System.Linq/IGrouping.cs @@ -0,0 +1,33 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Collections; + +namespace System.Linq { + public interface IGrouping : IEnumerable, IEnumerable { + + TKey Key { get; } + + } +} diff --git a/System.Core/System.Linq/ILookup.cs b/System.Core/System.Linq/ILookup.cs new file mode 100644 index 0000000..ffb93e6 --- /dev/null +++ b/System.Core/System.Linq/ILookup.cs @@ -0,0 +1,35 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Collections; + +namespace System.Linq { + public interface ILookup : IEnumerable>, IEnumerable { + + bool Contains(TKey key); + int Count { get; } + IEnumerable this[TKey key] { get; } + + } +} diff --git a/System.Core/System.Linq/IOrderedEnumerable.cs b/System.Core/System.Linq/IOrderedEnumerable.cs new file mode 100644 index 0000000..3b731ba --- /dev/null +++ b/System.Core/System.Linq/IOrderedEnumerable.cs @@ -0,0 +1,35 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace System.Linq { + + public interface IOrderedEnumerable : IEnumerable { + + IOrderedEnumerable CreateOrderedEnumerable( + Func selector, IComparer comparer, bool descending); + + } + +} diff --git a/System.Core/System.Linq/Lookup.cs b/System.Core/System.Linq/Lookup.cs new file mode 100644 index 0000000..7bdff42 --- /dev/null +++ b/System.Core/System.Linq/Lookup.cs @@ -0,0 +1,64 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Collections; +using System.Linq; +using System.Text; + +namespace System.Linq { + public class Lookup : ILookup { + + private Dictionary> lookup; + + internal Lookup(Dictionary> data) { + this.lookup = new Dictionary>(data.Comparer); + foreach (var item in data) { + this.lookup.Add(item.Key, new Grouping(item.Key, item.Value)); + } + } + + public bool Contains(TKey key) { + return this.lookup.ContainsKey(key); + } + + public int Count { + get { + return this.lookup.Count; + } + } + + public IEnumerable this[TKey key] { + get { + return this.lookup[key]; + } + } + + public IEnumerator> GetEnumerator() { + return this.lookup.Values.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() { + return this.lookup.Values.GetEnumerator(); + } + + } +} diff --git a/System.Core/System.Linq/OrderedEnumerable.cs b/System.Core/System.Linq/OrderedEnumerable.cs new file mode 100644 index 0000000..c955612 --- /dev/null +++ b/System.Core/System.Linq/OrderedEnumerable.cs @@ -0,0 +1,159 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Collections; + +#if LOCALTEST +namespace System_.Linq { +#else +namespace System.Linq { +#endif + class OrderedEnumerable : IOrderedEnumerable { + + private class QuickSort { + + public QuickSort(IEnumerable source, + Func selector, IComparer comparer, bool ascending) { + this.comparer = comparer; + this.ascending = ascending; + this.elements = source.ToArray(); + int len = this.elements.Length; + this.keys = new TKey[len]; + this.order = new int[len]; + for (int i = 0; i < len; i++) { + this.keys[i] = selector(this.elements[i]); + this.order[i] = i; + } + } + + private IComparer comparer; + private bool ascending; + private TElement[] elements; + private TKey[] keys; + private int[] order; + private const int INSERTION_SORT_SIZE = 6; + + private void Swap(int idx0, int idx1) { + if (idx0 != idx1) { + int temp = this.order[idx0]; + this.order[idx0] = this.order[idx1]; + this.order[idx1] = temp; + } + } + + private void PerformSort(int startIdx, int endIdx) { + // Special cases if lenth is 0, 1 or less than or equal to INSERTION_SORT_SIZE + int length = endIdx - startIdx + 1; + if (length <= 1) { + return; + } + if (length <= INSERTION_SORT_SIZE) { + // Perform insertion sort + for (int idx = startIdx + 1; idx <= endIdx; idx++) { + int i, orderIdx = this.order[idx]; + TKey key = this.keys[orderIdx]; + for (i = idx; i > startIdx && this.comparer.Compare(key, this.keys[this.order[i - 1]]) < 0; i--) { + this.order[i] = this.order[i - 1]; + } + this.order[i] = orderIdx; + } + return; + } + // Perform quick-sort + // Find the pivot value + int pivotIdx; + int midIdx = (startIdx + endIdx) / 2; + TKey pivot0 = this.keys[this.order[startIdx]]; + TKey pivot1 = this.keys[this.order[midIdx]]; + TKey pivot2 = this.keys[this.order[endIdx]]; + bool _0lessthan1 = this.comparer.Compare(pivot0, pivot1) < 0; + bool _1lessthan2 = this.comparer.Compare(pivot1, pivot2) < 0; + if (_0lessthan1 == _1lessthan2) { + pivotIdx = midIdx; + } else { + bool _0lessthan2 = this.comparer.Compare(pivot0, pivot2) < 0; + pivotIdx = (_1lessthan2 == _0lessthan2) ? startIdx : endIdx; + } + TKey pivot = this.keys[this.order[pivotIdx]]; + //Console.WriteLine("S={4},M={5},E={6} p0={1},p1={2},p2={3} Pivot = {0}", pivot, pivot0, pivot1, pivot2, startIdx, midIdx, endIdx); + // Perform sort + this.Swap(pivotIdx, endIdx); + int storeIndex = startIdx; + for (int i = startIdx; i < endIdx; i++) { + TKey value = this.keys[this.order[i]]; + // if value <= pivot + if (this.comparer.Compare(value, pivot) <= 0) { + this.Swap(storeIndex, i); + storeIndex++; + } + } + this.Swap(storeIndex, endIdx); + this.PerformSort(startIdx, storeIndex - 1); + this.PerformSort(storeIndex + 1, endIdx); + } + + public IEnumerable Sort() { + int len = this.elements.Length; + this.PerformSort(0, len - 1); + if (this.ascending) { + for (int i = 0; i < len; i++) { + yield return this.elements[this.order[i]]; + } + } else { + for (int i = len - 1; i >= 0; i--) { + yield return this.elements[this.order[i]]; + } + } + } + + } + + public OrderedEnumerable(IEnumerable source, + Func selector, IComparer comparer, bool ascending) { + this.source = source; + this.selector = selector; + this.comparer = comparer ?? Comparer.Default; + this.ascending = ascending; + } + + public IOrderedEnumerable CreateOrderedEnumerable( + Func selector, IComparer comparer, bool descending) { + throw new NotImplementedException(); + } + + private IEnumerable source; + private Func selector; + private IComparer comparer; + private bool ascending; + + public IEnumerator GetEnumerator() { + QuickSort sort = new QuickSort(this.source, this.selector, this.comparer, this.ascending); + return sort.Sort().GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() { + return this.GetEnumerator(); + } + + } +} diff --git a/System.Core/System.Runtime.CompilerServices/ExtensionAttribute.cs b/System.Core/System.Runtime.CompilerServices/ExtensionAttribute.cs new file mode 100644 index 0000000..8552db8 --- /dev/null +++ b/System.Core/System.Runtime.CompilerServices/ExtensionAttribute.cs @@ -0,0 +1,32 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace System.Runtime.CompilerServices { + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)] + public sealed class ExtensionAttribute : Attribute { + } + +} diff --git a/System.Core/System/Action.cs b/System.Core/System/Action.cs new file mode 100644 index 0000000..b7a86c1 --- /dev/null +++ b/System.Core/System/Action.cs @@ -0,0 +1,28 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +namespace System { + + public delegate void Action(T arg); + public delegate void Action(T1 arg1, T2 arg2); + public delegate void Action(T1 arg1, T2 arg2, T3 arg3); + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4); + +} diff --git a/System.Core/System/Func.cs b/System.Core/System/Func.cs new file mode 100644 index 0000000..0848ea9 --- /dev/null +++ b/System.Core/System/Func.cs @@ -0,0 +1,29 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +namespace System { + + public delegate TResult Func(); + public delegate TResult Func(T arg); + public delegate TResult Func(T1 arg1, T2 arg2); + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3); + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4); + +} diff --git a/System.Drawing/Properties/AssemblyInfo.cs b/System.Drawing/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..07406ef --- /dev/null +++ b/System.Drawing/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("System.Drawing")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Docobo")] +[assembly: AssemblyProduct("System.Drawing")] +[assembly: AssemblyCopyright("Copyright © Docobo 2007")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("d9baba9f-5d04-4f14-b992-e6439f76f8f1")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/System.Drawing/System.Drawing.Drawing2D/HatchBrush.cs b/System.Drawing/System.Drawing.Drawing2D/HatchBrush.cs new file mode 100644 index 0000000..1787d99 --- /dev/null +++ b/System.Drawing/System.Drawing.Drawing2D/HatchBrush.cs @@ -0,0 +1,58 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Drawing.Drawing2D { + public sealed class HatchBrush : Brush { + + public HatchBrush(HatchStyle hatchStyle, Color foreColor, Color backColor) { + this.hatchStyle = hatchStyle; + this.foreCol = foreColor; + this.backCol = backColor; + base.native = LibIGraph.CreateBrush_Hatch(hatchStyle, foreCol.ToArgb(), backCol.ToArgb()); + } + + public HatchBrush(HatchStyle hatchStyle, Color foreColor) : this(hatchStyle, foreColor, Color.Black) { } + + private HatchStyle hatchStyle; + private Color foreCol, backCol; + + public HatchStyle HatchStyle { + get { + return this.hatchStyle; + } + } + + public Color ForegroundColor { + get { + return this.foreCol; + } + } + + public Color BackgroundColor { + get { + return this.backCol; + } + } + } +} diff --git a/System.Drawing/System.Drawing.Drawing2D/HatchStyle.cs b/System.Drawing/System.Drawing.Drawing2D/HatchStyle.cs new file mode 100644 index 0000000..9668542 --- /dev/null +++ b/System.Drawing/System.Drawing.Drawing2D/HatchStyle.cs @@ -0,0 +1,84 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Drawing.Drawing2D { + public enum HatchStyle { + BackwardDiagonal = 3, + Cross = LargeGrid, + DarkDownwardDiagonal = 20, + DarkHorizontal = 29, + DarkUpwardDiagonal = 21, + DarkVertical = 28, + DashedDownwardDiagonal = 30, + DashedHorizontal = 32, + DashedUpwardDiagonal = 31, + DashedVertical = 33, + DiagonalBrick = 38, + DiagonalCross = 5, + Divot = 42, + DottedDiamond = 44, + DottedGrid = 43, + ForwardDiagonal = 2, + Horizontal = 0, + HorizontalBrick = 39, + LargeCheckerBoard = 50, + LargeConfetti = 35, + LargeGrid = 4, + LightDownwardDiagonal = 18, + LightHorizontal = 25, + LightUpwardDiagonal = 19, + LightVertical = 24, + Max = 4, + Min = 0, + NarrowHorizontal = 27, + NarrowVertical = 26, + OutlinedDiamond = 51, + Percent05 = 6, + Percent10 = 7, + Percent20 = 8, + Percent25 = 9, + Percent30 = 10, + Percent40 = 11, + Percent50 = 12, + Percent60 = 13, + Percent70 = 14, + Percent75 = 15, + Percent80 = 16, + Percent90 = 17, + Plaid = 41, + Shingle = 45, + SmallCheckerBoard = 49, + SmallConfetti = 34, + SmallGrid = 48, + SolidDiamond = 52, + Sphere = 47, + Trellis = 46, + Vertical = 1, + Wave = 37, + Weave = 40, + WideDownwardDiagonal = 22, + WideUpwardDiagonal = 23, + ZigZag = 36 + } +} diff --git a/System.Drawing/System.Drawing.Drawing2D/LinearGradientBrush.cs b/System.Drawing/System.Drawing.Drawing2D/LinearGradientBrush.cs new file mode 100644 index 0000000..e24eaf8 --- /dev/null +++ b/System.Drawing/System.Drawing.Drawing2D/LinearGradientBrush.cs @@ -0,0 +1,39 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Drawing.Drawing2D { + public sealed class LinearGradientBrush : Brush { + + public LinearGradientBrush(Point point1, Point point2, Color col1, Color col2) { + base.native = LibIGraph.CreateBrush_LinearGradient + (point1.X, point1.Y, point2.X, point2.Y, col1.ToArgb(), col2.ToArgb()); + } + + public LinearGradientBrush(PointF point1, PointF point2, Color col1, Color col2) { + base.native = LibIGraph.CreateBrush_LinearGradient + ((int)point1.X, (int)point1.Y, (int)point2.X, (int)point2.Y, col1.ToArgb(), col2.ToArgb()); + } + + } +} diff --git a/System.Drawing/System.Drawing.Drawing2D/WrapMode.cs b/System.Drawing/System.Drawing.Drawing2D/WrapMode.cs new file mode 100644 index 0000000..a51f0fa --- /dev/null +++ b/System.Drawing/System.Drawing.Drawing2D/WrapMode.cs @@ -0,0 +1,33 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Drawing.Drawing2D { + public enum WrapMode { + Tile = 0, + TileFlipX = 1, + TileFlipY = 2, + TileFlipXY = 3, + Clamp = 4 + } +} diff --git a/System.Drawing/System.Drawing.Imaging/PixelFormat.cs b/System.Drawing/System.Drawing.Imaging/PixelFormat.cs new file mode 100644 index 0000000..02c0305 --- /dev/null +++ b/System.Drawing/System.Drawing.Imaging/PixelFormat.cs @@ -0,0 +1,47 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +namespace System.Drawing.Imaging { + public enum PixelFormat { + Alpha = 262144, + Canonical = 2097152, + DontCare = 0, + Extended = 1048576, + Format16bppArgb1555 = 397319, + Format16bppGrayScale = 1052676, + Format16bppRgb555 = 135173, + Format16bppRgb565 = 135174, + Format1bppIndexed = 196865, + Format24bppRgb = 137224, + Format32bppArgb = 2498570, + Format32bppPArgb = 925707, + Format32bppRgb = 139273, + Format48bppRgb = 1060876, + Format4bppIndexed = 197634, + Format64bppArgb = 3424269, + Format64bppPArgb = 1851406, + Format8bppIndexed = 198659, + Gdi = 131072, + Indexed = 65536, + Max = 15, + PAlpha = 524288, + Undefined = 0, + } +} diff --git a/System.Drawing/System.Drawing.Text/TextRenderingHint.cs b/System.Drawing/System.Drawing.Text/TextRenderingHint.cs new file mode 100644 index 0000000..938b87f --- /dev/null +++ b/System.Drawing/System.Drawing.Text/TextRenderingHint.cs @@ -0,0 +1,34 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Drawing.Text { + public enum TextRenderingHint { + AntiAlias = 4, + AntiAliasGridFit = 3, + ClearTypeGridFit = 5, + SingleBitPerPixel = 2, + SingleBitPerPixelGridFit = 1, + SystemDefault = 0 + } +} diff --git a/System.Drawing/System.Drawing.csproj b/System.Drawing/System.Drawing.csproj new file mode 100644 index 0000000..2b03d24 --- /dev/null +++ b/System.Drawing/System.Drawing.csproj @@ -0,0 +1,130 @@ + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {0F7F935F-E3F5-40AD-BD22-0BA43721560F} + Library + Properties + System.Drawing + System.Drawing + + + + + 2.0 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + 512 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + 512 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + False + .NET Framework Client Profile + false + + + False + .NET Framework 2.0 %28x86%29 + true + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + false + + + False + .NET Framework 3.5 SP1 + false + + + + + + copy $(TargetPath) $(SolutionDir)\Builds\$(ConfigurationName)\ + + \ No newline at end of file diff --git a/System.Drawing/System.Drawing/Bitmap.cs b/System.Drawing/System.Drawing/Bitmap.cs new file mode 100644 index 0000000..122a819 --- /dev/null +++ b/System.Drawing/System.Drawing/Bitmap.cs @@ -0,0 +1,53 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing.Imaging; + +namespace System.Drawing { + public sealed class Bitmap : Image { + + public Bitmap(int width, int height) + : this(width, height, PixelFormat.Format32bppArgb) { } + + public Bitmap(int width, int height, PixelFormat pixelFormat) { + base.native = LibIGraph._CreateBitmap(width, height, pixelFormat); + if (base.native == IntPtr.Zero) { + throw new ArgumentException(); + } + base.width = width; + base.height = height; + base.pixelFormat = pixelFormat; + } + + internal Bitmap(IntPtr native, int width, int height, PixelFormat pixelFormat) { + if (native == IntPtr.Zero) { + throw new ArgumentException("Cannot create Bitmap"); + } + base.native = native; + base.width = width; + base.height = height; + base.pixelFormat = pixelFormat; + } + + } +} diff --git a/System.Drawing/System.Drawing/Brush.cs b/System.Drawing/System.Drawing/Brush.cs new file mode 100644 index 0000000..eb4152e --- /dev/null +++ b/System.Drawing/System.Drawing/Brush.cs @@ -0,0 +1,47 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Drawing { + public abstract class Brush : MarshalByRefObject, IDisposable { + + internal IntPtr native = IntPtr.Zero; + + ~Brush() { + this.Dispose(false); + } + + public void Dispose() { + this.Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) { + if (this.native != IntPtr.Zero) { + LibIGraph.DisposeBrush(this.native); + this.native = IntPtr.Zero; + } + } + + } +} diff --git a/System.Drawing/System.Drawing/Brushes.cs b/System.Drawing/System.Drawing/Brushes.cs new file mode 100644 index 0000000..79d447e --- /dev/null +++ b/System.Drawing/System.Drawing/Brushes.cs @@ -0,0 +1,1443 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Drawing { + public static class Brushes { + + static SolidBrush aliceBlue; + static SolidBrush antiqueWhite; + static SolidBrush aqua; + static SolidBrush aquamarine; + static SolidBrush azure; + static SolidBrush beige; + static SolidBrush bisque; + static SolidBrush black; + static SolidBrush blanchedAlmond; + static SolidBrush blue; + static SolidBrush blueViolet; + static SolidBrush brown; + static SolidBrush burlyWood; + static SolidBrush cadetBlue; + static SolidBrush chartreuse; + static SolidBrush chocolate; + static SolidBrush coral; + static SolidBrush cornflowerBlue; + static SolidBrush cornsilk; + static SolidBrush crimson; + static SolidBrush cyan; + static SolidBrush darkBlue; + static SolidBrush darkCyan; + static SolidBrush darkGoldenrod; + static SolidBrush darkGray; + static SolidBrush darkGreen; + static SolidBrush darkKhaki; + static SolidBrush darkMagenta; + static SolidBrush darkOliveGreen; + static SolidBrush darkOrange; + static SolidBrush darkOrchid; + static SolidBrush darkRed; + static SolidBrush darkSalmon; + static SolidBrush darkSeaGreen; + static SolidBrush darkSlateBlue; + static SolidBrush darkSlateGray; + static SolidBrush darkTurquoise; + static SolidBrush darkViolet; + static SolidBrush deepPink; + static SolidBrush deepSkyBlue; + static SolidBrush dimGray; + static SolidBrush dodgerBlue; + static SolidBrush firebrick; + static SolidBrush floralWhite; + static SolidBrush forestGreen; + static SolidBrush fuchsia; + static SolidBrush gainsboro; + static SolidBrush ghostWhite; + static SolidBrush gold; + static SolidBrush goldenrod; + static SolidBrush gray; + static SolidBrush green; + static SolidBrush greenYellow; + static SolidBrush honeydew; + static SolidBrush hotPink; + static SolidBrush indianRed; + static SolidBrush indigo; + static SolidBrush ivory; + static SolidBrush khaki; + static SolidBrush lavender; + static SolidBrush lavenderBlush; + static SolidBrush lawnGreen; + static SolidBrush lemonChiffon; + static SolidBrush lightBlue; + static SolidBrush lightCoral; + static SolidBrush lightCyan; + static SolidBrush lightGoldenrodYellow; + static SolidBrush lightGray; + static SolidBrush lightGreen; + static SolidBrush lightPink; + static SolidBrush lightSalmon; + static SolidBrush lightSeaGreen; + static SolidBrush lightSkyBlue; + static SolidBrush lightSlateGray; + static SolidBrush lightSteelBlue; + static SolidBrush lightYellow; + static SolidBrush lime; + static SolidBrush limeGreen; + static SolidBrush linen; + static SolidBrush magenta; + static SolidBrush maroon; + static SolidBrush mediumAquamarine; + static SolidBrush mediumBlue; + static SolidBrush mediumOrchid; + static SolidBrush mediumPurple; + static SolidBrush mediumSeaGreen; + static SolidBrush mediumSlateBlue; + static SolidBrush mediumSpringGreen; + static SolidBrush mediumTurquoise; + static SolidBrush mediumVioletRed; + static SolidBrush midnightBlue; + static SolidBrush mintCream; + static SolidBrush mistyRose; + static SolidBrush moccasin; + static SolidBrush navajoWhite; + static SolidBrush navy; + static SolidBrush oldLace; + static SolidBrush olive; + static SolidBrush oliveDrab; + static SolidBrush orange; + static SolidBrush orangeRed; + static SolidBrush orchid; + static SolidBrush paleGoldenrod; + static SolidBrush paleGreen; + static SolidBrush paleTurquoise; + static SolidBrush paleVioletRed; + static SolidBrush papayaWhip; + static SolidBrush peachPuff; + static SolidBrush peru; + static SolidBrush pink; + static SolidBrush plum; + static SolidBrush powderBlue; + static SolidBrush purple; + static SolidBrush red; + static SolidBrush rosyBrown; + static SolidBrush royalBlue; + static SolidBrush saddleBrown; + static SolidBrush salmon; + static SolidBrush sandyBrown; + static SolidBrush seaGreen; + static SolidBrush seaShell; + static SolidBrush sienna; + static SolidBrush silver; + static SolidBrush skyBlue; + static SolidBrush slateBlue; + static SolidBrush slateGray; + static SolidBrush snow; + static SolidBrush springGreen; + static SolidBrush steelBlue; + static SolidBrush tan; + static SolidBrush teal; + static SolidBrush thistle; + static SolidBrush tomato; + static SolidBrush transparent; + static SolidBrush turquoise; + static SolidBrush violet; + static SolidBrush wheat; + static SolidBrush white; + static SolidBrush whiteSmoke; + static SolidBrush yellow; + static SolidBrush yellowGreen; + + // We intentionally do not set the is_modifiable=false flag on + // the brushes, to stay Microsoft compatible + + public static Brush AliceBlue { + get { + if (aliceBlue == null) { + aliceBlue = new SolidBrush(Color.AliceBlue); + } + return (aliceBlue); + } + } + + public static Brush AntiqueWhite { + get { + if (antiqueWhite == null) { + antiqueWhite = new SolidBrush(Color.AntiqueWhite); + } + return (antiqueWhite); + } + } + + public static Brush Aqua { + get { + if (aqua == null) { + aqua = new SolidBrush(Color.Aqua); + } + return (aqua); + } + } + + public static Brush Aquamarine { + get { + if (aquamarine == null) { + aquamarine = new SolidBrush(Color.Aquamarine); + } + return (aquamarine); + } + } + + public static Brush Azure { + get { + if (azure == null) { + azure = new SolidBrush(Color.Azure); + } + return (azure); + } + } + + public static Brush Beige { + get { + if (beige == null) { + beige = new SolidBrush(Color.Beige); + } + return (beige); + } + } + + public static Brush Bisque { + get { + if (bisque == null) { + bisque = new SolidBrush(Color.Bisque); + } + return (bisque); + } + } + + public static Brush Black { + get { + if (black == null) { + black = new SolidBrush(Color.Black); + } + return (black); + } + } + + public static Brush BlanchedAlmond { + get { + if (blanchedAlmond == null) { + blanchedAlmond = new SolidBrush(Color.BlanchedAlmond); + } + return (blanchedAlmond); + } + } + + public static Brush Blue { + get { + if (blue == null) { + blue = new SolidBrush(Color.Blue); + } + return (blue); + } + } + + public static Brush BlueViolet { + get { + if (blueViolet == null) { + blueViolet = new SolidBrush(Color.BlueViolet); + } + return (blueViolet); + } + } + + public static Brush Brown { + get { + if (brown == null) { + brown = new SolidBrush(Color.Brown); + } + return (brown); + } + } + + public static Brush BurlyWood { + get { + if (burlyWood == null) { + burlyWood = new SolidBrush(Color.BurlyWood); + } + return (burlyWood); + } + } + + public static Brush CadetBlue { + get { + if (cadetBlue == null) { + cadetBlue = new SolidBrush(Color.CadetBlue); + } + return (cadetBlue); + } + } + + public static Brush Chartreuse { + get { + if (chartreuse == null) { + chartreuse = new SolidBrush(Color.Chartreuse); + } + return (chartreuse); + } + } + + public static Brush Chocolate { + get { + if (chocolate == null) { + chocolate = new SolidBrush(Color.Chocolate); + } + return (chocolate); + } + } + + public static Brush Coral { + get { + if (coral == null) { + coral = new SolidBrush(Color.Coral); + } + return (coral); + } + } + + public static Brush CornflowerBlue { + get { + if (cornflowerBlue == null) { + cornflowerBlue = new SolidBrush(Color.CornflowerBlue); + } + return (cornflowerBlue); + } + } + + public static Brush Cornsilk { + get { + if (cornsilk == null) { + cornsilk = new SolidBrush(Color.Cornsilk); + } + return (cornsilk); + } + } + + public static Brush Crimson { + get { + if (crimson == null) { + crimson = new SolidBrush(Color.Crimson); + } + return (crimson); + } + } + + public static Brush Cyan { + get { + if (cyan == null) { + cyan = new SolidBrush(Color.Cyan); + } + return (cyan); + } + } + + public static Brush DarkBlue { + get { + if (darkBlue == null) { + darkBlue = new SolidBrush(Color.DarkBlue); + } + return (darkBlue); + } + } + + public static Brush DarkCyan { + get { + if (darkCyan == null) { + darkCyan = new SolidBrush(Color.DarkCyan); + } + return (darkCyan); + } + } + + public static Brush DarkGoldenrod { + get { + if (darkGoldenrod == null) { + darkGoldenrod = new SolidBrush(Color.DarkGoldenrod); + } + return (darkGoldenrod); + } + } + + public static Brush DarkGray { + get { + if (darkGray == null) { + darkGray = new SolidBrush(Color.DarkGray); + } + return (darkGray); + } + } + + public static Brush DarkGreen { + get { + if (darkGreen == null) { + darkGreen = new SolidBrush(Color.DarkGreen); + } + return (darkGreen); + } + } + + public static Brush DarkKhaki { + get { + if (darkKhaki == null) { + darkKhaki = new SolidBrush(Color.DarkKhaki); + } + return (darkKhaki); + } + } + + public static Brush DarkMagenta { + get { + if (darkMagenta == null) { + darkMagenta = new SolidBrush(Color.DarkMagenta); + } + return (darkMagenta); + } + } + + public static Brush DarkOliveGreen { + get { + if (darkOliveGreen == null) { + darkOliveGreen = new SolidBrush(Color.DarkOliveGreen); + } + return (darkOliveGreen); + } + } + + public static Brush DarkOrange { + get { + if (darkOrange == null) { + darkOrange = new SolidBrush(Color.DarkOrange); + } + return (darkOrange); + } + } + + public static Brush DarkOrchid { + get { + if (darkOrchid == null) { + darkOrchid = new SolidBrush(Color.DarkOrchid); + } + return (darkOrchid); + } + } + + public static Brush DarkRed { + get { + if (darkRed == null) { + darkRed = new SolidBrush(Color.DarkRed); + } + return (darkRed); + } + } + + public static Brush DarkSalmon { + get { + if (darkSalmon == null) { + darkSalmon = new SolidBrush(Color.DarkSalmon); + } + return (darkSalmon); + } + } + + public static Brush DarkSeaGreen { + get { + if (darkSeaGreen == null) { + darkSeaGreen = new SolidBrush(Color.DarkSeaGreen); + } + return (darkSeaGreen); + } + } + + public static Brush DarkSlateBlue { + get { + if (darkSlateBlue == null) { + darkSlateBlue = new SolidBrush(Color.DarkSlateBlue); + } + return (darkSlateBlue); + } + } + + public static Brush DarkSlateGray { + get { + if (darkSlateGray == null) { + darkSlateGray = new SolidBrush(Color.DarkSlateGray); + } + return (darkSlateGray); + } + } + + public static Brush DarkTurquoise { + get { + if (darkTurquoise == null) { + darkTurquoise = new SolidBrush(Color.DarkTurquoise); + } + return (darkTurquoise); + } + } + + public static Brush DarkViolet { + get { + if (darkViolet == null) { + darkViolet = new SolidBrush(Color.DarkViolet); + } + return (darkViolet); + } + } + + public static Brush DeepPink { + get { + if (deepPink == null) { + deepPink = new SolidBrush(Color.DeepPink); + } + return (deepPink); + } + } + + public static Brush DeepSkyBlue { + get { + if (deepSkyBlue == null) { + deepSkyBlue = new SolidBrush(Color.DeepSkyBlue); + } + return (deepSkyBlue); + } + } + + public static Brush DimGray { + get { + if (dimGray == null) { + dimGray = new SolidBrush(Color.DimGray); + } + return (dimGray); + } + } + + public static Brush DodgerBlue { + get { + if (dodgerBlue == null) { + dodgerBlue = new SolidBrush(Color.DodgerBlue); + } + return (dodgerBlue); + } + } + + public static Brush Firebrick { + get { + if (firebrick == null) { + firebrick = new SolidBrush(Color.Firebrick); + } + return (firebrick); + } + } + + public static Brush FloralWhite { + get { + if (floralWhite == null) { + floralWhite = new SolidBrush(Color.FloralWhite); + } + return (floralWhite); + } + } + + public static Brush ForestGreen { + get { + if (forestGreen == null) { + forestGreen = new SolidBrush(Color.ForestGreen); + } + return (forestGreen); + } + } + + public static Brush Fuchsia { + get { + if (fuchsia == null) { + fuchsia = new SolidBrush(Color.Fuchsia); + } + return (fuchsia); + } + } + + public static Brush Gainsboro { + get { + if (gainsboro == null) { + gainsboro = new SolidBrush(Color.Gainsboro); + } + return (gainsboro); + } + } + + public static Brush GhostWhite { + get { + if (ghostWhite == null) { + ghostWhite = new SolidBrush(Color.GhostWhite); + } + return (ghostWhite); + } + } + + public static Brush Gold { + get { + if (gold == null) { + gold = new SolidBrush(Color.Gold); + } + return (gold); + } + } + + public static Brush Goldenrod { + get { + if (goldenrod == null) { + goldenrod = new SolidBrush(Color.Goldenrod); + } + return (goldenrod); + } + } + + public static Brush Gray { + get { + if (gray == null) { + gray = new SolidBrush(Color.Gray); + } + return (gray); + } + } + + public static Brush Green { + get { + if (green == null) { + green = new SolidBrush(Color.Green); + } + return (green); + } + } + + public static Brush GreenYellow { + get { + if (greenYellow == null) { + greenYellow = new SolidBrush(Color.GreenYellow); + } + return (greenYellow); + } + } + + public static Brush Honeydew { + get { + if (honeydew == null) { + honeydew = new SolidBrush(Color.Honeydew); + } + return (honeydew); + } + } + + public static Brush HotPink { + get { + if (hotPink == null) { + hotPink = new SolidBrush(Color.HotPink); + } + return (hotPink); + } + } + + public static Brush IndianRed { + get { + if (indianRed == null) { + indianRed = new SolidBrush(Color.IndianRed); + } + return (indianRed); + } + } + + public static Brush Indigo { + get { + if (indigo == null) { + indigo = new SolidBrush(Color.Indigo); + } + return (indigo); + } + } + + public static Brush Ivory { + get { + if (ivory == null) { + ivory = new SolidBrush(Color.Ivory); + } + return (ivory); + } + } + + public static Brush Khaki { + get { + if (khaki == null) { + khaki = new SolidBrush(Color.Khaki); + } + return (khaki); + } + } + + public static Brush Lavender { + get { + if (lavender == null) { + lavender = new SolidBrush(Color.Lavender); + } + return (lavender); + } + } + + public static Brush LavenderBlush { + get { + if (lavenderBlush == null) { + lavenderBlush = new SolidBrush(Color.LavenderBlush); + } + return (lavenderBlush); + } + } + + public static Brush LawnGreen { + get { + if (lawnGreen == null) { + lawnGreen = new SolidBrush(Color.LawnGreen); + } + return (lawnGreen); + } + } + + public static Brush LemonChiffon { + get { + if (lemonChiffon == null) { + lemonChiffon = new SolidBrush(Color.LemonChiffon); + } + return (lemonChiffon); + } + } + + public static Brush LightBlue { + get { + if (lightBlue == null) { + lightBlue = new SolidBrush(Color.LightBlue); + } + return (lightBlue); + } + } + + public static Brush LightCoral { + get { + if (lightCoral == null) { + lightCoral = new SolidBrush(Color.LightCoral); + } + return (lightCoral); + } + } + + public static Brush LightCyan { + get { + if (lightCyan == null) { + lightCyan = new SolidBrush(Color.LightCyan); + } + return (lightCyan); + } + } + + public static Brush LightGoldenrodYellow { + get { + if (lightGoldenrodYellow == null) { + lightGoldenrodYellow = new SolidBrush(Color.LightGoldenrodYellow); + } + return (lightGoldenrodYellow); + } + } + + public static Brush LightGray { + get { + if (lightGray == null) { + lightGray = new SolidBrush(Color.LightGray); + } + return (lightGray); + } + } + + public static Brush LightGreen { + get { + if (lightGreen == null) { + lightGreen = new SolidBrush(Color.LightGreen); + } + return (lightGreen); + } + } + + public static Brush LightPink { + get { + if (lightPink == null) { + lightPink = new SolidBrush(Color.LightPink); + } + return (lightPink); + } + } + + public static Brush LightSalmon { + get { + if (lightSalmon == null) { + lightSalmon = new SolidBrush(Color.LightSalmon); + } + return (lightSalmon); + } + } + + public static Brush LightSeaGreen { + get { + if (lightSeaGreen == null) { + lightSeaGreen = new SolidBrush(Color.LightSeaGreen); + } + return (lightSeaGreen); + } + } + + public static Brush LightSkyBlue { + get { + if (lightSkyBlue == null) { + lightSkyBlue = new SolidBrush(Color.LightSkyBlue); + } + return (lightSkyBlue); + } + } + + public static Brush LightSlateGray { + get { + if (lightSlateGray == null) { + lightSlateGray = new SolidBrush(Color.LightSlateGray); + } + return (lightSlateGray); + } + } + + public static Brush LightSteelBlue { + get { + if (lightSteelBlue == null) { + lightSteelBlue = new SolidBrush(Color.LightSteelBlue); + } + return (lightSteelBlue); + } + } + + public static Brush LightYellow { + get { + if (lightYellow == null) { + lightYellow = new SolidBrush(Color.LightYellow); + } + return (lightYellow); + } + } + + public static Brush Lime { + get { + if (lime == null) { + lime = new SolidBrush(Color.Lime); + } + return (lime); + } + } + + public static Brush LimeGreen { + get { + if (limeGreen == null) { + limeGreen = new SolidBrush(Color.LimeGreen); + } + return (limeGreen); + } + } + + public static Brush Linen { + get { + if (linen == null) { + linen = new SolidBrush(Color.Linen); + } + return (linen); + } + } + + public static Brush Magenta { + get { + if (magenta == null) { + magenta = new SolidBrush(Color.Magenta); + } + return (magenta); + } + } + + public static Brush Maroon { + get { + if (maroon == null) { + maroon = new SolidBrush(Color.Maroon); + } + return (maroon); + } + } + + public static Brush MediumAquamarine { + get { + if (mediumAquamarine == null) { + mediumAquamarine = new SolidBrush(Color.MediumAquamarine); + } + return (mediumAquamarine); + } + } + + public static Brush MediumBlue { + get { + if (mediumBlue == null) { + mediumBlue = new SolidBrush(Color.MediumBlue); + } + return (mediumBlue); + } + } + + public static Brush MediumOrchid { + get { + if (mediumOrchid == null) { + mediumOrchid = new SolidBrush(Color.MediumOrchid); + } + return (mediumOrchid); + } + } + + public static Brush MediumPurple { + get { + if (mediumPurple == null) { + mediumPurple = new SolidBrush(Color.MediumPurple); + } + return (mediumPurple); + } + } + + public static Brush MediumSeaGreen { + get { + if (mediumSeaGreen == null) { + mediumSeaGreen = new SolidBrush(Color.MediumSeaGreen); + } + return (mediumSeaGreen); + } + } + + public static Brush MediumSlateBlue { + get { + if (mediumSlateBlue == null) { + mediumSlateBlue = new SolidBrush(Color.MediumSlateBlue); + } + return (mediumSlateBlue); + } + } + + public static Brush MediumSpringGreen { + get { + if (mediumSpringGreen == null) { + mediumSpringGreen = new SolidBrush(Color.MediumSpringGreen); + } + return (mediumSpringGreen); + } + } + + public static Brush MediumTurquoise { + get { + if (mediumTurquoise == null) { + mediumTurquoise = new SolidBrush(Color.MediumTurquoise); + } + return (mediumTurquoise); + } + } + + public static Brush MediumVioletRed { + get { + if (mediumVioletRed == null) { + mediumVioletRed = new SolidBrush(Color.MediumVioletRed); + } + return (mediumVioletRed); + } + } + + public static Brush MidnightBlue { + get { + if (midnightBlue == null) { + midnightBlue = new SolidBrush(Color.MidnightBlue); + } + return (midnightBlue); + } + } + + public static Brush MintCream { + get { + if (mintCream == null) { + mintCream = new SolidBrush(Color.MintCream); + } + return (mintCream); + } + } + + public static Brush MistyRose { + get { + if (mistyRose == null) { + mistyRose = new SolidBrush(Color.MistyRose); + } + return (mistyRose); + } + } + + public static Brush Moccasin { + get { + if (moccasin == null) { + moccasin = new SolidBrush(Color.Moccasin); + } + return (moccasin); + } + } + + public static Brush NavajoWhite { + get { + if (navajoWhite == null) { + navajoWhite = new SolidBrush(Color.NavajoWhite); + } + return (navajoWhite); + } + } + + public static Brush Navy { + get { + if (navy == null) { + navy = new SolidBrush(Color.Navy); + } + return (navy); + } + } + + public static Brush OldLace { + get { + if (oldLace == null) { + oldLace = new SolidBrush(Color.OldLace); + } + return (oldLace); + } + } + + public static Brush Olive { + get { + if (olive == null) { + olive = new SolidBrush(Color.Olive); + } + return (olive); + } + } + + public static Brush OliveDrab { + get { + if (oliveDrab == null) { + oliveDrab = new SolidBrush(Color.OliveDrab); + } + return (oliveDrab); + } + } + + public static Brush Orange { + get { + if (orange == null) { + orange = new SolidBrush(Color.Orange); + } + return (orange); + } + } + + public static Brush OrangeRed { + get { + if (orangeRed == null) { + orangeRed = new SolidBrush(Color.OrangeRed); + } + return (orangeRed); + } + } + + public static Brush Orchid { + get { + if (orchid == null) { + orchid = new SolidBrush(Color.Orchid); + } + return (orchid); + } + } + + public static Brush PaleGoldenrod { + get { + if (paleGoldenrod == null) { + paleGoldenrod = new SolidBrush(Color.PaleGoldenrod); + } + return (paleGoldenrod); + } + } + + public static Brush PaleGreen { + get { + if (paleGreen == null) { + paleGreen = new SolidBrush(Color.PaleGreen); + } + return (paleGreen); + } + } + + public static Brush PaleTurquoise { + get { + if (paleTurquoise == null) { + paleTurquoise = new SolidBrush(Color.PaleTurquoise); + } + return (paleTurquoise); + } + } + + public static Brush PaleVioletRed { + get { + if (paleVioletRed == null) { + paleVioletRed = new SolidBrush(Color.PaleVioletRed); + } + return (paleVioletRed); + } + } + + public static Brush PapayaWhip { + get { + if (papayaWhip == null) { + papayaWhip = new SolidBrush(Color.PapayaWhip); + } + return (papayaWhip); + } + } + + public static Brush PeachPuff { + get { + if (peachPuff == null) { + peachPuff = new SolidBrush(Color.PeachPuff); + } + return (peachPuff); + } + } + + public static Brush Peru { + get { + if (peru == null) { + peru = new SolidBrush(Color.Peru); + } + return (peru); + } + } + + public static Brush Pink { + get { + if (pink == null) { + pink = new SolidBrush(Color.Pink); + } + return (pink); + } + } + + public static Brush Plum { + get { + if (plum == null) { + plum = new SolidBrush(Color.Plum); + } + return (plum); + } + } + + public static Brush PowderBlue { + get { + if (powderBlue == null) { + powderBlue = new SolidBrush(Color.PowderBlue); + } + return (powderBlue); + } + } + + public static Brush Purple { + get { + if (purple == null) { + purple = new SolidBrush(Color.Purple); + } + return (purple); + } + } + + public static Brush Red { + get { + if (red == null) { + red = new SolidBrush(Color.Red); + } + return (red); + } + } + + public static Brush RosyBrown { + get { + if (rosyBrown == null) { + rosyBrown = new SolidBrush(Color.RosyBrown); + } + return (rosyBrown); + } + } + + public static Brush RoyalBlue { + get { + if (royalBlue == null) { + royalBlue = new SolidBrush(Color.RoyalBlue); + } + return (royalBlue); + } + } + + public static Brush SaddleBrown { + get { + if (saddleBrown == null) { + saddleBrown = new SolidBrush(Color.SaddleBrown); + } + return (saddleBrown); + } + } + + public static Brush Salmon { + get { + if (salmon == null) { + salmon = new SolidBrush(Color.Salmon); + } + return (salmon); + } + } + + public static Brush SandyBrown { + get { + if (sandyBrown == null) { + sandyBrown = new SolidBrush(Color.SandyBrown); + } + return (sandyBrown); + } + } + + public static Brush SeaGreen { + get { + if (seaGreen == null) { + seaGreen = new SolidBrush(Color.SeaGreen); + } + return (seaGreen); + } + } + + public static Brush SeaShell { + get { + if (seaShell == null) { + seaShell = new SolidBrush(Color.SeaShell); + } + return (seaShell); + } + } + + public static Brush Sienna { + get { + if (sienna == null) { + sienna = new SolidBrush(Color.Sienna); + } + return (sienna); + } + } + + public static Brush Silver { + get { + if (silver == null) { + silver = new SolidBrush(Color.Silver); + } + return (silver); + } + } + + public static Brush SkyBlue { + get { + if (skyBlue == null) { + skyBlue = new SolidBrush(Color.SkyBlue); + } + return (skyBlue); + } + } + + public static Brush SlateBlue { + get { + if (slateBlue == null) { + slateBlue = new SolidBrush(Color.SlateBlue); + } + return (slateBlue); + } + } + + public static Brush SlateGray { + get { + if (slateGray == null) { + slateGray = new SolidBrush(Color.SlateGray); + } + return (slateGray); + } + } + + public static Brush Snow { + get { + if (snow == null) { + snow = new SolidBrush(Color.Snow); + } + return (snow); + } + } + + public static Brush SpringGreen { + get { + if (springGreen == null) { + springGreen = new SolidBrush(Color.SpringGreen); + } + return (springGreen); + } + } + + public static Brush SteelBlue { + get { + if (steelBlue == null) { + steelBlue = new SolidBrush(Color.SteelBlue); + } + return (steelBlue); + } + } + + public static Brush Tan { + get { + if (tan == null) { + tan = new SolidBrush(Color.Tan); + } + return (tan); + } + } + + public static Brush Teal { + get { + if (teal == null) { + teal = new SolidBrush(Color.Teal); + } + return (teal); + } + } + + public static Brush Thistle { + get { + if (thistle == null) { + thistle = new SolidBrush(Color.Thistle); + } + return (thistle); + } + } + + public static Brush Tomato { + get { + if (tomato == null) { + tomato = new SolidBrush(Color.Tomato); + } + return (tomato); + } + } + + public static Brush Transparent { + get { + if (transparent == null) { + transparent = new SolidBrush(Color.Transparent); + } + return (transparent); + } + } + + public static Brush Turquoise { + get { + if (turquoise == null) { + turquoise = new SolidBrush(Color.Turquoise); + } + return (turquoise); + } + } + + public static Brush Violet { + get { + if (violet == null) { + violet = new SolidBrush(Color.Violet); + } + return (violet); + } + } + + public static Brush Wheat { + get { + if (wheat == null) { + wheat = new SolidBrush(Color.Wheat); + } + return (wheat); + } + } + + public static Brush White { + get { + if (white == null) { + white = new SolidBrush(Color.White); + } + return (white); + } + } + + public static Brush WhiteSmoke { + get { + if (whiteSmoke == null) { + whiteSmoke = new SolidBrush(Color.WhiteSmoke); + } + return (whiteSmoke); + } + } + + public static Brush Yellow { + get { + if (yellow == null) { + yellow = new SolidBrush(Color.Yellow); + } + return (yellow); + } + } + + public static Brush YellowGreen { + get { + if (yellowGreen == null) { + yellowGreen = new SolidBrush(Color.YellowGreen); + } + return (yellowGreen); + } + } + + } +} diff --git a/System.Drawing/System.Drawing/Color.cs b/System.Drawing/System.Drawing/Color.cs new file mode 100644 index 0000000..e1f9c40 --- /dev/null +++ b/System.Drawing/System.Drawing/Color.cs @@ -0,0 +1,193 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Drawing { + public struct Color { + + public static Color FromKnownColor(KnownColor c) { + return KnownColors.FromKnownColor(c); + } + + public static Color FromArgb(int argb) { + Color col = new Color(); + col.value = argb; + return col; + } + + public static Color FromArgb(int alpha, Color baseCol) { + Color col = new Color(); + col.value = col.value & 0x00ffffff | (alpha << 24); + return col; + } + + private int value; + + public int ToArgb() { + return value; + } + + static public Color Transparent { get { return KnownColors.FromKnownColor(KnownColor.Transparent); } } + static public Color AliceBlue { get { return KnownColors.FromKnownColor(KnownColor.AliceBlue); } } + static public Color AntiqueWhite { get { return KnownColors.FromKnownColor(KnownColor.AntiqueWhite); } } + static public Color Aqua { get { return KnownColors.FromKnownColor(KnownColor.Aqua); } } + static public Color Aquamarine { get { return KnownColors.FromKnownColor(KnownColor.Aquamarine); } } + static public Color Azure { get { return KnownColors.FromKnownColor(KnownColor.Azure); } } + static public Color Beige { get { return KnownColors.FromKnownColor(KnownColor.Beige); } } + static public Color Bisque { get { return KnownColors.FromKnownColor(KnownColor.Bisque); } } + static public Color Black { get { return KnownColors.FromKnownColor(KnownColor.Black); } } + static public Color BlanchedAlmond { get { return KnownColors.FromKnownColor(KnownColor.BlanchedAlmond); } } + static public Color Blue { get { return KnownColors.FromKnownColor(KnownColor.Blue); } } + static public Color BlueViolet { get { return KnownColors.FromKnownColor(KnownColor.BlueViolet); } } + static public Color Brown { get { return KnownColors.FromKnownColor(KnownColor.Brown); } } + static public Color BurlyWood { get { return KnownColors.FromKnownColor(KnownColor.BurlyWood); } } + static public Color CadetBlue { get { return KnownColors.FromKnownColor(KnownColor.CadetBlue); } } + static public Color Chartreuse { get { return KnownColors.FromKnownColor(KnownColor.Chartreuse); } } + static public Color Chocolate { get { return KnownColors.FromKnownColor(KnownColor.Chocolate); } } + static public Color Coral { get { return KnownColors.FromKnownColor(KnownColor.Coral); } } + static public Color CornflowerBlue { get { return KnownColors.FromKnownColor(KnownColor.CornflowerBlue); } } + static public Color Cornsilk { get { return KnownColors.FromKnownColor(KnownColor.Cornsilk); } } + static public Color Crimson { get { return KnownColors.FromKnownColor(KnownColor.Crimson); } } + static public Color Cyan { get { return KnownColors.FromKnownColor(KnownColor.Cyan); } } + static public Color DarkBlue { get { return KnownColors.FromKnownColor(KnownColor.DarkBlue); } } + static public Color DarkCyan { get { return KnownColors.FromKnownColor(KnownColor.DarkCyan); } } + static public Color DarkGoldenrod { get { return KnownColors.FromKnownColor(KnownColor.DarkGoldenrod); } } + static public Color DarkGray { get { return KnownColors.FromKnownColor(KnownColor.DarkGray); } } + static public Color DarkGreen { get { return KnownColors.FromKnownColor(KnownColor.DarkGreen); } } + static public Color DarkKhaki { get { return KnownColors.FromKnownColor(KnownColor.DarkKhaki); } } + static public Color DarkMagenta { get { return KnownColors.FromKnownColor(KnownColor.DarkMagenta); } } + static public Color DarkOliveGreen { get { return KnownColors.FromKnownColor(KnownColor.DarkOliveGreen); } } + static public Color DarkOrange { get { return KnownColors.FromKnownColor(KnownColor.DarkOrange); } } + static public Color DarkOrchid { get { return KnownColors.FromKnownColor(KnownColor.DarkOrchid); } } + static public Color DarkRed { get { return KnownColors.FromKnownColor(KnownColor.DarkRed); } } + static public Color DarkSalmon { get { return KnownColors.FromKnownColor(KnownColor.DarkSalmon); } } + static public Color DarkSeaGreen { get { return KnownColors.FromKnownColor(KnownColor.DarkSeaGreen); } } + static public Color DarkSlateBlue { get { return KnownColors.FromKnownColor(KnownColor.DarkSlateBlue); } } + static public Color DarkSlateGray { get { return KnownColors.FromKnownColor(KnownColor.DarkSlateGray); } } + static public Color DarkTurquoise { get { return KnownColors.FromKnownColor(KnownColor.DarkTurquoise); } } + static public Color DarkViolet { get { return KnownColors.FromKnownColor(KnownColor.DarkViolet); } } + static public Color DeepPink { get { return KnownColors.FromKnownColor(KnownColor.DeepPink); } } + static public Color DeepSkyBlue { get { return KnownColors.FromKnownColor(KnownColor.DeepSkyBlue); } } + static public Color DimGray { get { return KnownColors.FromKnownColor(KnownColor.DimGray); } } + static public Color DodgerBlue { get { return KnownColors.FromKnownColor(KnownColor.DodgerBlue); } } + static public Color Firebrick { get { return KnownColors.FromKnownColor(KnownColor.Firebrick); } } + static public Color FloralWhite { get { return KnownColors.FromKnownColor(KnownColor.FloralWhite); } } + static public Color ForestGreen { get { return KnownColors.FromKnownColor(KnownColor.ForestGreen); } } + static public Color Fuchsia { get { return KnownColors.FromKnownColor(KnownColor.Fuchsia); } } + static public Color Gainsboro { get { return KnownColors.FromKnownColor(KnownColor.Gainsboro); } } + static public Color GhostWhite { get { return KnownColors.FromKnownColor(KnownColor.GhostWhite); } } + static public Color Gold { get { return KnownColors.FromKnownColor(KnownColor.Gold); } } + static public Color Goldenrod { get { return KnownColors.FromKnownColor(KnownColor.Goldenrod); } } + static public Color Gray { get { return KnownColors.FromKnownColor(KnownColor.Gray); } } + static public Color Green { get { return KnownColors.FromKnownColor(KnownColor.Green); } } + static public Color GreenYellow { get { return KnownColors.FromKnownColor(KnownColor.GreenYellow); } } + static public Color Honeydew { get { return KnownColors.FromKnownColor(KnownColor.Honeydew); } } + static public Color HotPink { get { return KnownColors.FromKnownColor(KnownColor.HotPink); } } + static public Color IndianRed { get { return KnownColors.FromKnownColor(KnownColor.IndianRed); } } + static public Color Indigo { get { return KnownColors.FromKnownColor(KnownColor.Indigo); } } + static public Color Ivory { get { return KnownColors.FromKnownColor(KnownColor.Ivory); } } + static public Color Khaki { get { return KnownColors.FromKnownColor(KnownColor.Khaki); } } + static public Color Lavender { get { return KnownColors.FromKnownColor(KnownColor.Lavender); } } + static public Color LavenderBlush { get { return KnownColors.FromKnownColor(KnownColor.LavenderBlush); } } + static public Color LawnGreen { get { return KnownColors.FromKnownColor(KnownColor.LawnGreen); } } + static public Color LemonChiffon { get { return KnownColors.FromKnownColor(KnownColor.LemonChiffon); } } + static public Color LightBlue { get { return KnownColors.FromKnownColor(KnownColor.LightBlue); } } + static public Color LightCoral { get { return KnownColors.FromKnownColor(KnownColor.LightCoral); } } + static public Color LightCyan { get { return KnownColors.FromKnownColor(KnownColor.LightCyan); } } + static public Color LightGoldenrodYellow { get { return KnownColors.FromKnownColor(KnownColor.LightGoldenrodYellow); } } + static public Color LightGreen { get { return KnownColors.FromKnownColor(KnownColor.LightGreen); } } + static public Color LightGray { get { return KnownColors.FromKnownColor(KnownColor.LightGray); } } + static public Color LightPink { get { return KnownColors.FromKnownColor(KnownColor.LightPink); } } + static public Color LightSalmon { get { return KnownColors.FromKnownColor(KnownColor.LightSalmon); } } + static public Color LightSeaGreen { get { return KnownColors.FromKnownColor(KnownColor.LightSeaGreen); } } + static public Color LightSkyBlue { get { return KnownColors.FromKnownColor(KnownColor.LightSkyBlue); } } + static public Color LightSlateGray { get { return KnownColors.FromKnownColor(KnownColor.LightSlateGray); } } + static public Color LightSteelBlue { get { return KnownColors.FromKnownColor(KnownColor.LightSteelBlue); } } + static public Color LightYellow { get { return KnownColors.FromKnownColor(KnownColor.LightYellow); } } + static public Color Lime { get { return KnownColors.FromKnownColor(KnownColor.Lime); } } + static public Color LimeGreen { get { return KnownColors.FromKnownColor(KnownColor.LimeGreen); } } + static public Color Linen { get { return KnownColors.FromKnownColor(KnownColor.Linen); } } + static public Color Magenta { get { return KnownColors.FromKnownColor(KnownColor.Magenta); } } + static public Color Maroon { get { return KnownColors.FromKnownColor(KnownColor.Maroon); } } + static public Color MediumAquamarine { get { return KnownColors.FromKnownColor(KnownColor.MediumAquamarine); } } + static public Color MediumBlue { get { return KnownColors.FromKnownColor(KnownColor.MediumBlue); } } + static public Color MediumOrchid { get { return KnownColors.FromKnownColor(KnownColor.MediumOrchid); } } + static public Color MediumPurple { get { return KnownColors.FromKnownColor(KnownColor.MediumPurple); } } + static public Color MediumSeaGreen { get { return KnownColors.FromKnownColor(KnownColor.MediumSeaGreen); } } + static public Color MediumSlateBlue { get { return KnownColors.FromKnownColor(KnownColor.MediumSlateBlue); } } + static public Color MediumSpringGreen { get { return KnownColors.FromKnownColor(KnownColor.MediumSpringGreen); } } + static public Color MediumTurquoise { get { return KnownColors.FromKnownColor(KnownColor.MediumTurquoise); } } + static public Color MediumVioletRed { get { return KnownColors.FromKnownColor(KnownColor.MediumVioletRed); } } + static public Color MidnightBlue { get { return KnownColors.FromKnownColor(KnownColor.MidnightBlue); } } + static public Color MintCream { get { return KnownColors.FromKnownColor(KnownColor.MintCream); } } + static public Color MistyRose { get { return KnownColors.FromKnownColor(KnownColor.MistyRose); } } + static public Color Moccasin { get { return KnownColors.FromKnownColor(KnownColor.Moccasin); } } + static public Color NavajoWhite { get { return KnownColors.FromKnownColor(KnownColor.NavajoWhite); } } + static public Color Navy { get { return KnownColors.FromKnownColor(KnownColor.Navy); } } + static public Color OldLace { get { return KnownColors.FromKnownColor(KnownColor.OldLace); } } + static public Color Olive { get { return KnownColors.FromKnownColor(KnownColor.Olive); } } + static public Color OliveDrab { get { return KnownColors.FromKnownColor(KnownColor.OliveDrab); } } + static public Color Orange { get { return KnownColors.FromKnownColor(KnownColor.Orange); } } + static public Color OrangeRed { get { return KnownColors.FromKnownColor(KnownColor.OrangeRed); } } + static public Color Orchid { get { return KnownColors.FromKnownColor(KnownColor.Orchid); } } + static public Color PaleGoldenrod { get { return KnownColors.FromKnownColor(KnownColor.PaleGoldenrod); } } + static public Color PaleGreen { get { return KnownColors.FromKnownColor(KnownColor.PaleGreen); } } + static public Color PaleTurquoise { get { return KnownColors.FromKnownColor(KnownColor.PaleTurquoise); } } + static public Color PaleVioletRed { get { return KnownColors.FromKnownColor(KnownColor.PaleVioletRed); } } + static public Color PapayaWhip { get { return KnownColors.FromKnownColor(KnownColor.PapayaWhip); } } + static public Color PeachPuff { get { return KnownColors.FromKnownColor(KnownColor.PeachPuff); } } + static public Color Peru { get { return KnownColors.FromKnownColor(KnownColor.Peru); } } + static public Color Pink { get { return KnownColors.FromKnownColor(KnownColor.Pink); } } + static public Color Plum { get { return KnownColors.FromKnownColor(KnownColor.Plum); } } + static public Color PowderBlue { get { return KnownColors.FromKnownColor(KnownColor.PowderBlue); } } + static public Color Purple { get { return KnownColors.FromKnownColor(KnownColor.Purple); } } + static public Color Red { get { return KnownColors.FromKnownColor(KnownColor.Red); } } + static public Color RosyBrown { get { return KnownColors.FromKnownColor(KnownColor.RosyBrown); } } + static public Color RoyalBlue { get { return KnownColors.FromKnownColor(KnownColor.RoyalBlue); } } + static public Color SaddleBrown { get { return KnownColors.FromKnownColor(KnownColor.SaddleBrown); } } + static public Color Salmon { get { return KnownColors.FromKnownColor(KnownColor.Salmon); } } + static public Color SandyBrown { get { return KnownColors.FromKnownColor(KnownColor.SandyBrown); } } + static public Color SeaGreen { get { return KnownColors.FromKnownColor(KnownColor.SeaGreen); } } + static public Color SeaShell { get { return KnownColors.FromKnownColor(KnownColor.SeaShell); } } + static public Color Sienna { get { return KnownColors.FromKnownColor(KnownColor.Sienna); } } + static public Color Silver { get { return KnownColors.FromKnownColor(KnownColor.Silver); } } + static public Color SkyBlue { get { return KnownColors.FromKnownColor(KnownColor.SkyBlue); } } + static public Color SlateBlue { get { return KnownColors.FromKnownColor(KnownColor.SlateBlue); } } + static public Color SlateGray { get { return KnownColors.FromKnownColor(KnownColor.SlateGray); } } + static public Color Snow { get { return KnownColors.FromKnownColor(KnownColor.Snow); } } + static public Color SpringGreen { get { return KnownColors.FromKnownColor(KnownColor.SpringGreen); } } + static public Color SteelBlue { get { return KnownColors.FromKnownColor(KnownColor.SteelBlue); } } + static public Color Tan { get { return KnownColors.FromKnownColor(KnownColor.Tan); } } + static public Color Teal { get { return KnownColors.FromKnownColor(KnownColor.Teal); } } + static public Color Thistle { get { return KnownColors.FromKnownColor(KnownColor.Thistle); } } + static public Color Tomato { get { return KnownColors.FromKnownColor(KnownColor.Tomato); } } + static public Color Turquoise { get { return KnownColors.FromKnownColor(KnownColor.Turquoise); } } + static public Color Violet { get { return KnownColors.FromKnownColor(KnownColor.Violet); } } + static public Color Wheat { get { return KnownColors.FromKnownColor(KnownColor.Wheat); } } + static public Color White { get { return KnownColors.FromKnownColor(KnownColor.White); } } + static public Color WhiteSmoke { get { return KnownColors.FromKnownColor(KnownColor.WhiteSmoke); } } + static public Color Yellow { get { return KnownColors.FromKnownColor(KnownColor.Yellow); } } + static public Color YellowGreen { get { return KnownColors.FromKnownColor(KnownColor.YellowGreen); } } + + } +} diff --git a/System.Drawing/System.Drawing/Font.cs b/System.Drawing/System.Drawing/Font.cs new file mode 100644 index 0000000..ea1dea2 --- /dev/null +++ b/System.Drawing/System.Drawing/Font.cs @@ -0,0 +1,57 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Drawing { + public sealed class Font : MarshalByRefObject, IDisposable { + + internal IntPtr native = IntPtr.Zero; + + private FontFamily family; + + public Font(FontFamily family, float emSize) + : this(family, emSize, FontStyle.Regular) { } + + public Font(FontFamily family, float emSize, FontStyle style) { + this.family = family; + this.native = LibIGraph._CreateFont(family.native, emSize, style); + } + + public Font(string familyName, float emSize) { + this.family = new FontFamily(familyName); + this.native = LibIGraph._CreateFont(this.family.native, emSize, FontStyle.Regular); + } + + ~Font() { + this.Dispose(); + } + + public void Dispose() { + if (this.native != IntPtr.Zero) { + LibIGraph.DisposeFont(this.native); + this.native = IntPtr.Zero; + GC.SuppressFinalize(this); + } + } + } +} diff --git a/System.Drawing/System.Drawing/FontFamily.cs b/System.Drawing/System.Drawing/FontFamily.cs new file mode 100644 index 0000000..a91ea1b --- /dev/null +++ b/System.Drawing/System.Drawing/FontFamily.cs @@ -0,0 +1,49 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Drawing { + public sealed class FontFamily:MarshalByRefObject, IDisposable { + + internal IntPtr native = IntPtr.Zero; + + public FontFamily(string name) { + this.native = LibIGraph.CreateFontFamily_Name(name); + if (this.native == IntPtr.Zero) { + throw new ArgumentException("Font '" + name + "' cannot be found."); + } + } + + ~FontFamily() { + this.Dispose(); + } + + public void Dispose() { + if (this.native != IntPtr.Zero) { + LibIGraph.DisposeFontFamily(this.native); + this.native = IntPtr.Zero; + GC.SuppressFinalize(this); + } + } + } +} diff --git a/System.Drawing/System.Drawing/FontStyle.cs b/System.Drawing/System.Drawing/FontStyle.cs new file mode 100644 index 0000000..22b7c7b --- /dev/null +++ b/System.Drawing/System.Drawing/FontStyle.cs @@ -0,0 +1,29 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +namespace System.Drawing { + public enum FontStyle { + Regular = 0, + Bold = 1, + Italic = 2, + Underline = 4, + Strikeout = 8 + } +} diff --git a/System.Drawing/System.Drawing/Graphics.cs b/System.Drawing/System.Drawing/Graphics.cs new file mode 100644 index 0000000..5fdfb6c --- /dev/null +++ b/System.Drawing/System.Drawing/Graphics.cs @@ -0,0 +1,236 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing.Imaging; +using System.Runtime.InteropServices; +using System.Drawing.Text; + +namespace System.Drawing { + public sealed class Graphics : MarshalByRefObject, IDisposable { + + public static Graphics FromHdc(IntPtr hdc) { + if (hdc != IntPtr.Zero) { + throw new NotImplementedException(); + } + int xSize, ySize; + PixelFormat pixelFormat; + IntPtr native = LibIGraph.GetScreen(out xSize, out ySize, out pixelFormat); + if (native == IntPtr.Zero) { + throw new Exception("CreateScreen() failed"); + } + return new Graphics(xSize, ySize, pixelFormat, native); + } + + public static Graphics FromImage(Image image) { + if (image == null) { + throw new ArgumentNullException("image"); + } + IntPtr native = LibIGraph.GetGraphicsFromImage(image.native); + if (native == IntPtr.Zero) { + throw new ArgumentException("Failed to get Graphics from given Image", "image"); + } + return new Graphics(image.Width, image.Height, image.PixelFormat, native); + } + + private IntPtr native = IntPtr.Zero; + private int xSizePixels, ySizePixels; + private PixelFormat pixelFormat; + private TextRenderingHint textRenderingHint; + private Region clip; + + private Graphics(int xSize, int ySize, PixelFormat pixelFormat, IntPtr native) { + this.xSizePixels = xSize; + this.ySizePixels = ySize; + this.pixelFormat = pixelFormat; + this.native = native; + this.textRenderingHint = TextRenderingHint.SystemDefault; + this.Clip = new Region(); + } + + ~Graphics() { + this.Dispose(); + } + + public void Dispose() { + if (this.native != IntPtr.Zero) { + LibIGraph.DisposeGraphics(this.native); + this.native = IntPtr.Zero; + GC.SuppressFinalize(this); + } + } + + public Region Clip { + get { + return this.clip; + } + set { + if (value == null) { + throw new ArgumentNullException(); + } + this.clip = value; + LibIGraph.Graphics_SetClip(this.native, value.native); + } + } + + public void ResetClip() { + this.Clip = new Region(); + } + + public void Clear(Color color) { + LibIGraph.Clear(this.native, color.ToArgb()); + } + + public TextRenderingHint TextRenderingHint { + get { + return this.textRenderingHint; + } + set { + LibIGraph.TextRenderingHint_Set(this.native, value); + this.textRenderingHint = value; + } + } + + public void DrawLine(Pen pen, int x1, int y1, int x2, int y2) { + LibIGraph.DrawLine_Ints(this.native, pen.native, x1, y1, x2, y2); + } + + public void DrawLine(Pen pen, Point pt1, Point pt2) { + LibIGraph.DrawLine_Ints(this.native, pen.native, pt1.X, pt1.Y, pt2.X, pt2.Y); + } + + public void DrawLines(Pen pen, Point[] points) { + int num = points.Length - 1; + for (int i = 0; i < num; i++) { + this.DrawLine(pen, points[i], points[i + 1]); + } + } + + public void DrawPolygon(Pen pen, Point[] points) { + this.DrawLines(pen, points); + this.DrawLine(pen, points[points.Length - 1], points[0]); + } + + public void DrawRectangle(Pen pen, int x, int y, int width, int height) { + DrawLines(pen, new Point[] { + new Point(x, y), + new Point(x + width, y), + new Point(x + width, y + height), + new Point(x, y + height), + new Point(x, y) + }); + } + + public void DrawRectangle(Pen pen, Rectangle rect) { + this.DrawRectangle(pen, rect.X, rect.Y, rect.Width, rect.Height); + } + + public void DrawRectangle(Pen pen, float x, float y, float width, float height) { + this.DrawRectangle(pen, (int)x, (int)y, (int)width, (int)height); + } + + public void FillRectangle(Brush brush, int x, int y, int width, int height) { + LibIGraph.FillRectangle_Ints(this.native, brush.native, x, y, width, height); + } + + public void FillRectangle(Brush brush, Rectangle rect) { + this.FillRectangle(brush, rect.X, rect.Y, rect.Width, rect.Height); + } + + public void FillRectangle(Brush brush, float x, float y, float width, float height) { + this.FillRectangle(brush, (int)x, (int)y, (int)width, (int)height); + } + + public void FillRectangle(Brush brush, RectangleF rect) { + this.FillRectangle(brush, rect.X, rect.Y, rect.Width, rect.Height); + } + + public void DrawEllipse(Pen pen, int x, int y, int width, int height) { + LibIGraph.DrawEllipse_Ints(this.native, pen.native, x, y, width, height); + } + + public void DrawEllipse(Pen pen, Rectangle rect) { + this.DrawRectangle(pen, rect.X, rect.Y, rect.Width, rect.Height); + } + + public void FillEllipse(Brush brush, int x, int y, int width, int height) { + LibIGraph.FillEllipse_Ints(this.native, brush.native, x, y, width, height); + } + + public void FillEllipse(Brush brush, Rectangle rect) { + this.FillEllipse(brush, rect.X, rect.Y, rect.Width, rect.Height); + } + + public void DrawString(string s, Font font, Brush brush, float x, float y, StringFormat format) { + LibIGraph.DrawString(this.native, s, font.native, brush.native, (int)x, (int)y, int.MaxValue, int.MaxValue, (format == null) ? IntPtr.Zero : format.native); + } + + public void DrawString(string s, Font font, Brush brush, float x, float y) { + this.DrawString(s, font, brush, x, y, StringFormat.GenericDefault); + } + + public void DrawString(string s, Font font, Brush brush, PointF point) { + this.DrawString(s, font, brush, point.X, point.Y, StringFormat.GenericDefault); + } + + public void DrawString(string s, Font font, Brush brush, RectangleF rect) { + LibIGraph.DrawString(this.native, s, font.native, brush.native, + (int)rect.Left, (int)rect.Top, (int)rect.Right, (int)rect.Bottom, + StringFormat.GenericDefault.native); + } + + public void DrawString(string s, Font font, Brush brush, RectangleF rect, StringFormat format) { + LibIGraph.DrawString(this.native, s, font.native, brush.native, + (int)rect.Left, (int)rect.Top, (int)rect.Right, (int)rect.Bottom, format.native); + } + + public SizeF MeasureString(string s, Font font) { + return this.MeasureString(s, font, int.MaxValue, StringFormat.GenericDefault); + } + + public SizeF MeasureString(string s, Font font, int width) { + return this.MeasureString(s, font, width, StringFormat.GenericDefault); + } + + public SizeF MeasureString(string s, Font font, int width, StringFormat format) { + int szWidth, szHeight; + LibIGraph.MeasureString(this.native, s, font.native, width, format.native, out szWidth, out szHeight); + return new SizeF(szWidth, szHeight); + } + + public void DrawImage(Image image, int x, int y) { + LibIGraph.DrawImageUnscaled(this.native, image.native, x, y); + } + + public void DrawImageUnscaled(Image image, int x, int y) { + LibIGraph.DrawImageUnscaled(this.native, image.native, x, y); + } + + public void CopyFromScreen(int srcX, int srcY, int destX, int destY, Size size) { + LibIGraph.Graphics_CopyFromScreen(this.native, srcX, srcY, destX, destY, size.Width, size.Height); + } + + public void CopyFromScreen(Point upperLeftSource, Point upperLeftDestination, Size size) { + this.CopyFromScreen(upperLeftSource.X, upperLeftSource.Y, upperLeftDestination.X, upperLeftDestination.Y, size); + } + } +} diff --git a/System.Drawing/System.Drawing/Image.cs b/System.Drawing/System.Drawing/Image.cs new file mode 100644 index 0000000..1454081 --- /dev/null +++ b/System.Drawing/System.Drawing/Image.cs @@ -0,0 +1,81 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing.Imaging; + +namespace System.Drawing { + public abstract class Image : MarshalByRefObject, IDisposable { + + public static Image FromFile(string filename) { + if (string.IsNullOrEmpty(filename)) { + throw new ArgumentNullException("filename"); + } + int width, height; + PixelFormat pixelFormat; + IntPtr native = LibIGraph.BitmapFromFile(filename, out width, out height, out pixelFormat); + return new Bitmap(native, width, height, pixelFormat); + } + + internal IntPtr native = IntPtr.Zero; + + protected int width, height; + protected PixelFormat pixelFormat; + + ~Image() { + this.Dispose(); + } + + public void Dispose() { + if (this.native != IntPtr.Zero) { + LibIGraph.DisposeImage(this.native); + GC.SuppressFinalize(this); + this.native = IntPtr.Zero; + } + } + + public int Width { + get { + return this.width; + } + } + + public int Height { + get { + return this.height; + } + } + + public PixelFormat PixelFormat { + get { + return this.pixelFormat; + } + } + + public Size Size { + get { + return new Size(this.width, this.height); + } + } + + } +} diff --git a/System.Drawing/System.Drawing/KnownColor.cs b/System.Drawing/System.Drawing/KnownColor.cs new file mode 100644 index 0000000..ba57a51 --- /dev/null +++ b/System.Drawing/System.Drawing/KnownColor.cs @@ -0,0 +1,202 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Drawing { + public enum KnownColor { + ActiveBorder = 1, + ActiveCaption = 2, + ActiveCaptionText = 3, + AppWorkspace = 4, + Control = 5, + ControlDark = 6, + ControlDarkDark = 7, + ControlLight = 8, + ControlLightLight = 9, + ControlText = 10, + Desktop = 11, + GrayText = 12, + Highlight = 13, + HighlightText = 14, + HotTrack = 15, + InactiveBorder = 16, + InactiveCaption = 17, + InactiveCaptionText = 18, + Info = 19, + InfoText = 20, + Menu = 21, + MenuText = 22, + ScrollBar = 23, + Window = 24, + WindowFrame = 25, + WindowText = 26, + Transparent = 27, + AliceBlue = 28, + AntiqueWhite = 29, + Aqua = 30, + Aquamarine = 31, + Azure = 32, + Beige = 33, + Bisque = 34, + Black = 35, + BlanchedAlmond = 36, + Blue = 37, + BlueViolet = 38, + Brown = 39, + BurlyWood = 40, + CadetBlue = 41, + Chartreuse = 42, + Chocolate = 43, + Coral = 44, + CornflowerBlue = 45, + Cornsilk = 46, + Crimson = 47, + Cyan = 48, + DarkBlue = 49, + DarkCyan = 50, + DarkGoldenrod = 51, + DarkGray = 52, + DarkGreen = 53, + DarkKhaki = 54, + DarkMagenta = 55, + DarkOliveGreen = 56, + DarkOrange = 57, + DarkOrchid = 58, + DarkRed = 59, + DarkSalmon = 60, + DarkSeaGreen = 61, + DarkSlateBlue = 62, + DarkSlateGray = 63, + DarkTurquoise = 64, + DarkViolet = 65, + DeepPink = 66, + DeepSkyBlue = 67, + DimGray = 68, + DodgerBlue = 69, + Firebrick = 70, + FloralWhite = 71, + ForestGreen = 72, + Fuchsia = 73, + Gainsboro = 74, + GhostWhite = 75, + Gold = 76, + Goldenrod = 77, + Gray = 78, + Green = 79, + GreenYellow = 80, + Honeydew = 81, + HotPink = 82, + IndianRed = 83, + Indigo = 84, + Ivory = 85, + Khaki = 86, + Lavender = 87, + LavenderBlush = 88, + LawnGreen = 89, + LemonChiffon = 90, + LightBlue = 91, + LightCoral = 92, + LightCyan = 93, + LightGoldenrodYellow = 94, + LightGray = 95, + LightGreen = 96, + LightPink = 97, + LightSalmon = 98, + LightSeaGreen = 99, + LightSkyBlue = 100, + LightSlateGray = 101, + LightSteelBlue = 102, + LightYellow = 103, + Lime = 104, + LimeGreen = 105, + Linen = 106, + Magenta = 107, + Maroon = 108, + MediumAquamarine = 109, + MediumBlue = 110, + MediumOrchid = 111, + MediumPurple = 112, + MediumSeaGreen = 113, + MediumSlateBlue = 114, + MediumSpringGreen = 115, + MediumTurquoise = 116, + MediumVioletRed = 117, + MidnightBlue = 118, + MintCream = 119, + MistyRose = 120, + Moccasin = 121, + NavajoWhite = 122, + Navy = 123, + OldLace = 124, + Olive = 125, + OliveDrab = 126, + Orange = 127, + OrangeRed = 128, + Orchid = 129, + PaleGoldenrod = 130, + PaleGreen = 131, + PaleTurquoise = 132, + PaleVioletRed = 133, + PapayaWhip = 134, + PeachPuff = 135, + Peru = 136, + Pink = 137, + Plum = 138, + PowderBlue = 139, + Purple = 140, + Red = 141, + RosyBrown = 142, + RoyalBlue = 143, + SaddleBrown = 144, + Salmon = 145, + SandyBrown = 146, + SeaGreen = 147, + SeaShell = 148, + Sienna = 149, + Silver = 150, + SkyBlue = 151, + SlateBlue = 152, + SlateGray = 153, + Snow = 154, + SpringGreen = 155, + SteelBlue = 156, + Tan = 157, + Teal = 158, + Thistle = 159, + Tomato = 160, + Turquoise = 161, + Violet = 162, + Wheat = 163, + White = 164, + WhiteSmoke = 165, + Yellow = 166, + YellowGreen = 167, + ButtonFace = 168, + ButtonHighlight = 169, + ButtonShadow = 170, + GradientActiveCaption = 171, + GradientInactiveCaption = 172, + MenuBar = 173, + MenuHighlight = 174 + } +} diff --git a/System.Drawing/System.Drawing/KnownColors.cs b/System.Drawing/System.Drawing/KnownColors.cs new file mode 100644 index 0000000..c826eb2 --- /dev/null +++ b/System.Drawing/System.Drawing/KnownColors.cs @@ -0,0 +1,212 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Drawing { + internal static class KnownColors { + + static private uint[] ArgbValues = new uint[] { + 0x00000000, /* 000 - Empty */ + 0xFFD4D0C8, /* 001 - ActiveBorder */ + 0xFF0054E3, /* 002 - ActiveCaption */ + 0xFFFFFFFF, /* 003 - ActiveCaptionText */ + 0xFF808080, /* 004 - AppWorkspace */ + 0xFFECE9D8, /* 005 - Control */ + 0xFFACA899, /* 006 - ControlDark */ + 0xFF716F64, /* 007 - ControlDarkDark */ + 0xFFF1EFE2, /* 008 - ControlLight */ + 0xFFFFFFFF, /* 009 - ControlLightLight */ + 0xFF000000, /* 010 - ControlText */ + 0xFF004E98, /* 011 - Desktop */ + 0xFFACA899, /* 012 - GrayText */ + 0xFF316AC5, /* 013 - Highlight */ + 0xFFFFFFFF, /* 014 - HighlightText */ + 0xFF000080, /* 015 - HotTrack */ + 0xFFD4D0C8, /* 016 - InactiveBorder */ + 0xFF7A96DF, /* 017 - InactiveCaption */ + 0xFFD8E4F8, /* 018 - InactiveCaptionText */ + 0xFFFFFFE1, /* 019 - Info */ + 0xFF000000, /* 020 - InfoText */ + 0xFFFFFFFF, /* 021 - Menu */ + 0xFF000000, /* 022 - MenuText */ + 0xFFD4D0C8, /* 023 - ScrollBar */ + 0xFFFFFFFF, /* 024 - Window */ + 0xFF000000, /* 025 - WindowFrame */ + 0xFF000000, /* 026 - WindowText */ + 0x00FFFFFF, /* 027 - Transparent */ + 0xFFF0F8FF, /* 028 - AliceBlue */ + 0xFFFAEBD7, /* 029 - AntiqueWhite */ + 0xFF00FFFF, /* 030 - Aqua */ + 0xFF7FFFD4, /* 031 - Aquamarine */ + 0xFFF0FFFF, /* 032 - Azure */ + 0xFFF5F5DC, /* 033 - Beige */ + 0xFFFFE4C4, /* 034 - Bisque */ + 0xFF000000, /* 035 - Black */ + 0xFFFFEBCD, /* 036 - BlanchedAlmond */ + 0xFF0000FF, /* 037 - Blue */ + 0xFF8A2BE2, /* 038 - BlueViolet */ + 0xFFA52A2A, /* 039 - Brown */ + 0xFFDEB887, /* 040 - BurlyWood */ + 0xFF5F9EA0, /* 041 - CadetBlue */ + 0xFF7FFF00, /* 042 - Chartreuse */ + 0xFFD2691E, /* 043 - Chocolate */ + 0xFFFF7F50, /* 044 - Coral */ + 0xFF6495ED, /* 045 - CornflowerBlue */ + 0xFFFFF8DC, /* 046 - Cornsilk */ + 0xFFDC143C, /* 047 - Crimson */ + 0xFF00FFFF, /* 048 - Cyan */ + 0xFF00008B, /* 049 - DarkBlue */ + 0xFF008B8B, /* 050 - DarkCyan */ + 0xFFB8860B, /* 051 - DarkGoldenrod */ + 0xFFA9A9A9, /* 052 - DarkGray */ + 0xFF006400, /* 053 - DarkGreen */ + 0xFFBDB76B, /* 054 - DarkKhaki */ + 0xFF8B008B, /* 055 - DarkMagenta */ + 0xFF556B2F, /* 056 - DarkOliveGreen */ + 0xFFFF8C00, /* 057 - DarkOrange */ + 0xFF9932CC, /* 058 - DarkOrchid */ + 0xFF8B0000, /* 059 - DarkRed */ + 0xFFE9967A, /* 060 - DarkSalmon */ + 0xFF8FBC8B, /* 061 - DarkSeaGreen */ + 0xFF483D8B, /* 062 - DarkSlateBlue */ + 0xFF2F4F4F, /* 063 - DarkSlateGray */ + 0xFF00CED1, /* 064 - DarkTurquoise */ + 0xFF9400D3, /* 065 - DarkViolet */ + 0xFFFF1493, /* 066 - DeepPink */ + 0xFF00BFFF, /* 067 - DeepSkyBlue */ + 0xFF696969, /* 068 - DimGray */ + 0xFF1E90FF, /* 069 - DodgerBlue */ + 0xFFB22222, /* 070 - Firebrick */ + 0xFFFFFAF0, /* 071 - FloralWhite */ + 0xFF228B22, /* 072 - ForestGreen */ + 0xFFFF00FF, /* 073 - Fuchsia */ + 0xFFDCDCDC, /* 074 - Gainsboro */ + 0xFFF8F8FF, /* 075 - GhostWhite */ + 0xFFFFD700, /* 076 - Gold */ + 0xFFDAA520, /* 077 - Goldenrod */ + 0xFF808080, /* 078 - Gray */ + 0xFF008000, /* 079 - Green */ + 0xFFADFF2F, /* 080 - GreenYellow */ + 0xFFF0FFF0, /* 081 - Honeydew */ + 0xFFFF69B4, /* 082 - HotPink */ + 0xFFCD5C5C, /* 083 - IndianRed */ + 0xFF4B0082, /* 084 - Indigo */ + 0xFFFFFFF0, /* 085 - Ivory */ + 0xFFF0E68C, /* 086 - Khaki */ + 0xFFE6E6FA, /* 087 - Lavender */ + 0xFFFFF0F5, /* 088 - LavenderBlush */ + 0xFF7CFC00, /* 089 - LawnGreen */ + 0xFFFFFACD, /* 090 - LemonChiffon */ + 0xFFADD8E6, /* 091 - LightBlue */ + 0xFFF08080, /* 092 - LightCoral */ + 0xFFE0FFFF, /* 093 - LightCyan */ + 0xFFFAFAD2, /* 094 - LightGoldenrodYellow */ + 0xFFD3D3D3, /* 095 - LightGray */ + 0xFF90EE90, /* 096 - LightGreen */ + 0xFFFFB6C1, /* 097 - LightPink */ + 0xFFFFA07A, /* 098 - LightSalmon */ + 0xFF20B2AA, /* 099 - LightSeaGreen */ + 0xFF87CEFA, /* 100 - LightSkyBlue */ + 0xFF778899, /* 101 - LightSlateGray */ + 0xFFB0C4DE, /* 102 - LightSteelBlue */ + 0xFFFFFFE0, /* 103 - LightYellow */ + 0xFF00FF00, /* 104 - Lime */ + 0xFF32CD32, /* 105 - LimeGreen */ + 0xFFFAF0E6, /* 106 - Linen */ + 0xFFFF00FF, /* 107 - Magenta */ + 0xFF800000, /* 108 - Maroon */ + 0xFF66CDAA, /* 109 - MediumAquamarine */ + 0xFF0000CD, /* 110 - MediumBlue */ + 0xFFBA55D3, /* 111 - MediumOrchid */ + 0xFF9370DB, /* 112 - MediumPurple */ + 0xFF3CB371, /* 113 - MediumSeaGreen */ + 0xFF7B68EE, /* 114 - MediumSlateBlue */ + 0xFF00FA9A, /* 115 - MediumSpringGreen */ + 0xFF48D1CC, /* 116 - MediumTurquoise */ + 0xFFC71585, /* 117 - MediumVioletRed */ + 0xFF191970, /* 118 - MidnightBlue */ + 0xFFF5FFFA, /* 119 - MintCream */ + 0xFFFFE4E1, /* 120 - MistyRose */ + 0xFFFFE4B5, /* 121 - Moccasin */ + 0xFFFFDEAD, /* 122 - NavajoWhite */ + 0xFF000080, /* 123 - Navy */ + 0xFFFDF5E6, /* 124 - OldLace */ + 0xFF808000, /* 125 - Olive */ + 0xFF6B8E23, /* 126 - OliveDrab */ + 0xFFFFA500, /* 127 - Orange */ + 0xFFFF4500, /* 128 - OrangeRed */ + 0xFFDA70D6, /* 129 - Orchid */ + 0xFFEEE8AA, /* 130 - PaleGoldenrod */ + 0xFF98FB98, /* 131 - PaleGreen */ + 0xFFAFEEEE, /* 132 - PaleTurquoise */ + 0xFFDB7093, /* 133 - PaleVioletRed */ + 0xFFFFEFD5, /* 134 - PapayaWhip */ + 0xFFFFDAB9, /* 135 - PeachPuff */ + 0xFFCD853F, /* 136 - Peru */ + 0xFFFFC0CB, /* 137 - Pink */ + 0xFFDDA0DD, /* 138 - Plum */ + 0xFFB0E0E6, /* 139 - PowderBlue */ + 0xFF800080, /* 140 - Purple */ + 0xFFFF0000, /* 141 - Red */ + 0xFFBC8F8F, /* 142 - RosyBrown */ + 0xFF4169E1, /* 143 - RoyalBlue */ + 0xFF8B4513, /* 144 - SaddleBrown */ + 0xFFFA8072, /* 145 - Salmon */ + 0xFFF4A460, /* 146 - SandyBrown */ + 0xFF2E8B57, /* 147 - SeaGreen */ + 0xFFFFF5EE, /* 148 - SeaShell */ + 0xFFA0522D, /* 149 - Sienna */ + 0xFFC0C0C0, /* 150 - Silver */ + 0xFF87CEEB, /* 151 - SkyBlue */ + 0xFF6A5ACD, /* 152 - SlateBlue */ + 0xFF708090, /* 153 - SlateGray */ + 0xFFFFFAFA, /* 154 - Snow */ + 0xFF00FF7F, /* 155 - SpringGreen */ + 0xFF4682B4, /* 156 - SteelBlue */ + 0xFFD2B48C, /* 157 - Tan */ + 0xFF008080, /* 158 - Teal */ + 0xFFD8BFD8, /* 159 - Thistle */ + 0xFFFF6347, /* 160 - Tomato */ + 0xFF40E0D0, /* 161 - Turquoise */ + 0xFFEE82EE, /* 162 - Violet */ + 0xFFF5DEB3, /* 163 - Wheat */ + 0xFFFFFFFF, /* 164 - White */ + 0xFFF5F5F5, /* 165 - WhiteSmoke */ + 0xFFFFFF00, /* 166 - Yellow */ + 0xFF9ACD32, /* 167 - YellowGreen */ + 0xFFECE9D8, /* 168 - ButtonFace */ + 0xFFFFFFFF, /* 169 - ButtonHighlight */ + 0xFFACA899, /* 170 - ButtonShadow */ + 0xFF3D95FF, /* 171 - GradientActiveCaption */ + 0xFF9DB9EB, /* 172 - GradientInactiveCaption */ + 0xFFECE9D8, /* 173 - MenuBar */ + 0xFF316AC5, /* 174 - MenuHighlight */ + }; + + internal static Color FromKnownColor(KnownColor knownColor) { + int idx = (int)knownColor; + return Color.FromArgb((int)ArgbValues[idx]); + } + + } +} diff --git a/System.Drawing/System.Drawing/LibIGraph.cs b/System.Drawing/System.Drawing/LibIGraph.cs new file mode 100644 index 0000000..558a4a3 --- /dev/null +++ b/System.Drawing/System.Drawing/LibIGraph.cs @@ -0,0 +1,186 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Runtime.InteropServices; +using System.Drawing.Imaging; +using System.Drawing.Text; +using System.Drawing.Drawing2D; + +namespace System.Drawing { + internal static class LibIGraph { + + #region Graphics methods + + [DllImport("libIGraph")] + extern public static IntPtr GetScreen(out int xSize, out int ySize, out PixelFormat pixelFormat); + + [DllImport("libIGraph")] + extern public static IntPtr GetGraphicsFromImage(IntPtr imageNative); + + [DllImport("libIGraph")] + extern public static void DisposeGraphics(IntPtr graphics); + + [DllImport("libIGraph")] + extern public static void TextRenderingHint_Set(IntPtr graphics, TextRenderingHint textRenderingHint); + + [DllImport("libIGraph")] + extern public static void Clear(IntPtr native, int argb); + + [DllImport("libIGraph")] + extern public static void DrawLine_Ints(IntPtr graphics, IntPtr pen, int x1, int y1, int x2, int y2); + + [DllImport("libIGraph")] + extern public static void FillRectangle_Ints(IntPtr graphics, IntPtr brush, int x, int y, int width, int height); + + [DllImport("libIGraph")] + extern public static void DrawEllipse_Ints(IntPtr graphics, IntPtr pen, int x, int y, int width, int height); + + [DllImport("libIGraph")] + extern public static void FillEllipse_Ints(IntPtr graphics, IntPtr brush, int x, int y, int width, int height); + + [DllImport("libIGraph", CharSet = CharSet.Unicode)] + extern public static void DrawString(IntPtr graphics, string s, IntPtr font, IntPtr brush, int x1, int y1, int x2, int y2, IntPtr format); + + [DllImport("libIGraph", CharSet = CharSet.Unicode)] + extern public static void MeasureString(IntPtr graphics, string s, IntPtr font, int width, IntPtr format, out int szWidth, out int szHeight); + + [DllImport("libIGraph")] + extern public static void DrawImageUnscaled(IntPtr graphics, IntPtr image, int x, int y); + + [DllImport("libIGraph")] + extern public static void Graphics_SetClip(IntPtr graphics, IntPtr region); + + [DllImport("libIGraph")] + extern public static void Graphics_CopyFromScreen(IntPtr graphics, int srcX, int srcY, int destX, int destY, int sizeX, int sizeY); + + #endregion + + #region Pen methods + + [DllImport("libIGraph")] + extern public static IntPtr CreatePen_Color(float width, int argb); + + [DllImport("libIGraph")] + extern public static void DisposePen(IntPtr native); + + [DllImport("libIGraph")] + extern public static void Pen_SetCol(IntPtr native, int argb); + + [DllImport("libIGraph")] + extern public static void Pen_SetWidth(IntPtr native, float width); + + #endregion + + #region Brush methods + + [DllImport("libIGraph")] + extern public static IntPtr CreateBrush_Solid(int argb); + + [DllImport("libIGraph")] + extern public static IntPtr CreateBrush_Hatch(HatchStyle hatchStyle, int foreCol, int backCol); + + [DllImport("libIGraph")] + extern public static IntPtr CreateBrush_LinearGradient(int x1, int y1, int x2, int y2, int col1, int col2); + + [DllImport("libIGraph")] + extern public static void DisposeBrush(IntPtr native); + + [DllImport("libIGraph")] + extern public static void SolidBrush_SetCol(IntPtr native, int argb); + + #endregion + + #region FontFamily methods + + [DllImport("libIGraph", CharSet=CharSet.Ansi)] + extern public static IntPtr CreateFontFamily_Name(string name); + + [DllImport("libIGraph")] + extern public static void DisposeFontFamily(IntPtr native); + + #endregion + + #region Font methods + + [DllImport("libIGraph")] + extern public static IntPtr _CreateFont(IntPtr family, float emSize, FontStyle style); + + [DllImport("libIGraph")] + extern public static void DisposeFont(IntPtr native); + + #endregion + + #region StringFormat methods + + [DllImport("libIGraph")] + extern public static IntPtr CreateStringFormat(StringAlignment alignment, StringFormatFlags formatFlags, StringAlignment lineAlignment, StringTrimming stringTrimming); + + [DllImport("libIGraph")] + extern public static void DisposeStringFormat(IntPtr native); + + [DllImport("libIGraph")] + extern public static void StringFormat_SetTrimming(IntPtr stringFormat, StringTrimming trimming); + + [DllImport("libIGraph")] + extern public static void StringFormat_SetAlignment(IntPtr stringFormat, StringAlignment alignment); + + [DllImport("libIGraph")] + extern public static void StringFormat_SetLineAlignment(IntPtr stringFormat, StringAlignment lineAlignment); + + [DllImport("libIGraph")] + extern public static void StringFormat_SetFormatFlags(IntPtr stringFormat, StringFormatFlags formatFlags); + + #endregion + + #region Image methods + + [DllImport("libIGraph")] + extern public static void DisposeImage(IntPtr native); + + #endregion + + #region Bitmap methods + + [DllImport("libIGraph")] + extern public static IntPtr _CreateBitmap(int width, int height, PixelFormat pixelFormat); + + [DllImport("libIGraph", CharSet = CharSet.Ansi)] + extern public static IntPtr BitmapFromFile(string filename, out int width, out int height, out PixelFormat pixelFormat); + + #endregion + + #region Region methods + + [DllImport("libIGraph")] + extern public static IntPtr CreateRegion_Infinite(); + + [DllImport("libIGraph")] + extern public static IntPtr CreateRegion_Rect(int x, int y, int width, int height); + + [DllImport("libIGraph")] + extern public static void DisposeRegion(IntPtr native); + + #endregion + + } +} diff --git a/System.Drawing/System.Drawing/Pen.cs b/System.Drawing/System.Drawing/Pen.cs new file mode 100644 index 0000000..7832a24 --- /dev/null +++ b/System.Drawing/System.Drawing/Pen.cs @@ -0,0 +1,95 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Drawing { + public sealed class Pen : MarshalByRefObject, IDisposable, ICloneable { + + internal IntPtr native = IntPtr.Zero; + private Color color; + private float width; + internal bool canChange = true; + + ~Pen() { + this.Dispose(false); + } + + public Pen(Color color) : this(color, 1.0f) { } + + public Pen(Color color, float width) { + if (width < 1.0f) { + width = 1.0f; + } + this.color = color; + this.width = width; + native = LibIGraph.CreatePen_Color(width, color.ToArgb()); + } + + public Color Color { + get { + return this.color; + } + set { + if (!this.canChange) { + throw new ArgumentException("This SolidBrush cannot be changed."); + } + this.color = value; + LibIGraph.Pen_SetCol(this.native, value.ToArgb()); + } + } + + public float Width { + get { + return this.width; + } + set { + if (!this.canChange) { + throw new ArgumentException("This Pen cannot be changed."); + } + if (value < 1.0f) { + value = 1.0f; + } + LibIGraph.Pen_SetWidth(this.native, value); + } + } + + public void Dispose() { + this.Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) { + if (!this.canChange && disposing) { + throw new ArgumentException("This Pen cannot be disposed of."); + } + if (this.native != IntPtr.Zero) { + LibIGraph.DisposePen(this.native); + this.native = IntPtr.Zero; + } + } + + public object Clone() { + throw new Exception("The method or operation is not implemented."); + } + } +} diff --git a/System.Drawing/System.Drawing/Pens.cs b/System.Drawing/System.Drawing/Pens.cs new file mode 100644 index 0000000..1645152 --- /dev/null +++ b/System.Drawing/System.Drawing/Pens.cs @@ -0,0 +1,1582 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Drawing { + public static class Pens { + + private static Pen aliceblue; + private static Pen antiquewhite; + private static Pen aqua; + private static Pen aquamarine; + private static Pen azure; + private static Pen beige; + private static Pen bisque; + private static Pen black; + private static Pen blanchedalmond; + private static Pen blue; + private static Pen blueviolet; + private static Pen brown; + private static Pen burlywood; + private static Pen cadetblue; + private static Pen chartreuse; + private static Pen chocolate; + private static Pen coral; + private static Pen cornflowerblue; + private static Pen cornsilk; + private static Pen crimson; + private static Pen cyan; + private static Pen darkblue; + private static Pen darkcyan; + private static Pen darkgoldenrod; + private static Pen darkgray; + private static Pen darkgreen; + private static Pen darkkhaki; + private static Pen darkmagenta; + private static Pen darkolivegreen; + private static Pen darkorange; + private static Pen darkorchid; + private static Pen darkred; + private static Pen darksalmon; + private static Pen darkseagreen; + private static Pen darkslateblue; + private static Pen darkslategray; + private static Pen darkturquoise; + private static Pen darkviolet; + private static Pen deeppink; + private static Pen deepskyblue; + private static Pen dimgray; + private static Pen dodgerblue; + private static Pen firebrick; + private static Pen floralwhite; + private static Pen forestgreen; + private static Pen fuchsia; + private static Pen gainsboro; + private static Pen ghostwhite; + private static Pen gold; + private static Pen goldenrod; + private static Pen gray; + private static Pen green; + private static Pen greenyellow; + private static Pen honeydew; + private static Pen hotpink; + private static Pen indianred; + private static Pen indigo; + private static Pen ivory; + private static Pen khaki; + private static Pen lavender; + private static Pen lavenderblush; + private static Pen lawngreen; + private static Pen lemonchiffon; + private static Pen lightblue; + private static Pen lightcoral; + private static Pen lightcyan; + private static Pen lightgoldenrodyellow; + private static Pen lightgray; + private static Pen lightgreen; + private static Pen lightpink; + private static Pen lightsalmon; + private static Pen lightseagreen; + private static Pen lightskyblue; + private static Pen lightslategray; + private static Pen lightsteelblue; + private static Pen lightyellow; + private static Pen lime; + private static Pen limegreen; + private static Pen linen; + private static Pen magenta; + private static Pen maroon; + private static Pen mediumaquamarine; + private static Pen mediumblue; + private static Pen mediumorchid; + private static Pen mediumpurple; + private static Pen mediumseagreen; + private static Pen mediumslateblue; + private static Pen mediumspringgreen; + private static Pen mediumturquoise; + private static Pen mediumvioletred; + private static Pen midnightblue; + private static Pen mintcream; + private static Pen mistyrose; + private static Pen moccasin; + private static Pen navajowhite; + private static Pen navy; + private static Pen oldlace; + private static Pen olive; + private static Pen olivedrab; + private static Pen orange; + private static Pen orangered; + private static Pen orchid; + private static Pen palegoldenrod; + private static Pen palegreen; + private static Pen paleturquoise; + private static Pen palevioletred; + private static Pen papayawhip; + private static Pen peachpuff; + private static Pen peru; + private static Pen pink; + private static Pen plum; + private static Pen powderblue; + private static Pen purple; + private static Pen red; + private static Pen rosybrown; + private static Pen royalblue; + private static Pen saddlebrown; + private static Pen salmon; + private static Pen sandybrown; + private static Pen seagreen; + private static Pen seashell; + private static Pen sienna; + private static Pen silver; + private static Pen skyblue; + private static Pen slateblue; + private static Pen slategray; + private static Pen snow; + private static Pen springgreen; + private static Pen steelblue; + private static Pen tan; + private static Pen teal; + private static Pen thistle; + private static Pen tomato; + private static Pen transparent; + private static Pen turquoise; + private static Pen violet; + private static Pen wheat; + private static Pen white; + private static Pen whitesmoke; + private static Pen yellow; + private static Pen yellowgreen; + + public static Pen AliceBlue { + get { + if (aliceblue == null) { + aliceblue = new Pen(Color.AliceBlue); + aliceblue.canChange = false; + } + return aliceblue; + } + } + + public static Pen AntiqueWhite { + get { + if (antiquewhite == null) { + antiquewhite = new Pen(Color.AntiqueWhite); + antiquewhite.canChange = false; + } + return antiquewhite; + } + } + + public static Pen Aqua { + get { + if (aqua == null) { + aqua = new Pen(Color.Aqua); + aqua.canChange = false; + } + return aqua; + } + } + + public static Pen Aquamarine { + get { + if (aquamarine == null) { + aquamarine = new Pen(Color.Aquamarine); + aquamarine.canChange = false; + } + return aquamarine; + } + } + + public static Pen Azure { + get { + if (azure == null) { + azure = new Pen(Color.Azure); + azure.canChange = false; + } + return azure; + } + } + + public static Pen Beige { + get { + if (beige == null) { + beige = new Pen(Color.Beige); + beige.canChange = false; + } + return beige; + } + } + + public static Pen Bisque { + get { + if (bisque == null) { + bisque = new Pen(Color.Bisque); + bisque.canChange = false; + } + return bisque; + } + } + + public static Pen Black { + get { + if (black == null) { + black = new Pen(Color.Black); + black.canChange = false; + } + return black; + } + } + + public static Pen BlanchedAlmond { + get { + if (blanchedalmond == null) { + blanchedalmond = new Pen(Color.BlanchedAlmond); + blanchedalmond.canChange = false; + } + return blanchedalmond; + } + } + + public static Pen Blue { + get { + if (blue == null) { + blue = new Pen(Color.Blue); + blue.canChange = false; + } + return blue; + } + } + + public static Pen BlueViolet { + get { + if (blueviolet == null) { + blueviolet = new Pen(Color.BlueViolet); + blueviolet.canChange = false; + } + return blueviolet; + } + } + + public static Pen Brown { + get { + if (brown == null) { + brown = new Pen(Color.Brown); + brown.canChange = false; + } + return brown; + } + } + + public static Pen BurlyWood { + get { + if (burlywood == null) { + burlywood = new Pen(Color.BurlyWood); + burlywood.canChange = false; + } + return burlywood; + } + } + + public static Pen CadetBlue { + get { + if (cadetblue == null) { + cadetblue = new Pen(Color.CadetBlue); + cadetblue.canChange = false; + } + return cadetblue; + } + } + + public static Pen Chartreuse { + get { + if (chartreuse == null) { + chartreuse = new Pen(Color.Chartreuse); + chartreuse.canChange = false; + } + return chartreuse; + } + } + + public static Pen Chocolate { + get { + if (chocolate == null) { + chocolate = new Pen(Color.Chocolate); + chocolate.canChange = false; + } + return chocolate; + } + } + + public static Pen Coral { + get { + if (coral == null) { + coral = new Pen(Color.Coral); + coral.canChange = false; + } + return coral; + } + } + + public static Pen CornflowerBlue { + get { + if (cornflowerblue == null) { + cornflowerblue = new Pen(Color.CornflowerBlue); + cornflowerblue.canChange = false; + } + return cornflowerblue; + } + } + + public static Pen Cornsilk { + get { + if (cornsilk == null) { + cornsilk = new Pen(Color.Cornsilk); + cornsilk.canChange = false; + } + return cornsilk; + } + } + + public static Pen Crimson { + get { + if (crimson == null) { + crimson = new Pen(Color.Crimson); + crimson.canChange = false; + } + return crimson; + } + } + + public static Pen Cyan { + get { + if (cyan == null) { + cyan = new Pen(Color.Cyan); + cyan.canChange = false; + } + return cyan; + } + } + + public static Pen DarkBlue { + get { + if (darkblue == null) { + darkblue = new Pen(Color.DarkBlue); + darkblue.canChange = false; + } + return darkblue; + } + } + + public static Pen DarkCyan { + get { + if (darkcyan == null) { + darkcyan = new Pen(Color.DarkCyan); + darkcyan.canChange = false; + } + return darkcyan; + } + } + + public static Pen DarkGoldenrod { + get { + if (darkgoldenrod == null) { + darkgoldenrod = new Pen(Color.DarkGoldenrod); + darkgoldenrod.canChange = false; + } + return darkgoldenrod; + } + } + + public static Pen DarkGray { + get { + if (darkgray == null) { + darkgray = new Pen(Color.DarkGray); + darkgray.canChange = false; + } + return darkgray; + } + } + + public static Pen DarkGreen { + get { + if (darkgreen == null) { + darkgreen = new Pen(Color.DarkGreen); + darkgreen.canChange = false; + } + return darkgreen; + } + } + + public static Pen DarkKhaki { + get { + if (darkkhaki == null) { + darkkhaki = new Pen(Color.DarkKhaki); + darkkhaki.canChange = false; + } + return darkkhaki; + } + } + + public static Pen DarkMagenta { + get { + if (darkmagenta == null) { + darkmagenta = new Pen(Color.DarkMagenta); + darkmagenta.canChange = false; + } + return darkmagenta; + } + } + + public static Pen DarkOliveGreen { + get { + if (darkolivegreen == null) { + darkolivegreen = new Pen(Color.DarkOliveGreen); + darkolivegreen.canChange = false; + } + return darkolivegreen; + } + } + + public static Pen DarkOrange { + get { + if (darkorange == null) { + darkorange = new Pen(Color.DarkOrange); + darkorange.canChange = false; + } + return darkorange; + } + } + + public static Pen DarkOrchid { + get { + if (darkorchid == null) { + darkorchid = new Pen(Color.DarkOrchid); + darkorchid.canChange = false; + } + return darkorchid; + } + } + + public static Pen DarkRed { + get { + if (darkred == null) { + darkred = new Pen(Color.DarkRed); + darkred.canChange = false; + } + return darkred; + } + } + + public static Pen DarkSalmon { + get { + if (darksalmon == null) { + darksalmon = new Pen(Color.DarkSalmon); + darksalmon.canChange = false; + } + return darksalmon; + } + } + + public static Pen DarkSeaGreen { + get { + if (darkseagreen == null) { + darkseagreen = new Pen(Color.DarkSeaGreen); + darkseagreen.canChange = false; + } + return darkseagreen; + } + } + + public static Pen DarkSlateBlue { + get { + if (darkslateblue == null) { + darkslateblue = new Pen(Color.DarkSlateBlue); + darkslateblue.canChange = false; + } + return darkslateblue; + } + } + + public static Pen DarkSlateGray { + get { + if (darkslategray == null) { + darkslategray = new Pen(Color.DarkSlateGray); + darkslategray.canChange = false; + } + return darkslategray; + } + } + + public static Pen DarkTurquoise { + get { + if (darkturquoise == null) { + darkturquoise = new Pen(Color.DarkTurquoise); + darkturquoise.canChange = false; + } + return darkturquoise; + } + } + + public static Pen DarkViolet { + get { + if (darkviolet == null) { + darkviolet = new Pen(Color.DarkViolet); + darkviolet.canChange = false; + } + return darkviolet; + } + } + + public static Pen DeepPink { + get { + if (deeppink == null) { + deeppink = new Pen(Color.DeepPink); + deeppink.canChange = false; + } + return deeppink; + } + } + + public static Pen DeepSkyBlue { + get { + if (deepskyblue == null) { + deepskyblue = new Pen(Color.DeepSkyBlue); + deepskyblue.canChange = false; + } + return deepskyblue; + } + } + + public static Pen DimGray { + get { + if (dimgray == null) { + dimgray = new Pen(Color.DimGray); + dimgray.canChange = false; + } + return dimgray; + } + } + + public static Pen DodgerBlue { + get { + if (dodgerblue == null) { + dodgerblue = new Pen(Color.DodgerBlue); + dodgerblue.canChange = false; + } + return dodgerblue; + } + } + + public static Pen Firebrick { + get { + if (firebrick == null) { + firebrick = new Pen(Color.Firebrick); + firebrick.canChange = false; + } + return firebrick; + } + } + + public static Pen FloralWhite { + get { + if (floralwhite == null) { + floralwhite = new Pen(Color.FloralWhite); + floralwhite.canChange = false; + } + return floralwhite; + } + } + + public static Pen ForestGreen { + get { + if (forestgreen == null) { + forestgreen = new Pen(Color.ForestGreen); + forestgreen.canChange = false; + } + return forestgreen; + } + } + + public static Pen Fuchsia { + get { + if (fuchsia == null) { + fuchsia = new Pen(Color.Fuchsia); + fuchsia.canChange = false; + } + return fuchsia; + } + } + + public static Pen Gainsboro { + get { + if (gainsboro == null) { + gainsboro = new Pen(Color.Gainsboro); + gainsboro.canChange = false; + } + return gainsboro; + } + } + + public static Pen GhostWhite { + get { + if (ghostwhite == null) { + ghostwhite = new Pen(Color.GhostWhite); + ghostwhite.canChange = false; + } + return ghostwhite; + } + } + + public static Pen Gold { + get { + if (gold == null) { + gold = new Pen(Color.Gold); + gold.canChange = false; + } + return gold; + } + } + + public static Pen Goldenrod { + get { + if (goldenrod == null) { + goldenrod = new Pen(Color.Goldenrod); + goldenrod.canChange = false; + } + return goldenrod; + } + } + + public static Pen Gray { + get { + if (gray == null) { + gray = new Pen(Color.Gray); + gray.canChange = false; + } + return gray; + } + } + + public static Pen Green { + get { + if (green == null) { + green = new Pen(Color.Green); + green.canChange = false; + } + return green; + } + } + + public static Pen GreenYellow { + get { + if (greenyellow == null) { + greenyellow = new Pen(Color.GreenYellow); + greenyellow.canChange = false; + } + return greenyellow; + } + } + + public static Pen Honeydew { + get { + if (honeydew == null) { + honeydew = new Pen(Color.Honeydew); + honeydew.canChange = false; + } + return honeydew; + } + } + + public static Pen HotPink { + get { + if (hotpink == null) { + hotpink = new Pen(Color.HotPink); + hotpink.canChange = false; + } + return hotpink; + } + } + + public static Pen IndianRed { + get { + if (indianred == null) { + indianred = new Pen(Color.IndianRed); + indianred.canChange = false; + } + return indianred; + } + } + + public static Pen Indigo { + get { + if (indigo == null) { + indigo = new Pen(Color.Indigo); + indigo.canChange = false; + } + return indigo; + } + } + + public static Pen Ivory { + get { + if (ivory == null) { + ivory = new Pen(Color.Ivory); + ivory.canChange = false; + } + return ivory; + } + } + + public static Pen Khaki { + get { + if (khaki == null) { + khaki = new Pen(Color.Khaki); + khaki.canChange = false; + } + return khaki; + } + } + + public static Pen Lavender { + get { + if (lavender == null) { + lavender = new Pen(Color.Lavender); + lavender.canChange = false; + } + return lavender; + } + } + + public static Pen LavenderBlush { + get { + if (lavenderblush == null) { + lavenderblush = new Pen(Color.LavenderBlush); + lavenderblush.canChange = false; + } + return lavenderblush; + } + } + + public static Pen LawnGreen { + get { + if (lawngreen == null) { + lawngreen = new Pen(Color.LawnGreen); + lawngreen.canChange = false; + } + return lawngreen; + } + } + + public static Pen LemonChiffon { + get { + if (lemonchiffon == null) { + lemonchiffon = new Pen(Color.LemonChiffon); + lemonchiffon.canChange = false; + } + return lemonchiffon; + } + } + + public static Pen LightBlue { + get { + if (lightblue == null) { + lightblue = new Pen(Color.LightBlue); + lightblue.canChange = false; + } + return lightblue; + } + } + + public static Pen LightCoral { + get { + if (lightcoral == null) { + lightcoral = new Pen(Color.LightCoral); + lightcoral.canChange = false; + } + return lightcoral; + } + } + + public static Pen LightCyan { + get { + if (lightcyan == null) { + lightcyan = new Pen(Color.LightCyan); + lightcyan.canChange = false; + } + return lightcyan; + } + } + + public static Pen LightGoldenrodYellow { + get { + if (lightgoldenrodyellow == null) { + lightgoldenrodyellow = new Pen(Color.LightGoldenrodYellow); + lightgoldenrodyellow.canChange = false; + } + return lightgoldenrodyellow; + } + } + + public static Pen LightGray { + get { + if (lightgray == null) { + lightgray = new Pen(Color.LightGray); + lightgray.canChange = false; + } + return lightgray; + } + } + + public static Pen LightGreen { + get { + if (lightgreen == null) { + lightgreen = new Pen(Color.LightGreen); + lightgreen.canChange = false; + } + return lightgreen; + } + } + + public static Pen LightPink { + get { + if (lightpink == null) { + lightpink = new Pen(Color.LightPink); + lightpink.canChange = false; + } + return lightpink; + } + } + + public static Pen LightSalmon { + get { + if (lightsalmon == null) { + lightsalmon = new Pen(Color.LightSalmon); + lightsalmon.canChange = false; + } + return lightsalmon; + } + } + + public static Pen LightSeaGreen { + get { + if (lightseagreen == null) { + lightseagreen = new Pen(Color.LightSeaGreen); + lightseagreen.canChange = false; + } + return lightseagreen; + } + } + + public static Pen LightSkyBlue { + get { + if (lightskyblue == null) { + lightskyblue = new Pen(Color.LightSkyBlue); + lightskyblue.canChange = false; + } + return lightskyblue; + } + } + + public static Pen LightSlateGray { + get { + if (lightslategray == null) { + lightslategray = new Pen(Color.LightSlateGray); + lightslategray.canChange = false; + } + return lightslategray; + } + } + + public static Pen LightSteelBlue { + get { + if (lightsteelblue == null) { + lightsteelblue = new Pen(Color.LightSteelBlue); + lightsteelblue.canChange = false; + } + return lightsteelblue; + } + } + + public static Pen LightYellow { + get { + if (lightyellow == null) { + lightyellow = new Pen(Color.LightYellow); + lightyellow.canChange = false; + } + return lightyellow; + } + } + + public static Pen Lime { + get { + if (lime == null) { + lime = new Pen(Color.Lime); + lime.canChange = false; + } + return lime; + } + } + + public static Pen LimeGreen { + get { + if (limegreen == null) { + limegreen = new Pen(Color.LimeGreen); + limegreen.canChange = false; + } + return limegreen; + } + } + + public static Pen Linen { + get { + if (linen == null) { + linen = new Pen(Color.Linen); + linen.canChange = false; + } + return linen; + } + } + + public static Pen Magenta { + get { + if (magenta == null) { + magenta = new Pen(Color.Magenta); + magenta.canChange = false; + } + return magenta; + } + } + + public static Pen Maroon { + get { + if (maroon == null) { + maroon = new Pen(Color.Maroon); + maroon.canChange = false; + } + return maroon; + } + } + + public static Pen MediumAquamarine { + get { + if (mediumaquamarine == null) { + mediumaquamarine = new Pen(Color.MediumAquamarine); + mediumaquamarine.canChange = false; + } + return mediumaquamarine; + } + } + + public static Pen MediumBlue { + get { + if (mediumblue == null) { + mediumblue = new Pen(Color.MediumBlue); + mediumblue.canChange = false; + } + return mediumblue; + } + } + + public static Pen MediumOrchid { + get { + if (mediumorchid == null) { + mediumorchid = new Pen(Color.MediumOrchid); + mediumorchid.canChange = false; + } + return mediumorchid; + } + } + + public static Pen MediumPurple { + get { + if (mediumpurple == null) { + mediumpurple = new Pen(Color.MediumPurple); + mediumpurple.canChange = false; + } + return mediumpurple; + } + } + + public static Pen MediumSeaGreen { + get { + if (mediumseagreen == null) { + mediumseagreen = new Pen(Color.MediumSeaGreen); + mediumseagreen.canChange = false; + } + return mediumseagreen; + } + } + + public static Pen MediumSlateBlue { + get { + if (mediumslateblue == null) { + mediumslateblue = new Pen(Color.MediumSlateBlue); + mediumslateblue.canChange = false; + } + return mediumslateblue; + } + } + + public static Pen MediumSpringGreen { + get { + if (mediumspringgreen == null) { + mediumspringgreen = new Pen(Color.MediumSpringGreen); + mediumspringgreen.canChange = false; + } + return mediumspringgreen; + } + } + + public static Pen MediumTurquoise { + get { + if (mediumturquoise == null) { + mediumturquoise = new Pen(Color.MediumTurquoise); + mediumturquoise.canChange = false; + } + return mediumturquoise; + } + } + + public static Pen MediumVioletRed { + get { + if (mediumvioletred == null) { + mediumvioletred = new Pen(Color.MediumVioletRed); + mediumvioletred.canChange = false; + } + return mediumvioletred; + } + } + + public static Pen MidnightBlue { + get { + if (midnightblue == null) { + midnightblue = new Pen(Color.MidnightBlue); + midnightblue.canChange = false; + } + return midnightblue; + } + } + + public static Pen MintCream { + get { + if (mintcream == null) { + mintcream = new Pen(Color.MintCream); + mintcream.canChange = false; + } + return mintcream; + } + } + + public static Pen MistyRose { + get { + if (mistyrose == null) { + mistyrose = new Pen(Color.MistyRose); + mistyrose.canChange = false; + } + return mistyrose; + } + } + + public static Pen Moccasin { + get { + if (moccasin == null) { + moccasin = new Pen(Color.Moccasin); + moccasin.canChange = false; + } + return moccasin; + } + } + + public static Pen NavajoWhite { + get { + if (navajowhite == null) { + navajowhite = new Pen(Color.NavajoWhite); + navajowhite.canChange = false; + } + return navajowhite; + } + } + + public static Pen Navy { + get { + if (navy == null) { + navy = new Pen(Color.Navy); + navy.canChange = false; + } + return navy; + } + } + + public static Pen OldLace { + get { + if (oldlace == null) { + oldlace = new Pen(Color.OldLace); + oldlace.canChange = false; + } + return oldlace; + } + } + + public static Pen Olive { + get { + if (olive == null) { + olive = new Pen(Color.Olive); + olive.canChange = false; + } + return olive; + } + } + + public static Pen OliveDrab { + get { + if (olivedrab == null) { + olivedrab = new Pen(Color.OliveDrab); + olivedrab.canChange = false; + } + return olivedrab; + } + } + + public static Pen Orange { + get { + if (orange == null) { + orange = new Pen(Color.Orange); + orange.canChange = false; + } + return orange; + } + } + + public static Pen OrangeRed { + get { + if (orangered == null) { + orangered = new Pen(Color.OrangeRed); + orangered.canChange = false; + } + return orangered; + } + } + + public static Pen Orchid { + get { + if (orchid == null) { + orchid = new Pen(Color.Orchid); + orchid.canChange = false; + } + return orchid; + } + } + + public static Pen PaleGoldenrod { + get { + if (palegoldenrod == null) { + palegoldenrod = new Pen(Color.PaleGoldenrod); + palegoldenrod.canChange = false; + } + return palegoldenrod; + } + } + + public static Pen PaleGreen { + get { + if (palegreen == null) { + palegreen = new Pen(Color.PaleGreen); + palegreen.canChange = false; + } + return palegreen; + } + } + + public static Pen PaleTurquoise { + get { + if (paleturquoise == null) { + paleturquoise = new Pen(Color.PaleTurquoise); + paleturquoise.canChange = false; + } + return paleturquoise; + } + } + + public static Pen PaleVioletRed { + get { + if (palevioletred == null) { + palevioletred = new Pen(Color.PaleVioletRed); + palevioletred.canChange = false; + } + return palevioletred; + } + } + + public static Pen PapayaWhip { + get { + if (papayawhip == null) { + papayawhip = new Pen(Color.PapayaWhip); + papayawhip.canChange = false; + } + return papayawhip; + } + } + + public static Pen PeachPuff { + get { + if (peachpuff == null) { + peachpuff = new Pen(Color.PeachPuff); + peachpuff.canChange = false; + } + return peachpuff; + } + } + + public static Pen Peru { + get { + if (peru == null) { + peru = new Pen(Color.Peru); + peru.canChange = false; + } + return peru; + } + } + + public static Pen Pink { + get { + if (pink == null) { + pink = new Pen(Color.Pink); + pink.canChange = false; + } + return pink; + } + } + + public static Pen Plum { + get { + if (plum == null) { + plum = new Pen(Color.Plum); + plum.canChange = false; + } + return plum; + } + } + + public static Pen PowderBlue { + get { + if (powderblue == null) { + powderblue = new Pen(Color.PowderBlue); + powderblue.canChange = false; + } + return powderblue; + } + } + + public static Pen Purple { + get { + if (purple == null) { + purple = new Pen(Color.Purple); + purple.canChange = false; + } + return purple; + } + } + + public static Pen Red { + get { + if (red == null) { + red = new Pen(Color.Red); + red.canChange = false; + } + return red; + } + } + + public static Pen RosyBrown { + get { + if (rosybrown == null) { + rosybrown = new Pen(Color.RosyBrown); + rosybrown.canChange = false; + } + return rosybrown; + } + } + + public static Pen RoyalBlue { + get { + if (royalblue == null) { + royalblue = new Pen(Color.RoyalBlue); + royalblue.canChange = false; + } + return royalblue; + } + } + + public static Pen SaddleBrown { + get { + if (saddlebrown == null) { + saddlebrown = new Pen(Color.SaddleBrown); + saddlebrown.canChange = false; + } + return saddlebrown; + } + } + + public static Pen Salmon { + get { + if (salmon == null) { + salmon = new Pen(Color.Salmon); + salmon.canChange = false; + } + return salmon; + } + } + + public static Pen SandyBrown { + get { + if (sandybrown == null) { + sandybrown = new Pen(Color.SandyBrown); + sandybrown.canChange = false; + } + return sandybrown; + } + } + + public static Pen SeaGreen { + get { + if (seagreen == null) { + seagreen = new Pen(Color.SeaGreen); + seagreen.canChange = false; + } + return seagreen; + } + } + + public static Pen SeaShell { + get { + if (seashell == null) { + seashell = new Pen(Color.SeaShell); + seashell.canChange = false; + } + return seashell; + } + } + + public static Pen Sienna { + get { + if (sienna == null) { + sienna = new Pen(Color.Sienna); + sienna.canChange = false; + } + return sienna; + } + } + + public static Pen Silver { + get { + if (silver == null) { + silver = new Pen(Color.Silver); + silver.canChange = false; + } + return silver; + } + } + + public static Pen SkyBlue { + get { + if (skyblue == null) { + skyblue = new Pen(Color.SkyBlue); + skyblue.canChange = false; + } + return skyblue; + } + } + + public static Pen SlateBlue { + get { + if (slateblue == null) { + slateblue = new Pen(Color.SlateBlue); + slateblue.canChange = false; + } + return slateblue; + } + } + + public static Pen SlateGray { + get { + if (slategray == null) { + slategray = new Pen(Color.SlateGray); + slategray.canChange = false; + } + return slategray; + } + } + + public static Pen Snow { + get { + if (snow == null) { + snow = new Pen(Color.Snow); + snow.canChange = false; + } + return snow; + } + } + + public static Pen SpringGreen { + get { + if (springgreen == null) { + springgreen = new Pen(Color.SpringGreen); + springgreen.canChange = false; + } + return springgreen; + } + } + + public static Pen SteelBlue { + get { + if (steelblue == null) { + steelblue = new Pen(Color.SteelBlue); + steelblue.canChange = false; + } + return steelblue; + } + } + + public static Pen Tan { + get { + if (tan == null) { + tan = new Pen(Color.Tan); + tan.canChange = false; + } + return tan; + } + } + + public static Pen Teal { + get { + if (teal == null) { + teal = new Pen(Color.Teal); + teal.canChange = false; + } + return teal; + } + } + + public static Pen Thistle { + get { + if (thistle == null) { + thistle = new Pen(Color.Thistle); + thistle.canChange = false; + } + return thistle; + } + } + + public static Pen Tomato { + get { + if (tomato == null) { + tomato = new Pen(Color.Tomato); + tomato.canChange = false; + } + return tomato; + } + } + + public static Pen Transparent { + get { + if (transparent == null) { + transparent = new Pen(Color.Transparent); + transparent.canChange = false; + } + return transparent; + } + } + + public static Pen Turquoise { + get { + if (turquoise == null) { + turquoise = new Pen(Color.Turquoise); + turquoise.canChange = false; + } + return turquoise; + } + } + + public static Pen Violet { + get { + if (violet == null) { + violet = new Pen(Color.Violet); + violet.canChange = false; + } + return violet; + } + } + + public static Pen Wheat { + get { + if (wheat == null) { + wheat = new Pen(Color.Wheat); + wheat.canChange = false; + } + return wheat; + } + } + + public static Pen White { + get { + if (white == null) { + white = new Pen(Color.White); + white.canChange = false; + } + return white; + } + } + + public static Pen WhiteSmoke { + get { + if (whitesmoke == null) { + whitesmoke = new Pen(Color.WhiteSmoke); + whitesmoke.canChange = false; + } + return whitesmoke; + } + } + + public static Pen Yellow { + get { + if (yellow == null) { + yellow = new Pen(Color.Yellow); + yellow.canChange = false; + } + return yellow; + } + } + + public static Pen YellowGreen { + get { + if (yellowgreen == null) { + yellowgreen = new Pen(Color.YellowGreen); + yellowgreen.canChange = false; + } + return yellowgreen; + + } + } + + } +} diff --git a/System.Drawing/System.Drawing/Point.cs b/System.Drawing/System.Drawing/Point.cs new file mode 100644 index 0000000..b36b0cf --- /dev/null +++ b/System.Drawing/System.Drawing/Point.cs @@ -0,0 +1,125 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Drawing { + public struct Point { + + public static readonly Point Empty = new Point(); + + private int x, y; + + public Point(int dw) { + this.x = dw >> 16; + this.y = dw & 0xffff; + } + + public Point(int x, int y) { + this.x = x; + this.y = y; + } + + public Point(Size sz) { + this.x = sz.Width; + this.y = sz.Height; + } + + public int X { + get { + return this.x; + } + set { + this.x = value; + } + } + + public int Y { + get { + return this.y; + } + set { + this.y = value; + } + } + + public bool IsEmpty { + get { + return this.x == 0 && this.y == 0; + } + } + + public void Offset(int dx, int dy) { + this.x += dx; + this.y += dy; + } + + public void Offset(Point pt) { + this.x += pt.x; + this.y += pt.y; + } + + public static Point Add(Point pt, Size sz) { + return new Point(pt.x + sz.Width, pt.y + sz.Height); + } + + public static Point Subtract(Point pt, Size sz) { + return new Point(pt.x - sz.Width, pt.y - sz.Height); + } + + public static Point operator +(Point pt, Size sz) { + return new Point(pt.x + sz.Width, pt.y + sz.Height); + } + + public static Point operator -(Point pt, Size sz) { + return new Point(pt.x - sz.Width, pt.y - sz.Height); + } + + public static bool operator ==(Point a, Point b) { + return ((a.x == b.x) && (a.y == b.y)); + } + + public static bool operator !=(Point a, Point b) { + return ((a.x != b.x) || (a.y != b.y)); + } + + public static explicit operator Size(Point pt) { + return new Size(pt.x, pt.x); + } + + public override bool Equals(object o) { + if (!(o is Point)) { + return false; + } + return this == (Point)o; + } + + public override int GetHashCode() { + return x ^ y; + } + + public override string ToString() { + return string.Format("{{X={0},Y={1}}}", x, y); + } + + } +} diff --git a/System.Drawing/System.Drawing/PointF.cs b/System.Drawing/System.Drawing/PointF.cs new file mode 100644 index 0000000..71d2a75 --- /dev/null +++ b/System.Drawing/System.Drawing/PointF.cs @@ -0,0 +1,81 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Drawing { + public struct PointF { + + private float x, y; + + public static readonly PointF Empty; + + public PointF(float x, float y) { + this.x = x; + this.y = y; + } + + public float X { + get { + return this.x; + } + set { + this.x = value; + } + } + + public float Y { + get { + return this.y; + } + set { + this.y = value; + } + } + + public bool IsEmpty { + get { + return this.x == 0.0f && this.y == 0.0f; + } + } + + public static bool operator ==(PointF a, PointF b) { + return a.x == b.x && a.y == b.y; + } + + public static bool operator !=(PointF a, PointF b) { + return a.x != b.x || a.y != b.y; + } + + public override bool Equals(object obj) { + return obj is PointF && (PointF)obj == this; + } + + public override int GetHashCode() { + return (int)this.x ^ (int)this.y; + } + + public override string ToString() { + return String.Format("{{X={0}, Y={1}}}", this.x, this.y); + } + } +} diff --git a/System.Drawing/System.Drawing/Rectangle.cs b/System.Drawing/System.Drawing/Rectangle.cs new file mode 100644 index 0000000..4de1606 --- /dev/null +++ b/System.Drawing/System.Drawing/Rectangle.cs @@ -0,0 +1,220 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Drawing { + public struct Rectangle { + + public static readonly Rectangle Empty = new Rectangle(); + + public static Rectangle FromLTRB(int left, int top, int right, int bottom) { + return new Rectangle(left, top, right - left, bottom - top); + } + + public static Rectangle Inflate(Rectangle rect, int x, int y) { + Rectangle r = new Rectangle(rect.Location, rect.Size); + r.Inflate(x, y); + return r; + } + + private int x, y, width, height; + + public Rectangle(int x, int y, int width, int height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + public Rectangle(Point loc, Size sz) { + this.x = loc.X; + this.y = loc.Y; + this.width = sz.Width; + this.height = sz.Height; + } + + public int X { + get { + return this.x; + } + set { + this.x = value; + } + } + + public int Y { + get { + return this.y; + } + set { + this.y = value; + } + } + + public int Width { + get { + return this.width; + } + set { + this.width = value; + } + } + + public int Height { + get { + return this.height; + } + set { + this.height = value; + } + } + + public int Left { + get { + return this.x; + } + } + + public int Right { + get { + return this.x + this.width; + } + } + + public int Top { + get { + return this.y; + } + } + + public int Bottom { + get { + return this.y + this.height; + } + } + + public Point Location { + get { + return new Point(this.x, this.y); + } + set { + this.x = value.X; + this.y = value.Y; + } + } + + public Size Size { + get { + return new Size(this.width, this.height); + } + set { + this.width = value.Width; + this.height = value.Height; + } + } + + public void Inflate(int width, int height) { + this.x -= width; + this.y -= height; + this.width += width * 2; + this.height += height * 2; + } + + + public void Inflate(Size sz) { + Inflate(sz.Width, sz.Height); + } + + public void Offset(Point pt) { + this.x += pt.X; + this.y += pt.Y; + } + + public void Offset(int dx, int dy) { + this.x += dx; + this.y += dy; + } + + public bool Contains(int x, int y) { + return (x >= Left) && (x < Right) && (y >= Top) && (y < Bottom); + } + + public bool Contains(Point pt) { + return Contains(pt.X, pt.Y); + } + + public bool Contains(Rectangle rect) { + return rect == Intersect(this, rect); + } + + public bool IntersectsWith(Rectangle r) { + return !((Left >= r.Right) || (Right <= r.Left) || (Top >= r.Bottom) || (Bottom <= r.Top)); + } + + private bool IntersectsWithInclusive(Rectangle r) { + return !((Left > r.Right) || (Right < r.Left) || (Top > r.Bottom) || (Bottom < r.Top)); + } + + public void Intersect(Rectangle r) { + this = Rectangle.Intersect(this, r); + } + + public static Rectangle Intersect(Rectangle r1, Rectangle r2) { + // MS.NET returns a non-empty rectangle if the two rectangles + // touch each other + if (!r1.IntersectsWithInclusive(r2)) { + return Empty; + } + + return Rectangle.FromLTRB( + Math.Max(r1.x, r2.x), + Math.Max(r1.y, r2.y), + Math.Min(r1.Right, r2.Right), + Math.Min(r1.Bottom, r2.Bottom)); + } + + public static bool operator ==(Rectangle r1, Rectangle r2) { + return ((r1.Location == r2.Location) && (r1.Size == r2.Size)); + } + + public static bool operator !=(Rectangle r1, Rectangle r2) { + return ((r1.Location != r2.Location) || (r1.Size != r2.Size)); + } + + public override bool Equals(object o) { + if (!(o is Rectangle)) { + return false; + } + return this == (Rectangle)o; + } + + public override int GetHashCode() { + return ((this.height + this.width) ^ this.x) + this.y; + } + + public override string ToString() { + return String.Format("{{X={0},Y={1},Width={2},Height={3}}}", this.x, this.y, this.width, this.height); + } + + } +} diff --git a/System.Drawing/System.Drawing/RectangleF.cs b/System.Drawing/System.Drawing/RectangleF.cs new file mode 100644 index 0000000..62db499 --- /dev/null +++ b/System.Drawing/System.Drawing/RectangleF.cs @@ -0,0 +1,110 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Drawing { + public struct RectangleF { + + private float x, y, width, height; + + public static readonly RectangleF Empty; + + public RectangleF(PointF location, SizeF size) { + this.x = location.X; + this.y = location.Y; + this.width = size.Width; + this.height = size.Height; + } + + public RectangleF(float x, float y, float width, float height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + public float X { + get { + return this.x; + } + set { + this.x = value; + } + } + + public float Y { + get { + return this.y; + } + set { + this.y = value; + } + } + + public float Width { + get { + return this.width; + } + set { + this.width = value; + } + } + + public float Height { + get { + return this.height; + } + set { + this.height = value; + } + } + + public float Left { + get { + return this.x; + } + } + + public float Right { + get { + return this.x + this.width; + } + } + + public float Top { + get { + return this.y; + } + } + + public float Bottom { + get { + return this.y + this.height; + } + } + + public static implicit operator RectangleF(Rectangle r) { + return new RectangleF(r.X, r.Y, r.Width, r.Height); + } + } +} diff --git a/System.Drawing/System.Drawing/Region.cs b/System.Drawing/System.Drawing/Region.cs new file mode 100644 index 0000000..21fb850 --- /dev/null +++ b/System.Drawing/System.Drawing/Region.cs @@ -0,0 +1,58 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Drawing { + public sealed class Region : MarshalByRefObject, IDisposable { + + internal IntPtr native = IntPtr.Zero; + private bool isInfinite; + + public Region() { + this.native = LibIGraph.CreateRegion_Infinite(); + this.isInfinite = true; + } + + public Region(Rectangle rect) { + this.native = LibIGraph.CreateRegion_Rect(rect.X, rect.Y, rect.Width, rect.Height); + this.isInfinite = false; + } + + ~Region() { + this.Dispose(); + } + + public void Dispose() { + if (this.native != null) { + LibIGraph.DisposeRegion(this.native); + this.native = IntPtr.Zero; + GC.SuppressFinalize(this); + } + } + + public bool IsInfinite(Graphics g) { + return this.isInfinite; + } + + } +} diff --git a/System.Drawing/System.Drawing/Size.cs b/System.Drawing/System.Drawing/Size.cs new file mode 100644 index 0000000..25b3289 --- /dev/null +++ b/System.Drawing/System.Drawing/Size.cs @@ -0,0 +1,110 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Drawing { + public struct Size { + + public static readonly Size Empty = new Size(); + + private int width, height; + + public Size(int width, int height) { + this.width = width; + this.height = height; + } + + public Size(Point pt) { + this.width = pt.X; + this.height = pt.Y; + } + + public int Width { + get { + return this.width; + } + set { + this.width = value; + } + } + + public int Height { + get { + return this.height; + } + set { + this.height = value; + } + } + + public bool IsEmpty { + get { + return this.width == 0 && this.height == 0; + } + } + + public static Size Add(Size a, Size b) { + return new Size(a.Width + b.Width, a.Height + b.Height); + } + + public static Size Subtract(Size a, Size b) { + return new Size(a.Width - b.Width, a.Height - b.Height); + } + + public static Size operator +(Size a, Size b) { + return new Size(a.Width + b.Width, a.Height + b.Height); + } + + public static Size operator -(Size a, Size b) { + return new Size(a.Width - b.Width, a.Height - b.Height); + } + + public static bool operator ==(Size a, Size b) { + return ((a.Width == b.Width) && (a.Height == b.Height)); + } + + public static bool operator !=(Size a, Size b) { + return ((a.Width != b.Width) || (a.Height != b.Height)); + } + + public static explicit operator Point(Size sz) { + return new Point(sz.Width, sz.Height); + } + + public override bool Equals(object o) { + if (!(o is Size)) { + return false; + } + return this == (Size)o; + } + + public override int GetHashCode() { + return width ^ height; + } + + public override string ToString() { + return String.Format("{{Width={0}, Height={1}}}", width, height); + } + + } +} diff --git a/System.Drawing/System.Drawing/SizeF.cs b/System.Drawing/System.Drawing/SizeF.cs new file mode 100644 index 0000000..bdc4326 --- /dev/null +++ b/System.Drawing/System.Drawing/SizeF.cs @@ -0,0 +1,91 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Drawing { + public struct SizeF { + + private float width, height; + + public static readonly SizeF Empty; + + public SizeF(PointF pt) { + this.width = pt.X; + this.height = pt.Y; + } + + public SizeF(SizeF size) { + this.width = size.width; + this.height = size.height; + } + + public SizeF(float width, float height) { + this.width = width; + this.height = height; + } + + public float Width { + get { + return this.width; + } + set { + this.width = value; + } + } + + public float Height { + get { + return this.height; + } + set { + this.height = value; + } + } + + public bool IsEmpty { + get { + return this.width == 0.0f && this.height == 0.0f; + } + } + + public static bool operator ==(SizeF a, SizeF b) { + return a.width == b.width && a.height == b.height; + } + + public static bool operator !=(SizeF a, SizeF b) { + return a.width != b.width || a.height != b.height; + } + + public override bool Equals(object obj) { + return obj is SizeF && (SizeF)obj == this; + } + + public override int GetHashCode() { + return (int)this.width ^ (int)this.height; + } + + public override string ToString() { + return string.Format("{{Width={0}, Height={1}}}", width, height); + } + } +} diff --git a/System.Drawing/System.Drawing/SolidBrush.cs b/System.Drawing/System.Drawing/SolidBrush.cs new file mode 100644 index 0000000..3404c13 --- /dev/null +++ b/System.Drawing/System.Drawing/SolidBrush.cs @@ -0,0 +1,59 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Drawing { + public sealed class SolidBrush : Brush { + + private Color col; + internal bool canChange = true; + + public SolidBrush(Color col) { + this.col = col; + base.native = LibIGraph.CreateBrush_Solid(col.ToArgb()); + } + + public Color Color { + get { + return this.col; + } + set { + if (canChange) { + this.col = value; + LibIGraph.SolidBrush_SetCol(base.native, value.ToArgb()); + } else { + throw new ArgumentException("This SolidBrush cannot be changed."); + } + } + } + + protected override void Dispose(bool disposing) { + if (disposing && !this.canChange) { + // If this is a system brush, then refuse to dispose of it. + throw new ArgumentException("This SolidBrush cannot be changed."); + } + base.Dispose(disposing); + } + + } +} diff --git a/System.Drawing/System.Drawing/StringAlignment.cs b/System.Drawing/System.Drawing/StringAlignment.cs new file mode 100644 index 0000000..aa6d2fc --- /dev/null +++ b/System.Drawing/System.Drawing/StringAlignment.cs @@ -0,0 +1,31 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Drawing { + public enum StringAlignment { + Near = 0, + Center = 1, + Far = 2 + } +} diff --git a/System.Drawing/System.Drawing/StringFormat.cs b/System.Drawing/System.Drawing/StringFormat.cs new file mode 100644 index 0000000..07c3b9b --- /dev/null +++ b/System.Drawing/System.Drawing/StringFormat.cs @@ -0,0 +1,125 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Drawing { + public sealed class StringFormat : MarshalByRefObject, IDisposable, ICloneable { + + internal IntPtr native = IntPtr.Zero; + + private static StringFormat genericDefault = null; + private static StringFormat genericTypographic = null; + + private StringTrimming trimming; + private StringAlignment alignment; + private StringAlignment lineAlignment; + private StringFormatFlags stringFormatFlags; + + public StringFormat() : this(0) { } + + public StringFormat(StringFormatFlags options) { + this.native = LibIGraph.CreateStringFormat + (StringAlignment.Near, options, StringAlignment.Near, StringTrimming.None); + this.trimming = StringTrimming.None; + this.alignment = StringAlignment.Near; + this.lineAlignment = StringAlignment.Near; + this.stringFormatFlags = options; + } + + ~StringFormat() { + this.Dispose(); + } + + public StringTrimming Trimming { + get { + return this.trimming; + } + set { + LibIGraph.StringFormat_SetTrimming(this.native, value); + this.trimming = value; + } + } + + public StringAlignment Alignment { + get { + return this.alignment; + } + set { + LibIGraph.StringFormat_SetAlignment(this.native, value); + this.alignment = value; + } + } + + public StringAlignment LineAlignment { + get { + return this.lineAlignment; + } + set { + LibIGraph.StringFormat_SetLineAlignment(this.native, value); + this.lineAlignment = value; + } + } + + public StringFormatFlags FormatFlags { + get { + return this.stringFormatFlags; + } + set { + LibIGraph.StringFormat_SetFormatFlags(this.native, value); + this.stringFormatFlags = value; + } + } + + public static StringFormat GenericDefault { + get { + if (genericDefault == null) { + genericDefault = new StringFormat(); + genericDefault.Trimming = StringTrimming.Character; + } + return genericDefault; + } + } + + public static StringFormat GenericTypographic { + get { + if (genericTypographic == null) { + genericTypographic = new StringFormat + (StringFormatFlags.NoClip | StringFormatFlags.FitBlackBox | StringFormatFlags.LineLimit); + } + return genericTypographic; + } + } + + public object Clone() { + throw new Exception("The method or operation is not implemented."); + } + + public void Dispose() { + if (this.native != IntPtr.Zero) { + LibIGraph.DisposeStringFormat(this.native); + this.native = IntPtr.Zero; + GC.SuppressFinalize(this); + } + } + } +} diff --git a/System.Drawing/System.Drawing/StringFormatFlags.cs b/System.Drawing/System.Drawing/StringFormatFlags.cs new file mode 100644 index 0000000..8b3d08a --- /dev/null +++ b/System.Drawing/System.Drawing/StringFormatFlags.cs @@ -0,0 +1,37 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Drawing { + public enum StringFormatFlags { + DirectionRightToLeft = 0x0001, + DirectionVertical = 0x0002, + FitBlackBox = 0x0004, + DisplayFormatControl = 0x0020, + NoFontFallback = 0x0400, + MeasureTrailingSpaces = 0x0800, + NoWrap = 0x1000, + LineLimit = 0x2000, + NoClip = 0x4000 + } +} diff --git a/System.Drawing/System.Drawing/StringTrimming.cs b/System.Drawing/System.Drawing/StringTrimming.cs new file mode 100644 index 0000000..253d5e5 --- /dev/null +++ b/System.Drawing/System.Drawing/StringTrimming.cs @@ -0,0 +1,34 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Drawing { + public enum StringTrimming { + None = 0, + Character = 1, + Word = 2, + EllipsisCharacter = 3, + EllipsisWord = 4, + EllipsisPath = 5 + } +} diff --git a/System/Properties/AssemblyInfo.cs b/System/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..905f5bf --- /dev/null +++ b/System/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +/*using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("System")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Docobo")] +[assembly: AssemblyProduct("System")] +[assembly: AssemblyCopyright("Copyright © Docobo 2007")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("ac7fc7c3-9352-46c9-a145-9737bfab7e1a")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] +*/ \ No newline at end of file diff --git a/System/System.Collections.Generic/Queue.cs b/System/System.Collections.Generic/Queue.cs new file mode 100644 index 0000000..a753fa8 --- /dev/null +++ b/System/System.Collections.Generic/Queue.cs @@ -0,0 +1,245 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Collections.Generic { + public class Queue : IEnumerable, ICollection, IEnumerable { + T[] _array; + int _head; + int _tail; + int _size; + int _version; + + private const int INITIAL_SIZE = 16; + + public Queue() { + } + + public Queue(int count) { + if (count < 0) + throw new ArgumentOutOfRangeException("count"); + + _array = new T[count]; + } + + public Queue(IEnumerable collection) { + if (collection == null) + throw new ArgumentNullException("collection"); + + foreach (T t in collection) + Enqueue(t); + } + + public void Clear() { + if (_array != null) + Array.Clear(_array, 0, _array.Length); + + _head = _tail = _size = 0; + _version++; + } + + public bool Contains(T item) { + if (item == null) { + foreach (T t in this) + if (t == null) + return true; + } else { + foreach (T t in this) + if (item.Equals(t)) + return true; + } + + return false; + } + + public void CopyTo(T[] array, int idx) { + if (array == null) + throw new ArgumentNullException(); + + if ((uint)idx > (uint)array.Length) + throw new ArgumentOutOfRangeException(); + + if (array.Length - idx < _size) + throw new ArgumentOutOfRangeException(); + + if (_size == 0) + return; + + int contents_length = _array.Length; + int length_from_head = contents_length - _head; + + Array.Copy(_array, _head, array, idx, Math.Min(_size, length_from_head)); + if (_size > length_from_head) + Array.Copy(_array, 0, array, + idx + length_from_head, + _size - length_from_head); + + } + + void ICollection.CopyTo(Array array, int idx) { + if (array == null) + throw new ArgumentNullException(); + + if ((uint)idx < (uint)array.Length) + throw new ArgumentOutOfRangeException(); + + if (array.Length - idx < _size) + throw new ArgumentOutOfRangeException(); + + if (_size == 0) + return; + + try { + int contents_length = _array.Length; + int length_from_head = contents_length - _head; + + Array.Copy(_array, _head, array, idx, Math.Min(_size, length_from_head)); + if (_size > length_from_head) + Array.Copy(_array, 0, array, + idx + length_from_head, + _size - length_from_head); + } catch (ArrayTypeMismatchException) { + throw new ArgumentException(); + } + } + + public T Dequeue() { + T ret = Peek(); + + // clear stuff out to make the GC happy + _array[_head] = default(T); + + if (++_head == _array.Length) + _head = 0; + _size--; + _version++; + + return ret; + } + + public T Peek() { + if (_size == 0) + throw new InvalidOperationException(); + + return _array[_head]; + } + + public void Enqueue(T item) { + if (_array == null || _size == _array.Length) + SetCapacity(Math.Max(_size * 2, 4)); + + _array[_tail] = item; + + if (++_tail == _array.Length) + _tail = 0; + + _size++; + _version++; + } + + public T[] ToArray() { + T[] t = new T[_size]; + CopyTo(t, 0); + return t; + } + + public void TrimExcess() { + if (_array != null && (_size < _array.Length * 0.9)) + SetCapacity(_size); + } + + void SetCapacity(int new_size) { + if (_array != null && new_size == _array.Length) + return; + + if (new_size < _size) + throw new InvalidOperationException("shouldnt happen"); + + T[] new_data = new T[new_size]; + if (_size > 0) + CopyTo(new_data, 0); + + _array = new_data; + _tail = _size; + _head = 0; + _version++; + } + + public int Count { + get { return _size; } + } + + bool ICollection.IsSynchronized { + get { return false; } + } + + object ICollection.SyncRoot { + get { return this; } + } + + public Enumerator GetEnumerator() { + return new Enumerator(this); + } + + IEnumerator IEnumerable.GetEnumerator() { + return GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() { + return GetEnumerator(); + } + + public struct Enumerator : IEnumerator, IEnumerator, IDisposable { + const int NOT_STARTED = -2; + + // this MUST be -1, because we depend on it in move next. + // we just decr the _size, so, 0 - 1 == FINISHED + const int FINISHED = -1; + + Queue q; + int idx; + int ver; + + internal Enumerator(Queue q) { + this.q = q; + idx = NOT_STARTED; + ver = q._version; + } + + public void Dispose() { + idx = NOT_STARTED; + } + + public bool MoveNext() { + if (ver != q._version) + throw new InvalidOperationException(); + + if (idx == NOT_STARTED) + idx = q._size; + + return idx != FINISHED && --idx != FINISHED; + } + + public T Current { + get { + if (idx < 0) + throw new InvalidOperationException(); + + return q._array[(q._size - 1 - idx + q._head) % q._array.Length]; + } + } + + void IEnumerator.Reset() { + if (ver != q._version) + throw new InvalidOperationException(); + + idx = NOT_STARTED; + } + + object IEnumerator.Current { + get { return Current; } + } + + } + } +} diff --git a/System/System.Collections.Generic/Stack.cs b/System/System.Collections.Generic/Stack.cs new file mode 100644 index 0000000..ec9f491 --- /dev/null +++ b/System/System.Collections.Generic/Stack.cs @@ -0,0 +1,239 @@ +// +// System.Collections.Generic.Stack +// +// Authors: +// Martin Baulig (martin@ximian.com) +// Ben Maurer (bmaurer@ximian.com) +// +// (C) 2003, 2004 Novell, Inc. +// + +// +// Copyright (C) 2004 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +//using System.Runtime.InteropServices; + +namespace System.Collections.Generic +{ + public class Stack : IEnumerable , ICollection, IEnumerable + { + T [] _array; + int _size; + int _version; + + private const int INITIAL_SIZE = 16; + + public Stack () + { + } + + public Stack (int count) + { + if (count < 0) + throw new ArgumentOutOfRangeException ("count"); + + _array = new T [count]; + } + + public Stack (IEnumerable collection) + { + if (collection == null) + throw new ArgumentNullException ("collection"); + + ICollection col = collection as ICollection ; + + if (col != null) { + _size = col.Count; + _array = new T [_size]; + col.CopyTo (_array, 0); + } else { + foreach (T t in collection) + Push (t); + } + } + + public void Clear () + { + if (_array != null) + Array.Clear (_array, 0, _array.Length); + + _size = 0; + _version ++; + } + + public bool Contains (T t) + { + return _array != null && Array.IndexOf (_array, t, 0, _size) != -1; + } + + public void CopyTo (T [] dest, int idx) + { + // this gets copied in the order that it is poped + if (_array != null) { + Array.Copy (_array, 0, dest, idx, _size); + Array.Reverse (dest, idx, _size); + } + } + + public T Peek () + { + if (_size == 0) + throw new InvalidOperationException (); + + return _array [_size - 1]; + } + + public T Pop () + { + if (_size == 0) + throw new InvalidOperationException (); + + _version ++; + T popped = _array [--_size]; + // clear stuff out to make the GC happy + _array [_size] = default(T); + return popped; + } + + public void Push (T t) + { + if (_size == 0 || _size == _array.Length) + Array.Resize (ref _array, _size == 0 ? INITIAL_SIZE : 2 * _size); + + _version ++; + + _array [_size++] = t; + } + + public T [] ToArray () + { + T [] copy = new T [_size]; + CopyTo (copy, 0); + return copy; + } + + public void TrimExcess () + { + if (_array != null && (_size < _array.Length * 0.9)) + Array.Resize (ref _array, _size); + _version ++; + } + + public int Count { + get { return _size; } + } + + bool ICollection.IsSynchronized { + get { return false; } + } + + object ICollection.SyncRoot { + get { return this; } + } + + void ICollection.CopyTo (Array dest, int idx) + { + try { + if (_array != null) { + _array.CopyTo (dest, idx); + Array.Reverse (dest, idx, _size); + } + } catch (ArrayTypeMismatchException) { + throw new ArgumentException (); + } + } + + public Enumerator GetEnumerator () + { + return new Enumerator (this); + } + + IEnumerator IEnumerable.GetEnumerator () + { + return GetEnumerator (); + } + + IEnumerator IEnumerable.GetEnumerator () + { + return GetEnumerator (); + } + + public struct Enumerator : IEnumerator , IEnumerator, IDisposable { + const int NOT_STARTED = -2; + + // this MUST be -1, because we depend on it in move next. + // we just decr the _size, so, 0 - 1 == FINISHED + const int FINISHED = -1; + + Stack parent; + int idx; + int _version; + + internal Enumerator (Stack t) + { + parent = t; + idx = NOT_STARTED; + _version = t._version; + } + + public void Dispose () + { + idx = NOT_STARTED; + } + + public bool MoveNext () + { + if (_version != parent._version) + throw new InvalidOperationException (); + + if (idx == -2) + idx = parent._size; + + return idx != FINISHED && -- idx != FINISHED; + } + + public T Current { + get { + if (idx < 0) + throw new InvalidOperationException (); + + return parent._array [idx]; + } + } + + void IEnumerator.Reset () + { + if (_version != parent._version) + throw new InvalidOperationException (); + + idx = NOT_STARTED; + } + + object IEnumerator.Current { + get { return Current; } + } + + } + } +} diff --git a/System/System.ComponentModel/Win32Exception.cs b/System/System.ComponentModel/Win32Exception.cs new file mode 100644 index 0000000..8f3d469 --- /dev/null +++ b/System/System.ComponentModel/Win32Exception.cs @@ -0,0 +1,50 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Runtime.InteropServices; + +namespace System.ComponentModel { + public class Win32Exception : ExternalException { + + private int nativeError = 0; + + public Win32Exception() : base("Win32 exception", 0) { } + + public Win32Exception(int err) + : base("Win32 exception", err) { + this.nativeError = err; + } + + public Win32Exception(int err, string msg) + : base(msg, err) { + this.nativeError = err; + } + + public int NativeErrorCode { + get { + return this.nativeError; + } + } + + } +} diff --git a/System/System.Net.Sockets/AddressFamily.cs b/System/System.Net.Sockets/AddressFamily.cs new file mode 100644 index 0000000..4c33b79 --- /dev/null +++ b/System/System.Net.Sockets/AddressFamily.cs @@ -0,0 +1,59 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Net.Sockets { + public enum AddressFamily { + Unknown = -1, + Unspecified = 0, + Unix = 1, + InterNetwork = 2, + ImpLink = 3, + Pup = 4, + Chaos = 5, + NS = 6, + Ipx = 6, + Iso = 7, + Osi = 7, + Ecma = 8, + DataKit = 9, + Ccitt = 10, + Sna = 11, + DecNet = 12, + DataLink = 13, + Lat = 14, + HyperChannel = 15, + AppleTalk = 16, + NetBios = 17, + VoiceView = 18, + FireFox = 19, + Banyan = 21, + Atm = 22, + InterNetworkV6 = 23, + Cluster = 24, + Ieee12844 = 25, + Irda = 26, + NetworkDesigners = 28, + Max = 29, + } +} diff --git a/System/System.Net.Sockets/ProtocolType.cs b/System/System.Net.Sockets/ProtocolType.cs new file mode 100644 index 0000000..23afcd5 --- /dev/null +++ b/System/System.Net.Sockets/ProtocolType.cs @@ -0,0 +1,53 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Net.Sockets { + public enum ProtocolType { + IP = 0, + Icmp = 1, + Igmp = 2, + Ggp = 3, + Tcp = 6, + Pup = 12, + Udp = 17, + Idp = 22, + IPv6 = 41, + ND = 77, + Raw = 255, + Unspecified = 0, + Ipx = 1000, + Spx = 1256, + SpxII = 1257, + Unknown = -1, + IPv4 = 4, + IPv6RoutingHeader = 43, + IPv6FragmentHeader = 44, + IPSecEncapsulatingSecurityPayload = 50, + IPSecAuthenticationHeader = 51, + IcmpV6 = 58, + IPv6NoNextHeader = 59, + IPv6DestinationOptions = 60, + IPv6HopByHopOptions = 0, + } +} diff --git a/System/System.Net.Sockets/Socket.cs b/System/System.Net.Sockets/Socket.cs new file mode 100644 index 0000000..a769ecc --- /dev/null +++ b/System/System.Net.Sockets/Socket.cs @@ -0,0 +1,217 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Runtime.CompilerServices; + +namespace System.Net.Sockets { + public class Socket : IDisposable { + + #region Internal Methods + + [MethodImpl(MethodImplOptions.InternalCall)] + extern private static IntPtr Internal_CreateSocket(int family, int type, int proto, out int error); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern private static void Internal_Close(IntPtr native); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern private static void Internal_Bind(IntPtr native, uint address, int port, out int error); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern private static void Internal_Listen(IntPtr native, int backLog, out int error); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern private static IntPtr Internal_Accept(IntPtr native, out int error); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern private static void Internal_Connect(IntPtr native, uint address, int port, out int error); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern private static int Internal_Receive(IntPtr native, byte[] buffer, int offset, int size, int flags, out int error); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern private static int Internal_Send(IntPtr native, byte[] buffer, int offset, int size, int flags, out int error); + + #endregion + + private IntPtr native; + private AddressFamily family; + private SocketType type; + private ProtocolType proto; + + public Socket(AddressFamily family, SocketType type, ProtocolType proto) { + this.family = family; + this.type = type; + this.proto = proto; + + int error; + this.native = Internal_CreateSocket((int)family, (int)type, (int)proto, out error); + this.CheckError(error); + } + + private Socket(AddressFamily family, SocketType type, ProtocolType proto, IntPtr native) { + this.family = family; + this.type = type; + this.proto = proto; + this.native = native; + } + + ~Socket() { + this.Dispose(false); + } + + private void Dispose(bool disposing) { + if (this.native != IntPtr.Zero) { + Internal_Close(this.native); + this.native = IntPtr.Zero; + if (disposing) { + GC.SuppressFinalize(this); + } + } + } + + void IDisposable.Dispose() { + this.Dispose(true); + } + + public void Close() { + this.Dispose(true); + } + + private void CheckDisposed() { + if (this.native == IntPtr.Zero) { + throw new ObjectDisposedException(this.GetType().ToString()); + } + } + + private void CheckError(int error) { + if (error != 0) { + Console.WriteLine("SOCKET_ERROR {0}", error); + throw new SocketException(error); + } + } + + private void GetIPInfo(EndPoint ep, out uint addr, out int port) { + if (ep.AddressFamily != AddressFamily.InterNetwork) { + throw new ArgumentException("EndPoint", "Can only handle IPv4 addresses"); + } + SocketAddress sockAddr = ep.Serialize(); + port = (((int)sockAddr[2]) << 8) | sockAddr[3]; + addr = ((((uint)sockAddr[7]) << 24) | (((uint)sockAddr[6]) << 16) | + (((uint)sockAddr[5]) << 8) | (uint)sockAddr[4]); + } + + public void Bind(EndPoint epLocal) { + this.CheckDisposed(); + if (epLocal == null) { + throw new ArgumentNullException("epLocal"); + } + int port; + uint addr; + this.GetIPInfo(epLocal, out addr, out port); + int error; + Internal_Bind(this.native, addr, port, out error); + this.CheckError(error); + } + + public void Listen(int backLog) { + this.CheckDisposed(); + int error; + Internal_Listen(this.native, backLog, out error); + this.CheckError(error); + } + + public Socket Accept() { + this.CheckDisposed(); + int error; + IntPtr socket = Internal_Accept(this.native, out error); + this.CheckError(error); + return new Socket(this.family, this.type, this.proto, socket); + } + + public void Connect(EndPoint epRemote) { + this.CheckDisposed(); + if (epRemote == null) { + throw new ArgumentNullException("epRemote"); + } + int port; + uint addr; + this.GetIPInfo(epRemote, out addr, out port); + int error; + Internal_Connect(this.native, addr, port, out error); + this.CheckError(error); + } + + public int Send(byte[] buffer) { + return this.Send(buffer, 0, buffer.Length, SocketFlags.None); + } + + public int Send(byte[] buffer, SocketFlags flags) { + return this.Send(buffer, 0, buffer.Length, flags); + } + + public int Send(byte[] buffer, int size, SocketFlags flags) { + return this.Send(buffer, 0, size, flags); + } + + public int Send(byte[] buffer, int offset, int size, SocketFlags flags) { + this.CheckDisposed(); + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + if (offset < 0 || size < 0 || offset + size > buffer.Length) { + throw new ArgumentOutOfRangeException(); + } + int error; + int ret = Internal_Send(this.native, buffer, offset, size, (int)flags, out error); + this.CheckError(error); + return ret; + } + + public int Receive(byte[] buffer) { + return this.Receive(buffer, 0, buffer.Length, SocketFlags.None); + } + + public int Receive(byte[] buffer, SocketFlags flags) { + return this.Receive(buffer, 0, buffer.Length, flags); + } + + public int Receive(byte[] buffer, int size, SocketFlags flags) { + return this.Receive(buffer, 0, size, flags); + } + + public int Receive(byte[] buffer, int offset, int size, SocketFlags flags) { + this.CheckDisposed(); + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + if (offset < 0 || size < 0 || offset + size > buffer.Length) { + throw new ArgumentOutOfRangeException(); + } + int error; + int ret = Internal_Receive(this.native, buffer, offset, size, (int)flags, out error); + this.CheckError(error); + return ret; + } + } +} diff --git a/System/System.Net.Sockets/SocketException.cs b/System/System.Net.Sockets/SocketException.cs new file mode 100644 index 0000000..8610de7 --- /dev/null +++ b/System/System.Net.Sockets/SocketException.cs @@ -0,0 +1,38 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; +using System.ComponentModel; + +namespace System.Net.Sockets { + public class SocketException : Win32Exception { + + public SocketException(int error) : base(error) { } + + public override int ErrorCode { + get { + return NativeErrorCode; + } + } + + } +} diff --git a/System/System.Net.Sockets/SocketFlags.cs b/System/System.Net.Sockets/SocketFlags.cs new file mode 100644 index 0000000..0d7d9a9 --- /dev/null +++ b/System/System.Net.Sockets/SocketFlags.cs @@ -0,0 +1,39 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Net.Sockets { + [Flags] + public enum SocketFlags { + None = 0x00000000, + OutOfBand = 0x00000001, + Peek = 0x00000002, + DontRoute = 0x00000004, + MaxIOVectorLength = 0x00000010, + Truncated = 0x00000100, + ControlDataTruncated = 0x00000200, + Broadcast = 0x00000400, + Multicast = 0x00000800, + Partial = 0x00008000, + } +} diff --git a/System/System.Net.Sockets/SocketOptionLevel.cs b/System/System.Net.Sockets/SocketOptionLevel.cs new file mode 100644 index 0000000..e2621fc --- /dev/null +++ b/System/System.Net.Sockets/SocketOptionLevel.cs @@ -0,0 +1,33 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Net.Sockets { + public enum SocketOptionLevel { + Socket = 65535, + IP = 0, + IPv6 = 41, + Tcp = 6, + Udp = 17, + } +} diff --git a/System/System.Net.Sockets/SocketOptionName.cs b/System/System.Net.Sockets/SocketOptionName.cs new file mode 100644 index 0000000..0a9900c --- /dev/null +++ b/System/System.Net.Sockets/SocketOptionName.cs @@ -0,0 +1,71 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Net.Sockets { + public enum SocketOptionName { + Debug = 1, + AcceptConnection = 2, + ReuseAddress = 4, + KeepAlive = 8, + DontRoute = 16, + Broadcast = 32, + UseLoopback = 64, + Linger = 128, + OutOfBandInline = 256, + DontLinger = -129, + ExclusiveAddressUse = -5, + SendBuffer = 4097, + ReceiveBuffer = 4098, + SendLowWater = 4099, + ReceiveLowWater = 4100, + SendTimeout = 4101, + ReceiveTimeout = 4102, + Error = 4103, + Type = 4104, + MaxConnections = 2147483647, + IPOptions = 1, + HeaderIncluded = 2, + TypeOfService = 3, + IpTimeToLive = 4, + MulticastInterface = 9, + MulticastTimeToLive = 10, + MulticastLoopback = 11, + AddMembership = 12, + DropMembership = 13, + DontFragment = 14, + AddSourceMembership = 15, + DropSourceMembership = 16, + BlockSource = 17, + UnblockSource = 18, + PacketInformation = 19, + NoDelay = 1, + BsdUrgent = 2, + Expedited = 2, + NoChecksum = 1, + ChecksumCoverage = 20, + HopLimit = 21, + UpdateAcceptContext = 28683, + UpdateConnectContext = 28688, + } +} diff --git a/System/System.Net.Sockets/SocketType.cs b/System/System.Net.Sockets/SocketType.cs new file mode 100644 index 0000000..8c29b67 --- /dev/null +++ b/System/System.Net.Sockets/SocketType.cs @@ -0,0 +1,34 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Net.Sockets { + public enum SocketType { + Stream = 1, + Dgram = 2, + Raw = 3, + Rdm = 4, + Seqpacket = 5, + Unknown = -1, + } +} diff --git a/System/System.Net/Dns.cs b/System/System.Net/Dns.cs new file mode 100644 index 0000000..7e7eb96 --- /dev/null +++ b/System/System.Net/Dns.cs @@ -0,0 +1,59 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Runtime.CompilerServices; + +namespace System.Net { + public static class Dns { + + [MethodImpl(MethodImplOptions.InternalCall)] + extern private static int[] Internal_GetHostEnt(string dnsName, out string hostName); + + public static IPHostEntry GetHostEntry(string hostNameOrAddress) { + IPAddress ipAddr; + bool isIPAddr = IPAddress.TryParse(hostNameOrAddress, out ipAddr); + if (!isIPAddr) { + string hostName; + int[] ips = Internal_GetHostEnt(hostNameOrAddress, out hostName); + IPAddress[] addresses = new IPAddress[ips.Length]; + for (int i = 0; i < ips.Length; i++) { + addresses[i] = new IPAddress((uint)ips[i]); + } + IPHostEntry hostEnt = new IPHostEntry(); + hostEnt.AddressList = addresses; + hostEnt.HostName = hostName; + return hostEnt; + } else { + return GetHostEntry(ipAddr); + } + } + + public static IPHostEntry GetHostEntry(IPAddress addr) { + if (addr == null) { + throw new ArgumentNullException("address"); + } + throw new NotImplementedException(); + } + + } +} diff --git a/System/System.Net/EndPoint.cs b/System/System.Net/EndPoint.cs new file mode 100644 index 0000000..78d045e --- /dev/null +++ b/System/System.Net/EndPoint.cs @@ -0,0 +1,46 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Net.Sockets; + +namespace System.Net { + public abstract class EndPoint { + + protected EndPoint() { } + + public virtual EndPoint Create(SocketAddress address) { + throw new NotSupportedException(); + } + + public virtual AddressFamily AddressFamily { + get { + throw new NotSupportedException(); + } + } + + public virtual SocketAddress Serialize() { + throw new NotSupportedException(); + } + + } +} diff --git a/System/System.Net/IPAddress.cs b/System/System.Net/IPAddress.cs new file mode 100644 index 0000000..b9c84be --- /dev/null +++ b/System/System.Net/IPAddress.cs @@ -0,0 +1,101 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Net.Sockets; + +namespace System.Net { + public class IPAddress { + + public static readonly IPAddress Any = new IPAddress(0); + public static readonly IPAddress Broadcast = IPAddress.Parse("255.255.255.255"); + public static readonly IPAddress Loopback = IPAddress.Parse("127.0.0.1"); + public static readonly IPAddress None = IPAddress.Parse("255.255.255.255"); + + public static IPAddress Parse(string ip) { + IPAddress addr; + if (TryParse(ip, out addr)) { + return addr; + } + throw new FormatException("An invalid IP address was specified"); + } + + public static bool TryParse(string ip, out IPAddress address) { + // Only handle IPv4 + if (ip == null) { + throw new ArgumentNullException("ip"); + } + if (ip.Length == 0 || ip == " ") { + address = new IPAddress(0); + return true; + } + string[] parts = ip.Split('.'); + if (parts.Length != 4) { + address = null; + return false; + } + uint a = 0; + for (int i = 0; i < 4; i++) { + int val; + if (!int.TryParse(parts[i], out val)) { + address = null; + return false; + } + a |= ((uint)val) << (i << 3); + } + address = new IPAddress((long)a); + return true; + } + + private uint ip4Address; + private AddressFamily family = AddressFamily.InterNetwork; + + public IPAddress(long addr) { + this.ip4Address = (uint)addr; + } + + public AddressFamily AddressFamily { + get { + return this.family; + } + } + + internal uint InternalIPv4Address { + get { return this.ip4Address; } + } + + public override int GetHashCode() { + return (int)this.ip4Address; + } + + public override bool Equals(object obj) { + IPAddress a = obj as IPAddress; + return a != null && a.ip4Address == this.ip4Address; + } + + public override string ToString() { + return string.Format("{0}.{1}.{2}.{3}", + this.ip4Address & 0xff, (this.ip4Address >> 8) & 0xff, + (this.ip4Address >> 16) & 0xff, this.ip4Address >> 24); + } + } +} diff --git a/System/System.Net/IPEndPoint.cs b/System/System.Net/IPEndPoint.cs new file mode 100644 index 0000000..fde50da --- /dev/null +++ b/System/System.Net/IPEndPoint.cs @@ -0,0 +1,127 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Net.Sockets; + +namespace System.Net { + public class IPEndPoint : EndPoint { + + public const int MinPort = 0; + public const int MaxPort = 0xffff; + + public IPAddress address; + public int port; + + public IPEndPoint(IPAddress addr, int port) { + if (addr == null) { + throw new ArgumentNullException(); + } + this.Address = addr; + this.Port = port; + } + + public IPEndPoint(long addr, int port) : this(new IPAddress(addr), port) { } + + public IPAddress Address { + get { + return this.address; + } + set { + this.address = value; + } + } + + public int Port { + get { + return this.port; + } + set { + if (value < MinPort || value > MaxPort) { + throw new ArgumentOutOfRangeException("Port"); + } + this.port = value; + } + } + + public override AddressFamily AddressFamily { + get { + return this.address.AddressFamily; + } + } + + public override EndPoint Create(SocketAddress sockaddr) { + if (sockaddr.Size < 8) { + return null; + } + if (sockaddr.Family != AddressFamily.InterNetwork) { + // Only support IP4 + return null; + } + int port = (((int)sockaddr[2]) << 8) | (int)sockaddr[3]; + long address = (((long)sockaddr[7]) << 24) | + (((long)sockaddr[6]) << 16) | + (((long)sockaddr[5]) << 8) | + (long)sockaddr[4]; + return new IPEndPoint(address, port); + } + + public override SocketAddress Serialize() { + SocketAddress sockaddr = null; + switch (this.address.AddressFamily) { + case AddressFamily.InterNetwork: + // .net produces a 16 byte buffer, even though + // only 8 bytes are used. I guess its just a + // holdover from struct sockaddr padding. + sockaddr = new SocketAddress(AddressFamily.InterNetwork, 16); + + // bytes 2 and 3 store the port, the rest + // stores the address + sockaddr[2] = (byte)((this.port >> 8) & 0xff); + sockaddr[3] = (byte)(this.port & 0xff); + uint addr = this.address.InternalIPv4Address; + sockaddr[4] = (byte)(addr & 0xff); + sockaddr[5] = (byte)((addr >> 8) & 0xff); + sockaddr[6] = (byte)((addr >> 16) & 0xff); + sockaddr[7] = (byte)((addr >> 24) & 0xff); + break; + } + return sockaddr; + } + + public override string ToString() { + return this.address.ToString() + ":" + this.port.ToString(); + } + + public override int GetHashCode() { + return this.address.GetHashCode() + this.port; + } + + public override bool Equals(Object obj) { + IPEndPoint p = obj as IPEndPoint; + return p != null && + p.port == this.port && + p.address.Equals(this.address); + } + + } +} diff --git a/System/System.Net/IPHostEntry.cs b/System/System.Net/IPHostEntry.cs new file mode 100644 index 0000000..e7ac9a9 --- /dev/null +++ b/System/System.Net/IPHostEntry.cs @@ -0,0 +1,51 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Net { + public class IPHostEntry { + + private IPAddress[] addressList; + private String[] aliases; + private String hostName; + + public IPHostEntry() { + } + + public IPAddress[] AddressList { + get { return addressList; } + set { addressList = value; } + } + + public string[] Aliases { + get { return aliases; } + set { aliases = value; } + } + + public string HostName { + get { return hostName; } + set { hostName = value; } + } + + } +} diff --git a/System/System.Net/SocketAddress.cs b/System/System.Net/SocketAddress.cs new file mode 100644 index 0000000..fe685eb --- /dev/null +++ b/System/System.Net/SocketAddress.cs @@ -0,0 +1,105 @@ +// Copyright (c) 2009 DotNetAnywhere +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Net.Sockets; + +namespace System.Net { + public class SocketAddress { + private byte[] data; + + public SocketAddress(AddressFamily family, int size) { + if (size < 2) { + throw new ArgumentOutOfRangeException("size is too small"); + } + + data = new byte[size]; + data[0] = (byte)family; + data[1] = (byte)((int)family >> 8); + } + + public SocketAddress(AddressFamily family) : this(family, 32) { } + + public AddressFamily Family { + get { + return (AddressFamily)(data[0] + (data[1] << 8)); + } + } + + public int Size { + get { + return data.Length; + } + } + + public byte this[int offset] { + get { + return (data[offset]); + } + + set { + data[offset] = value; + } + } + + public override string ToString() { + string af = ((AddressFamily)data[0]).ToString(); + int size = data.Length; + string ret = af + ":" + size + ":{"; + + for (int i = 2; i < size; i++) { + int val = (int)data[i]; + ret = ret + val; + if (i < size - 1) { + ret = ret + ","; + } + } + + ret = ret + "}"; + + return (ret); + } + + public override bool Equals(object obj) { + if (obj is System.Net.SocketAddress && + ((System.Net.SocketAddress)obj).data.Length == data.Length) { + byte[] otherData = ((System.Net.SocketAddress)obj).data; + for (int i = 0; i < data.Length; i++) + if (otherData[i] != data[i]) + return false; + + return true; + } + + return false; + } + + public override int GetHashCode() { + int code = 0; + + for (int i = 0; i < data.Length; i++) + code += data[i] + i; + + return code; + } + } +} diff --git a/System/System.csproj b/System/System.csproj new file mode 100644 index 0000000..233b6b3 --- /dev/null +++ b/System/System.csproj @@ -0,0 +1,122 @@ + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {388F5D73-0211-4A64-B501-92CDC4E32ACF} + Library + Properties + System + System + + + + + 2.0 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + 512 + true + + + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + 512 + true + + + + + + + + + + + + + + + + + + + + + + + + + + {6A77A7C0-FB66-4CAA-94EE-142DBA20655D} + corlib + + + + + False + .NET Framework Client Profile + false + + + False + .NET Framework 2.0 %28x86%29 + true + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + false + + + False + .NET Framework 3.5 SP1 + false + + + + + + copy $(TargetPath) $(SolutionDir)\Builds\$(ConfigurationName)\ + + \ No newline at end of file diff --git a/corlib/Properties/AssemblyInfo.cs b/corlib/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..eb07758 --- /dev/null +++ b/corlib/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +/*using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("corlib")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("corlib")] +[assembly: AssemblyCopyright("Copyright © 2007")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("32d5f5f8-8b09-424d-ad44-4ed1da918a19")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("2.0.0.0")] +[assembly: AssemblyFileVersion("2.0.0.0")] +*/ \ No newline at end of file diff --git a/corlib/System.Collections.Generic/Comparer.cs b/corlib/System.Collections.Generic/Comparer.cs new file mode 100644 index 0000000..db81661 --- /dev/null +++ b/corlib/System.Collections.Generic/Comparer.cs @@ -0,0 +1,75 @@ +#if !LOCALTEST + +using System; +using System.Collections; + +namespace System.Collections.Generic { + public abstract class Comparer : IComparer,IComparer { + + private sealed class DefaultComparer : Comparer { + + public override int Compare(T x, T y) { + if (x == null) { + return y == null ? 0 : -1; + } + if (y == null) { + return 1; + } + IComparable iComp = x as IComparable; + if (iComp != null) { + return iComp.CompareTo(y); + } + IComparable iComp2 = x as IComparable; + if (iComp2 != null) { + return iComp2.CompareTo(y); + } + throw new ArgumentException("Does not implement IComparable"); + } + + } + + private sealed class DefaultComparerValueType : Comparer { + + public override int Compare(T x, T y) { + IComparable iComp = x as IComparable; + if (iComp != null) { + return iComp.CompareTo(y); + } + IComparable iComp2 = x as IComparable; + if (iComp2 != null) { + return iComp2.CompareTo(y); + } + throw new ArgumentException("Does not implement IComparable"); + } + + } + + static Comparer() { + if (typeof(T).IsValueType) { + Default = new DefaultComparerValueType(); + } else { + Default = new DefaultComparer(); + } + } + + public static Comparer Default { get; private set; } + + public abstract int Compare(T x, T y); + + public int Compare(object x, object y) { + if (x == null) { + return y == null ? 0 : -1; + } + if (y == null) { + return 1; + } + if (x is T && y is T) { + return this.Compare((T)x, (T)y); + } + throw new ArgumentException(); + } + + } +} + +#endif diff --git a/corlib/System.Collections.Generic/Dictionary.cs b/corlib/System.Collections.Generic/Dictionary.cs new file mode 100644 index 0000000..d488228 --- /dev/null +++ b/corlib/System.Collections.Generic/Dictionary.cs @@ -0,0 +1,612 @@ +using System; + +#if LOCALTEST +using System.Collections; +using System.Collections.Generic; +namespace System_.Collections.Generic { +#else +namespace System.Collections.Generic { +#endif + public class Dictionary : IDictionary, ICollection>, + IEnumerable>, IDictionary, ICollection, IEnumerable { + + public struct Enumerator : IEnumerator>, + IDisposable, IDictionaryEnumerator, IEnumerator { + + Dictionary dict; + private int curSlot, curItem; + + internal Enumerator(Dictionary dictionary) { + this.dict = dictionary; + this.curSlot = -1; + this.curItem = 0; + } + + public bool MoveNext() { + do { + if (this.curSlot >= this.dict.capacity) { + return false; + } + if (this.curSlot < 0 || this.dict.keys[this.curSlot] == null || + this.curItem > this.dict.keys[this.curSlot].Count) { + this.curSlot++; + this.curItem = 0; + } else { + this.curItem++; + } + if (this.curSlot >= this.dict.capacity) { + return false; + } + } while (this.dict.keys[this.curSlot] == null || this.curItem >= dict.keys[this.curSlot].Count); + return true; + } + + public KeyValuePair Current { + get { + return new KeyValuePair( + this.dict.keys[this.curSlot][this.curItem], + this.dict.values[this.curSlot][this.curItem] + ); + } + } + + object IEnumerator.Current { + get { return this.Current; } + } + + void IEnumerator.Reset() { + this.curSlot = -1; + this.curItem = 0; + } + + DictionaryEntry IDictionaryEnumerator.Entry { + get { + return new DictionaryEntry( + this.dict.keys[this.curSlot][this.curItem], + this.dict.values[this.curSlot][this.curItem] + ); + } + } + + object IDictionaryEnumerator.Key { + get { + return dict.keys[this.curSlot][this.curItem]; + } + } + + object IDictionaryEnumerator.Value { + get { + return this.dict.values[this.curSlot][this.curItem]; + } + } + + public void Dispose() { + this.dict = null; + } + } + + public sealed class KeyCollection : ICollection, IEnumerable, ICollection, IEnumerable { + + public struct Enumerator : IEnumerator, IDisposable, IEnumerator { + + private Dictionary.Enumerator hostEnumerator; + + internal Enumerator(Dictionary host) { + this.hostEnumerator = host.GetEnumerator(); + } + + public void Dispose() { + this.hostEnumerator.Dispose(); + } + + public bool MoveNext() { + return this.hostEnumerator.MoveNext(); + } + + public TKey Current { + get { return this.hostEnumerator.Current.Key; } + } + + object IEnumerator.Current { + get { return this.hostEnumerator.Current.Key; } + } + + void IEnumerator.Reset() { + ((IEnumerator)this.hostEnumerator).Reset(); + } + } + + private Dictionary dictionary; + + public KeyCollection(Dictionary dictionary) { + if (dictionary == null) { + throw new ArgumentException("dictionary"); + } + this.dictionary = dictionary; + } + + public void CopyTo(TKey[] array, int index) { + throw new NotImplementedException(); + } + + public Enumerator GetEnumerator() { + return new Enumerator(this.dictionary); + } + + void ICollection.Add(TKey item) { + throw new NotSupportedException("this is a read-only collection"); + } + + void ICollection.Clear() { + throw new NotSupportedException("this is a read-only collection"); + } + + bool ICollection.Contains(TKey item) { + return this.dictionary.ContainsKey(item); + } + + bool ICollection.Remove(TKey item) { + throw new NotSupportedException("this is a read-only collection"); + } + + IEnumerator IEnumerable.GetEnumerator() { + return this.GetEnumerator(); + } + + void ICollection.CopyTo(Array array, int index) { + this.CopyTo((TKey[])array, index); + } + + IEnumerator IEnumerable.GetEnumerator() { + return this.GetEnumerator(); + } + + public int Count { + get { + return this.dictionary.Count; + } + } + + bool ICollection.IsReadOnly { + get { + return true; + } + } + + bool ICollection.IsSynchronized { + get { + return false; + } + } + + object ICollection.SyncRoot { + get { + return ((ICollection)this.dictionary).SyncRoot; + } + } + + } + + public sealed class ValueCollection : ICollection, IEnumerable, ICollection, IEnumerable { + + public struct Enumerator : IEnumerator, IDisposable, IEnumerator { + + private Dictionary.Enumerator hostEnumerator; + + internal Enumerator(Dictionary host) { + this.hostEnumerator = host.GetEnumerator(); + } + + public void Dispose() { + this.hostEnumerator.Dispose(); + } + + public bool MoveNext() { + return this.hostEnumerator.MoveNext(); + } + + public TValue Current { + get { return this.hostEnumerator.Current.Value; } + } + + object IEnumerator.Current { + get { return this.hostEnumerator.Current.Value; } + } + + void IEnumerator.Reset() { + ((IEnumerator)this.hostEnumerator).Reset(); + } + } + + private Dictionary dictionary; + + public ValueCollection(Dictionary dictionary) { + if (dictionary == null) { + throw new ArgumentException("dictionary"); + } + this.dictionary = dictionary; + } + + public void CopyTo(TValue[] array, int index) { + throw new NotImplementedException(); + } + + public Enumerator GetEnumerator() { + return new Enumerator(this.dictionary); + } + + void ICollection.Add(TValue item) { + throw new NotSupportedException("this is a read-only collection"); + } + + void ICollection.Clear() { + throw new NotSupportedException("this is a read-only collection"); + } + + bool ICollection.Contains(TValue item) { + return this.dictionary.ContainsValue(item); + } + + bool ICollection.Remove(TValue item) { + throw new NotSupportedException("this is a read-only collection"); + } + + IEnumerator IEnumerable.GetEnumerator() { + return this.GetEnumerator(); + } + + void ICollection.CopyTo(Array array, int index) { + this.CopyTo((TValue[])array, index); + } + + IEnumerator IEnumerable.GetEnumerator() { + return this.GetEnumerator(); + } + + public int Count { + get { + return this.dictionary.Count; + } + } + + bool ICollection.IsReadOnly { + get { + return true; + } + } + + bool ICollection.IsSynchronized { + get { + return false; + } + } + + object ICollection.SyncRoot { + get { + return ((ICollection)this.dictionary).SyncRoot; + } + } + + } + + private static int[] capacities = { + 11, 23, 47, 97, 191, 379, 757, 1511, 3023, 6047, 12097, 24179, 48353, 96731 + }; + + private List[] keys; + private List[] values; + private int capacity, capacityIndex, count; + private IEqualityComparer comparer; + + public Dictionary() { + this.Init(0, null); + } + + public Dictionary(IDictionary dictionary) : this(dictionary, null) { } + + public Dictionary(IEqualityComparer comparer) { + this.Init(0, comparer); + } + + public Dictionary(int capacity) { + this.Init(capacity, null); + } + + public Dictionary(IDictionary dictionary, IEqualityComparer comparer) { + this.Init(dictionary.Count, comparer); + foreach (var item in dictionary) { + this.Add(item.Key, item.Value); + } + } + + public Dictionary(int capacity, IEqualityComparer comparer) { + this.Init(capacity, comparer); + } + + private void Init(int initialCapacity, IEqualityComparer comparer) { + // Initialise the comparer + this.comparer = comparer ?? EqualityComparer.Default; + // Initialise the capacity of the dictionary + this.capacityIndex = -1; + for (int i = 0; i < capacities.Length; i++) { + if (initialCapacity <= capacities[i]) { + this.capacityIndex = i; + this.capacity = capacities[i]; + break; + } + } + if (this.capacityIndex == -1){ + // If the capacity is off the end of the scale, then just use the capacity given + this.capacity = initialCapacity; + this.capacityIndex = capacities.Length; + } + this.Clear(); + } + + private int GetSlot(TKey key) { + uint hash = (uint)key.GetHashCode(); + return (int)(hash % (uint)this.capacity); + } + + public void Add(TKey key, TValue value) { + Add(key, value, false); + } + + private void Add(TKey key, TValue value, bool replace) { + if (key == null) { + throw new ArgumentNullException(); + } + int slot = this.GetSlot(key); + List keySlot = this.keys[slot]; + if (keySlot != null) { + // There are element(s) at this index, so see if this key is already in this dictionary + // Can't use keySlot.IndexOf() because it doesn't honour the comparer + for (int i = keySlot.Count - 1; i >= 0; i--) { + if (this.comparer.Equals(keySlot[i], key)) { + // The key is already in this dictionary + if (replace) { + this.values[slot][i] = value; + return; + } else { + throw new ArgumentException("Key already exists in dictionary"); + } + } + } + // Key not already in dictionary, so carry on + } + this.count++; + if (this.count > this.capacity) { + // Increase capacity + List[] currentKeys = this.keys; + List[] currentValues = this.values; + this.capacityIndex++; + this.capacity = (this.capacityIndex >= capacities.Length) ? + this.capacity * 2 + 1 : capacities[this.capacityIndex]; + this.Clear(); + // Add all the items in this dictionary to the enlarged dictionary lists. + for (int slotIdx = currentKeys.Length - 1; slotIdx >= 0; slotIdx--) { + List currentKeySlot = currentKeys[slotIdx]; + if (currentKeySlot != null) { + List currentValueSlot = currentValues[slotIdx]; + for (int listIdx = currentKeySlot.Count - 1; listIdx >= 0; listIdx--) { + this.Add(currentKeySlot[listIdx], currentValueSlot[listIdx], false); + } + } + } + // Reload these values, as they will have changed due to dictionary capacity resizing + slot = key.GetHashCode() % this.capacity; + keySlot = this.keys[slot]; + } + List valueSlot; + if (keySlot == null) { + // There are no elements at this index, so create a new list for the element being added + this.keys[slot] = keySlot = new List(1); + this.values[slot] = valueSlot = new List(1); + } else { + valueSlot = this.values[slot]; + } + keySlot.Add(key); + valueSlot.Add(value); + } + + public TValue this[TKey key] { + get { + TValue value; + if (this.TryGetValue(key, out value)) { + return value; + } + throw new KeyNotFoundException(key.ToString()); + } + set { + Add(key, value, true); + } + } + + public bool TryGetValue(TKey key, out TValue value) { + if (key == null) { + throw new ArgumentNullException(); + } + int slot = this.GetSlot(key); + List keySlot = this.keys[slot]; + if (keySlot != null) { + // Can't use keySlot.IndexOf() because it doesn't honour the comparer + for (int i = keySlot.Count - 1; i >= 0; i--) { + if (this.comparer.Equals(keySlot[i], key)) { + value = this.values[slot][i]; + return true; + } + } + } + value = default(TValue); + return false; + } + + public bool ContainsKey(TKey key) { + TValue dummy; + return (TryGetValue(key, out dummy)); + } + + public bool ContainsValue(TValue value) { + Enumerator e = new Enumerator(this); + while (e.MoveNext()) { + if (e.Current.Value.Equals(value)) { + return true; + } + } + return false; + } + + public bool Remove(TKey key) { + int slot = this.GetSlot(key); + List keySlot = this.keys[slot]; + if (keySlot != null) { + // Can't use keySlot.IndexOf() because it doesn't honour the comparer + for (int i = keySlot.Count - 1; i >= 0; i--) { + if (this.comparer.Equals(keySlot[i], key)) { + keySlot.RemoveAt(i); + this.values[slot].RemoveAt(i); + this.count--; + return true; + } + } + } + return false; + } + + public IEqualityComparer Comparer { + get { + return this.comparer; + } + } + + public int Count { + get { + return this.count; + } + } + + public KeyCollection Keys { + get { + return new KeyCollection(this); + } + } + + public ValueCollection Values { + get { + return new ValueCollection(this); + } + } + + public bool IsReadOnly { + get { + return false; + } + } + + public void Clear() { + this.keys = new List[this.capacity]; + this.values = new List[this.capacity]; + this.count = 0; + } + + public Enumerator GetEnumerator() { + return new Enumerator(this); + } + + ICollection IDictionary.Keys { + get { + return new KeyCollection(this); + } + } + + ICollection IDictionary.Values { + get { + return new ValueCollection(this); + } + } + + void ICollection>.Add(KeyValuePair item) { + this.Add(item.Key, item.Value); + } + + bool ICollection>.Contains(KeyValuePair item) { + return this.ContainsKey(item.Key); + } + + void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) { + throw new Exception("The method or operation is not implemented."); + } + + bool ICollection>.Remove(KeyValuePair item) { + return this.Remove(item.Key); + } + + IEnumerator> IEnumerable>.GetEnumerator() { + return new Enumerator(this); + } + + IEnumerator IEnumerable.GetEnumerator() { + return new Enumerator(this); + } + + public bool IsFixedSize { + get { + return false; + } + } + + object IDictionary.this[object key] { + get { + return this[(TKey)key]; + } + set { + this[(TKey)key] = (TValue)value; + } + } + + ICollection IDictionary.Keys { + get { + return Keys; + } + } + + ICollection IDictionary.Values { + get { + return Values; + } + } + + void IDictionary.Add(object key, object value) { + Add((TKey)key, (TValue)value); + } + + bool IDictionary.Contains(object key) { + return ContainsKey((TKey)key); + } + + IDictionaryEnumerator IDictionary.GetEnumerator() { + return new Enumerator(this); + } + + void IDictionary.Remove(object key) { + Remove((TKey)key); + } + + public bool IsSynchronized { + get { + return false; + } + } + + public object SyncRoot { + get { + return this; + } + } + + public void CopyTo(Array array, int index) { + throw new Exception("The method or operation is not implemented."); + } + + } +} diff --git a/corlib/System.Collections.Generic/EqualityComparer.cs b/corlib/System.Collections.Generic/EqualityComparer.cs new file mode 100644 index 0000000..466d657 --- /dev/null +++ b/corlib/System.Collections.Generic/EqualityComparer.cs @@ -0,0 +1,53 @@ +#if !LOCALTEST + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Collections.Generic { + + public abstract class EqualityComparer : IEqualityComparer, IEqualityComparer { + + private class DefaultComparer : EqualityComparer { + + public override bool Equals(T x, T y) { + if (x == null) { + return y == null; + } + return x.Equals(y); + } + + public override int GetHashCode(T obj) { + if (obj == null) { + return 0; + } + return obj.GetHashCode(); + } + + } + + static EqualityComparer() { + // Need to use the GenericEqualityComparer, but can't because + // cannot instantiate the type yet, because T needs to implement IEquatable + Default = new DefaultComparer(); + } + + public static EqualityComparer Default { get; private set; } + + public abstract bool Equals(T x, T y); + + public abstract int GetHashCode(T obj); + + bool IEqualityComparer.Equals(object x, object y) { + return this.Equals((T)x, (T)y); + } + + int IEqualityComparer.GetHashCode(object obj) { + return this.GetHashCode((T)obj); + } + + } + +} + +#endif diff --git a/corlib/System.Collections.Generic/GenericEqualityComparer.cs b/corlib/System.Collections.Generic/GenericEqualityComparer.cs new file mode 100644 index 0000000..038dba4 --- /dev/null +++ b/corlib/System.Collections.Generic/GenericEqualityComparer.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Collections.Generic { + class GenericEqualityComparer : EqualityComparer where T : IEquatable { + + public override bool Equals(T x, T y) { + if (x == null) { + return y == null; + } + return x.Equals(y); + } + + public override int GetHashCode(T obj) { + if (obj == null) { + return 0; + } + return obj.GetHashCode(); + } + + } +} diff --git a/corlib/System.Collections.Generic/ICollection.cs b/corlib/System.Collections.Generic/ICollection.cs new file mode 100644 index 0000000..f5a8b89 --- /dev/null +++ b/corlib/System.Collections.Generic/ICollection.cs @@ -0,0 +1,33 @@ +#if !LOCALTEST + +using System; + +namespace System.Collections.Generic { + + public interface ICollection : IEnumerable { + + // DO NOT change the order of these method definitions. + // The auto-generated ICollection interface on Array relies on the order. + + int Count { + get; + } + + bool IsReadOnly { + get; + } + + void Add(T item); + + void Clear(); + + bool Contains(T item); + + void CopyTo(T[] array, int arrayIndex); + + bool Remove(T item); + + } + +} +#endif diff --git a/corlib/System.Collections.Generic/IComparer.cs b/corlib/System.Collections.Generic/IComparer.cs new file mode 100644 index 0000000..2c81fea --- /dev/null +++ b/corlib/System.Collections.Generic/IComparer.cs @@ -0,0 +1,13 @@ +#if !LOCALTEST + +namespace System.Collections.Generic { + + public interface IComparer { + + int Compare(T x, T y); + + } + +} + +#endif diff --git a/corlib/System.Collections.Generic/IDictionary.cs b/corlib/System.Collections.Generic/IDictionary.cs new file mode 100644 index 0000000..458e008 --- /dev/null +++ b/corlib/System.Collections.Generic/IDictionary.cs @@ -0,0 +1,18 @@ +#if !LOCALTEST + +using System; + +namespace System.Collections.Generic { + public interface IDictionary : ICollection> { + + void Add(TKey key, TValue value); + bool ContainsKey(TKey key); + bool Remove(TKey key); + bool TryGetValue(TKey key, out TValue value); + TValue this[TKey key] { get; set; } + ICollection Keys { get; } + ICollection Values { get; } + + } +} +#endif diff --git a/corlib/System.Collections.Generic/IEnumerable.cs b/corlib/System.Collections.Generic/IEnumerable.cs new file mode 100644 index 0000000..4016de4 --- /dev/null +++ b/corlib/System.Collections.Generic/IEnumerable.cs @@ -0,0 +1,15 @@ +#if !LOCALTEST + +using System; +using System.Collections; + +namespace System.Collections.Generic { + + public interface IEnumerable : IEnumerable { + + new IEnumerator GetEnumerator(); + + } + +} +#endif diff --git a/corlib/System.Collections.Generic/IEnumerator.cs b/corlib/System.Collections.Generic/IEnumerator.cs new file mode 100644 index 0000000..00c5d77 --- /dev/null +++ b/corlib/System.Collections.Generic/IEnumerator.cs @@ -0,0 +1,16 @@ +#if !LOCALTEST + +using System; + +namespace System.Collections.Generic { + + public interface IEnumerator : IDisposable, IEnumerator { + + new T Current { + get; + } + + } + +} +#endif diff --git a/corlib/System.Collections.Generic/IEqualityComparer.cs b/corlib/System.Collections.Generic/IEqualityComparer.cs new file mode 100644 index 0000000..a3d26f9 --- /dev/null +++ b/corlib/System.Collections.Generic/IEqualityComparer.cs @@ -0,0 +1,18 @@ +#if !LOCALTEST + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Collections.Generic { + + public interface IEqualityComparer { + + bool Equals(T x, T y); + int GetHashCode(T obj); + + } + +} + +#endif diff --git a/corlib/System.Collections.Generic/IList.cs b/corlib/System.Collections.Generic/IList.cs new file mode 100644 index 0000000..1e402d7 --- /dev/null +++ b/corlib/System.Collections.Generic/IList.cs @@ -0,0 +1,26 @@ +#if !LOCALTEST + +using System; + +namespace System.Collections.Generic { + + public interface IList : ICollection { + + // DO NOT change the order of these method definitions. + // The auto-generated IList interface on Array relies on the order. + + int IndexOf(T item); + + void Insert(int index, T item); + + void RemoveAt(int index); + + T this[int index] { + get; + set; + } + + } + +} +#endif diff --git a/corlib/System.Collections.Generic/KeyNotFoundException.cs b/corlib/System.Collections.Generic/KeyNotFoundException.cs new file mode 100644 index 0000000..ec70043 --- /dev/null +++ b/corlib/System.Collections.Generic/KeyNotFoundException.cs @@ -0,0 +1,16 @@ +#if !LOCALTEST + +using System; + +namespace System.Collections.Generic { + public class KeyNotFoundException : SystemException { + + public KeyNotFoundException() : base("The given key was not present in the dictionary.") { } + + public KeyNotFoundException(string message) : base(message) { } + + public KeyNotFoundException(string message, Exception inner) : base(message, inner) { } + + } +} +#endif diff --git a/corlib/System.Collections.Generic/KeyValuePair.cs b/corlib/System.Collections.Generic/KeyValuePair.cs new file mode 100644 index 0000000..a0eff31 --- /dev/null +++ b/corlib/System.Collections.Generic/KeyValuePair.cs @@ -0,0 +1,35 @@ +#if !LOCALTEST + +using System; + +namespace System.Collections.Generic { + public struct KeyValuePair { + + private TKey key; + private TValue value; + + public KeyValuePair(TKey Key, TValue Value) { + this.key = Key; + this.value = Value; + } + + public TKey Key { + get { + return key; + } + } + + public TValue Value { + get { + return value; + } + } + + public override string ToString() { + return "[" + (Key != null ? Key.ToString() : string.Empty) + + ", " + (Value != null ? Value.ToString() : string.Empty) + "]"; + } + + } +} +#endif diff --git a/corlib/System.Collections.Generic/List.cs b/corlib/System.Collections.Generic/List.cs new file mode 100644 index 0000000..929f5c5 --- /dev/null +++ b/corlib/System.Collections.Generic/List.cs @@ -0,0 +1,273 @@ +using System; + +#if LOCALTEST +using System.Collections; +using System.Collections.Generic; +namespace System_.Collections.Generic { +#else +namespace System.Collections.Generic { +#endif + public class List : IList, ICollection, IEnumerable, IList, ICollection, IEnumerable { + + public struct Enumerator : IEnumerator, IDisposable { + + private List list; + private int index; + + internal Enumerator(List list) { + this.list = list; + this.index = -1; + } + + public T Current { + get { + return this.list[this.index]; + } + } + + public void Dispose() { + } + + object IEnumerator.Current { + get { + return this.list[this.index]; + } + } + + public bool MoveNext() { + this.index++; + return (this.index < this.list.Count); + } + + public void Reset() { + this.index = -1; + } + + } + + private const int defaultCapacity = 4; + + private T[] items; + private int size; + + public List() : this(defaultCapacity) { } + + public List(int capacity) { + if (capacity < 0) { + throw new ArgumentOutOfRangeException("capacity"); + } + this.items = new T[capacity]; + this.size = 0; + } + + public List(IEnumerable collection) { + ICollection iCol = collection as ICollection; + if (iCol != null) { + this.size = iCol.Count; + this.items = new T[this.size]; + iCol.CopyTo(this.items, 0); + } else { + this.items = new T[defaultCapacity]; + this.size = 0; + foreach (T item in collection) { + this.Add(item); + } + } + } + + private void EnsureSpace(int space) { + if (this.size + space > this.items.Length) { + Array.Resize(ref this.items, Math.Max(this.items.Length << 1, 4)); + } + } + + private void Shift(int index, int count) { + if (count > 0) { + this.EnsureSpace(count); + for (int i = this.size - 1; i >= index; i--) { + this.items[i + count] = this.items[i]; + } + } else { + for (int i = index; i < this.size + count; i++) { + this.items[i] = this.items[i - count]; + } + } + this.size += count; + } + + public void Add(T item) { + this.EnsureSpace(1); + this.items[this.size++] = item; + } + + public int Count { + get { + return this.size; + } + } + + public int Capacity { + get { + return this.items.Length; + } + set { + throw new NotImplementedException(); + } + } + + public T this[int index] { + get { + if (index >= this.size || index < 0) { + throw new ArgumentOutOfRangeException("index"); + } + return this.items[index]; + } + set { + if (index >= this.size || index < 0) { + throw new ArgumentOutOfRangeException("index"); + } + this.items[index] = value; + } + } + + public Enumerator GetEnumerator() { + return new Enumerator(this); + } + + public int IndexOf(T item, int start, int count) { + return Array.IndexOf(this.items, item, start, count); + } + + public int IndexOf(T item, int start) { + return this.IndexOf(item, start, this.size - start); + } + + public void InsertRange(int index, IEnumerable collection) { + if (collection == null) { + throw new ArgumentNullException("collection"); + } + if (index < 0 || index > this.size) { + throw new ArgumentOutOfRangeException("index"); + } + List toInsert = new List(collection); + this.Shift(index, toInsert.Count); + for (int i = 0; i < toInsert.Count; i++) { + this.items[index + i] = toInsert[i]; + } + } + + public T[] ToArray() { + T[] array = new T[this.size]; + Array.Copy(this.items, array, this.size); + return array; + } + + #region Interface Members + + public int IndexOf(T item) { + return this.IndexOf(item, 0, size); + } + + public void Insert(int index, T item) { + if (index < 0 || index > this.size) { + throw new ArgumentOutOfRangeException("index"); + } + this.Shift(index, 1); + this.items[index] = item; + } + + public void RemoveAt(int index) { + this.Shift(index, -1); + } + + public bool IsReadOnly { + get { + return false; + } + } + + public void Clear() { + Array.Clear(this.items, 0, this.items.Length); + this.size = 0; + } + + public bool Contains(T item) { + return Array.IndexOf(this.items, item) >= 0; + } + + public void CopyTo(T[] array, int arrayIndex) { + Array.Copy(this.items, 0, (Array)array, arrayIndex, this.size); + } + + public bool Remove(T item) { + int idx = Array.IndexOf(this.items, item); + if (idx >= 0) { + this.RemoveAt(idx); + return true; + } + return false; + } + + IEnumerator IEnumerable.GetEnumerator() { + return new Enumerator(this); + } + + IEnumerator IEnumerable.GetEnumerator() { + return new Enumerator(this); + } + + public bool IsFixedSize { + get { + return false; + } + } + + object IList.this[int index] { + get { + return this[index]; + } + set { + this[index] = (T)value; + } + } + + public int Add(object value) { + this.Add((T)value); + return this.items.Length - 1; + } + + public bool Contains(object value) { + return this.Contains((T)value); + } + + public int IndexOf(object value) { + return this.IndexOf((T)value); + } + + public void Insert(int index, object value) { + this.Insert(index, (T)value); + } + + public void Remove(object value) { + this.Remove((T)value); + } + + public bool IsSynchronized { + get { + return false; + } + } + + public object SyncRoot { + get { + return this; + } + } + + public void CopyTo(Array array, int index) { + Array.Copy(this.items, 0, array, index, this.size); + } + + #endregion + } +} diff --git a/corlib/System.Collections/ArrayList.cs b/corlib/System.Collections/ArrayList.cs new file mode 100644 index 0000000..d3e6d93 --- /dev/null +++ b/corlib/System.Collections/ArrayList.cs @@ -0,0 +1,214 @@ +using System; +using System.Collections.Generic; + +#if LOCALTEST +using System.Collections; +namespace System_.Collections { +#else +namespace System.Collections { +#endif + public class ArrayList : IList, ICollection, IEnumerable, ICloneable { + + private List list; + + public ArrayList() { + this.list = new List(); + } + + public ArrayList(ICollection c) { + if (c == null) { + throw new ArgumentNullException(); + } + this.list = new List(c.Count); + foreach (object o in c) { + this.list.Add(o); + } + } + + public ArrayList(int capacity) { + this.list = new List(capacity); + } + + public virtual int Add(object value) { + return this.list.Add(value); + } + + public virtual void AddRange(ICollection c) { + if (c == null) { + throw new ArgumentNullException(); + } + foreach (object o in c) { + this.list.Add(o); + } + } + + public virtual void Clear() { + this.list.Clear(); + } + + public virtual object Clone() { + throw new NotImplementedException(); + } + + public virtual bool Contains(object item) { + return this.list.Contains(item); + } + + public virtual void CopyTo(Array array) { + this.list.CopyTo(array, 0); + } + + public virtual void CopyTo(Array array, int arrayIndex) { + throw new NotImplementedException(); + } + + public virtual void CopyTo(int index, Array array, int arrayIndex, int count){ + throw new NotImplementedException(); + } + + public virtual IEnumerator GetEnumerator() { + return this.list.GetEnumerator(); + } + + public virtual IEnumerable GetEnumerator(int index, int count) { + throw new NotImplementedException(); + } + + public virtual ArrayList GetRange(int index, int count) { + throw new NotImplementedException(); + } + + public virtual int IndexOf(object value) { + return this.list.IndexOf(value); + } + + public virtual int IndexOf(object value, int startIndex) { + return this.list.IndexOf(value, startIndex); + } + + public virtual int IndexOf(object value, int startIndex, int count) { + return this.list.IndexOf(value, startIndex, count); + } + + public virtual void Insert(int index, object value) { + this.list.Insert(index, value); + } + + public virtual void InsertRange(int index, ICollection c) { + List insert = new List(c.Count); + foreach (object o in c) { + insert.Add(o); + } + this.list.InsertRange(index, insert); + } + + public virtual int LastIndexOf(object value) { + throw new NotImplementedException(); + } + + public virtual int LastIndexOf(object value, int startIndex) { + throw new NotImplementedException(); + } + + public virtual int LastIndexOf(object value, int startIndex, int count) { + throw new NotImplementedException(); + } + + public virtual void Remove(object obj) { + this.list.Remove(obj); + } + + public virtual void RemoveAt(int index) { + this.list.RemoveAt(index); + } + + public virtual void RemoveRange(int index, int count) { + throw new NotImplementedException(); + } + + public virtual void Reverse() { + throw new NotImplementedException(); + } + + public virtual void Reverse(int index, int count) { + throw new NotImplementedException(); + } + + public virtual void SetRange(int index, ICollection c) { + throw new NotImplementedException(); + } + + public virtual void Sort() { + throw new NotImplementedException(); + } + + public virtual void Sort(IComparer comparer) { + throw new NotImplementedException(); + } + + public virtual void Sort(int index, int count, IComparer comparer) { + throw new NotImplementedException(); + } + + public virtual object[] ToArray() { + throw new NotImplementedException(); + } + + public virtual Array ToArray(Type type) { + throw new NotImplementedException(); + } + + public virtual void TromToSize() { + throw new NotImplementedException(); + } + + public virtual int Capacity { + get { + return this.list.Capacity; + } + set { + this.list.Capacity = value; + } + } + + public virtual int Count { + get { + return this.list.Count; + } + } + + public virtual bool IsFixedSize { + get { + return false; + } + } + + public virtual bool IsReadOnly { + get { + return false; + } + } + + public virtual bool IsSynchronized { + get { + return false; + } + } + + public virtual object this[int index] { + get { + return this.list[index]; + } + set { + this.list[index] = value; + } + } + + public virtual object SyncRoot { + get { + return this; + } + } + + } +} diff --git a/corlib/System.Collections/DictionaryEntry.cs b/corlib/System.Collections/DictionaryEntry.cs new file mode 100644 index 0000000..0f6cd2e --- /dev/null +++ b/corlib/System.Collections/DictionaryEntry.cs @@ -0,0 +1,43 @@ +#if !LOCALTEST +using System; + +namespace System.Collections { + public struct DictionaryEntry { + + private object key; + private object val; + + public DictionaryEntry(object key, object value) { + if (key == null) { + throw new ArgumentNullException("key"); + } + + this.key = key; + val = value; + } + + public object Key { + get { + return key; + } + set { + if (value == null) { + throw new ArgumentNullException("value"); + } + key = value; + } + } + + public object Value { + get { + return val; + } + set { + val = value; + } + } + + } +} + +#endif diff --git a/corlib/System.Collections/ICollection.cs b/corlib/System.Collections/ICollection.cs new file mode 100644 index 0000000..8d82fc4 --- /dev/null +++ b/corlib/System.Collections/ICollection.cs @@ -0,0 +1,18 @@ +#if !LOCALTEST + +using System; + +namespace System.Collections { + public interface ICollection : IEnumerable { + + int Count { get; } + + bool IsSynchronized { get; } + + object SyncRoot { get; } + + void CopyTo(Array array, int index); + + } +} +#endif diff --git a/corlib/System.Collections/IComparer.cs b/corlib/System.Collections/IComparer.cs new file mode 100644 index 0000000..ad4ecc1 --- /dev/null +++ b/corlib/System.Collections/IComparer.cs @@ -0,0 +1,11 @@ +#if !LOCALTEST + +namespace System.Collections { + public interface IComparer { + + int Compare(object x, object y); + + } +} + +#endif diff --git a/corlib/System.Collections/IDictionary.cs b/corlib/System.Collections/IDictionary.cs new file mode 100644 index 0000000..96406b9 --- /dev/null +++ b/corlib/System.Collections/IDictionary.cs @@ -0,0 +1,21 @@ +#if !LOCALTEST + +using System; + +namespace System.Collections { + public interface IDictionary : ICollection { + + bool IsFixedSize { get; } + bool IsReadOnly { get; } + object this[object key] { get; set; } + ICollection Keys { get; } + ICollection Values { get; } + void Add(object key, object value); + void Clear(); + bool Contains(object key); + new IDictionaryEnumerator GetEnumerator(); + void Remove(object key); + + } +} +#endif diff --git a/corlib/System.Collections/IDictionaryEnumerator.cs b/corlib/System.Collections/IDictionaryEnumerator.cs new file mode 100644 index 0000000..e8f8862 --- /dev/null +++ b/corlib/System.Collections/IDictionaryEnumerator.cs @@ -0,0 +1,14 @@ +#if !LOCALTEST + +using System; + +namespace System.Collections { + public interface IDictionaryEnumerator : IEnumerator { + + DictionaryEntry Entry { get; } + object Key { get; } + object Value { get; } + + } +} +#endif diff --git a/corlib/System.Collections/IEnumerable.cs b/corlib/System.Collections/IEnumerable.cs new file mode 100644 index 0000000..48549bc --- /dev/null +++ b/corlib/System.Collections/IEnumerable.cs @@ -0,0 +1,11 @@ +#if !LOCALTEST +namespace System.Collections { + + public interface IEnumerable { + + IEnumerator GetEnumerator(); + + } + +} +#endif diff --git a/corlib/System.Collections/IEnumerator.cs b/corlib/System.Collections/IEnumerator.cs new file mode 100644 index 0000000..78f011e --- /dev/null +++ b/corlib/System.Collections/IEnumerator.cs @@ -0,0 +1,11 @@ +#if !LOCALTEST +namespace System.Collections { + + public interface IEnumerator { + object Current { get;} + bool MoveNext(); + void Reset(); + } + +} +#endif diff --git a/corlib/System.Collections/IEqualityComparer.cs b/corlib/System.Collections/IEqualityComparer.cs new file mode 100644 index 0000000..a26fa03 --- /dev/null +++ b/corlib/System.Collections/IEqualityComparer.cs @@ -0,0 +1,18 @@ +#if !LOCALTEST + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Collections { + + public interface IEqualityComparer { + + bool Equals(object x, object y); + int GetHashCode(object obj); + + } + +} + +#endif diff --git a/corlib/System.Collections/IList.cs b/corlib/System.Collections/IList.cs new file mode 100644 index 0000000..778b573 --- /dev/null +++ b/corlib/System.Collections/IList.cs @@ -0,0 +1,30 @@ +#if !LOCALTEST + +using System; + +namespace System.Collections { + public interface IList : ICollection, IEnumerable { + + bool IsFixedSize { get; } + + bool IsReadOnly { get; } + + object this[int index] { get; set; } + + int Add(object value); + + void Clear(); + + bool Contains(object value); + + int IndexOf(object value); + + void Insert(int index, object value); + + void Remove(object value); + + void RemoveAt(int index); + + } +} +#endif diff --git a/corlib/System.Diagnostics/Debugger.cs b/corlib/System.Diagnostics/Debugger.cs new file mode 100644 index 0000000..15cce71 --- /dev/null +++ b/corlib/System.Diagnostics/Debugger.cs @@ -0,0 +1,13 @@ +#if !LOCALTEST + +using System.Runtime.CompilerServices; +namespace System.Diagnostics { + public sealed class Debugger { + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public static void Break(); + + } +} + +#endif diff --git a/corlib/System.Globalization/Calendar.cs b/corlib/System.Globalization/Calendar.cs new file mode 100644 index 0000000..0b2776f --- /dev/null +++ b/corlib/System.Globalization/Calendar.cs @@ -0,0 +1,61 @@ +#if !LOCALTEST + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Globalization { + public abstract class Calendar { + + internal static Calendar CreateByName(string name) { + switch (name) { + case "GregorianCalendar:Localized": + return new GregorianCalendar(); + default: + Console.WriteLine("Calendar: {0}", name); + return null; + //throw new NotSupportedException(string.Format("Calendar name '{0}' not known", name)); + } + } + + public const int CurrentEra = 0; + + public abstract int[] Eras { get;} + public abstract int GetEra(DateTime dt); + public abstract int GetDayOfMonth(DateTime time); + public abstract DayOfWeek GetDayOfWeek(DateTime time); + public abstract int GetMonth(DateTime time); + public abstract int GetYear(DateTime time); + + internal string[] eraNames; + internal string[] eraAbbrNames; + + public bool IsReadOnly { + get { + // Only support read-only calendars for now. + return true; + } + } + + public virtual DateTime MaxSupportedDateTime { + get { + return DateTime.MaxValue; + } + } + + public virtual DateTime MinSupportedDateTime { + get { + return DateTime.MinValue; + } + } + + public virtual int TwoDigitYearMax { + get { + return 2029; + } + } + + } +} + +#endif diff --git a/corlib/System.Globalization/CalendarWeekRule.cs b/corlib/System.Globalization/CalendarWeekRule.cs new file mode 100644 index 0000000..96bd10d --- /dev/null +++ b/corlib/System.Globalization/CalendarWeekRule.cs @@ -0,0 +1,15 @@ +#if !LOCALTEST + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Globalization { + public enum CalendarWeekRule { + FirstDay = 0, + FirstFullWeek = 1, + FirstFourDayWeek = 2 + } +} + +#endif diff --git a/corlib/System.Globalization/CalendricalCalculations.cs b/corlib/System.Globalization/CalendricalCalculations.cs new file mode 100644 index 0000000..840611e --- /dev/null +++ b/corlib/System.Globalization/CalendricalCalculations.cs @@ -0,0 +1,2393 @@ +// CalendricalCalculations.cs +// +// (C) Ulrich Kunitz 2002 +// + +// +// Copyright (C) 2004 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace System.Globalization { + +//using System.Collections; +/* +/// A class that provides mathematical functions. +/// +/// +/// We are breaking the .Net +/// naming conventions to be compatible to the "Calendrical Calculations" +/// bool. +/// +/// +internal class CCMath { + /// + /// A static method which rounds a double value. + /// + /// The double value to round. + /// The rounded double. + public static double round(double x) { + return System.Math.Floor(x+0.5); + } + + /// + /// A static method that computes the remainder of the division + /// of two doubles. + /// + /// The double value which is divided. + /// The divisor. + /// The remainder as double value. + public static double mod(double x, double y) { + return x - y * System.Math.Floor(x/y); + } + + /// + /// The static method divides two integers. + /// + /// The integer x value. + /// The integer y value. + /// The qotient of x and y defined by floor(x/y). + /// + /// + /// Please notify that the function is not compatible to the standard + /// integer divide operation /. + /// + public static int div(int x, int y) { + return (int)System.Math.Floor((double)x/(double)y); + } + + /// + /// The static method computes the remainder of two integers. + /// + /// The integer value which will be divided. + /// The divisor integer value. + /// The remainder as integer value. + /// + /// Please notify that the method is not compatible to the C# + /// remainder operation %. + /// + public static int mod(int x, int y) { + return x - y * div(x, y); + } + + /// + /// A static method that combines integer division and remainder + /// computation. + /// + /// Remainder integer output value. + /// + /// Integer to be divided. + /// Divisor integer value. + /// The quotient as integer. + /// + /// + public static int div_mod(out int remainder, int x, int y) { + int d = div(x, y); + remainder = x - y * d; + return d; + } + + /// + /// A static method returning the sign of the argument. + /// + /// The double argument. + /// An integer value: -1 for a negative argument; + /// 0 for a zero argument, and 1 for a positive argument. + /// + public static int signum(double x) { + if (x < 0.0) + return -1; + if (x == 0.0) + return 0; + return 1; + } + + /// + /// A static method returning the sign of the integer + /// argument. + /// + /// The integer argument. + /// An integer value: -1 for a negative argument; + /// 0 for a zero argument, and 1 for a positive argument. + /// + public static int signum(int x) { + if (x < 0) + return -1; + if (x == 0) + return 0; + return 1; + } + + /// + /// An adjusted remainder function as defined in "Calendrical + /// Calculations". + /// + /// The double x argument. + /// The double y argument, the divisor. + /// A double value representing remainder; but instead 0.0 + /// the divisor y is returned. + /// + public static double amod(double x, double y) { + double d = mod(x, y); + return (d == 0.0) ? y : d; + } + + /// + /// The adjusted remainder functions for integers as defined in + /// "Calendrical Calculations". + /// + /// The integer argument to be divided. + /// The integer divisor argument. + /// The remainder as an integer; however instead 0 + /// is the divisor y returned. + /// + public static int amod(int x, int y) { + int i = mod(x, y); + return (i == 0) ? y : i; + } +} +*/ + +/// The class implements methods to handle the fixed date value from +/// the "Calendrical Calculations" books. +/// +/// +/// +/// For implementing the Calendar classes I used the algorithms from the +/// book "Calendrical Calculations" by Nachum Dershowitz and Edward M. +/// Rheingold, second reprint 1998. Trying to prevent the introduction of new +/// bugs, I implemented their algorithms in the +/// +/// namespace and wrapped it in the calendar classes. +/// +/// +/// The fixed day number is also known as R.D. - rata die. +/// Midnight at the onset of Monday, +/// January 1, year 1 (Gregorian) is R.D. 1. +/// +/// Here are all my references: +/// +/// +/// [1] Nachum Dershowitz and Edward M. Rheingold: "Calendrical Calculations"; +/// Cambridge University Press; second reprint 1998. +/// +/// +/// [2] P. Kenneth Seidelmann (ed.): "Explanatory Supplement to the Astronomical +/// Almanac"; University Science Books, Sausalito; 1992 +/// +/// +/// [3] F. Richard Stephenson: "Historical Eclipses and Earth Rotation"; +/// Cambridge University Press; 1997 +/// +/// +/// +internal class CCFixed { + /// The method computes the + /// + /// from a fixed day number. + /// + /// A integer representing the fixed day number. + /// + /// The representing + /// the date. + /// + public static System.DateTime ToDateTime(int date) { + long ticks = (date - 1) * System.TimeSpan.TicksPerDay; + return new System.DateTime(ticks); + } + + /// The method computes the + /// + /// from a fixed day number and time arguments. + /// + /// An integer representing the fixed day number. + /// + /// An integer argument specifying the hour. + /// + /// An integer argument specifying the minute. + /// + /// An integer argument giving the second. + /// + /// An double argument specifying + /// the milliseconds. Notice that + /// has 100 nanosecond resolution. + /// + /// The representing + /// the date. + /// + public static System.DateTime ToDateTime(int date, + int hour, int minute, int second, double milliseconds) + { + System.DateTime time = ToDateTime(date); + time = time.AddHours(hour); + time = time.AddMinutes(minute); + time = time.AddSeconds(second); + return time.AddMilliseconds(milliseconds); + } + + /// + /// A static method computing the fixed day number from a + /// value. + /// + /// A + /// value representing the date. + /// + /// The fixed day number as integer representing the date. + /// + public static int FromDateTime(System.DateTime time) { + return 1 + (int)(time.Ticks / System.TimeSpan.TicksPerDay); + } + + /// + /// The static method computes the . + /// + /// An integer representing the fixed day number. + /// + /// The day of week. + public static DayOfWeek day_of_week(int date) { + return (DayOfWeek)(date % 7);//CCMath.mod(date, 7); + } + + /// + /// The static method computes the date of a day of week on or before + /// a particular date. + /// + /// An integer representing the date as + /// fixed day number. + /// + /// An integer representing the day of the week, + /// starting with 0 for sunday. + /// + /// The fixed day number of the day of week specified by k + /// on or before the given date. + /// + public static int kday_on_or_before(int date, int k) { + return date - (int)day_of_week(date-k); + } + + /// + /// The static method computes the date of a day of week on or after + /// a particular date. + /// + /// An integer representing the date as + /// fixed day number. + /// + /// An integer representing the day of the week, + /// starting with 0 for sunday. + /// + /// The fixed day number of the day of week specified by k + /// on or after the given date. + /// + public static int kday_on_or_after(int date, int k) { + return kday_on_or_before(date+6, k); + } + + /// + /// The static method computes the date of a day of week that is + /// nearest to a particular date. + /// + /// An integer representing the date as + /// fixed day number. + /// + /// An integer representing the day of the week, + /// starting with 0 for sunday. + /// + /// The fixed day number of the day of week neares to the + /// given date. + /// + public static int kd_nearest(int date, int k) { + return kday_on_or_before(date+3, k); + } + + /// + /// The static method computes the date of a day of week after + /// a particular date. + /// + /// An integer representing the date as + /// fixed day number. + /// + /// An integer representing the day of the week, + /// starting with 0 for sunday. + /// + /// The fixed day number of the day of week specified by k + /// after the given date. + /// + public static int kday_after(int date, int k) { + return kday_on_or_before(date+7, k); + } + + /// + /// The static method computes the date of a day of week before + /// a particular date. + /// + /// An integer representing the date as + /// fixed day number. + /// + /// An integer representing the day of the week, + /// starting with 0 for sunday. + /// + /// The fixed day number of the day of week specified by k + /// before the given date. + /// + public static int kday_before(int date, int k) { + return kday_on_or_before(date-1, k); + } +} // class CCFixed + + +/// +/// A class encapsulating the functions of the Gregorian calendar as static +/// methods. +/// +/// +/// +/// This class is not compatible to +/// . +/// +/// +/// The fixed day number is also known as R.D. - rata die. +/// Midnight at the onset of Monday, +/// January 1, year 1 (Gregorian) is R.D. 1. +/// +/// +/// +internal class CCGregorianCalendar { + /// An integer defining the epoch of the Gregorian calendar + /// as fixed day number. + /// The epoch is January 3, 1 C.E. (Julian). + const int epoch = 1; + + /// The enumeration defines the months of the Gregorian + /// calendar. + /// + public enum Month { + /// + /// January. + /// + january = 1, + /// + /// February. + /// + february, + /// + /// March. + /// + march, + /// + /// April. + /// + april, + /// + /// May. + /// + may, + /// + /// June. + /// + june, + /// + /// July. + /// + july, + /// + /// August. + /// + august, + /// + /// September. + /// + september, + /// + /// October. + /// + october, + /// + /// November. + /// + november, + /// + /// December. + /// + december + }; + + + /// + /// The method tells whether the year is a leap year. + /// + /// An integer representing the Gregorian year. + /// + /// A boolean which is true if is + /// a leap year. + /// + public static bool is_leap_year(int year) { + if (year % 4 != 0) + return false; + switch (year % 400) { + case 100: + return false; + case 200: + return false; + case 300: + return false; + } + return true; + } + + /// + /// The method returns the fixed day number of the given Gregorian + /// date. + /// + /// An integer representing the day of the month, + /// counting from 1. + /// + /// An integer representing the month in the + /// Gregorian year. + /// + /// An integer representing the Gregorian year. + /// Non-positive values are allowed also. + /// + /// An integer value representing the fixed day number. + /// + public static int fixed_from_dmy(int day, int month, int year) { + int k = epoch - 1; + k += 365 * (year-1); + //k += CCMath.div(year-1, 4); + //k -= CCMath.div(year-1, 100); + //k += CCMath.div(year-1, 400); + //k += CCMath.div(367*month-362, 12); + k += (year - 1) / 4; + k -= (year - 1) / 100; + k += (year - 1) / 400; + k += (367 * month - 362) / 12; + if (month > 2) { + k -= is_leap_year(year) ? 1 : 2; + } + + k += day; + + return k; + } + + /// + /// The method computes the Gregorian year from a fixed day number. + /// + /// The fixed day number. + /// + /// An integer value giving the Gregorian year of the date. + /// + public static int year_from_fixed(int date) { + int d = date - epoch; + int n_400 = d / 146097; + d %= 146097; + int n_100 = d / 36524; + d %= 36524; + int n_4 = d / 1461; + d %= 1461; + int n_1 = d / 365; + //int n_400 = CCMath.div_mod(out d, d, 146097); + //int n_100 = CCMath.div_mod(out d, d, 36524); + //int n_4 = CCMath.div_mod(out d, d, 1461); + //int n_1 = CCMath.div(d, 365); + + int year = 400*n_400 + 100*n_100 + 4*n_4 + n_1; + return (n_100 == 4 || n_1 == 4) ? year : year + 1; + } + + /// + /// The method computes the Gregorian year and month from a fixed day + /// number. + /// + /// The output value giving the Gregorian month. + /// + /// The output value giving the Gregorian year. + /// + /// An integer value specifying the fixed day + /// number. + public static void my_from_fixed(out int month, out int year, + int date) + { + year = year_from_fixed(date); + + int prior_days = date - fixed_from_dmy(1, (int)Month.january, + year); + + int correction; + if (date < fixed_from_dmy(1, (int)Month.march, year)) { + correction = 0; + } else if (is_leap_year(year)) { + correction = 1; + } else { + correction = 2; + } + + //month = CCMath.div(12 * (prior_days + correction) + 373, 367); + month = (12 * (prior_days + correction) + 373) / 367; + + } + + /// + /// The method computes the Gregorian year, month, and day from a + /// fixed day number. + /// + /// The output value returning the day of the + /// month. + /// + /// The output value giving the Gregorian month. + /// + /// The output value giving the Gregorian year. + /// + /// An integer value specifying the fixed day + /// number. + public static void dmy_from_fixed(out int day, out int month, + out int year, + int date) + { + my_from_fixed(out month, out year, date); + day = date - fixed_from_dmy(1, month, year) + 1; + } + + /// A method computing the Gregorian month from a fixed + /// day number. + /// + /// An integer specifying the fixed day number. + /// + /// An integer value representing the Gregorian month. + /// + public static int month_from_fixed(int date) { + int month, year; + + my_from_fixed(out month, out year, date); + return month; + } + + /// + /// A method computing the day of the month from a fixed day number. + /// + /// An integer specifying the fixed day number. + /// + /// An integer value representing the day of the month. + /// + public static int day_from_fixed(int date) { + int day, month, year; + + dmy_from_fixed(out day, out month, out year, date); + return day; + } + + /// + /// The method computes the difference between two Gregorian dates. + /// + /// The integer parameter gives the day of month + /// of the first date. + /// + /// The integer parameter gives the Gregorian + /// month of the first date. + /// + /// The integer parameter gives the Gregorian + /// year of the first date. + /// + /// The integer parameter gives the day of month + /// of the second date. + /// + /// The integer parameter gives the Gregorian + /// month of the second date. + /// + /// The integer parameter gives the Gregorian + /// year of the second date. + /// + /// An integer giving the difference of days from the first + /// the second date. + /// + public static int date_difference(int dayA, int monthA, int yearA, + int dayB, int monthB, int yearB) + { + return fixed_from_dmy(dayB, monthB, yearB) - + fixed_from_dmy(dayA, monthA, yearA); + } + + /// + /// The method computes the number of the day in the year from + /// a Gregorian date. + /// + /// An integer representing the day of the month, + /// counting from 1. + /// + /// An integer representing the month in the + /// Gregorian year. + /// + /// An integer representing the Gregorian year. + /// Non-positive values are allowed also. + /// + /// An integer value giving the number of the day in the + /// Gregorian year, counting from 1. + /// + public static int day_number(int day, int month, int year) { + return date_difference(31, (int)Month.december, year-1, + day, month, year); + } + + /// + /// The method computes the days remaining in the given Gregorian + /// year from a Gregorian date. + /// + /// An integer representing the day of the month, + /// counting from 1. + /// + /// An integer representing the month in the + /// Gregorian year. + /// + /// An integer representing the Gregorian year. + /// Non-positive values are allowed also. + /// + /// An integer value giving the number of days remaining in + /// the Gregorian year. + /// + public static int days_remaining(int day, int month, int year) { + return date_difference(day, month, year, + 31, (int)Month.december, year); + } + + // Helper functions for the Gregorian calendars. + + /// + /// Adds months to the given date. + /// + /// The + /// to which to add + /// months. + /// + /// The number of months to add. + /// A new value, that + /// results from adding to the specified + /// DateTime. + public static System.DateTime AddMonths(System.DateTime time, + int months) + { + int rd = CCFixed.FromDateTime(time); + int day, month, year; + dmy_from_fixed(out day, out month, out year, rd); + month += months; + int maxday = GetDaysInMonth (year, month); + if (day > maxday) + day = maxday; + rd = fixed_from_dmy(day, month, year); + System.DateTime t = CCFixed.ToDateTime(rd); + return t.Add(time.TimeOfDay); + } + + /// + /// Adds years to the given date. + /// + /// The + /// to which to add + /// months. + /// + /// The number of years to add. + /// A new value, that + /// results from adding to the specified + /// DateTime. + public static System.DateTime AddYears(System.DateTime time, + int years) + { + int rd = CCFixed.FromDateTime(time); + int day, month, year; + dmy_from_fixed(out day, out month, out year, rd); + year += years; + int maxday = GetDaysInMonth (year, month); + if (day > maxday) + day = maxday; + rd = fixed_from_dmy(day, month, year); + System.DateTime t = CCFixed.ToDateTime(rd); + return t.Add(time.TimeOfDay); + } + + /// + /// Gets the of the month from . + /// + /// The + /// that specifies a + /// date. + /// + /// An integer giving the day of months, starting with 1. + /// + public static int GetDayOfMonth(System.DateTime time) { + return day_from_fixed(CCFixed.FromDateTime(time)); + } + + /// + /// The method gives the number of the day in the year. + /// + /// The + /// that specifies a + /// date. + /// + /// An integer representing the day of the year, + /// starting with 1. + public static int GetDayOfYear(System.DateTime time) { + int rd = CCFixed.FromDateTime(time); + int year = year_from_fixed(rd); + int rd1_1 = fixed_from_dmy(1, 1, year); + return rd - rd1_1 + 1; + } + + /// + /// A method that gives the number of days of the specified + /// month of the . + /// + /// An integer that gives the year in the current + /// era. + /// An integer that gives the month, starting + /// with 1. + /// An integer that gives the number of days of the + /// specified month. + public static int GetDaysInMonth(int year, int month) { + int rd1 = fixed_from_dmy(1, month, year); + int rd2 = fixed_from_dmy(1, month+1, year); + return rd2 - rd1; + } + + /// + /// The method gives the number of days in the specified year. + /// + /// An integer that gives the year. + /// + /// An integer that gives the number of days of the + /// specified year. + public static int GetDaysInYear(int year) { + int rd1 = fixed_from_dmy(1, 1, year); + int rd2 = fixed_from_dmy(1, 1, year+1); + return rd2 - rd1; + } + + /// + /// The method gives the number of the month of the specified + /// date. + /// + /// The + /// that specifies a + /// date. + /// + /// An integer representing the month, + /// starting with 1. + public static int GetMonth(System.DateTime time) { + return month_from_fixed(CCFixed.FromDateTime(time)); + } + + /// + /// The method gives the number of the year of the specified + /// date. + /// + /// The + /// that specifies a + /// date. + /// + /// An integer representing the year. + /// + public static int GetYear(System.DateTime time) { + return year_from_fixed(CCFixed.FromDateTime(time)); + } + + /// + /// A virtual method that tells whether the given day + /// is a leap day. + /// + /// An integer that specifies the year. + /// + /// An integer that specifies the month. + /// + /// An integer that specifies the day. + /// + /// A boolean that tells whether the given day is a leap + /// day. + /// + public static bool IsLeapDay(int year, int month, int day) { + return is_leap_year(year) && month == 2 && day == 29; + } + + /// + /// A method that creates the + /// from the parameters. + /// + /// An integer that gives the year + /// + /// An integer that specifies the month. + /// + /// An integer that specifies the day. + /// + /// An integer that specifies the hour. + /// + /// An integer that specifies the minute. + /// + /// An integer that gives the second. + /// + /// An integer that gives the + /// milliseconds. + /// + /// A + /// representig the date and time. + /// + public static System.DateTime ToDateTime(int year, int month, int day, + int hour, int minute, int second, int milliseconds) + { + return CCFixed.ToDateTime(fixed_from_dmy(day, month, year), + hour, minute, second, milliseconds); + } +} // class CCGregorianCalendar + +/* +/// +/// A class encapsulating the functions of the Julian calendar as static +/// methods. +/// +/// +/// The algorithms don't support a year 0. Years before Common Era +/// (B.C.E. or B.C.) are negative and years of Common Era (C.E. or A.D.) +/// are positive. +/// +/// +/// This class is not compatible to +/// . +/// +/// +/// +internal class CCJulianCalendar { + /// An integer defining the epoch of the Julian calendar + /// as fixed day number. + /// The epoch is December 30, 0 (Gregorian). + const int epoch = -1; // 30. 12. 0 Gregorian + + /// The enumeration defines the months of the Julian + /// calendar. + /// + public enum Month { + /// + /// January. + /// + january = 1, + /// + /// February. + /// + february, + /// + /// March. + /// + march, + /// + /// April. + /// + april, + /// + /// May. + /// + may, + /// + /// June. + /// + june, + /// + /// July. + /// + july, + /// + /// August. + /// + august, + /// + /// September. + /// + september, + /// + /// October. + /// + october, + /// + /// November. + /// + november, + /// + /// December. + /// + december + }; + + /// + /// The method tells whether the year is a leap year. + /// + /// An integer representing the Julian year. + /// + /// A boolean which is true if is + /// a leap year. + /// + public static bool is_leap_year(int year) { + return CCMath.mod(year, 4) == (year > 0 ? 0 : 3); + } + + /// + /// The method returns the fixed day number of the given Julian + /// date. + /// + /// An integer representing the day of the month, + /// counting from 1. + /// + /// An integer representing the month in the + /// Julian year. + /// + /// An integer representing the Julian year. + /// Positive and Negative values are allowed. + /// + /// An integer value representing the fixed day number. + /// + public static int fixed_from_dmy(int day, int month, int year) { + int y = year < 0 ? year+1 : year; + int k = epoch - 1; + k += 365 * (y-1); + k += CCMath.div(y-1, 4); + k += CCMath.div(367*month-362, 12); + if (month > 2) { + k += is_leap_year(year) ? -1 : -2; + } + k += day; + + return k; + } + + /// + /// The method computes the Julian year from a fixed day number. + /// + /// The fixed day number. + /// + /// An integer value giving the Julian year of the date. + /// + public static int year_from_fixed(int date) { + int approx = CCMath.div(4*(date-epoch)+1464, 1461); + return approx <= 0 ? approx - 1 : approx; + } + + /// + /// The method computes the Julian year and month from a fixed day + /// number. + /// + /// The output value giving the Julian month. + /// + /// The output value giving the Julian year. + /// + /// An integer value specifying the fixed day + /// number. + public static void my_from_fixed(out int month, out int year, int date) + { + year = year_from_fixed(date); + + int prior_days = date - fixed_from_dmy(1, (int)Month.january, + year); + + int correction; + if (date < fixed_from_dmy(1, (int)Month.march, year)) { + correction = 0; + } else if (is_leap_year(year)) { + correction = 1; + } else { + correction = 2; + } + + month = CCMath.div(12 * (prior_days + correction) + 373, 367); + } + + + /// + /// The method computes the Julian year, month, and day from a + /// fixed day number. + /// + /// The output value returning the day of the + /// month. + /// + /// The output value giving the Julian month. + /// + /// The output value giving the Julian year. + /// + /// An integer value specifying the fixed day + /// number. + public static void dmy_from_fixed(out int day, out int month, + out int year, int date) + { + my_from_fixed(out month, out year, date); + day = date - fixed_from_dmy(1, month, year) + 1; + } + + /// A method computing the Julian month from a fixed + /// day number. + /// + /// An integer specifying the fixed day number. + /// + /// An integer value representing the Julian month. + /// + public static int month_from_fixed(int date) { + int month, year; + + my_from_fixed(out month, out year, date); + return month; + } + + /// + /// A method computing the day of the month from a fixed day number. + /// + /// An integer specifying the fixed day number. + /// + /// An integer value representing the day of the month. + /// + public static int day_from_fixed(int date) { + int day; + int month; + int year; + + dmy_from_fixed(out day, out month, out year, date); + return day; + } + + /// + /// The method computes the difference between two Julian dates. + /// + /// The integer parameter gives the day of month + /// of the first date. + /// + /// The integer parameter gives the Julian + /// month of the first date. + /// + /// The integer parameter gives the Julian + /// year of the first date. + /// + /// The integer parameter gives the day of month + /// of the second date. + /// + /// The integer parameter gives the Julian + /// month of the second date. + /// + /// The integer parameter gives the Julian + /// year of the second date. + /// + /// An integer giving the difference of days from the first + /// the second date. + /// + public static int date_difference(int dayA, int monthA, int yearA, + int dayB, int monthB, int yearB) + { + return fixed_from_dmy(dayB, monthB, yearB) - + fixed_from_dmy(dayA, monthA, yearA); + } + + /// + /// The method computes the number of the day in the year from + /// a Julian date. + /// + /// An integer representing the day of the month, + /// counting from 1. + /// + /// An integer representing the month in the + /// Julian year. + /// + /// An integer representing the Julian year. + /// Negative values are allowed also. + /// + /// An integer value giving the number of the day in the + /// Julian year, counting from 1. + /// + public static int day_number(int day, int month, int year) { + return date_difference(31, (int)Month.december, year-1, + day, month, year); + } + + /// + /// The method computes the days remaining in the given Julian + /// year from a Julian date. + /// + /// An integer representing the day of the month, + /// counting from 1. + /// + /// An integer representing the month in the + /// Julian year. + /// + /// An integer representing the Julian year. + /// Negative values are allowed also. + /// + /// An integer value giving the number of days remaining in + /// the Julian year. + /// + public static int days_remaining(int day, int month, int year) { + return date_difference(day, month, year, + 31, (int)Month.december, year); + } +} // class CCJulianCalendar + +/// +/// A class encapsulating the functions of the Hebrew calendar as static +/// methods. +/// +/// +/// +/// This class is not compatible to +/// . +/// +/// +/// +internal class CCHebrewCalendar { + /// An integer defining the epoch of the Hebrew calendar + /// as fixed day number. + /// The epoch is October 10, 3761 B.C.E. (Julian). + const int epoch = -1373427; + + /// The enumeration defines the months of the Gregorian + /// calendar. + /// + /// + /// The enumaration differs from .NET which defines Tishri as month 1. + /// + public enum Month { + /// + /// Nisan. + /// + nisan = 1, + /// + /// Iyyar. + /// + iyyar, + /// + /// Sivan. + /// + sivan, + /// + /// Tammuz. + /// + tammuz, + /// + /// Av. + /// + av, + /// + /// Elul. + /// + elul, + /// + /// Tishri. + /// + tishri, + /// + /// Heshvan. + /// + heshvan, + /// + /// Kislev. + /// + kislev, + /// + /// Teveth. + /// + teveth, + /// + /// Shevat. + /// + shevat, + /// + /// Adar. + /// + adar, + /// + /// Adar I. Only in years with Adar II. + /// + adar_I = 12, + /// + /// Adar II. Only in years wirh Adar I. + /// + adar_II = 13, + }; + + /// + /// The method tells whether the year is a leap year. + /// + /// An integer representing the Hebrew year. + /// + /// A boolean which is true if is + /// a leap year. + /// + public static bool is_leap_year(int year) { + return CCMath.mod(7*year+1, 19) < 7; + } + + /// + /// The Method gives the number of the last month in a year, which + /// is equal with the number of month in a Hebrew year. + /// + /// An integer representing the Hebrew year. + /// + /// An integer giving the number of the last month of the + /// Hebrew year, which is the same as the numbers of month in the + /// year. + /// + public static int last_month_of_year(int year) { + return is_leap_year(year) ? 13 : 12; + } + + + /// The method is a helper function. + /// An integer specifying the Hebrew year. + /// + /// An integer representing the number of elapsed days + /// until the Hebrew year. + public static int elapsed_days(int year) { + int months_elapsed = CCMath.div(235*year-234, 19); + int r; + int d = CCMath.div_mod(out r, months_elapsed, 1080); + int parts_elapsed = 204 + 793 * r; + int hours_elapsed = 11 + 12 * months_elapsed + + 793 * d + CCMath.div(parts_elapsed, 1080); + + int day = 29*months_elapsed + CCMath.div(hours_elapsed, 24); + + if (CCMath.mod(3*(day+1), 7) < 3) { + day += 1; + } + + return day; + } + + /// A method computing the delay of new year for the given + /// Hebrew year. + /// + /// An integer that gives the Hebrew year. + /// + /// The new year delay in days of the given Hebrew year. + /// + public static int new_year_delay(int year) { + int ny1 = elapsed_days(year); + int ny2 = elapsed_days(year+1); + + if (ny2 - ny1 == 356) { + return 2; + } + int ny0 = elapsed_days(year-1); + if (ny1 - ny0 == 382) { + return 1; + } + return 0; + } + + /// + /// The method computes the last day of month (nummer of days in a + /// month) of the given Hebrew year. + /// + /// The Hebrew month, allowed value between + /// One and Thirteen. + /// + /// An integer that gives the Hebrew year. + /// + /// The number of the last day of the month of the given + /// Hebrew year, which gives automatically the number of days in the + /// month. + /// + /// + /// The exception is thrown if month not between One and Thirteen. + /// + public static int last_day_of_month(int month, int year) { + if (month < 1 || month > 13) + throw new System.ArgumentOutOfRangeException("month", + "Month should be between One and Thirteen."); + switch (month) { + case 2: return 29; + case 4: return 29; + case 6: return 29; + case 8: + if (!long_heshvan(year)) + return 29; + break; + case 9: + if (short_kislev(year)) + return 29; + break; + case 10: return 29; + case 12: + if (!is_leap_year(year)) + return 29; + break; + case 13: return 29; + } + return 30; + } + + /// + /// The functions checks whether the month Heshvan is a long one + /// in the given Hebrew year. + /// + /// An integer that gives the Hebrew year. + /// + /// A boolean value: true if there is a long Heshvan + /// in the given Hebrew year; false otherwise. + /// + public static bool long_heshvan(int year) { + return CCMath.mod(days_in_year(year), 10) == 5; + } + + /// + /// The functions checks whether the month Kislev is a short one + /// in the given Hebrew year. + /// + /// An integer that gives the Hebrew year. + /// + /// A boolean value: true if there is a short Kislev + /// in the given Hebrew year; false otherwise. + /// + public static bool short_kislev(int year) { + return CCMath.mod(days_in_year(year), 10) == 3; + } + + /// + /// The functions gives the number of days in the specified Hebrew + /// year. + /// + /// An integer that gives the Hebrew year. + /// + /// The days of the Hebrew year as integer. + /// + public static int days_in_year(int year) { + return fixed_from_dmy(1, 7, year+1) - + fixed_from_dmy(1, 7, year); + } + + /// + /// The method returns the fixed day number of the given Hebrew + /// date. + /// + /// An integer representing the day of the month, + /// counting from 1. + /// + /// An integer representing the month in the + /// Hebrew year. + /// + /// An integer representing the Hebrew year. + /// Non-positive values are allowed also. + /// + /// An integer value representing the fixed day number. + /// + public static int fixed_from_dmy(int day, int month, int year) { + int m; + int k = epoch-1; + k += elapsed_days(year); + k += new_year_delay(year); + + if (month < 7) { + int l = last_month_of_year(year); + for (m = 7; m <= l; m++) { + k += last_day_of_month(m, year); + } + for (m = 1; m < month; m++) { + k += last_day_of_month(m, year); + } + } + else { + for (m = 7; m < month; m++) { + k += last_day_of_month(m, year); + } + } + + k += day; + + return k; + } + + /// + /// The method computes the Hebrew year from a fixed day number. + /// + /// The fixed day number. + /// + /// An integer value giving the Hebrew year of the date. + /// + public static int year_from_fixed(int date) { + int approx = (int)System.Math.Floor( + ((double)(date - epoch))/(35975351.0/98496.0)); + int y; + for (y = approx; date >= fixed_from_dmy(1, 7, y); y++) {} + return y-1; + } + + /// + /// The method computes the Hebrew year and month from a fixed day + /// number. + /// + /// The output value giving the Hebrew month. + /// + /// The output value giving the Hebrew year. + /// + /// An integer value specifying the fixed day + /// number. + public static void my_from_fixed(out int month, out int year, + int date) + { + year = year_from_fixed(date); + + int start = date < fixed_from_dmy(1, 1, year) ? 7 : 1; + + for (month = start; + date > fixed_from_dmy(last_day_of_month(month, year), + month, year); + month++) + {} + } + + /// + /// The method computes the Hebrew year, month, and day from a + /// fixed day number. + /// + /// The output value returning the day of the + /// month. + /// + /// The output value giving the Hebrew month. + /// + /// The output value giving the Hebrew year. + /// + /// An integer value specifying the fixed day + /// number. + public static void dmy_from_fixed(out int day, out int month, + out int year, int date) + { + my_from_fixed(out month, out year, date); + day = date - fixed_from_dmy(1, month, year) + 1; + } + + /// A method computing the Hebrew month from a fixed + /// day number. + /// + /// An integer specifying the fixed day number. + /// + /// An integer value representing the Hebrew month. + /// + public static int month_from_fixed(int date) { + int month, year; + + my_from_fixed(out month, out year, date); + return month; + } + + /// + /// A method computing the day of the month from a fixed day number. + /// + /// An integer specifying the fixed day number. + /// + /// An integer value representing the day of the month. + /// + public static int day_from_fixed(int date) { + int day, month, year; + + dmy_from_fixed(out day, out month, out year, date); + return day; + } + + /// + /// The method computes the difference between two Hebrew dates. + /// + /// The integer parameter gives the day of month + /// of the first date. + /// + /// The integer parameter gives the Hebrew + /// month of the first date. + /// + /// The integer parameter gives the Hebrew + /// year of the first date. + /// + /// The integer parameter gives the day of month + /// of the second date. + /// + /// The integer parameter gives the Hebrew + /// month of the second date. + /// + /// The integer parameter gives the Hebrew + /// year of the second date. + /// + /// An integer giving the difference of days from the first + /// the second date. + /// + public static int date_difference(int dayA, int monthA, int yearA, + int dayB, int monthB, int yearB) + { + return fixed_from_dmy(dayB, monthB, yearB) - + fixed_from_dmy(dayA, monthA, yearA); + } + + /// + /// The method computes the number of the day in the year from + /// a Hebrew date. + /// + /// An integer representing the day of the month, + /// counting from 1. + /// + /// An integer representing the month in the + /// Hebrew year. + /// + /// An integer representing the Hebrew year. + /// + /// An integer value giving the number of the day in the + /// Hebrew year, counting from 1. + /// + public static int day_number(int day, int month, int year) { + return date_difference(1, 7, year, + day, month, year) + 1; + } + + /// + /// The method computes the days remaining in the given Hebrew + /// year from a Hebrew date. + /// + /// An integer representing the day of the month, + /// counting from 1. + /// + /// An integer representing the month in the + /// Hebrew year. + /// + /// An integer representing the Hebrew year. + /// + /// An integer value giving the number of days remaining in + /// the Hebrew year. + /// + public static int days_remaining(int day, int month, int year) { + return date_difference(day, month, year, + 1, 7, year+1)-1; + } +} // class HebrewCalendar + + +/// +/// A class encapsulating the functions of the Islamic calendar as static +/// methods. +/// +/// +/// There is no difference here in using Hijri or Islamic calendar. +/// +/// The epoch of the Islamic calendar isn't fixed, because we cannot +/// surely say today, when the crescent of the new moon has been observed +/// around the July 16, 622 C.E. Julian. Even today the start and end of +/// the month Ramadan is defined by religous authorities. So the calendar +/// can be offset by two days. +/// +/// +/// We don't support the offset here, however we changed the epoch from +/// "Calendrical Calculations" to value, that .Net seems to be using. +/// +/// +/// This class is not compatible to +/// . +/// +/// +/// +internal class CCHijriCalendar { + /// An integer defining the epoch of the Gregorian calendar + /// as fixed day number. + /// + /// + /// The epoch is given as 16 July 622 C.E. Julian (R.D. 227015) + /// in Calendrical Calculations, the approximate date of + /// the emigration of + /// Muhammed to Medina. However there is no way to determine today + /// the observation of the crescent of the new moon in July 622 C.E. + /// (Julian). So there is some variability in the epoch. + /// Religous authorities determine the epoch by observing the + /// crescent of the new moon for the month Ramadan, so there might + /// be an offsets by two days of the epoch. + /// + /// Windows + /// supports an AddHijriDate parameter in the registry to adapt + /// for it. It seems that the .NET implementation of + /// HijriCalendar uses an epoch of 227014, so we use it here. The + /// ArgumentOutOfRangeException gives July, 18 622 as epoch, + /// which is 227014 supporting our theory. + /// + /// + const int epoch = 227014; + + /// The enumeration defines the months of the Islamic + /// calendar. + /// + public enum Month { + /// + /// Muharram. + /// + muharram = 1, + /// + /// Safar. + /// + safar, + /// + /// Rabi I. + /// + rabi_I, + /// + /// Rabi II. + /// + rabi_II, + /// + /// Jumada I. + /// + jumada_I, + /// + /// Jumada II. + /// + jumada_II, + /// + /// Rajab. + /// + rajab, + /// + /// Shaban. + /// + shaban, + /// + /// Ramadan. + /// + ramadan, + /// + /// Shawwal. + /// + shawwal, + /// + /// Dhu Al-Quada. + /// + dhu_al_quada, + /// + /// Dhu Al-Hijja. + /// + dhu_al_hijja, + }; + + /// + /// The method tells whether the year is a leap year. + /// + /// An integer representing the Islamic year. + /// + /// A boolean which is true if is + /// a leap year. + /// + public static bool is_leap_year(int year) { + return CCMath.mod(14+11*year, 30) < 11; + } + + /// + /// The method returns the fixed day number of the given Islamic + /// date. + /// + /// An integer representing the day of the month, + /// counting from 1. + /// + /// An integer representing the month in the + /// Islamic year. + /// + /// An integer representing the Islamic year. + /// Non-positive values are allowed also. + /// + /// An integer value representing the fixed day number. + /// + public static int fixed_from_dmy(int day, int month, int year) { + int k = epoch - 1; + k += 354 * (year-1); + k += CCMath.div(3+11*year, 30); + k += (int)System.Math.Ceiling(29.5 * (double)(month-1)); + k += day; + + return k; + } + + /// + /// The method computes the Islamic year from a fixed day number. + /// + /// The fixed day number. + /// + /// An integer value giving the Islamic year of the date. + /// + public static int year_from_fixed(int date) { + return CCMath.div(30*(date-epoch)+10646, 10631); + } + + /// + /// The method computes the Islamic year and month from a fixed day + /// number. + /// + /// The output value giving the Islamic month. + /// + /// The output value giving the Islamic year. + /// + /// An integer value specifying the fixed day + /// number. + public static void my_from_fixed(out int month, out int year, int date) + { + year = year_from_fixed(date); + + int m = 1+(int)System.Math.Ceiling( + ((double)(date-29-fixed_from_dmy(1,1,year)))/29.5); + + month = m < 12 ? m : 12; + } + + /// + /// The method computes the Islamic year, month, and day from a + /// fixed day number. + /// + /// The output value returning the day of the + /// month. + /// + /// The output value giving the Islamic month. + /// + /// The output value giving the Islamic year. + /// + /// An integer value specifying the fixed day + /// number. + public static void dmy_from_fixed(out int day, out int month, + out int year, int date) + { + my_from_fixed(out month, out year, date); + day = date - fixed_from_dmy(1, month, year) + 1; + } + + /// A method computing the Islamic month from a fixed + /// day number. + /// + /// An integer specifying the fixed day number. + /// + /// An integer value representing the Islamic month. + /// + public static int month_from_fixed(int date) { + int month, year; + + my_from_fixed(out month, out year, date); + return month; + } + + /// + /// A method computing the day of the month from a fixed day number. + /// + /// An integer specifying the fixed day number. + /// + /// An integer value representing the day of the month. + /// + public static int day_from_fixed(int date) { + int day; + int month; + int year; + + dmy_from_fixed(out day, out month, out year, date); + return day; + } + + /// + /// The method computes the difference between two Islamic dates. + /// + /// The integer parameter gives the day of month + /// of the first date. + /// + /// The integer parameter gives the Islamic + /// month of the first date. + /// + /// The integer parameter gives the Islamic + /// year of the first date. + /// + /// The integer parameter gives the day of month + /// of the second date. + /// + /// The integer parameter gives the Islamic + /// month of the second date. + /// + /// The integer parameter gives the Islamic + /// year of the second date. + /// + /// An integer giving the difference of days from the first + /// the second date. + /// + public static int date_difference(int dayA, int monthA, int yearA, + int dayB, int monthB, int yearB) + { + return fixed_from_dmy(dayB, monthB, yearB) - + fixed_from_dmy(dayA, monthA, yearA); + } + + /// + /// The method computes the number of the day in the year from + /// a Islamic date. + /// + /// An integer representing the day of the month, + /// counting from 1. + /// + /// An integer representing the month in the + /// Islamic year. + /// + /// An integer representing the Islamic year. + /// + /// An integer value giving the number of the day in the + /// Islamic year, counting from 1. + /// + public static int day_number(int day, int month, int year) { + return date_difference(31, 12, year-1, day, month, year); + } + + /// + /// The method computes the days remaining in the given Islamic + /// year from a Islamic date. + /// + /// An integer representing the day of the month, + /// counting from 1. + /// + /// An integer representing the month in the + /// Islamic year. + /// + /// An integer representing the Islamic year. + /// Non-positive values are allowed also. + /// + /// An integer value giving the number of days remaining in + /// the Islamic year. + /// + public static int days_remaining(int day, int month, int year) { + return date_difference(day, month, year,31, 12, year); + } +} // class CCHijriCalendar + +internal class CCEastAsianLunisolarCalendar +{ + const int initial_epact = 29; // at 1900 + + public static int fixed_from_dmy (int day, int month, int year) + { + throw new Exception ("fixed_from_dmy"); + } + + public static int year_from_fixed (int date) + { + throw new Exception ("year_from_fixed"); + } + + public static void my_from_fixed(out int month, out int year, int date) + { + throw new Exception ("my_from_fixed"); + } + + public static void dmy_from_fixed(out int day, out int month, + out int year, int date) + { + throw new Exception ("dmy_from_fixed"); + } + + public static DateTime AddMonths (DateTime date, int months) + { + + throw new Exception ("AddMonths"); + } + + public static DateTime AddYears (DateTime date, int years) + { + throw new Exception ("AddYears"); + } + + public static int GetDayOfMonth (DateTime date) + { + throw new Exception ("GetDayOfMonth"); + } + + public static int GetDayOfYear (DateTime date) + { + throw new Exception ("GetDayOfYear"); + } + + public static int GetDaysInMonth (int gyear, int month) + { + throw new Exception ("GetDaysInMonth"); + } + + public static int GetDaysInYear (int year) + { + throw new Exception ("GetDaysInYear"); + } + + public static int GetMonth (DateTime date) + { + throw new Exception ("GetMonth"); + } + + static readonly int [] leap_month_calc = new int [] { + 0, 2, 0, 2, 2, 4, 5, 6, 7, 8, 9, 10}; + + public static bool IsLeapMonth (int gyear, int month) + { + int goldenNumber = gyear % 19; + + bool chu = false; + bool leap = false; + double s = 0; + for (int y = 0; y < goldenNumber; y++) { + for (int l = 0, m = 1; m <= month; m++) { + if (leap) { + l += 30; + leap = false; + if (y == goldenNumber && m == month) + return true; + } else { + l += chu ? 30 : 29; + chu = !chu; + s += 30.44; + if (s - l > 29) + leap = true; + } + } + } + return false; + + throw new Exception ("IsLeapMonth"); + } + + public static bool IsLeapYear (int gyear) + { + + // FIXME: it is still wrong. + int d = gyear % 19; + switch (d) { + case 0: case 3: case 6: case 9: case 11: case 14: case 17: + return true; + default: + return false; + } + } + + public static DateTime ToDateTime (int year, int month, int day, int hour, int minute, int second, int millisecond) + { + throw new Exception ("ToDateTime"); + } +} + +/// +/// A class that supports the Gregorian based calendars with other eras +/// (e.g. ). +/// +internal class CCGregorianEraHandler { + /// + /// A struct that represents a single era. + /// + struct Era { + /// + /// The integer number identifying the era. + /// + private int _nr; + + /// + /// A get-only property that gives the era integer number. + /// + public int Nr { get { return _nr; } } + + /// This integer gives the first day of the era as + /// fixed day number. + /// + private int _start; // inclusive + /// + /// This integer gives the gregorian year of the + /// value. + /// + private int _gregorianYearStart; + /// + /// This integer gives the last day of the era as fixed day + /// number. + /// + private int _end; // inclusive + /// + /// This integer gives the largest year number of this era. + /// + private int _maxYear; + + /// + /// This constructor creates the era structure. + /// + /// The integer number of the era. + /// + /// The fixed day number defining the + /// first day of the era. + /// + /// The fixed day number that defines the + /// last day of the era. + /// + public Era(int nr, int start, int end) { + if (nr == 0) + throw new System.ArgumentException( + "Era number shouldn't be zero."); + _nr = nr; + if (start > end) { + throw new System.ArgumentException( + "Era should start before end."); + } + _start = start; + _end = end; + + _gregorianYearStart = + CCGregorianCalendar.year_from_fixed(_start); + int gregorianYearEnd = + CCGregorianCalendar.year_from_fixed(_end); + _maxYear = gregorianYearEnd - _gregorianYearStart + 1; + } + + /// + /// This method computes the Gregorian year from the year + /// of this era. + /// + /// An integer giving the year in the + /// era. + /// + /// + /// The Gregorian year as integer. + /// + /// + /// The exception is thrown if the year isn't valid in this + /// era. + /// + public int GregorianYear(int year) { + if (year < 1 || year > _maxYear) { + System.IO.StringWriter sw = + new System.IO.StringWriter(); + sw.Write( + "Valid Values are between " + + "{0} and {1}, inclusive.", + 1, _maxYear); + throw new System.ArgumentOutOfRangeException( + "year", sw.ToString()); + } + return year + _gregorianYearStart - 1; + } + + /// + /// This function checks wether the given fixed day number is + /// ion the time span of the era. + /// + /// An integer giving the fixed day + /// number. + /// + /// A boolean: true if the argument is in the time + /// span of the era. + /// + public bool Covers(int date) { + return _start <= date && date <= _end; + } + + /// + /// This function returns the year of the era and sets + /// the era in an output parameter. + /// + /// An output parameter returning the + /// era number. + /// + /// An integer giving the fixed day + /// number. + /// + /// An integer giving the year of the era. + /// + /// + /// The exception is thrown if date is outside of the time + /// span of the era. + /// + public int EraYear(out int era, int date) { + if (!Covers(date)) + throw new System.ArgumentOutOfRangeException( + "date", + "Time was out of Era range."); + int gregorianYear = + CCGregorianCalendar.year_from_fixed(date); + era = _nr; + return gregorianYear - _gregorianYearStart + 1; + } + } // struct Era + + /// + /// A private member storing the eras in a + /// . + /// + //private SortedList _Eras; + + /// + /// The property returns the era numbers as an array of integers. + /// + public int[] Eras { + get { + int[] a = new int[_Eras.Count]; + + for (int i = 0; i < _Eras.Count; i++) { + Era e = (Era)_Eras.GetByIndex(i); + a[i] = e.Nr; + } + + return a; + } + } + + /// + /// Constructor. + /// + public CCGregorianEraHandler() { + _Eras = new SortedList(); + } + + /// + /// Method adds an era to the GregorianEraHandler instance. + /// + /// The integer number of the era. + /// + /// The fixed day number defining the + /// first day of the era. + /// + /// The fixed day number that defines the + /// last day of the era. + /// + public void appendEra(int nr, int rd_start, int rd_end) { + Era era = new Era(nr, rd_start, rd_end); + _Eras[(System.Object)nr] = era; + } + /// + /// Method adds a yet not-ended era to the GregorianEraHandler + /// instance. + /// + /// The integer number of the era. + /// + /// The fixed day number defining the + /// first day of the era. + /// + public void appendEra(int nr, int rd_start) { + appendEra(nr, rd_start, + CCFixed.FromDateTime(DateTime.MaxValue)); + } + + /// + /// This method computes the Gregorian year from the year + /// of the given era. + /// + /// An integer giving the year in the + /// era. + /// + /// An integer giving the era number. + /// + /// + /// The Gregorian year as integer. + /// + /// + /// The exception is thrown if the year isn't valid in this + /// era. + /// + public int GregorianYear(int year, int era) { + Era e = (Era)_Eras[(System.Object)era]; + return e.GregorianYear(year); + } + + /// + /// This function returns the year of the era and sets + /// the era in an output parameter. + /// + /// An output parameter returning the + /// era number. + /// + /// An integer giving the fixed day + /// number. + /// + /// An integer giving the year of the era. + /// + /// + /// The exception is thrown if the fixed day number is outside of the + /// time spans of all eras. + /// + public int EraYear(out int era, int date) + { + IList list = _Eras.GetValueList(); + + foreach (Era e in list) { + if (e.Covers(date)) + return e.EraYear(out era, date); + } + + throw new System.ArgumentOutOfRangeException("date", + "Time value was out of era range."); + } + + /// + /// The method checks whether a given + /// is covered by any era. + /// + /// A + /// giving the date and time. + /// + /// + /// The exception is thrown if the argument isn't inside the time + /// span of any era. + /// + public void CheckDateTime(System.DateTime time) { + int date = CCFixed.FromDateTime(time); + + if (!ValidDate(date)) + throw new System.ArgumentOutOfRangeException("time", + "Time value was out of era range."); + } + + /// + /// The method tests whether a given + /// fixed day number is covered by any era. + /// + /// An integer representing the fixed day number. + /// + /// A boolean is returned: true if the argument is inside + /// the time span of one era; false otherwise. + /// + public bool ValidDate(int date) { + IList list = _Eras.GetValueList(); + + foreach (Era e in list) { + if (e.Covers(date)) + return true; + } + + return false; + } + + /// + /// The method tests, whether the era number does exist. + /// + /// An integer giving the era number. + /// + /// A boole value: True if the era number does exist; + /// false otherwise. + /// + public bool ValidEra(int era) { + return _Eras.Contains((System.Object)era); + } +} // class CCGregorianEraHandler + + +// FIXME: remove this class. It should be identical to CCGregorianEraHandler +internal class CCEastAsianLunisolarEraHandler +{ + struct Era + { + private int _nr; // era index + + public int Nr { + get { return _nr; } + } + + private int _start; // inclusive + private int _gregorianYearStart; + private int _end; // inclusive + private int _maxYear; + + public Era (int nr, int start, int end) + { + if (nr == 0) + throw new ArgumentException ("Era number shouldn't be zero."); + _nr = nr; + if (start > end) + throw new ArgumentException ("Era should start before end."); + _start = start; + _end = end; + + _gregorianYearStart = CCGregorianCalendar.year_from_fixed (_start); + int gregorianYearEnd = CCGregorianCalendar.year_from_fixed (_end); + _maxYear = gregorianYearEnd - _gregorianYearStart + 1; + } + + public int GregorianYear (int year) + { + if (year < 1 || year > _maxYear) + throw new ArgumentOutOfRangeException ("year", String.Format ("Valid Values are between {0} and {1}, inclusive.", 1, _maxYear)); + return year + _gregorianYearStart - 1; + } + + public bool Covers (int date) { + return _start <= date && date <= _end; + } + + public int EraYear (out int era, int date) { + if (!Covers (date)) + throw new ArgumentOutOfRangeException ("date", "Time was out of Era range."); + int gregorianYear = CCGregorianCalendar.year_from_fixed (date); + era = _nr; + return gregorianYear - _gregorianYearStart + 1; + } + } + + //private SortedList _Eras; + + public int [] Eras + { + get { + int[] a = new int [_Eras.Count]; + for (int i = 0; i < _Eras.Count; i++) { + Era e = (Era) _Eras.GetByIndex (i); + a[i] = e.Nr; + } + return a; + } + } + + public CCEastAsianLunisolarEraHandler () + { + _Eras = new SortedList (); + } + + public void appendEra (int nr, int rd_start, int rd_end) + { + Era era = new Era (nr, rd_start, rd_end); + _Eras [nr] = era; + } + + public void appendEra (int nr, int rd_start) + { + appendEra (nr, rd_start, CCFixed.FromDateTime (DateTime.MaxValue)); + } + + public int GregorianYear (int year, int era) + { + Era e = (Era) _Eras [era]; + return e.GregorianYear (year); + } + + public int EraYear (out int era, int date) + { + foreach (Era e in _Eras.Values) + if (e.Covers (date)) + return e.EraYear (out era, date); + + throw new ArgumentOutOfRangeException ("date", "Time value was out of era range."); + } + + public void CheckDateTime (DateTime time) + { + int date = CCFixed.FromDateTime (time); + + if (!ValidDate (date)) + throw new ArgumentOutOfRangeException ("time", "Time value was out of era range."); + } + + public bool ValidDate (int date) + { + foreach (Era e in _Eras.Values) { + if (e.Covers (date)) + return true; + } + return false; + } + + public bool ValidEra (int era) + { + return _Eras.Contains (era); + } +} +*/ +} // namespace System.Globalization diff --git a/corlib/System.Globalization/CultureInfo.cs b/corlib/System.Globalization/CultureInfo.cs new file mode 100644 index 0000000..c9d46d7 --- /dev/null +++ b/corlib/System.Globalization/CultureInfo.cs @@ -0,0 +1,273 @@ +#if !LOCALTEST + +using System.Threading; +using System.Collections.Generic; +using System.IO; + +namespace System.Globalization { + public class CultureInfo { + + #region Static methods + + private static Dictionary shareByName = new Dictionary(); + + private static CultureInfo invariantCulture = null; + + public static CultureInfo GetCultureInfo(string name) { + // Always use lower-case version of name + lock (shareByName) { + CultureInfo ci; + if (!shareByName.TryGetValue(name.ToLowerInvariant(), out ci)) { + ci = new CultureInfo(name); + // Don't put in cache, as the constructor already does this + } + return ci; + } + } + + public static CultureInfo CurrentCulture { + get { + return Thread.CurrentThread.CurrentCulture; + } + } + + public static CultureInfo InvariantCulture { + get { + if (invariantCulture == null) { + invariantCulture = new CultureInfo(string.Empty); + } + return invariantCulture; + } + } + + public static CultureInfo[] GetCultures(CultureTypes types) { + DirectoryInfo cultureDir = new DirectoryInfo(Environment.CultureDirectory); + List ret = new List(); + foreach (FileInfo fi in cultureDir.GetFiles()) { + CultureInfo ci = CultureInfo.GetCultureInfo(fi.Name); + if ((ci.cultureTypes & types) > 0) { + ret.Add(ci); + } + } + return ret.ToArray(); + } + + #endregion + + private string name; + private int lcid; + private string parentName; + private CultureInfo parent = null; + private string displayName; + private string englishName; + private string nativeName; + private string twoLetterISOLanguageName; + private string threeLetterISOLanguageName; + private string threeLetterWindowsLanguageName; + private CultureTypes cultureTypes; + private string ietfLanguageTag; + private bool isNeutralCulture; + private NumberFormatInfo numberFormatInfo; + private TextInfo textInfo; + private DateTimeFormatInfo dateTimeFormat; + + public CultureInfo(string name) { + if (name == null) { + throw new ArgumentNullException(); + } + if (name.Length == 0) { + ConstructInvariant(); + return; + } + // Always use lower-case version of name + string nameLower = name.ToLowerInvariant(); + // If this culture is already loaded and cached, then just copy all of its settings + lock (shareByName) { + CultureInfo cached; + if (shareByName.TryGetValue(nameLower, out cached)) { + CopyFrom(cached); + return; + } + } + // Not cached, so create from new and place in cache + ConstructFromFile(name); + } + + private void ConstructInvariant() { + this.name = string.Empty; + this.displayName = + this.englishName = + this.nativeName = "Invariant Language (Invariant Country)"; + this.lcid = 0x7f; + this.numberFormatInfo = NumberFormatInfo.InvariantInfo; + this.dateTimeFormat = DateTimeFormatInfo.InvariantInfo; + } + + private void ConstructFromFile(string name) { + string fileName = Environment.CultureDirectory + Path.DirectorySeparatorStr + name; + try { + using (StreamReader s = File.OpenText(fileName)) { + this.name = s.ReadLine(); + this.lcid = int.Parse(s.ReadLine().Substring(2), NumberStyles.HexNumber); + this.parentName = s.ReadLine(); + this.englishName = s.ReadLine(); + this.nativeName = s.ReadLine(); + this.displayName = s.ReadLine(); + this.twoLetterISOLanguageName = s.ReadLine(); + this.threeLetterISOLanguageName = s.ReadLine(); + this.threeLetterWindowsLanguageName = s.ReadLine(); + string calendarName = s.ReadLine(); // Calendar + s.ReadLine(); // Optional calendars + this.cultureTypes = (CultureTypes)int.Parse(s.ReadLine()); + this.ietfLanguageTag = s.ReadLine(); + this.isNeutralCulture = bool.Parse(s.ReadLine()); + this.textInfo = new TextInfo(this, s); + if (!this.isNeutralCulture) { + this.numberFormatInfo = new NumberFormatInfo(s); + this.dateTimeFormat = new DateTimeFormatInfo(s, calendarName); + } else { + this.numberFormatInfo = null; + this.dateTimeFormat = null; + } + } + } catch (FileNotFoundException) { + throw new ArgumentException(string.Format("{0} is not a valid culture", name)); + } + lock (shareByName) { + shareByName.Add(name.ToLowerInvariant(), this); + } + } + + private void CopyFrom(CultureInfo ci) { + this.name = ci.name; + this.lcid = ci.lcid; + this.parent = ci.parent; + this.englishName = ci.englishName; + this.nativeName = ci.nativeName; + this.displayName = ci.displayName; + this.twoLetterISOLanguageName = ci.twoLetterISOLanguageName; + this.threeLetterISOLanguageName = ci.threeLetterISOLanguageName; + this.threeLetterWindowsLanguageName = ci.threeLetterWindowsLanguageName; + this.cultureTypes = ci.cultureTypes; + this.ietfLanguageTag = ci.ietfLanguageTag; + this.isNeutralCulture = ci.isNeutralCulture; + + this.textInfo = ci.textInfo; + this.numberFormatInfo = ci.numberFormatInfo; + this.dateTimeFormat = ci.dateTimeFormat; + } + + public bool IsReadOnly { + get{ + // At the moment, all CultureInfo's are read-only + return true; + } + } + + public virtual NumberFormatInfo NumberFormat { + get { + if (this.numberFormatInfo == null) { + throw new NotSupportedException("Not supported for neutral cultures"); + } + return this.numberFormatInfo; + } + } + + public virtual DateTimeFormatInfo DateTimeFormat { + get { + if (this.dateTimeFormat == null) { + throw new NotSupportedException("Not supported for neutral cultures"); + } + return this.dateTimeFormat; + } + } + + public virtual int LCID { + get { + return this.lcid; + } + } + + public virtual string Name { + get { + return this.name; + } + } + + public virtual CultureInfo Parent { + get { + if (this.parent == null) { + this.parent = CultureInfo.GetCultureInfo(this.parentName); + } + return this.parent; + } + } + + public virtual string DisplayName { + get { + return this.displayName; + } + } + + public virtual string EnglishName { + get { + return this.englishName; + } + } + + public virtual string NativeName { + get { + return this.nativeName; + } + } + + public virtual string TwoLetterISOLanguageName { + get { + return this.twoLetterISOLanguageName; + } + } + + public virtual string ThreeLetterISOLanguageName { + get { + return this.threeLetterISOLanguageName; + } + } + + public virtual string ThreeLetterWindowsLanguageName { + get { + return this.threeLetterWindowsLanguageName; + } + } + + public virtual CultureTypes CultureTypes { + get { + return this.cultureTypes; + } + } + + public virtual string IetfLanguageTag { + get { + return this.ietfLanguageTag; + } + } + + public virtual bool IsNeutralCulture { + get { + return this.isNeutralCulture; + } + } + + public virtual TextInfo TextInfo { + get { + return this.textInfo; + } + } + + public override string ToString() { + return this.name; + } + + } +} + +#endif \ No newline at end of file diff --git a/corlib/System.Globalization/CultureTypes.cs b/corlib/System.Globalization/CultureTypes.cs new file mode 100644 index 0000000..f0fa8aa --- /dev/null +++ b/corlib/System.Globalization/CultureTypes.cs @@ -0,0 +1,17 @@ +#if !LOCALTEST + +namespace System.Globalization { + [Flags] + public enum CultureTypes { + NeutralCultures = 1, + SpecificCultures = 2, + InstalledWin32Cultures = 4, + AllCultures = 7, + UserCustomCulture = 8, + ReplacementCultures = 16, + WindowsOnlyCultures = 32, + FrameworkCultures = 64, + } +} + +#endif \ No newline at end of file diff --git a/corlib/System.Globalization/DateTimeFormatInfo.cs b/corlib/System.Globalization/DateTimeFormatInfo.cs new file mode 100644 index 0000000..a9bcfab --- /dev/null +++ b/corlib/System.Globalization/DateTimeFormatInfo.cs @@ -0,0 +1,170 @@ +#if !LOCALTEST + +using System.IO; +using System.Threading; +namespace System.Globalization { + public sealed class DateTimeFormatInfo { + + public static DateTimeFormatInfo InvariantInfo { + get { + DateTimeFormatInfo dtfi = new DateTimeFormatInfo(); + dtfi.isReadOnly = true; + return dtfi; + } + } + + public static DateTimeFormatInfo CurrentInfo { + get { + return Thread.CurrentThread.CurrentCulture.DateTimeFormat; + } + } + + public static DateTimeFormatInfo GetInstance(IFormatProvider fp) { + if (fp != null) { + DateTimeFormatInfo dtf = (DateTimeFormatInfo)fp.GetFormat(typeof(DateTimeFormatInfo)); + if (dtf != null) { + return dtf; + } + } + + return CurrentInfo; + } + + private bool isReadOnly; + private string[] abbreviatedDayNames; + private string[] abbreviatedMonthGenitiveNames; + private string[] abbreviatedMonthNames; + private string amDesignator; + private CalendarWeekRule calendarWeekRule; + private string dateSeparator; + private string[] dayNames; + private DayOfWeek firstDayOfWeek; + private string fullDateTimePattern; + private string longDatePattern; + private string longTimePattern; + private string monthDayPattern; + private string[] monthGenitiveNames; + private string[] monthNames; + private string nativeCalendarName; // This probably needs to change + private string pmDesignator; + private string rfc1123Pattern; + private string shortDatePattern; + private string[] shortestDayNames; + private string shortTimePattern; + private string sortableDateTimePattern; + private string timeSeparator; + private string universalSortableDateTimePattern; + private string yearMonthPattern; + private Calendar calendar; + + internal DateTimeFormatInfo(StreamReader s, string calendarName) { + char[] comma = new char[] { ',' }; + this.abbreviatedDayNames = s.ReadLine().Split(comma); + this.abbreviatedMonthGenitiveNames = s.ReadLine().Split(comma); + this.abbreviatedMonthNames = s.ReadLine().Split(comma); + this.amDesignator = s.ReadLine(); + this.calendarWeekRule = (CalendarWeekRule)int.Parse(s.ReadLine()); + this.dateSeparator = s.ReadLine(); + this.dayNames = s.ReadLine().Split(comma); + this.firstDayOfWeek = (DayOfWeek)int.Parse(s.ReadLine()); + this.fullDateTimePattern = s.ReadLine(); + this.longDatePattern = s.ReadLine(); + this.longTimePattern = s.ReadLine(); + this.monthDayPattern = s.ReadLine(); + this.monthGenitiveNames = s.ReadLine().Split(comma); + this.monthNames = s.ReadLine().Split(comma); + this.nativeCalendarName = s.ReadLine(); + s.ReadLine(); // TODO: Appears to be a mistake in the culture files. Extra line added. + this.pmDesignator = s.ReadLine(); + this.rfc1123Pattern = s.ReadLine(); // This is always the same, so does it need to be in the culture file? + this.shortDatePattern = s.ReadLine(); + this.shortestDayNames = s.ReadLine().Split(comma); + this.shortTimePattern = s.ReadLine(); + this.sortableDateTimePattern = s.ReadLine(); // This is always the same + this.timeSeparator = s.ReadLine(); + this.universalSortableDateTimePattern = s.ReadLine(); // This is always the same + this.yearMonthPattern = s.ReadLine(); + this.calendar = Calendar.CreateByName(calendarName); + } + + public DateTimeFormatInfo() { + // Construct an invariant culture DateTimeFormatInfo + char[] comma = new char[] { ',' }; + this.isReadOnly = true; + this.abbreviatedDayNames = "Sun,Mon,Tue,Wed,Thu,Fri,Sat".Split(comma); + this.abbreviatedMonthGenitiveNames = "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec,".Split(comma); + this.abbreviatedMonthNames = "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec,".Split(comma); + this.amDesignator = "AM"; + this.calendarWeekRule = CalendarWeekRule.FirstDay; + this.dateSeparator = "/"; + this.dayNames = "Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday".Split(comma); + this.firstDayOfWeek = DayOfWeek.Sunday; + this.fullDateTimePattern = "dddd, dd MMMM yyyy HH:mm:ss"; + this.longDatePattern = "dddd, dd MMMM yyyy"; + this.longTimePattern = "HH:mm:ss"; + this.monthDayPattern = "MMMM dd"; + this.monthGenitiveNames = "January,February,March,April,May,June,July,August,September,October,November,December,".Split(comma); + this.monthNames = "January,February,March,April,May,June,July,August,September,October,November,December,".Split(comma); + this.nativeCalendarName = "Gregorian Calendar"; + this.pmDesignator = "PM"; + this.rfc1123Pattern = "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'"; + this.shortDatePattern = "MM/dd/yyyy"; + this.shortestDayNames = "Su,Mo,Tu,We,Th,Fr,Sa".Split(comma); + this.shortTimePattern = "HH:mm"; + this.sortableDateTimePattern = "yyyy'-'MM'-'dd'T'HH':'mm':'ss"; + this.timeSeparator = ":"; + this.universalSortableDateTimePattern = "yyyy'-'MM'-'dd HH':'mm':'ss'Z'"; + this.yearMonthPattern = "yyyy MMMM"; + this.calendar = new GregorianCalendar(); + } + + public bool IsReadOnly { get { return this.isReadOnly; } } + public string[] AbbreviatedDayNames { get { return this.abbreviatedDayNames; } } + public string[] AbbreviatedMonthGenitiveNames { get { return this.abbreviatedMonthGenitiveNames; } } + public string[] AbbreviatedMonthNames { get { return this.abbreviatedMonthNames; } } + public string AMDesignator { get { return this.amDesignator; } } + public CalendarWeekRule CalendarWeekRule { get { return this.calendarWeekRule; } } + public string DateSeparator { get { return this.dateSeparator; } } + public string[] DayNames { get { return this.dayNames; } } + public DayOfWeek FirstDayOfWeek { get { return this.firstDayOfWeek; } } + public string FullDateTimePattern { get { return this.fullDateTimePattern; } } + public string LongDatePattern { get { return this.longDatePattern; } } + public string LongTimePattern { get { return this.longTimePattern; } } + public string MonthDayPattern { get { return this.monthDayPattern; } } + public string[] MonthGenitiveNames { get { return this.monthGenitiveNames; } } + public string[] MonthNames { get { return this.monthNames; } } + public string NativeCalendarName { get { return this.nativeCalendarName; } } + public string PMDesignator { get { return this.pmDesignator; } } + public string RFC1123Pattern { get { return this.rfc1123Pattern; } } + public string ShortDatePattern { get { return this.shortDatePattern; } } + public string[] ShortestDayNames { get { return this.shortestDayNames; } } + public string ShortTimePattern { get { return this.shortTimePattern; } } + public string SortableDateTimePattern { get { return this.sortableDateTimePattern; } } + public string TimeSeparator { get { return this.timeSeparator; } } + public string UniversalSortableDateTimePattern { get { return this.universalSortableDateTimePattern; } } + public string YearMonthPattern { get { return this.yearMonthPattern; } } + public Calendar Calendar { get { return this.calendar; } } + + public string GetAbbreviatedDayName(DayOfWeek dow) { + return this.abbreviatedDayNames[(int)dow]; + } + + public string GetAbbreviatedMonthName(int m) { + return this.abbreviatedMonthNames[m]; + } + + public string GetDayName(DayOfWeek dow) { + return this.dayNames[(int)dow]; + } + + public string GetEraName(int era) { + return this.calendar.eraNames[era - 1]; + } + + public string GetMonthName(int m) { + return this.monthNames[m]; + } + } +} + +#endif diff --git a/corlib/System.Globalization/DigitShapes.cs b/corlib/System.Globalization/DigitShapes.cs new file mode 100644 index 0000000..1b3b304 --- /dev/null +++ b/corlib/System.Globalization/DigitShapes.cs @@ -0,0 +1,11 @@ +#if !LOCALTEST + +namespace System.Globalization { + public enum DigitShapes { + Context = 0, + None = 1, + NativeNational = 2 + } +} + +#endif diff --git a/corlib/System.Globalization/GregorianCalendar.cs b/corlib/System.Globalization/GregorianCalendar.cs new file mode 100644 index 0000000..437d37d --- /dev/null +++ b/corlib/System.Globalization/GregorianCalendar.cs @@ -0,0 +1,51 @@ +#if !LOCALTEST + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Globalization { + public class GregorianCalendar : Calendar { + + public const int ADEra = 1; + + private GregorianCalendarTypes type; + + public GregorianCalendar() : this(GregorianCalendarTypes.Localized) { } + + public GregorianCalendar(GregorianCalendarTypes type) { + base.eraNames = new string[] { "A.D." }; + base.eraAbbrNames = new string[] { "AD" }; + this.type = type; + } + + public override int[] Eras { + get { + return new int[] { ADEra }; + } + } + + public override int GetEra(DateTime dt) { + return ADEra; + } + + public override DayOfWeek GetDayOfWeek(DateTime time) { + int rd = CCFixed.FromDateTime(time); + return (DayOfWeek)CCFixed.day_of_week(rd); + } + + public override int GetDayOfMonth(DateTime time) { + return CCGregorianCalendar.GetDayOfMonth(time); + } + + public override int GetMonth(DateTime time) { + return CCGregorianCalendar.GetMonth(time); + } + + public override int GetYear(DateTime time) { + return CCGregorianCalendar.GetYear(time); + } + } +} + +#endif diff --git a/corlib/System.Globalization/GregorianCalendarTypes.cs b/corlib/System.Globalization/GregorianCalendarTypes.cs new file mode 100644 index 0000000..bd2c968 --- /dev/null +++ b/corlib/System.Globalization/GregorianCalendarTypes.cs @@ -0,0 +1,18 @@ +#if !LOCALTEST + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Globalization { + public enum GregorianCalendarTypes { + Localized = 1, + USEnglish = 2, + MiddleEastFrench = 9, + Arabic = 10, + TransliteratedEnglish = 11, + TransliteratedFrench = 12, + } +} + +#endif diff --git a/corlib/System.Globalization/NumberFormatInfo.cs b/corlib/System.Globalization/NumberFormatInfo.cs new file mode 100644 index 0000000..becf570 --- /dev/null +++ b/corlib/System.Globalization/NumberFormatInfo.cs @@ -0,0 +1,183 @@ +#if !LOCALTEST + +using System.Threading; +using System.IO; +namespace System.Globalization { + public class NumberFormatInfo : IFormatProvider { + + #region Static Methods/Properties + + private static string[] defaultNativeDigits = new string[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + + public static NumberFormatInfo CurrentInfo { + get { + NumberFormatInfo nfi = Thread.CurrentThread.CurrentCulture.NumberFormat; + return nfi; + } + } + + public static NumberFormatInfo InvariantInfo { + get { + NumberFormatInfo nfi = new NumberFormatInfo(); + nfi.isReadOnly = true; + return nfi; + } + } + + public static NumberFormatInfo GetInstance(IFormatProvider provider) { + if (provider != null) { + NumberFormatInfo nfi; + nfi = (NumberFormatInfo)provider.GetFormat(typeof(NumberFormatInfo)); + if (nfi != null) { + return nfi; + } + } + + return CurrentInfo; + } + + #endregion + + private bool isReadOnly; + private int currencyDecimalDigits; + private string currencyDecimalSeparator; + private string currencyGroupSeparator; + private int[] currencyGroupSizes; + private int currencyNegativePattern; + private int currencyPositivePattern; + private string currencySymbol; + private DigitShapes digitSubstitution; + private string naNSymbol; + private string[] nativeDigits; + private string negativeInfinitySymbol; + private string negativeSign; + private int numberDecimalDigits; + private string numberDecimalSeparator; + private string numberGroupSeparator; + private int[] numberGroupSizes; + private int numberNegativePattern; + private int percentDecimalDigits; + private string percentDecimalSeparator; + private string percentGroupSeparator; + private int[] percentGroupSizes; + private int percentNegativePattern; + private int percentPositivePattern; + private string percentSymbol; + private string perMilleSymbol; + private string positiveInfinitySymbol; + private string positiveSign; + + private static int[] ConvertToIntArray(string s) { + string[] list = s.Split(','); + int listLen = list.Length; + int[] ret = new int[listLen]; + for (int i = 0; i < listLen; i++) { + ret[i] = int.Parse(list[i]); + } + return ret; + } + + internal NumberFormatInfo(StreamReader s) { + this.isReadOnly = true; + // Sets up information from stream + this.currencyDecimalDigits = int.Parse(s.ReadLine()); + this.currencyDecimalSeparator = s.ReadLine(); + this.currencyGroupSeparator = s.ReadLine(); + this.currencyGroupSizes = ConvertToIntArray(s.ReadLine()); + this.currencyNegativePattern = int.Parse(s.ReadLine()); + this.currencyPositivePattern = int.Parse(s.ReadLine()); + this.currencySymbol = s.ReadLine(); + this.digitSubstitution = (DigitShapes)int.Parse(s.ReadLine()); + this.naNSymbol = s.ReadLine(); + this.nativeDigits = s.ReadLine().Split(','); + this.negativeInfinitySymbol = s.ReadLine(); + this.negativeSign = s.ReadLine(); + this.numberDecimalDigits = int.Parse(s.ReadLine()); + this.numberDecimalSeparator = s.ReadLine(); + this.numberGroupSeparator = s.ReadLine(); + this.numberGroupSizes = ConvertToIntArray(s.ReadLine()); + this.numberNegativePattern = int.Parse(s.ReadLine()); + this.percentDecimalDigits = int.Parse(s.ReadLine()); + this.percentDecimalSeparator = s.ReadLine(); + this.percentGroupSeparator = s.ReadLine(); + this.percentGroupSizes = ConvertToIntArray(s.ReadLine()); + this.percentNegativePattern = int.Parse(s.ReadLine()); + this.percentPositivePattern = int.Parse(s.ReadLine()); + this.percentSymbol = s.ReadLine(); + this.perMilleSymbol = s.ReadLine(); + this.positiveInfinitySymbol = s.ReadLine(); + this.positiveSign = s.ReadLine(); + } + + public NumberFormatInfo() { + this.isReadOnly = true; + // Set up defaults for invariant culture + this.currencyDecimalDigits = 2; + this.currencyDecimalSeparator = "."; + this.currencyGroupSeparator = ","; + this.currencyGroupSizes = new int[] { 3 }; + this.currencyNegativePattern = 0; + this.currencyPositivePattern = 0; + this.currencySymbol = "$"; + this.digitSubstitution = DigitShapes.None; + this.naNSymbol = "NaN"; + this.nativeDigits = defaultNativeDigits; + this.negativeInfinitySymbol = "-Infinity"; + this.negativeSign = "-"; + this.numberDecimalDigits = 2; + this.numberDecimalSeparator = "."; + this.numberGroupSeparator = ","; + this.numberGroupSizes = new int[] { 3 }; + this.numberNegativePattern = 1; + this.percentDecimalDigits = 2; + this.percentDecimalSeparator = "."; + this.percentGroupSeparator = ","; + this.percentGroupSizes = new int[] { 3 }; + this.percentNegativePattern = 0; + this.percentPositivePattern = 0; + this.percentSymbol = "%"; + this.perMilleSymbol = "\x2030"; + this.positiveInfinitySymbol = "Infinity"; + this.positiveSign = "+"; + } + + public bool IsReadOnly { get { return this.isReadOnly; } } + public int CurrencyDecimalDigits { get { return this.currencyDecimalDigits; } } + public string CurrencyDecimalSeparator { get { return this.currencyDecimalSeparator; } } + public string CurrencyGroupSeparator { get { return this.currencyGroupSeparator; } } + public int[] CurrencyGroupSizes { get { return this.currencyGroupSizes; } } + public int CurrencyNegativePattern { get { return this.currencyNegativePattern; } } + public int CurrencyPositivePattern { get { return this.currencyPositivePattern; } } + public string CurrencySymbol { get { return this.currencySymbol; } } + public DigitShapes DigitSubstitution { get { return this.digitSubstitution; } } + public string NaNSymbol { get { return this.naNSymbol; } } + public string[] NativeDigits { get { return this.nativeDigits; } } + public string NegativeInfinitySymbol { get { return this.negativeInfinitySymbol; } } + public string NegativeSign { get { return this.negativeSign; } } + public int NumberDecimalDigits { get { return this.numberDecimalDigits; } } + public string NumberDecimalSeparator { get { return this.numberDecimalSeparator; } } + public string NumberGroupSeparator { get { return this.numberGroupSeparator; } } + public int[] NumberGroupSizes { get { return this.numberGroupSizes; } } + public int NumberNegativePattern { get { return this.numberNegativePattern; } } + public int PercentDecimalDigits { get { return this.percentDecimalDigits; } } + public string PercentDecimalSeparator { get { return this.percentDecimalSeparator; } } + public string PercentGroupSeparator { get { return this.percentGroupSeparator; } } + public int[] PercentGroupSizes { get { return this.percentGroupSizes; } } + public int PercentNegativePattern { get { return this.percentNegativePattern; } } + public int PercentPositivePattern { get { return this.percentPositivePattern; } } + public string PercentSymbol { get { return this.percentSymbol; } } + public string PerMilleSymbol { get { return this.perMilleSymbol; } } + public string PositiveInfinitySymbol { get { return this.positiveInfinitySymbol; } } + public string PositiveSign { get { return this.positiveSign; } } + + #region IFormatProvider Members + + public object GetFormat(Type formatType) { + throw new Exception("The method or operation is not implemented."); + } + + #endregion + } +} + +#endif diff --git a/corlib/System.Globalization/NumberStyles.cs b/corlib/System.Globalization/NumberStyles.cs new file mode 100644 index 0000000..d7fa158 --- /dev/null +++ b/corlib/System.Globalization/NumberStyles.cs @@ -0,0 +1,32 @@ +#if !LOCALTEST + +namespace System.Globalization { + public enum NumberStyles { + None = 0x00000000, + AllowLeadingWhite = 0x00000001, + AllowTrailingWhite = 0x00000002, + AllowLeadingSign = 0x00000004, + AllowTrailingSign = 0x00000008, + AllowParentheses = 0x00000010, + AllowDecimalPoint = 0x00000020, + AllowThousands = 0x00000040, + AllowExponent = 0x00000080, + AllowCurrencySymbol = 0x00000100, + AllowHexSpecifier = 0x00000200, + + Integer = (AllowLeadingWhite | AllowTrailingWhite | AllowLeadingSign), + HexNumber = (AllowLeadingWhite | AllowTrailingWhite | AllowHexSpecifier), + Number = (AllowLeadingWhite | AllowTrailingWhite | AllowLeadingSign | + AllowTrailingSign | AllowDecimalPoint | AllowThousands), + Float = (AllowLeadingWhite | AllowTrailingWhite | AllowLeadingSign | + AllowDecimalPoint | AllowExponent), + Currency = (AllowLeadingWhite | AllowTrailingWhite | AllowLeadingSign | + AllowTrailingSign | AllowParentheses | AllowDecimalPoint | + AllowThousands | AllowCurrencySymbol), + Any = (AllowLeadingWhite | AllowTrailingWhite | AllowLeadingSign | + AllowTrailingSign | AllowParentheses | AllowDecimalPoint | + AllowThousands | AllowExponent | AllowCurrencySymbol), + } +} + +#endif diff --git a/corlib/System.Globalization/TextInfo.cs b/corlib/System.Globalization/TextInfo.cs new file mode 100644 index 0000000..871ddf9 --- /dev/null +++ b/corlib/System.Globalization/TextInfo.cs @@ -0,0 +1,177 @@ +#if !LOCALTEST + +using System.Text; +using System.IO; +namespace System.Globalization { + public class TextInfo { + + private int ansiCodePage; + private int ebcdicCodePage; + private bool isRightToLeft; + private string listSeparator; + private int macCodePage; + private int oemCodePage; + private CultureInfo ci; + + internal TextInfo(CultureInfo ci, StreamReader s) { + this.ansiCodePage = int.Parse(s.ReadLine()); + this.ebcdicCodePage = int.Parse(s.ReadLine()); + this.isRightToLeft = bool.Parse(s.ReadLine()); + this.listSeparator = s.ReadLine(); + this.macCodePage = int.Parse(s.ReadLine()); + this.oemCodePage = int.Parse(s.ReadLine()); + this.ci = ci; + } + + public virtual int ANSICodePage { + get { + return this.ansiCodePage; + } + } + + public string CultureName { + get { + return this.ci.Name; + } + } + + public int EBCDICCodePage { + get { + return this.ebcdicCodePage; + } + } + + public bool IsReadOnly { + get { + return true; + } + } + + public bool IsRightToLeft { + get { + return this.isRightToLeft; + } + } + + public int LCID { + get { + return this.ci.LCID; + } + } + + public string ListSeparator { + get { + return this.listSeparator; + } + } + + public int MacCodePage { + get { + return this.macCodePage; + } + } + + public int OEMCodePage { + get { + return this.oemCodePage; + } + } + + public char ToLower(char c) { + // For the moment, ignore culture + return char.ToLowerInvariant(c); + } + + public string ToLower(string s) { + // For the moment, ignore culture + return s.ToLowerInvariant(); + } + + public char ToUpper(char c) { + // For the moment, ignore culture + return char.ToUpperInvariant(c); + } + + public string ToUpper(string s) { + // For the moment, ignore culture + return s.ToUpperInvariant(); + } + + public string ToTitleCase(string str) { + if (str == null) { + throw new ArgumentNullException("str"); + } + + StringBuilder sb = null; + int i = 0; + int start = 0; + while (i < str.Length) { + if (!char.IsLetter(str[i++])) { + continue; + } + i--; + char t = ToUpper(str[i]); + bool capitalize = true; + if (t == str[i]) { + capitalize = false; + bool allTitle = true; + // if the word is all titlecase, + // then don't capitalize it. + int saved = i; + while (++i < str.Length) { + if (char.IsWhiteSpace(str[i])) { + break; + } + t = ToUpper(str[i]); + if (t != str[i]) { + allTitle = false; + break; + } + } + if (allTitle) { + continue; + } + i = saved; + + // still check if all remaining + // characters are lowercase, + // where we don't have to modify + // the source word. + while (++i < str.Length) { + if (char.IsWhiteSpace(str[i])) { + break; + } + if (ToLower(str[i]) != str[i]) { + capitalize = true; + i = saved; + break; + } + } + } + + if (capitalize) { + if (sb == null) { + sb = new StringBuilder(str.Length); + } + sb.Append(str, start, i - start); + sb.Append(ToUpper(str[i])); + start = i + 1; + while (++i < str.Length) { + if (char.IsWhiteSpace(str[i])) { + break; + } + sb.Append(ToLower(str[i])); + } + start = i; + } + } + if (sb != null) + sb.Append(str, start, str.Length - start); + + return sb != null ? sb.ToString() : str; + } + + } +} + +#endif diff --git a/corlib/System.Globalization/UnicodeCategory.cs b/corlib/System.Globalization/UnicodeCategory.cs new file mode 100644 index 0000000..1fdde0c --- /dev/null +++ b/corlib/System.Globalization/UnicodeCategory.cs @@ -0,0 +1,38 @@ +#if !LOCALTEST + +namespace System.Globalization { + public enum UnicodeCategory { + UppercaseLetter = 0, + LowercaseLetter = 1, + TitlecaseLetter = 2, + ModifierLetter = 3, + OtherLetter = 4, + NonSpacingMark = 5, + SpacingCombiningMark = 6, + EnclosingMark = 7, + DecimalDigitNumber = 8, + LetterNumber = 9, + OtherNumber = 10, + SpaceSeparator = 11, + LineSeparator = 12, + ParagraphSeparator = 13, + Control = 14, + Format = 15, + Surrogate = 16, + PrivateUse = 17, + ConnectorPunctuation = 18, + DashPunctuation = 19, + OpenPunctuation = 20, + ClosePunctuation = 21, + InitialQuotePunctuation = 22, + FinalQuotePunctuation = 23, + OtherPunctuation = 24, + MathSymbol = 25, + CurrencySymbol = 26, + ModifierSymbol = 27, + OtherSymbol = 28, + OtherNotAssigned = 29, + } +} + +#endif diff --git a/corlib/System.IO/CheckArgument.cs b/corlib/System.IO/CheckArgument.cs new file mode 100644 index 0000000..59259b0 --- /dev/null +++ b/corlib/System.IO/CheckArgument.cs @@ -0,0 +1,123 @@ +#if !LOCALTEST + +namespace System.IO { + internal static class CheckArgument { + /// + /// Generates and exception if arg contains whitepace only + /// + public static void WhitespaceOnly(string arg, string desc) { + if (arg != null && arg.Length > 0) { + string temp = arg.Trim(); + if (temp.Length == 0) { + throw new ArgumentException(desc); + } + } + } + + /// + /// Generates and exception if arg contains whitepace only + /// + public static void WhitespaceOnly(string arg) { + WhitespaceOnly(arg, "Argument string consists of whitespace characters only."); + } + + /// + /// Generates and exception if arg is empty + /// + public static void Empty(string arg, string desc) { + if (arg != null && arg.Length == 0) { + throw new ArgumentException(desc); + } + } + + /// + /// Generates and exception if arg is empty + /// + public static void Empty(string arg) { + Empty(arg, "Argument string is empty."); + } + + /// + /// Generates and exception if arg is null + /// + public static void Null(Object arg, string desc) { + if (arg == null) { + throw new ArgumentNullException(desc); + } + } + + /// + /// Generates and exception if arg is null + /// + public static void Null(Object arg) { + if (arg == null) { + throw new ArgumentNullException(); + } + } + + /// + /// Generates and exception if path contains invalid path characters + /// + public static void PathChars(string path, string desc) { + if (path != null) { + if (path.IndexOfAny(System.IO.Path.InvalidPathChars) > -1) { + throw new ArgumentException(desc); + } + } + } + + /// + /// Generates and exception if path contains invalid path characters + /// + public static void PathChars(string path) { + PathChars(path, "Path contains invalid characters"); + } + + /// + /// Generates and exception if path too long + /// + public static void PathLength(string path, string desc) { + //TODO: find out how long is too long + } + + /// + /// Generates and exception if path too long + /// + public static void PathLength(string path) { + PathLength(path, "Path is too long"); + } + + /// + /// Generates and exception if path is illegal + /// + public static void Path(string path, bool bAllowNull, bool bLength) { + if (path != null) //allow null + { + Empty(path, "Path cannot be the empty string"); // path can't be empty + WhitespaceOnly(path, "Path cannot be all whitespace"); // path can't be all whitespace + PathChars(path); // path can't contain invalid characters + if (bLength) { + PathLength("Path too long"); + } + } else if (!bAllowNull) { + throw new ArgumentNullException("Parameter name: path"); + } + } + + /// + /// Generates and exception if path is illegal + /// + public static void Path(string path, bool bAllowNull) { + Path(path, bAllowNull, false); + } + + /// + /// Generates and exception if path is illegal + /// + public static void Path(string path) { + Path(path, false, false); + } + } +} + +#endif diff --git a/corlib/System.IO/Directory.cs b/corlib/System.IO/Directory.cs new file mode 100644 index 0000000..1fa3d88 --- /dev/null +++ b/corlib/System.IO/Directory.cs @@ -0,0 +1,77 @@ +#if !LOCALTEST + +namespace System.IO { + public static class Directory { + + public static string GetCurrentDirectory() { + int error; + string dir = FileInternal.GetCurrentDirectory(out error); + if (error != 0) { + throw FileInternal.GetException(error, string.Empty); + } + return dir; + } + + public static string[] GetFiles(string path) { + return GetFiles(path, "*"); + } + + public static string[] GetFiles(string path, string pattern) { + return GetFileSystemEntries(path, pattern, FileAttributes.Directory, 0); + } + + private static string[] GetFileSystemEntries(string path, string pattern, FileAttributes mask, FileAttributes attrs) { + if (path == null || pattern == null) + throw new ArgumentNullException(); + + if (pattern == String.Empty) + return new string[] { }; + + if (path.Trim() == "") + throw new ArgumentException("The Path does not have a valid format"); + + string wild = Path.Combine(path, pattern); + string wildpath = Path.GetDirectoryName(wild); + if (wildpath.IndexOfAny(Path.InvalidPathChars) != -1) + throw new ArgumentException("Path contains invalid characters"); + + if (wildpath.IndexOfAny(Path.InvalidPathChars) != -1) { + if (path.IndexOfAny(SearchPattern.InvalidChars) == -1) + throw new ArgumentException("Path contains invalid characters", "path"); + + throw new ArgumentException("Pattern contains invalid characters", "pattern"); + } + + int error; + if (!FileInternal.ExistsDirectory(wildpath, out error)) { + if (error == FileInternal.Error_OK) { + int file_error; + if (FileInternal.ExistsFile(wildpath, out file_error)) { + return new string[] { wildpath }; + } + } + + if (error != FileInternal.ERROR_PATH_NOT_FOUND) + throw FileInternal.GetException(error, wildpath); + + if (wildpath.IndexOfAny(SearchPattern.WildcardChars) == -1) + throw new DirectoryNotFoundException("Directory '" + wildpath + "' not found."); + + if (path.IndexOfAny(SearchPattern.WildcardChars) == -1) + throw new ArgumentException("Pattern is invalid", "pattern"); + + throw new ArgumentException("Path is invalid", "path"); + } + + string path_with_pattern = Path.Combine(wildpath, pattern); + string[] result = FileInternal.GetFileSystemEntries(path, path_with_pattern, attrs, mask, out error); + if (error != 0) + throw FileInternal.GetException(error, wildpath); + + return result; + } + + } +} + +#endif diff --git a/corlib/System.IO/DirectoryInfo.cs b/corlib/System.IO/DirectoryInfo.cs new file mode 100644 index 0000000..5a63e0c --- /dev/null +++ b/corlib/System.IO/DirectoryInfo.cs @@ -0,0 +1,67 @@ +#if !LOCALTEST + +namespace System.IO { + public class DirectoryInfo : FileSystemInfo { + + private string current; + private string parent; + + public DirectoryInfo(string path) { + base.CheckPath(path); + + base.fullPath = Path.GetFullPath(path); + base.originalPath = path; + + int len = base.fullPath.Length - 1; + if ((len > 1) && (base.fullPath[len] == Path.DirectorySeparatorChar)) { + len--; + } + int last = base.fullPath.LastIndexOf(Path.DirectorySeparatorChar, len); + if ((last == -1) || ((last == 0) && (len == 0))) { + current = base.fullPath; + parent = null; + } else { + current = base.fullPath.Substring(last + 1, len - last); + if (last == 0 && !Environment.IsRunningOnWindows) { + parent = Path.DirectorySeparatorStr; + } else { + parent = base.fullPath.Substring(0, last); + } + // adjust for drives, i.e. a special case for windows + if (Environment.IsRunningOnWindows) { + if ((parent.Length == 2) && (parent[1] == ':') && Char.IsLetter(parent[0])) { + parent += Path.DirectorySeparatorChar; + } + } + } + } + + public override bool Exists { + get { throw new Exception("The method or operation is not implemented."); } + } + + public override string Name { + get { + return this.current; + } + } + + public FileInfo[] GetFiles() { + return GetFiles("*"); + } + + public FileInfo[] GetFiles(string pattern) { + string[] names = Directory.GetFiles(base.fullPath, pattern); + + FileInfo[] infos = new FileInfo[names.Length]; + int i = 0; + foreach (string name in names) { + infos[i++] = new FileInfo(name); + } + return infos; + } + + } +} + +#endif diff --git a/corlib/System.IO/DirectoryNotFoundException.cs b/corlib/System.IO/DirectoryNotFoundException.cs new file mode 100644 index 0000000..71c6033 --- /dev/null +++ b/corlib/System.IO/DirectoryNotFoundException.cs @@ -0,0 +1,12 @@ +#if !LOCALTEST + +namespace System.IO { + public class DirectoryNotFoundException : SystemException { + + public DirectoryNotFoundException() : base("Directory not found.") { } + public DirectoryNotFoundException(string msg) : base(msg) { } + + } +} + +#endif diff --git a/corlib/System.IO/File.cs b/corlib/System.IO/File.cs new file mode 100644 index 0000000..415b2dc --- /dev/null +++ b/corlib/System.IO/File.cs @@ -0,0 +1,25 @@ +#if !LOCALTEST + +namespace System.IO { + public static class File { + + public static FileStream OpenRead(string path) { + return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); + } + + public static StreamReader OpenText(string path) { + return new StreamReader(path); + } + + public static bool Exists(string path) { + if (string.IsNullOrEmpty(path)) { + return false; + } + int error; + return FileInternal.ExistsFile(path, out error); + } + + } +} + +#endif diff --git a/corlib/System.IO/FileAccess.cs b/corlib/System.IO/FileAccess.cs new file mode 100644 index 0000000..31f7d58 --- /dev/null +++ b/corlib/System.IO/FileAccess.cs @@ -0,0 +1,11 @@ +#if !LOCALTEST + +namespace System.IO { + public enum FileAccess : int { + Read = 1, + Write = 2, + ReadWrite = Read | Write, + } +} + +#endif diff --git a/corlib/System.IO/FileAttributes.cs b/corlib/System.IO/FileAttributes.cs new file mode 100644 index 0000000..d60760a --- /dev/null +++ b/corlib/System.IO/FileAttributes.cs @@ -0,0 +1,22 @@ +#if !LOCALTEST + +namespace System.IO { + public enum FileAttributes { + Archive = 0x00020, + Compressed = 0x00800, + Device = 0x00040, // Reserved for future use (NOT the w32 value). + Directory = 0x00010, + Encrypted = 0x04000, // NOT the w32 value + Hidden = 0x00002, + Normal = 0x00080, + NotContentIndexed = 0x02000, + Offline = 0x01000, + ReadOnly = 0x00001, + ReparsePoint = 0x00400, + SparseFile = 0x00200, + System = 0x00004, + Temporary = 0x00100 + } +} + +#endif diff --git a/corlib/System.IO/FileInfo.cs b/corlib/System.IO/FileInfo.cs new file mode 100644 index 0000000..2526fcc --- /dev/null +++ b/corlib/System.IO/FileInfo.cs @@ -0,0 +1,28 @@ +#if !LOCALTEST + +namespace System.IO { + public sealed class FileInfo : FileSystemInfo { + + private bool exists; + + public FileInfo(string path) { + CheckPath(path); + + base.originalPath = path; + base.fullPath = Path.GetFullPath(path); + } + + public override bool Exists { + get { throw new Exception("The method or operation is not implemented."); } + } + + public override string Name { + get { + return Path.GetFileName(base.fullPath); + } + } + + } +} + +#endif diff --git a/corlib/System.IO/FileInternal.cs b/corlib/System.IO/FileInternal.cs new file mode 100644 index 0000000..826649e --- /dev/null +++ b/corlib/System.IO/FileInternal.cs @@ -0,0 +1,71 @@ +#if !LOCALTEST + +using System.Runtime.CompilerServices; +namespace System.IO { + internal static class FileInternal { + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public static IntPtr Open(string fileName, FileMode mode, FileAccess access, FileShare share, out int error); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public static int Read(IntPtr handle, byte[] dst, int dstOfs, int count, out int error); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public static void Close(IntPtr handle, out int error); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public static string GetCurrentDirectory(out int error); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public static FileAttributes GetFileAttributes(string path, out int error); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public static string[] GetFileSystemEntries(string path, string pathPattern, FileAttributes attrs, FileAttributes mask, out int error); + + public const int Error_OK = 0; + public const int Error_UnknownMode = -1; + public const int ERROR_FILE_NOT_FOUND = 2; + public const int ERROR_PATH_NOT_FOUND = 3; + + public static Exception GetException(int error, string path) { + switch (error) { + case Error_UnknownMode: + return new IOException("Unknown file mode"); + case ERROR_FILE_NOT_FOUND: + return new FileNotFoundException(string.Format("Could not find file \"{0}\"", path)); + default: + return new IOException(); + } + } + + public static readonly FileAttributes InvalidFileAttributes = (FileAttributes)(-1); + + public static bool ExistsFile(string path, out int error) { + FileAttributes attrs = GetFileAttributes(path, out error); + if (attrs == InvalidFileAttributes) { + return false; + } + if ((attrs & FileAttributes.Directory) != 0) { + return false; + } + return true; + } + + public static bool ExistsDirectory(string path, out int error) { + FileAttributes attrs = GetFileAttributes(path, out error); + // Actually, we are looking for a directory, not a file + if (error == FileInternal.ERROR_FILE_NOT_FOUND) { + error = FileInternal.ERROR_PATH_NOT_FOUND; + } + if (attrs == InvalidFileAttributes) { + return false; + } + if ((attrs & FileAttributes.Directory) == 0) { + return false; + } + return true; + } + } +} + +#endif diff --git a/corlib/System.IO/FileMode.cs b/corlib/System.IO/FileMode.cs new file mode 100644 index 0000000..7f39843 --- /dev/null +++ b/corlib/System.IO/FileMode.cs @@ -0,0 +1,14 @@ +#if !LOCALTEST + +namespace System.IO { + public enum FileMode : int { + CreateNew = 1, + Create = 2, + Open = 3, + OpenOrCreate = 4, + Truncate = 5, + Append = 6, + } +} + +#endif diff --git a/corlib/System.IO/FileNotFoundException.cs b/corlib/System.IO/FileNotFoundException.cs new file mode 100644 index 0000000..d015d4e --- /dev/null +++ b/corlib/System.IO/FileNotFoundException.cs @@ -0,0 +1,11 @@ +#if !LOCALTEST + +namespace System.IO { + public class FileNotFoundException : IOException { + + public FileNotFoundException(string msg) : base(msg) { } + + } +} + +#endif diff --git a/corlib/System.IO/FileShare.cs b/corlib/System.IO/FileShare.cs new file mode 100644 index 0000000..8083bbc --- /dev/null +++ b/corlib/System.IO/FileShare.cs @@ -0,0 +1,14 @@ +#if !LOCALTEST + +namespace System.IO { + public enum FileShare : int { + None = 0, + Read = 1, + Write = 2, + ReadWrite = 3, + Delete = 4, + Inheritable = 16, + } +} + +#endif diff --git a/corlib/System.IO/FileStream.cs b/corlib/System.IO/FileStream.cs new file mode 100644 index 0000000..8f50acd --- /dev/null +++ b/corlib/System.IO/FileStream.cs @@ -0,0 +1,106 @@ +#if !LOCALTEST + +namespace System.IO { + public class FileStream : Stream { + + private IntPtr handle = IntPtr.Zero; + private string filename; + private bool canRead, canWrite, canSeek; + + public FileStream(string filename, FileMode mode, FileAccess access, FileShare share) { + int error; + IntPtr handle = FileInternal.Open(filename, mode, access, share, out error); + if (error != 0) { + throw FileInternal.GetException(error, filename); + } + this.handle = handle; + this.filename = filename; + + this.canRead = true; + this.canWrite = true; + this.canSeek = true; + } + + ~FileStream() { + this.Dispose(false); + } + + protected override void Dispose(bool disposing) { + if (this.handle != IntPtr.Zero) { + int error; + FileInternal.Close(this.handle, out error); + if (disposing && error != 0) { + // Throw exception on error, but not if this is being called from destructor + throw FileInternal.GetException(error, this.filename); + } + this.handle = IntPtr.Zero; + // TODO: GC.UnregisterForFinalize(this); + } + } + + public override void Flush() { + throw new Exception("The method or operation is not implemented."); + } + + public override int Read(byte[] buffer, int offset, int count) { + if (this.handle == IntPtr.Zero) { + throw new ObjectDisposedException("Stream has been closed"); + } + if (offset < 0 || count < 0 || offset + count > buffer.Length) { + throw new ArgumentOutOfRangeException(); + } + + int error; + int ret = FileInternal.Read(this.handle, buffer, offset, count, out error); + if (error != 0) { + throw FileInternal.GetException(error, this.filename); + } + return ret; + } + + public override long Seek(long offset, SeekOrigin origin) { + throw new Exception("The method or operation is not implemented."); + } + + public override void SetLength(long value) { + throw new Exception("The method or operation is not implemented."); + } + + public override void Write(byte[] buffer, int offset, int count) { + throw new Exception("The method or operation is not implemented."); + } + + public override bool CanRead { + get { + return this.canRead; + } + } + + public override bool CanSeek { + get { + return this.canSeek; + } + } + + public override bool CanWrite { + get { + return this.canWrite; + } + } + + public override long Length { + get { throw new Exception("The method or operation is not implemented."); } + } + + public override long Position { + get { + throw new Exception("The method or operation is not implemented."); + } + set { + throw new Exception("The method or operation is not implemented."); + } + } + } +} + +#endif \ No newline at end of file diff --git a/corlib/System.IO/FileSystemInfo.cs b/corlib/System.IO/FileSystemInfo.cs new file mode 100644 index 0000000..4460a2b --- /dev/null +++ b/corlib/System.IO/FileSystemInfo.cs @@ -0,0 +1,39 @@ +#if !LOCALTEST + +namespace System.IO { + public abstract class FileSystemInfo : MarshalByRefObject { + + protected string fullPath = null; + protected string originalPath = null; + + internal void CheckPath(string path) { + if (path == null) + throw new ArgumentNullException("path"); + + if (path.Length == 0) + throw new ArgumentException("path", "Empty path."); + + if (path.IndexOfAny(Path.InvalidPathChars) != -1) + throw new ArgumentException("path", "Invalid characters in path."); + } + + public abstract bool Exists { get; } + + public abstract string Name { get; } + + public virtual string FullName { + get { + return this.fullPath; + } + } + + public string Extension { + get { + return Path.GetExtension(Name); + } + } + + } +} + +#endif diff --git a/corlib/System.IO/IOException.cs b/corlib/System.IO/IOException.cs new file mode 100644 index 0000000..8628d00 --- /dev/null +++ b/corlib/System.IO/IOException.cs @@ -0,0 +1,12 @@ +#if !LOCALTEST + +namespace System.IO { + public class IOException : SystemException { + + public IOException() : base("I/O Error") { } + public IOException(string message) : base(message) { } + + } +} + +#endif diff --git a/corlib/System.IO/Path.cs b/corlib/System.IO/Path.cs new file mode 100644 index 0000000..4684f92 --- /dev/null +++ b/corlib/System.IO/Path.cs @@ -0,0 +1,693 @@ +#if !LOCALTEST + +namespace System.IO { + public static class Path { + + /* static Path() { + InvalidPathChars = GetInvalidPathChars(); + if (Environment.Platform == PlatformID.Unix) { + AltDirectorySeparatorChar = '/'; + DirectorySeparatorChar = '/'; + PathSeparator = ';'; + VolumeSeparatorChar = '/'; + } else { + AltDirectorySeparatorChar = '/'; + DirectorySeparatorChar = '\\'; + PathSeparator = ';'; + VolumeSeparatorChar = ':'; + } + DirectorySeparatorStr = DirectorySeparatorChar.ToString(); + dirEqualsVolume = (DirectorySeparatorChar == VolumeSeparatorChar); + } + + public static readonly char AltDirectorySeparatorChar; + public static readonly char DirectorySeparatorChar; + internal static readonly string DirectorySeparatorStr; + public static readonly char[] InvalidPathChars; + public static readonly char PathSeparator; + public static readonly char VolumeSeparatorChar; + private static bool dirEqualsVolume; + + public static char[] GetInvalidPathChars() { + // return a new array as we do not want anyone to be able to change the values + if (Environment.Platform == PlatformID.Unix) { + return new char[] { '\x00' }; + } else { + return new char[] { + '\x22', '\x3C', '\x3E', '\x7C', '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', + '\x08', '\x09', '\x0A', '\x0B', '\x0C', '\x0D', '\x0E', '\x0F', '\x10', '\x11', '\x12', + '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1A', '\x1B', '\x1C', '\x1D', + '\x1E', '\x1F' }; + } + } + + private static bool IsDsc(char c) { + return c == DirectorySeparatorChar || c == AltDirectorySeparatorChar; + } + + private static string WindowsDriveAdjustment(string path) { + // two special cases to consider when a drive is specified + if (path.Length < 2) { + return path; + } + if ((path[1] != ':') || !Char.IsLetter(path[0])) { + return path; + } + string current = Directory.GetCurrentDirectory(); + // first, only the drive is specified + if (path.Length == 2) { + // then if the current directory is on the same drive + if (current[0] == path[0]) { + path = current; // we return it + } else { + path += '\\'; + } + } else if ((path[2] != Path.DirectorySeparatorChar) && (path[2] != Path.AltDirectorySeparatorChar)) { + // second, the drive + a directory is specified *without* a separator between them (e.g. C:dir). + // If the current directory is on the specified drive... + if (current[0] == path[0]) { + // then specified directory is appended to the current drive directory + path = Path.Combine(current, path.Substring(2, path.Length - 2)); + } else { + // if not, then just pretend there was a separator (Path.Combine won't work in this case) + path = String.Concat(path.Substring(0, 2), DirectorySeparatorStr, path.Substring(2, path.Length - 2)); + } + } + return path; + } + + public static bool IsPathRooted(string path) { + if (path == null || path.Length == 0) { + return false; + } + if (path.IndexOfAny(InvalidPathChars) != -1) { + throw new ArgumentException("Illegal characters in path", "path"); + } + char c = path[0]; + return (c == DirectorySeparatorChar || + c == AltDirectorySeparatorChar || + (!dirEqualsVolume && path.Length > 1 && path[1] == VolumeSeparatorChar)); + } + + static string CanonicalizePath(string path) { + // STEP 1: Check for empty string + if (path == null) { + return path; + } + if (Environment.IsRunningOnWindows) { + path = path.Trim(); + } + if (path.Length == 0) { + return path; + } + // STEP 2: Check to see if this is only a root + string root = Path.GetPathRoot(path); + // it will return '\' for path '\', while it should return 'c:\' or so. + // Note: commenting this out makes the ened for the (target == 1...) check in step 5 + //if (root == path) return path; + + // STEP 3: split the directories, this gets rid of consecutative "/"'s + string[] dirs = path.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); + // STEP 4: Get rid of directories containing . and .. + int target = 0; + + for (int i = 0; i < dirs.Length; i++) { + if (dirs[i] == "." || (i != 0 && dirs[i].Length == 0)) { + continue; + } else if (dirs[i] == "..") { + if (target != 0) { + target--; + } + } else { + dirs[target++] = dirs[i]; + } + } + + // STEP 5: Combine everything. + if (target == 0 || (target == 1 && dirs[0] == "")) { + return root; + } else { + string ret = String.Join(DirectorySeparatorStr, dirs, 0, target); + if (Environment.IsRunningOnWindows) { + if (!SameRoot(root, ret)) { + ret = root + ret; + } + // In GetFullPath(), it is assured that here never comes UNC. So this must only applied to such path that starts with '\', without drive specification. + if (!IsDsc(path[0]) && SameRoot(root, path)) { + if (ret.Length <= 2 && !ret.EndsWith(DirectorySeparatorStr)) { // '\' after "c:" + ret += Path.DirectorySeparatorChar; + } + return ret; + } else { + string current = Directory.GetCurrentDirectory(); + if (current.Length > 1 && current[1] == Path.VolumeSeparatorChar) { + // DOS local file path + if (ret.Length == 0 || IsDsc(ret[0])) { + ret += '\\'; + } + return current.Substring(0, 2) + ret; + } else if (IsDsc(current[current.Length - 1]) && IsDsc(ret[0])) { + return current + ret.Substring(1); + } else { + return current + ret; + } + } + } + return ret; + } + } + + public static string GetFullPath(string path) { + if (path == null) { + throw new ArgumentNullException("path"); + } + if (path.Trim().Length == 0) { + string msg = "The specified path is not of a legal form (empty)."; + throw new ArgumentException(msg, "path"); + } + + // adjust for drives, i.e. a special case for windows + if (Environment.IsRunningOnWindows) { + path = WindowsDriveAdjustment(path); + } + // if the supplied path ends with a separator... + char end = path[path.Length - 1]; + + if (path.Length >= 2 && IsDsc(path[0]) && IsDsc(path[1])) { + if (path.Length == 2 || path.IndexOf(path[0], 2) < 0) { + throw new ArgumentException("UNC pass should be of the form \\\\server\\share."); + } + if (path[0] != DirectorySeparatorChar) { + path = path.Replace(AltDirectorySeparatorChar, DirectorySeparatorChar); + } + } else { + if (!IsPathRooted(path)) { + path = Directory.GetCurrentDirectory() + DirectorySeparatorStr + path; + } else if (DirectorySeparatorChar == '\\' && path.Length >= 2 && IsDsc(path[0]) && !IsDsc(path[1])) { // like `\abc\def' + string current = Directory.GetCurrentDirectory(); + if (current[1] == VolumeSeparatorChar) { + path = current.Substring(0, 2) + path; + } else { + path = current.Substring(0, current.IndexOf('\\', current.IndexOf("\\\\") + 1)); + } + } + path = CanonicalizePath(path); + } + + // if the original ended with a [Alt]DirectorySeparatorChar then ensure the full path also ends with one + if (IsDsc(end) && (path[path.Length - 1] != DirectorySeparatorChar)) { + path += DirectorySeparatorChar; + } + + return path; + }*/ + + public static readonly char[] InvalidPathChars; + public static readonly char AltDirectorySeparatorChar; + public static readonly char DirectorySeparatorChar; + public static readonly char PathSeparator; + internal static readonly string DirectorySeparatorStr; + public static readonly char VolumeSeparatorChar; + + private static readonly char[] PathSeparatorChars; + private static readonly bool dirEqualsVolume; + + // class methods + public static string ChangeExtension(string path, string extension) { + if (path == null) + return null; + + if (path.IndexOfAny(InvalidPathChars) != -1) + throw new ArgumentException("Illegal characters in path", "path"); + + int iExt = findExtension(path); + + if (extension == null) + return iExt < 0 ? path : path.Substring(0, iExt); + else if (extension == String.Empty) + return iExt < 0 ? path + '.' : path.Substring(0, iExt + 1); + + else if (path.Length != 0) { + if (extension.Length > 0 && extension[0] != '.') + extension = "." + extension; + } else + extension = String.Empty; + + if (iExt < 0) { + return path + extension; + } else if (iExt > 0) { + string temp = path.Substring(0, iExt); + return temp + extension; + } + + return extension; + } + + public static string Combine(string path1, string path2) { + if (path1 == null) + throw new ArgumentNullException("path1"); + + if (path2 == null) + throw new ArgumentNullException("path2"); + + if (path1 == String.Empty) + return path2; + + if (path2 == String.Empty) + return path1; + + if (path1.IndexOfAny(InvalidPathChars) != -1) + throw new ArgumentException("Illegal characters in path", "path1"); + + if (path2.IndexOfAny(InvalidPathChars) != -1) + throw new ArgumentException("Illegal characters in path", "path2"); + + //TODO???: UNC names + // LAMESPEC: MS says that if path1 is not empty and path2 is a full path + // it should throw ArgumentException + if (IsPathRooted(path2)) + return path2; + + char p1end = path1[path1.Length - 1]; + if (p1end != DirectorySeparatorChar && p1end != AltDirectorySeparatorChar && p1end != VolumeSeparatorChar) + return path1 + DirectorySeparatorChar + path2; + + return path1 + path2; + } + + public static string GetDirectoryName(string path) { + // LAMESPEC: For empty string MS docs say both + // return null AND throw exception. Seems .NET throws. + if (path == String.Empty) { + throw new ArgumentException(); + } + if (path == null || GetPathRoot(path) == path) { + return null; + } + CheckArgument.WhitespaceOnly(path); + CheckArgument.PathChars(path); + + int nLast = path.LastIndexOfAny(PathSeparatorChars); + if (nLast == 0) { + nLast++; + } + if (nLast > 0) { + string ret = path.Substring(0, nLast); + int l = ret.Length; + if (l >= 2 && ret[l - 1] == VolumeSeparatorChar) { + return ret + DirectorySeparatorChar; + } else { + return ret; + } + } + + return String.Empty; + } + + public static string GetExtension(string path) { + if (path == null) { + return null; + } + if (path.IndexOfAny(InvalidPathChars) != -1) { + throw new ArgumentException("Illegal characters in path", "path"); + } + int iExt = findExtension(path); + + if (iExt > -1) { + if (iExt < path.Length - 1) { + return path.Substring(iExt); + } + } + return string.Empty; + } + + public static string GetFileName(string path) { + if (path == null || path == String.Empty) { + return path; + } + if (path.IndexOfAny(InvalidPathChars) != -1) { + throw new ArgumentException("Illegal characters in path", "path"); + } + int nLast = path.LastIndexOfAny(PathSeparatorChars); + if (nLast >= 0) { + return path.Substring(nLast + 1); + } + return path; + } + + public static string GetFileNameWithoutExtension(string path) { + return ChangeExtension(GetFileName(path), null); + } + + public static string GetFullPath(string path) { + string fullpath = InsecureGetFullPath(path); + return fullpath; + } + + internal static string WindowsDriveAdjustment(string path) { + // two special cases to consider when a drive is specified + if (path.Length < 2) { + return path; + } + if ((path[1] != ':') || !Char.IsLetter(path[0])) { + return path; + } + string current = Directory.GetCurrentDirectory(); + // first, only the drive is specified + if (path.Length == 2) { + // then if the current directory is on the same drive + if (current[0] == path[0]) { + path = current; // we return it + } else { + path += '\\'; + } + } else if ((path[2] != Path.DirectorySeparatorChar) && (path[2] != Path.AltDirectorySeparatorChar)) { + // second, the drive + a directory is specified *without* a separator between them (e.g. C:dir). + // If the current directory is on the specified drive... + if (current[0] == path[0]) { + // then specified directory is appended to the current drive directory + path = Path.Combine(current, path.Substring(2, path.Length - 2)); + } else { + // if not, then just pretend there was a separator (Path.Combine won't work in this case) + path = String.Concat(path.Substring(0, 2), DirectorySeparatorStr, path.Substring(2, path.Length - 2)); + } + } + return path; + } + + // insecure - do not call directly + internal static string InsecureGetFullPath(string path) { + if (path == null) { + throw new ArgumentNullException("path"); + } + if (path.Trim().Length == 0) { + string msg = "The specified path is not of a legal form (empty)."; + throw new ArgumentException(msg, "path"); + } + + // adjust for drives, i.e. a special case for windows + if (Environment.IsRunningOnWindows) { + path = WindowsDriveAdjustment(path); + } + // if the supplied path ends with a separator... + char end = path[path.Length - 1]; + + if (path.Length >= 2 && + IsDsc(path[0]) && + IsDsc(path[1])) { + if (path.Length == 2 || path.IndexOf(path[0], 2) < 0) { + throw new ArgumentException("UNC pass should be of the form \\\\server\\share."); + } + if (path[0] != DirectorySeparatorChar) { + path = path.Replace(AltDirectorySeparatorChar, DirectorySeparatorChar); + } + } else { + if (!IsPathRooted(path)) { + path = Directory.GetCurrentDirectory() + DirectorySeparatorStr + path; + } else if (DirectorySeparatorChar == '\\' && + path.Length >= 2 && + IsDsc(path[0]) && + !IsDsc(path[1])) { // like `\abc\def' + string current = Directory.GetCurrentDirectory(); + if (current[1] == VolumeSeparatorChar) { + path = current.Substring(0, 2) + path; + } else { + path = current.Substring(0, current.IndexOf('\\', current.IndexOf("\\\\") + 1)); + } + } + path = CanonicalizePath(path); + } + + // if the original ended with a [Alt]DirectorySeparatorChar then ensure the full path also ends with one + if (IsDsc(end) && (path[path.Length - 1] != DirectorySeparatorChar)) { + path += DirectorySeparatorChar; + } + + return path; + } + + static bool IsDsc(char c) { + return c == DirectorySeparatorChar || c == AltDirectorySeparatorChar; + } + + public static string GetPathRoot(string path) { + if (path == null) + return null; + + if (path == String.Empty) + throw new ArgumentException("This specified path is invalid."); + + if (!IsPathRooted(path)) + return String.Empty; + + if (DirectorySeparatorChar == '/') { + // UNIX + return IsDsc(path[0]) ? DirectorySeparatorStr : String.Empty; + } else { + // Windows + int len = 2; + + if (path.Length == 1 && IsDsc(path[0])) + return DirectorySeparatorStr; + else if (path.Length < 2) + return String.Empty; + + if (IsDsc(path[0]) && IsDsc(path[1])) { + // UNC: \\server or \\server\share + // Get server + while (len < path.Length && !IsDsc(path[len])) len++; + + // Get share + if (len < path.Length) { + len++; + while (len < path.Length && !IsDsc(path[len])) len++; + } + + return DirectorySeparatorStr + + DirectorySeparatorStr + + path.Substring(2, len - 2).Replace(AltDirectorySeparatorChar, DirectorySeparatorChar); + } else if (IsDsc(path[0])) { + // path starts with '\' or '/' + return DirectorySeparatorStr; + } else if (path[1] == VolumeSeparatorChar) { + // C:\folder + if (path.Length >= 3 && (IsDsc(path[2]))) len++; + } else + return Directory.GetCurrentDirectory().Substring(0, 2);// + path.Substring (0, len); + return path.Substring(0, len); + } + } + + public static string GetTempFileName() { + throw new NotImplementedException(); + } + + /*public static string GetTempPath() { + string p = get_temp_path(); + if (p.Length > 0 && p[p.Length - 1] != DirectorySeparatorChar) + return p + DirectorySeparatorChar; + + return p; + } + + //private static extern string get_temp_path(); + */ + + public static bool HasExtension(string path) { + if (path == null || path.Trim() == String.Empty) + return false; + + int pos = findExtension(path); + return 0 <= pos && pos < path.Length - 1; + } + + public static bool IsPathRooted(string path) { + if (path == null || path.Length == 0) + return false; + + if (path.IndexOfAny(InvalidPathChars) != -1) + throw new ArgumentException("Illegal characters in path", "path"); + + char c = path[0]; + return (c == DirectorySeparatorChar || + c == AltDirectorySeparatorChar || + (!dirEqualsVolume && path.Length > 1 && path[1] == VolumeSeparatorChar)); + } + + public static char[] GetInvalidFileNameChars () + { + // return a new array as we do not want anyone to be able to change the values + if (Environment.IsRunningOnWindows) { + return new char [41] { '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', + '\x08', '\x09', '\x0A', '\x0B', '\x0C', '\x0D', '\x0E', '\x0F', '\x10', '\x11', '\x12', + '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1A', '\x1B', '\x1C', '\x1D', + '\x1E', '\x1F', '\x22', '\x3C', '\x3E', '\x7C', ':', '*', '?', '\\', '/' }; + } else { + return new char [2] { '\x00', '/' }; + } + } + + public static char[] GetInvalidPathChars () + { + // return a new array as we do not want anyone to be able to change the values + if (Environment.IsRunningOnWindows) { + return new char [36] { '\x22', '\x3C', '\x3E', '\x7C', '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', + '\x08', '\x09', '\x0A', '\x0B', '\x0C', '\x0D', '\x0E', '\x0F', '\x10', '\x11', '\x12', + '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1A', '\x1B', '\x1C', '\x1D', + '\x1E', '\x1F' }; + } else { + return new char [1] { '\x00' }; + } + } + + public static string GetRandomFileName () + { + throw new NotImplementedException(); + } + // private class methods + + private static int findExtension(string path) { + // method should return the index of the path extension + // start or -1 if no valid extension + if (path != null) { + int iLastDot = path.LastIndexOf('.'); + int iLastSep = path.LastIndexOfAny(PathSeparatorChars); + + if (iLastDot > iLastSep) + return iLastDot; + } + return -1; + } + + static Path() { + if (Environment.Platform == PlatformID.Unix) { + AltDirectorySeparatorChar = '/'; + DirectorySeparatorChar = '/'; + PathSeparator = ';'; + VolumeSeparatorChar = '/'; + } else { + AltDirectorySeparatorChar = '/'; + DirectorySeparatorChar = '\\'; + PathSeparator = ';'; + VolumeSeparatorChar = ':'; + } + + // this copy will be modifiable ("by design") + InvalidPathChars = GetInvalidPathChars (); + + // internal fields + DirectorySeparatorStr = DirectorySeparatorChar.ToString(); + PathSeparatorChars = new char[] { + DirectorySeparatorChar, + AltDirectorySeparatorChar, + VolumeSeparatorChar + }; + + dirEqualsVolume = (DirectorySeparatorChar == VolumeSeparatorChar); + } + + static bool SameRoot(string root, string path) { + // compare root - if enough details are available + if ((root.Length < 2) || (path.Length < 2)) + return false; + // same volume/drive + if (!root[0].Equals(path[0])) + return false; + // presence if the separator + if (path[1] != Path.VolumeSeparatorChar) + return false; + if ((root.Length > 2) && (path.Length > 2)) { + // but don't directory compare the directory separator + return (IsDsc(root[2]) && IsDsc(path[2])); + } + return true; + } + + static string CanonicalizePath(string path) { + // STEP 1: Check for empty string + if (path == null) + return path; + if (Environment.IsRunningOnWindows) + path = path.Trim(); + + if (path.Length == 0) + return path; + + // STEP 2: Check to see if this is only a root + string root = Path.GetPathRoot(path); + // it will return '\' for path '\', while it should return 'c:\' or so. + // Note: commenting this out makes the ened for the (target == 1...) check in step 5 + //if (root == path) return path; + + // STEP 3: split the directories, this gets rid of consecutative "/"'s + string[] dirs = path.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); + // STEP 4: Get rid of directories containing . and .. + int target = 0; + + for (int i = 0; i < dirs.Length; i++) { + if (dirs[i] == "." || (i != 0 && dirs[i].Length == 0)) + continue; + else if (dirs[i] == "..") { + if (target != 0) + target--; + } else + dirs[target++] = dirs[i]; + } + + // STEP 5: Combine everything. + if (target == 0 || (target == 1 && dirs[0] == "")) + return root; + else { + string ret = String.Join(DirectorySeparatorStr, dirs, 0, target); + if (Environment.IsRunningOnWindows) { + if (!SameRoot(root, ret)) + ret = root + ret; + // In GetFullPath(), it is assured that here never comes UNC. So this must only applied to such path that starts with '\', without drive specification. + if (!IsDsc(path[0]) && SameRoot(root, path)) { + if (ret.Length <= 2 && !ret.EndsWith(DirectorySeparatorStr)) // '\' after "c:" + ret += Path.DirectorySeparatorChar; + return ret; + } else { + string current = Directory.GetCurrentDirectory(); + if (current.Length > 1 && current[1] == Path.VolumeSeparatorChar) { + // DOS local file path + if (ret.Length == 0 || IsDsc(ret[0])) + ret += '\\'; + return current.Substring(0, 2) + ret; + } else if (IsDsc(current[current.Length - 1]) && IsDsc(ret[0])) + return current + ret.Substring(1); + else + return current + ret; + } + } + return ret; + } + } + + // required for FileIOPermission (and most proibably reusable elsewhere too) + // both path MUST be "full paths" + static internal bool IsPathSubsetOf(string subset, string path) { + if (subset.Length > path.Length) + return false; + + // check that everything up to the last separator match + int slast = subset.LastIndexOfAny(PathSeparatorChars); + if (String.Compare(subset, 0, path, 0, slast) != 0) + return false; + + slast++; + // then check if the last segment is identical + int plast = path.IndexOfAny(PathSeparatorChars, slast); + if (plast >= slast) { + return String.Compare(subset, slast, path, slast, path.Length - plast) == 0; + } + if (subset.Length != path.Length) + return false; + + return String.Compare(subset, slast, path, slast, subset.Length - slast) == 0; + } + + } +} + +#endif diff --git a/corlib/System.IO/SearchPattern.cs b/corlib/System.IO/SearchPattern.cs new file mode 100644 index 0000000..1b5a911 --- /dev/null +++ b/corlib/System.IO/SearchPattern.cs @@ -0,0 +1,12 @@ +#if !LOCALTEST + +namespace System.IO { + internal class SearchPattern { + + internal static readonly char[] WildcardChars = { '*', '?' }; + internal static readonly char[] InvalidChars = { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }; + + } +} + +#endif diff --git a/corlib/System.IO/SeekOrigin.cs b/corlib/System.IO/SeekOrigin.cs new file mode 100644 index 0000000..cf34ae1 --- /dev/null +++ b/corlib/System.IO/SeekOrigin.cs @@ -0,0 +1,11 @@ +#if !LOCALTEST + +namespace System.IO { + public enum SeekOrigin : int { + Begin = 0, + Current = 1, + End = 2, + } +} + +#endif diff --git a/corlib/System.IO/Stream.cs b/corlib/System.IO/Stream.cs new file mode 100644 index 0000000..b34821c --- /dev/null +++ b/corlib/System.IO/Stream.cs @@ -0,0 +1,85 @@ +#if !LOCALTEST + +using System.Runtime.InteropServices; +namespace System.IO { + public abstract class Stream : MarshalByRefObject, IDisposable { + + public static readonly Stream Null = new NullStream(); + + private class NullStream : Stream { + public override bool CanRead { get { return true; } } + public override bool CanSeek { get { return true; } } + public override bool CanWrite { get { return true; } } + public override long Length { get { return 0; } } + public override long Position { get { return 0; } set { } } + public override void Flush() { } + public override int Read(byte[] buffer, int offset, int count) { return 0; } + public override int ReadByte() { return -1; } + public override long Seek(long offset, SeekOrigin origin) { return 0; } + public override void Write(byte[] buffer, int offset, int count) { } + public override void WriteByte(byte value) { } + public override void SetLength(long value) { } + } + + protected Stream() { + } + + public abstract bool CanRead { get; } + public abstract bool CanSeek { get; } + public abstract bool CanWrite { get; } + public abstract long Length { get; } + public abstract long Position { get; set; } + + public virtual bool CanTimeout { + get { + return false; + } + } + + public void Dispose() { + Close(); + } + + void IDisposable.Dispose() { + Close(); + } + + public virtual void Close() { + Dispose(true); + } + + protected virtual void Dispose(bool disposing) { + // nothing. + } + + public abstract void Flush(); + + public abstract int Read([In, Out] byte[] buffer, int offset, int count); + + public virtual int ReadByte() { + byte[] buffer = new byte[1]; + + if (Read(buffer, 0, 1) == 1) + return buffer[0]; + + return -1; + } + + public abstract long Seek(long offset, SeekOrigin origin); + + public abstract void SetLength(long value); + + public abstract void Write(byte[] buffer, int offset, int count); + + public virtual void WriteByte(byte value) { + byte[] buffer = new byte[1]; + + buffer[0] = value; + + Write(buffer, 0, 1); + } + + } +} + +#endif diff --git a/corlib/System.IO/StreamReader.cs b/corlib/System.IO/StreamReader.cs new file mode 100644 index 0000000..4d80892 --- /dev/null +++ b/corlib/System.IO/StreamReader.cs @@ -0,0 +1,464 @@ +#if !LOCALTEST + +using System; +using System.Text; +using System.Runtime.InteropServices; + +namespace System.IO { + public class StreamReader : TextReader { + + const int DefaultBufferSize = 1024; + const int DefaultFileBufferSize = 4096; + const int MinimumBufferSize = 128; + + // + // The input buffer + // + byte[] input_buffer; + + // + // The decoded buffer from the above input buffer + // + char[] decoded_buffer; + + // + // Decoded bytes in decoded_buffer. + // + int decoded_count; + + // + // Current position in the decoded_buffer + // + int pos; + + // + // The buffer size that we are using + // + int buffer_size; + + int do_checks; + + Encoding encoding; + Decoder decoder; + + Stream base_stream; + bool mayBlock; + StringBuilder line_builder; + + private class NullStreamReader : StreamReader { + public override int Peek() { + return -1; + } + + public override int Read() { + return -1; + } + + public override int Read([In, Out] char[] buffer, int index, int count) { + return 0; + } + + public override string ReadLine() { + return null; + } + + public override string ReadToEnd() { + return String.Empty; + } + + public override Stream BaseStream { + get { return Stream.Null; } + } + + public override Encoding CurrentEncoding { + get { return Encoding.Unicode; } + } + } + + public new static readonly StreamReader Null = (StreamReader)(new NullStreamReader()); + + internal StreamReader() { } + + public StreamReader(Stream stream) + : this(stream, Encoding.UTF8Unmarked, true, DefaultBufferSize) { } + + public StreamReader(Stream stream, bool detect_encoding_from_bytemarks) + : this(stream, Encoding.UTF8Unmarked, detect_encoding_from_bytemarks, DefaultBufferSize) { } + + public StreamReader(Stream stream, Encoding encoding) + : this(stream, encoding, true, DefaultBufferSize) { } + + public StreamReader(Stream stream, Encoding encoding, bool detect_encoding_from_bytemarks) + : this(stream, encoding, detect_encoding_from_bytemarks, DefaultBufferSize) { } + + public StreamReader(Stream stream, Encoding encoding, bool detect_encoding_from_bytemarks, int buffer_size) { + Initialize(stream, encoding, detect_encoding_from_bytemarks, buffer_size); + } + + public StreamReader(string path) + : this(path, Encoding.UTF8Unmarked, true, DefaultFileBufferSize) { } + + public StreamReader(string path, bool detect_encoding_from_bytemarks) + : this(path, Encoding.UTF8Unmarked, detect_encoding_from_bytemarks, DefaultFileBufferSize) { } + + public StreamReader(string path, Encoding encoding) + : this(path, encoding, true, DefaultFileBufferSize) { } + + public StreamReader(string path, Encoding encoding, bool detect_encoding_from_bytemarks) + : this(path, encoding, detect_encoding_from_bytemarks, DefaultFileBufferSize) { } + + public StreamReader(string path, Encoding encoding, bool detect_encoding_from_bytemarks, int buffer_size) { + if (null == path) { + throw new ArgumentNullException("path"); + } + if (String.Empty == path) { + throw new ArgumentException("Empty path not allowed"); + } + if (path.IndexOfAny(Path.InvalidPathChars) != -1) { + throw new ArgumentException("path contains invalid characters"); + } + if (null == encoding) { + throw new ArgumentNullException("encoding"); + } + if (buffer_size <= 0) { + throw new ArgumentOutOfRangeException("buffer_size", "The minimum size of the buffer must be positive"); + } + + Stream stream = File.OpenRead(path); + Initialize(stream, encoding, detect_encoding_from_bytemarks, buffer_size); + } + + internal void Initialize(Stream stream, Encoding encoding, bool detect_encoding_from_bytemarks, int buffer_size) { + if (null == stream) { + throw new ArgumentNullException("stream"); + } + if (null == encoding) { + throw new ArgumentNullException("encoding"); + } + if (!stream.CanRead) { + throw new ArgumentException("Cannot read stream"); + } + if (buffer_size <= 0) { + throw new ArgumentOutOfRangeException("buffer_size", "The minimum size of the buffer must be positive"); + } + + if (buffer_size < MinimumBufferSize) { + buffer_size = MinimumBufferSize; + } + + base_stream = stream; + input_buffer = new byte[buffer_size]; + this.buffer_size = buffer_size; + this.encoding = encoding; + decoder = encoding.GetDecoder(); + + byte[] preamble = encoding.GetPreamble(); + do_checks = detect_encoding_from_bytemarks ? 1 : 0; + do_checks += (preamble.Length == 0) ? 0 : 2; + + decoded_buffer = new char[encoding.GetMaxCharCount(buffer_size)]; + decoded_count = 0; + pos = 0; + } + + public virtual Stream BaseStream { + get { + return base_stream; + } + } + + public virtual Encoding CurrentEncoding { + get { + if (encoding == null) { + throw new Exception(); + } + return encoding; + } + } + + + public bool EndOfStream { + get { return Peek() < 0; } + } + + public override void Close() { + Dispose(true); + } + + protected override void Dispose(bool disposing) { + if (disposing && base_stream != null) { + base_stream.Close(); + } + input_buffer = null; + decoded_buffer = null; + encoding = null; + decoder = null; + base_stream = null; + base.Dispose(disposing); + } + + // + // Provides auto-detection of the encoding, as well as skipping over + // byte marks at the beginning of a stream. + // + int DoChecks(int count) { + if ((do_checks & 2) == 2) { + byte[] preamble = encoding.GetPreamble(); + int c = preamble.Length; + if (count >= c) { + int i; + + for (i = 0; i < c; i++) { + if (input_buffer[i] != preamble[i]) { + break; + } + } + + if (i == c) { + return i; + } + } + } + + if ((do_checks & 1) == 1) { + if (count < 2) { + return 0; + } + + /*if (input_buffer[0] == 0xfe && input_buffer[1] == 0xff) { + this.encoding = Encoding.BigEndianUnicode; + return 2; + }*/ + + if (count < 3) { + return 0; + } + + if (input_buffer[0] == 0xef && input_buffer[1] == 0xbb && input_buffer[2] == 0xbf) { + this.encoding = Encoding.UTF8Unmarked; + return 3; + } + + if (count < 4) { + if (input_buffer[0] == 0xff && input_buffer[1] == 0xfe && input_buffer[2] != 0) { + this.encoding = Encoding.Unicode; + return 2; + } + return 0; + } + + /*if (input_buffer[0] == 0 && input_buffer[1] == 0 + && input_buffer[2] == 0xfe && input_buffer[3] == 0xff) { + this.encoding = Encoding.BigEndianUTF32; + return 4; + } + + if (input_buffer[0] == 0xff && input_buffer[1] == 0xfe) { + if (input_buffer[2] == 0 && input_buffer[3] == 0) { + this.encoding = Encoding.UTF32; + return 4; + } + + this.encoding = Encoding.Unicode; + return 2; + }*/ + } + + return 0; + } + + public void DiscardBufferedData() { + pos = decoded_count = 0; + mayBlock = false; + // Discard internal state of the decoder too. + decoder = encoding.GetDecoder(); + } + + // the buffer is empty, fill it again + private int ReadBuffer() { + pos = 0; + int cbEncoded = 0; + + // keep looping until the decoder gives us some chars + decoded_count = 0; + int parse_start = 0; + do { + cbEncoded = base_stream.Read(input_buffer, 0, buffer_size); + + if (cbEncoded <= 0) { + return 0; + } + + mayBlock = (cbEncoded < buffer_size); + if (do_checks > 0) { + Encoding old = encoding; + parse_start = DoChecks(cbEncoded); + if (old != encoding) { + decoder = encoding.GetDecoder(); + } + do_checks = 0; + cbEncoded -= parse_start; + } + + decoded_count += decoder.GetChars(input_buffer, parse_start, cbEncoded, decoded_buffer, 0); + parse_start = 0; + } while (decoded_count == 0); + + return decoded_count; + } + + public override int Peek() { + if (base_stream == null) { + throw new ObjectDisposedException("StreamReader", "Cannot read from a closed StreamReader"); + } + if (pos >= decoded_count && (mayBlock || ReadBuffer() == 0)) { + return -1; + } + + return decoded_buffer[pos]; + } + + public override int Read() { + if (base_stream == null) { + throw new ObjectDisposedException("StreamReader", "Cannot read from a closed StreamReader"); + } + if (pos >= decoded_count && ReadBuffer() == 0) { + return -1; + } + + return decoded_buffer[pos++]; + } + + public override int Read([In, Out] char[] dest_buffer, int index, int count) { + if (base_stream == null) { + throw new ObjectDisposedException("StreamReader", "Cannot read from a closed StreamReader"); + } + if (dest_buffer == null) { + throw new ArgumentNullException("dest_buffer"); + } + if (index < 0) { + throw new ArgumentOutOfRangeException("index", "< 0"); + } + if (count < 0) { + throw new ArgumentOutOfRangeException("count", "< 0"); + } + // re-ordered to avoid possible integer overflow + if (index > dest_buffer.Length - count) { + throw new ArgumentException("index + count > dest_buffer.Length"); + } + + int chars_read = 0; + while (count > 0) { + if (pos >= decoded_count && ReadBuffer() == 0) { + return chars_read > 0 ? chars_read : 0; + } + + int cch = Math.Min(decoded_count - pos, count); + Array.Copy(decoded_buffer, pos, dest_buffer, index, cch); + pos += cch; + index += cch; + count -= cch; + chars_read += cch; + if (mayBlock) { + break; + } + } + return chars_read; + } + + bool foundCR; + int FindNextEOL() { + char c = '\0'; + for (; pos < decoded_count; pos++) { + c = decoded_buffer[pos]; + if (c == '\n') { + pos++; + int res = (foundCR) ? (pos - 2) : (pos - 1); + if (res < 0) { + res = 0; // if a new buffer starts with a \n and there was a \r at + } + // the end of the previous one, we get here. + foundCR = false; + return res; + } else if (foundCR) { + foundCR = false; + return pos - 1; + } + + foundCR = (c == '\r'); + } + + return -1; + } + + public override string ReadLine() { + if (base_stream == null) { + throw new ObjectDisposedException("StreamReader", "Cannot read from a closed StreamReader"); + } + + if (pos >= decoded_count && ReadBuffer() == 0) { + return null; + } + + int begin = pos; + int end = FindNextEOL(); + if (end < decoded_count && end >= begin) { + return new string(decoded_buffer, begin, end - begin); + } + + if (line_builder == null) { + line_builder = new StringBuilder(); + } else { + line_builder.Length = 0; + } + + while (true) { + if (foundCR) { // don't include the trailing CR if present + decoded_count--; + } + + line_builder.Append(decoded_buffer, begin, decoded_count - begin); + if (ReadBuffer() == 0) { + if (line_builder.Capacity > 32768) { + StringBuilder sb = line_builder; + line_builder = null; + return sb.ToString(0, sb.Length); + } + return line_builder.ToString(0, line_builder.Length); + } + + begin = pos; + end = FindNextEOL(); + if (end < decoded_count && end >= begin) { + line_builder.Append(decoded_buffer, begin, end - begin); + if (line_builder.Capacity > 32768) { + StringBuilder sb = line_builder; + line_builder = null; + return sb.ToString(0, sb.Length); + } + return line_builder.ToString(0, line_builder.Length); + } + } + } + + public override string ReadToEnd() { + if (base_stream == null) { + throw new ObjectDisposedException("StreamReader", "Cannot read from a closed StreamReader"); + } + + StringBuilder text = new StringBuilder(); + + int size = decoded_buffer.Length; + char[] buffer = new char[size]; + int len; + + while ((len = Read(buffer, 0, size)) > 0) { + text.Append(buffer, 0, len); + } + + return text.ToString(); + } + } +} + +#endif diff --git a/corlib/System.IO/TextReader.cs b/corlib/System.IO/TextReader.cs new file mode 100644 index 0000000..07efe04 --- /dev/null +++ b/corlib/System.IO/TextReader.cs @@ -0,0 +1,135 @@ +#if !LOCALTEST + +using System; +using System.Runtime.InteropServices; + +namespace System.IO { + + public abstract class TextReader : MarshalByRefObject, IDisposable { + + protected TextReader() { } + + public static readonly TextReader Null; + + public virtual void Close() { + Dispose(true); + } + + public void Dispose () + { + Dispose(true); + } + + protected virtual void Dispose(bool disposing) { + return; + } + + public virtual int Peek() { + return -1; + } + + public virtual int Read() { + return -1; + } + + + public virtual int Read([In, Out] char[] buffer, int index, int count) { + int c, i; + + for (i = 0; i < count; i++) { + if ((c = Read()) == -1) + return i; + buffer[index + i] = (char)c; + } + + return i; + } + + public virtual int ReadBlock([In, Out] char[] buffer, int index, int count) { + int total_read_count = 0; + int current_read_count = 0; + + do { + current_read_count = Read(buffer, index, count); + index += current_read_count; + total_read_count += current_read_count; + count -= current_read_count; + } while (current_read_count != 0 && count > 0); + + return total_read_count; + } + + public virtual string ReadLine() { + return String.Empty; + } + + public virtual string ReadToEnd() { + return String.Empty; + } + + public static TextReader Synchronized(TextReader reader) { + if (reader == null) + throw new ArgumentNullException("reader is null"); + if (reader is SynchronizedReader) + return reader; + + return new SynchronizedReader(reader); + } + } + + // + // Synchronized Reader implementation, used internally. + // + internal class SynchronizedReader : TextReader { + TextReader reader; + + public SynchronizedReader(TextReader reader) { + this.reader = reader; + } + + public override void Close() { + lock (this) { + reader.Close(); + } + } + + public override int Peek() { + lock (this) { + return reader.Peek(); + } + } + + public override int ReadBlock(char[] buffer, int index, int count) { + lock (this) { + return reader.ReadBlock(buffer, index, count); + } + } + + public override string ReadLine() { + lock (this) { + return reader.ReadLine(); + } + } + + public override string ReadToEnd() { + lock (this) { + return reader.ReadToEnd(); + } + } + + public override int Read() { + lock (this) { + return reader.Read(); + } + } + + public override int Read(char[] buffer, int index, int count) { + lock (this) { + return reader.Read(buffer, index, count); + } + } + + } +} + +#endif \ No newline at end of file diff --git a/corlib/System.Reflection/DefaultMemberAttribute.cs b/corlib/System.Reflection/DefaultMemberAttribute.cs new file mode 100644 index 0000000..041ea57 --- /dev/null +++ b/corlib/System.Reflection/DefaultMemberAttribute.cs @@ -0,0 +1,24 @@ +#if !LOCALTEST + +using System; + +namespace System.Reflection { + + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface)] + public sealed class DefaultMemberAttribute : Attribute { + + private string memberName; + + public DefaultMemberAttribute(string memberName) { + this.memberName = memberName; + } + + public string MemberName { + get { + return this.memberName; + } + } + } +} + +#endif diff --git a/corlib/System.Reflection/MemberInfo.cs b/corlib/System.Reflection/MemberInfo.cs new file mode 100644 index 0000000..aff0caf --- /dev/null +++ b/corlib/System.Reflection/MemberInfo.cs @@ -0,0 +1,18 @@ +#if !LOCALTEST + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Reflection { + public abstract class MemberInfo { + + protected MemberInfo() { + } + + public abstract string Name { get;} + + } +} + +#endif diff --git a/corlib/System.Runtime.CompilerServices/IndexerNameAttribute.cs b/corlib/System.Runtime.CompilerServices/IndexerNameAttribute.cs new file mode 100644 index 0000000..e57faa1 --- /dev/null +++ b/corlib/System.Runtime.CompilerServices/IndexerNameAttribute.cs @@ -0,0 +1,15 @@ +#if !LOCALTEST + +using System; + +namespace System.Runtime.CompilerServices { + + [AttributeUsage(AttributeTargets.Property, Inherited = true)] + public sealed class IndexerNameAttribute : Attribute { + + public IndexerNameAttribute(string indexName) { + } + + } +} +#endif diff --git a/corlib/System.Runtime.CompilerServices/MethodImplAttribute.cs b/corlib/System.Runtime.CompilerServices/MethodImplAttribute.cs new file mode 100644 index 0000000..3c2225a --- /dev/null +++ b/corlib/System.Runtime.CompilerServices/MethodImplAttribute.cs @@ -0,0 +1,28 @@ +#if !LOCALTEST + +using System; + +namespace System.Runtime.CompilerServices { + + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor, Inherited = false)] + public sealed class MethodImplAttribute : Attribute { + + private MethodImplOptions options; + + public MethodImplAttribute() { + } + + public MethodImplAttribute(MethodImplOptions options) { + this.options = options; + } + + public MethodImplOptions Value { + get { + return options; + } + } + + } +} + +#endif diff --git a/corlib/System.Runtime.CompilerServices/MethodImplOptions.cs b/corlib/System.Runtime.CompilerServices/MethodImplOptions.cs new file mode 100644 index 0000000..c0e2e3f --- /dev/null +++ b/corlib/System.Runtime.CompilerServices/MethodImplOptions.cs @@ -0,0 +1,17 @@ +#if !LOCALTEST + +using System; + +namespace System.Runtime.CompilerServices { + [Flags] + public enum MethodImplOptions { + Unmanaged = 0x0004, + ForwardRef = 0x0010, + InternalCall = 0x1000, + Synchronized = 0x0020, + NoInlining = 0x0008, + PreserveSig = 0x0080, + } +} + +#endif diff --git a/corlib/System.Runtime.CompilerServices/RuntimeHelpers.cs b/corlib/System.Runtime.CompilerServices/RuntimeHelpers.cs new file mode 100644 index 0000000..e90ab0d --- /dev/null +++ b/corlib/System.Runtime.CompilerServices/RuntimeHelpers.cs @@ -0,0 +1,13 @@ +#if !LOCALTEST + +using System; + +namespace System.Runtime.CompilerServices { + public static class RuntimeHelpers { + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + extern public static void InitializeArray(Array array, RuntimeFieldHandle fldHandle); + + } +} +#endif diff --git a/corlib/System.Runtime.InteropServices/CallingConvention.cs b/corlib/System.Runtime.InteropServices/CallingConvention.cs new file mode 100644 index 0000000..1568f14 --- /dev/null +++ b/corlib/System.Runtime.InteropServices/CallingConvention.cs @@ -0,0 +1,13 @@ +#if !LOCALTEST + +namespace System.Runtime.InteropServices { + public enum CallingConvention { + Winapi = 1, + Cdecl = 2, + StdCall = 3, + ThisCall = 4, + FastCall = 5, + } +} + +#endif diff --git a/corlib/System.Runtime.InteropServices/CharSet.cs b/corlib/System.Runtime.InteropServices/CharSet.cs new file mode 100644 index 0000000..95d4993 --- /dev/null +++ b/corlib/System.Runtime.InteropServices/CharSet.cs @@ -0,0 +1,12 @@ +#if !LOCALTEST + +namespace System.Runtime.InteropServices { + public enum CharSet { + None = 1, + Ansi = 2, + Unicode = 3, + Auto = 4, + } +} + +#endif diff --git a/corlib/System.Runtime.InteropServices/DllImportAttribute.cs b/corlib/System.Runtime.InteropServices/DllImportAttribute.cs new file mode 100644 index 0000000..4a07466 --- /dev/null +++ b/corlib/System.Runtime.InteropServices/DllImportAttribute.cs @@ -0,0 +1,30 @@ +#if !LOCALTEST + +namespace System.Runtime.InteropServices { + public class DllImportAttribute : Attribute { + + // Sync with C code + private string dllName; + public bool BestFitMapping; + public CallingConvention CallingConvention; + public CharSet CharSet; + public string EntryPoint; + public bool ExactSpelling; + public bool PreserveSig; + public bool SetLastError; + public bool ThrowOnUnmappableChar; + + public DllImportAttribute(string dllName) { + this.dllName = dllName; + } + + public string Value { + get { + return this.dllName; + } + } + + } +} + +#endif diff --git a/corlib/System.Runtime.InteropServices/ExternalException.cs b/corlib/System.Runtime.InteropServices/ExternalException.cs new file mode 100644 index 0000000..d1324c0 --- /dev/null +++ b/corlib/System.Runtime.InteropServices/ExternalException.cs @@ -0,0 +1,26 @@ +#if !LOCALTEST + +namespace System.Runtime.InteropServices { + public class ExternalException : SystemException { + + public ExternalException() : base("External exception") { } + + public ExternalException(string msg) : base(msg) { } + + public ExternalException(string msg, Exception inner) : base(msg, inner) { } + + public ExternalException(string msg, int err) + : base(msg) { + base.HResult = err; + } + + public virtual int ErrorCode { + get { + return base.HResult; + } + } + + } +} + +#endif diff --git a/corlib/System.Runtime.InteropServices/InAttribute.cs b/corlib/System.Runtime.InteropServices/InAttribute.cs new file mode 100644 index 0000000..c3ebba7 --- /dev/null +++ b/corlib/System.Runtime.InteropServices/InAttribute.cs @@ -0,0 +1,12 @@ +#if !LOCALTEST + +namespace System.Runtime.InteropServices { + + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + public sealed class InAttribute : Attribute { + public InAttribute() { } + } + +} + +#endif diff --git a/corlib/System.Runtime.InteropServices/OutAttribute.cs b/corlib/System.Runtime.InteropServices/OutAttribute.cs new file mode 100644 index 0000000..2331173 --- /dev/null +++ b/corlib/System.Runtime.InteropServices/OutAttribute.cs @@ -0,0 +1,14 @@ +#if !LOCALTEST + +using System; + +namespace System.Runtime.InteropServices { + + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + public sealed class OutAttribute : Attribute { + public OutAttribute() { } + } + +} + +#endif diff --git a/corlib/System.Text/Decoder.cs b/corlib/System.Text/Decoder.cs new file mode 100644 index 0000000..b101a18 --- /dev/null +++ b/corlib/System.Text/Decoder.cs @@ -0,0 +1,24 @@ +#if !LOCALTEST + +namespace System.Text { + public abstract class Decoder { + public virtual int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex) { + return GetChars(bytes, byteIndex, byteCount, chars, charIndex, false); + } + + public virtual int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex, bool flush) { + if (bytes == null || chars == null) { + throw new ArgumentNullException(); + } + if (byteIndex < 0 || byteCount < 0 || charIndex < 0 || + byteIndex + byteCount > bytes.Length || charIndex >= chars.Length) { + throw new ArgumentOutOfRangeException(); + } + return GetCharsSafe(bytes, byteIndex, byteCount, chars, charIndex, flush); + } + + protected abstract int GetCharsSafe(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex, bool flush); + } +} + +#endif diff --git a/corlib/System.Text/Encoding.cs b/corlib/System.Text/Encoding.cs new file mode 100644 index 0000000..305b2cb --- /dev/null +++ b/corlib/System.Text/Encoding.cs @@ -0,0 +1,76 @@ +#if !LOCALTEST + +namespace System.Text { + + public abstract class Encoding : ICloneable { + + private static object lockObj = new object(); + + #region Static common Encoding properties + + private static Encoding unicodeEncoding = null; + private static Encoding utf8Encoding = null; + private static Encoding utf8UnmarkedEncoding = null; + + public static Encoding Unicode { + get { + if (unicodeEncoding == null) { + lock (lockObj) { + if (unicodeEncoding == null) { + unicodeEncoding = new UnicodeEncoding(true, false); + } + } + } + return unicodeEncoding; + } + } + + public static Encoding UTF8 { + get { + if (utf8Encoding == null) { + lock (lockObj) { + if (utf8Encoding == null) { + utf8Encoding = new UTF8Encoding(true); + } + } + } + return utf8Encoding; + } + } + + public static Encoding UTF8Unmarked { + get { + if (utf8UnmarkedEncoding == null) { + lock (lockObj) { + if (utf8UnmarkedEncoding == null) { + utf8UnmarkedEncoding = new UTF8Encoding(false); + } + } + } + return utf8UnmarkedEncoding; + } + } + + #endregion + + public virtual byte[] GetPreamble() { + return new byte[0]; + } + + public abstract int GetMaxCharCount(int byteCount); + + public abstract Decoder GetDecoder(); + + + #region ICloneable Members + + public object Clone() { + return (Encoding)object.Clone(this); + } + + #endregion + } + +} + +#endif diff --git a/corlib/System.Text/StringBuilder.cs b/corlib/System.Text/StringBuilder.cs new file mode 100644 index 0000000..984cd01 --- /dev/null +++ b/corlib/System.Text/StringBuilder.cs @@ -0,0 +1,447 @@ +using System; +using System.Runtime.CompilerServices; + +#if LOCALTEST +namespace System_.Text { +#else +namespace System.Text { +#endif + public sealed class StringBuilder { + + private const int defaultMaxCapacity = int.MaxValue; + private const int defaultInitialCapacity = 16; + + private int length; + private int capacity; + private char[] data; + + #region Constructors + + public StringBuilder() : this(defaultInitialCapacity, defaultMaxCapacity) { } + + public StringBuilder(int initialCapacity) : this(initialCapacity, defaultMaxCapacity) { } + + public StringBuilder(int initialCapacity, int maxCapacity) { + this.capacity = Math.Max(initialCapacity, 2); + this.length = 0; + this.data = new char[this.capacity]; + } + + public StringBuilder(string value) + : this((value != null) ? value.Length : defaultInitialCapacity, defaultMaxCapacity) { + if (value != null) { + this.Append(value); + } + } + + public StringBuilder(string value, int initialCapacity) + : this(initialCapacity, defaultMaxCapacity) { + if (value != null) { + this.Append(value); + } + } + + public StringBuilder(string value, int startIndex, int length, int initialCapacity) + : this(initialCapacity, defaultMaxCapacity) { + if (value == null) { + value = string.Empty; + } + if (startIndex < 0 || length < 0 || startIndex + length > value.Length) { + throw new ArgumentOutOfRangeException(); + } + this.Append(value, startIndex, length); + } + + #endregion + + public override string ToString() { + return new string(this.data, 0, this.length); + } + + public string ToString(int startIndex, int length) { + if (startIndex < 0 || length < 0 || startIndex + length > this.length) { + throw new ArgumentOutOfRangeException(); + } + return new string(this.data, startIndex, length); + } + + private void EnsureSpace(int space) { + if (this.length + space > this.capacity) { + do { + this.capacity <<= 1; + } while (this.capacity < this.length + space); + char[] newData = new char[capacity]; + Array.Copy(this.data, 0, newData, 0, this.length); + this.data = newData; + } + } + + public int Length { + get { + return this.length; + } + set { + if (value < 0) { + throw new ArgumentOutOfRangeException(); + } + if (value > this.length) { + this.EnsureSpace(this.length - value); + for (int i = this.length; i < value; i++) { + this.data[i] = '\x0000'; + } + } + this.length = value; + } + } + + public int Capacity { + get { + return this.capacity; + } + } + + [IndexerName("Chars")] + public char this[int index] { + get { + if (index < 0 || index >= this.length) { + throw new IndexOutOfRangeException(); + } + return this.data[index]; + } + set { + if (index < 0 || index >= this.length) { + throw new IndexOutOfRangeException(); + } + this.data[index] = value; + } + } + + public void CopyTo(int srcIndex, char[] dst, int dstIndex, int count) { + if (dst == null) { + throw new ArgumentNullException("destination"); + } + if (srcIndex < 0 || count < 0 || dstIndex < 0 || + srcIndex + count > this.length || dstIndex + count > dst.Length) { + throw new ArgumentOutOfRangeException(); + } + Array.Copy(this.data, srcIndex, dst, dstIndex, count); + } + + public void EnsureCapacity(int capacity) { + if (this.capacity < capacity) { + // This is not quite right, as it will often over-allocate memory + this.EnsureSpace(capacity - this.capacity); + } + } + + public StringBuilder Remove(int startIndex, int length) { + if (startIndex < 0 || length < 0 || startIndex + length > this.length) { + throw new ArgumentOutOfRangeException(); + } + Array.Copy(this.data, startIndex + length, this.data, startIndex, this.length - length - startIndex); + this.length -= length; + return this; + } + + #region Append Methods + + public StringBuilder Append(string value) { + int len = value.Length; + this.EnsureSpace(len); + for (int i = 0; i < len; i++) { + this.data[this.length++] = value[i]; + } + return this; + } + + public StringBuilder Append(string value, int startIndex, int count) { + if (value == null) { + return this; + } + if (startIndex < 0 || count < 0 || value.Length < startIndex + count) { + throw new ArgumentOutOfRangeException(); + } + this.EnsureSpace(count); + for (int i = 0; i < count; i++) { + this.data[this.length++] = value[startIndex + i]; + } + return this; + } + + public StringBuilder Append(char value) { + EnsureSpace(1); + data[length++] = value; + return this; + } + + public StringBuilder Append(char value, int repeatCount) { + if (repeatCount < 0) { + throw new ArgumentOutOfRangeException(); + } + EnsureSpace(repeatCount); + for (int i = 0; i < repeatCount; i++) { + this.data[this.length++] = value; + } + return this; + } + + public StringBuilder Append(char[] value) { + if (value == null) { + return this; + } + int addLen = value.Length; + this.EnsureSpace(addLen); + Array.Copy(value, 0, this.data, this.length, addLen); + this.length += addLen; + return this; + } + + public StringBuilder Append(char[] value, int startIndex, int charCount) { + if (value == null) { + return this; + } + if (charCount < 0 || startIndex < 0 || value.Length < (startIndex + charCount)) { + throw new ArgumentOutOfRangeException(); + } + this.EnsureSpace(charCount); + Array.Copy(value, startIndex, this.data, this.length, charCount); + this.length += charCount; + return this; + } + + public StringBuilder Append(object value) { + if (value == null) { + return this; + } + return Append(value.ToString()); + } + + public StringBuilder Append(bool value) { + return Append(value.ToString()); + } + + public StringBuilder Append(byte value) { + return Append(value.ToString()); + } + + public StringBuilder Append(decimal value) { + return Append(value.ToString()); + } + + public StringBuilder Append(double value) { + return Append(value.ToString()); + } + + public StringBuilder Append(short value) { + return Append(value.ToString()); + } + + public StringBuilder Append(int value) { + return Append(value.ToString()); + } + + public StringBuilder Append(long value) { + return Append(value.ToString()); + } + + public StringBuilder Append(sbyte value) { + return Append(value.ToString()); + } + + public StringBuilder Append(float value) { + return Append(value.ToString()); + } + + public StringBuilder Append(ushort value) { + return Append(value.ToString()); + } + + public StringBuilder Append(uint value) { + return Append(value.ToString()); + } + + public StringBuilder Append(ulong value) { + return Append(value.ToString()); + } + + #endregion + + #region AppendFormat Methods + + public StringBuilder AppendFormat(string format, object obj0) { + StringHelper.FormatHelper(this, null, format, obj0); + return this; + } + + public StringBuilder AppendFormat(string format, object obj0, object obj1) { + StringHelper.FormatHelper(this, null, format, obj0, obj1); + return this; + } + + public StringBuilder AppendFormat(string format, object obj0, object obj1, object obj2) { + StringHelper.FormatHelper(this, null, format, obj0, obj1, obj2); + return this; + } + + public StringBuilder AppendFormat(string format, params object[] objs) { + StringHelper.FormatHelper(this, null, format, objs); + return this; + } + + public StringBuilder AppendFormat(IFormatProvider provider, string format, params object[] objs) { + StringHelper.FormatHelper(this, provider, format, objs); + return this; + } + + #endregion + + #region AppendLine Methods + + public StringBuilder AppendLine() { + return this.Append(Environment.NewLine); + } + + public StringBuilder AppendLine(string value) { + return this.Append(value).Append(Environment.NewLine); + } + + #endregion + + #region Insert Methods + + public StringBuilder Insert(int index, string value) { + if (index < 0 || index > this.length) { + throw new ArgumentOutOfRangeException(); + } + if (string.IsNullOrEmpty(value)) { + return this; + } + int len = value.Length; + EnsureSpace(len); + Array.Copy(this.data, index, this.data, index + len, this.length - index); + for (int i = 0; i < len; i++) { + this.data[index + i] = value[i]; + } + this.length += len; + return this; + } + + public StringBuilder Insert(int index, bool value) { + return this.Insert(index, value.ToString()); + } + + public StringBuilder Insert(int index, byte value) { + return this.Insert(index, value.ToString()); + } + + public StringBuilder Insert(int index, char value) { + return this.Insert(index, value.ToString()); + } + + public StringBuilder Insert(int index, char[] value) { + return this.Insert(index, new string(value)); + } + + public StringBuilder Insert(int index, decimal value) { + return this.Insert(index, value.ToString()); + } + + public StringBuilder Insert(int index, double value) { + return this.Insert(index, value.ToString()); + } + + public StringBuilder Insert(int index, short value) { + return this.Insert(index, value.ToString()); + } + + public StringBuilder Insert(int index, int value) { + return this.Insert(index, value.ToString()); + } + + public StringBuilder Insert(int index, long value) { + return this.Insert(index, value.ToString()); + } + + public StringBuilder Insert(int index, object value) { + return this.Insert(index, value.ToString()); + } + + public StringBuilder Insert(int index, sbyte value) { + return this.Insert(index, value.ToString()); + } + + public StringBuilder Insert(int index, float value) { + return this.Insert(index, value.ToString()); + } + + public StringBuilder Insert(int index, ushort value) { + return this.Insert(index, value.ToString()); + } + + public StringBuilder Insert(int index, uint value) { + return this.Insert(index, value.ToString()); + } + + public StringBuilder Insert(int index, ulong value) { + return this.Insert(index, value.ToString()); + } + + public StringBuilder Insert(int index, string value, int count) { + if (count < 0) { + throw new ArgumentOutOfRangeException(); + } + if (count == 0 || string.IsNullOrEmpty(value)) { + return this; + } + StringBuilder toInsert = new StringBuilder(value.Length * count); + for (; count > 0; count--) { + toInsert.Append(value); + } + return this.Insert(index, toInsert.ToString()); + } + + public StringBuilder Insert(int index, char[] value, int startIndex, int charCount) { + if (value == null && (startIndex != 0 || charCount != 0)) { + throw new ArgumentNullException("value"); + } + if (startIndex < 0 || charCount < 0 || startIndex + charCount > value.Length) { + throw new ArgumentOutOfRangeException(); + } + return this.Insert(index, new string(value, startIndex, charCount)); + } + + #endregion + + #region Replace Methods + + public StringBuilder Replace(char oldChar, char newChar) { + return this.Replace(oldChar, newChar, 0, this.length); + } + + public StringBuilder Replace(string oldValue, string newValue) { + return this.Replace(oldValue, newValue, 0, this.length); + } + + public StringBuilder Replace(char oldChar, char newChar, int startIndex, int count) { + if (startIndex < 0 || count < 0 || startIndex + count > this.length) { + throw new ArgumentOutOfRangeException(); + } + for (int i = 0; i < count; i++) { + if (this.data[startIndex + i] == oldChar) { + this.data[startIndex + i] = newChar; + } + } + return this; + } + + public StringBuilder Replace(string oldValue, string newValue, int startIndex, int count) { + string subStr = this.ToString(startIndex, count); + subStr = subStr.Replace(oldValue, newValue); + this.Remove(startIndex, count); + this.Insert(startIndex, subStr); + return this; + } + + #endregion + } +} diff --git a/corlib/System.Text/UTF8Encoding.cs b/corlib/System.Text/UTF8Encoding.cs new file mode 100644 index 0000000..0383fc9 --- /dev/null +++ b/corlib/System.Text/UTF8Encoding.cs @@ -0,0 +1,109 @@ +#if !LOCALTEST + +namespace System.Text { + public class UTF8Encoding : Encoding { + + private class UTF8Decoder : Decoder { + + private byte b0, b1, b2, b3; + private int bufOfs = 0; + + protected override int GetCharsSafe(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex, bool flush) { + int charIndexOrg = charIndex; + int charsLen = chars.Length; + char ch = '\u0000'; + bool chSet = false; + for (int i = 0; i < byteCount; i++) { + byte b = bytes[byteIndex + i]; + switch (bufOfs) { + case 0: + if (b < 0x80) { + ch = (char)b; + chSet = true; + } else { + b0 = b; + bufOfs = 1; + } + break; + case 1: + if ((b0 & 0xe0) == 0xc0) { + ch = (char)(((b0 & 0x1f) << 6) | (b & 0x3f)); + chSet = true; + } else { + b1 = b; + bufOfs = 2; + } + break; + case 2: + if ((b0 & 0xf0) == 0xe0) { + ch = (char)(((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b & 0x3f)); + chSet = true; + } else { + b2 = b; + bufOfs = 3; + } + break; + case 3: + if ((b0 & 0xf8) == 0xf0) { + ch = (char)(((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b & 0x3f)); + chSet = true; + } else { + b3 = b; + bufOfs = 4; + } + break; + default: + throw new NotSupportedException("Cannot handle UTF8 characters more than 4 bytes"); + } + if (chSet) { + if (charIndex >= charsLen) { + throw new ArgumentException(); + } + chars[charIndex++] = ch; + bufOfs = 0; + chSet = false; + } + } + if (flush) { + bufOfs = 0; + } + return charIndex - charIndexOrg; + } + + } + + private bool emitIdentifier; + private bool throwOnInvalidBytes; + + public UTF8Encoding() : this(false, false) { } + + public UTF8Encoding(bool encoderShouldEmitUTF8Identifier) : this(encoderShouldEmitUTF8Identifier, false) { } + + public UTF8Encoding(bool encoderShouldEmitUTF8Identifier, bool throwOnInvalidBytes) { + this.emitIdentifier = encoderShouldEmitUTF8Identifier; + this.throwOnInvalidBytes = throwOnInvalidBytes; + } + + public override byte[] GetPreamble() { + if (emitIdentifier) { + return new byte[3] { 0xef, 0xbb, 0xbf }; + } else { + return new byte[0]; + } + } + + public override int GetMaxCharCount(int byteCount) { + if (byteCount < 0) { + throw new ArgumentOutOfRangeException("byteCount"); + } + return byteCount; + } + + public override Decoder GetDecoder() { + return new UTF8Decoder(); + } + + } +} + +#endif diff --git a/corlib/System.Text/UnicodeEncoding.cs b/corlib/System.Text/UnicodeEncoding.cs new file mode 100644 index 0000000..b10bd61 --- /dev/null +++ b/corlib/System.Text/UnicodeEncoding.cs @@ -0,0 +1,59 @@ +#if !LOCALTEST + +namespace System.Text { + public class UnicodeEncoding : Encoding { + + private class UnicodeDecoder : Decoder { + + private bool bigEndian; + + public UnicodeDecoder(bool bigEndian) { + this.bigEndian = bigEndian; + } + + protected override int GetCharsSafe(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex, bool flush) { + throw new Exception("The method or operation is not implemented."); + } + } + + private bool bigEndian; + private bool byteOrderMark; + private bool throwOnInvalidBytes; + + public UnicodeEncoding() : this(false, true, false) { } + + public UnicodeEncoding(bool bigEndian, bool byteOrderMark) : this(bigEndian, byteOrderMark, false) { } + + public UnicodeEncoding(bool bigEndian, bool byteOrderMark, bool throwOnInvalidBytes) { + this.bigEndian = bigEndian; + this.byteOrderMark = byteOrderMark; + this.throwOnInvalidBytes = throwOnInvalidBytes; + } + + public override byte[] GetPreamble() { + if (byteOrderMark) { + byte[] preamble = new byte[2] { 0xff, 0xfe }; + if (bigEndian) { + Array.Reverse(preamble); + } + return preamble; + } else { + return new byte[0]; + } + } + + public override int GetMaxCharCount(int byteCount) { + if (byteCount < 0) { + throw new ArgumentOutOfRangeException("byteCount"); + } + return byteCount / 2; + } + + public override Decoder GetDecoder() { + return new UnicodeDecoder(this.bigEndian); + } + + } +} + +#endif diff --git a/corlib/System.Threading/Interlocked.cs b/corlib/System.Threading/Interlocked.cs new file mode 100644 index 0000000..d263eda --- /dev/null +++ b/corlib/System.Threading/Interlocked.cs @@ -0,0 +1,25 @@ +#if !LOCALTEST + +using System.Runtime.CompilerServices; +namespace System.Threading { + public static class Interlocked { + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public static int CompareExchange(ref int loc, int value, int comparand); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public static int Increment(ref int loc); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public static int Decrement(ref int loc); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public static int Add(ref int loc, int value); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public static int Exchange(ref int loc, int value); + + } +} + +#endif diff --git a/corlib/System.Threading/Monitor.cs b/corlib/System.Threading/Monitor.cs new file mode 100644 index 0000000..b426bb9 --- /dev/null +++ b/corlib/System.Threading/Monitor.cs @@ -0,0 +1,31 @@ +#if !LOCALTEST + +using System.Runtime.CompilerServices; + +namespace System.Threading { + public static class Monitor { + + [MethodImpl(MethodImplOptions.InternalCall)] + extern private static bool Internal_TryEnter(object obj, int msTimeout); + + public static void Enter(object obj) { + if (obj == null) { + throw new ArgumentNullException("obj"); + } + Internal_TryEnter(obj, -1); + } + + [MethodImpl(MethodImplOptions.InternalCall)] + extern private static void Internal_Exit(object obj); + + public static void Exit(object obj) { + if (obj == null) { + throw new ArgumentNullException("obj"); + } + Internal_Exit(obj); + } + + } +} + +#endif diff --git a/corlib/System.Threading/ParameterizedThreadStart.cs b/corlib/System.Threading/ParameterizedThreadStart.cs new file mode 100644 index 0000000..ae8a8e6 --- /dev/null +++ b/corlib/System.Threading/ParameterizedThreadStart.cs @@ -0,0 +1,7 @@ +#if !LOCALTEST + +namespace System.Threading { + public delegate void ParameterizedThreadStart(object obj); +} + +#endif diff --git a/corlib/System.Threading/Thread.cs b/corlib/System.Threading/Thread.cs new file mode 100644 index 0000000..1325f17 --- /dev/null +++ b/corlib/System.Threading/Thread.cs @@ -0,0 +1,81 @@ +#if !LOCALTEST + +using System.Runtime.CompilerServices; +using System.Globalization; + +namespace System.Threading { + public sealed class Thread { + + // These member vars MUST be synced with C code. + private int managedThreadID = 0; + private MulticastDelegate threadStart = null; + private object param = null; + private ThreadState threadState = ThreadState.Unstarted; + + private CultureInfo currentCulture; + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public static void Sleep(int millisecondsTimeout); + + extern public static Thread CurrentThread { + [MethodImpl(MethodImplOptions.InternalCall)] + get; + } + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public Thread(ThreadStart threadStart); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public Thread(ParameterizedThreadStart threadStart); + + public int ManagedThreadId { + get { + return this.managedThreadID; + } + } + + public ThreadState ThreadState { + get { + return this.threadState; + } + } + + public bool IsBackground { + get { + return ((this.threadState & ThreadState.Background) != 0); + } + set { + if (value) { + this.threadState |= ThreadState.Background; + } else { + this.threadState &= ~ThreadState.Background; + } + } + } + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public void Start(); + + public void Start(object param) { + this.param = param; + this.Start(); + } + + public CultureInfo CurrentCulture { + get { + if (this.currentCulture == null) { + this.currentCulture = CultureInfo.InvariantCulture; + } + return this.currentCulture; + } + set { + if (value == null) { + throw new ArgumentNullException(); + } + this.currentCulture = value; + } + } + } +} + +#endif diff --git a/corlib/System.Threading/ThreadStart.cs b/corlib/System.Threading/ThreadStart.cs new file mode 100644 index 0000000..7f3b65b --- /dev/null +++ b/corlib/System.Threading/ThreadStart.cs @@ -0,0 +1,7 @@ +#if !LOCALTEST + +namespace System.Threading { + public delegate void ThreadStart(); +} + +#endif diff --git a/corlib/System.Threading/ThreadState.cs b/corlib/System.Threading/ThreadState.cs new file mode 100644 index 0000000..473c433 --- /dev/null +++ b/corlib/System.Threading/ThreadState.cs @@ -0,0 +1,21 @@ +#if !LOCALTEST + +namespace System.Threading { + + [Flags] + public enum ThreadState { + Running = 0x00000000, + StopRequested = 0x00000001, + SuspendRequested = 0x00000002, + Background = 0x00000004, + Unstarted = 0x00000008, + Stopped = 0x00000010, + WaitSleepJoin = 0x00000020, + Suspended = 0x00000040, + AbortRequested = 0x00000080, + Aborted = 0x00000100, + } + +} + +#endif diff --git a/corlib/System.Threading/WaitHandle.cs b/corlib/System.Threading/WaitHandle.cs new file mode 100644 index 0000000..a5ffa53 --- /dev/null +++ b/corlib/System.Threading/WaitHandle.cs @@ -0,0 +1,14 @@ +#if !LOCALTEST + +using System; + +namespace System.Threading { + public abstract class WaitHandle : MarshalByRefObject, IDisposable { + + public void Dispose() { + } + + } +} + +#endif diff --git a/corlib/System/Action.cs b/corlib/System/Action.cs new file mode 100644 index 0000000..613574c --- /dev/null +++ b/corlib/System/Action.cs @@ -0,0 +1,7 @@ +#if !LOCALTEST + +namespace System { + public delegate void Action (T obj); +} + +#endif diff --git a/corlib/System/Activator.cs b/corlib/System/Activator.cs new file mode 100644 index 0000000..9b02030 --- /dev/null +++ b/corlib/System/Activator.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace corlib.System { + + public static class Activator { + + + + } + +} diff --git a/corlib/System/ArgumentException.cs b/corlib/System/ArgumentException.cs new file mode 100644 index 0000000..cb4e437 --- /dev/null +++ b/corlib/System/ArgumentException.cs @@ -0,0 +1,43 @@ +#if !LOCALTEST + +namespace System { + public class ArgumentException : SystemException { + + private string paramName; + + public ArgumentException() : base("An invalid argument was specified.") { } + + public ArgumentException(string message) : base(message) { } + + public ArgumentException(string message, Exception innerException) : base(message, innerException) { } + + public ArgumentException(string message, string paramName) + : base(message) { + + this.paramName = paramName; + } + + public virtual string ParamName { + get { + return paramName; + } + } + + public override string Message { + get { + string baseMsg = base.Message; + if (baseMsg == null) { + baseMsg = "An invalid argument was specified."; + } + if (paramName == null) { + return baseMsg; + } else { + return baseMsg + Environment.NewLine + "Parameter name: " + paramName; + } + } + } + + } +} + +#endif diff --git a/corlib/System/ArgumentNullException.cs b/corlib/System/ArgumentNullException.cs new file mode 100644 index 0000000..5d679ff --- /dev/null +++ b/corlib/System/ArgumentNullException.cs @@ -0,0 +1,19 @@ +#if !LOCALTEST + +namespace System { + public class ArgumentNullException : ArgumentException { + + public ArgumentNullException() : base("Argument cannot be null.") { } + + public ArgumentNullException(string paramName) : base("Argument cannot be null.", paramName) { } + + public ArgumentNullException(string paramName, string message) : base(message, paramName) { } + + public ArgumentNullException(string message, Exception innerException) + : base(message, innerException) { + } + + } +} + +#endif \ No newline at end of file diff --git a/corlib/System/ArgumentOutOfRangeException.cs b/corlib/System/ArgumentOutOfRangeException.cs new file mode 100644 index 0000000..7044040 --- /dev/null +++ b/corlib/System/ArgumentOutOfRangeException.cs @@ -0,0 +1,14 @@ +#if !LOCALTEST + +namespace System { + public class ArgumentOutOfRangeException : ArgumentException { + + public ArgumentOutOfRangeException() : base("Argument is out of range.") { } + + public ArgumentOutOfRangeException(string paramName) : base("Argument is out of range.", paramName) { } + + public ArgumentOutOfRangeException(string paramName, string msg) : base(msg, paramName) { } + } +} + +#endif diff --git a/corlib/System/ArithmeticException.cs b/corlib/System/ArithmeticException.cs new file mode 100644 index 0000000..1807d5f --- /dev/null +++ b/corlib/System/ArithmeticException.cs @@ -0,0 +1,12 @@ +#if !LOCALTEST + +namespace System { + public class ArithmeticException : SystemException { + + public ArithmeticException() : base("Overflow or underflow in the arithmetic operation.") { } + public ArithmeticException(string msg) : base(msg) { } + + } +} + +#endif diff --git a/corlib/System/Array.cs b/corlib/System/Array.cs new file mode 100644 index 0000000..7fa66a7 --- /dev/null +++ b/corlib/System/Array.cs @@ -0,0 +1,405 @@ +#if !LOCALTEST + +using System.Runtime.CompilerServices; +using System.Collections; +using System.Collections.Generic; + +namespace System { + + public abstract class Array : ICloneable, IList, ICollection, IEnumerable { + + private class NonGenericEnumerator : IEnumerator { + + private Array array; + private int index, length; + + public NonGenericEnumerator(Array array) { + this.array = array; + this.index = -1; + this.length = array.length; + } + + public object Current { + get { + if (index < 0) { + throw new InvalidOperationException("Enumeration has not started"); + } + if (index >= length) { + throw new InvalidOperationException("Enumeration has finished"); + } + return array.GetValue(index); + } + } + + public bool MoveNext() { + index++; + return (index < length); + } + + public void Reset() { + index = -1; + } + + } + + private struct GenericEnumerator : IEnumerator { + + private Array array; + private int index, length; + + public GenericEnumerator(Array array) { + this.array = array; + this.index = -1; + this.length = array.length; + } + + public T Current { + get { + if (index < 0) { + throw new InvalidOperationException("Enumeration has not started"); + } + if (index >= length) { + throw new InvalidOperationException("Enumeration has finished"); + } + return (T)array.GetValue(index); + } + } + + public void Dispose() { + } + + object IEnumerator.Current { + get { + return this.Current; + } + } + + public bool MoveNext() { + index++; + return (index < length); + } + + public void Reset() { + this.index = -1; + } + } + + private Array() { + } + + #region Generic interface methods + + // The name of these methods are important. They are directly referenced in the interpreter. + private IEnumerator Internal_GetGenericEnumerator() { + return new GenericEnumerator(this); + } + + private bool Internal_GenericIsReadOnly() { + return true; + } + + private void Internal_GenericAdd(T item) { + throw new NotSupportedException("Collection is read-only"); + } + + private void Internal_GenericClear() { + Array.Clear(this, 0, this.length); + } + + private bool Internal_GenericContains(T item) { + return Array.IndexOf(this, (object)item) >= 0; + } + + private void Internal_GenericCopyTo(T[] array, int arrayIndex) { + Array.Copy(this, 0, (Array)array, arrayIndex, this.length); + } + + private bool Internal_GenericRemove(T item) { + throw new NotSupportedException("Collection is read-only"); + } + + private int Internal_GenericIndexOf(T item) { + return IndexOf(this, (object)item); + } + + private void Internal_GenericInsert(int index, T item) { + throw new NotSupportedException("List is read-only"); + } + + private void Internal_GenericRemoveAt(int index) { + throw new NotSupportedException("List is read-only"); + } + + private T Internal_GenericGetItem(int index) { + return (T)GetValue(index); + } + + private void Internal_GenericSetItem(int index, T value) { + SetValue((object)value, index); + } + + #endregion + + // This must be the only field, as it ties up with the Array definition in InterNet2 + private int length; + + public int Length { + get { + return this.length; + } + } + + [MethodImpl(MethodImplOptions.InternalCall)] + extern private object Internal_GetValue(int index); + + /// + /// Returns true if the value set ok, returns false if the Type was wrong + /// + [MethodImpl(MethodImplOptions.InternalCall)] + extern public bool Internal_SetValue(object value, int index); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public static void Clear(Array array, int index, int length); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern private static bool Internal_Copy(Array src, int srcIndex, Array dst, int dstIndex, int length); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public static void Resize(ref T[] array, int newSize); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public static void Reverse(Array array, int index, int length); + + public static void Reverse(Array array) { + Reverse(array, 0, array.length); + } + + public static int IndexOf(Array array, object value) { + return IndexOf(array, value, 0, array.length); + } + + public static int IndexOf(Array array, object value, int startIndex) { + return IndexOf(array, value, startIndex, array.length - startIndex); + } + + public static int IndexOf(Array array, object value, int startIndex, int count) { + if (array == null) { + throw new ArgumentNullException("array"); + } + int max = startIndex + count; + if (startIndex < 0 || max > array.length) { + throw new ArgumentOutOfRangeException(); + } + for (int i = startIndex; i < max; i++) { + if (object.Equals(value, array.GetValue(i))) { + return i; + } + } + return -1; + } + + public static void Copy(Array srcArray, int srcIndex, Array dstArray, int dstIndex, int length) { + if (srcArray == null || dstArray == null) { + throw new ArgumentNullException((srcArray == null) ? "sourceArray" : "destinationArray"); + } + if (srcIndex < 0 || dstIndex < 0 || length < 0) { + throw new ArgumentOutOfRangeException(); + } + if (srcIndex + length > srcArray.length || dstIndex + length > dstArray.length) { + throw new ArgumentException(); + } + if (Internal_Copy(srcArray, srcIndex, dstArray, dstIndex, length)) { + // When src element type can always be cast to dst element type, then can do a really fast copy. + return; + } + + int start, inc, end; + // Need to make sure it works even if both arrays are the same + if (dstIndex > srcIndex) { + start = 0; + inc = 1; + end = length; + } else { + start = length - 1; + inc = -1; + end = -1; + } + for (int i = start; i != end; i += inc) { + object item = srcArray.GetValue(srcIndex + i); + dstArray.SetValue(item, dstIndex + i); + } + } + + public static void Copy(Array srcArray, Array dstArray, int length) { + Copy(srcArray, 0, dstArray, 0, length); + } + + public static int IndexOf(T[] array, T value) { + return IndexOf((Array)array, (object)value); + } + + public static int IndexOf(T[] array, T value, int startIndex) { + return IndexOf((Array)array, (object)value, startIndex); + } + + public static int IndexOf(T[] array, T value, int startIndex, int count) { + return IndexOf((Array)array, (object)value, startIndex, count); + } + + public object GetValue(int index) { + if (index < 0 || index >= this.length) { + throw new IndexOutOfRangeException(); + } + return Internal_GetValue(index); + } + + public void SetValue(object value, int index) { + if (index < 0 || index >= this.length) { + throw new IndexOutOfRangeException(); + } + if (!Internal_SetValue(value, index)) { + throw new InvalidCastException(); + } + } + + public int Rank { + get { + return 1; + } + } + + public int GetLength(int dimension) { + if (dimension != 0) { + throw new IndexOutOfRangeException(); + } + return this.length; + } + + public int GetLowerBound(int dimension) { + if (dimension != 0) { + throw new IndexOutOfRangeException(); + } + return 0; + } + + public int GetUpperBound(int dimension) { + if (dimension != 0) { + throw new IndexOutOfRangeException(); + } + return this.length - 1; + } + + public static TOutput[] ConvertAll(TInput[] array, Converter converter) { + if (array == null) { + throw new ArgumentNullException("array"); + } + if (converter == null) { + throw new ArgumentNullException("converter"); + } + + TOutput[] output = new TOutput[array.Length]; + int arrayLen = array.Length; + for (int i = 0; i < arrayLen; i++) { + output[i] = converter(array[i]); + } + + return output; + } + + + #region Interface Members + + public object Clone() { + return object.Clone(this); + } + + public bool IsFixedSize { + get { + return true; + } + } + + public bool IsReadOnly { + get { + return false; + } + } + + object IList.this[int index] { + get { + if (index < 0 || index >= this.length) { + throw new ArgumentOutOfRangeException("index"); + } + return GetValue(index); + } + set { + if (index < 0 || index >= this.length) { + throw new ArgumentOutOfRangeException("index"); + } + SetValue(value, index); + } + } + + int IList.Add(object value) { + throw new NotSupportedException("Collection is read-only"); + } + + void IList.Clear() { + Array.Clear(this, 0, this.length); + } + + bool IList.Contains(object value) { + return (IndexOf(this, value) >= 0); + } + + int IList.IndexOf(object value) { + return IndexOf(this, value); + } + + void IList.Insert(int index, object value) { + throw new NotSupportedException("Collection is read-only"); + } + + void IList.Remove(object value) { + throw new NotSupportedException("Collection is read-only"); + } + + void IList.RemoveAt(int index) { + throw new NotSupportedException("Collection is read-only"); + } + + int ICollection.Count { + get { + return this.length; + } + } + + public bool IsSynchronized { + get { + return false; + } + } + + public object SyncRoot { + get { + return this; + } + } + + public void CopyTo(Array array, int index) { + Copy(this, 0, array, index, this.length); + } + + public IEnumerator GetEnumerator() { + return new NonGenericEnumerator(this); + } + + IEnumerator IEnumerable.GetEnumerator() { + return GetEnumerator(); + } + + #endregion + } + +} +#endif diff --git a/corlib/System/ArrayTypeMismatchException.cs b/corlib/System/ArrayTypeMismatchException.cs new file mode 100644 index 0000000..ddd018f --- /dev/null +++ b/corlib/System/ArrayTypeMismatchException.cs @@ -0,0 +1,12 @@ +#if !LOCALTEST + +namespace System { + public class ArrayTypeMismatchException : SystemException { + + public ArrayTypeMismatchException() : base("Source array type cannot be assigned to destination array type.") { } + public ArrayTypeMismatchException(string msg) : base(msg) { } + + } +} + +#endif diff --git a/corlib/System/AsyncCallback.cs b/corlib/System/AsyncCallback.cs new file mode 100644 index 0000000..5d2af3a --- /dev/null +++ b/corlib/System/AsyncCallback.cs @@ -0,0 +1,9 @@ +#if !LOCALTEST + +namespace System { + + public delegate void AsyncCallback(IAsyncResult ar); + +} + +#endif diff --git a/corlib/System/Attribute.cs b/corlib/System/Attribute.cs new file mode 100644 index 0000000..8f49e18 --- /dev/null +++ b/corlib/System/Attribute.cs @@ -0,0 +1,8 @@ +#if !LOCALTEST + +namespace System { + public abstract class Attribute { + } +} + +#endif diff --git a/corlib/System/AttributeTargets.cs b/corlib/System/AttributeTargets.cs new file mode 100644 index 0000000..e6bb623 --- /dev/null +++ b/corlib/System/AttributeTargets.cs @@ -0,0 +1,28 @@ +#if !LOCALTEST + +namespace System { + + public enum AttributeTargets { + Assembly = 0x00000001, + Module = 0x00000002, + Class = 0x00000004, + Struct = 0x00000008, + Enum = 0x00000010, + Constructor = 0x00000020, + Method = 0x00000040, + Property = 0x00000080, + Field = 0x00000100, + Event = 0x00000200, + Interface = 0x00000400, + Parameter = 0x00000800, + Delegate = 0x00001000, + ReturnValue = 0x00002000, + GenericParameter = 0x00004000, + + All = Assembly | Module | Class | Struct | Enum | Constructor | + Method | Property | Field | Event | Interface | Parameter | Delegate | ReturnValue | GenericParameter + } + +} + +#endif diff --git a/corlib/System/AttributeUsageAttribute.cs b/corlib/System/AttributeUsageAttribute.cs new file mode 100644 index 0000000..225b3ca --- /dev/null +++ b/corlib/System/AttributeUsageAttribute.cs @@ -0,0 +1,43 @@ +#if !LOCALTEST + +using System; + +namespace System { + public sealed class AttributeUsageAttribute : Attribute { + + AttributeTargets validOn; + bool allowMultiple = false; + bool inherited = true; + + public AttributeUsageAttribute(AttributeTargets validOn) { + this.validOn = validOn; + } + + public bool AllowMultiple { + get { + return allowMultiple; + } + set { + allowMultiple = value; + } + } + + public bool Inherited { + get { + return inherited; + } + set { + inherited = value; + } + } + + public AttributeTargets ValidOn { + get { + return validOn; + } + } + + } +} + +#endif diff --git a/corlib/System/BitConverter.cs b/corlib/System/BitConverter.cs new file mode 100644 index 0000000..e66583a --- /dev/null +++ b/corlib/System/BitConverter.cs @@ -0,0 +1,22 @@ +#if !LOCALTEST + +using System.Runtime.CompilerServices; +namespace System { + public static class BitConverter { + + public static readonly bool IsLittleEndian = AmILittleEndian(); + + private unsafe static bool AmILittleEndian() { + int i = 1; + byte b = *((byte*)&i); + return (b == 1); + } + + public unsafe static long DoubleToInt64Bits(double value) { + return *((long*)&value); + } + + } +} + +#endif diff --git a/corlib/System/Boolean.cs b/corlib/System/Boolean.cs new file mode 100644 index 0000000..9ecd9b8 --- /dev/null +++ b/corlib/System/Boolean.cs @@ -0,0 +1,70 @@ +#if !LOCALTEST + +namespace System { + public struct Boolean : IComparable, IComparable, IEquatable { + + public static readonly string TrueString = "True"; + public static readonly string FalseString = "False"; + + internal bool m_value; + + public override string ToString() { + return this.m_value ? TrueString : FalseString; + } + + public override bool Equals(object obj) { + return (obj is bool) && ((bool)obj).m_value == this.m_value; + } + + public override int GetHashCode() { + return (this.m_value) ? 1 : 0; + } + + public static bool Parse(string value) { + if (value == null) { + throw new ArgumentNullException("value"); + } + value = value.Trim(); + if (value == TrueString) { + return true; + } + if (value == FalseString) { + return false; + } + throw new FormatException("Value is not a valid boolean"); + } + + #region IComparable Members + + public int CompareTo(object obj) { + if (obj == null) { + return 1; + } + if (!(obj is int)) { + throw new ArgumentException(); + } + return this.CompareTo((bool)obj); + } + + #endregion + + #region IComparable Members + + public int CompareTo(bool x) { + return (this.m_value == x) ? 0 : ((this.m_value) ? 1 : -1); + } + + #endregion + + #region IEquatable Members + + public bool Equals(bool x) { + return this.m_value == x; + } + + #endregion + + } +} + +#endif \ No newline at end of file diff --git a/corlib/System/Byte.cs b/corlib/System/Byte.cs new file mode 100644 index 0000000..e9f3265 --- /dev/null +++ b/corlib/System/Byte.cs @@ -0,0 +1,73 @@ +#if !LOCALTEST + +using System.Globalization; +namespace System { + public struct Byte : IFormattable, IComparable, IComparable, IEquatable { + public const byte MinValue = 0; + public const byte MaxValue = 255; + + internal byte m_value; + + public override bool Equals(object obj) { + return (obj is byte) && ((byte)obj).m_value == this.m_value; + } + + public override int GetHashCode() { + return (int)this.m_value; + } + + #region ToString methods + + public override string ToString() { + return NumberFormatter.FormatGeneral(new NumberFormatter.NumberStore(this.m_value)); + } + + public string ToString(IFormatProvider formatProvider) { + return NumberFormatter.FormatGeneral(new NumberFormatter.NumberStore(this.m_value), formatProvider); + } + + public string ToString(string format) { + return this.ToString(format, null); + } + + public string ToString(string format, IFormatProvider formatProvider) { + NumberFormatInfo nfi = NumberFormatInfo.GetInstance(formatProvider); + return NumberFormatter.NumberToString(format, this.m_value, nfi); + } + + #endregion + + #region IComparable Members + + public int CompareTo(object obj) { + if (obj == null) { + return 1; + } + if (!(obj is byte)) { + throw new ArgumentException(); + } + return this.CompareTo((byte)obj); + } + + #endregion + + #region IComparable Members + + public int CompareTo(byte x) { + return (this.m_value > x) ? 1 : ((this.m_value < x) ? -1 : 0); + } + + #endregion + + #region IEquatable Members + + public bool Equals(byte x) { + return this.m_value == x; + } + + #endregion + + } +} + +#endif diff --git a/corlib/System/Char.cs b/corlib/System/Char.cs new file mode 100644 index 0000000..8cb400f --- /dev/null +++ b/corlib/System/Char.cs @@ -0,0 +1,196 @@ +#if !LOCALTEST + +using System; +using System.Collections.Generic; +using System.Text; +using System.Runtime.CompilerServices; +using System.Globalization; + +namespace System { + public struct Char : IComparable, IComparable, IEquatable { + + // Note that this array must be ordered, because binary searching is used on it. + internal static readonly char[] WhiteChars = { + (char) 0x9, (char) 0xA, (char) 0xB, (char) 0xC, (char) 0xD, + (char) 0x85, (char) 0x1680, (char) 0x2028, (char) 0x2029, + (char) 0x20, (char) 0xA0, (char) 0x2000, (char) 0x2001, + (char) 0x2002, (char) 0x2003, (char) 0x2004, (char) 0x2005, + (char) 0x2006, (char) 0x2007, (char) 0x2008, (char) 0x2009, + (char) 0x200A, (char) 0x200B, (char) 0x3000, (char) 0xFEFF }; + + + internal char m_value; + + public override string ToString() { + return new string(m_value, 1); + } + + public override bool Equals(object obj) { + return (obj is char && ((char)obj).m_value == this.m_value); + } + + public override int GetHashCode() { + return (int)this.m_value; + } + + [MethodImpl(MethodImplOptions.InternalCall)] + extern static public UnicodeCategory GetUnicodeCategory(char c); + + public static UnicodeCategory GetUnicodeCategory(string str, int index) { + if (str == null) { + throw new ArgumentNullException("str"); + } + if (index < 0 || index >= str.Length) { + throw new ArgumentOutOfRangeException("index"); + } + return GetUnicodeCategory(str[index]); + } + + public static bool IsWhiteSpace(char c) { + // TODO: Make this use Array.BinarySearch() when implemented + for (int i = 0; i < WhiteChars.Length; i++) { + if (WhiteChars[i] == c) { + return true; + } + } + return false; + } + + public static bool IsWhiteSpace(string str, int index) { + if (str == null) { + throw new ArgumentNullException("str"); + } + if (index < 0 || index >= str.Length) { + throw new ArgumentOutOfRangeException("index"); + } + return IsWhiteSpace(str[index]); + } + + public static bool IsLetter(char c) { + return GetUnicodeCategory(c) <= UnicodeCategory.OtherLetter; + } + + public static bool IsLetter(string str, int index) { + if (str == null) { + throw new ArgumentNullException("str"); + } + if (index < 0 || index >= str.Length) { + throw new ArgumentOutOfRangeException("index"); + } + return IsLetter(str[index]); + } + + public static bool IsDigit(char c) { + return GetUnicodeCategory(c) == UnicodeCategory.DecimalDigitNumber; + } + + public static bool IsDigit(string str, int index) { + if (str == null) { + throw new ArgumentNullException("str"); + } + if (index < 0 || index >= str.Length) { + throw new ArgumentOutOfRangeException("index"); + } + return IsDigit(str[index]); + } + + public static bool IsLower(char c) { + return GetUnicodeCategory(c) == UnicodeCategory.LowercaseLetter; + } + + public static bool IsLower(string str, int index) { + if (str == null) { + throw new ArgumentNullException("str"); + } + if (index < 0 || index >= str.Length) { + throw new ArgumentOutOfRangeException("index"); + } + return IsLower(str[index]); + } + + public static bool IsUpper(char c) { + return GetUnicodeCategory(c) == UnicodeCategory.UppercaseLetter; + } + + public static bool IsUpper(string str, int index) { + if (str == null) { + throw new ArgumentNullException("str"); + } + if (index < 0 || index >= str.Length) { + throw new ArgumentOutOfRangeException("index"); + } + return IsUpper(str[index]); + } + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public static char ToLowerInvariant(char c); + + public static char ToLower(char c) { + return ToLower(c, CultureInfo.CurrentCulture); + } + + public static char ToLower(char c, CultureInfo culture) { + if (culture == null) { + throw new ArgumentNullException("culture"); + } + if (culture.LCID == 0x7f) { + // Invariant culture + return ToLowerInvariant(c); + } + return '?'; + //return culture.TextInfo.ToUpper(c); + } + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public static char ToUpperInvariant(char c); + + public static char ToUpper(char c) { + return ToUpper(c, CultureInfo.CurrentCulture); + } + + public static char ToUpper(char c, CultureInfo culture) { + if (culture == null) { + throw new ArgumentNullException("culture"); + } + if (culture.LCID == 0x7f) { + // Invariant culture + return ToUpperInvariant(c); + } + return '?'; + //return culture.TextInfo.ToUpper(c); + } + + #region IComparable Members + + public int CompareTo(object obj) { + if (obj == null) { + return 1; + } + if (!(obj is char)) { + throw new ArgumentException(); + } + return this.CompareTo((char)obj); + } + + #endregion + + #region IComparable Members + + public int CompareTo(char x) { + return (this.m_value > x) ? 1 : ((this.m_value < x) ? -1 : 0); + } + + #endregion + + #region IEquatable Members + + public bool Equals(char x) { + return this.m_value == x; + } + + #endregion + + } +} + +#endif diff --git a/corlib/System/CharEnumerator.cs b/corlib/System/CharEnumerator.cs new file mode 100644 index 0000000..b04e948 --- /dev/null +++ b/corlib/System/CharEnumerator.cs @@ -0,0 +1,69 @@ +#if !LOCALTEST + +using System.Collections.Generic; +using System.Collections; + +namespace System { + public sealed class CharEnumerator : ICloneable, IEnumerator, IEnumerator { + + private string str; + private int index; + private int length; + + internal CharEnumerator(string s) { + this.str = s; + this.index = -1; + this.length = s.Length; + } + + #region IClonable Members + + public object Clone() { + return object.Clone(this); + } + + #endregion + + #region IEnumerator Members + + object IEnumerator.Current { + get { + return Current; + } + } + + public bool MoveNext() { + this.index++; + return (this.index < this.length); + } + + public void Reset() { + this.index = -1; + } + + #endregion + + #region IEnumerator Members + + public char Current { + get { + if (index == -1 || index >= length) { + throw new InvalidOperationException("The position is not valid."); + } + return str[index]; + } + } + + #endregion + + #region IDisposable Members + + public void Dispose() { + // Nothing needed + } + + #endregion + } +} + +#endif diff --git a/corlib/System/Console.cs b/corlib/System/Console.cs new file mode 100644 index 0000000..6c111e7 --- /dev/null +++ b/corlib/System/Console.cs @@ -0,0 +1,175 @@ +#if !LOCALTEST + +using System.Runtime.CompilerServices; + +namespace System { + public static class Console { + + static byte[] ascii2ConsoleKey_Map = new byte[128] { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 9 , 0x00, 0x00, 0x00, 13 , 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 27 , 0x00, 0x00, 0x00, 0x00, + 32 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 48 , 49 , 50 , 51 , 52 , 53 , 54 , 55 , 56 , 57 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 65 , 66 , 67 , 68 , 69 , 70 , 71 , 72 , 73 , 74 , 75 , 76 , 77 , 78 , 79 , + 80 , 81 , 82 , 83 , 84 , 85 , 86 , 87 , 88 , 89 , 90 , 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 65 , 66 , 67 , 68 , 69 , 70 , 71 , 72 , 73 , 74 , 75 , 76 , 77 , 78 , 79 , + 80 , 81 , 82 , 83 , 84 , 85 , 86 , 87 , 88 , 89 , 90 , 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public static void Write(string s); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern private static int Internal_ReadKey(); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern private static bool Internal_KeyAvailable(); + + #region Write Methods + + public static void Write(object value) { + if (value != null) { + Write(value.ToString()); + } + } + + public static void Write(char value) { + Write(value.ToString()); + } + + public static void Write(string format, params object[] args) { + Write(string.Format(format, args)); + } + + public static void Write(string format, object obj1) { + Write(format, new object[] { obj1 }); + } + + public static void Write(string format, object obj1, object obj2) { + Write(format, new object[] { obj1, obj2 }); + } + + public static void Write(string format, object obj1, object obj2, object obj3) { + Write(format, new object[] { obj1, obj2, obj3 }); + } + + public static void Write(string format, object obj1, object obj2, object obj3, object obj4) { + Write(format, new object[] { obj1, obj2, obj3, obj4 }); + } + + #endregion + + #region WriteLine Methods + + public static void WriteLine(string value) { + Write(value); + Write(Environment.NewLine); + } + + public static void WriteLine() { + WriteLine(string.Empty); + } + + public static void WriteLine(bool value) { + WriteLine(value.ToString()); + } + + public static void WriteLine(sbyte value) { + WriteLine(value.ToString()); + } + + public static void WriteLine(byte value) { + WriteLine(value.ToString()); + } + + public static void WriteLine(int value) { + WriteLine(value.ToString()); + } + + public static void WriteLine(uint value) { + WriteLine(value.ToString()); + } + + public static void WriteLine(long value) { + WriteLine(value.ToString()); + } + + public static void WriteLine(ulong value) { + WriteLine(value.ToString()); + } + + public static void WriteLine(char value) { + WriteLine(value.ToString()); + } + + public static void WriteLine(float value) { + WriteLine(value.ToString()); + } + + public static void WriteLine(double value) { + WriteLine(value.ToString()); + } + + public static void WriteLine(object value) { + if (value == null) { + WriteLine(); + } else { + WriteLine(value.ToString()); + } + } + + public static void WriteLine(string format, params object[] args) { + WriteLine(string.Format(format, args)); + } + + public static void WriteLine(string format, object obj1) { + WriteLine(format, new object[] { obj1 }); + } + + public static void WriteLine(string format, object obj1, object obj2) { + WriteLine(format, new object[] { obj1, obj2 }); + } + + public static void WriteLine(string format, object obj1, object obj2, object obj3) { + WriteLine(format, new object[] { obj1, obj2, obj3 }); + } + + public static void WriteLine(string format, object obj1, object obj2, object obj3, object obj4) { + WriteLine(format, new object[] { obj1, obj2, obj3, obj4 }); + } + + #endregion + + #region ReadKey Methods + + public static bool KeyAvailable { + get { + return Internal_KeyAvailable(); + } + } + + public static ConsoleKeyInfo ReadKey() { + return ReadKey(false); + } + + public static ConsoleKeyInfo ReadKey(bool intercept) { + int key = Internal_ReadKey(); + char c = (char)key; + if (!intercept) { + Write(c); + } + ConsoleKey k; + if (key < 128) { + k = (ConsoleKey)ascii2ConsoleKey_Map[key]; + } else { + k = ConsoleKey.Unknown; + } + return new ConsoleKeyInfo(c, k, false, false, false); + } + + #endregion + + } +} + +#endif diff --git a/corlib/System/ConsoleKey.cs b/corlib/System/ConsoleKey.cs new file mode 100644 index 0000000..2b6a8fd --- /dev/null +++ b/corlib/System/ConsoleKey.cs @@ -0,0 +1,153 @@ +#if !LOCALTEST + +namespace System { + public enum ConsoleKey { + Unknown = 0, // Non-standard + Backspace = 8, + Tab = 9, + Clear = 12, + Enter = 13, + Pause = 19, + Escape = 27, + Spacebar = 32, + PageUp = 33, + PageDown = 34, + End = 35, + Home = 36, + LeftArrow = 37, + UpArrow = 38, + RightArrow = 39, + DownArrow = 40, + Select = 41, + Print = 42, + Execute = 43, + PrintScreen = 44, + Insert = 45, + Delete = 46, + Help = 47, + D0 = 48, + D1 = 49, + D2 = 50, + D3 = 51, + D4 = 52, + D5 = 53, + D6 = 54, + D7 = 55, + D8 = 56, + D9 = 57, + A = 65, + B = 66, + C = 67, + D = 68, + E = 69, + F = 70, + G = 71, + H = 72, + I = 73, + J = 74, + K = 75, + L = 76, + M = 77, + N = 78, + O = 79, + P = 80, + Q = 81, + R = 82, + S = 83, + T = 84, + U = 85, + V = 86, + W = 87, + X = 88, + Y = 89, + Z = 90, + LeftWindows = 91, + RightWindows = 92, + Applications = 93, + Sleep = 95, + NumPad0 = 96, + NumPad1 = 97, + NumPad2 = 98, + NumPad3 = 99, + NumPad4 = 100, + NumPad5 = 101, + NumPad6 = 102, + NumPad7 = 103, + NumPad8 = 104, + NumPad9 = 105, + Multiply = 106, + Add = 107, + Separator = 108, + Subtract = 109, + Decimal = 110, + Divide = 111, + F1 = 112, + F2 = 113, + F3 = 114, + F4 = 115, + F5 = 116, + F6 = 117, + F7 = 118, + F8 = 119, + F9 = 120, + F10 = 121, + F11 = 122, + F12 = 123, + F13 = 124, + F14 = 125, + F15 = 126, + F16 = 127, + F17 = 128, + F18 = 129, + F19 = 130, + F20 = 131, + F21 = 132, + F22 = 133, + F23 = 134, + F24 = 135, + BrowserBack = 166, + BrowserForward = 167, + BrowserRefresh = 168, + BrowserStop = 169, + BrowserSearch = 170, + BrowserFavorites = 171, + BrowserHome = 172, + VolumeMute = 173, + VolumeDown = 174, + VolumeUp = 175, + MediaNext = 176, + MediaPrevious = 177, + MediaStop = 178, + MediaPlay = 179, + LaunchMail = 180, + LaunchMediaSelect = 181, + LaunchApp1 = 182, + LaunchApp2 = 183, + Oem1 = 186, + OemPlus = 187, + OemComma = 188, + OemMinus = 189, + OemPeriod = 190, + Oem2 = 191, + Oem3 = 192, + Oem4 = 219, + Oem5 = 220, + Oem6 = 221, + Oem7 = 222, + Oem8 = 223, + Oem102 = 226, + Process = 229, + Packet = 231, + Attention = 246, + CrSel = 247, + ExSel = 248, + EraseEndOfFile = 249, + Play = 250, + Zoom = 251, + NoName = 252, + Pa1 = 253, + OemClear = 254, + } +} + +#endif diff --git a/corlib/System/ConsoleKeyInfo.cs b/corlib/System/ConsoleKeyInfo.cs new file mode 100644 index 0000000..075985e --- /dev/null +++ b/corlib/System/ConsoleKeyInfo.cs @@ -0,0 +1,65 @@ +#if !LOCALTEST + +namespace System { + public struct ConsoleKeyInfo { + internal static ConsoleKeyInfo Empty = new ConsoleKeyInfo('\0', 0, false, false, false); + ConsoleKey key; + char keychar; + ConsoleModifiers modifiers; + + public ConsoleKeyInfo(char keyChar, ConsoleKey key, bool shift, bool alt, bool control) { + this.key = key; + this.keychar = keyChar; + modifiers = 0; + SetModifiers(shift, alt, control); + } + + internal ConsoleKeyInfo(ConsoleKeyInfo other) { + this.key = other.key; + this.keychar = other.keychar; + this.modifiers = other.modifiers; + } + + internal void SetKey(ConsoleKey key) { + this.key = key; + } + + internal void SetKeyChar(char keyChar) { + this.keychar = keyChar; + } + + internal void SetModifiers(bool shift, bool alt, bool control) { + this.modifiers = (shift) ? ConsoleModifiers.Shift : 0; + this.modifiers |= (alt) ? ConsoleModifiers.Alt : 0; + this.modifiers |= (control) ? ConsoleModifiers.Control : 0; + } + + public ConsoleKey Key { + get { return key; } + } + + public char KeyChar { + get { return keychar; } + } + + public ConsoleModifiers Modifiers { + get { return modifiers; } + } + + public override bool Equals(object o) { + if (!(o is ConsoleKeyInfo)) + return false; + return Equals((ConsoleKeyInfo)o); + } + + public bool Equals(ConsoleKeyInfo o) { + return key == o.key && o.keychar == keychar && o.modifiers == modifiers; + } + + public override int GetHashCode() { + return key.GetHashCode() ^ keychar.GetHashCode() ^ modifiers.GetHashCode(); + } + } +} + +#endif diff --git a/corlib/System/ConsoleModifiers.cs b/corlib/System/ConsoleModifiers.cs new file mode 100644 index 0000000..247dff8 --- /dev/null +++ b/corlib/System/ConsoleModifiers.cs @@ -0,0 +1,12 @@ +#if !LOCALTEST + +namespace System { + [Flags] + public enum ConsoleModifiers { + Alt = 1, + Shift = 2, + Control = 4 + } +} + +#endif diff --git a/corlib/System/Converter.cs b/corlib/System/Converter.cs new file mode 100644 index 0000000..52a6370 --- /dev/null +++ b/corlib/System/Converter.cs @@ -0,0 +1,7 @@ +#if !LOCALTEST + +namespace System { + public delegate TOutput Converter(TInput input); +} + +#endif diff --git a/corlib/System/DateTime.cs b/corlib/System/DateTime.cs new file mode 100644 index 0000000..4805296 --- /dev/null +++ b/corlib/System/DateTime.cs @@ -0,0 +1,745 @@ +#if !LOCALTEST + +using System.Runtime.CompilerServices; +using System.Globalization; +using System.Text; +namespace System { + public struct DateTime : IFormattable, IComparable, IComparable, IEquatable { + + public static readonly DateTime MinValue = new DateTime(0); + public static readonly DateTime MaxValue = new DateTime(3155378975999999999L); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern private static long InternalUtcNow(); + + private TimeSpan ticks; + private DateTimeKind kind; + + private static readonly int[] daysMonth = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + private static readonly int[] daysMonthLeap = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + + private static int AbsoluteDays(int year, int month, int day) { + int[] days; + int temp = 0, m = 1; + + days = (IsLeapYear(year) ? daysMonthLeap : daysMonth); + + while (m < month) + temp += days[m++]; + return ((day - 1) + temp + (365 * (year - 1)) + ((year - 1) / 4) - ((year - 1) / 100) + ((year - 1) / 400)); + } + + public DateTime(long ticks) { + this.ticks = new TimeSpan(ticks); + this.kind = DateTimeKind.Unspecified; + } + + public DateTime(long ticks, DateTimeKind kind) { + this.ticks = new TimeSpan(ticks); + this.kind = kind; + } + + public DateTime(int year, int month, int day) + : this(year, month, day, 0, 0, 0, 0, DateTimeKind.Unspecified) { + } + + public DateTime(int year, int month, int day, int hour, int minute, int second) + : this(year, month, day, hour, minute, second, 0, DateTimeKind.Unspecified) { + } + + public DateTime(int year, int month, int day, int hour, int minute, int second, DateTimeKind kind) + : this(year, month, day, hour, minute, second, 0, kind) { + } + + public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond) + : this(year, month, day, hour, minute, second, millisecond, DateTimeKind.Unspecified) { + } + + public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, DateTimeKind kind) { + ticks = new TimeSpan(AbsoluteDays(year, month, day), hour, minute, second, millisecond); + this.kind = kind; + } + + public DateTime Date { + get { + return new DateTime(this.Year, this.Month, this.Day, 0, 0, 0, this.kind); + } + } + + public int Day { + get { + return this.FromTicks(Which.Day); + } + } + + public DayOfWeek DayOfWeek { + get { + return (DayOfWeek)((this.ticks.Days + 1) % 7); + } + } + + public int DayOfYear { + get { + return this.FromTicks(Which.DayYear); + } + } + + public int Hour { + get { + return this.ticks.Hours; + } + } + + public DateTimeKind Kind { + get { + return this.kind; + } + } + + public int Millisecond { + get { + return this.ticks.MilliSeconds; + } + } + + public int Minute { + get { + return this.ticks.Minutes; + } + } + + public int Month { + get { + return this.FromTicks(Which.Month); + } + } + + public int Second { + get { + return this.ticks.Seconds; + } + } + + public long Ticks { + get { + return this.ticks.Ticks; + } + } + + public TimeSpan TimeOfDay { + get { + return new TimeSpan(this.ticks.Ticks % TimeSpan.TicksPerDay); + } + } + + public int Year { + get { + return this.FromTicks(Which.Year); + } + } + + public static DateTime UtcNow { + get { + return new DateTime(InternalUtcNow(), DateTimeKind.Utc); + } + } + + private enum Which { + Day, + DayYear, + Month, + Year + }; + + public DateTime Add(TimeSpan ts) { + return new DateTime(this.ticks.Ticks + ts.Ticks, this.kind); + } + + public TimeSpan Subtract(DateTime dt) { + return this.ticks - dt.ticks; + } + + public DateTime Subtract(TimeSpan ts) { + return new DateTime(this.ticks.Ticks - ts.Ticks, this.kind); + } + + public DateTime AddDays(double days) { + return this.AddTicks((long)(days * (double)TimeSpan.TicksPerDay)); + } + + public DateTime AddHours(double hours) { + return this.AddTicks((long)(hours * (double)TimeSpan.TicksPerHour)); + } + + public DateTime AddMilliseconds(double ms) { + return this.AddTicks((long)(ms * (double)TimeSpan.TicksPerMillisecond)); + } + + public DateTime AddMinutes(double mins) { + return this.AddTicks((long)(mins * (double)TimeSpan.TicksPerMinute)); + } + + public DateTime AddSeconds(double seconds) { + return this.AddTicks((long)(seconds * (double)TimeSpan.TicksPerSecond)); + } + + public DateTime AddTicks(long ticks) { + return new DateTime(this.ticks.Ticks + ticks, this.kind); + } + + public DateTime AddMonths(int months) { + int day, month, year, maxday; + DateTime temp; + + day = this.Day; + month = this.Month + (months % 12); + year = this.Year + months / 12; + + if (month < 1) { + month = 12 + month; + year--; + } else if (month > 12) { + month = month - 12; + year++; + } + maxday = DaysInMonth(year, month); + if (day > maxday) + day = maxday; + + temp = new DateTime(year, month, day); + temp.kind = kind; + return temp.Add(this.TimeOfDay); + } + + public DateTime AddYears(int years) { + return this.AddMonths(years * 12); + } + + public static DateTime operator +(DateTime d, TimeSpan t) { + return d.Add(t); + } + + public static TimeSpan operator -(DateTime d1, DateTime d2) { + return d1.Subtract(d2); + } + + public static DateTime operator -(DateTime d, TimeSpan t) { + return d.Subtract(t); + } + + public static bool operator ==(DateTime d1, DateTime d2) { + return d1.ticks == d2.ticks; + } + + public static bool operator !=(DateTime d1, DateTime d2) { + return d1.ticks != d2.ticks; + } + + public static bool operator >(DateTime d1, DateTime d2) { + return d1.ticks > d2.ticks; + } + + public static bool operator >=(DateTime d1, DateTime d2) { + return d1.ticks >= d2.ticks; + } + + public static bool operator <(DateTime d1, DateTime d2) { + return d1.ticks < d2.ticks; + } + + public static bool operator <=(DateTime d1, DateTime d2) { + return d1.ticks <= d2.ticks; + } + + private const int dp400 = 146097; + private const int dp100 = 36524; + private const int dp4 = 1461; + + public static bool IsLeapYear(int year) { + return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0); + } + + private int FromTicks(Which what) { + int num400, num100, num4, numyears; + int M = 1; + + int[] days = daysMonth; + int totaldays = this.ticks.Days; + + num400 = (totaldays / dp400); + totaldays -= num400 * dp400; + + num100 = (totaldays / dp100); + if (num100 == 4) // leap + num100 = 3; + totaldays -= (num100 * dp100); + + num4 = totaldays / dp4; + totaldays -= (num4 * dp4); + + numyears = totaldays / 365; + + if (numyears == 4) { + //leap + numyears = 3; + } + if (what == Which.Year) { + return num400 * 400 + num100 * 100 + num4 * 4 + numyears + 1; + } + + totaldays -= (numyears * 365); + if (what == Which.DayYear) { + return totaldays + 1; + } + + if ((numyears == 3) && ((num100 == 3) || !(num4 == 24))) { + //31 dec leapyear + days = daysMonthLeap; + } + + while (totaldays >= days[M]) { + totaldays -= days[M++]; + } + + if (what == Which.Month) { + return M; + } + + return totaldays + 1; + } + + public static int DaysInMonth(int year, int month) { + if (month < 1 || month > 12) { + throw new ArgumentOutOfRangeException(); + } + int[] days = (IsLeapYear(year) ? daysMonthLeap : daysMonth); + return days[month]; + } + + public override bool Equals(object obj) { + if (!(obj is System.DateTime)) { + return false; + } + return ((DateTime)obj).ticks == ticks; + } + + public override int GetHashCode() { + return this.ticks.GetHashCode(); + } + + #region ToString() stuff + + public override string ToString() { + return this.ToString("G", null); + } + + public string ToString(IFormatProvider fp) { + return this.ToString(null, fp); + } + + public string ToString(string format) { + return this.ToString(format, null); + } + + public string ToString(string format, IFormatProvider fp) { + DateTimeFormatInfo dtf = DateTimeFormatInfo.GetInstance(fp); + + if (string.IsNullOrEmpty(format)) { + format = "G"; + } + + bool useUtc = false, useInvariant = false; + if (format.Length == 1) { + format = GetStandardPattern(format[0], dtf, out useUtc, out useInvariant); + } + + return this.ToString2(format, dtf); + } + + #region ToString helper functions + + private string ToString2(string format, DateTimeFormatInfo dfi) { + // the length of the format is usually a good guess of the number + // of chars in the result. Might save us a few bytes sometimes + // Add + 10 for cases like mmmm dddd + StringBuilder result = new StringBuilder(format.Length + 10); + + // For some cases, the output should not use culture dependent calendar + DateTimeFormatInfo inv = DateTimeFormatInfo.InvariantInfo; + if (format == inv.RFC1123Pattern) + dfi = inv; + else if (format == inv.UniversalSortableDateTimePattern) + dfi = inv; + + int i = 0; + + while (i < format.Length) { + int tokLen; + bool omitZeros = false; + char ch = format[i]; + + switch (ch) { + + // + // Time Formats + // + case 'h': + // hour, [1, 12] + tokLen = CountRepeat(format, i, ch); + + int hr = this.Hour % 12; + if (hr == 0) + hr = 12; + + ZeroPad(result, hr, tokLen == 1 ? 1 : 2); + break; + case 'H': + // hour, [0, 23] + tokLen = CountRepeat(format, i, ch); + ZeroPad(result, this.Hour, tokLen == 1 ? 1 : 2); + break; + case 'm': + // minute, [0, 59] + tokLen = CountRepeat(format, i, ch); + ZeroPad(result, this.Minute, tokLen == 1 ? 1 : 2); + break; + case 's': + // second [0, 29] + tokLen = CountRepeat(format, i, ch); + ZeroPad(result, this.Second, tokLen == 1 ? 1 : 2); + break; + case 'F': + omitZeros = true; + goto case 'f'; + case 'f': + // fraction of second, to same number of + // digits as there are f's + + tokLen = CountRepeat(format, i, ch); + if (tokLen > 7) + throw new FormatException("Invalid Format String"); + + int dec = (int)((long)(this.Ticks % TimeSpan.TicksPerSecond) / (long)Math.Pow(10, 7 - tokLen)); + int startLen = result.Length; + ZeroPad(result, dec, tokLen); + + if (omitZeros) { + while (result.Length > startLen && result[result.Length - 1] == '0') + result.Length--; + // when the value was 0, then trim even preceding '.' (!) It is fixed character. + if (dec == 0 && startLen > 0 && result[startLen - 1] == '.') + result.Length--; + } + + break; + case 't': + // AM/PM. t == first char, tt+ == full + tokLen = CountRepeat(format, i, ch); + string desig = this.Hour < 12 ? dfi.AMDesignator : dfi.PMDesignator; + + if (tokLen == 1) { + if (desig.Length >= 1) + result.Append(desig[0]); + } else + result.Append(desig); + + break; + case 'z': + // timezone. t = +/-h; tt = +/-hh; ttt+=+/-hh:mm + tokLen = CountRepeat(format, i, ch); + throw new NotImplementedException("TimeZone not supported"); + /*TimeSpan offset = TimeZone.CurrentTimeZone.GetUtcOffset(this); + + if (offset.Ticks >= 0) + result.Append('+'); + else + result.Append('-'); + + switch (tokLen) { + case 1: + result.Append(Math.Abs(offset.Hours)); + break; + case 2: + result.Append(Math.Abs(offset.Hours).ToString("00")); + break; + default: + result.Append(Math.Abs(offset.Hours).ToString("00")); + result.Append(':'); + result.Append(Math.Abs(offset.Minutes).ToString("00")); + break; + } + break;*/ + case 'K': // 'Z' (UTC) or zzz (Local) + tokLen = 1; + switch (kind) { + case DateTimeKind.Utc: + result.Append ('Z'); + break; + case DateTimeKind.Local: + throw new NotImplementedException("TimeZone not supported"); + /*offset = TimeZone.CurrentTimeZone.GetUtcOffset (this); + if (offset.Ticks >= 0) + result.Append ('+'); + else + result.Append ('-'); + result.Append (Math.Abs (offset.Hours).ToString ("00")); + result.Append (':'); + result.Append (Math.Abs (offset.Minutes).ToString ("00")); + break;*/ + } + break; + // + // Date tokens + // + case 'd': + // day. d(d?) = day of month (leading 0 if two d's) + // ddd = three leter day of week + // dddd+ full day-of-week + tokLen = CountRepeat(format, i, ch); + + if (tokLen <= 2) + ZeroPad(result, dfi.Calendar.GetDayOfMonth(this), tokLen == 1 ? 1 : 2); + else if (tokLen == 3) + result.Append(dfi.GetAbbreviatedDayName(dfi.Calendar.GetDayOfWeek(this))); + else + result.Append(dfi.GetDayName(dfi.Calendar.GetDayOfWeek(this))); + + break; + case 'M': + // Month.m(m?) = month # (with leading 0 if two mm) + // mmm = 3 letter name + // mmmm+ = full name + tokLen = CountRepeat(format, i, ch); + int month = dfi.Calendar.GetMonth(this); + if (tokLen <= 2) + ZeroPad(result, month, tokLen); + else if (tokLen == 3) + result.Append(dfi.GetAbbreviatedMonthName(month)); + else + result.Append(dfi.GetMonthName(month)); + + break; + case 'y': + // Year. y(y?) = two digit year, with leading 0 if yy + // yyy+ full year, if yyy and yr < 1000, displayed as three digits + tokLen = CountRepeat(format, i, ch); + + if (tokLen <= 2) + ZeroPad(result, dfi.Calendar.GetYear(this) % 100, tokLen); + else + ZeroPad(result, dfi.Calendar.GetYear(this), (tokLen == 3 ? 3 : 4)); + + break; + case 'g': + // Era name + tokLen = CountRepeat(format, i, ch); + result.Append(dfi.GetEraName(dfi.Calendar.GetEra(this))); + break; + + // + // Other + // + case ':': + result.Append(dfi.TimeSeparator); + tokLen = 1; + break; + case '/': + result.Append(dfi.DateSeparator); + tokLen = 1; + break; + case '\'': + case '"': + tokLen = ParseQuotedString(format, i, result); + break; + case '%': + if (i >= format.Length - 1) + throw new FormatException("% at end of date time string"); + if (format[i + 1] == '%') + throw new FormatException("%% in date string"); + + // Look for the next char + tokLen = 1; + break; + case '\\': + // C-Style escape + if (i >= format.Length - 1) + throw new FormatException("\\ at end of date time string"); + + result.Append(format[i + 1]); + tokLen = 2; + + break; + default: + // catch all + result.Append(ch); + tokLen = 1; + break; + } + i += tokLen; + } + return result.ToString(); + } + + private static int CountRepeat(string fmt, int p, char c) { + int l = fmt.Length; + int i = p + 1; + while ((i < l) && (fmt[i] == c)) + i++; + + return i - p; + } + + private static void ZeroPad(StringBuilder output, int digits, int len) { + char[] buffer = new char[16]; + int pos = 16; + + do { + buffer[--pos] = (char)('0' + digits % 10); + digits /= 10; + len--; + } while (digits > 0); + + while (len-- > 0) { + buffer[--pos] = '0'; + } + + output.Append(buffer, pos, 16 - pos); + } + + private static int ParseQuotedString(string fmt, int pos, StringBuilder output) { + // pos == position of " or ' + + int len = fmt.Length; + int start = pos; + char quoteChar = fmt[pos++]; + + while (pos < len) { + char ch = fmt[pos++]; + + if (ch == quoteChar) + return pos - start; + + if (ch == '\\') { + // C-Style escape + if (pos >= len) + throw new FormatException("Un-ended quote"); + + output.Append(fmt[pos++]); + } else { + output.Append(ch); + } + } + + throw new FormatException("Un-ended quote"); + } + + private static string GetStandardPattern(char format, DateTimeFormatInfo dfi, out bool useUtc, out bool useInvariant) { + String pattern; + + useUtc = false; + useInvariant = false; + + switch (format) { + case 'd': + pattern = dfi.ShortDatePattern; + break; + case 'D': + pattern = dfi.LongDatePattern; + break; + case 'f': + pattern = dfi.LongDatePattern + " " + dfi.ShortTimePattern; + break; + case 'F': + pattern = dfi.FullDateTimePattern; + break; + case 'g': + pattern = dfi.ShortDatePattern + " " + dfi.ShortTimePattern; + break; + case 'G': + pattern = dfi.ShortDatePattern + " " + dfi.LongTimePattern; + break; + case 'm': + case 'M': + pattern = dfi.MonthDayPattern; + break; +#if NET_2_0 + case 'o': + pattern = dfi.RoundtripPattern; + break; +#endif + case 'r': + case 'R': + pattern = dfi.RFC1123Pattern; + // commented by LP 09/jun/2002, rfc 1123 pattern is always in GMT + // uncommented by AE 27/may/2004 + // useutc = true; + useInvariant = true; + break; + case 's': + pattern = dfi.SortableDateTimePattern; + break; + case 't': + pattern = dfi.ShortTimePattern; + break; + case 'T': + pattern = dfi.LongTimePattern; + break; + case 'u': + pattern = dfi.UniversalSortableDateTimePattern; + useUtc = true; + break; + case 'U': + // pattern = dfi.LongDatePattern + " " + dfi.LongTimePattern; + pattern = dfi.FullDateTimePattern; + useUtc = true; + break; + case 'y': + case 'Y': + pattern = dfi.YearMonthPattern; + break; + default: + pattern = null; + break; + // throw new FormatException (String.Format ("Invalid format pattern: '{0}'", format)); + } + + return pattern; + } + + #endregion + + #endregion + + #region IComparable Members + + public int CompareTo(object obj) { + if (obj == null) { + return 1; + } + if (!(obj is DateTime)) { + throw new ArgumentException(); + } + return this.CompareTo((DateTime)obj); + } + + #endregion + + #region IComparable Members + + public int CompareTo(DateTime x) { + return this.ticks.CompareTo(x.ticks); + } + + #endregion + + #region IEquatable Members + + public bool Equals(DateTime x) { + return this.ticks.Equals(x.ticks); + } + + #endregion + } +} + +#endif diff --git a/corlib/System/DateTimeKind.cs b/corlib/System/DateTimeKind.cs new file mode 100644 index 0000000..c3de5f7 --- /dev/null +++ b/corlib/System/DateTimeKind.cs @@ -0,0 +1,11 @@ +#if !LOCALTEST + +namespace System { + public enum DateTimeKind { + Unspecified, + Utc, + Local + } +} + +#endif diff --git a/corlib/System/DayOfWeek.cs b/corlib/System/DayOfWeek.cs new file mode 100644 index 0000000..3f4c0c6 --- /dev/null +++ b/corlib/System/DayOfWeek.cs @@ -0,0 +1,15 @@ +#if !LOCALTEST + +namespace System { + public enum DayOfWeek { + Sunday, + Monday, + Tuesday, + Wednesday, + Thursday, + Friday, + Saturday + } +} + +#endif diff --git a/corlib/System/Decimal.cs b/corlib/System/Decimal.cs new file mode 100644 index 0000000..c92e74e --- /dev/null +++ b/corlib/System/Decimal.cs @@ -0,0 +1,19 @@ +#if !LOCALTEST + +namespace System { + public struct Decimal { + + // internal representation of decimal + private uint flags; + private uint hi; + private uint lo; + private uint mid; + + public static int[] GetBits(Decimal d) { + return new int[] { 0, 0, 0, 0 }; + } + + } +} + +#endif \ No newline at end of file diff --git a/corlib/System/Delegate.cs b/corlib/System/Delegate.cs new file mode 100644 index 0000000..bd1f549 --- /dev/null +++ b/corlib/System/Delegate.cs @@ -0,0 +1,62 @@ +#if !LOCALTEST + +namespace System { + public abstract class Delegate { + + // These must be the same as defined in the interpreter + // If/when reflection is implemented, this IntPtr may change to MethodInfo + private object targetObj = null; + private IntPtr targetMethod = IntPtr.Zero; + protected Delegate pNext = null; + + public override bool Equals(object obj) { + Delegate d = obj as Delegate; + if (d == null) { + return false; + } + return d.targetObj == this.targetObj && d.targetMethod.Equals(this.targetMethod); + } + + public override int GetHashCode() { + int ret = targetMethod.GetHashCode(); + if (targetObj != null) { + ret ^= targetObj.GetHashCode(); + } + return ret; + } + + public static Delegate Combine(Delegate a, Delegate b) { + if (a == null) { + return b; + } else if (b == null) { + return a; + } + + if (a.GetType() != b.GetType()) { + throw new ArgumentException("Incompatible delegate types"); + } + + return a.CombineImpl(b); + } + + protected virtual Delegate CombineImpl(Delegate d) { + throw new MulticastNotSupportedException(); + } + + public static Delegate Remove(Delegate source, Delegate value) { + if (source == null) { + return null; + } + return source.RemoveImpl(value); + } + + protected virtual Delegate RemoveImpl(Delegate d) { + if (d.Equals(this)) { + return null; + } + return this; + } + } +} + +#endif \ No newline at end of file diff --git a/corlib/System/Double.cs b/corlib/System/Double.cs new file mode 100644 index 0000000..fa1c957 --- /dev/null +++ b/corlib/System/Double.cs @@ -0,0 +1,108 @@ +#if !LOCALTEST + +using System.Globalization; +namespace System { + public struct Double : IFormattable, IComparable, IComparable, IEquatable { + + public const double Epsilon = 4.9406564584124650e-324; + public const double MaxValue = 1.7976931348623157e308; + public const double MinValue = -1.7976931348623157e308; + public const double NaN = 0.0d / 0.0d; + public const double NegativeInfinity = -1.0d / 0.0d; + public const double PositiveInfinity = 1.0d / 0.0d; + + internal double m_value; + + public static bool IsNaN(double d) { +#pragma warning disable 1718 + return d != d; +#pragma warning restore + } + + public static bool IsNegativeInfinity(double d) { + return (d < 0.0d && (d == NegativeInfinity || d == PositiveInfinity)); + } + + public static bool IsPositiveInfinity(double d) { + return (d > 0.0d && (d == NegativeInfinity || d == PositiveInfinity)); + } + + public static bool IsInfinity(double d) { + return (d == PositiveInfinity || d == NegativeInfinity); + } + + public override bool Equals(object o) { + if (!(o is System.Double)) { + return false; + } + if (IsNaN((double)o)) { + return IsNaN(this.m_value); + } + return ((double)o) == this.m_value; + } + + public override unsafe int GetHashCode() { + double d = m_value; + return (*((long*)&d)).GetHashCode(); + } + + public override string ToString() { + return ToString(null, null); + } + + public string ToString(IFormatProvider fp) { + return ToString(null, fp); + } + + public string ToString(string format) { + return ToString(format, null); + } + + public string ToString(string format, IFormatProvider fp) { + NumberFormatInfo nfi = NumberFormatInfo.GetInstance(fp); + return NumberFormatter.NumberToString(format, this.m_value, nfi); + } + + #region IComparable Members + + public int CompareTo(object obj) { + if (obj == null) { + return 1; + } + if (!(obj is double)) { + throw new ArgumentException(); + } + return this.CompareTo((double)obj); + } + + #endregion + + #region IComparable Members + + public int CompareTo(double x) { + if (double.IsNaN(this.m_value)) { + return double.IsNaN(x) ? 0 : -1; + } + if (double.IsNaN(x)) { + return 1; + } + return (this.m_value > x) ? 1 : ((this.m_value < x) ? -1 : 0); + } + + #endregion + + #region IEquatable Members + + public bool Equals(double x) { + if (double.IsNaN(this.m_value)) { + return double.IsNaN(x); + } + return this.m_value == x; + } + + #endregion + + } +} + +#endif diff --git a/corlib/System/Enum.cs b/corlib/System/Enum.cs new file mode 100644 index 0000000..a7d2f24 --- /dev/null +++ b/corlib/System/Enum.cs @@ -0,0 +1,114 @@ +#if !LOCALTEST + +using System; +using System.Runtime.CompilerServices; +using System.Collections.Generic; +using System.Text; + +namespace System { + public abstract class Enum : ValueType { + + [MethodImpl(MethodImplOptions.InternalCall)] + extern static private void Internal_GetInfo(Type enumType, out string[] names, out int[] values); + + private static Dictionary cache = new Dictionary(); + + public static string[] GetNames(Type enumType) { + if (enumType == null) { + throw new ArgumentNullException(); + } + if (!enumType.IsEnum) { + throw new ArgumentException(); + } + EnumInfo info = EnumInfo.GetInfo(enumType); + return info.GetNames(); + } + + private struct EnumInfo { + private string[] names; + private int[] values; + + public static EnumInfo GetInfo(Type enumType) { + lock (cache) { + EnumInfo info; + if (!Enum.cache.TryGetValue(enumType, out info)) { + info = new EnumInfo(); + Enum.Internal_GetInfo(enumType, out info.names, out info.values); + Enum.cache.Add(enumType, info); + } + return info; + } + } + + public string GetName(int value) { + int valuesLen = values.Length; + for (int i = 0; i < valuesLen; i++) { + if (this.values[i] == value) { + return this.names[i]; + } + } + // Pretend it's got the [Flags] attribute, so look for bits set. + // TODO Sort out Flags attribute properly + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < valuesLen; i++) { + int thisValue = this.values[i]; + if ((value & thisValue) == thisValue) { + sb.Append(this.names[i]); + sb.Append(", "); + } + } + if (sb.Length > 0) { + return sb.ToString(0, sb.Length - 2); + } + return null; + } + + public string[] GetNames() { + List names = new List(); + for (int i = 0; i < this.values.Length; i++) { + names.Add(this.GetName(this.values[i])); + } + return names.ToArray(); + } + + } + + protected Enum() { } + + [MethodImpl(MethodImplOptions.InternalCall)] + extern private int Internal_GetValue(); + + public static string GetName(Type enumType, object value) { + if (enumType == null || value == null) { + throw new ArgumentNullException(); + } + if (!enumType.IsEnum) { + throw new ArgumentException("enumType is not an Enum type."); + } + EnumInfo info = EnumInfo.GetInfo(enumType); + return info.GetName((int)value); + } + + public static string Format(Type enumType, object value, string format) { + if (enumType == null || value == null || format == null) { + throw new ArgumentNullException("enumType"); + } + if (!enumType.IsEnum) { + throw new ArgumentException("Type provided must be an Enum."); + } + string ret = GetName(enumType, value); + if (ret == null) { + return value.ToString(); + } else { + return ret; + } + } + + public override string ToString() { + return Format(this.GetType(), this.Internal_GetValue(), "G"); + } + + } +} + +#endif diff --git a/corlib/System/Environment.cs b/corlib/System/Environment.cs new file mode 100644 index 0000000..1438fd4 --- /dev/null +++ b/corlib/System/Environment.cs @@ -0,0 +1,55 @@ +#if !LOCALTEST + +using System.Runtime.CompilerServices; +using System.IO; +namespace System { + public static class Environment { + + public static string NewLine { + get { + return (Platform == PlatformID.Unix) ? "\n" : "\r\n"; + } + } + + extern public static int TickCount { + [MethodImpl(MethodImplOptions.InternalCall)] + get; + } + + internal static string CultureDirectory { + get { + return string.Format(".{0}Cultures", Path.DirectorySeparatorStr); + } + } + + private static OperatingSystem os = null; + + internal static extern PlatformID Platform { + [MethodImplAttribute(MethodImplOptions.InternalCall)] + get; + } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern string GetOSVersionString(); + + public static OperatingSystem OSVersion { + get { + if (os == null) { + Version v = Version.CreateFromString(GetOSVersionString()); + PlatformID p = Platform; + os = new OperatingSystem(p, v); + } + return os; + } + } + + internal static bool IsRunningOnWindows { + get { + return Platform != PlatformID.Unix; + } + } + + } +} + +#endif diff --git a/corlib/System/Exception.cs b/corlib/System/Exception.cs new file mode 100644 index 0000000..7930a18 --- /dev/null +++ b/corlib/System/Exception.cs @@ -0,0 +1,44 @@ +#if !LOCALTEST + +namespace System { + public class Exception { + + private Exception innerException; + private string message; + private int hresult = unchecked((int)0x80004005); + + public Exception() { } + + public Exception(string message) { + this.message = message; + } + + public Exception(string message, Exception innerException) { + this.innerException = innerException; + this.message = message; + } + + public virtual string Message { + get { + return message; + } + } + + public Exception InnerException { + get { + return innerException; + } + } + + protected int HResult { + get { return hresult; } + set { hresult = value; } + } + + public override string ToString() { + return Message ?? string.Empty; + } + } +} + +#endif \ No newline at end of file diff --git a/corlib/System/FlagsAttribute.cs b/corlib/System/FlagsAttribute.cs new file mode 100644 index 0000000..e16404d --- /dev/null +++ b/corlib/System/FlagsAttribute.cs @@ -0,0 +1,11 @@ +#if !LOCALTEST + +namespace System { + + [AttributeUsage(AttributeTargets.Enum, Inherited=false)] + public sealed class FlagsAttribute : Attribute { + } + +} + +#endif diff --git a/corlib/System/FormatException.cs b/corlib/System/FormatException.cs new file mode 100644 index 0000000..0ce548f --- /dev/null +++ b/corlib/System/FormatException.cs @@ -0,0 +1,10 @@ +#if !LOCALTEST + +namespace System { + public class FormatException : SystemException { + public FormatException() : base("Invalid Format.") { } + public FormatException(string msg) : base(msg) { } + } +} + +#endif diff --git a/corlib/System/GC.cs b/corlib/System/GC.cs new file mode 100644 index 0000000..f14b7db --- /dev/null +++ b/corlib/System/GC.cs @@ -0,0 +1,59 @@ +#if !LOCALTEST + +using System.Runtime.CompilerServices; +namespace System { + public static class GC { + + public static int MaxGeneration { + get { + return 2; + } + } + + [MethodImpl(MethodImplOptions.InternalCall)] + extern private static int Internal_CollectionCount(); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public static void Collect(); + + public static void Collect(int generation) { + if (generation < 0) { + throw new ArgumentOutOfRangeException("generation"); + } + Collect(); + } + + public static int CollectionCount(int generation) { + if (generation < 0) { + throw new ArgumentOutOfRangeException("generation"); + } + if (generation != 0) { + return 0; + } + return Internal_CollectionCount(); + } + + public static int GetGeneration(object obj) { + if (obj == null) { + throw new NullReferenceException(); + } + return 0; + } + + public static int GetGeneration(WeakReference wr) { + if (wr == null || !wr.IsAlive) { + throw new NullReferenceException(); + } + return 0; + } + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public static long GetTotalMemory(bool forceFullCollection); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public static void SuppressFinalize(object obj); + + } +} + +#endif diff --git a/corlib/System/IAsyncResult.cs b/corlib/System/IAsyncResult.cs new file mode 100644 index 0000000..29c5c6e --- /dev/null +++ b/corlib/System/IAsyncResult.cs @@ -0,0 +1,16 @@ +#if !LOCALTEST + +using System.Threading; + +namespace System { + public interface IAsyncResult { + + object AsyncState { get;} + WaitHandle AsyncWaitHandle { get; } + bool CompletedSynchronously { get; } + bool IsCompleted { get; } + + } +} + +#endif diff --git a/corlib/System/ICloneable.cs b/corlib/System/ICloneable.cs new file mode 100644 index 0000000..b1424ac --- /dev/null +++ b/corlib/System/ICloneable.cs @@ -0,0 +1,11 @@ +#if !LOCALTEST + +namespace System { + public interface ICloneable { + + object Clone(); + + } +} + +#endif diff --git a/corlib/System/IComparable.cs b/corlib/System/IComparable.cs new file mode 100644 index 0000000..c063692 --- /dev/null +++ b/corlib/System/IComparable.cs @@ -0,0 +1,15 @@ +#if !LOCALTEST + +namespace System { + + public interface IComparable { + int CompareTo(object obj); + } + + public interface IComparable { + int CompareTo(T x); + } + +} + +#endif \ No newline at end of file diff --git a/corlib/System/ICustomFormatter.cs b/corlib/System/ICustomFormatter.cs new file mode 100644 index 0000000..893524c --- /dev/null +++ b/corlib/System/ICustomFormatter.cs @@ -0,0 +1,11 @@ +#if !LOCALTEST + +namespace System { + public interface ICustomFormatter { + + string Format(string format, object arg, IFormatProvider formatProvider); + + } +} + +#endif diff --git a/corlib/System/IDisposable.cs b/corlib/System/IDisposable.cs new file mode 100644 index 0000000..2e1093b --- /dev/null +++ b/corlib/System/IDisposable.cs @@ -0,0 +1,9 @@ +#if !LOCALTEST + +namespace System { + public interface IDisposable { + void Dispose(); + } +} + +#endif diff --git a/corlib/System/IEquatable.cs b/corlib/System/IEquatable.cs new file mode 100644 index 0000000..9c90fa3 --- /dev/null +++ b/corlib/System/IEquatable.cs @@ -0,0 +1,11 @@ +#if !LOCALTEST + +namespace System { + + public interface IEquatable { + bool Equals(T x); + } + +} + +#endif diff --git a/corlib/System/IFormatProvider.cs b/corlib/System/IFormatProvider.cs new file mode 100644 index 0000000..28140c2 --- /dev/null +++ b/corlib/System/IFormatProvider.cs @@ -0,0 +1,13 @@ +#if !LOCALTEST + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System { + public interface IFormatProvider { + object GetFormat(Type formatType); + } +} + +#endif diff --git a/corlib/System/IFormattable.cs b/corlib/System/IFormattable.cs new file mode 100644 index 0000000..eede1c4 --- /dev/null +++ b/corlib/System/IFormattable.cs @@ -0,0 +1,11 @@ +#if !LOCALTEST + +namespace System { + public interface IFormattable { + + string ToString(string format, IFormatProvider formatProvider); + + } +} + +#endif diff --git a/corlib/System/IndexOutOfRangeException.cs b/corlib/System/IndexOutOfRangeException.cs new file mode 100644 index 0000000..17ef2b0 --- /dev/null +++ b/corlib/System/IndexOutOfRangeException.cs @@ -0,0 +1,17 @@ +#if !LOCALTEST + +namespace System { + public class IndexOutOfRangeException : SystemException { + + public IndexOutOfRangeException() : base("Array index is out of range.") { } + + public IndexOutOfRangeException(string message) : base(message) { } + + public IndexOutOfRangeException(string message, Exception innerException) + : base(message, innerException) { + } + + } +} + +#endif diff --git a/corlib/System/Int16.cs b/corlib/System/Int16.cs new file mode 100644 index 0000000..ca4a67d --- /dev/null +++ b/corlib/System/Int16.cs @@ -0,0 +1,69 @@ +#if !LOCALTEST + +using System.Globalization; +namespace System { + public struct Int16 : IFormattable, IComparable, IComparable, IEquatable { + public const short MaxValue = 0x7fff; + public const short MinValue = -32768; + + internal short m_value; + + public override bool Equals(object obj) { + return (obj is short) && ((short)obj).m_value == this.m_value; + } + + public override int GetHashCode() { + return (int)this.m_value; + } + + public override string ToString() { + return NumberFormatter.FormatGeneral(new NumberFormatter.NumberStore(this.m_value)); + } + + public string ToString(IFormatProvider formatProvider) { + return NumberFormatter.FormatGeneral(new NumberFormatter.NumberStore(this.m_value), formatProvider); + } + + public string ToString(string format) { + return ToString(format, null); + } + + public string ToString(string format, IFormatProvider formatProvider) { + NumberFormatInfo nfi = NumberFormatInfo.GetInstance(formatProvider); + return NumberFormatter.NumberToString(format, m_value, nfi); + } + + #region IComparable Members + + public int CompareTo(object obj) { + if (obj == null) { + return 1; + } + if (!(obj is short)) { + throw new ArgumentException(); + } + return this.CompareTo((short)obj); + } + + #endregion + + #region IComparable Members + + public int CompareTo(short x) { + return (this.m_value > x) ? 1 : ((this.m_value < x) ? -1 : 0); + } + + #endregion + + #region IEquatable Members + + public bool Equals(short x) { + return this.m_value == x; + } + + #endregion + + } +} + +#endif diff --git a/corlib/System/Int32.cs b/corlib/System/Int32.cs new file mode 100644 index 0000000..428d19b --- /dev/null +++ b/corlib/System/Int32.cs @@ -0,0 +1,110 @@ +#if !LOCALTEST + +using System.Runtime.CompilerServices; +using System.Globalization; +using System.Threading; + +namespace System { + public struct Int32 : IFormattable, IComparable, IComparable,IEquatable { + public const int MaxValue = 0x7fffffff; + public const int MinValue = -2147483648; + + internal int m_value; + + public override bool Equals(object obj) { + return (obj is int && ((int)obj).m_value == this.m_value); + } + + public override int GetHashCode() { + return this.m_value; + } + + #region Parse methods + + public static int Parse(string s) { + return Parse(s, NumberStyles.Integer, null); + } + + public static int Parse(string s, NumberStyles style) { + return Parse(s, style, null); + } + + public static int Parse(string s, IFormatProvider formatProvider) { + return Parse(s, NumberStyles.Integer, formatProvider); + } + + public static int Parse(string s, NumberStyles style, IFormatProvider formatProvider) { + Exception e; + int res; + if (!ParseHelper.Parse(s, style, formatProvider, false, out res, out e)) { + throw e; + } + return res; + } + + public static bool TryParse(string s, out int result) { + return TryParse(s, NumberStyles.Integer, null, out result); + } + + public static bool TryParse(string s, NumberStyles style,IFormatProvider format, out int result) { + Exception e; + return ParseHelper.Parse(s, style, format, true, out result, out e); + } + + #endregion + + #region ToString methods + + public override string ToString() { + return NumberFormatter.FormatGeneral(new NumberFormatter.NumberStore(this.m_value)); + } + + public string ToString(IFormatProvider formatProvider) { + return NumberFormatter.FormatGeneral(new NumberFormatter.NumberStore(this.m_value), formatProvider); + } + + public string ToString(string format) { + return this.ToString(format, null); + } + + public string ToString(string format, IFormatProvider formatProvider) { + NumberFormatInfo nfi = NumberFormatInfo.GetInstance(formatProvider); + return NumberFormatter.NumberToString(format, this.m_value, nfi); + } + + #endregion + + #region IComparable Members + + public int CompareTo(object obj) { + if (obj == null) { + return 1; + } + if (!(obj is int)){ + throw new ArgumentException(); + } + return this.CompareTo((int)obj); + } + + #endregion + + #region IComparable Members + + public int CompareTo(int x) { + return (this.m_value > x) ? 1 : ((this.m_value < x) ? -1 : 0); + } + + #endregion + + #region IEquatable Members + + public bool Equals(int x) { + return this.m_value == x; + } + + #endregion + + } +} + +#endif diff --git a/corlib/System/Int64.cs b/corlib/System/Int64.cs new file mode 100644 index 0000000..c697561 --- /dev/null +++ b/corlib/System/Int64.cs @@ -0,0 +1,70 @@ +#if !LOCALTEST + +using System.Runtime.CompilerServices; +using System.Globalization; +namespace System { + public struct Int64 : IFormattable, IComparable, IComparable, IEquatable { + public const long MaxValue = 0x7fffffffffffffff; + public const long MinValue = unchecked((long)0x8000000000000000); + + private long m_value; + + public override bool Equals(object o) { + return (o is long) && ((long)o).m_value == this.m_value; + } + + public override int GetHashCode() { + return (int)(m_value & 0xffffffff) ^ (int)(m_value >> 32); + } + + public override string ToString() { + return NumberFormatter.FormatGeneral(new NumberFormatter.NumberStore(this.m_value)); + } + + public string ToString(IFormatProvider formatProvider) { + return NumberFormatter.FormatGeneral(new NumberFormatter.NumberStore(this.m_value), formatProvider); + } + + public string ToString(string format) { + return ToString(format, null); + } + + public string ToString(string format, IFormatProvider formatProvider) { + NumberFormatInfo nfi = NumberFormatInfo.GetInstance(formatProvider); + return NumberFormatter.NumberToString(format, m_value, nfi); + } + + #region IComparable Members + + public int CompareTo(object obj) { + if (obj == null) { + return 1; + } + if (!(obj is long)) { + throw new ArgumentException(); + } + return this.CompareTo((long)obj); + } + + #endregion + + #region IComparable Members + + public int CompareTo(long x) { + return (this.m_value > x) ? 1 : ((this.m_value < x) ? -1 : 0); + } + + #endregion + + #region IEquatable Members + + public bool Equals(long x) { + return this.m_value == x; + } + + #endregion + + } +} + +#endif diff --git a/corlib/System/IntPtr.cs b/corlib/System/IntPtr.cs new file mode 100644 index 0000000..70c20bb --- /dev/null +++ b/corlib/System/IntPtr.cs @@ -0,0 +1,62 @@ +#if !LOCALTEST + +namespace System { + public unsafe struct IntPtr { + + public static readonly IntPtr Zero = new IntPtr(0); + + private void* value; + + public IntPtr(int value) { + this.value = (void*)value; + } + + public IntPtr(long value) { + this.value = (void*)value; + } + + public IntPtr(void* value) { + this.value = value; + } + + public static int Size { + get { + return sizeof(void*); + } + } + + public int ToInt32() { + return (int)this.value; + } + + public long ToInt64() { + return (long)this.value; + } + + public override bool Equals(object obj) { + return (obj is IntPtr && ((IntPtr)obj).value == this.value); + } + + public override int GetHashCode() { + return (int)this.value; + } + + public static bool operator ==(IntPtr a, IntPtr b) { + return a.value == b.value; + } + + public static bool operator !=(IntPtr a, IntPtr b) { + return a.value != b.value; + } + + public override string ToString() { + if (Size == 4) { + return string.Format("0x{0:x4}", (int)this.value); + } else { + return string.Format("0x{0:x8}", (long)this.value); + } + } + } +} + +#endif diff --git a/corlib/System/InvalidCastException.cs b/corlib/System/InvalidCastException.cs new file mode 100644 index 0000000..05dacb7 --- /dev/null +++ b/corlib/System/InvalidCastException.cs @@ -0,0 +1,7 @@ +namespace System { + public class InvalidCastException : SystemException { + + public InvalidCastException() : base("An invalid cast has occured") { } + + } +} diff --git a/corlib/System/InvalidOperationException.cs b/corlib/System/InvalidOperationException.cs new file mode 100644 index 0000000..e1c2dcf --- /dev/null +++ b/corlib/System/InvalidOperationException.cs @@ -0,0 +1,13 @@ +namespace System { + public class InvalidOperationException : SystemException { + + public InvalidOperationException() + : base("Operation is not valid due to the current state of the object") { } + + public InvalidOperationException(string message) : base(message) { } + + public InvalidOperationException(string message, Exception innerException) + : base(message, innerException) { } + + } +} diff --git a/corlib/System/MarshalByRefObject.cs b/corlib/System/MarshalByRefObject.cs new file mode 100644 index 0000000..138b106 --- /dev/null +++ b/corlib/System/MarshalByRefObject.cs @@ -0,0 +1,8 @@ +#if !LOCALTEST + +namespace System { + public abstract class MarshalByRefObject { + } +} + +#endif diff --git a/corlib/System/Math.cs b/corlib/System/Math.cs new file mode 100644 index 0000000..e864cf0 --- /dev/null +++ b/corlib/System/Math.cs @@ -0,0 +1,203 @@ +using System.Runtime.CompilerServices; + +#if LOCALTEST +using System; +namespace System_ { +#else +namespace System { +#endif + public static class Math { + + public const double E = 2.7182818284590452354; + public const double PI = 3.14159265358979323846; + + #region Abs() + + public static sbyte Abs(sbyte v) { + if (v == sbyte.MinValue) { + throw new OverflowException("Value is too small"); + } + return (v >= 0) ? v : (sbyte)-v; + } + + public static short Abs(short v) { + if (v == short.MinValue) { + throw new OverflowException("Value is too small"); + } + return (v >= 0) ? v : (short)-v; + } + + public static int Abs(int v) { + if (v == int.MinValue) { + throw new OverflowException("Value is too small"); + } + return (v >= 0) ? v : -v; + } + + public static long Abs(long v) { + if (v == long.MinValue) { + throw new OverflowException("Value is too small"); + } + return (v >= 0) ? v : -v; + } + + public static float Abs(float v) { + return (v >= 0) ? v : -v; + } + + public static double Abs(double v) { + return (v >= 0) ? v : -v; + } + + #endregion + + #region Min() + + public static sbyte Min(sbyte v1, sbyte v2) { + return (v1 < v2) ? v1 : v2; + } + + public static short Min(short v1, short v2) { + return (v1 < v2) ? v1 : v2; + } + + public static int Min(int v1, int v2) { + return (v1 < v2) ? v1 : v2; + } + + public static long Min(long v1, long v2) { + return (v1 < v2) ? v1 : v2; + } + + public static byte Min(byte v1, byte v2) { + return (v1 < v2) ? v1 : v2; + } + + public static ushort Min(ushort v1, ushort v2) { + return (v1 < v2) ? v1 : v2; + } + + public static uint Min(uint v1, uint v2) { + return (v1 < v2) ? v1 : v2; + } + + public static ulong Min(ulong v1, ulong v2) { + return (v1 < v2) ? v1 : v2; + } + + public static float Min(float v1, float v2) { + if (float.IsNaN(v1) || float.IsNaN(v2)) { + return float.NaN; + } + return (v1 < v2) ? v1 : v2; + } + + public static double Min(double v1, double v2) { + if (double.IsNaN(v1) || double.IsNaN(v2)) { + return double.NaN; + } + return (v1 < v2) ? v1 : v2; + } + + #endregion + + #region Max() + + public static sbyte Max(sbyte v1, sbyte v2) { + return (v1 > v2) ? v1 : v2; + } + + public static short Max(short v1, short v2) { + return (v1 > v2) ? v1 : v2; + } + + public static int Max(int v1, int v2) { + return (v1 > v2) ? v1 : v2; + } + + public static long Max(long v1, long v2) { + return (v1 > v2) ? v1 : v2; + } + + public static byte Max(byte v1, byte v2) { + return (v1 > v2) ? v1 : v2; + } + + public static ushort Max(ushort v1, ushort v2) { + return (v1 > v2) ? v1 : v2; + } + + public static uint Max(uint v1, uint v2) { + return (v1 > v2) ? v1 : v2; + } + + public static ulong Max(ulong v1, ulong v2) { + return (v1 > v2) ? v1 : v2; + } + + public static float Max(float v1, float v2) { + if (float.IsNaN(v1) || float.IsNaN(v2)) { + return float.NaN; + } + return (v1 > v2) ? v1 : v2; + } + + public static double Max(double v1, double v2) { + if (double.IsNaN(v1) || double.IsNaN(v2)) { + return double.NaN; + } + return (v1 > v2) ? v1 : v2; + } + + #endregion + + #region Sign() + + public static int Sign(sbyte v) { + return (v > 0) ? 1 : ((v < 0) ? -1 : 0); + } + + public static int Sign(short v) { + return (v > 0) ? 1 : ((v < 0) ? -1 : 0); + } + + public static int Sign(int v) { + return (v > 0) ? 1 : ((v < 0) ? -1 : 0); + } + + public static int Sign(long v) { + return (v > 0) ? 1 : ((v < 0) ? -1 : 0); + } + + public static int Sign(float v) { + if (float.IsNaN(v)) { + throw new ArithmeticException("NaN"); + } + return (v > 0) ? 1 : ((v < 0) ? -1 : 0); + } + + public static int Sign(double v) { + if (double.IsNaN(v)) { + throw new ArithmeticException("NaN"); + } + return (v > 0) ? 1 : ((v < 0) ? -1 : 0); + } + + #endregion + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public extern static double Sin(double x); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public extern static double Cos(double x); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public extern static double Tan(double x); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public extern static double Pow(double x, double y); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public extern static double Sqrt(double x); + } +} diff --git a/corlib/System/MulticastDelegate.cs b/corlib/System/MulticastDelegate.cs new file mode 100644 index 0000000..8f08b15 --- /dev/null +++ b/corlib/System/MulticastDelegate.cs @@ -0,0 +1,55 @@ +#if !LOCALTEST + +namespace System { + public abstract class MulticastDelegate : Delegate { + + protected override Delegate CombineImpl(Delegate follow) { + + MulticastDelegate ret = (MulticastDelegate)object.Clone(this); + MulticastDelegate cur = ret; + + // Clone and add all the current delegate(s) + for (MulticastDelegate del = (MulticastDelegate)this.pNext; del != null; del = (MulticastDelegate)del.pNext) { + cur.pNext = (MulticastDelegate)object.Clone(del); + cur = (MulticastDelegate)cur.pNext; + } + + // Add all the following delegate(s) + cur.pNext = (MulticastDelegate)object.Clone(follow); + cur = (MulticastDelegate)cur.pNext; + for (MulticastDelegate del = (MulticastDelegate)((MulticastDelegate)follow).pNext; del != null; del = (MulticastDelegate)del.pNext) { + cur.pNext = (MulticastDelegate)object.Clone(del); + cur = (MulticastDelegate)cur.pNext; + } + cur.pNext = null; + + return ret; + } + + protected override Delegate RemoveImpl(Delegate d) { + + MulticastDelegate ret = null, cur = null; + + for (MulticastDelegate del = this; del != null; del = (MulticastDelegate)del.pNext) { + // Miss out the one we're removing + if (!del.Equals(d)) { + if (ret == null) { + ret = (MulticastDelegate)object.Clone(del); + cur = ret; + } else { + cur.pNext = (MulticastDelegate)object.Clone(del); + cur = (MulticastDelegate)cur.pNext; + } + } + } + if (cur != null) { + cur.pNext = null; + } + + return ret; + } + + } +} + +#endif \ No newline at end of file diff --git a/corlib/System/MulticastNotSupportedException.cs b/corlib/System/MulticastNotSupportedException.cs new file mode 100644 index 0000000..284bf4e --- /dev/null +++ b/corlib/System/MulticastNotSupportedException.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace System { + public class MulticastNotSupportedException : SystemException { + public MulticastNotSupportedException() + : base("This operation cannot be performed with the specified delagates.") { + } + + public MulticastNotSupportedException(string msg) : base(msg) { } + } +} diff --git a/corlib/System/NotImplementedException.cs b/corlib/System/NotImplementedException.cs new file mode 100644 index 0000000..9c40ad0 --- /dev/null +++ b/corlib/System/NotImplementedException.cs @@ -0,0 +1,13 @@ +#if !LOCALTEST + +namespace System { + public class NotImplementedException : SystemException { + public NotImplementedException() : base("The requested feature is not implemented.") { } + + public NotImplementedException(string message) : base(message) { } + + public NotImplementedException(string message, Exception inner) : base(message, inner) { } + } +} + +#endif diff --git a/corlib/System/NotSupportedException.cs b/corlib/System/NotSupportedException.cs new file mode 100644 index 0000000..307d672 --- /dev/null +++ b/corlib/System/NotSupportedException.cs @@ -0,0 +1,15 @@ +#if !LOCALTEST + +namespace System { + public class NotSupportedException : SystemException { + + public NotSupportedException() : base("Operation is not supported.") { } + + public NotSupportedException(string message) : base(message) { } + + public NotSupportedException(string message, Exception innerException) : base(message, innerException) { } + + } +} + +#endif diff --git a/corlib/System/NullReferenceException.cs b/corlib/System/NullReferenceException.cs new file mode 100644 index 0000000..0586a02 --- /dev/null +++ b/corlib/System/NullReferenceException.cs @@ -0,0 +1,14 @@ +#if !LOCALTEST + +namespace System { + public class NullReferenceException : SystemException { + + public NullReferenceException(string msg) : base(msg) { } + + public NullReferenceException() + : base("A null value was found where an object instance was required.") { + } + } +} + +#endif diff --git a/corlib/System/Nullable.cs b/corlib/System/Nullable.cs new file mode 100644 index 0000000..e9b4ccb --- /dev/null +++ b/corlib/System/Nullable.cs @@ -0,0 +1,107 @@ +#if !LOCALTEST + +namespace System { + + public static class Nullable { + public static int Compare(Nullable left, Nullable right) where T : struct { + if (!left.HasValue && !right.HasValue) { + return 0; + } + if (!left.HasValue) { + return -1; + } + if (!right.HasValue) { + return 1; + } + IComparable iComp = left.Value as IComparable; + if (iComp == null) { + throw new ArgumentException("At least one object must implement IComparable"); + } + return iComp.CompareTo(right.Value); + } + + public static bool Equals(Nullable value1, Nullable value2) where T : struct { + return value1.Equals(value2); + } + + public static Type GetUnderlyingType(Type nullableType) { + if (nullableType == null) { + throw new ArgumentNullException("nullableType"); + } + if (nullableType.IsGenericType && nullableType.GetGenericTypeDefinition() == typeof(Nullable<>)) { + return nullableType.GetGenericArguments()[0]; + } else { + return null; + } + } + } + + public struct Nullable where T : struct { + + // Note the order of these must not be changed, as the interpreter assumes this order + private bool hasValue; + private T value; + + public Nullable(T value) { + this.hasValue = true; + this.value = value; + } + + public bool HasValue { + get { + return this.hasValue; + } + } + + public T Value { + get { + if (!this.hasValue) { + throw new InvalidOperationException("Nullable object must have a value"); + } + return this.value; + } + } + + public T GetValueOrDefault() { + return this.GetValueOrDefault(default(T)); + } + + public T GetValueOrDefault(T def) { + return this.hasValue ? this.value : def; + } + + public override bool Equals(object obj) { + if (obj == null) { + return !this.hasValue; + } + Nullable other = obj as Nullable; + if (other != null) { + if (this.hasValue && other.hasValue) { + // The values are value-types, so cannot be null + return this.value.Equals(other.value); + } else { + return this.hasValue == other.hasValue; + } + } + return false; + } + + public override int GetHashCode() { + if (this.hasValue) { + return this.value.GetHashCode(); + } else { + return 0; + } + } + + public override string ToString() { + if (this.hasValue) { + return this.value.ToString(); + } else { + return string.Empty; + } + } + } +} + +#endif diff --git a/corlib/System/NumberFormatter.cs b/corlib/System/NumberFormatter.cs new file mode 100644 index 0000000..1095def --- /dev/null +++ b/corlib/System/NumberFormatter.cs @@ -0,0 +1,2314 @@ +#if !LOCALTEST + +using System.Collections; +using System.Globalization; +using System.Text; + +namespace System { + class NumberFormatter { + static char[] digitLowerTable = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + static char[] digitUpperTable = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + + #region NumberToString + public static string NumberToString(string format, sbyte value, NumberFormatInfo nfi) { + char specifier; + int precision; + bool custom; + ParseBasicFormat(format, out specifier, out precision, out custom); + if (!custom && (specifier == 'x' || specifier == 'X')) + return FormatHexadecimal(value >= 0 ? (ulong)value : (ulong)-value, value >= 0, 1, precision, specifier == 'X'); + return NumberToString(format, new NumberStore(value), nfi, specifier, precision, custom); + } + public static string NumberToString(string format, byte value, NumberFormatInfo nfi) { + char specifier; + int precision; + bool custom; + ParseBasicFormat(format, out specifier, out precision, out custom); + if (!custom && (specifier == 'x' || specifier == 'X')) + return FormatHexadecimal(value, true, 1, precision, specifier == 'X'); + return NumberToString(format, new NumberStore(value), nfi, specifier, precision, custom); + } + public static string NumberToString(string format, ushort value, NumberFormatInfo nfi) { + char specifier; + int precision; + bool custom; + ParseBasicFormat(format, out specifier, out precision, out custom); + if (!custom && (specifier == 'x' || specifier == 'X')) + return FormatHexadecimal(value, true, 2, precision, specifier == 'X'); + return NumberToString(format, new NumberStore(value), nfi, specifier, precision, custom); + } + public static string NumberToString(string format, short value, NumberFormatInfo nfi) { + char specifier; + int precision; + bool custom; + ParseBasicFormat(format, out specifier, out precision, out custom); + if (!custom && (specifier == 'x' || specifier == 'X')) + return FormatHexadecimal(value >= 0 ? (ulong)value : (ulong)-value, value >= 0, 2, precision, specifier == 'X'); + return NumberToString(format, new NumberStore(value), nfi, specifier, precision, custom); + } + public static string NumberToString(string format, uint value, NumberFormatInfo nfi) { + char specifier; + int precision; + bool custom; + ParseBasicFormat(format, out specifier, out precision, out custom); + if (!custom && (specifier == 'x' || specifier == 'X')) + return FormatHexadecimal(value, true, 4, precision, specifier == 'X'); + return NumberToString(format, new NumberStore(value), nfi, specifier, precision, custom); + } + public static string NumberToString(string format, int value, NumberFormatInfo nfi) { + char specifier; + int precision; + bool custom; + ParseBasicFormat(format, out specifier, out precision, out custom); + if (!custom && (specifier == 'x' || specifier == 'X')) + return FormatHexadecimal(value >= 0 ? (ulong)value : (ulong)-(long)value, value >= 0, 4, precision, specifier == 'X'); + return NumberToString(format, new NumberStore(value), nfi, specifier, precision, custom); + } + public static string NumberToString(string format, ulong value, NumberFormatInfo nfi) { + char specifier; + int precision; + bool custom; + ParseBasicFormat(format, out specifier, out precision, out custom); + if (!custom && (specifier == 'x' || specifier == 'X')) + return FormatHexadecimal(value, true, 8, precision, specifier == 'X'); + return NumberToString(format, new NumberStore(value), nfi, specifier, precision, custom); + } + public static string NumberToString(string format, long value, NumberFormatInfo nfi) { + char specifier; + int precision; + bool custom; + ParseBasicFormat(format, out specifier, out precision, out custom); + if (!custom && (specifier == 'x' || specifier == 'X')) + return FormatHexadecimal(value >= 0 ? (ulong)value : (ulong)-value, value >= 0, 8, precision, specifier == 'X'); + return NumberToString(format, new NumberStore(value), nfi, specifier, precision, custom); + } + public static string NumberToString(string format, float value, NumberFormatInfo nfi) { + char specifier; + int precision; + bool custom; + ParseBasicFormat(format, out specifier, out precision, out custom); + if (!custom && (specifier == 'x' || specifier == 'X')) throw new FormatException(); + return NumberToString(format, new NumberStore(value), nfi, specifier, precision, custom); + } + public static string NumberToString(string format, double value, NumberFormatInfo nfi) { + char specifier; + int precision; + bool custom; + ParseBasicFormat(format, out specifier, out precision, out custom); + if (!custom && (specifier == 'x' || specifier == 'X')) throw new FormatException(); + return NumberToString(format, new NumberStore(value), nfi, specifier, precision, custom); + } + public static string NumberToString(string format, decimal value, NumberFormatInfo nfi) { + char specifier; + int precision; + bool custom; + ParseBasicFormat(format, out specifier, out precision, out custom); + if (!custom && (specifier == 'x' || specifier == 'X')) throw new FormatException(); + return NumberToString(format, new NumberStore(value), nfi, specifier, precision, custom); + } + public static string NumberToString(string format, NumberStore ns, NumberFormatInfo nfi, char specifier, int precision, bool custom) { + if (ns.IsNaN) { + return nfi.NaNSymbol; + } + if (ns.IsInfinity) { + if (ns.Positive) + return nfi.PositiveInfinitySymbol; + else + return nfi.NegativeInfinitySymbol; + } + + if (nfi == null) + nfi = NumberFormatInfo.GetInstance(null); + + if (custom) { + if (ns.IsFloatingSource) + ns.RoundEffectiveDigits(ns.DefaultPrecision); + return FormatCustom(format, ns, nfi); + } + + if (ns.IsFloatingSource) { + switch (specifier) { + case 'p': + case 'P': + case 'c': + case 'C': + case 'f': + case 'F': + case 'N': + case 'n': + ns.RoundEffectiveDigits(ns.DefaultPrecision); + break; + case 'g': + case 'G': + if (precision <= 0) + ns.RoundEffectiveDigits(ns.DefaultPrecision, ns.IsBankerApplicable, true); + else + ns.RoundEffectiveDigits(precision); + break; + case 'r': + case 'R': + ns.RoundEffectiveDigits(ns.DefaultMaxPrecision); + break; + default: + if (precision > ns.DefaultPrecision) + ns.RoundEffectiveDigits(precision + 1); + else + ns.RoundEffectiveDigits(ns.DefaultPrecision + 1); + break; + } + } + + switch (specifier) { + case 'c': + case 'C': + return FormatCurrency(ns, precision, nfi); + case 'd': + case 'D': + return FormatDecimal(ns, precision, nfi); + case 'e': + case 'E': + return FormatExponential(ns, precision, nfi, specifier == 'E'); + case 'f': + case 'F': + return FormatFixedPoint(ns, precision, nfi); + case 'g': + case 'G': + if (ns.IsFloatingSource || ns.IsDecimalSource || precision != -1) + return FormatGeneral(ns, precision, nfi, specifier == 'G', false); + return FormatDecimal(ns, precision, nfi); + case 'n': + case 'N': + return FormatNumber(ns, precision, nfi); + case 'p': + case 'P': + return FormatPercent(ns, precision, nfi); + case 'r': + case 'R': + if (ns.IsFloatingSource) { + return FormatGeneral(ns, ns.DefaultPrecision, nfi, true, true); + } else { + throw new FormatException("The specified format cannot be used in this instance"); + } + default: + throw new FormatException("The specified format '" + format + "' is invalid"); + } + } + #endregion + + #region BasicParser + private static void ParseBasicFormat(string format, out char specifier, out int precision, out bool custom) { + if (format == null || format.Length == 0) { + precision = -1; + specifier = 'G'; + custom = false; + return; + } + + precision = -1; + specifier = format[0]; + custom = false; + + if (Char.IsLetter(specifier)) { + if (format.Length == 1) + return; + + bool flag = true; + precision = 0; + for (int i = 1; i < format.Length; i++) { + char c = format[i]; + if (char.IsDigit(c)) { + precision = precision * 10 + (c - '0'); + if (precision > 99) { + flag = false; + break; + } + } else { + flag = false; + break; + } + } + if (flag) + return; + } + + custom = true; + return; + } + + #endregion + + #region Helpers + private static void ZeroTrimEnd(StringBuilder sb) { + ZeroTrimEnd(sb, false); + } + private static void ZeroTrimEnd(StringBuilder sb, bool canEmpty) { + int len = 0; + for (int i = sb.Length - 1; (canEmpty ? i >= 0 : i > 0); i--) { + if (sb[i] != '0') + break; + len++; + } + + if (len > 0) + sb.Remove(sb.Length - len, len); + } + #endregion + + #region Basic + internal static string FormatCurrency(NumberStore ns, int precision, NumberFormatInfo nfi) { + precision = (precision >= 0 ? precision : nfi.CurrencyDecimalDigits); + ns.RoundDecimal(precision); + StringBuilder sb = new StringBuilder(ns.IntegerDigits * 2 + precision * 2 + 16); + bool needNegativeSign = !ns.Positive && !ns.ZeroOnly; + + if (!needNegativeSign) { + switch (nfi.CurrencyPositivePattern) { + case 0: + sb.Append(nfi.CurrencySymbol); + break; + case 2: + sb.Append(nfi.CurrencySymbol); + sb.Append(' '); + break; + } + } else { + switch (nfi.CurrencyNegativePattern) { + case 0: + sb.Append('('); + sb.Append(nfi.CurrencySymbol); + break; + case 1: + sb.Append(nfi.NegativeSign); + sb.Append(nfi.CurrencySymbol); + break; + case 2: + sb.Append(nfi.CurrencySymbol); + sb.Append(nfi.NegativeSign); + break; + case 3: + sb.Append(nfi.CurrencySymbol); + break; + case 4: + sb.Append('('); + break; + case 5: + sb.Append(nfi.NegativeSign); + break; + case 8: + sb.Append(nfi.NegativeSign); + break; + case 9: + sb.Append(nfi.NegativeSign); + sb.Append(nfi.CurrencySymbol); + sb.Append(' '); + break; + case 11: + sb.Append(nfi.CurrencySymbol); + sb.Append(' '); + break; + case 12: + sb.Append(nfi.CurrencySymbol); + sb.Append(' '); + sb.Append(nfi.NegativeSign); + break; + case 14: + sb.Append('('); + sb.Append(nfi.CurrencySymbol); + sb.Append(' '); + break; + case 15: + sb.Append('('); + break; + } + } + + ns.AppendIntegerStringWithGroupSeparator(sb, nfi.CurrencyGroupSizes, nfi.CurrencyGroupSeparator); + + if (precision > 0) { + sb.Append(nfi.CurrencyDecimalSeparator); + ns.AppendDecimalString(precision, sb); + } + + if (!needNegativeSign) { + switch (nfi.CurrencyPositivePattern) { + case 1: + sb.Append(nfi.CurrencySymbol); + break; + case 3: + sb.Append(' '); + sb.Append(nfi.CurrencySymbol); + break; + } + } else { + switch (nfi.CurrencyNegativePattern) { + case 0: + sb.Append(')'); + break; + case 3: + sb.Append(nfi.NegativeSign); + break; + case 4: + sb.Append(nfi.CurrencySymbol); + sb.Append(')'); + break; + case 5: + sb.Append(nfi.CurrencySymbol); + break; + case 6: + sb.Append(nfi.NegativeSign); + sb.Append(nfi.CurrencySymbol); + break; + case 7: + sb.Append(nfi.CurrencySymbol); + sb.Append(nfi.NegativeSign); + break; + case 8: + sb.Append(' '); + sb.Append(nfi.CurrencySymbol); + break; + case 10: + sb.Append(' '); + sb.Append(nfi.CurrencySymbol); + sb.Append(nfi.NegativeSign); + break; + case 11: + sb.Append(nfi.NegativeSign); + break; + case 13: + sb.Append(nfi.NegativeSign); + sb.Append(' '); + sb.Append(nfi.CurrencySymbol); + break; + case 14: + sb.Append(')'); + break; + case 15: + sb.Append(' '); + sb.Append(nfi.CurrencySymbol); + sb.Append(')'); + break; + } + } + + return sb.ToString(); + } + internal static string FormatDecimal(NumberStore ns, int precision, NumberFormatInfo nfi) { + if (ns.IsFloatingSource || ns.IsDecimalSource) + throw new FormatException(); + + precision = precision > 0 ? precision : 1; + precision = ns.IntegerDigits > precision ? ns.IntegerDigits : precision; + + StringBuilder sb = new StringBuilder(precision + nfi.NegativeSign.Length); + + if (!ns.Positive && !ns.CheckZeroOnlyInteger()) { + sb.Append(nfi.NegativeSign); + } + + ns.AppendIntegerString(precision, sb); + + return sb.ToString(); + } + internal static string FormatFixedPoint(NumberStore ns, int precision, NumberFormatInfo nfi) { + precision = precision >= 0 ? precision : nfi.NumberDecimalDigits; + ns.RoundDecimal(precision); + + StringBuilder cb = new StringBuilder(ns.IntegerDigits + precision + nfi.NumberDecimalSeparator.Length); + + if (!ns.Positive && !ns.ZeroOnly) + cb.Append(nfi.NegativeSign); + + ns.AppendIntegerString(ns.IntegerDigits > 0 ? ns.IntegerDigits : 1, cb); + + if (precision > 0) { + cb.Append(nfi.NumberDecimalSeparator); + ns.AppendDecimalString(precision, cb); + } + + return cb.ToString(); + } + + internal static string FormatGeneral(NumberStore ns) { + return FormatGeneral(ns, -1, NumberFormatInfo.CurrentInfo, true, false); + } + internal static string FormatGeneral(NumberStore ns, IFormatProvider provider) { + return FormatGeneral(ns, -1, NumberFormatInfo.GetInstance(provider), true, false); + } + private static string FormatGeneral(NumberStore ns, int precision, NumberFormatInfo nfi, bool upper, bool roundtrip) { + if (ns.ZeroOnly) + return "0"; + + precision = precision > 0 ? precision : ns.DefaultPrecision; + + int exponent = 0; + bool expMode = (ns.IsDecimalSource && precision == ns.DefaultPrecision ? false : (ns.IntegerDigits > precision || ns.DecimalPointPosition <= -4)); + if (expMode) { + while (!(ns.DecimalPointPosition == 1 && ns.GetChar(0) != '0')) { + if (ns.DecimalPointPosition > 1) { + ns.Divide10(1); + exponent++; + } else { + ns.Multiply10(1); + exponent--; + } + } + } + + precision = precision < ns.DefaultPrecision + 2 ? (precision < ns.DefaultMaxPrecision ? precision : ns.DefaultMaxPrecision) : ns.DefaultPrecision + 2; + StringBuilder cb = new StringBuilder(ns.IntegerDigits + precision + 16); + if (expMode) { + if (ns.RoundDecimal(precision - 1)) { + ns.Divide10(1); + exponent++; + } + } else if (!roundtrip) { + if (ns.IsDecimalSource) + ns.RoundPos(precision); + else + ns.RoundDecimal(precision, true, false); + } + + if (!ns.Positive) { + cb.Append(nfi.NegativeSign); + } + + ns.AppendIntegerString(ns.IntegerDigits > 0 ? ns.IntegerDigits : 1, cb); + + if (ns.DecimalDigits > 0) { + cb.Append(nfi.NumberDecimalSeparator); + ns.AppendDecimalString(ns.DecimalDigits, cb); + } + + if (expMode) { + if (upper) + cb.Append('E'); + else + cb.Append('e'); + + if (exponent >= 0) + cb.Append(nfi.PositiveSign); + else { + cb.Append(nfi.NegativeSign); + exponent = -exponent; + } + + if (exponent == 0) { + cb.Append('0', 2); + } else if (exponent < 10) { + cb.Append('0'); + cb.Append(digitLowerTable[exponent]); + } else if (exponent < 100) { + cb.Append(digitLowerTable[exponent / 10 % 10]); + cb.Append(digitLowerTable[exponent % 10]); + } else if (exponent < 1000) { + cb.Append(digitLowerTable[exponent / 100 % 10]); + cb.Append(digitLowerTable[exponent / 10 % 10]); + cb.Append(digitLowerTable[exponent % 10]); + } + } + + return cb.ToString(); + } + internal static string FormatNumber(NumberStore ns, int precision, NumberFormatInfo nfi) { + precision = (precision >= 0 ? precision : nfi.NumberDecimalDigits); + StringBuilder sb = new StringBuilder(ns.IntegerDigits * 3 + precision); + + ns.RoundDecimal(precision); + bool needNegativeSign = (!ns.Positive && !ns.ZeroOnly); + + if (needNegativeSign) { + switch (nfi.NumberNegativePattern) { + case 0: + sb.Append('('); + break; + case 1: + sb.Append(nfi.NegativeSign); + break; + case 2: + sb.Append(nfi.NegativeSign); + sb.Append(' '); + break; + } + } + + ns.AppendIntegerStringWithGroupSeparator(sb, nfi.NumberGroupSizes, nfi.NumberGroupSeparator); + + if (precision > 0) { + sb.Append(nfi.NumberDecimalSeparator); + ns.AppendDecimalString(precision, sb); + } + + if (needNegativeSign) { + switch (nfi.NumberNegativePattern) { + case 0: + sb.Append(')'); + break; + case 3: + sb.Append(nfi.NegativeSign); + break; + case 4: + sb.Append(' '); + sb.Append(nfi.NegativeSign); + break; + } + } + + return sb.ToString(); + } + internal static string FormatPercent(NumberStore ns, int precision, NumberFormatInfo nfi) { + precision = (precision >= 0 ? precision : nfi.PercentDecimalDigits); + ns.Multiply10(2); + ns.RoundDecimal(precision); + bool needNegativeSign = (!ns.Positive && !ns.ZeroOnly); + + StringBuilder sb = new StringBuilder(ns.IntegerDigits * 2 + precision + 16); + + if (!needNegativeSign) { + if (nfi.PercentPositivePattern == 2) { + sb.Append(nfi.PercentSymbol); + } + } else { + switch (nfi.PercentNegativePattern) { + case 0: + sb.Append(nfi.NegativeSign); + break; + case 1: + sb.Append(nfi.NegativeSign); + break; + case 2: + sb.Append(nfi.NegativeSign); + sb.Append(nfi.PercentSymbol); + break; + } + } + + ns.AppendIntegerStringWithGroupSeparator(sb, nfi.PercentGroupSizes, nfi.PercentGroupSeparator); + + if (precision > 0) { + sb.Append(nfi.PercentDecimalSeparator); + ns.AppendDecimalString(precision, sb); + } + + if (!needNegativeSign) { + switch (nfi.PercentPositivePattern) { + case 0: + sb.Append(' '); + sb.Append(nfi.PercentSymbol); + break; + case 1: + sb.Append(nfi.PercentSymbol); + break; + } + } else { + switch (nfi.PercentNegativePattern) { + case 0: + sb.Append(' '); + sb.Append(nfi.PercentSymbol); + break; + case 1: + sb.Append(nfi.PercentSymbol); + break; + } + } + + return sb.ToString(); + } + static string FormatHexadecimal(ulong value, bool positive, int byteSize, int precision, bool upper) { + if (!positive) { + switch (byteSize) { + case 1: + value = (ulong)(256UL - value); + break; + case 2: + value = (ulong)(65536UL - value); + break; + case 4: + value = (ulong)(4294967296UL - value); + break; + case 8: + value = 0 - value; + break; + } + } + + char[] digits = (upper ? digitUpperTable : digitLowerTable); + int size = precision > 16 ? precision : 16; + /*char* buffer = stackalloc char[size]; + char* last = buffer + size; + char* ptr = last; + + while (value > 0) { + *--ptr = digits[value & 0xF]; + value >>= 4; + } + + while (ptr == last || last - ptr < precision) + *--ptr = '0'; + + return new string(ptr, 0, (int)(last - ptr));*/ + char[] buffer = new char[size]; + int idx = size; + while (value > 0) { + uint valTemp = (uint)value; + valTemp &= 0xf; + buffer[--idx] = digits[valTemp]; + value >>= 4; + } + while (idx == size || size - idx < precision) { + buffer[--idx] = '0'; + } + return new string(buffer, idx, size - idx); + } + internal static string FormatExponential(NumberStore ns, int precision, NumberFormatInfo nfi, bool upper) { + if (precision < 0) + precision = 6; + + if (ns.ZeroOnly) { + StringBuilder sb = new StringBuilder(precision + nfi.PositiveSign.Length + 6); + sb.Append('0'); + if (precision > 0) { + sb.Append('.'); + sb.Append('0', precision); + } + + if (upper) + sb.Append('E'); + else + sb.Append('e'); + + sb.Append(nfi.PositiveSign); + sb.Append('0', 3); + + return sb.ToString(); + } + + int exponent = 0; + while (!(ns.DecimalPointPosition == 1 && ns.GetChar(0) != '0')) { + if (ns.DecimalPointPosition > 1) { + ns.Divide10(1); + exponent++; + } else { + ns.Multiply10(1); + exponent--; + } + } + + if (ns.RoundDecimal(precision)) { + ns.Divide10(1); + exponent++; + } + + StringBuilder cb = new StringBuilder(ns.DecimalDigits + 1 + 8); + + if (!ns.Positive) { + cb.Append(nfi.NegativeSign); + } + + ns.AppendIntegerString(ns.IntegerDigits > 0 ? ns.IntegerDigits : 1, cb); + + if (precision > 0) { + cb.Append(nfi.NumberDecimalSeparator); + ns.AppendDecimalString(precision, cb); + } + + if (upper) + cb.Append('E'); + else + cb.Append('e'); + + if (exponent >= 0) + cb.Append(nfi.PositiveSign); + else { + cb.Append(nfi.NegativeSign); + exponent = -exponent; + } + + if (exponent == 0) { + cb.Append('0', 3); + } else if (exponent < 10) { + cb.Append('0', 2); + cb.Append(digitLowerTable[exponent]); + } else if (exponent < 100) { + cb.Append('0', 1); + cb.Append(digitLowerTable[exponent / 10 % 10]); + cb.Append(digitLowerTable[exponent % 10]); + } else if (exponent < 1000) { + cb.Append(digitLowerTable[exponent / 100 % 10]); + cb.Append(digitLowerTable[exponent / 10 % 10]); + cb.Append(digitLowerTable[exponent % 10]); + /*} else { // exponent range is 0...+-324 + int pos = cb.Length; + int count = 3; + while (exponent > 0 || --count > 0) { + cb.Insert (pos, digitLowerTable [exponent % 10]); + exponent /= 10; + }*/ + } + + return cb.ToString(); + } + #endregion + + #region Custom + internal static string FormatCustom(string format, NumberStore ns, NumberFormatInfo nfi) { + bool p = ns.Positive; + int offset = 0; + int length = 0; + CustomInfo.GetActiveSection(format, ref p, ns.ZeroOnly, ref offset, ref length); + if (length == 0) { + return ns.Positive ? String.Empty : nfi.NegativeSign; + } + ns.Positive = p; + + CustomInfo info = CustomInfo.Parse(format, offset, length, nfi); +#if false + Console.WriteLine("Format : {0}",format); + Console.WriteLine("DecimalDigits : {0}",info.DecimalDigits); + Console.WriteLine("DecimalPointPos : {0}",info.DecimalPointPos); + Console.WriteLine("DecimalTailSharpDigits : {0}",info.DecimalTailSharpDigits); + Console.WriteLine("IntegerDigits : {0}",info.IntegerDigits); + Console.WriteLine("IntegerHeadSharpDigits : {0}",info.IntegerHeadSharpDigits); + Console.WriteLine("IntegerHeadPos : {0}",info.IntegerHeadPos); + Console.WriteLine("UseExponent : {0}",info.UseExponent); + Console.WriteLine("ExponentDigits : {0}",info.ExponentDigits); + Console.WriteLine("ExponentTailSharpDigits : {0}",info.ExponentTailSharpDigits); + Console.WriteLine("ExponentNegativeSignOnly : {0}",info.ExponentNegativeSignOnly); + Console.WriteLine("DividePlaces : {0}",info.DividePlaces); + Console.WriteLine("Percents : {0}",info.Percents); + Console.WriteLine("Permilles : {0}",info.Permilles); +#endif + StringBuilder sb_int = new StringBuilder(info.IntegerDigits * 2); + StringBuilder sb_dec = new StringBuilder(info.DecimalDigits * 2); + StringBuilder sb_exp = (info.UseExponent ? new StringBuilder(info.ExponentDigits * 2) : null); + + int diff = 0; + if (info.Percents > 0) { + ns.Multiply10(2 * info.Percents); + } + if (info.Permilles > 0) { + ns.Multiply10(3 * info.Permilles); + } + if (info.DividePlaces > 0) { + ns.Divide10(info.DividePlaces); + } + + bool expPositive = true; + if (info.UseExponent && (info.DecimalDigits > 0 || info.IntegerDigits > 0)) { + if (!ns.ZeroOnly) { + while (true) { + while (ns.IntegerDigits > info.IntegerDigits) { + ns.Divide10(1); + diff--; + if (ns.IntegerDigits == 1 && ns.GetChar(0) == '0') + break; + } + while (ns.IntegerDigits < info.IntegerDigits || (ns.IntegerDigits == info.IntegerDigits && ns.GetChar(0) == '0')) { + ns.Multiply10(1); + diff++; + } + + if (!ns.RoundDecimal(info.DecimalDigits)) + break; + } + } + + expPositive = diff <= 0; + NumberStore.AppendIntegerStringFromUInt32(sb_exp, (uint)(diff >= 0 ? diff : -diff)); + } else { + ns.RoundDecimal(info.DecimalDigits); + if (ns.ZeroOnly) + ns.Positive = true; + } + + if (info.IntegerDigits != 0 || !ns.CheckZeroOnlyInteger()) { + ns.AppendIntegerString(ns.IntegerDigits, sb_int); + } + /* if (sb_int.Length > info.IntegerDigits) { + int len = 0; + while (sb_int.Length > info.IntegerDigits && len < sb_int.Length) { + if (sb_int [len] == '0') + len ++; + else + break; + } + sb_int.Remove (0, len); + } */ + + ns.AppendDecimalString(ns.DecimalDigits, sb_dec); + + if (info.UseExponent) { + if (info.DecimalDigits <= 0 && info.IntegerDigits <= 0) + ns.Positive = true; + + if (sb_int.Length < info.IntegerDigits) + sb_int.Insert(0, "0", info.IntegerDigits - sb_int.Length); + + while (sb_exp.Length < info.ExponentDigits - info.ExponentTailSharpDigits) + sb_exp.Insert(0, '0'); + + if (expPositive && !info.ExponentNegativeSignOnly) + sb_exp.Insert(0, nfi.PositiveSign); + else if (!expPositive) + sb_exp.Insert(0, nfi.NegativeSign); + } else { + if (sb_int.Length < info.IntegerDigits - info.IntegerHeadSharpDigits) + sb_int.Insert(0, "0", info.IntegerDigits - info.IntegerHeadSharpDigits - sb_int.Length); + if (info.IntegerDigits == info.IntegerHeadSharpDigits && NumberStore.IsZeroOnly(sb_int)) + sb_int.Remove(0, sb_int.Length); + } + + ZeroTrimEnd(sb_dec, true); + while (sb_dec.Length < info.DecimalDigits - info.DecimalTailSharpDigits) + sb_dec.Append('0'); + if (sb_dec.Length > info.DecimalDigits) + sb_dec.Remove(info.DecimalDigits, sb_dec.Length - info.DecimalDigits); + + return info.Format(format, offset, length, nfi, ns.Positive, sb_int, sb_dec, sb_exp); + } + + private class CustomInfo { + public bool UseGroup = false; + public int DecimalDigits = 0; + public int DecimalPointPos = -1; + public int DecimalTailSharpDigits = 0; + public int IntegerDigits = 0; + public int IntegerHeadSharpDigits = 0; + public int IntegerHeadPos = 0; + public bool UseExponent = false; + public int ExponentDigits = 0; + public int ExponentTailSharpDigits = 0; + public bool ExponentNegativeSignOnly = true; + public int DividePlaces = 0; + public int Percents = 0; + public int Permilles = 0; + + public static void GetActiveSection(string format, ref bool positive, bool zero, ref int offset, ref int length) { + int[] lens = new int[3]; + int index = 0; + int lastPos = 0; + char literal = '\0'; + for (int i = 0; i < format.Length; i++) { + char c = format[i]; + + if (c == literal || (literal == '\0' && (c == '\"' || c == '\''))) { + if (literal == '\0') + literal = c; + else + literal = '\0'; + continue; + } + + if (literal == '\0' && format[i] == ';' && (i == 0 || format[i - 1] != '\\')) { + lens[index++] = i - lastPos; + lastPos = i + 1; + if (index == 3) + break; + } + } + + if (index == 0) { + offset = 0; + length = format.Length; + return; + } + if (index == 1) { + if (positive || zero) { + offset = 0; + length = lens[0]; + return; + } + if (lens[0] + 1 < format.Length) { + positive = true; + offset = lens[0] + 1; + length = format.Length - offset; + return; + } else { + offset = 0; + length = lens[0]; + return; + } + } + if (index == 2) { + if (zero) { + offset = lens[0] + lens[1] + 2; + length = format.Length - offset; + return; + } + if (positive) { + offset = 0; + length = lens[0]; + return; + } + if (lens[1] > 0) { + positive = true; + offset = lens[0] + 1; + length = lens[1]; + return; + } else { + offset = 0; + length = lens[0]; + return; + } + } + if (index == 3) { + if (zero) { + offset = lens[0] + lens[1] + 2; + length = lens[2]; + return; + } + if (positive) { + offset = 0; + length = lens[0]; + return; + } + if (lens[1] > 0) { + positive = true; + offset = lens[0] + 1; + length = lens[1]; + return; + } else { + offset = 0; + length = lens[0]; + return; + } + } + + throw new ArgumentException(); + } + + public static CustomInfo Parse(string format, int offset, int length, NumberFormatInfo nfi) { + char literal = '\0'; + bool integerArea = true; + bool decimalArea = false; + bool exponentArea = false; + bool sharpContinues = true; + + CustomInfo info = new CustomInfo(); + int groupSeparatorCounter = 0; + + for (int i = offset; i - offset < length; i++) { + char c = format[i]; + + if (c == literal && c != '\0') { + literal = '\0'; + continue; + } + if (literal != '\0') + continue; + + if (exponentArea && (c != '\0' && c != '0' && c != '#')) { + exponentArea = false; + integerArea = (info.DecimalPointPos < 0); + decimalArea = !integerArea; + i--; + continue; + } + + switch (c) { + case '\\': + i++; + continue; + case '\'': + case '\"': + if (c == '\"' || c == '\'') { + literal = c; + } + continue; + case '#': + if (sharpContinues && integerArea) + info.IntegerHeadSharpDigits++; + else if (decimalArea) + info.DecimalTailSharpDigits++; + else if (exponentArea) + info.ExponentTailSharpDigits++; + + goto case '0'; + case '0': + if (c != '#') { + sharpContinues = false; + if (decimalArea) + info.DecimalTailSharpDigits = 0; + else if (exponentArea) + info.ExponentTailSharpDigits = 0; + } + if (info.IntegerHeadPos == -1) + info.IntegerHeadPos = i; + + if (integerArea) { + info.IntegerDigits++; + if (groupSeparatorCounter > 0) + info.UseGroup = true; + groupSeparatorCounter = 0; + } else if (decimalArea) { + info.DecimalDigits++; + } else if (exponentArea) { + info.ExponentDigits++; + } + break; + case 'e': + case 'E': + if (info.UseExponent) + break; + + info.UseExponent = true; + integerArea = false; + decimalArea = false; + exponentArea = true; + if (i + 1 - offset < length) { + char nc = format[i + 1]; + if (nc == '+') + info.ExponentNegativeSignOnly = false; + if (nc == '+' || nc == '-') { + i++; + } else if (nc != '0' && nc != '#') { + info.UseExponent = false; + if (info.DecimalPointPos < 0) + integerArea = true; + } + c = '\0'; + } + + break; + case '.': + integerArea = false; + decimalArea = true; + exponentArea = false; + if (info.DecimalPointPos == -1) + info.DecimalPointPos = i; + break; + case '%': + info.Percents++; + break; + case '\u2030': + info.Permilles++; + break; + case ',': + if (integerArea && info.IntegerDigits > 0) + groupSeparatorCounter++; + break; + default: + break; + } + } + + if (info.ExponentDigits == 0) + info.UseExponent = false; + else + info.IntegerHeadSharpDigits = 0; + + if (info.DecimalDigits == 0) + info.DecimalPointPos = -1; + + info.DividePlaces += groupSeparatorCounter * 3; + + return info; + } + + public string Format(string format, int offset, int length, NumberFormatInfo nfi, bool positive, StringBuilder sb_int, StringBuilder sb_dec, StringBuilder sb_exp) { + StringBuilder sb = new StringBuilder(); + char literal = '\0'; + bool integerArea = true; + bool decimalArea = false; + int intSharpCounter = 0; + int sb_int_index = 0; + int sb_dec_index = 0; + + int[] groups = nfi.NumberGroupSizes; + string groupSeparator = nfi.NumberGroupSeparator; + int intLen = 0, total = 0, groupIndex = 0, counter = 0, groupSize = 0, fraction = 0; + if (UseGroup && groups.Length > 0) { + intLen = sb_int.Length; + for (int i = 0; i < groups.Length; i++) { + total += groups[i]; + if (total <= intLen) + groupIndex = i; + } + groupSize = groups[groupIndex]; + fraction = intLen > total ? intLen - total : 0; + if (groupSize == 0) { + while (groupIndex >= 0 && groups[groupIndex] == 0) + groupIndex--; + + groupSize = fraction > 0 ? fraction : groups[groupIndex]; + } + if (fraction == 0) { + counter = groupSize; + } else { + groupIndex += fraction / groupSize; + counter = fraction % groupSize; + if (counter == 0) + counter = groupSize; + else + groupIndex++; + } + } else { + UseGroup = false; + } + + for (int i = offset; i - offset < length; i++) { + char c = format[i]; + + if (c == literal && c != '\0') { + literal = '\0'; + continue; + } + if (literal != '\0') { + sb.Append(c); + continue; + } + + switch (c) { + case '\\': + i++; + if (i - offset < length) + sb.Append(format[i]); + continue; + case '\'': + case '\"': + if (c == '\"' || c == '\'') { + literal = c; + } + continue; + case '#': + goto case '0'; + case '0': + if (integerArea) { + intSharpCounter++; + if (IntegerDigits - intSharpCounter < sb_int.Length + sb_int_index || c == '0') + while (IntegerDigits - intSharpCounter + sb_int_index < sb_int.Length) { + sb.Append(sb_int[sb_int_index++]); + if (UseGroup && --intLen > 0 && --counter == 0) { + sb.Append(groupSeparator); + if (--groupIndex < groups.Length && groupIndex >= 0) + groupSize = groups[groupIndex]; + counter = groupSize; + } + } + break; + } else if (decimalArea) { + if (sb_dec_index < sb_dec.Length) + sb.Append(sb_dec[sb_dec_index++]); + break; + } + + sb.Append(c); + break; + case 'e': + case 'E': + if (sb_exp == null || !UseExponent) { + sb.Append(c); + break; + } + + bool flag1 = true; + bool flag2 = false; + + int q; + for (q = i + 1; q - offset < length; q++) { + if (format[q] == '0') { + flag2 = true; + continue; + } + if (q == i + 1 && (format[q] == '+' || format[q] == '-')) { + continue; + } + if (!flag2) + flag1 = false; + break; + } + + if (flag1) { + i = q - 1; + integerArea = (DecimalPointPos < 0); + decimalArea = !integerArea; + + sb.Append(c); + sb.Append(sb_exp); + sb_exp = null; + } else + sb.Append(c); + + break; + case '.': + if (DecimalPointPos == i) { + if (DecimalDigits > 0) { + while (sb_int_index < sb_int.Length) + sb.Append(sb_int[sb_int_index++]); + } + if (sb_dec.Length > 0) + sb.Append(nfi.NumberDecimalSeparator); + } + integerArea = false; + decimalArea = true; + break; + case ',': + break; + case '%': + sb.Append(nfi.PercentSymbol); + break; + case '\u2030': + sb.Append(nfi.PerMilleSymbol); + break; + default: + sb.Append(c); + break; + } + } + + if (!positive) + sb.Insert(0, nfi.NegativeSign); + + return sb.ToString(); + } + } + + #endregion + + #region Internal structures + internal struct NumberStore { + bool _NaN; + bool _infinity; + bool _positive; + int _decPointPos; + int _defPrecision; + int _defMaxPrecision; + int _defByteSize; + + byte[] _digits; + + static uint[] IntList = new uint[] { + 1, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000, + }; + + static ulong[] ULongList = new ulong[] { + 1, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000, + 10000000000, + 100000000000, + 1000000000000, + 10000000000000, + 100000000000000, + 1000000000000000, + 10000000000000000, + 100000000000000000, + 1000000000000000000, + 10000000000000000000, + }; + + #region Constructors + public NumberStore(long value) { + _infinity = _NaN = false; + _defByteSize = 8; + _defMaxPrecision = _defPrecision = 19; + _positive = value >= 0; + + if (value == 0) { + _digits = new byte[] { 0 }; + _decPointPos = 1; + return; + } + + ulong v = (ulong)(_positive ? value : -value); + + int i = 18, j = 0; + + if (v < 10) + i = 0; + else if (v < 100) + i = 1; + else if (v < 1000) + i = 2; + else if (v < 10000) + i = 3; + else if (v < 100000) + i = 4; + else if (v < 1000000) + i = 5; + else if (v < 10000000) + i = 6; + else if (v < 100000000) + i = 7; + else if (v < 1000000000) + i = 8; + else if (v < 10000000000) + i = 9; + else if (v < 100000000000) + i = 10; + else if (v < 1000000000000) + i = 11; + else if (v < 10000000000000) + i = 12; + else if (v < 100000000000000) + i = 13; + else if (v < 1000000000000000) + i = 14; + else if (v < 10000000000000000) + i = 15; + else if (v < 100000000000000000) + i = 16; + else if (v < 1000000000000000000) + i = 17; + else + i = 18; + + _digits = new byte[i + 1]; + do { + ulong n = v / ULongList[i]; + _digits[j++] = (byte)n; + v -= ULongList[i--] * n; + } while (i >= 0); + + _decPointPos = _digits.Length; + } + public NumberStore(int value) { + _infinity = _NaN = false; + _defByteSize = 4; + _defMaxPrecision = _defPrecision = 10; + _positive = value >= 0; + + if (value == 0) { + _digits = new byte[] { 0 }; + _decPointPos = 1; + return; + } + + uint v = (uint)(_positive ? value : -value); + + int i = 9, j = 0; + + if (v < 10) + i = 0; + else if (v < 100) + i = 1; + else if (v < 1000) + i = 2; + else if (v < 10000) + i = 3; + else if (v < 100000) + i = 4; + else if (v < 1000000) + i = 5; + else if (v < 10000000) + i = 6; + else if (v < 100000000) + i = 7; + else if (v < 1000000000) + i = 8; + else + i = 9; + + _digits = new byte[i + 1]; + do { + uint n = v / IntList[i]; + _digits[j++] = (byte)n; + v -= IntList[i--] * n; + } while (i >= 0); + + _decPointPos = _digits.Length; + } + public NumberStore(short value) + : this((int)value) { + _defByteSize = 2; + _defMaxPrecision = _defPrecision = 5; + } + public NumberStore(sbyte value) + : this((int)value) { + _defByteSize = 1; + _defMaxPrecision = _defPrecision = 3; + } + + public NumberStore(ulong value) { + _infinity = _NaN = false; + _defByteSize = 8; + _defMaxPrecision = _defPrecision = 20; + _positive = true; + + if (value == 0) { + _digits = new byte[] { 0 }; + _decPointPos = 1; + return; + } + + int i = 19, j = 0; + + if (value < 10) + i = 0; + else if (value < 100) + i = 1; + else if (value < 1000) + i = 2; + else if (value < 10000) + i = 3; + else if (value < 100000) + i = 4; + else if (value < 1000000) + i = 5; + else if (value < 10000000) + i = 6; + else if (value < 100000000) + i = 7; + else if (value < 1000000000) + i = 8; + else if (value < 10000000000) + i = 9; + else if (value < 100000000000) + i = 10; + else if (value < 1000000000000) + i = 11; + else if (value < 10000000000000) + i = 12; + else if (value < 100000000000000) + i = 13; + else if (value < 1000000000000000) + i = 14; + else if (value < 10000000000000000) + i = 15; + else if (value < 100000000000000000) + i = 16; + else if (value < 1000000000000000000) + i = 17; + else if (value < 10000000000000000000) + i = 18; + else + i = 19; + + _digits = new byte[i + 1]; + do { + ulong n = value / ULongList[i]; + _digits[j++] = (byte)n; + value -= ULongList[i--] * n; + } while (i >= 0); + + _decPointPos = _digits.Length; + } + public NumberStore(uint value) { + _infinity = _NaN = false; + _positive = true; + _defByteSize = 4; + _defMaxPrecision = _defPrecision = 10; + + if (value == 0) { + _digits = new byte[] { 0 }; + _decPointPos = 1; + return; + } + + int i = 9, j = 0; + + if (value < 10) + i = 0; + else if (value < 100) + i = 1; + else if (value < 1000) + i = 2; + else if (value < 10000) + i = 3; + else if (value < 100000) + i = 4; + else if (value < 1000000) + i = 5; + else if (value < 10000000) + i = 6; + else if (value < 100000000) + i = 7; + else if (value < 1000000000) + i = 8; + else + i = 9; + + _digits = new byte[i + 1]; + do { + uint n = value / IntList[i]; + _digits[j++] = (byte)n; + value -= IntList[i--] * n; + } while (i >= 0); + + _decPointPos = _digits.Length; + } + public NumberStore(ushort value) + : this((uint)value) { + _defByteSize = 2; + _defMaxPrecision = _defPrecision = 5; + } + public NumberStore(byte value) + : this((uint)value) { + _defByteSize = 1; + _defMaxPrecision = _defPrecision = 3; + } + + public NumberStore(double value) { + _digits = null; + _defByteSize = 64; + _defPrecision = 15; + _defMaxPrecision = _defPrecision + 2; + + if (double.IsNaN(value) || double.IsInfinity(value)) { + _NaN = double.IsNaN(value); + _infinity = double.IsInfinity(value); + _positive = value > 0; + _decPointPos = 0; + return; + } else { + _NaN = _infinity = false; + } + + long bits = BitConverter.DoubleToInt64Bits(value); + _positive = (bits >= 0); + int e = (int)((bits >> 52) & 0x7ffL); + long m = bits & 0xfffffffffffffL; + + if (e == 0 && m == 0) { + _decPointPos = 1; + _digits = new byte[] { 0 }; + _positive = true; + return; + } + + if (e == 0) { + e++; + } else if (e != 0) { + m |= (1L << 52); + } + + e -= 1075; + + int nsize = 0; + while ((m & 1) == 0) { + m >>= 1; + e++; + nsize++; + } + + long mt = m; + int length = 1; + byte[] temp = new byte[56]; + for (int i = temp.Length - 1; i >= 0; i--, length++) { + temp[i] = (byte)(mt % 10); + mt /= 10; + if (mt == 0) + break; + } + + _decPointPos = temp.Length - 1; + + if (e >= 0) { + for (int i = 0; i < e; i++) { + if (MultiplyBy(ref temp, ref length, 2)) { + _decPointPos++; + } + } + } else { + for (int i = 0; i < -e; i++) { + if (MultiplyBy(ref temp, ref length, 5)) { + _decPointPos++; + } + } + _decPointPos += e; + } + + int ulvc = 1; + ulong ulv = 0; + for (int i = 0; i < temp.Length; i++) + if (temp[i] != 0) { + _decPointPos -= i - 1; + _digits = new byte[temp.Length - i]; + for (int q = i; q < temp.Length; q++) { + _digits[q - i] = temp[q]; + if (ulvc < 20) { + ulv = ulv * 10 + temp[q]; + ulvc++; + } + } + break; + } + + RoundEffectiveDigits(17, true, true); + } + public NumberStore(float value) { + _digits = null; + _defByteSize = 32; + _defPrecision = 7; + _defMaxPrecision = _defPrecision + 2; + + if (float.IsNaN(value) || float.IsInfinity(value)) { + _NaN = float.IsNaN(value); + _infinity = float.IsInfinity(value); + _positive = value > 0; + _decPointPos = 0; + return; + } else + _infinity = _NaN = false; + + long bits = BitConverter.DoubleToInt64Bits(value); + _positive = (bits >= 0); + int e = (int)((bits >> 52) & 0x7ffL); + long m = bits & 0xfffffffffffffL; + + if (e == 0 && m == 0) { + _decPointPos = 1; + _digits = new byte[] { 0 }; + _positive = true; + return; + } + + if (e == 0) { + e++; + } else if (e != 0) { + m |= (1L << 52); + } + + e -= 1075; + + int nsize = 0; + while ((m & 1) == 0) { + m >>= 1; + e++; + nsize++; + } + + long mt = m; + int length = 1; + byte[] temp = new byte[26]; + for (int i = temp.Length - 1; i >= 0; i--, length++) { + temp[i] = (byte)(mt % 10); + mt /= 10; + if (mt == 0) + break; + } + + _decPointPos = temp.Length - 1; + + if (e >= 0) { + for (int i = 0; i < e; i++) { + if (MultiplyBy(ref temp, ref length, 2)) { + _decPointPos++; + } + } + } else { + for (int i = 0; i < -e; i++) { + if (MultiplyBy(ref temp, ref length, 5)) { + _decPointPos++; + } + } + _decPointPos += e; + } + + int ulvc = 1; + ulong ulv = 0; + for (int i = 0; i < temp.Length; i++) + if (temp[i] != 0) { + _decPointPos -= i - 1; + _digits = new byte[temp.Length - i]; + for (int q = i; q < temp.Length; q++) { + _digits[q - i] = temp[q]; + if (ulvc < 20) { + ulv = ulv * 10 + temp[q]; + ulvc++; + } + } + break; + } + + RoundEffectiveDigits(9, true, true); + } + + internal bool MultiplyBy(ref byte[] buffer, ref int length, int amount) { + int mod = 0; + int ret; + int start = buffer.Length - length - 1; + if (start < 0) start = 0; + + for (int i = buffer.Length - 1; i > start; i--) { + ret = buffer[i] * amount + mod; + mod = ret / 10; + buffer[i] = (byte)(ret % 10); + } + + if (mod != 0) { + length = buffer.Length - start; + + if (start == 0) { + buffer[0] = (byte)mod; + Array.Copy(buffer, 0, buffer, 1, buffer.Length - 1); + buffer[0] = 0; + return true; + } else { + buffer[start] = (byte)mod; + } + } + + return false; + } + + + public NumberStore(decimal value) { + int[] bits = decimal.GetBits(value); + _positive = (bits[3] & 0x80000000) == 0; + bits[3] = bits[3] & 0x7FFFFFFF; + int ss = (bits[3] & 0x1F0000) >> 16; + ulong lo = (ulong)((((ulong)bits[1]) << 32) | (uint)bits[0]); + ulong hi = (uint)bits[2]; + uint rest = 0; + + int digits = 0; + while (hi > 0 || lo > 0) { + digits++; + DivideDecimal(ref lo, ref hi, 10, ref rest); + } + + lo = (ulong)((((ulong)bits[1]) << 32) | (uint)bits[0]); + hi = (uint)bits[2]; + + _digits = new byte[digits]; + int i = digits; + while (hi > 0 || lo > 0) { + DivideDecimal(ref lo, ref hi, 10, ref rest); + _digits[--i] = (byte)rest; + } + + _infinity = _NaN = false; + _decPointPos = _digits.Length - ss; + _defPrecision = _defMaxPrecision = 100; + _defByteSize = 16; + } + static int DivideDecimal(ref ulong lo, ref ulong hi, uint factor, ref uint rest) { + ulong a, b, c, h; + + h = hi; + a = (uint)(h >> 32); + b = a / factor; + a -= b * factor; + a <<= 32; + a |= (uint)h; + c = a / factor; + a -= c * factor; + a <<= 32; + hi = b << 32 | (uint)c; + + h = lo; + a |= (uint)(h >> 32); + b = a / factor; + a -= b * factor; + a <<= 32; + a |= (uint)h; + c = a / factor; + a -= c * factor; + lo = b << 32 | (uint)c; + + rest = (uint)a; + + a <<= 1; + return (a >= factor || (a == factor && (c & 1) == 1)) ? 1 : 0; + } + #endregion + + #region Public Property + public bool IsNaN { + get { return _NaN; } + } + public bool IsInfinity { + get { return _infinity; } + } + public int DecimalPointPosition { + get { return _decPointPos; } + } + public bool Positive { + get { return _positive; } + set { _positive = value; } + } + public int DefaultPrecision { + get { return _defPrecision; } + } + public int DefaultMaxPrecision { + get { return _defMaxPrecision; } + } + public int DefaultByteSize { + get { return _defByteSize; } + } + public bool HasDecimal { + get { return _digits.Length > _decPointPos; } + } + public int IntegerDigits { + get { return _decPointPos > 0 ? _decPointPos : 1; } + } + public int DecimalDigits { + get { return HasDecimal ? _digits.Length - _decPointPos : 0; } + } + public bool IsFloatingSource { + get { return _defPrecision == 15 || _defPrecision == 7; } + } + public bool IsDecimalSource { + get { return _defPrecision > 30; } + } + public bool IsBankerApplicable { + get { + if ((_digits == null) || (_digits.Length < 2)) + return false; + return ((_digits[_digits.Length - 2] & 1) == 1); + } + } + public bool ZeroOnly { + get { + for (int i = 0; i < _digits.Length; i++) + if (_digits[i] != 0) + return false; + return true; + } + } + #endregion + + #region Public Method + + #region Round + public bool RoundPos(int pos) { + return RoundPos(pos, true); + } + public bool RoundPos(int pos, bool carryFive) { + bool carry = false; + + if (_decPointPos <= 0) + pos = pos - _decPointPos - 1; + + if (pos >= _digits.Length) + return false; + + if (pos < 0) { + _digits = new byte[1]; + _digits[0] = 0; + _decPointPos = 1; + _positive = true; + return false; + } + + for (int i = pos; i >= 0; i--) { + RoundHelper(i, carryFive, ref carry); + if (!carry) + break; + } + + if (carry) { + byte[] temp = new byte[_digits.Length + 1]; + _digits.CopyTo(temp, 1); + temp[0] = 1; + _digits = temp; + _decPointPos++; + pos++; + } + + for (int i = pos; i < _digits.Length; i++) + _digits[i] = 0; + TrimDecimalEndZeros(); + + return carry; + } + public bool RoundDecimal(int decimals) { + return RoundDecimal(decimals, true, true); + } + public bool RoundDecimal(int decimals, bool carryFive, bool countZero) { + bool carry = false; + + if (countZero || (_decPointPos > 0)) + decimals += _decPointPos; + + if (!HasDecimal || decimals >= _digits.Length) + return false; + + if (decimals < 0) { + _digits = new byte[1]; + _digits[0] = 0; + _decPointPos = 1; + _positive = true; + return false; + } + + for (int i = decimals; i >= 0; i--) { + RoundHelper(i, carryFive, ref carry); + if (!carry) + break; + } + + if (carry) { + byte[] temp = new byte[_digits.Length + 1]; + _digits.CopyTo(temp, 1); + temp[0] = 1; + _digits = temp; + _decPointPos++; + decimals++; + } + + for (int i = decimals; i < _digits.Length; i++) + _digits[i] = 0; + TrimDecimalEndZeros(); + + return carry; + } + void RoundHelper(int index, bool carryFive, ref bool carry) { + if (carry) { + if (_digits[index] == 9) { + carry = true; + _digits[index] = 0; + } else { + carry = false; + _digits[index]++; + } + } else if (_digits[index] >= (carryFive ? 5 : 6)) { + carry = true; + } + } + public bool RoundEffectiveDigits(int digits) { + return RoundEffectiveDigits(digits, true, true); + } + public bool RoundEffectiveDigits(int digits, bool carryFive, bool carryEven) { + bool carry = false; + + if (digits >= _digits.Length || digits < 0) + return false; + + if (digits + 1 < _digits.Length && _digits[digits + 1] == 5 && _digits[digits] % 2 == (carryEven ? 0 : 1)) + carryFive = false; + + /// are we cutting from the maximum precision ? + if (_digits.Length == _defMaxPrecision) { + // special case if we *aren't* cutting inside the extra precision (e.g. 16 on 17) + if (digits != _defMaxPrecision - 1) { + // ok, here we look at the *two* extra numbers we're keeping + // (we keep 17 digits while the true precision is 15 digits). + int extra = _digits[_defMaxPrecision - 2] * 10 + _digits[_defMaxPrecision - 1]; + carry = (extra >= 50); + if (carry) { + _digits[_defMaxPrecision - 2] = 0; + _digits[_defMaxPrecision - 1] = 0; + int d = _digits.Length - 3; + CarryPropagation(ref d, carryFive, ref carry); + } + } + } + CarryPropagation(ref digits, carryFive, ref carry); + + for (int i = digits; i < _digits.Length; i++) + _digits[i] = 0; + TrimDecimalEndZeros(); + + return carry; + } + + private void CarryPropagation(ref int digits, bool carryFive, ref bool carry) { + for (int i = digits; i >= 0; i--) { + RoundHelper(i, carryFive, ref carry); + if (!carry) + break; + } + + if (carry) { + byte[] temp = new byte[_digits.Length + 1]; + _digits.CopyTo(temp, 1); + temp[0] = 1; + _digits = temp; + _decPointPos++; + digits++; + } + } + + #endregion + + #region Trim + public void TrimDecimalEndZeros() { + int len = 0; + for (int i = _digits.Length - 1; i >= 0; i--) { + if (_digits[i] != 0) + break; + len++; + } + + if (len > 0) { + byte[] temp = new byte[_digits.Length - len]; + Array.Copy(_digits, 0, temp, 0, temp.Length); + _digits = temp; + } + } + public void TrimIntegerStartZeros() { + if (_decPointPos < 0 && _decPointPos >= _digits.Length) + return; + + int len = 0; + for (int i = 0; i < _decPointPos && i < _digits.Length; i++) { + if (_digits[i] != 0) + break; + len++; + } + + if (len == _decPointPos) + len--; + + if (len == _digits.Length) { + _digits = new byte[1]; + _digits[0] = 0; + _decPointPos = 1; + _positive = true; + } else if (len > 0) { + byte[] temp = new byte[_digits.Length - len]; + Array.Copy(_digits, len, temp, 0, temp.Length); + _digits = temp; + _decPointPos -= len; + } + } + + #endregion + + #region Integer + public void AppendIntegerString(int minLength, StringBuilder cb) { + if (IntegerDigits == 0) { + cb.Append('0', minLength); + return; + } + if (_decPointPos <= 0) { + cb.Append('0', minLength); + return; + } + + if (_decPointPos < minLength) + cb.Append('0', minLength - _decPointPos); + + for (int i = 0; i < _decPointPos; i++) { + if (i < _digits.Length) + cb.Append((char)('0' + _digits[i])); + else + cb.Append('0'); + } + } + public void AppendIntegerStringWithGroupSeparator(StringBuilder sb, int[] groups, string groupSeparator) { + if (_decPointPos <= 0) { + sb.Append('0'); + return; + } + + int intLen = IntegerDigits; + int total = 0; + int groupIndex = 0; + for (int i = 0; i < groups.Length; i++) { + total += groups[i]; + if (total <= intLen) + groupIndex = i; + } + + if (groups.Length > 0 && total > 0) { + int counter; + int groupSize = groups[groupIndex]; + int fraction = intLen > total ? intLen - total : 0; + if (groupSize == 0) { + while (groupIndex >= 0 && groups[groupIndex] == 0) + groupIndex--; + + groupSize = fraction > 0 ? fraction : groups[groupIndex]; + } + if (fraction == 0) { + counter = groupSize; + } else { + groupIndex += fraction / groupSize; + counter = fraction % groupSize; + if (counter == 0) + counter = groupSize; + else + groupIndex++; + } + + for (int i = 0; i < _decPointPos; i++) { + if (i < _digits.Length) { + sb.Append((char)('0' + _digits[i])); + } else { + sb.Append('0'); + } + + if (i < intLen - 1 && --counter == 0) { + sb.Append(groupSeparator); + if (--groupIndex < groups.Length && groupIndex >= 0) + groupSize = groups[groupIndex]; + counter = groupSize; + } + } + } else { + for (int i = 0; i < _decPointPos; i++) { + if (i < _digits.Length) { + sb.Append((char)('0' + _digits[i])); + } else { + sb.Append('0'); + } + } + } + } + #endregion + + #region Decimal + public string GetDecimalString(int precision) { + if (!HasDecimal) + return new string('0', precision); + + StringBuilder sb = new StringBuilder(precision); + for (int i = _decPointPos; i < _digits.Length && i < precision + _decPointPos; i++) { + if (i >= 0) + sb.Append((char)('0' + _digits[i])); + else + sb.Append('0'); + } + if (sb.Length < precision) + sb.Append('0', precision - sb.Length); + else if (sb.Length > precision) + sb.Remove(0, precision); + return sb.ToString(); + } + + public void AppendDecimalString(int precision, StringBuilder cb) { + if (!HasDecimal) { + cb.Append('0', precision); + return; + } + + int i = _decPointPos; + for (; i < _digits.Length && i < precision + _decPointPos; i++) { + if (i >= 0) + cb.Append((char)('0' + _digits[i])); + else + cb.Append('0'); + } + + i -= _decPointPos; + if (i < precision) + cb.Append('0', precision - i); + } + #endregion + + #region others + public bool CheckZeroOnlyInteger() { + for (int i = 0; i < _decPointPos && i < _digits.Length; i++) { + if (_digits[i] != 0) + return false; + } + return true; + } + public void Multiply10(int count) { + if (count <= 0) + return; + + _decPointPos += count; + + TrimIntegerStartZeros(); + } + public void Divide10(int count) { + if (count <= 0) + return; + + _decPointPos -= count; + } + public override string ToString() { + StringBuilder sb = new StringBuilder(); + AppendIntegerString(IntegerDigits, sb); + if (HasDecimal) { + sb.Append('.'); + AppendDecimalString(DecimalDigits, sb); + } + return sb.ToString(); + } + public char GetChar(int pos) { + if (_decPointPos <= 0) + pos += _decPointPos - 1; + + if (pos < 0 || pos >= _digits.Length) + return '0'; + else + return (char)('0' + _digits[pos]); + } + public byte GetDigitByte(int pos) { + if (_decPointPos <= 0) + pos += _decPointPos - 1; + + if (pos < 0 || pos >= _digits.Length) + return 0; + else + return _digits[pos]; + } + public NumberStore GetClone() { + NumberStore ns = new NumberStore(); + + ns._decPointPos = this._decPointPos; + ns._defMaxPrecision = this._defMaxPrecision; + ns._defPrecision = this._defPrecision; + ns._digits = (byte[])this._digits.Clone(); + ns._infinity = this._infinity; + ns._NaN = this._NaN; + ns._positive = this._positive; + + return ns; + } + public int GetDecimalPointPos() { + return _decPointPos; + } + public void SetDecimalPointPos(int dp) { + _decPointPos = dp; + } + #endregion + + #endregion + + #region Public Static Method + public static bool IsZeroOnly(StringBuilder sb) { + for (int i = 0; i < sb.Length; i++) + if (char.IsDigit(sb[i]) && sb[i] != '0') + return false; + return true; + } + public static void AppendIntegerStringFromUInt32(StringBuilder sb, uint v) { + if (v < 0) + throw new ArgumentException(); + + int i = 9; + + if (v >= 1000000000) + i = 9; + else if (v >= 100000000) + i = 8; + else if (v >= 10000000) + i = 7; + else if (v >= 1000000) + i = 6; + else if (v >= 100000) + i = 5; + else if (v >= 10000) + i = 4; + else if (v >= 1000) + i = 3; + else if (v >= 100) + i = 2; + else if (v >= 10) + i = 1; + else + i = 0; + do { + uint n = v / IntList[i]; + sb.Append(NumberFormatter.digitLowerTable[n]); + v -= IntList[i--] * n; + } while (i >= 0); + } + #endregion + } + #endregion + } +} + +#endif diff --git a/corlib/System/Object.cs b/corlib/System/Object.cs new file mode 100644 index 0000000..e73efdc --- /dev/null +++ b/corlib/System/Object.cs @@ -0,0 +1,45 @@ +#if !LOCALTEST + +using System.Runtime.CompilerServices; + +namespace System { + public class Object { + + public Object() { + } + + ~Object() { + } + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public Type GetType(); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public virtual bool Equals(object obj); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public virtual int GetHashCode(); + + public virtual string ToString() { + return this.GetType().FullName; + } + + public static bool Equals(object a, object b) { + if (a == b) { + return true; + } + if (a == null || b == null) { + return false; + } + return a.Equals(b); + } + + public static bool ReferenceEquals(object a, object b) { + return (a == b); + } + + [MethodImpl(MethodImplOptions.InternalCall)] + extern internal static object Clone(object obj); + } +} +#endif diff --git a/corlib/System/ObjectDisposedException.cs b/corlib/System/ObjectDisposedException.cs new file mode 100644 index 0000000..87db6d2 --- /dev/null +++ b/corlib/System/ObjectDisposedException.cs @@ -0,0 +1,27 @@ +#if !LOCALTEST + +namespace System { + public class ObjectDisposedException : InvalidOperationException { + + private string objectName; + + public ObjectDisposedException(string objectName) + : base("The object was used after being disposed") { + this.objectName = objectName; + } + + public ObjectDisposedException(string objectName, string msg) + : base(msg) { + this.objectName = objectName; + } + + public string ObjectName { + get { + return this.objectName; + } + } + + } +} + +#endif diff --git a/corlib/System/OperatingSystem.cs b/corlib/System/OperatingSystem.cs new file mode 100644 index 0000000..d3f587b --- /dev/null +++ b/corlib/System/OperatingSystem.cs @@ -0,0 +1,78 @@ +#if !LOCALTEST + +namespace System { + public sealed class OperatingSystem : ICloneable { + + private PlatformID platformID; + private Version version; + + public OperatingSystem(PlatformID platformID, Version version) { + if (version == null) { + throw new ArgumentNullException("version"); + } + this.platformID = platformID; + this.version = version; + } + + public PlatformID Platform { + get { + return this.platformID; + } + } + + public Version Version { + get { + return this.version; + } + } + + public string ServicePack { + get { + return String.Empty; + } + } + + public string VersionString { + get { + return ToString(); + } + } + + public override string ToString() { + string str; + + switch (this.platformID) { + case PlatformID.Win32NT: + str = "Microsoft Windows NT"; + break; + case PlatformID.Win32S: + str = "Microsoft Win32S"; + break; + case PlatformID.Win32Windows: + str = "Microsoft Windows 98"; + break; + case PlatformID.WinCE: + str = "Microsoft Windows CE"; + break; + case PlatformID.Unix: + str = "Unix"; + break; + default: + str = ""; + break; + } + + return str + " " + this.version.ToString() + " (InterNet2)"; + } + + #region ICloneable Members + + public object Clone() { + return (OperatingSystem)object.Clone(this); + } + + #endregion + } +} + +#endif diff --git a/corlib/System/OverflowException.cs b/corlib/System/OverflowException.cs new file mode 100644 index 0000000..81736ff --- /dev/null +++ b/corlib/System/OverflowException.cs @@ -0,0 +1,12 @@ +#if !LOCALTEST + +namespace System { + public class OverflowException : ArithmeticException { + + public OverflowException() : base("Number overflow.") { } + public OverflowException(string msg) : base(msg) { } + + } +} + +#endif diff --git a/corlib/System/ParamArrayAttribute.cs b/corlib/System/ParamArrayAttribute.cs new file mode 100644 index 0000000..b2cb2cf --- /dev/null +++ b/corlib/System/ParamArrayAttribute.cs @@ -0,0 +1,14 @@ +#if !LOCALTEST + +using System; + +namespace System { + public sealed class ParamArrayAttribute : Attribute { + + public ParamArrayAttribute() { + } + + } +} + +#endif diff --git a/corlib/System/ParseHelper.cs b/corlib/System/ParseHelper.cs new file mode 100644 index 0000000..cc2324d --- /dev/null +++ b/corlib/System/ParseHelper.cs @@ -0,0 +1,364 @@ +#if !LOCALTEST + +using System.Globalization; +using System.Threading; +namespace System { + internal static class ParseHelper { + + private static bool CheckStyle(NumberStyles style, bool tryParse, ref Exception exc) { + if ((style & NumberStyles.AllowHexSpecifier) != 0) { + NumberStyles ne = style ^ NumberStyles.AllowHexSpecifier; + if ((ne & NumberStyles.AllowLeadingWhite) != 0) { + ne ^= NumberStyles.AllowLeadingWhite; + } + if ((ne & NumberStyles.AllowTrailingWhite) != 0) { + ne ^= NumberStyles.AllowTrailingWhite; + } + if (ne != 0) { + if (!tryParse) { + exc = new ArgumentException( + "With AllowHexSpecifier only " + + "AllowLeadingWhite and AllowTrailingWhite " + + "are permitted."); + } + return false; + } + } + + return true; + } + + private static bool JumpOverWhite(ref int pos, string s, bool reportError, bool tryParse, ref Exception exc) { + while (pos < s.Length && Char.IsWhiteSpace(s[pos])) { + pos++; + } + if (reportError && pos >= s.Length) { + if (!tryParse) { + exc = GetFormatException(); + } + return false; + } + + return true; + } + + private static void FindSign(ref int pos, string s, NumberFormatInfo nfi, + ref bool foundSign, ref bool negative) { + if ((pos + nfi.NegativeSign.Length) <= s.Length && + s.IndexOf(nfi.NegativeSign, pos, nfi.NegativeSign.Length) == pos) { + negative = true; + foundSign = true; + pos += nfi.NegativeSign.Length; + } else if ((pos + nfi.PositiveSign.Length) < s.Length && + s.IndexOf(nfi.PositiveSign, pos, nfi.PositiveSign.Length) == pos) { + negative = false; + pos += nfi.PositiveSign.Length; + foundSign = true; + } + } + + private static void FindCurrency(ref int pos, string s, NumberFormatInfo nfi, ref bool foundCurrency) { + if ((pos + nfi.CurrencySymbol.Length) <= s.Length && + s.Substring(pos, nfi.CurrencySymbol.Length) == nfi.CurrencySymbol) { + foundCurrency = true; + pos += nfi.CurrencySymbol.Length; + } + } + + private static bool FindExponent(ref int pos, string s) { + int i = s.IndexOfAny(new char[] { 'e', 'E' }, pos); + if (i < 0) { + return false; + } + if (++i == s.Length) { + return false; + } + if (s[i] == '+' || s[i] == '-') { + if (++i == s.Length) { + return false; + } + } + if (!Char.IsDigit(s[i])) { + return false; + } + for (; i < s.Length; ++i) { + if (!Char.IsDigit(s[i])) { + break; + } + } + pos = i; + return true; + } + + private static bool FindOther(ref int pos, string s, string other) { + if ((pos + other.Length) <= s.Length && s.Substring(pos, other.Length) == other) { + pos += other.Length; + return true; + } + return false; + } + + private static bool ValidDigit(char e, bool allowHex) { + if (allowHex) { + return Char.IsDigit(e) || (e >= 'A' && e <= 'F') || (e >= 'a' && e <= 'f'); + } + return Char.IsDigit(e); + } + + private static Exception GetFormatException() { + return new FormatException("Input string was not in the correct format"); + } + + internal static bool Parse(string s, NumberStyles style, IFormatProvider fp, bool tryParse, out int result, out Exception exc) { + result = 0; + exc = null; + + if (s == null) { + if (!tryParse) { + exc = GetFormatException(); + } + return false; + } + + if (s == null) { + if (!tryParse) { + exc = new ArgumentNullException(); + } + return false; + } + + if (s.Length == 0) { + if (!tryParse) { + exc = GetFormatException(); + } + return false; + } + + NumberFormatInfo nfi; + if (fp != null) { + Type typeNFI = typeof(System.Globalization.NumberFormatInfo); + nfi = (NumberFormatInfo)fp.GetFormat(typeNFI); + } else { + nfi = Thread.CurrentThread.CurrentCulture.NumberFormat; + } + if (!CheckStyle(style, tryParse, ref exc)) { + return false; + } + bool AllowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) != 0; + bool AllowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) != 0; + bool AllowThousands = (style & NumberStyles.AllowThousands) != 0; + bool AllowDecimalPoint = (style & NumberStyles.AllowDecimalPoint) != 0; + bool AllowParentheses = (style & NumberStyles.AllowParentheses) != 0; + bool AllowTrailingSign = (style & NumberStyles.AllowTrailingSign) != 0; + bool AllowLeadingSign = (style & NumberStyles.AllowLeadingSign) != 0; + bool AllowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) != 0; + bool AllowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) != 0; + bool AllowExponent = (style & NumberStyles.AllowExponent) != 0; + + int pos = 0; + + if (AllowLeadingWhite && !JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { + return false; + } + + bool foundOpenParentheses = false; + bool negative = false; + bool foundSign = false; + bool foundCurrency = false; + + // Pre-number stuff + if (AllowParentheses && s[pos] == '(') { + foundOpenParentheses = true; + foundSign = true; + negative = true; // MS always make the number negative when there parentheses + // even when NumberFormatInfo.NumberNegativePattern != 0!!! + pos++; + if (AllowLeadingWhite && !!JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { + return false; + } + if (s.Substring(pos, nfi.NegativeSign.Length) == nfi.NegativeSign) { + if (!tryParse) { + exc = GetFormatException(); + } + return false; + } + + if (s.Substring(pos, nfi.PositiveSign.Length) == nfi.PositiveSign) { + if (!tryParse) { + exc = GetFormatException(); + } + return false; + } + } + + if (AllowLeadingSign && !foundSign) { + // Sign + Currency + FindSign(ref pos, s, nfi, ref foundSign, ref negative); + if (foundSign) { + if (AllowLeadingWhite && !JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { + return false; + } + if (AllowCurrencySymbol) { + FindCurrency(ref pos, s, nfi, ref foundCurrency); + if (foundCurrency && AllowLeadingWhite && !JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { + return false; + } + } + } + } + + if (AllowCurrencySymbol && !foundCurrency) { + // Currency + sign + FindCurrency(ref pos, s, nfi, ref foundCurrency); + if (foundCurrency) { + if (AllowLeadingWhite && !JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { + return false; + } + if (foundCurrency) { + if (!foundSign && AllowLeadingSign) { + FindSign(ref pos, s, nfi, ref foundSign, ref negative); + if (foundSign && AllowLeadingWhite && !JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { + return false; + } + } + } + } + } + + int number = 0; + int nDigits = 0; + bool decimalPointFound = false; + int digitValue; + char hexDigit; + + // Number stuff + do { + if (!ValidDigit(s[pos], AllowHexSpecifier)) { + if (AllowThousands && FindOther(ref pos, s, nfi.NumberGroupSeparator)) { + continue; + } else { + if (!decimalPointFound && AllowDecimalPoint && FindOther(ref pos, s, nfi.NumberDecimalSeparator)) { + decimalPointFound = true; + continue; + } + } + break; + } else if (AllowHexSpecifier) { + nDigits++; + hexDigit = s[pos++]; + if (Char.IsDigit(hexDigit)) { + digitValue = (int)(hexDigit - '0'); + } else if (Char.IsLower(hexDigit)) { + digitValue = (int)(hexDigit - 'a' + 10); + } else { + digitValue = (int)(hexDigit - 'A' + 10); + } + uint unumber = (uint)number; + try { + number = (int)checked(unumber * 16u + (uint)digitValue); + } catch (OverflowException e) { + exc = e; + return false; + } + } else if (decimalPointFound) { + nDigits++; + // Allows decimal point as long as it's only + // followed by zeroes. + if (s[pos++] != '0') { + if (!tryParse) { + exc = new OverflowException("Value too large or too small."); + } + return false; + } + } else { + nDigits++; + + try { + // Calculations done as negative + // (abs (MinValue) > abs (MaxValue)) + number = checked( + number * 10 - + (int)(s[pos++] - '0') + ); + } catch (OverflowException) { + if (!tryParse) { + exc = new OverflowException("Value too large or too small."); + } + return false; + } + } + } while (pos < s.Length); + + // Post number stuff + if (nDigits == 0) { + if (!tryParse) { + exc = GetFormatException(); + } + return false; + } + + if (AllowExponent) { + FindExponent(ref pos, s); + } + if (AllowTrailingSign && !foundSign) { + // Sign + Currency + FindSign(ref pos, s, nfi, ref foundSign, ref negative); + if (foundSign) { + if (AllowTrailingWhite && !JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { + return false; + } + if (AllowCurrencySymbol) { + FindCurrency(ref pos, s, nfi, ref foundCurrency); + } + } + } + + if (AllowCurrencySymbol && !foundCurrency) { + // Currency + sign + FindCurrency(ref pos, s, nfi, ref foundCurrency); + if (foundCurrency) { + if (AllowTrailingWhite && !JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { + return false; + } + if (!foundSign && AllowTrailingSign) { + FindSign(ref pos, s, nfi, ref foundSign, ref negative); + } + } + } + + if (AllowTrailingWhite && pos < s.Length && !JumpOverWhite(ref pos, s, false, tryParse, ref exc)) { + return false; + } + + if (foundOpenParentheses) { + if (pos >= s.Length || s[pos++] != ')') { + if (!tryParse) { + exc = GetFormatException(); + } + return false; + } + if (AllowTrailingWhite && pos < s.Length && !JumpOverWhite(ref pos, s, false, tryParse, ref exc)) { + return false; + } + } + + if (pos < s.Length && s[pos] != '\u0000') { + if (!tryParse) { + exc = GetFormatException(); + } + return false; + } + + if (!negative && !AllowHexSpecifier) { + number = checked(-number); + } + + result = number; + + return true; + } + + } +} + +#endif diff --git a/corlib/System/PlatformID.cs b/corlib/System/PlatformID.cs new file mode 100644 index 0000000..067802b --- /dev/null +++ b/corlib/System/PlatformID.cs @@ -0,0 +1,13 @@ +#if !LOCALTEST + +namespace System { + public enum PlatformID { + Win32S = 0, + Win32Windows = 1, + Win32NT = 2, + WinCE = 3, + Unix = 4 + } +} + +#endif diff --git a/corlib/System/Predicate.cs b/corlib/System/Predicate.cs new file mode 100644 index 0000000..6073b65 --- /dev/null +++ b/corlib/System/Predicate.cs @@ -0,0 +1,7 @@ +#if !LOCALTEST + +namespace System { + public delegate bool Predicate(T obj); +} + +#endif diff --git a/corlib/System/Random.cs b/corlib/System/Random.cs new file mode 100644 index 0000000..47eb541 --- /dev/null +++ b/corlib/System/Random.cs @@ -0,0 +1,81 @@ +#if LOCALTEST +using System; +namespace System_ { +#else +namespace System { +#endif + public class Random { + + private const int MBIG = int.MaxValue; + private const int MSEED = 161803398; + private const int MZ = 0; + + private int inext, inextp; + private int[] SeedArray = new int[56]; + + public Random() : this(Environment.TickCount) { } + + public Random(int seed) { + int ii; + int mj, mk; + + // Numerical Recipes in C online @ http://www.library.cornell.edu/nr/bookcpdf/c7-1.pdf + mj = MSEED - Math.Abs(seed); + SeedArray[55] = mj; + mk = 1; + for (int i = 1; i < 55; i++) { // [1, 55] is special (Knuth) + ii = (21 * i) % 55; + SeedArray[ii] = mk; + mk = mj - mk; + if (mk < 0) + mk += MBIG; + mj = SeedArray[ii]; + } + for (int k = 1; k < 5; k++) { + for (int i = 1; i < 56; i++) { + SeedArray[i] -= SeedArray[1 + (i + 30) % 55]; + if (SeedArray[i] < 0) + SeedArray[i] += MBIG; + } + } + inext = 0; + inextp = 31; + } + + public int Next() { + return Next(0, int.MaxValue); + } + + public int Next(int maxValue) { + if (maxValue < 0) { + throw new ArgumentOutOfRangeException("maxValue"); + } + return Next(0, maxValue); + } + + public int Next(int minValue, int maxValue) { + if (minValue > maxValue) { + throw new ArgumentOutOfRangeException(); + } + + if (++inext >= 56) { + inext = 1; + } + if (++inextp >= 56) { + inextp = 1; + } + + int retVal = SeedArray[inext] - SeedArray[inextp]; + if (retVal < 0) { + retVal += MBIG; + } + SeedArray[inext] = retVal; + + if (minValue == maxValue) { + return minValue; + } + return (retVal % (maxValue - minValue)) + minValue; + } + + } +} diff --git a/corlib/System/RuntimeFieldHandle.cs b/corlib/System/RuntimeFieldHandle.cs new file mode 100644 index 0000000..b489407 --- /dev/null +++ b/corlib/System/RuntimeFieldHandle.cs @@ -0,0 +1,20 @@ +#if !LOCALTEST + +namespace System { + public struct RuntimeFieldHandle { + + private IntPtr value; + + internal RuntimeFieldHandle(IntPtr v) { + value = v; + } + + public IntPtr Value { + get { + return value; + } + } + } +} + +#endif diff --git a/corlib/System/RuntimeMethodHandle.cs b/corlib/System/RuntimeMethodHandle.cs new file mode 100644 index 0000000..d0495ce --- /dev/null +++ b/corlib/System/RuntimeMethodHandle.cs @@ -0,0 +1,21 @@ +#if !LOCALTEST + +namespace System { + public struct RuntimeMethodHandle { + + IntPtr value; + + internal RuntimeMethodHandle(IntPtr v) { + value = v; + } + + public IntPtr Value { + get { + return value; + } + } + + } +} + +#endif diff --git a/corlib/System/RuntimeType.cs b/corlib/System/RuntimeType.cs new file mode 100644 index 0000000..c0fd9a6 --- /dev/null +++ b/corlib/System/RuntimeType.cs @@ -0,0 +1,80 @@ +#if !LOCALTEST + +using System.Runtime.CompilerServices; +using System.Text; +using System.Collections.Generic; + +namespace System { + + class RuntimeType : Type { + + [MethodImpl(MethodImplOptions.InternalCall)] + extern private RuntimeType GetNestingParentType(); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern private RuntimeType Internal_GetGenericTypeDefinition(); + + extern public override Type BaseType { + [MethodImpl(MethodImplOptions.InternalCall)] + get; + } + + public extern override bool IsEnum { + [MethodImpl(MethodImplOptions.InternalCall)] + get; + } + + extern public override string Namespace { + [MethodImpl(MethodImplOptions.InternalCall)] + get; + } + + extern public override string Name { + [MethodImpl(MethodImplOptions.InternalCall)] + get; + } + + public override string FullName { + get { + StringBuilder ret = new StringBuilder(32); + ret.Append(this.Namespace); + ret.Append('.'); + RuntimeType nestingParentType = this.GetNestingParentType(); + if (nestingParentType != null) { + List nestingParents = new List(); + nestingParents.Add(nestingParentType); + nestingParentType = nestingParentType.GetNestingParentType(); + while (nestingParentType != null) { + nestingParents.Add(nestingParentType); + nestingParentType = nestingParentType.GetNestingParentType(); + } + for (int ofs = nestingParents.Count - 1; ofs >= 0; ofs--) { + ret.Append(nestingParents[ofs].Name); + ret.Append('+'); + } + } + ret.Append(this.Name); + return ret.ToString(); + } + } + + extern public override bool IsGenericType { + [MethodImpl(MethodImplOptions.InternalCall)] + get; + } + + public override Type GetGenericTypeDefinition() { + if (!this.IsGenericType) { + throw new InvalidOperationException("This is not a generic type"); + } + return this.Internal_GetGenericTypeDefinition(); + } + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public override Type[] GetGenericArguments(); + + } + +} + +#endif diff --git a/corlib/System/RuntimeTypeHandle.cs b/corlib/System/RuntimeTypeHandle.cs new file mode 100644 index 0000000..ca2cbce --- /dev/null +++ b/corlib/System/RuntimeTypeHandle.cs @@ -0,0 +1,20 @@ +#if !LOCALTEST + +namespace System { + public struct RuntimeTypeHandle { + + private IntPtr value; + + internal RuntimeTypeHandle(IntPtr v) { + value = v; + } + + public IntPtr Value { + get { + return value; + } + } + } +} + +#endif diff --git a/corlib/System/SByte.cs b/corlib/System/SByte.cs new file mode 100644 index 0000000..7438b77 --- /dev/null +++ b/corlib/System/SByte.cs @@ -0,0 +1,73 @@ +#if !LOCALTEST + +using System.Globalization; +namespace System { + public struct SByte : IFormattable, IComparable, IComparable, IEquatable { + public const sbyte MinValue = -128; + public const sbyte MaxValue = 127; + + internal sbyte m_value; + + public override bool Equals(object obj) { + return (obj is sbyte) && ((sbyte)obj).m_value == this.m_value; + } + + public override int GetHashCode() { + return (int)this.m_value; + } + + #region ToString methods + + public override string ToString() { + return NumberFormatter.FormatGeneral(new NumberFormatter.NumberStore(this.m_value)); + } + + public string ToString(IFormatProvider formatProvider) { + return NumberFormatter.FormatGeneral(new NumberFormatter.NumberStore(this.m_value), formatProvider); + } + + public string ToString(string format) { + return this.ToString(format, null); + } + + public string ToString(string format, IFormatProvider formatProvider) { + NumberFormatInfo nfi = NumberFormatInfo.GetInstance(formatProvider); + return NumberFormatter.NumberToString(format, this.m_value, nfi); + } + + #endregion + + #region IComparable Members + + public int CompareTo(object obj) { + if (obj == null) { + return 1; + } + if (!(obj is int)) { + throw new ArgumentException(); + } + return this.CompareTo((sbyte)obj); + } + + #endregion + + #region IComparable Members + + public int CompareTo(sbyte x) { + return (this.m_value > x) ? 1 : ((this.m_value < x) ? -1 : 0); + } + + #endregion + + #region IEquatable Members + + public bool Equals(sbyte x) { + return this.m_value == x; + } + + #endregion + + } +} + +#endif \ No newline at end of file diff --git a/corlib/System/Single.cs b/corlib/System/Single.cs new file mode 100644 index 0000000..8dc3392 --- /dev/null +++ b/corlib/System/Single.cs @@ -0,0 +1,108 @@ +#if !LOCALTEST + +using System.Globalization; +namespace System { + public struct Single : IFormattable, IComparable, IComparable, IEquatable { + + public const float Epsilon = 1.4e-45f; + public const float MaxValue = 3.40282346638528859e38f; + public const float MinValue = -3.40282346638528859e38f; + public const float NaN = 0.0f / 0.0f; + public const float PositiveInfinity = 1.0f / 0.0f; + public const float NegativeInfinity = -1.0f / 0.0f; + + private float m_value; + + public static bool IsNaN(float f) { +#pragma warning disable 1718 + return (f != f); +#pragma warning restore + } + + public static bool IsNegativeInfinity(float f) { + return (f < 0.0f && (f == NegativeInfinity || f == PositiveInfinity)); + } + + public static bool IsPositiveInfinity(float f) { + return (f > 0.0f && (f == NegativeInfinity || f == PositiveInfinity)); + } + + public static bool IsInfinity(float f) { + return (f == PositiveInfinity || f == NegativeInfinity); + } + + public override bool Equals(object o) { + if (!(o is Single)) { + return false; + } + if (IsNaN((float)o)) { + return IsNaN(this); + } + return ((float)o).m_value == this.m_value; + } + + public unsafe override int GetHashCode() { + float f = this.m_value; + return (*((int*)&f)).GetHashCode(); + } + + public override string ToString() { + return ToString(null, null); + } + + public string ToString(IFormatProvider provider) { + return ToString(null, provider); + } + + public string ToString(string format) { + return ToString(format, null); + } + + public string ToString(string format, IFormatProvider provider) { + NumberFormatInfo nfi = NumberFormatInfo.GetInstance(provider); + return NumberFormatter.NumberToString(format, this.m_value, nfi); + } + + #region IComparable Members + + public int CompareTo(object obj) { + if (obj == null) { + return 1; + } + if (!(obj is float)) { + throw new ArgumentException(); + } + return this.CompareTo((float)obj); + } + + #endregion + + #region IComparable Members + + public int CompareTo(float x) { + if (float.IsNaN(this.m_value)) { + return float.IsNaN(x) ? 0 : -1; + } + if (float.IsNaN(x)) { + return 1; + } + return (this.m_value > x) ? 1 : ((this.m_value < x) ? -1 : 0); + } + + #endregion + + #region IEquatable Members + + public bool Equals(float x) { + if (float.IsNaN(this.m_value)) { + return float.IsNaN(x); + } + return this.m_value == x; + } + + #endregion + + } +} + +#endif diff --git a/corlib/System/String.cs b/corlib/System/String.cs new file mode 100644 index 0000000..4ca31d9 --- /dev/null +++ b/corlib/System/String.cs @@ -0,0 +1,578 @@ +#if !LOCALTEST + +using System.Runtime.CompilerServices; +using System.Text; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; + +namespace System { + public class String : ICloneable, IEnumerable, IEnumerable, + IComparable, IComparable, IEquatable { + + public static readonly string Empty = ""; + + public static bool IsNullOrEmpty(string value) { + return (value == null) || (value.length == 0); + } + + // This field must be the only field, to tie up with C code + private int length; + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public String(char c, int count); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public String(char[] chars); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public String(char[] chars, int startIndex, int length); + + #region Private Internal Calls + + [MethodImpl(MethodImplOptions.InternalCall)] + extern private String(string str, int startIndex, int length); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern private static string InternalConcat(string str0, string str1); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern private string InternalReplace(string oldValue, string newValue); + + // trimType: bit 0 = start; bit 1 = end + [MethodImpl(MethodImplOptions.InternalCall)] + extern private string InternalTrim(char[] trimChars, int trimType); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern private int InternalIndexOf(char value, int startIndex, int count, bool forwards); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern private int InternalIndexOfAny(char[] anyOf, int startIndex, int count, bool forward); + + #endregion + + public virtual int Length { + get { + return this.length; + } + } + + [IndexerName("Chars")] + extern virtual public char this[int index] { + [MethodImpl(MethodImplOptions.InternalCall)] + get; + } + + #region Misc Methods + + public static string Join(string separator, string[] value) { + return Join(separator, value, 0, value.Length); + } + + public static string Join(string separator, string[] value, int startIndex, int count) { + StringBuilder sb = new StringBuilder(); + for (int i = startIndex; i < count; i++) { + sb.Append(value[i]); + sb.Append(separator); + } + return sb.ToString(0, sb.Length - separator.Length); + } + + public string[] Split(params char[] separator) { + return this.Split(separator, int.MaxValue); + } + + public string[] Split(char[] separator, int count) { + if (count < 0) { + throw new ArgumentException("count"); + } + if (count == 0) { + return new string[0]; + } + if (separator == null || separator.Length == 0) { + separator = char.WhiteChars; + } + + List ret = new List(); + + int pos = 0; + for (; count > 0; count--) { + int sepPos = this.IndexOfAny(separator, pos); + if (sepPos < 0) { + ret.Add(new string(this, pos, this.length - pos)); + break; + } + ret.Add(new string(this, pos, sepPos - pos)); + pos = sepPos + 1; + } + + return ret.ToArray(); + } + + public bool StartsWith(string str) { + return this.Substring(0, str.length) == str; + } + + public bool EndsWith(string str) { + return this.Substring(this.length - str.length, str.length) == str; + } + + #endregion + + #region Concat Methods + + public static string Concat(string str0, string str1) { + if (str0 == null) { + return str1 ?? string.Empty; + } + if (str1 == null) { + return str0; + } + return InternalConcat(str0, str1); + } + + public static string Concat(string str0, string str1, string str2) { + return Concat(Concat(str0, str1), str2); + } + + public static string Concat(string str0, string str1, string str2, string str3) { + return Concat(Concat(str0, str1), Concat(str2, str3)); + } + + public static string Concat(params string[] values) { + if (values == null) { + throw new ArgumentNullException("args"); + } + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < values.Length; i++) { + sb.Append(values[i]); + } + return sb.ToString(); + } + + public static string Concat(object obj0) { + return obj0.ToString(); + } + + public static string Concat(object obj0, object obj1) { + string str0 = (obj0 == null) ? null : obj0.ToString(); + string str1 = (obj1 == null) ? null : obj1.ToString(); + if (str0 == null) { + return str1 ?? string.Empty; + } + if (str1 == null) { + return str0; + } + return InternalConcat(str0, str1); + } + + public static string Concat(object obj0, object obj1, object obj2) { + return Concat(new object[] { obj0, obj1, obj2 }); + } + + public static string Concat(object obj0, object obj1, object obj2, object obj3) { + return Concat(new object[] { obj0, obj1, obj2, obj3 }); + } + + public static string Concat(params object[] objs) { + if (objs == null) { + throw new ArgumentNullException("args"); + } + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < objs.Length; i++) { + sb.Append(objs[i]); + } + return sb.ToString(); + } + + #endregion + + #region Trim Methods + + public string Trim(params char[] trimChars) { + if (trimChars == null || trimChars.Length == 0) { + trimChars = char.WhiteChars; + } + return InternalTrim(trimChars, 3); + } + + public string Trim() { + return InternalTrim(char.WhiteChars, 3); + } + + public string TrimStart(params char[] trimChars) { + if (trimChars == null || trimChars.Length == 0) { + trimChars = char.WhiteChars; + } + return InternalTrim(trimChars, 1); + } + + public string TrimEnd(params char[] trimChars) { + if (trimChars == null || trimChars.Length == 0) { + trimChars = char.WhiteChars; + } + return InternalTrim(trimChars, 2); + } + + #endregion + + #region Substring Methods + + public string Substring(int startIndex) { + if (startIndex < 0 || startIndex > this.length) { + throw new ArgumentOutOfRangeException(); + } + + return new string(this, startIndex, this.length - startIndex); + } + + public string Substring(int startIndex, int length) { + if (startIndex < 0 || length < 0 || startIndex + length > this.length) { + throw new ArgumentOutOfRangeException(); + } + + return new string(this, startIndex, length); + } + + #endregion + + #region Format Methods + + public static string Format(string format, object obj0) { + return Format(null, format, new object[] { obj0 }); + } + + public static string Format(string format, object obj0, object obj1) { + return Format(null, format, new object[] { obj0, obj1 }); + } + + public static string Format(string format, object obj0, object obj1, object obj2) { + return Format(null, format, new object[] { obj0, obj1, obj2 }); + } + + public static string Format(string format, params object[] args) { + return Format(null, format, args); + } + + public static string Format(IFormatProvider provider, string format, params object[] args) { + StringBuilder sb = new StringBuilder(); + StringHelper.FormatHelper(sb, provider, format, args); + return sb.ToString(); + } + + #endregion + + #region Replace & Remove Methods + + public string Replace(char oldChar, char newChar) { + StringBuilder sb = new StringBuilder(this); + return sb.Replace(oldChar, newChar).ToString(); + } + + public string Replace(string oldValue, string newValue) { + if (oldValue == null) { + throw new ArgumentNullException("oldValue"); + } + if (oldValue.Length == 0) { + throw new ArgumentException("oldValue is an empty string."); + } + if (this.length == 0) { + return this; + } + if (newValue == null) { + newValue = string.Empty; + } + return InternalReplace(oldValue, newValue); + } + + public string Remove(int startIndex) { + if (startIndex < 0 || startIndex >= this.length) { + throw new ArgumentOutOfRangeException("startIndex"); + } + return new string(this, 0, startIndex); + } + + public string Remove(int startIndex, int count) { + if (startIndex < 0 || count < 0 || startIndex + count >= this.length) { + throw new ArgumentOutOfRangeException(); + } + int pos2 = startIndex+count; + return (new string(this, 0, startIndex)) + (new string(this, pos2, this.length - pos2)); + } + + #endregion + + #region Compare and CompareOrdinal Methods + + public static int Compare(string strA, string strB) { + return CompareOrdinal(strA, strB); + } + + public static int Compare(string strA, int indexA, string strB, int indexB, int length) { + return CompareOrdinal(strA.Substring(indexA, length), strB.Substring(indexB, length)); + } + + public static int CompareOrdinal(string strA, string strB) { + if (strA == null) { + if (strB == null) { + return 0; + } + return -1; + } + if (strB == null) { + return 1; + } + int top = Math.Min(strA.Length, strB.Length); + for (int i = 0; i < top; i++) { + if (strA[i] != strB[i]) { + return (strA[i] - strB[i]); + } + } + return strA.Length - strB.Length; + } + + #endregion + + #region IndexOf... Methods + + public int IndexOf(string value) { + return IndexOf(value, 0, this.length); + } + + public int IndexOf(string value, int startIndex) { + return IndexOf(value, startIndex, this.length - startIndex); + } + + public int IndexOf(string value, int startIndex, int count) { + if (value == null) { + throw new ArgumentNullException("value"); + } + if (startIndex < 0 || count < 0 || startIndex + count > this.length) { + throw new ArgumentOutOfRangeException(); + } + if (value.length == 0) { + return startIndex; + } + int valueLen = value.length; + int finalIndex = startIndex + count - valueLen + 1; + char char0 = value[0]; + for (int i = startIndex; i < finalIndex; i++) { + if (this[i] == char0) { + bool ok = true; + for (int j = 1; j < valueLen; j++) { + if (this[i + j] != value[j]) { + ok = false; + break; + } + } + if (ok) { + return i; + } + } + } + return -1; + } + + public int IndexOf(char value) { + return this.IndexOf(value, 0, this.length, true); + } + + public int IndexOf(char value, int startIndex) { + return this.IndexOf(value, startIndex, this.length - startIndex, true); + } + + public int IndexOf(char value, int startIndex, int count) { + return this.IndexOf(value, startIndex, count, true); + } + + public int LastIndexOf(char value) { + return this.IndexOf(value, 0, this.length, false); + } + + public int LastIndexOf(char value, int startIndex) { + return this.IndexOf(value, startIndex, this.length - startIndex, false); + } + + public int LastIndexOf(char value, int startIndex, int count) { + return this.IndexOf(value, startIndex, count, false); + } + + private int IndexOf(char value, int startIndex, int count, bool forwards) { + if (startIndex < 0 || count < 0 || startIndex + count > this.length) { + throw new ArgumentOutOfRangeException(); + } + return this.InternalIndexOf(value, startIndex, count, forwards); + } + + public int IndexOfAny(char[] anyOf) { + return this.IndexOfAny(anyOf, 0, this.length, true); + } + + public int IndexOfAny(char[] anyOf, int startIndex) { + return this.IndexOfAny(anyOf, startIndex, this.length - startIndex, true); + } + + public int IndexOfAny(char[] anyOf, int startIndex, int count) { + return this.IndexOfAny(anyOf, startIndex, count, true); + } + + public int LastIndexOfAny(char[] anyOf) { + return this.IndexOfAny(anyOf, 0, this.length, false); + } + + public int LastIndexOfAny(char[] anyOf, int startIndex) { + return this.IndexOfAny(anyOf, startIndex, this.length - startIndex, false); + } + + public int LastIndexOfAny(char[] anyOf, int startIndex, int count) { + return this.IndexOfAny(anyOf, startIndex, count, false); + } + + private int IndexOfAny(char[] anyOf, int startIndex, int count, bool forward) { + if (startIndex < 0 || count < 0 || startIndex + count > this.length) { + throw new ArgumentOutOfRangeException(); + } + /*int anyOfLen = anyOf.Length; + int finIndex = (forward) ? (startIndex + count) : (startIndex - 1); + int inc = (forward) ? 1 : -1; + for (int i = (forward) ? startIndex : (startIndex + count - 1); i != finIndex; i += inc) { + char c = this[i]; + for (int j = 0; j < anyOfLen; j++) { + if (c == anyOf[j]) { + return i; + } + } + } + return -1;*/ + return this.InternalIndexOfAny(anyOf, startIndex, count, forward); + } + + #endregion + + #region Case methods + + public string ToLower() { + return ToLower(CultureInfo.CurrentCulture); + } + + public string ToLower(CultureInfo culture) { + if (culture == null) { + throw new ArgumentNullException("culture"); + } + if (culture.LCID == 0x007f) { + return ToLowerInvariant(); + } + return culture.TextInfo.ToLower(this); + } + + public string ToLowerInvariant() { + int len = this.length; + StringBuilder sb = new StringBuilder(len); + for (int i = 0; i < len; i++) { + sb.Append(char.ToLowerInvariant(this[i])); + } + return sb.ToString(); + } + + public string ToUpper() { + return ToLower(CultureInfo.CurrentCulture); + } + + public string ToUpper(CultureInfo culture) { + if (culture == null) { + throw new ArgumentNullException("culture"); + } + if (culture.LCID == 0x007f) { + return ToUpperInvariant(); + } + return culture.TextInfo.ToUpper(this); + } + + public string ToUpperInvariant() { + int len = this.length; + StringBuilder sb = new StringBuilder(len); + for (int i = 0; i < len; i++) { + sb.Append(char.ToUpperInvariant(this[i])); + } + return sb.ToString(); + } + + #endregion + + #region Overrides and Operators + + public override string ToString() { + return this; + } + + public override bool Equals(object obj) { + return Equals(this, obj as string); + } + + public static bool operator ==(string a, string b) { + return Equals(a, b); + } + + public static bool operator !=(string a, string b) { + return !Equals(a, b); + } + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public static bool Equals(string a, string b); + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public override int GetHashCode(); + + #endregion + + #region IClonable Members + + public object Clone() { + return this; + } + + #endregion + + #region IComparable Members + + public int CompareTo(object value) { + if (value == null) { + return 1; + } + if (!(value is string)) { + throw new ArgumentException(); + } + return string.Compare(this, (string)value); + } + + public int CompareTo(string value) { + if (value == null) + return 1; + + return string.Compare(this, value); + } + + #endregion + + #region IEquatable Members + + public bool Equals(string other) { + return Equals(this, other); + } + + #endregion + + #region IEnumerable Members + + public IEnumerator GetEnumerator() { + return new CharEnumerator(this); + } + + IEnumerator IEnumerable.GetEnumerator() { + return new CharEnumerator(this); + } + + #endregion + } +} +#endif diff --git a/corlib/System/StringComparison.cs b/corlib/System/StringComparison.cs new file mode 100644 index 0000000..c61949b --- /dev/null +++ b/corlib/System/StringComparison.cs @@ -0,0 +1,14 @@ +#if !LOCALTEST + +namespace System { + public enum StringComparison { + CurrentCulture, + CurrentCultureIgnoreCase, + InvariantCulture, + InvariantCultureIgnoreCase, + Ordinal, + OrdinalIgnoreCase + } +} + +#endif diff --git a/corlib/System/StringHelper.cs b/corlib/System/StringHelper.cs new file mode 100644 index 0000000..242477b --- /dev/null +++ b/corlib/System/StringHelper.cs @@ -0,0 +1,158 @@ + +#if LOCALTEST +using System; +using System_.Text; +namespace System_ { +#else +using System.Text; +namespace System { +#endif + internal static class StringHelper { + + private static int ParseDecimal(string str, ref int ptr) { + int p = ptr; + int n = 0; + while (true) { + char c = str[p]; + if (c < '0' || c > '9') { + break; + } + n = n * 10 + c - '0'; + ++p; + } + if (p == ptr) { + return -1; + } + ptr = p; + return n; + } + + private static void ParseFormatSpecifier(string str, ref int ptr, out int n, out int width, out bool leftAlign, out string format) { + // parses format specifier of form: + // N,[\ +[-]M][:F]} + // + // where: + try { + // N = argument number (non-negative integer) + n = ParseDecimal(str, ref ptr); + if (n < 0) { + throw new FormatException("Input string was not in a correct format."); + } + // M = width (non-negative integer) + if (str[ptr] == ',') { + // White space between ',' and number or sign. + ++ptr; + while (char.IsWhiteSpace(str[ptr])) { + ++ptr; + } + int start = ptr; + + format = str.Substring(start, ptr - start); + + leftAlign = (str[ptr] == '-'); + if (leftAlign) { + ++ptr; + } + width = ParseDecimal(str, ref ptr); + if (width < 0) { + throw new FormatException("Input string was not in a correct format."); + } + } else { + width = 0; + leftAlign = false; + format = string.Empty; + } + + // F = argument format (string) + + if (str[ptr] == ':') { + int start = ++ptr; + while (str[ptr] != '}') { + ++ptr; + } + format += str.Substring(start, ptr - start); + } else + format = null; + + if (str[ptr++] != '}') { + throw new FormatException("Input string was not in a correct format."); + } + } catch (IndexOutOfRangeException) { + throw new FormatException("Input string was not in a correct format."); + } + } + + internal static void FormatHelper(StringBuilder result, IFormatProvider provider, string format, params object[] args) { + + if (format == null || args == null) { + throw new ArgumentNullException(); + } + + int ptr = 0, start = 0, formatLen = format.Length; + while (ptr < formatLen) { + char c = format[ptr++]; + if (c == '{') { + result.Append(format, start, ptr - start - 1); + if (format[ptr] == '{') { + // If a "{{" is found then it's not a format specifier, so just continue + start = ptr++; + continue; + } + // Start of format specifier, so parse it + int n, width; + bool leftAlign; + string argFormat; + + ParseFormatSpecifier (format, ref ptr, out n, out width, out leftAlign, out argFormat); + if (n >= args.Length) { + throw new FormatException("Index (zero based) must be greater than or equal to zero and less than the size of the argument list."); + } + // Format the argument + object arg = args[n]; + string str; + ICustomFormatter formatter = null; + if (provider != null) { + formatter = provider.GetFormat(typeof(ICustomFormatter)) as ICustomFormatter; + } + if (arg == null) { + str = string.Empty; + } else if (formatter != null) { + str = formatter.Format(argFormat, arg, provider); + } else if (arg is IFormattable) { + str = ((IFormattable)arg).ToString(argFormat, provider); + } else { + str = arg.ToString(); + } + // Apply any padding needed and append to result + if (width > str.Length) { + int padLen = width - str.Length; + if (leftAlign) { + result.Append(str); + result.Append(' ', padLen); + } else { + result.Append(' ', padLen); + result.Append(str); + } + } else { + result.Append(str); + } + start = ptr; + } else if (c == '}') { + if (ptr < formatLen && format[ptr] == '}') { + // Handle case of "}}" appearing in the string + result.Append(format, start, ptr - start - 1); + start = ptr++; + } else { + // single "}" not allowed without "{" beforehand + throw new FormatException("Input string was not of the correct format."); + } + } + } + + if (start < formatLen) { + result.Append(format, start, formatLen - start); + } + } + + } +} diff --git a/corlib/System/SystemException.cs b/corlib/System/SystemException.cs new file mode 100644 index 0000000..e15ff56 --- /dev/null +++ b/corlib/System/SystemException.cs @@ -0,0 +1,15 @@ +#if !LOCALTEST + +namespace System { + public class SystemException : Exception { + + public SystemException() : base("A SystemException has occured.") { } + + public SystemException(string message) : base(message) { } + + public SystemException(string message, Exception innerException) : base(message, innerException) { } + + } +} + +#endif diff --git a/corlib/System/TimeSpan.cs b/corlib/System/TimeSpan.cs new file mode 100644 index 0000000..b5d3a72 --- /dev/null +++ b/corlib/System/TimeSpan.cs @@ -0,0 +1,242 @@ +#if !LOCALTEST + +using System.Text; +namespace System { + public struct TimeSpan : IComparable, IComparable, IEquatable { + + public static readonly TimeSpan MaxValue = new TimeSpan(long.MaxValue); + public static readonly TimeSpan MinValue = new TimeSpan(long.MinValue); + public static readonly TimeSpan Zero = new TimeSpan(0L); + + public const long TicksPerDay = 864000000000L; + public const long TicksPerHour = 36000000000L; + public const long TicksPerMillisecond = 10000L; + public const long TicksPerMinute = 600000000L; + public const long TicksPerSecond = 10000000L; + + private long ticks; + + public TimeSpan(long ticks) { + this.ticks = ticks; + } + + public TimeSpan(int hours, int minutes, int seconds) { + this.ticks = CalcTicks(0, hours, minutes, seconds, 0); + } + + public TimeSpan(int days, int hours, int minutes, int seconds) { + this.ticks = CalcTicks(days, hours, minutes, seconds, 0); + } + + public TimeSpan(int days, int hours, int minutes, int seconds, int milliseconds) { + this.ticks = CalcTicks(days, hours, minutes, seconds, milliseconds); + } + + private static long CalcTicks(int days, int hours, int minutes, int seconds, int millis) { + long t; + t = (long)days * TicksPerDay + + (long)hours * TicksPerHour + (long)minutes * TicksPerMinute + + (long)seconds * TicksPerSecond + (long)millis * TicksPerMillisecond; + return t; + } + + public int Days { + get { + return (int)(this.ticks / TicksPerDay); + } + } + + public int Hours { + get { + return (int)((this.ticks % TicksPerDay) / TicksPerHour); + } + } + + public int Minutes { + get { + return (int)((this.ticks % TicksPerHour) / TicksPerMinute); + } + } + + public int Seconds { + get { + return (int)((this.ticks % TicksPerMinute) / TicksPerSecond); + } + } + + public int MilliSeconds { + get { + return (int)((this.ticks % TicksPerSecond) / TicksPerMillisecond); + } + } + + public long Ticks { + get { + return this.ticks; + } + } + + public double TotalDays { + get { + return ((double)this.ticks) / ((double)TicksPerDay); + } + } + + public double TotalHours { + get { + return ((double)this.ticks) / ((double)TicksPerHour); + } + } + + public double TotalMinutes { + get { + return ((double)this.ticks) / ((double)TicksPerMinute); + } + } + + public double TotalSeconds { + get { + return ((double)this.ticks) / ((double)TicksPerSecond); + } + } + + public double TotalMilliseconds { + get { + return ((double)this.ticks) / ((double)TicksPerMillisecond); + } + } + + public TimeSpan Add(TimeSpan ts) { + return new TimeSpan(this.ticks + ts.ticks); + } + + public TimeSpan Subtract(TimeSpan ts) { + return new TimeSpan(this.ticks - ts.ticks); + } + + public TimeSpan Negate(TimeSpan ts) { + return new TimeSpan(-this.ticks); + } + + public TimeSpan Duration() { + return new TimeSpan(Math.Abs(this.ticks)); + } + + public static int Compare(TimeSpan t1, TimeSpan t2) { + if (t1.ticks < t2.ticks) { + return -1; + } + if (t1.ticks > t2.ticks) { + return 1; + } + return 0; + } + + #region IComparable Members + + public int CompareTo(object obj) { + if (obj == null) { + return 1; + } + if (!(obj is TimeSpan)) { + throw new ArgumentException("Object must be a TimeSpan"); + } + return Compare(this, (TimeSpan)obj); + } + + #endregion + + #region IComparable Members + + public int CompareTo(TimeSpan x) { + return Compare(this, x); + } + + #endregion + + #region IEquatable Members + + public bool Equals(TimeSpan x) { + return this.ticks == x.ticks; + } + + #endregion + + public override int GetHashCode() { + return this.ticks.GetHashCode(); + } + + public override bool Equals(object obj) { + if (!(obj is TimeSpan)) { + return false; + } + return this.ticks == ((TimeSpan)obj).ticks; + } + + public static bool Equals(TimeSpan t1, TimeSpan t2) { + return t1.ticks == t2.ticks; + } + + public override string ToString() { + StringBuilder sb = new StringBuilder(14); + + if (this.ticks < 0) { + sb.Append('-'); + } + if (this.Days != 0) { + sb.Append(Math.Abs(this.Days)); + sb.Append('.'); + } + sb.AppendFormat("{0:D2}:{1:D2}:{2:D2}", + Math.Abs(this.Hours), Math.Abs(this.Minutes), Math.Abs(this.Seconds)); + if (this.MilliSeconds != 0) { + sb.Append('.'); + sb.AppendFormat("{0:D7}", Math.Abs(this.MilliSeconds) * (int)TicksPerMillisecond); + } + + return sb.ToString(); + } + + public static TimeSpan operator +(TimeSpan t1, TimeSpan t2) { + return new TimeSpan(t1.ticks + t2.ticks); + } + + public static TimeSpan operator -(TimeSpan t1, TimeSpan t2) { + return new TimeSpan(t1.ticks - t2.ticks); + } + + public static bool operator ==(TimeSpan t1, TimeSpan t2) { + return t1.ticks == t2.ticks; + } + + public static bool operator !=(TimeSpan t1, TimeSpan t2) { + return t1.ticks != t2.ticks; + } + + public static bool operator >(TimeSpan t1, TimeSpan t2) { + return t1.ticks > t2.ticks; + } + + public static bool operator >=(TimeSpan t1, TimeSpan t2) { + return t1.ticks >= t2.ticks; + } + + public static bool operator <(TimeSpan t1, TimeSpan t2) { + return t1.ticks < t2.ticks; + } + + public static bool operator <=(TimeSpan t1, TimeSpan t2) { + return t1.ticks <= t2.ticks; + } + + public static TimeSpan operator +(TimeSpan ts) { + return ts; + } + + public static TimeSpan operator -(TimeSpan ts) { + return new TimeSpan(-ts.ticks); + } + } +} + +#endif diff --git a/corlib/System/Type.cs b/corlib/System/Type.cs new file mode 100644 index 0000000..758a9ad --- /dev/null +++ b/corlib/System/Type.cs @@ -0,0 +1,49 @@ +#if !LOCALTEST + +using System.Runtime.CompilerServices; +using System.Reflection; + +namespace System { + public abstract class Type : MemberInfo { + + public static readonly Type[] EmptyTypes = new Type[0]; + + [MethodImpl(MethodImplOptions.InternalCall)] + extern public static Type GetTypeFromHandle(RuntimeTypeHandle handle); + + public abstract Type BaseType { + get; + } + + public abstract bool IsEnum { + get; + } + + public abstract string Namespace { + get; + } + + public abstract string FullName { + get; + } + + public abstract bool IsGenericType { + get; + } + + public abstract Type GetGenericTypeDefinition(); + + public abstract Type[] GetGenericArguments(); + + extern public bool IsValueType { + [MethodImpl(MethodImplOptions.InternalCall)] + get; + } + + public override string ToString() { + return this.FullName; + } + } +} + +#endif diff --git a/corlib/System/UInt16.cs b/corlib/System/UInt16.cs new file mode 100644 index 0000000..15e93d8 --- /dev/null +++ b/corlib/System/UInt16.cs @@ -0,0 +1,73 @@ +#if !LOCALTEST + +using System.Globalization; +namespace System { + public struct UInt16:IFormattable,IComparable,IComparable,IEquatable { + public const ushort MaxValue = 0xffff; + public const ushort MinValue = 0; + + internal ushort m_value; + + public override bool Equals(object obj) { + return (obj is ushort) && ((ushort)obj).m_value == this.m_value; + } + + public override int GetHashCode() { + return (int)this.m_value; + } + + #region ToString methods + + public override string ToString() { + return NumberFormatter.FormatGeneral(new NumberFormatter.NumberStore(this.m_value)); + } + + public string ToString(IFormatProvider formatProvider) { + return NumberFormatter.FormatGeneral(new NumberFormatter.NumberStore(this.m_value), formatProvider); + } + + public string ToString(string format) { + return this.ToString(format, null); + } + + public string ToString(string format, IFormatProvider formatProvider) { + NumberFormatInfo nfi = NumberFormatInfo.GetInstance(formatProvider); + return NumberFormatter.NumberToString(format, this.m_value, nfi); + } + + #endregion + +#region IComparable Members + + public int CompareTo(object obj) { + if (obj == null) { + return 1; + } + if (!(obj is ushort)) { + throw new ArgumentException(); + } + return this.CompareTo((ushort)obj); + } + + #endregion + + #region IComparable Members + + public int CompareTo(ushort x) { + return (this.m_value > x) ? 1 : ((this.m_value < x) ? -1 : 0); + } + + #endregion + + #region IEquatable Members + + public bool Equals(ushort x) { + return this.m_value == x; + } + + #endregion + + } +} + +#endif diff --git a/corlib/System/UInt32.cs b/corlib/System/UInt32.cs new file mode 100644 index 0000000..081d7bf --- /dev/null +++ b/corlib/System/UInt32.cs @@ -0,0 +1,74 @@ +#if !LOCALTEST + +using System.Runtime.CompilerServices; +using System.Globalization; +namespace System { + public struct UInt32 : IFormattable, IComparable, IComparable, IEquatable { + public const uint MaxValue = 0xffffffff; + public const uint MinValue = 0; + + internal uint m_value; + + public override bool Equals(object obj) { + return (obj is uint) && ((uint)obj).m_value == this.m_value; + } + + public override int GetHashCode() { + return (int)this.m_value; + } + + #region ToString methods + + public override string ToString() { + return NumberFormatter.FormatGeneral(new NumberFormatter.NumberStore(this.m_value)); + } + + public string ToString(IFormatProvider formatProvider) { + return NumberFormatter.FormatGeneral(new NumberFormatter.NumberStore(this.m_value), formatProvider); + } + + public string ToString(string format) { + return ToString(format, null); + } + + public string ToString(string format, IFormatProvider formatProvider) { + NumberFormatInfo nfi = NumberFormatInfo.GetInstance(formatProvider); + return NumberFormatter.NumberToString(format, m_value, nfi); + } + + #endregion + + #region IComparable Members + + public int CompareTo(object obj) { + if (obj == null) { + return 1; + } + if (!(obj is uint)) { + throw new ArgumentException(); + } + return this.CompareTo((uint)obj); + } + + #endregion + + #region IComparable Members + + public int CompareTo(uint x) { + return (this.m_value > x) ? 1 : ((this.m_value < x) ? -1 : 0); + } + + #endregion + + #region IEquatable Members + + public bool Equals(uint x) { + return this.m_value == x; + } + + #endregion + + } +} + +#endif diff --git a/corlib/System/UInt64.cs b/corlib/System/UInt64.cs new file mode 100644 index 0000000..f9daf21 --- /dev/null +++ b/corlib/System/UInt64.cs @@ -0,0 +1,74 @@ +#if !LOCALTEST + +using System.Globalization; +namespace System { + public struct UInt64 : IFormattable, IComparable, IComparable, IEquatable { + + public const ulong MinValue = 0; + public const ulong MaxValue = 0xffffffffffffffffL; + + internal ulong m_value; + + public override bool Equals(object obj) { + return (obj is ulong) && ((ulong)obj).m_value == this.m_value; + } + + public override int GetHashCode() { + return (int)(this.m_value & 0xffffffff) ^ (int)(this.m_value >> 32); + } + + #region ToString methods + + public override string ToString() { + return NumberFormatter.FormatGeneral(new NumberFormatter.NumberStore(this.m_value)); + } + + public string ToString(IFormatProvider formatProvider) { + return NumberFormatter.FormatGeneral(new NumberFormatter.NumberStore(this.m_value), formatProvider); + } + + public string ToString(string format) { + return this.ToString(format, null); + } + + public string ToString(string format, IFormatProvider formatProvider) { + NumberFormatInfo nfi = NumberFormatInfo.GetInstance(formatProvider); + return NumberFormatter.NumberToString(format, this.m_value, nfi); + } + + #endregion + + #region IComparable Members + + public int CompareTo(object obj) { + if (obj == null) { + return 1; + } + if (!(obj is ulong)) { + throw new ArgumentException(); + } + return this.CompareTo((ulong)obj); + } + + #endregion + + #region IComparable Members + + public int CompareTo(ulong x) { + return (this.m_value > x) ? 1 : ((this.m_value < x) ? -1 : 0); + } + + #endregion + + #region IEquatable Members + + public bool Equals(ulong x) { + return this.m_value == x; + } + + #endregion + + } +} + +#endif diff --git a/corlib/System/UIntPtr.cs b/corlib/System/UIntPtr.cs new file mode 100644 index 0000000..2046a9e --- /dev/null +++ b/corlib/System/UIntPtr.cs @@ -0,0 +1,61 @@ +#if !LOCALTEST + +namespace System { + public unsafe struct UIntPtr { + + private void* value; + + public UIntPtr(uint value) { + this.value = (void*)value; + } + + public UIntPtr(ulong value) { + this.value = (void*)value; + } + + public UIntPtr(void* value) { + this.value = value; + } + + public static int Size { + get { + return sizeof(void*); + } + } + + public uint ToUInt32() { + return (uint)this.value; + } + + public ulong ToUInt64() { + return (ulong)this.value; + } + + public override bool Equals(object obj) { + return (obj is UIntPtr && ((UIntPtr)obj).value == this.value); + } + + public override int GetHashCode() { + return (int)this.value; + } + + public static bool operator ==(UIntPtr a, UIntPtr b) { + return a.value == b.value; + } + + public static bool operator !=(UIntPtr a, UIntPtr b) { + return a.value != b.value; + } + + public override string ToString() { + if (Size == 4) { + return string.Format("0x{0:x4}", (int)this.value); + } else { + return string.Format("0x{0:x8}", (long)this.value); + } + } + + } +} + +#endif \ No newline at end of file diff --git a/corlib/System/ValueType.cs b/corlib/System/ValueType.cs new file mode 100644 index 0000000..57669c8 --- /dev/null +++ b/corlib/System/ValueType.cs @@ -0,0 +1,42 @@ +#if !LOCALTEST + +using System.Runtime.CompilerServices; + +namespace System { + public abstract class ValueType { + + protected ValueType() { + } + + [MethodImpl(MethodImplOptions.InternalCall)] + extern private static object[] GetFields(object o1, object o2); + + public override bool Equals(object obj) { + if (obj == null || this.GetType() != obj.GetType()) { + return false; + } + object[] fields = GetFields(this, obj); + int len = fields.Length; + for (int i = 0; i < len; i += 2) { + object meVal = fields[i]; + object youVal = fields[i + 1]; + if (!object.Equals(meVal, youVal)) { + return false; + } + } + return true; + } + + public override int GetHashCode() { + object[] fields = GetFields(this, null); + + int hash = 0; + int len = fields.Length; + for (int i = 0; i < len; i++) { + hash ^= fields[i].GetHashCode(); + } + return hash; + } + } +} +#endif diff --git a/corlib/System/Version.cs b/corlib/System/Version.cs new file mode 100644 index 0000000..dac9571 --- /dev/null +++ b/corlib/System/Version.cs @@ -0,0 +1,335 @@ +#if !LOCALTEST + +namespace System { + + public sealed class Version : ICloneable, IComparable, IComparable, IEquatable { + int _Major, _Minor, _Build, _Revision; + + private const int UNDEFINED = -1; + + private void CheckedSet(int defined, int major, int minor, int build, int revision) { + // defined should be 2, 3 or 4 + + if (major < 0) { + throw new ArgumentOutOfRangeException("major"); + } + this._Major = major; + + if (minor < 0) { + throw new ArgumentOutOfRangeException("minor"); + } + this._Minor = minor; + + if (defined == 2) { + this._Build = UNDEFINED; + this._Revision = UNDEFINED; + return; + } + + if (build < 0) { + throw new ArgumentOutOfRangeException("build"); + } + this._Build = build; + + if (defined == 3) { + this._Revision = UNDEFINED; + return; + } + + if (revision < 0) { + throw new ArgumentOutOfRangeException("revision"); + } + this._Revision = revision; + } + + public Version() { + CheckedSet(2, 0, 0, -1, -1); + } + + public Version(string version) { + int n; + string[] vals; + int major = -1, minor = -1, build = -1, revision = -1; + + if (version == null) { + throw new ArgumentNullException("version"); + } + + vals = version.Split('.'); + n = vals.Length; + + if (n < 2 || n > 4) { + throw new ArgumentException("There must be 2, 3 or 4 components in the version string."); + } + + if (n > 0) { + major = int.Parse(vals[0]); + } + if (n > 1) { + minor = int.Parse(vals[1]); + } + if (n > 2) { + build = int.Parse(vals[2]); + } + if (n > 3) { + revision = int.Parse(vals[3]); + } + + CheckedSet(n, major, minor, build, revision); + } + + public Version(int major, int minor) { + CheckedSet(2, major, minor, 0, 0); + } + + public Version(int major, int minor, int build) { + CheckedSet(3, major, minor, build, 0); + } + + public Version(int major, int minor, int build, int revision) { + CheckedSet(4, major, minor, build, revision); + } + + public int Build { + get { + return _Build; + } + } + + public int Major { + get { + return _Major; + } + } + + public int Minor { + get { + return _Minor; + } + } + + public int Revision { + get { + return _Revision; + } + } + + public short MajorRevision { + get { + return (short)(_Revision >> 16); + } + } + + public short MinorRevision { + get { + return (short)_Revision; + } + } + + public object Clone() { + if (_Build == -1) { + return new Version(_Major, _Minor); + } else if (_Revision == -1) { + return new Version(_Major, _Minor, _Build); + } else { + return new Version(_Major, _Minor, _Build, _Revision); + } + } + + public int CompareTo(object version) { + if (version == null) { + return 1; + } + if (!(version is Version)) { + throw new ArgumentException("Argument to Version.CompareTo must be a Version."); + } + return this.CompareTo((Version)version); + } + + public override bool Equals(object obj) { + return this.Equals(obj as Version); + } + + public int CompareTo(Version v) { + if (v == null) { + return 1; + } + if (this._Major > v._Major) { + return 1; + } else if (this._Major < v._Major) { + return -1; + } + if (this._Minor > v._Minor) { + return 1; + } else if (this._Minor < v._Minor) { + return -1; + } + if (this._Build > v._Build) { + return 1; + } else if (this._Build < v._Build) { + return -1; + } + if (this._Revision > v._Revision) { + return 1; + } else if (this._Revision < v._Revision) { + return -1; + } + return 0; + } + + public bool Equals(Version x) { + return ((x != null) && + (x._Major == _Major) && + (x._Minor == _Minor) && + (x._Build == _Build) && + (x._Revision == _Revision)); + } + + public override int GetHashCode() { + return (_Revision << 24) | (_Build << 16) | (_Minor << 8) | _Major; + } + + // + // Returns a stringified representation of the version, format: + // major.minor[.build[.revision]] + // + public override string ToString() { + string mm = _Major.ToString() + "." + _Minor.ToString(); + + if (_Build != UNDEFINED) { + mm = mm + "." + _Build.ToString(); + } + if (_Revision != UNDEFINED) { + mm = mm + "." + _Revision.ToString(); + } + + return mm; + } + + // + // LAME: This API is lame, since there is no way of knowing + // how many fields a Version object has, it is unfair to throw + // an ArgumentException, but this is what the spec claims. + // + // ie, Version a = new Version (1, 2); a.ToString (3) should + // throw the expcetion. + // + public string ToString(int fields) { + if (fields == 0) { + return String.Empty; + } + if (fields == 1) { + return _Major.ToString(); + } + if (fields == 2) { + return _Major.ToString() + "." + _Minor.ToString(); + } + if (fields == 3) { + if (_Build == UNDEFINED) { + throw new ArgumentException + ("fields is larger than the number of components defined in this instance."); + } + return _Major.ToString() + "." + _Minor.ToString() + "." + _Build.ToString(); + } + if (fields == 4) { + if (_Build == UNDEFINED || _Revision == UNDEFINED) { + throw new ArgumentException + ("fields is larger than the number of components defined in this instance."); + } + return _Major.ToString() + "." + _Minor.ToString() + "." + _Build.ToString() + "." + _Revision.ToString(); + } + throw new ArgumentException("Invalid fields parameter: " + fields.ToString()); + } + + public static bool operator ==(Version v1, Version v2) { + return Equals(v1, v2); + } + + public static bool operator !=(Version v1, Version v2) { + return !Equals(v1, v2); + } + + public static bool operator >(Version v1, Version v2) { + return v1.CompareTo(v2) > 0; + } + + public static bool operator >=(Version v1, Version v2) { + return v1.CompareTo(v2) >= 0; + } + + public static bool operator <(Version v1, Version v2) { + return v1.CompareTo(v2) < 0; + } + + public static bool operator <=(Version v1, Version v2) { + return v1.CompareTo(v2) <= 0; + } + + // a very gentle way to construct a Version object which takes + // the first four numbers in a string as the version + internal static Version CreateFromString(string info) { + int major = 0; + int minor = 0; + int build = 0; + int revision = 0; + int state = 1; + int number = UNDEFINED; // string may not begin with a digit + + if (info == null) { + return new Version(0, 0, 0, 0); + } + for (int i = 0; i < info.Length; i++) { + char c = info[i]; + if (char.IsDigit(c)) { + if (number < 0) { + number = (c - '0'); + } else { + number = (number * 10) + (c - '0'); + } + } else if (number >= 0) { + // assign + switch (state) { + case 1: + major = number; + break; + case 2: + minor = number; + break; + case 3: + build = number; + break; + case 4: + revision = number; + break; + } + number = -1; + state++; + } + // ignore end of string + if (state == 5) + break; + } + + // Last number + if (number >= 0) { + switch (state) { + case 1: + major = number; + break; + case 2: + minor = number; + break; + case 3: + build = number; + break; + case 4: + revision = number; + break; + } + } + return new Version(major, minor, build, revision); + } + } +} + +#endif diff --git a/corlib/System/Void.cs b/corlib/System/Void.cs new file mode 100644 index 0000000..6f60de5 --- /dev/null +++ b/corlib/System/Void.cs @@ -0,0 +1,8 @@ +#if !LOCALTEST + +namespace System { + public struct Void { + } +} + +#endif diff --git a/corlib/System/WeakReference.cs b/corlib/System/WeakReference.cs new file mode 100644 index 0000000..511dc7e --- /dev/null +++ b/corlib/System/WeakReference.cs @@ -0,0 +1,44 @@ +#if !LOCALTEST + +using System.Runtime.CompilerServices; +namespace System { + public class WeakReference { + + // These MUST agree with the definition in System.WeakReference.c + private object target = null; + private bool trackResurrection; + private IntPtr nextWeakRef; + + public WeakReference(object target) : this(target, false) { } + + public WeakReference(object target, bool trackResurrection) { + this.trackResurrection = trackResurrection; + this.Target = target; + } + + ~WeakReference() { + this.Target = null; + } + + public bool TrackResurrection { + get { + return this.trackResurrection; + } + } + + extern public object Target { + [MethodImpl(MethodImplOptions.InternalCall)] + get; + [MethodImpl(MethodImplOptions.InternalCall)] + set; + } + + public bool IsAlive { + get { + return (this.Target != null); + } + } + } +} + +#endif diff --git a/corlib/corlib.csproj b/corlib/corlib.csproj new file mode 100644 index 0000000..1126e9c --- /dev/null +++ b/corlib/corlib.csproj @@ -0,0 +1,288 @@ + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {6A77A7C0-FB66-4CAA-94EE-142DBA20655D} + Library + Properties + corlib + corlib + + + + + 2.0 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + bin\Debug\ + TRACE;DEBUG + prompt + 4 + 512 + Off + true + true + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + Off + true + 512 + true + + + true + bin\LocalTest\ + TRACE;DEBUG;LOCALTEST + 512 + false + full + AnyCPU + true + GlobalSuppressions.cs + Off + prompt + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + False + .NET Framework Client Profile + false + + + False + .NET Framework 2.0 %28x86%29 + true + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + false + + + False + .NET Framework 3.5 SP1 + false + + + + + + copy $(TargetPath) $(SolutionDir)\Builds\$(ConfigurationName)\ + + \ No newline at end of file