Some cosmetic changes; all methods in the StringBuilderHelper are now extension methods; added GarbagePolicy enumeration for StringBuilder helper methods; custom Semaphore is not internal in Windows builds to avoid ambiguous symbols
git-svn-id: file:///srv/devel/repo-conversion/nusu@263 d2e56fa2-650e-0410-a79f-9358c0239efd
This commit is contained in:
parent
1a05bf9d63
commit
07a9de6283
218
Documents/DoubleConverter.txt
Normal file
218
Documents/DoubleConverter.txt
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
From http://www.yoda.arachsys.com/csharp/DoubleConverter.cs
|
||||||
|
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A class to allow the conversion of doubles to string representations of
|
||||||
|
/// their exact decimal values. The implementation aims for readability over
|
||||||
|
/// efficiency.
|
||||||
|
/// </summary>
|
||||||
|
public class DoubleConverter
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the given double to a string representation of its
|
||||||
|
/// exact decimal value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="d">The double to convert.</param>
|
||||||
|
/// <returns>A string representation of the double's exact decimal value.</return>
|
||||||
|
public static string ToExactString (double d)
|
||||||
|
{
|
||||||
|
if (double.IsPositiveInfinity(d))
|
||||||
|
return "+Infinity";
|
||||||
|
if (double.IsNegativeInfinity(d))
|
||||||
|
return "-Infinity";
|
||||||
|
if (double.IsNaN(d))
|
||||||
|
return "NaN";
|
||||||
|
|
||||||
|
// Translate the double into sign, exponent and mantissa.
|
||||||
|
long bits = BitConverter.DoubleToInt64Bits(d);
|
||||||
|
// Note that the shift is sign-extended, hence the test against -1 not 1
|
||||||
|
bool negative = (bits < 0);
|
||||||
|
int exponent = (int) ((bits >> 52) & 0x7ffL);
|
||||||
|
long mantissa = bits & 0xfffffffffffffL;
|
||||||
|
|
||||||
|
// Subnormal numbers; exponent is effectively one higher,
|
||||||
|
// but there's no extra normalisation bit in the mantissa
|
||||||
|
if (exponent==0)
|
||||||
|
{
|
||||||
|
exponent++;
|
||||||
|
}
|
||||||
|
// Normal numbers; leave exponent as it is but add extra
|
||||||
|
// bit to the front of the mantissa
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mantissa = mantissa | (1L<<52);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bias the exponent. It's actually biased by 1023, but we're
|
||||||
|
// treating the mantissa as m.0 rather than 0.m, so we need
|
||||||
|
// to subtract another 52 from it.
|
||||||
|
exponent -= 1075;
|
||||||
|
|
||||||
|
if (mantissa == 0)
|
||||||
|
{
|
||||||
|
return "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Normalize */
|
||||||
|
while((mantissa & 1) == 0)
|
||||||
|
{ /* i.e., Mantissa is even */
|
||||||
|
mantissa >>= 1;
|
||||||
|
exponent++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a new decimal expansion with the mantissa
|
||||||
|
ArbitraryDecimal ad = new ArbitraryDecimal (mantissa);
|
||||||
|
|
||||||
|
// If the exponent is less than 0, we need to repeatedly
|
||||||
|
// divide by 2 - which is the equivalent of multiplying
|
||||||
|
// by 5 and dividing by 10.
|
||||||
|
if (exponent < 0)
|
||||||
|
{
|
||||||
|
for (int i=0; i < -exponent; i++)
|
||||||
|
ad.MultiplyBy(5);
|
||||||
|
ad.Shift(-exponent);
|
||||||
|
}
|
||||||
|
// Otherwise, we need to repeatedly multiply by 2
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i=0; i < exponent; i++)
|
||||||
|
ad.MultiplyBy(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, return the string with an appropriate sign
|
||||||
|
if (negative)
|
||||||
|
return "-"+ad.ToString();
|
||||||
|
else
|
||||||
|
return ad.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Private class used for manipulating
|
||||||
|
class ArbitraryDecimal
|
||||||
|
{
|
||||||
|
/// <summary>Digits in the decimal expansion, one byte per digit
|
||||||
|
byte[] digits;
|
||||||
|
/// <summary>
|
||||||
|
/// How many digits are *after* the decimal point
|
||||||
|
/// </summary>
|
||||||
|
int decimalPoint=0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs an arbitrary decimal expansion from the given long.
|
||||||
|
/// The long must not be negative.
|
||||||
|
/// </summary>
|
||||||
|
internal ArbitraryDecimal (long x)
|
||||||
|
{
|
||||||
|
string tmp = x.ToString(CultureInfo.InvariantCulture);
|
||||||
|
digits = new byte[tmp.Length];
|
||||||
|
for (int i=0; i < tmp.Length; i++)
|
||||||
|
digits[i] = (byte) (tmp[i]-'0');
|
||||||
|
Normalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Multiplies the current expansion by the given amount, which should
|
||||||
|
/// only be 2 or 5.
|
||||||
|
/// </summary>
|
||||||
|
internal void MultiplyBy(int amount)
|
||||||
|
{
|
||||||
|
byte[] result = new byte[digits.Length+1];
|
||||||
|
for (int i=digits.Length-1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
int resultDigit = digits[i]*amount+result[i+1];
|
||||||
|
result[i]=(byte)(resultDigit/10);
|
||||||
|
result[i+1]=(byte)(resultDigit%10);
|
||||||
|
}
|
||||||
|
if (result[0] != 0)
|
||||||
|
{
|
||||||
|
digits=result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Array.Copy (result, 1, digits, 0, digits.Length);
|
||||||
|
}
|
||||||
|
Normalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shifts the decimal point; a negative value makes
|
||||||
|
/// the decimal expansion bigger (as fewer digits come after the
|
||||||
|
/// decimal place) and a positive value makes the decimal
|
||||||
|
/// expansion smaller.
|
||||||
|
/// </summary>
|
||||||
|
internal void Shift (int amount)
|
||||||
|
{
|
||||||
|
decimalPoint += amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes leading/trailing zeroes from the expansion.
|
||||||
|
/// </summary>
|
||||||
|
internal void Normalize()
|
||||||
|
{
|
||||||
|
int first;
|
||||||
|
for (first=0; first < digits.Length; first++)
|
||||||
|
if (digits[first]!=0)
|
||||||
|
break;
|
||||||
|
int last;
|
||||||
|
for (last=digits.Length-1; last >= 0; last--)
|
||||||
|
if (digits[last]!=0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (first==0 && last==digits.Length-1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
byte[] tmp = new byte[last-first+1];
|
||||||
|
for (int i=0; i < tmp.Length; i++)
|
||||||
|
tmp[i]=digits[i+first];
|
||||||
|
|
||||||
|
decimalPoint -= digits.Length-(last+1);
|
||||||
|
digits=tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the value to a proper decimal string representation.
|
||||||
|
/// </summary>
|
||||||
|
public override String ToString()
|
||||||
|
{
|
||||||
|
char[] digitString = new char[digits.Length];
|
||||||
|
for (int i=0; i < digits.Length; i++)
|
||||||
|
digitString[i] = (char)(digits[i]+'0');
|
||||||
|
|
||||||
|
// Simplest case - nothing after the decimal point,
|
||||||
|
// and last real digit is non-zero, eg value=35
|
||||||
|
if (decimalPoint==0)
|
||||||
|
{
|
||||||
|
return new string (digitString);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fairly simple case - nothing after the decimal
|
||||||
|
// point, but some 0s to add, eg value=350
|
||||||
|
if (decimalPoint < 0)
|
||||||
|
{
|
||||||
|
return new string (digitString)+
|
||||||
|
new string ('0', -decimalPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nothing before the decimal point, eg 0.035
|
||||||
|
if (decimalPoint >= digitString.Length)
|
||||||
|
{
|
||||||
|
return "0."+
|
||||||
|
new string ('0',(decimalPoint-digitString.Length))+
|
||||||
|
new string (digitString);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Most complicated case - part of the string comes
|
||||||
|
// before the decimal point, part comes after it,
|
||||||
|
// eg 3.5
|
||||||
|
return new string (digitString, 0,
|
||||||
|
digitString.Length-decimalPoint)+
|
||||||
|
"."+
|
||||||
|
new string (digitString,
|
||||||
|
digitString.Length-decimalPoint,
|
||||||
|
decimalPoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -197,6 +197,7 @@
|
||||||
<Compile Include="Source\Collections\WeakCollection.Test.cs">
|
<Compile Include="Source\Collections\WeakCollection.Test.cs">
|
||||||
<DependentUpon>WeakCollection.cs</DependentUpon>
|
<DependentUpon>WeakCollection.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Source\GarbagePolicy.cs" />
|
||||||
<Compile Include="Source\IO\PartialStream.cs" />
|
<Compile Include="Source\IO\PartialStream.cs" />
|
||||||
<Compile Include="Source\IO\PartialStream.Test.cs">
|
<Compile Include="Source\IO\PartialStream.Test.cs">
|
||||||
<DependentUpon>PartialStream.cs</DependentUpon>
|
<DependentUpon>PartialStream.cs</DependentUpon>
|
||||||
|
@ -335,6 +336,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="Documents\CommandLine.txt" />
|
<Content Include="Documents\CommandLine.txt" />
|
||||||
|
<Content Include="Documents\DoubleConverter.txt" />
|
||||||
<Content Include="Documents\Nuclex.Support.txt" />
|
<Content Include="Documents\Nuclex.Support.txt" />
|
||||||
<Content Include="Documents\Request Framework.txt" />
|
<Content Include="Documents\Request Framework.txt" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -228,6 +228,7 @@
|
||||||
<Compile Include="Source\Collections\WeakCollection.Test.cs">
|
<Compile Include="Source\Collections\WeakCollection.Test.cs">
|
||||||
<DependentUpon>WeakCollection.cs</DependentUpon>
|
<DependentUpon>WeakCollection.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Source\GarbagePolicy.cs" />
|
||||||
<Compile Include="Source\IO\PartialStream.cs" />
|
<Compile Include="Source\IO\PartialStream.cs" />
|
||||||
<Compile Include="Source\IO\PartialStream.Test.cs">
|
<Compile Include="Source\IO\PartialStream.Test.cs">
|
||||||
<DependentUpon>PartialStream.cs</DependentUpon>
|
<DependentUpon>PartialStream.cs</DependentUpon>
|
||||||
|
@ -366,6 +367,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="Documents\CommandLine.txt" />
|
<Content Include="Documents\CommandLine.txt" />
|
||||||
|
<Content Include="Documents\DoubleConverter.txt" />
|
||||||
<Content Include="Documents\Nuclex.Support.txt" />
|
<Content Include="Documents\Nuclex.Support.txt" />
|
||||||
<Content Include="Documents\Request Framework.txt" />
|
<Content Include="Documents\Request Framework.txt" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -239,6 +239,7 @@
|
||||||
<Compile Include="Source\Collections\WeakCollection.Test.cs">
|
<Compile Include="Source\Collections\WeakCollection.Test.cs">
|
||||||
<DependentUpon>WeakCollection.cs</DependentUpon>
|
<DependentUpon>WeakCollection.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Source\GarbagePolicy.cs" />
|
||||||
<Compile Include="Source\IO\PartialStream.cs" />
|
<Compile Include="Source\IO\PartialStream.cs" />
|
||||||
<Compile Include="Source\IO\PartialStream.Test.cs">
|
<Compile Include="Source\IO\PartialStream.Test.cs">
|
||||||
<DependentUpon>PartialStream.cs</DependentUpon>
|
<DependentUpon>PartialStream.cs</DependentUpon>
|
||||||
|
@ -377,6 +378,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="Documents\CommandLine.txt" />
|
<Content Include="Documents\CommandLine.txt" />
|
||||||
|
<Content Include="Documents\DoubleConverter.txt" />
|
||||||
<Content Include="Documents\Nuclex.Support.txt" />
|
<Content Include="Documents\Nuclex.Support.txt" />
|
||||||
<Content Include="Documents\Request Framework.txt" />
|
<Content Include="Documents\Request Framework.txt" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -194,6 +194,35 @@ namespace Nuclex.Support.Collections {
|
||||||
Assert.IsFalse(set2.IsSubsetOf(set1));
|
Assert.IsFalse(set2.IsSubsetOf(set1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verifies that a set can determine if another set overlaps with it
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void CanDetermineOverlap() {
|
||||||
|
var set1 = new ObservableSet<int>() { 1, 3, 5 };
|
||||||
|
var set2 = new ObservableSet<int>() { 3 };
|
||||||
|
|
||||||
|
Assert.IsTrue(set1.Overlaps(set2));
|
||||||
|
Assert.IsTrue(set2.Overlaps(set1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verifies that a set can determine if another set contains the same elements
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void CanDetermineSetEquality() {
|
||||||
|
var set1 = new ObservableSet<int>() { 1, 3, 5 };
|
||||||
|
var set2 = new ObservableSet<int>() { 3, 1, 5 };
|
||||||
|
|
||||||
|
Assert.IsTrue(set1.SetEquals(set2));
|
||||||
|
Assert.IsTrue(set2.SetEquals(set1));
|
||||||
|
|
||||||
|
set1.Add(7);
|
||||||
|
|
||||||
|
Assert.IsFalse(set1.SetEquals(set2));
|
||||||
|
Assert.IsFalse(set2.SetEquals(set1));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Creates mock object for the test</summary>
|
/// <summary>Creates mock object for the test</summary>
|
||||||
private MockFactory mockFactory;
|
private MockFactory mockFactory;
|
||||||
/// <summary>Observable set being tested</summary>
|
/// <summary>Observable set being tested</summary>
|
||||||
|
|
|
@ -37,9 +37,9 @@ namespace Nuclex.Support.Collections {
|
||||||
ISet<TItem>,
|
ISet<TItem>,
|
||||||
ICollection<TItem>,
|
ICollection<TItem>,
|
||||||
#if !NO_SPECIALIZED_COLLECTIONS
|
#if !NO_SPECIALIZED_COLLECTIONS
|
||||||
INotifyCollectionChanged,
|
INotifyCollectionChanged,
|
||||||
#endif
|
#endif
|
||||||
IObservableCollection<TItem> {
|
IObservableCollection<TItem> {
|
||||||
|
|
||||||
/// <summary>Raised when an item has been added to the collection</summary>
|
/// <summary>Raised when an item has been added to the collection</summary>
|
||||||
public event EventHandler<ItemEventArgs<TItem>> ItemAdded;
|
public event EventHandler<ItemEventArgs<TItem>> ItemAdded;
|
||||||
|
|
|
@ -29,22 +29,22 @@ namespace Nuclex.Support {
|
||||||
public static class EnumHelper {
|
public static class EnumHelper {
|
||||||
|
|
||||||
/// <summary>Returns the highest value encountered in an enumeration</summary>
|
/// <summary>Returns the highest value encountered in an enumeration</summary>
|
||||||
/// <typeparam name="EnumType">
|
/// <typeparam name="TEnum">
|
||||||
/// Enumeration of which the highest value will be returned
|
/// Enumeration of which the highest value will be returned
|
||||||
/// </typeparam>
|
/// </typeparam>
|
||||||
/// <returns>The highest value in the enumeration</returns>
|
/// <returns>The highest value in the enumeration</returns>
|
||||||
public static EnumType GetHighestValue<EnumType>() where EnumType : IComparable {
|
public static TEnum GetHighestValue<TEnum>() where TEnum : IComparable {
|
||||||
EnumType[] values = GetValues<EnumType>();
|
TEnum[] values = GetValues<TEnum>();
|
||||||
|
|
||||||
// If the enumeration is empty, return nothing
|
// If the enumeration is empty, return nothing
|
||||||
if(values.Length == 0) {
|
if(values.Length == 0) {
|
||||||
return default(EnumType);
|
return default(TEnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for the highest value in the enumeration. We initialize the highest value
|
// Look for the highest value in the enumeration. We initialize the highest value
|
||||||
// to the first enumeration value so we don't have to use some arbitrary starting
|
// to the first enumeration value so we don't have to use some arbitrary starting
|
||||||
// value which might actually appear in the enumeration.
|
// value which might actually appear in the enumeration.
|
||||||
EnumType highestValue = values[0];
|
TEnum highestValue = values[0];
|
||||||
for(int index = 1; index < values.Length; ++index) {
|
for(int index = 1; index < values.Length; ++index) {
|
||||||
if(values[index].CompareTo(highestValue) > 0) {
|
if(values[index].CompareTo(highestValue) > 0) {
|
||||||
highestValue = values[index];
|
highestValue = values[index];
|
||||||
|
@ -81,7 +81,7 @@ namespace Nuclex.Support {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Retrieves a list of all values contained in an enumeration</summary>
|
/// <summary>Retrieves a list of all values contained in an enumeration</summary>
|
||||||
/// <typeparam name="EnumType">
|
/// <typeparam name="TEnum">
|
||||||
/// Type of the enumeration whose values will be returned
|
/// Type of the enumeration whose values will be returned
|
||||||
/// </typeparam>
|
/// </typeparam>
|
||||||
/// <returns>All values contained in the specified enumeration</returns>
|
/// <returns>All values contained in the specified enumeration</returns>
|
||||||
|
@ -89,21 +89,21 @@ namespace Nuclex.Support {
|
||||||
/// This method produces collectable garbage so it's best to only call it once
|
/// This method produces collectable garbage so it's best to only call it once
|
||||||
/// and cache the result.
|
/// and cache the result.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public static EnumType[] GetValues<EnumType>() {
|
public static TEnum[] GetValues<TEnum>() {
|
||||||
#if XBOX360 || WINDOWS_PHONE
|
#if XBOX360 || WINDOWS_PHONE
|
||||||
return GetValuesXbox360<EnumType>();
|
return GetValuesXbox360<TEnum>();
|
||||||
#else
|
#else
|
||||||
return (EnumType[])Enum.GetValues(typeof(EnumType));
|
return (TEnum[])Enum.GetValues(typeof(TEnum));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Retrieves a list of all values contained in an enumeration</summary>
|
/// <summary>Retrieves a list of all values contained in an enumeration</summary>
|
||||||
/// <typeparam name="EnumType">
|
/// <typeparam name="TEnum">
|
||||||
/// Type of the enumeration whose values will be returned
|
/// Type of the enumeration whose values will be returned
|
||||||
/// </typeparam>
|
/// </typeparam>
|
||||||
/// <returns>All values contained in the specified enumeration</returns>
|
/// <returns>All values contained in the specified enumeration</returns>
|
||||||
internal static EnumType[] GetValuesXbox360<EnumType>() {
|
internal static TEnum[] GetValuesXbox360<TEnum>() {
|
||||||
Type enumType = typeof(EnumType);
|
Type enumType = typeof(TEnum);
|
||||||
if(!enumType.IsEnum) {
|
if(!enumType.IsEnum) {
|
||||||
throw new ArgumentException(
|
throw new ArgumentException(
|
||||||
"The provided type needs to be an enumeration", "EnumType"
|
"The provided type needs to be an enumeration", "EnumType"
|
||||||
|
@ -117,9 +117,9 @@ namespace Nuclex.Support {
|
||||||
|
|
||||||
// Create an array to hold the enumeration values and copy them over from
|
// Create an array to hold the enumeration values and copy them over from
|
||||||
// the fields we just retrieved
|
// the fields we just retrieved
|
||||||
EnumType[] values = new EnumType[fieldInfos.Length];
|
TEnum[] values = new TEnum[fieldInfos.Length];
|
||||||
for(int index = 0; index < fieldInfos.Length; ++index) {
|
for(int index = 0; index < fieldInfos.Length; ++index) {
|
||||||
values[index] = (EnumType)fieldInfos[index].GetValue(null);
|
values[index] = (TEnum)fieldInfos[index].GetValue(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return values;
|
return values;
|
||||||
|
|
33
Source/GarbagePolicy.cs
Normal file
33
Source/GarbagePolicy.cs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#region CPL License
|
||||||
|
/*
|
||||||
|
Nuclex Framework
|
||||||
|
Copyright (C) 2002-2012 Nuclex Development Labs
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the IBM Common Public License as
|
||||||
|
published by the IBM Corporation; either version 1.0 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
IBM Common Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the IBM Common Public
|
||||||
|
License along with this library
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Nuclex.Support {
|
||||||
|
|
||||||
|
/// <summary>How to behave in in respect to the garbage collector</summary>
|
||||||
|
public enum GarbagePolicy {
|
||||||
|
/// <summary>Avoid feeding the garbage collector whenever possible</summary>
|
||||||
|
Avoid,
|
||||||
|
/// <summary>Accept garbage production</summary>
|
||||||
|
Accept
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Nuclex.Support
|
|
@ -175,9 +175,6 @@ namespace Nuclex.Support {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether the property change affects the specified property
|
/// Determines whether the property change affects the specified property
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TValue">
|
|
||||||
/// Type of the property that will be tested for being affected
|
|
||||||
/// </typeparam>
|
|
||||||
/// <param name="arguments">
|
/// <param name="arguments">
|
||||||
/// Property change that has been reported by the observed object
|
/// Property change that has been reported by the observed object
|
||||||
/// </param>
|
/// </param>
|
||||||
|
|
|
@ -56,10 +56,12 @@ namespace Nuclex.Support {
|
||||||
/// become eligible for execution.
|
/// become eligible for execution.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
#if !(XBOX360 || WINDOWS_PHONE)
|
#if WINDOWS
|
||||||
[Obsolete("Prefer the normal semaphore on Windows builds.")]
|
[Obsolete("Prefer the normal semaphore on Windows builds.")]
|
||||||
#endif
|
internal class Semaphore : WaitHandle {
|
||||||
|
#else
|
||||||
public class Semaphore : WaitHandle {
|
public class Semaphore : WaitHandle {
|
||||||
|
#endif
|
||||||
|
|
||||||
/// <summary>Initializes a new semaphore</summary>
|
/// <summary>Initializes a new semaphore</summary>
|
||||||
public Semaphore() {
|
public Semaphore() {
|
||||||
|
|
|
@ -24,13 +24,13 @@ using System.Diagnostics;
|
||||||
namespace Nuclex.Support {
|
namespace Nuclex.Support {
|
||||||
|
|
||||||
/// <summary>Manages a globally shared instance of the given Type</summary>
|
/// <summary>Manages a globally shared instance of the given Type</summary>
|
||||||
/// <typeparam name="SharedType">
|
/// <typeparam name="TShared">
|
||||||
/// Type of which a globally shared instance will be provided
|
/// Type of which a globally shared instance will be provided
|
||||||
/// </typeparam>
|
/// </typeparam>
|
||||||
public static class Shared<SharedType> where SharedType : new() {
|
public static class Shared<TShared> where TShared : new() {
|
||||||
|
|
||||||
/// <summary>Returns the global instance of the class</summary>
|
/// <summary>Returns the global instance of the class</summary>
|
||||||
public static SharedType Instance {
|
public static TShared Instance {
|
||||||
[DebuggerStepThrough]
|
[DebuggerStepThrough]
|
||||||
get {
|
get {
|
||||||
return instance;
|
return instance;
|
||||||
|
@ -38,7 +38,7 @@ namespace Nuclex.Support {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Stored the globally shared instance</summary>
|
/// <summary>Stored the globally shared instance</summary>
|
||||||
private static readonly SharedType instance = new SharedType();
|
private static readonly TShared instance = new TShared();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,8 +40,13 @@ namespace Nuclex.Support {
|
||||||
[Test]
|
[Test]
|
||||||
public void TestAppendByte() {
|
public void TestAppendByte() {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
StringBuilderHelper.Append(builder, (byte)255);
|
|
||||||
|
|
||||||
|
builder.Append((byte)255, GarbagePolicy.Avoid);
|
||||||
|
Assert.AreEqual("255", builder.ToString());
|
||||||
|
|
||||||
|
builder.Clear();
|
||||||
|
|
||||||
|
builder.Append((byte)255, GarbagePolicy.Accept);
|
||||||
Assert.AreEqual("255", builder.ToString());
|
Assert.AreEqual("255", builder.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,8 +56,13 @@ namespace Nuclex.Support {
|
||||||
[Test]
|
[Test]
|
||||||
public void TestAppendNullByte() {
|
public void TestAppendNullByte() {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
StringBuilderHelper.Append(builder, (byte)0);
|
|
||||||
|
|
||||||
|
builder.Append((byte)0, GarbagePolicy.Avoid);
|
||||||
|
Assert.AreEqual("0", builder.ToString());
|
||||||
|
|
||||||
|
builder.Clear();
|
||||||
|
|
||||||
|
builder.Append((byte)0, GarbagePolicy.Accept);
|
||||||
Assert.AreEqual("0", builder.ToString());
|
Assert.AreEqual("0", builder.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,8 +72,13 @@ namespace Nuclex.Support {
|
||||||
[Test]
|
[Test]
|
||||||
public void TestAppendPositiveInteger() {
|
public void TestAppendPositiveInteger() {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
StringBuilderHelper.Append(builder, 12345);
|
|
||||||
|
|
||||||
|
builder.Append(12345, GarbagePolicy.Avoid);
|
||||||
|
Assert.AreEqual("12345", builder.ToString());
|
||||||
|
|
||||||
|
builder.Clear();
|
||||||
|
|
||||||
|
builder.Append(12345, GarbagePolicy.Accept);
|
||||||
Assert.AreEqual("12345", builder.ToString());
|
Assert.AreEqual("12345", builder.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,8 +88,13 @@ namespace Nuclex.Support {
|
||||||
[Test]
|
[Test]
|
||||||
public void TestAppendNullInteger() {
|
public void TestAppendNullInteger() {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
StringBuilderHelper.Append(builder, 0);
|
|
||||||
|
|
||||||
|
builder.Append(0, GarbagePolicy.Avoid);
|
||||||
|
Assert.AreEqual("0", builder.ToString());
|
||||||
|
|
||||||
|
builder.Clear();
|
||||||
|
|
||||||
|
builder.Append(0, GarbagePolicy.Accept);
|
||||||
Assert.AreEqual("0", builder.ToString());
|
Assert.AreEqual("0", builder.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,8 +104,13 @@ namespace Nuclex.Support {
|
||||||
[Test]
|
[Test]
|
||||||
public void TestAppendNegativeInteger() {
|
public void TestAppendNegativeInteger() {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
StringBuilderHelper.Append(builder, -12345);
|
|
||||||
|
|
||||||
|
builder.Append(-12345, GarbagePolicy.Avoid);
|
||||||
|
Assert.AreEqual("-12345", builder.ToString());
|
||||||
|
|
||||||
|
builder.Clear();
|
||||||
|
|
||||||
|
builder.Append(-12345, GarbagePolicy.Accept);
|
||||||
Assert.AreEqual("-12345", builder.ToString());
|
Assert.AreEqual("-12345", builder.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,8 +120,13 @@ namespace Nuclex.Support {
|
||||||
[Test]
|
[Test]
|
||||||
public void TestAppendPositiveLong() {
|
public void TestAppendPositiveLong() {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
StringBuilderHelper.Append(builder, 12345L);
|
|
||||||
|
|
||||||
|
builder.Append(12345L, GarbagePolicy.Avoid);
|
||||||
|
Assert.AreEqual("12345", builder.ToString());
|
||||||
|
|
||||||
|
builder.Clear();
|
||||||
|
|
||||||
|
builder.Append(12345L, GarbagePolicy.Accept);
|
||||||
Assert.AreEqual("12345", builder.ToString());
|
Assert.AreEqual("12345", builder.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,8 +136,13 @@ namespace Nuclex.Support {
|
||||||
[Test]
|
[Test]
|
||||||
public void TestAppendNullLong() {
|
public void TestAppendNullLong() {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
StringBuilderHelper.Append(builder, 0L);
|
|
||||||
|
|
||||||
|
builder.Append(0L, GarbagePolicy.Avoid);
|
||||||
|
Assert.AreEqual("0", builder.ToString());
|
||||||
|
|
||||||
|
builder.Clear();
|
||||||
|
|
||||||
|
builder.Append(0L, GarbagePolicy.Accept);
|
||||||
Assert.AreEqual("0", builder.ToString());
|
Assert.AreEqual("0", builder.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,8 +152,13 @@ namespace Nuclex.Support {
|
||||||
[Test]
|
[Test]
|
||||||
public void TestAppendNegativeLong() {
|
public void TestAppendNegativeLong() {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
StringBuilderHelper.Append(builder, -12345L);
|
|
||||||
|
|
||||||
|
builder.Append(-12345L, GarbagePolicy.Avoid);
|
||||||
|
Assert.AreEqual("-12345", builder.ToString());
|
||||||
|
|
||||||
|
builder.Clear();
|
||||||
|
|
||||||
|
builder.Append(-12345L, GarbagePolicy.Accept);
|
||||||
Assert.AreEqual("-12345", builder.ToString());
|
Assert.AreEqual("-12345", builder.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,9 +168,14 @@ namespace Nuclex.Support {
|
||||||
[Test]
|
[Test]
|
||||||
public void TestAppendNegativeFloat() {
|
public void TestAppendNegativeFloat() {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
StringBuilderHelper.Append(builder, -32.015625f);
|
|
||||||
|
|
||||||
Assert.AreEqual("-32.015625", builder.ToString());
|
builder.Append(-0.125f, GarbagePolicy.Avoid);
|
||||||
|
Assert.AreEqual("-0.125", builder.ToString());
|
||||||
|
|
||||||
|
builder.Clear();
|
||||||
|
|
||||||
|
builder.Append(-0.125f, GarbagePolicy.Accept);
|
||||||
|
Assert.AreEqual("-0.125", builder.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -139,8 +184,13 @@ namespace Nuclex.Support {
|
||||||
[Test]
|
[Test]
|
||||||
public void TestAppendPositiveFloat() {
|
public void TestAppendPositiveFloat() {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
StringBuilderHelper.Append(builder, 10.0625f);
|
|
||||||
|
|
||||||
|
builder.Append(10.0625f, GarbagePolicy.Avoid);
|
||||||
|
Assert.AreEqual("10.0625", builder.ToString());
|
||||||
|
|
||||||
|
builder.Clear();
|
||||||
|
|
||||||
|
builder.Append(10.0625f, GarbagePolicy.Accept);
|
||||||
Assert.AreEqual("10.0625", builder.ToString());
|
Assert.AreEqual("10.0625", builder.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,8 +200,13 @@ namespace Nuclex.Support {
|
||||||
[Test]
|
[Test]
|
||||||
public void TestAppendSmallFloat() {
|
public void TestAppendSmallFloat() {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
StringBuilderHelper.Append(builder, 0.00390625f);
|
|
||||||
|
|
||||||
|
builder.Append(0.00390625f, GarbagePolicy.Avoid);
|
||||||
|
Assert.AreEqual("0.00390625", builder.ToString());
|
||||||
|
|
||||||
|
builder.Clear();
|
||||||
|
|
||||||
|
builder.Append(0.00390625f, GarbagePolicy.Accept);
|
||||||
Assert.AreEqual("0.00390625", builder.ToString());
|
Assert.AreEqual("0.00390625", builder.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,17 +216,21 @@ namespace Nuclex.Support {
|
||||||
[Test]
|
[Test]
|
||||||
public void TestAppendHugeFloat() {
|
public void TestAppendHugeFloat() {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
StringBuilderHelper.Append(builder, 1000000000.0f);
|
|
||||||
|
|
||||||
|
builder.Append(1000000000.0f, GarbagePolicy.Avoid);
|
||||||
Assert.AreEqual("1000000000.0", builder.ToString());
|
Assert.AreEqual("1000000000.0", builder.ToString());
|
||||||
|
|
||||||
|
builder.Clear();
|
||||||
|
|
||||||
|
builder.Append(1000000000.0f, GarbagePolicy.Accept);
|
||||||
|
Assert.AreEqual("1E+09", builder.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Tests whether the number of decimal places can be restricted</summary>
|
/// <summary>Tests whether the number of decimal places can be restricted</summary>
|
||||||
[Test]
|
[Test]
|
||||||
public void TestAppendFloatLimitDecimalPlaces() {
|
public void TestAppendFloatLimitDecimalPlaces() {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
StringBuilderHelper.Append(builder, 0.00390625f, 3);
|
builder.Append(0.00390625f, 3);
|
||||||
|
|
||||||
Assert.AreEqual("0.003", builder.ToString());
|
Assert.AreEqual("0.003", builder.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,8 +240,7 @@ namespace Nuclex.Support {
|
||||||
[Test]
|
[Test]
|
||||||
public void TestAppendFloatWithoutDecimalPlaces() {
|
public void TestAppendFloatWithoutDecimalPlaces() {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
StringBuilderHelper.Append(builder, 0.00390625f, 0);
|
builder.Append(0.00390625f, 0);
|
||||||
|
|
||||||
Assert.AreEqual("0", builder.ToString()); // Note: no rounding!
|
Assert.AreEqual("0", builder.ToString()); // Note: no rounding!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,10 +250,10 @@ namespace Nuclex.Support {
|
||||||
[Test]
|
[Test]
|
||||||
public void TestAppendOutOfRangeFloat() {
|
public void TestAppendOutOfRangeFloat() {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
Assert.IsFalse(StringBuilderHelper.Append(builder, float.PositiveInfinity));
|
Assert.IsFalse(builder.Append(float.PositiveInfinity, GarbagePolicy.Avoid));
|
||||||
Assert.IsFalse(StringBuilderHelper.Append(builder, float.NegativeInfinity));
|
Assert.IsFalse(builder.Append(float.NegativeInfinity, GarbagePolicy.Avoid));
|
||||||
Assert.IsFalse(StringBuilderHelper.Append(builder, float.NaN));
|
Assert.IsFalse(builder.Append(float.NaN, GarbagePolicy.Avoid));
|
||||||
Assert.IsFalse(StringBuilderHelper.Append(builder, 0.000000059604644775390625f));
|
Assert.IsFalse(builder.Append(0.000000059604644775390625f, GarbagePolicy.Avoid));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -205,8 +263,13 @@ namespace Nuclex.Support {
|
||||||
[Test]
|
[Test]
|
||||||
public void TestAppendNegativeDouble() {
|
public void TestAppendNegativeDouble() {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
StringBuilderHelper.Append(builder, -32.015625);
|
|
||||||
|
|
||||||
|
builder.Append(-32.015625, GarbagePolicy.Avoid);
|
||||||
|
Assert.AreEqual("-32.015625", builder.ToString());
|
||||||
|
|
||||||
|
builder.Clear();
|
||||||
|
|
||||||
|
builder.Append(-32.015625, GarbagePolicy.Accept);
|
||||||
Assert.AreEqual("-32.015625", builder.ToString());
|
Assert.AreEqual("-32.015625", builder.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,8 +280,13 @@ namespace Nuclex.Support {
|
||||||
[Test]
|
[Test]
|
||||||
public void TestAppendPositiveDouble() {
|
public void TestAppendPositiveDouble() {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
StringBuilderHelper.Append(builder, 10.0625);
|
|
||||||
|
|
||||||
|
builder.Append(10.0625, GarbagePolicy.Avoid);
|
||||||
|
Assert.AreEqual("10.0625", builder.ToString());
|
||||||
|
|
||||||
|
builder.Clear();
|
||||||
|
|
||||||
|
builder.Append(10.0625, GarbagePolicy.Accept);
|
||||||
Assert.AreEqual("10.0625", builder.ToString());
|
Assert.AreEqual("10.0625", builder.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,8 +297,13 @@ namespace Nuclex.Support {
|
||||||
[Test]
|
[Test]
|
||||||
public void TestAppendSmallDouble() {
|
public void TestAppendSmallDouble() {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
StringBuilderHelper.Append(builder, 0.00390625);
|
|
||||||
|
|
||||||
|
builder.Append(0.00390625, GarbagePolicy.Avoid);
|
||||||
|
Assert.AreEqual("0.00390625", builder.ToString());
|
||||||
|
|
||||||
|
builder.Clear();
|
||||||
|
|
||||||
|
builder.Append(0.00390625, GarbagePolicy.Accept);
|
||||||
Assert.AreEqual("0.00390625", builder.ToString());
|
Assert.AreEqual("0.00390625", builder.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,9 +314,14 @@ namespace Nuclex.Support {
|
||||||
[Test]
|
[Test]
|
||||||
public void TestAppendHugeDouble() {
|
public void TestAppendHugeDouble() {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
StringBuilderHelper.Append(builder, 1000000000000000000.0);
|
|
||||||
|
|
||||||
|
builder.Append(1000000000000000000.0, GarbagePolicy.Avoid);
|
||||||
Assert.AreEqual("1000000000000000000.0", builder.ToString());
|
Assert.AreEqual("1000000000000000000.0", builder.ToString());
|
||||||
|
|
||||||
|
builder.Clear();
|
||||||
|
|
||||||
|
builder.Append(1000000000000000000.0, GarbagePolicy.Accept);
|
||||||
|
Assert.AreEqual("1E+18", builder.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Tests whether the number of decimal places can be restricted</summary>
|
/// <summary>Tests whether the number of decimal places can be restricted</summary>
|
||||||
|
@ -273,12 +351,10 @@ namespace Nuclex.Support {
|
||||||
[Test]
|
[Test]
|
||||||
public void TestAppendOutOfRangeDouble() {
|
public void TestAppendOutOfRangeDouble() {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
Assert.IsFalse(StringBuilderHelper.Append(builder, double.PositiveInfinity));
|
Assert.IsFalse(builder.Append(double.PositiveInfinity, GarbagePolicy.Avoid));
|
||||||
Assert.IsFalse(StringBuilderHelper.Append(builder, double.NegativeInfinity));
|
Assert.IsFalse(builder.Append(double.NegativeInfinity, GarbagePolicy.Avoid));
|
||||||
Assert.IsFalse(StringBuilderHelper.Append(builder, double.NaN));
|
Assert.IsFalse(builder.Append(double.NaN, GarbagePolicy.Avoid));
|
||||||
Assert.IsFalse(
|
Assert.IsFalse(builder.Append(1.1102230246251565404236316680908e-16, GarbagePolicy.Avoid));
|
||||||
StringBuilderHelper.Append(builder, 1.1102230246251565404236316680908e-16)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -291,7 +367,7 @@ namespace Nuclex.Support {
|
||||||
|
|
||||||
Assert.AreEqual(string.Empty, builder.ToString());
|
Assert.AreEqual(string.Empty, builder.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Nuclex.Support
|
} // namespace Nuclex.Support
|
||||||
|
|
|
@ -25,12 +25,6 @@ using System.Text;
|
||||||
|
|
||||||
namespace Nuclex.Support {
|
namespace Nuclex.Support {
|
||||||
|
|
||||||
/*
|
|
||||||
public enum Garbage {
|
|
||||||
Avoid,
|
|
||||||
Accept
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/// <summary>Contains helper methods for the string builder class</summary>
|
/// <summary>Contains helper methods for the string builder class</summary>
|
||||||
public static class StringBuilderHelper {
|
public static class StringBuilderHelper {
|
||||||
|
|
||||||
|
@ -50,13 +44,20 @@ namespace Nuclex.Support {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="builder">String builder to which an integer will be appended</param>
|
/// <param name="builder">String builder to which an integer will be appended</param>
|
||||||
/// <param name="value">Byte that will be appended to the string builder</param>
|
/// <param name="value">Byte that will be appended to the string builder</param>
|
||||||
|
/// <param name="garbagePolicy">How to behave regarding the garbage collector</param>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// The normal StringBuilder.Append() method generates garbage when converting
|
/// The normal StringBuilder.Append() method generates garbage when converting
|
||||||
/// integer arguments whereas this method will avoid any garbage, albeit probably
|
/// integer arguments whereas this method will avoid any garbage, albeit probably
|
||||||
/// with a small performance impact compared to the built-in method.
|
/// with a small performance impact compared to the built-in method.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public static void Append(StringBuilder builder, byte value) {
|
public static void Append(
|
||||||
recursiveAppend(builder, value);
|
this StringBuilder builder, byte value, GarbagePolicy garbagePolicy
|
||||||
|
) {
|
||||||
|
if(garbagePolicy == GarbagePolicy.Avoid) {
|
||||||
|
recursiveAppend(builder, value);
|
||||||
|
} else {
|
||||||
|
builder.Append((int)value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -64,17 +65,24 @@ namespace Nuclex.Support {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="builder">String builder to which an integer will be appended</param>
|
/// <param name="builder">String builder to which an integer will be appended</param>
|
||||||
/// <param name="value">Integer that will be appended to the string builder</param>
|
/// <param name="value">Integer that will be appended to the string builder</param>
|
||||||
|
/// <param name="garbagePolicy">How to behave regarding the garbage collector</param>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// The normal StringBuilder.Append() method generates garbage when converting
|
/// The normal StringBuilder.Append() method generates garbage when converting
|
||||||
/// integer arguments whereas this method will avoid any garbage, albeit probably
|
/// integer arguments whereas this method will avoid any garbage, albeit probably
|
||||||
/// with a small performance impact compared to the built-in method.
|
/// with a small performance impact compared to the built-in method.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public static void Append(StringBuilder builder, int value) {
|
public static void Append(
|
||||||
if (value < 0) {
|
this StringBuilder builder, int value, GarbagePolicy garbagePolicy
|
||||||
builder.Append('-');
|
) {
|
||||||
recursiveAppend(builder, -value);
|
if(garbagePolicy == GarbagePolicy.Avoid) {
|
||||||
|
if(value < 0) {
|
||||||
|
builder.Append('-');
|
||||||
|
recursiveAppend(builder, -value);
|
||||||
|
} else {
|
||||||
|
recursiveAppend(builder, value);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
recursiveAppend(builder, value);
|
builder.Append(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,17 +91,24 @@ namespace Nuclex.Support {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="builder">String builder to which an integer will be appended</param>
|
/// <param name="builder">String builder to which an integer will be appended</param>
|
||||||
/// <param name="value">Long integer that will be appended to the string builder</param>
|
/// <param name="value">Long integer that will be appended to the string builder</param>
|
||||||
|
/// <param name="garbagePolicy">How to behave regarding the garbage collector</param>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// The normal StringBuilder.Append() method generates garbage when converting
|
/// The normal StringBuilder.Append() method generates garbage when converting
|
||||||
/// integer arguments whereas this method will avoid any garbage, albeit probably
|
/// integer arguments whereas this method will avoid any garbage, albeit probably
|
||||||
/// with a small performance impact compared to the built-in method.
|
/// with a small performance impact compared to the built-in method.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public static void Append(StringBuilder builder, long value) {
|
public static void Append(
|
||||||
if (value < 0) {
|
this StringBuilder builder, long value, GarbagePolicy garbagePolicy
|
||||||
builder.Append('-');
|
) {
|
||||||
recursiveAppend(builder, -value);
|
if(garbagePolicy == GarbagePolicy.Avoid) {
|
||||||
|
if(value < 0) {
|
||||||
|
builder.Append('-');
|
||||||
|
recursiveAppend(builder, -value);
|
||||||
|
} else {
|
||||||
|
recursiveAppend(builder, value);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
recursiveAppend(builder, value);
|
builder.Append(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,14 +117,22 @@ namespace Nuclex.Support {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="builder">String builder the value will be appended to</param>
|
/// <param name="builder">String builder the value will be appended to</param>
|
||||||
/// <param name="value">Value that will be appended to the string builder</param>
|
/// <param name="value">Value that will be appended to the string builder</param>
|
||||||
|
/// <param name="garbagePolicy">How to behave regarding the garbage collector</param>
|
||||||
/// <returns>Whether the value was inside the algorithm's supported range</returns>
|
/// <returns>Whether the value was inside the algorithm's supported range</returns>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Uses an algorithm that covers the sane range of possible values but will
|
/// Uses an algorithm that covers the sane range of possible values but will
|
||||||
/// fail to render extreme values, NaNs and infinity. In these cases, false
|
/// fail to render extreme values, NaNs and infinity. In these cases, false
|
||||||
/// is returned and the traditional double.ToString() method can be used.
|
/// is returned and the traditional double.ToString() method can be used.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public static bool Append(StringBuilder builder, float value) {
|
public static bool Append(
|
||||||
return Append(builder, value, int.MaxValue);
|
this StringBuilder builder, float value, GarbagePolicy garbagePolicy
|
||||||
|
) {
|
||||||
|
if(garbagePolicy == GarbagePolicy.Avoid) {
|
||||||
|
return Append(builder, value, int.MaxValue);
|
||||||
|
} else {
|
||||||
|
builder.Append(value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -124,7 +147,7 @@ namespace Nuclex.Support {
|
||||||
/// fail to render extreme values, NaNs and infinity. In these cases, false
|
/// fail to render extreme values, NaNs and infinity. In these cases, false
|
||||||
/// is returned and the traditional double.ToString() method can be used.
|
/// is returned and the traditional double.ToString() method can be used.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public static bool Append(StringBuilder builder, float value, int decimalPlaces) {
|
public static bool Append(this StringBuilder builder, float value, int decimalPlaces) {
|
||||||
const int ExponentBits = 0xFF; // Bit mask for the exponent bits
|
const int ExponentBits = 0xFF; // Bit mask for the exponent bits
|
||||||
const int FractionalBitCount = 23; // Number of bits for fractional part
|
const int FractionalBitCount = 23; // Number of bits for fractional part
|
||||||
const int ExponentBias = 127; // Bias subtraced from exponent
|
const int ExponentBias = 127; // Bias subtraced from exponent
|
||||||
|
@ -142,9 +165,9 @@ namespace Nuclex.Support {
|
||||||
|
|
||||||
int integral;
|
int integral;
|
||||||
int fractional;
|
int fractional;
|
||||||
if (exponent >= 0) {
|
if(exponent >= 0) {
|
||||||
if (exponent >= FractionalBitCount) {
|
if(exponent >= FractionalBitCount) {
|
||||||
if (exponent >= NumericBitCount) {
|
if(exponent >= NumericBitCount) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
integral = mantissa << (exponent - FractionalBitCount);
|
integral = mantissa << (exponent - FractionalBitCount);
|
||||||
|
@ -154,7 +177,7 @@ namespace Nuclex.Support {
|
||||||
fractional = (mantissa << (exponent + 1)) & FractionalBits;
|
fractional = (mantissa << (exponent + 1)) & FractionalBits;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (exponent < -FractionalBitCount) {
|
if(exponent < -FractionalBitCount) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
integral = 0;
|
integral = 0;
|
||||||
|
@ -162,30 +185,30 @@ namespace Nuclex.Support {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build the integral part
|
// Build the integral part
|
||||||
if (intValue < 0) {
|
if(intValue < 0) {
|
||||||
builder.Append('-');
|
builder.Append('-');
|
||||||
}
|
}
|
||||||
if (integral == 0) {
|
if(integral == 0) {
|
||||||
builder.Append('0');
|
builder.Append('0');
|
||||||
} else {
|
} else {
|
||||||
recursiveAppend(builder, integral);
|
recursiveAppend(builder, integral);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decimalPlaces > 0) {
|
if(decimalPlaces > 0) {
|
||||||
builder.Append('.');
|
builder.Append('.');
|
||||||
|
|
||||||
// Build the fractional part
|
// Build the fractional part
|
||||||
if (fractional == 0) {
|
if(fractional == 0) {
|
||||||
builder.Append('0');
|
builder.Append('0');
|
||||||
} else {
|
} else {
|
||||||
while (fractional != 0) {
|
while(fractional != 0) {
|
||||||
fractional *= 10;
|
fractional *= 10;
|
||||||
int digit = (fractional >> FractionalBitCountPlusOne);
|
int digit = (fractional >> FractionalBitCountPlusOne);
|
||||||
builder.Append(numbers[digit]);
|
builder.Append(numbers[digit]);
|
||||||
fractional &= FractionalBits;
|
fractional &= FractionalBits;
|
||||||
|
|
||||||
--decimalPlaces;
|
--decimalPlaces;
|
||||||
if (decimalPlaces == 0) {
|
if(decimalPlaces == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -201,14 +224,22 @@ namespace Nuclex.Support {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="builder">String builder the value will be appended to</param>
|
/// <param name="builder">String builder the value will be appended to</param>
|
||||||
/// <param name="value">Value that will be appended to the string builder</param>
|
/// <param name="value">Value that will be appended to the string builder</param>
|
||||||
|
/// <param name="garbagePolicy">How to behave regarding the garbage collector</param>
|
||||||
/// <returns>Whether the value was inside the algorithm's supported range</returns>
|
/// <returns>Whether the value was inside the algorithm's supported range</returns>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Uses an algorithm that covers the sane range of possible values but will
|
/// Uses an algorithm that covers the sane range of possible values but will
|
||||||
/// fail to render extreme values, NaNs and infinity. In these cases, false
|
/// fail to render extreme values, NaNs and infinity. In these cases, false
|
||||||
/// is returned and the traditional double.ToString() method can be used.
|
/// is returned and the traditional double.ToString() method can be used.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public static bool Append(StringBuilder builder, double value) {
|
public static bool Append(
|
||||||
return Append(builder, value, int.MaxValue);
|
this StringBuilder builder, double value, GarbagePolicy garbagePolicy
|
||||||
|
) {
|
||||||
|
if(garbagePolicy == GarbagePolicy.Avoid) {
|
||||||
|
return Append(builder, value, int.MaxValue);
|
||||||
|
} else {
|
||||||
|
builder.Append(value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -224,7 +255,7 @@ namespace Nuclex.Support {
|
||||||
/// fail to render extreme values, NaNs and infinity. In these cases, false
|
/// fail to render extreme values, NaNs and infinity. In these cases, false
|
||||||
/// is returned and the traditional double.ToString() method can be used.
|
/// is returned and the traditional double.ToString() method can be used.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public static bool Append(StringBuilder builder, double value, int decimalPlaces) {
|
public static bool Append(this StringBuilder builder, double value, int decimalPlaces) {
|
||||||
const long ExponentBits = 0x7FF; // Bit mask for the exponent bits
|
const long ExponentBits = 0x7FF; // Bit mask for the exponent bits
|
||||||
const int FractionalBitCount = 52; // Number of bits for fractional part
|
const int FractionalBitCount = 52; // Number of bits for fractional part
|
||||||
const int ExponentBias = 1023; // Bias subtraced from exponent
|
const int ExponentBias = 1023; // Bias subtraced from exponent
|
||||||
|
@ -242,9 +273,9 @@ namespace Nuclex.Support {
|
||||||
|
|
||||||
long integral;
|
long integral;
|
||||||
long fractional;
|
long fractional;
|
||||||
if (exponent >= 0) {
|
if(exponent >= 0) {
|
||||||
if (exponent >= FractionalBitCount) {
|
if(exponent >= FractionalBitCount) {
|
||||||
if (exponent >= NumericBitCount) {
|
if(exponent >= NumericBitCount) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
integral = mantissa << (int)(exponent - FractionalBitCount);
|
integral = mantissa << (int)(exponent - FractionalBitCount);
|
||||||
|
@ -254,7 +285,7 @@ namespace Nuclex.Support {
|
||||||
fractional = (mantissa << (int)(exponent + 1)) & FractionalBits;
|
fractional = (mantissa << (int)(exponent + 1)) & FractionalBits;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (exponent < -FractionalBitCount) {
|
if(exponent < -FractionalBitCount) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
integral = 0;
|
integral = 0;
|
||||||
|
@ -262,30 +293,30 @@ namespace Nuclex.Support {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build the integral part
|
// Build the integral part
|
||||||
if (longValue < 0) {
|
if(longValue < 0) {
|
||||||
builder.Append('-');
|
builder.Append('-');
|
||||||
}
|
}
|
||||||
if (integral == 0) {
|
if(integral == 0) {
|
||||||
builder.Append('0');
|
builder.Append('0');
|
||||||
} else {
|
} else {
|
||||||
recursiveAppend(builder, integral);
|
recursiveAppend(builder, integral);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decimalPlaces > 0) {
|
if(decimalPlaces > 0) {
|
||||||
builder.Append('.');
|
builder.Append('.');
|
||||||
|
|
||||||
// Build the fractional part
|
// Build the fractional part
|
||||||
if (fractional == 0) {
|
if(fractional == 0) {
|
||||||
builder.Append('0');
|
builder.Append('0');
|
||||||
} else {
|
} else {
|
||||||
while (fractional != 0) {
|
while(fractional != 0) {
|
||||||
fractional *= 10;
|
fractional *= 10;
|
||||||
long digit = (fractional >> FractionalBitCountPlusOne);
|
long digit = (fractional >> FractionalBitCountPlusOne);
|
||||||
builder.Append(numbers[digit]);
|
builder.Append(numbers[digit]);
|
||||||
fractional &= FractionalBits;
|
fractional &= FractionalBits;
|
||||||
|
|
||||||
--decimalPlaces;
|
--decimalPlaces;
|
||||||
if (decimalPlaces == 0) {
|
if(decimalPlaces == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -307,7 +338,7 @@ namespace Nuclex.Support {
|
||||||
int tenth = remaining / 10;
|
int tenth = remaining / 10;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (tenth > 0) {
|
if(tenth > 0) {
|
||||||
recursiveAppend(builder, tenth);
|
recursiveAppend(builder, tenth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,7 +357,7 @@ namespace Nuclex.Support {
|
||||||
long tenth = remaining / 10;
|
long tenth = remaining / 10;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (tenth > 0) {
|
if(tenth > 0) {
|
||||||
recursiveAppend(builder, tenth);
|
recursiveAppend(builder, tenth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user