Commit b7d1bc7c authored by Ray Koopa's avatar Ray Koopa

Move common functionality to Syroot.BinaryData.Core.

parent 44cf070c
using System;
namespace Syroot.BinaryData.Core
{
/// <summary>
/// Represents utilities for working with the time_t format of the C library.
/// </summary>
public static class CTimeTools
{
// ---- FIELDS -------------------------------------------------------------------------------------------------
private static readonly DateTime _base = new DateTime(1970, 1, 1);
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
/// <summary>
/// Gets the <see cref="DateTime"/> instance representing the given time_t <paramref name="seconds"/>.
/// </summary>
/// <param name="seconds">The number of seconds as counted by the time_t instance.</param>
/// <returns>The <see cref="DateTime"/> instance.</returns>
public static DateTime GetDateTime(UInt64 seconds) => _base.AddSeconds(seconds);
/// <summary>
/// Calculates the seconds since 1970-01-01 for the given <paramref name="value"/>.
/// </summary>
/// <param name="value">The <see cref="DateTime"/> to calculate the seconds for.</param>
/// <returns>The seconds since 1970-01-01.</returns>
/// <exception cref="ArgumentOutOfRangeException">The value lies in front of the base date.</exception>
public static Double GetSeconds(DateTime value)
{
if (value < _base)
throw new ArgumentOutOfRangeException($"Date {value} cannot be represented by time_t.");
return (value - _base).TotalSeconds;
}
}
}
using System;
namespace Syroot.BinaryData.Core
{
/// <summary>
/// Represents the possible byte order of binary data.
/// </summary>
public enum Endian : ushort
{
/// <summary>Indicates that the endianness will not be changed for this operation.</summary>
None,
/// <summary>Indicates the byte order of the system executing the assembly.</summary>
System = 1,
/// <summary>Indicates big endian byte order.</summary>
Big = 0xFEFF,
/// <summary>Indicates little endian byte order.</summary>
Little = 0xFFFE
}
/// <summary>
/// Represents extension methods for <see cref="Endian"/> instances.
/// </summary>
public static class EndianExtensions
{
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
/// <summary>
/// Gets a value indicating whether the <see cref="Endian"/> equals the system's native endianness.
/// </summary>
/// <param name="self">The extended <see cref="Endian"/> instance.</param>
/// <returns><see langword="true"/> if this is the system endianness; otherwise, <see langword="false"/>.
/// </returns>
public static bool IsSystem(this Endian self)
{
return self != Endian.Big && BitConverter.IsLittleEndian
|| self != Endian.Little && !BitConverter.IsLittleEndian;
}
}
}
using System;
namespace Syroot.BinaryData.Core
{
/// <summary>
/// Represents utilities for working with <see cref="Endian"/> instances.
/// </summary>
public static class EndianTools
{
// ---- FIELDS -------------------------------------------------------------------------------------------------
/// <summary>The <see cref="Endian"/> representing system endianness.</summary>
public static readonly Endian SystemEndian = BitConverter.IsLittleEndian ? Endian.Little : Endian.Big;
/// <summary>The <see cref="Endian"/> not representing system endianness.</summary>
public static readonly Endian NonSystemEndian = BitConverter.IsLittleEndian ? Endian.Big : Endian.Little;
}
}
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using System.Runtime.CompilerServices;
namespace Syroot.BinaryData.Memory
namespace Syroot.BinaryData.Core
{
/// <summary>
/// Represents small helper functions.
/// Represents utilities for working with <see cref="Enum"/> instances.
/// </summary>
internal static class Tools
public static class EnumTools
{
// ---- FIELDS -------------------------------------------------------------------------------------------------
private static readonly DateTime _timeTBase = new DateTime(1970, 1, 1);
private static readonly Dictionary<Type, bool> _flagEnums = new Dictionary<Type, bool>();
private static readonly ConcurrentDictionary<Type, bool> _flagEnums = new ConcurrentDictionary<Type, bool>();
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
/// <summary>
/// Calculates the delta required to add to <paramref name="position"/> to reach the given
/// <paramref name="alignment"/>.
/// Validates the given <paramref name="value"/> to be defined in the enum of the given type, allowing combined
/// flags for enums decorated with the <see cref="FlagsAttribute"/>.
/// </summary>
/// <param name="position">The initial position.</param>
/// <param name="alignment">The multiple to align to. If negative, the delta is negative to reach the previous
/// multiple rather than the next one.</param>
/// <returns>The delta to add to the position.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static int GetAlignmentDelta(int position, int alignment)
{
return (-position % alignment + alignment) % alignment;
}
/// <summary>
/// Calculates the seconds since 1970-01-01 for the given <paramref name="value"/>.
/// </summary>
/// <param name="value">The <see cref="DateTime"/> to calculate the seconds for.</param>
/// <returns>The seconds since 1970-01-01.</returns>
/// <exception cref="ArgumentOutOfRangeException">The value lies in front of the base date.</exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static Double GetTimeTSeconds(DateTime value)
{
if (value < _timeTBase)
throw new ArgumentOutOfRangeException($"Date {value} cannot be represented by time_t.");
return (value - _timeTBase).TotalSeconds;
}
internal static bool ValidateEnumValue<T>(T value) where T : Enum
/// <param name="enumType">The type of the <see cref="Enum"/> to validate against.</param>
/// <param name="value">The value to validate.</param>
/// <returns><see langword="true"/> when the value is defined; otherwise, <see langword="false"/>.</returns>
public static bool Validate(Type enumType, object value)
{
// Check if a simple value is defined in the enum.
Type enumType = typeof(T);
bool valid = Enum.IsDefined(enumType, value);
if (!valid)
{
......@@ -56,7 +32,7 @@ namespace Syroot.BinaryData.Memory
if (!_flagEnums.TryGetValue(enumType, out bool isFlag))
{
isFlag = enumType.GetCustomAttributes(typeof(FlagsAttribute), false)?.Any() == true;
_flagEnums.Add(enumType, isFlag);
_flagEnums.TryAdd(enumType, isFlag);
}
if (isFlag)
{
......
namespace Syroot.BinaryData.Core
{
/// <summary>
/// Represents utilities for mathematical operations.
/// </summary>
public static class MathTools
{
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
/// <summary>
/// Calculates the delta required to add to <paramref name="position"/> to reach the given
/// <paramref name="alignment"/>.
/// </summary>
/// <param name="position">The initial position.</param>
/// <param name="alignment">The multiple to align to. If negative, the delta is negative to reach the previous
/// multiple rather than the next one.</param>
/// <returns>The delta to add to the position.</returns>
public static int GetAlignmentDelta(int position, int alignment)
{
return (-position % alignment + alignment) % alignment;
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Authors>Syroot</Authors>
<Copyright>(c) Syroot, licensed under MIT</Copyright>
<Description>.NET library providing common functionality for Syroot.BinaryData packages.</Description>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<LangVersion>latest</LangVersion>
<PackageIconUrl>https://gitlab.com/Syroot/BinaryData/raw/master/res/icon.png</PackageIconUrl>
<PackageLicenseUrl>https://gitlab.com/Syroot/BinaryData/raw/master/LICENSE</PackageLicenseUrl>
<PackageProjectUrl>https://gitlab.com/Syroot/BinaryData</PackageProjectUrl>
<PackageReleaseNotes>Initial release.</PackageReleaseNotes>
<PackageTags>binary data</PackageTags>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://gitlab.com/Syroot/BinaryData</RepositoryUrl>
<TargetFrameworks>net452;netcoreapp2.1;netstandard2.0</TargetFrameworks>
<VersionPrefix>5.2.0-alpha1</VersionPrefix>
</PropertyGroup>
</Project>
namespace Syroot.BinaryData.Scratchpad
{
internal class Program
{
// ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
private static void Main(string[] args)
{
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net452;netcoreapp2.1;netstandard2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Syroot.BinaryData.Memory\Syroot.BinaryData.Memory.csproj" />
<ProjectReference Include="..\Syroot.BinaryData.Serialization\Syroot.BinaryData.Serialization.csproj" />
<ProjectReference Include="..\Syroot.BinaryData\Syroot.BinaryData.csproj" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<IsPackable>false</IsPackable>
<LangVersion>latest</LangVersion>
<TargetFramework>net452</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.6.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.2.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Syroot.BinaryData.Serialization\Syroot.BinaryData.Serialization.csproj" />
<ProjectReference Include="..\Syroot.BinaryData\Syroot.BinaryData.csproj" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<AssemblyName>Syroot.BinaryData.Serialization</AssemblyName>
<AssemblyTitle>BinaryData Serialization</AssemblyTitle>
<Authors>Syroot</Authors>
<Configurations>Debug;Release;ReleaseSigned</Configurations>
<Copyright>(c) Syroot, licensed under MIT</Copyright>
<Description>.NET library automating binary serialization of classes and structs.</Description>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageIconUrl>https://raw.githubusercontent.com/Syroot/BinaryData/master/res/Logo.png</PackageIconUrl>
<PackageId>Syroot.BinaryData.Serialization</PackageId>
<PackageLicenseUrl>https://raw.githubusercontent.com/Syroot/BinaryData/master/LICENSE</PackageLicenseUrl>
<PackageProjectUrl>https://github.com/Syroot/BinaryData</PackageProjectUrl>
<PackageReleaseNotes>Separated from Syroot.IO.BinaryData package.</PackageReleaseNotes>
<PackageTags>binary;data;io;binaryreader;binarywriter;serialization</PackageTags>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/Syroot/BinaryData</RepositoryUrl>
<TargetFrameworks>net452;netstandard2.0</TargetFrameworks>
<VersionPrefix>5.0.0</VersionPrefix>
<AssemblyOriginatorKeyFile>Syroot.BinaryData.Serialization.pfx</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Syroot.BinaryData\Syroot.BinaryData.csproj" />
</ItemGroup>
<!-- Release (Signed) -->
<PropertyGroup Condition="'$(Configuration)' == 'ReleaseSigned'">
<AssemblyOriginatorKeyFile>Syroot.BinaryData.Serialization.pfx</AssemblyOriginatorKeyFile>
<PackageId>Syroot.BinaryData.Serialization.Signed</PackageId>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Authors>Syroot</Authors>
<Copyright>(c) Syroot, licensed under MIT</Copyright>
<Description>.NET library automating binary serialization of classes and structs.</Description>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<LangVersion>latest</LangVersion>
<PackageIconUrl>https://gitlab.com/Syroot/BinaryData/raw/master/res/icon.png</PackageIconUrl>
<PackageLicenseUrl>https://gitlab.com/Syroot/BinaryData/raw/master/LICENSE</PackageLicenseUrl>
<PackageProjectUrl>https://gitlab.com/Syroot/BinaryData</PackageProjectUrl>
<PackageReleaseNotes>Move common functionality to BinaryData.Core package.</PackageReleaseNotes>
<PackageTags>binary binaryreader binarywriter data io serialization stream</PackageTags>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://gitlab.com/Syroot/BinaryData</RepositoryUrl>
<TargetFrameworks>net452;netstandard2.0</TargetFrameworks>
<VersionPrefix>5.2.0-alpha1</VersionPrefix>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Syroot.BinaryData\Syroot.BinaryData.csproj" />
</ItemGroup>
</Project>
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Syroot.BinaryData.Core;
namespace Syroot.BinaryData.Test
{
......
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net452</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.2.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.2.0" />
<ProjectReference Include="..\Syroot.BinaryData\Syroot.BinaryData.csproj" />
</ItemGroup>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<IsPackable>false</IsPackable>
<LangVersion>latest</LangVersion>
<TargetFramework>net452</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.2.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.2.0" />
<ProjectReference Include="..\Syroot.BinaryData\Syroot.BinaryData.csproj" />
</ItemGroup>
</Project>
using System;
using Syroot.BinaryData.Core;
namespace Syroot.BinaryData
{
......@@ -13,7 +14,7 @@ namespace Syroot.BinaryData
/// The exception thrown if a conversion buffer is too small or <c>null</c>.
/// </summary>
protected static readonly Exception BufferException = new Exception("Buffer null or too small.");
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
/// <summary>
......@@ -56,7 +57,7 @@ namespace Syroot.BinaryData
public static ByteConverter System { get; }
/// <summary>
/// Gets the <see cref="BinaryData.Endian"/> in which data is stored as converted by this instance.
/// Gets the <see cref="Core.Endian"/> in which data is stored as converted by this instance.
/// </summary>
public abstract Endian Endian { get; }
......@@ -81,7 +82,7 @@ namespace Syroot.BinaryData
throw new ArgumentException($"Invalid {nameof(Endian)}.", nameof(byteOrder));
}
}
/// <summary>
/// Stores the specified <see cref="Decimal"/> value as bytes in the given <paramref name="buffer"/>.
/// </summary>
......@@ -118,7 +119,7 @@ namespace Syroot.BinaryData
/// <param name="value">The value to convert.</param>
/// <param name="buffer">The byte array to store the value in.</param>
public abstract void GetBytes(Int16 value, Span<byte> buffer);
/// <summary>
/// Stores the specified <see cref="Int32"/> value as bytes in the given <paramref name="buffer"/>.
/// </summary>
......@@ -190,7 +191,7 @@ namespace Syroot.BinaryData
/// <param name="buffer">The byte array storing the raw data.</param>
/// <returns>The converted value.</returns>
public abstract Double ToDouble(ReadOnlySpan<byte> buffer);
/// <summary>
/// Returns an <see cref="Int16"/> instance converted from the bytes in the given <paramref name="buffer"/>.
/// </summary>
......@@ -220,21 +221,21 @@ namespace Syroot.BinaryData
public abstract Single ToSingle(ReadOnlySpan<byte> buffer);
/// <summary>
/// Returns an <see cref="UInt16"/> instance converted from the bytes in the given <paramref name="buffer"/>.
/// Returns a <see cref="UInt16"/> instance converted from the bytes in the given <paramref name="buffer"/>.
/// </summary>
/// <param name="buffer">The byte array storing the raw data.</param>
/// <returns>The converted value.</returns>
public abstract UInt16 ToUInt16(ReadOnlySpan<byte> buffer);
/// <summary>
/// Returns an <see cref="UInt32"/> instance converted from the bytes in the given <paramref name="buffer"/>.
/// Returns a <see cref="UInt32"/> instance converted from the bytes in the given <paramref name="buffer"/>.
/// </summary>
/// <param name="buffer">The byte array storing the raw data.</param>
/// <returns>The converted value.</returns>
public abstract UInt32 ToUInt32(ReadOnlySpan<byte> buffer);
/// <summary>
/// Returns an <see cref="UInt64"/> instance converted from the bytes in the given <paramref name="buffer"/>.
/// Returns a <see cref="UInt64"/> instance converted from the bytes in the given <paramref name="buffer"/>.
/// </summary>
/// <param name="buffer">The byte array storing the raw data.</param>
/// <returns>The converted value.</returns>
......
using System;
using System.Security;
using Syroot.BinaryData.Core;
namespace Syroot.BinaryData
{
......@@ -12,7 +13,7 @@ namespace Syroot.BinaryData
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
/// <summary>
/// Gets the <see cref="BinaryData.Endian"/> in which data is stored as converted by this instance.
/// Gets the <see cref="Core.Endian"/> in which data is stored as converted by this instance.
/// </summary>
public override Endian Endian => Endian.Big;
......@@ -210,7 +211,7 @@ namespace Syroot.BinaryData
}
/// <summary>
/// Returns an <see cref="UInt16"/> instance converted from the bytes in the given <paramref name="buffer"/>.
/// Returns a <see cref="UInt16"/> instance converted from the bytes in the given <paramref name="buffer"/>.
/// </summary>
/// <param name="buffer">The byte array storing the raw data.</param>
/// <returns>The converted value.</returns>
......@@ -221,7 +222,7 @@ namespace Syroot.BinaryData
}
/// <summary>
/// Returns an <see cref="UInt32"/> instance converted from the bytes in the given <paramref name="buffer"/>.
/// Returns a <see cref="UInt32"/> instance converted from the bytes in the given <paramref name="buffer"/>.
/// </summary>
/// <param name="buffer">The byte array storing the raw data.</param>
/// <returns>The converted value.</returns>
......@@ -234,7 +235,7 @@ namespace Syroot.BinaryData
}
/// <summary>
/// Returns an <see cref="UInt64"/> instance converted from the bytes in the given <paramref name="buffer"/>.
/// Returns a <see cref="UInt64"/> instance converted from the bytes in the given <paramref name="buffer"/>.
/// </summary>
/// <param name="buffer">The byte array storing the raw data.</param>
/// <returns>The converted value.</returns>
......
using System;
using System.Security;
using Syroot.BinaryData.Core;
namespace Syroot.BinaryData
{
......@@ -12,7 +13,7 @@ namespace Syroot.BinaryData
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
/// <summary>
/// Gets the <see cref="BinaryData.Endian"/> in which data is stored as converted by this instance.
/// Gets the <see cref="Core.Endian"/> in which data is stored as converted by this instance.
/// </summary>
public override Endian Endian => Endian.Little;
......@@ -210,7 +211,7 @@ namespace Syroot.BinaryData
}
/// <summary>
/// Returns an <see cref="UInt16"/> instance converted from the bytes in the given <paramref name="buffer"/>.
/// Returns a <see cref="UInt16"/> instance converted from the bytes in the given <paramref name="buffer"/>.
/// </summary>
/// <param name="buffer">The byte array storing the raw data.</param>
/// <returns>The converted value.</returns>
......@@ -221,7 +222,7 @@ namespace Syroot.BinaryData
}
/// <summary>
/// Returns an <see cref="UInt32"/> instance converted from the bytes in the given <paramref name="buffer"/>.
/// Returns a <see cref="UInt32"/> instance converted from the bytes in the given <paramref name="buffer"/>.
/// </summary>
/// <param name="buffer">The byte array storing the raw data.</param>
/// <returns>The converted value.</returns>
......@@ -234,7 +235,7 @@ namespace Syroot.BinaryData
}
/// <summary>
/// Returns an <see cref="UInt64"/> instance converted from the bytes in the given <paramref name="buffer"/>.
/// Returns a <see cref="UInt64"/> instance converted from the bytes in the given <paramref name="buffer"/>.
/// </summary>
/// <param name="buffer">The byte array storing the raw data.</param>
/// <returns>The converted value.</returns>
......
using System;
using System.Runtime.InteropServices;
using System.Security;
using Syroot.BinaryData.Core;
namespace Syroot.BinaryData
{
......@@ -10,16 +11,12 @@ namespace Syroot.BinaryData
[SecuritySafeCritical]
public sealed class ByteConverterSystem : ByteConverter
{
// ---- FIELDS -------------------------------------------------------------------------------------------------
private readonly Endian _systemEndianness = BitConverter.IsLittleEndian ? Endian.Little : Endian.Big;
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
/// <summary>
/// Gets the <see cref="BinaryData.Endian"/> in which data is stored as converted by this instance.
/// Gets the <see cref="Core.Endian"/> in which data is stored as converted by this instance.
/// </summary>
public override Endian Endian => _systemEndianness;
public override Endian Endian => EndianTools.SystemEndian;
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
......@@ -131,21 +128,21 @@ namespace Syroot.BinaryData
public override Single ToSingle(ReadOnlySpan<byte> buffer) => MemoryMarshal.Cast<byte, Single>(buffer)[0];
/// <summary>
/// Returns an <see cref="UInt16"/> instance converted from the bytes in the given <paramref name="buffer"/>.
/// Returns a <see cref="UInt16"/> instance converted from the bytes in the given <paramref name="buffer"/>.
/// </summary>
/// <param name="buffer">The byte array storing the raw data.</param>
/// <returns>The converted value.</returns>
public override UInt16 ToUInt16(ReadOnlySpan<byte> buffer) => MemoryMarshal.Cast<byte, UInt16>(buffer)[0];
/// <summary>
/// Returns an <see cref="UInt32"/> instance converted from the bytes in the given <paramref name="buffer"/>.
/// Returns a <see cref="UInt32"/> instance converted from the bytes in the given <paramref name="buffer"/>.
/// </summary>
/// <param name="buffer">The byte array storing the raw data.</param>
/// <returns>The converted value.</returns>
public override UInt32 ToUInt32(ReadOnlySpan<byte> buffer) => MemoryMarshal.Cast<byte, UInt32>(buffer)[0];
/// <summary>
/// Returns an <see cref="UInt64"/> instance converted from the bytes in the given <paramref name="buffer"/>.
/// Returns a <see cref="UInt64"/> instance converted from the bytes in the given <paramref name="buffer"/>.
/// </summary>
/// <param name="buffer">The byte array storing the raw data.</param>
/// <returns>The converted value.</returns>
......
namespace Syroot.BinaryData
{
/// <summary>
/// Represents the possible byte order of binary data.
/// </summary>
public enum Endian : ushort
{
/// <summary>
/// Indicates that the endianness will not be changed for this operation.
/// </summary>
None,
/// <summary>
/// Indicates the byte order of the system executing the assembly.
/// </summary>
System = 1,
/// <summary>
/// Indicates big endian byte order.
/// </summary>
Big = 0xFEFF,
/// <summary>
/// Indicates little endian byte order.
/// </summary>
Little = 0xFFFE
}
}
using System;
using System.Collections.Concurrent;
using System.Linq;
namespace Syroot.BinaryData
{
/// <summary>
/// Represents a collection of methods extending enum types.
/// </summary>
public static class EnumTools
{
// ---- FIELDS -------------------------------------------------------------------------------------------------
private static ConcurrentDictionary<Type, bool> _flagEnums = new ConcurrentDictionary<Type, bool>();
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
/// <summary>
/// Returns whether <paramref name="value"/> is a defined value in the enum of the given
/// <paramref name="enumType"/> or a valid set of flags for enums decorated with the
/// <see cref="FlagsAttribute"/>.
/// </summary>
/// <param name="enumType">The type of the enum.</param>
/// <param name="value">The value to check against the enum type.</param>
/// <returns><c>true</c> if the value is valid; otherwise <c>false</c>.</returns>
public static bool IsValid(Type enumType, object value)
{
// For enumerations decorated with the FlagsAttribute, allow sets of flags.
bool valid = Enum.IsDefined(enumType, value);
if (!valid && IsFlagsEnum(enumType))
{
long mask = 0;
foreach (object definedValue in Enum.GetValues(enumType))
mask |= Convert.ToInt64(definedValue);
long longValue = Convert.ToInt64(value);
valid = (mask & longValue) == longValue;
}
return valid;
}
// ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
private static bool IsFlagsEnum(Type type)
{
if (!_flagEnums.TryGetValue(type, out bool value))
{
value = type.GetCustomAttributes(typeof(FlagsAttribute), true)?.Any() == true;
_flagEnums.TryAdd(type, value);
}
return value;
}
}
}
......@@ -3,15 +3,12 @@ using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Syroot.BinaryData.Core;
namespace Syroot.BinaryData
{
public static partial class StreamExtensions
{
// ---- FIELDS -------------------------------------------------------------------------------------------------
private static readonly DateTime _cTimeBase = new DateTime(1970, 1, 1);
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
// ---- Read 1 DateTime ----
......@@ -29,11 +26,11 @@ namespace Syroot.BinaryData
switch (coding)
{
case DateTimeCoding.NetTicks:
return ReadDateTimeAsNetTicks(stream, converter);
return new DateTime(ReadInt64(stream, converter));
case DateTimeCoding.CTime:
return ReadDateTimeAsCTime(stream, converter);
return CTimeTools.GetDateTime(ReadUInt32(stream, converter));
case DateTimeCoding.CTime64:
return ReadDateTimeAsCTime64(stream, converter);
return CTimeTools.GetDateTime(ReadUInt64(stream, converter));
default:
throw new ArgumentException($"Invalid {nameof(DateTimeCoding)}.", nameof(coding));
}
......@@ -54,11 +51,11 @@ namespace Syroot.BinaryData
switch (coding)
{
case DateTimeCoding.NetTicks:
return await ReadDateTimeAsNetTicksAsync(stream, converter, cancellationToken);
return new DateTime(await ReadInt64Async(stream, converter, cancellationToken));
case DateTimeCoding.CTime:
return await ReadDateTimeAsCTimeAsync(stream, converter, cancellationToken);
return CTimeTools.GetDateTime(await ReadUInt32Async(stream, converter, cancellationToken));
case DateTimeCoding.CTime64:
return await ReadDateTimeAsCTime64Async(stream, converter, cancellationToken);
return CTimeTools.GetDateTime(await ReadUInt64Async(stream, converter, cancellationToken));
default:
throw new ArgumentException($"Invalid {nameof(DateTimeCoding)}.", nameof(coding));
}
......@@ -119,10 +116,10 @@ namespace Syroot.BinaryData
Write(stream, value.Ticks, converter);
break;
case DateTimeCoding.CTime:
Write(stream, (UInt32)GetCTimeTicks(value), converter);
Write(stream, (UInt32)CTimeTools.GetSeconds(value), converter);
break;
case DateTimeCoding.CTime64:
Write(stream, (UInt64)GetCTimeTicks(value), converter);
Write(stream, (UInt64)CTimeTools.GetSeconds(value), converter);
break;
default:
throw new ArgumentException($"Invalid {nameof(DateTimeCoding)}.", nameof(coding));
......@@ -148,11 +145,11 @@ namespace Syroot.BinaryData
await WriteAsync(stream, value.Ticks, converter, cancellationToken);
break;
case DateTimeCoding.CTime:
await WriteAsync(stream, (UInt32)GetCTimeTicks(value), converter,
await WriteAsync(stream, (UInt32)CTimeTools.GetSeconds(value), converter,
cancellationToken);