Skip to content

Commit

Permalink
Added UtilPack.JSON.Configuration and resurrected old method. The new…
Browse files Browse the repository at this point in the history
… project is from ResourcePooling repo originally.
  • Loading branch information
stazz committed Feb 10, 2019
1 parent 0792069 commit 8ab0646
Show file tree
Hide file tree
Showing 6 changed files with 299 additions and 56 deletions.
157 changes: 157 additions & 0 deletions Source/Code/UtilPack.JSON.Configuration/StringContents.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/*
* Copyright 2019 Stanislav Muhametsin. All rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.FileProviders;
using System;
using System.Text;

namespace UtilPack.JSON.Configuration
{
internal sealed class StringContentFileProvider : IFileProvider
{
public const String PATH = ":::non-existing:::";

private readonly FileInfo _fileInfo;


public StringContentFileProvider( String stringContents )
: this( new FileInfo( stringContents ) )
{

}

public StringContentFileProvider( Byte[] serializedContents )
: this( new FileInfo( serializedContents ) )
{
}

private StringContentFileProvider( FileInfo info )
{
this._fileInfo = ArgumentValidator.ValidateNotNull( nameof( info ), info );
}



public IDirectoryContents GetDirectoryContents( String subpath )
{
return NotFoundDirectoryContents.Singleton;
}

public IFileInfo GetFileInfo( String subpath )
{
return String.Equals( PATH, subpath, StringComparison.Ordinal ) ?
this._fileInfo :
null;
}

public Microsoft.Extensions.Primitives.IChangeToken Watch( String filter )
{
return ChangeToken.Instance;
}

private sealed class FileInfo : IFileInfo
{

private static readonly Encoding TheEncoding = new UTF8Encoding( false, false );

private readonly Byte[] _contentsAsBytes;

public FileInfo( String stringContents )
: this( TheEncoding.GetBytes( stringContents ) )
{

}

public FileInfo( Byte[] serializedContents )
{
this._contentsAsBytes = serializedContents;
}

public Boolean Exists => true;

public Int64 Length => this._contentsAsBytes.Length;

public String PhysicalPath => PATH;

public String Name => PATH;

public DateTimeOffset LastModified => DateTimeOffset.MinValue;

public Boolean IsDirectory => false;

public System.IO.Stream CreateReadStream()
{
return new System.IO.MemoryStream( this._contentsAsBytes, 0, this._contentsAsBytes.Length, false, false );
}
}

private sealed class ChangeToken : Microsoft.Extensions.Primitives.IChangeToken
{
public static ChangeToken Instance = new ChangeToken();

private ChangeToken()
{

}

public Boolean HasChanged => false;

public Boolean ActiveChangeCallbacks => true;

public IDisposable RegisterChangeCallback(
Action<Object> callback,
Object state
)
{
return NoOpDisposable.Instance;
}
}


}

/// <summary>
/// This class contains extension methods for types defined in other assemblies.
/// </summary>
public static partial class JsonConfigurationExtensions
{
/// <summary>
/// Adds the given string as JSON content for this <see cref="IConfigurationBuilder"/>.
/// </summary>
/// <param name="builder">This <see cref="IConfigurationBuilder"/>.</param>
/// <param name="textualContents">The JSON contents, as <see cref="String"/>.</param>
/// <returns>The <paramref name="builder"/>.</returns>
public static IConfigurationBuilder AddJsonContents( this IConfigurationBuilder builder, String textualContents )
{
return ArgumentValidator.ValidateNotNullReference( builder )
.AddJsonFile( new StringContentFileProvider( textualContents ), StringContentFileProvider.PATH, false, false );
}

/// <summary>
/// Adds the given serialized string as JSON content for this <see cref="IConfigurationBuilder"/>.
/// </summary>
/// <param name="builder">This <see cref="IConfigurationBuilder"/>.</param>
/// <param name="stringAsBytes">The JSON contents, as <see cref="Byte"/> array.</param>
/// <returns>The <paramref name="builder"/>.</returns>
public static IConfigurationBuilder AddJsonContents( this IConfigurationBuilder builder, Byte[] stringAsBytes )
{
return ArgumentValidator.ValidateNotNullReference( builder )
.AddJsonFile( new StringContentFileProvider( stringAsBytes ), StringContentFileProvider.PATH, false, false );
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard1.3;netstandard2.0;net451</TargetFrameworks>
</PropertyGroup>

<PropertyGroup>
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="../UtilPack/UtilPack.csproj" />
</ItemGroup>

<PropertyGroup>
<MicrosoftConfigurationVersion Condition=" '$(TargetFramework)' == 'net451' Or '$(TargetFramework)' == 'netstandard1.3' ">1.1.2</MicrosoftConfigurationVersion>
<MicrosoftConfigurationVersion Condition=" '$(TargetFramework)' != 'net451' And '$(TargetFramework)' != 'netstandard1.3'">2.2.0</MicrosoftConfigurationVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="$(MicrosoftConfigurationVersion)" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
<Reference Include="System.Runtime" />
<Reference Include="System.Threading.Tasks" />
</ItemGroup>


<!-- Assembly information stuff -->
<PropertyGroup>
<VersionPrefix>1.0.0</VersionPrefix>
<VersionSuffix></VersionSuffix>
<AssemblyTitle>$(AssemblyName)</AssemblyTitle>
<Description>Small library containing extension methods for Microsoft.Extensions.Configuiration.Json package, including methods to add JSON contents as string or byte array.</Description>
</PropertyGroup>

<!-- NuGet package stuff -->
<PropertyGroup>
<PackageId>$(AssemblyName)</PackageId>
<PackageVersion>$(VersionPrefix)</PackageVersion>
<PackageVersion Condition=" '$(VersionSuffix)' != ''">$(PackageVersion)-$(VersionSuffix)</PackageVersion>
<PackageReleaseNotes>Initial release.</PackageReleaseNotes>
<PackageTags>json utility microsoft configuration extensions json</PackageTags>
<Title>UtilPack: Extensions for Microsoft.Extensions.Configuration.Json</Title>
</PropertyGroup>

<Import Project="$(CIPropsFilePath)" Condition=" '$(CIPropsFilePath)' != '' and Exists('$(CIPropsFilePath)') " />

</Project>
109 changes: 56 additions & 53 deletions Source/Code/UtilPack/BinaryExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using UtilPack;

namespace UtilPack
Expand Down Expand Up @@ -220,62 +222,63 @@ public static Stream SeekFromBegin( this Stream stream, Int64 position )
// return (Byte) b;
// }

// /// <summary>
// /// Reads a whole stream and returns its contents as single byte array.
// /// </summary>
// /// <param name="stream">The stream to read.</param>
// /// <param name="buffer">The optional buffer to use. If not specified, then a buffer of <c>1024</c> bytes will be used. The buffer will only be used if stream does not support querying length and position.</param>
// /// <returns>The stream contents as single byte array.</returns>
// /// <exception cref="NullReferenceException">If <paramref name="stream"/> is <c>null</c>.</exception>
//#if !NET40
// [System.Runtime.CompilerServices.MethodImpl( System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining )]
//#endif
// public static Byte[] ReadUntilTheEnd( this Stream stream, Byte[] buffer = null )
// {
// Int64 arrayLen = -1;
// if ( stream.CanSeek )
// {
// try
// {
// arrayLen = stream.Length - stream.Position;
// }
// catch ( NotSupportedException )
// {
// // stream can't be queried for length or position
// }
// }
/// <summary>
/// Reads a whole stream and returns its contents as single byte array.
/// </summary>
/// <param name="stream">The stream to read.</param>
/// <param name="buffer">The optional buffer to use. If not specified, then a buffer of <c>1024</c> bytes will be used. The buffer will only be used if stream does not support querying length and position.</param><
/// <param name="token">The <see cref="CancellationToken"/>.</param>
/// <returns>The stream contents as single byte array.</returns>
/// <exception cref="NullReferenceException">If <paramref name="stream"/> is <c>null</c>.</exception>
#if !NET40
[System.Runtime.CompilerServices.MethodImpl( System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining )]
#endif
public static async Task<Byte[]> ReadUntilTheEndAsync( this Stream stream, CancellationToken token, Byte[] buffer = null )
{
Int64 arrayLen = -1;
if ( stream.CanSeek )
{
try
{
arrayLen = stream.Length - stream.Position;
}
catch ( NotSupportedException )
{
// stream can't be queried for length or position
}
}

// Byte[] retVal;
// if ( arrayLen < 0 )
// {
// // Have to read using the buffer.
// if ( buffer == null )
// {
// buffer = new Byte[1024];
// }
Byte[] retVal;
if ( arrayLen < 0 )
{
// Have to read using the buffer.
if ( buffer == null )
{
buffer = new Byte[1024];
}

// using ( var ms = new MemoryStream() )
// {
// Int32 read;
// while ( ( read = stream.Read( buffer, 0, buffer.Length ) ) > 0 )
// {
// ms.Write( buffer, 0, read );
// }
// retVal = ms.ToArray();
// }
// }
// else if ( arrayLen == 0 )
// {
// retVal = Empty<Byte>.Array;
// }
// else
// {
// retVal = new Byte[arrayLen];
// stream.ReadWholeArray( retVal );
// }
using ( var ms = new MemoryStream() )
{
Int32 read;
while ( ( read = await stream.ReadAsync( buffer, 0, buffer.Length, token ) ) > 0 )
{
ms.Write( buffer, 0, read );
}
retVal = ms.ToArray();
}
}
else if ( arrayLen == 0 )
{
retVal = Empty<Byte>.Array;
}
else
{
retVal = new Byte[arrayLen];
await stream.ReadAtLeastAsync( retVal, 0, retVal.Length, retVal.Length, token );
}

// return retVal;
// }
return retVal;
}

/// <summary>
/// Reads a single byte at specified index in byte array.
Expand Down
27 changes: 27 additions & 0 deletions Source/Code/UtilPack/StreamRelated.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1626,6 +1626,7 @@ public static Int32 AppendToBytes( this StreamWriterWithResizableBuffer writer,
}


// TODO remove this method in 2.0, as there is overload with cancellation token which should be used.
/// <summary>
/// Using given chunk read size, read at least the given amount of bytes into the given array from this stream.
/// </summary>
Expand All @@ -1649,6 +1650,32 @@ public static async Task<Int32> ReadAtLeastAsync( this Stream stream, Byte[] arr
offset += readCount;
}
return offset - originalOffset;
}

/// <summary>
/// Using given chunk read size, read at least the given amount of bytes into the given array from this stream.
/// </summary>
/// <param name="stream">This stream.</param>
/// <param name="array">The byte array to write data to.</param>
/// <param name="offset">The offset in <paramref name="array"/> where to start writing.</param>
/// <param name="minAmount">The minimum amount to read.</param>
/// <param name="chunkCount">The maximum amount of bytes to read at a time.</param>
/// <param name="token">The <see cref="CancellationToken"/> to use.</param>
/// <returns>Asynchronously returns amount of bytes read.</returns>
public static async Task<Int32> ReadAtLeastAsync( this Stream stream, Byte[] array, Int32 offset, Int32 minAmount, Int32 chunkCount, CancellationToken token )
{
var originalOffset = offset;
while ( minAmount > 0 )
{
var readCount = await stream.ReadAsync( array, offset, chunkCount, token );
if ( readCount <= 0 )
{
throw new EndOfStreamException();
}
minAmount -= readCount;
offset += readCount;
}
return offset - originalOffset;
}

/// <summary>
Expand Down
4 changes: 2 additions & 2 deletions Source/Code/UtilPack/UtilPack.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

<!-- Assembly information stuff -->
<PropertyGroup>
<VersionPrefix>1.7.1</VersionPrefix>
<VersionPrefix>1.7.2</VersionPrefix>
<VersionSuffix></VersionSuffix>
<AssemblyTitle>UtilPack.Common</AssemblyTitle>
<Description>Library containing useful and generic methods, which are missing from one or more BCL.</Description>
Expand All @@ -35,7 +35,7 @@
<PackageId>$(AssemblyName)</PackageId>
<PackageVersion>$(VersionPrefix)</PackageVersion>
<PackageVersion Condition=" '$(VersionSuffix)' != ''">$(PackageVersion)-$(VersionSuffix)</PackageVersion>
<PackageReleaseNotes>Removed Prepend and Append extension methods for IEnumerable&lt;T&gt; from netstandard2.0 version.</PackageReleaseNotes>
<PackageReleaseNotes>Restored method to read the remaining bytes in stream into single byte array.</PackageReleaseNotes>
<PackageTags>bcl utility binary serialization collection extensions</PackageTags>
<Title>Utility Package for CLR</Title>
</PropertyGroup>
Expand Down
Loading

0 comments on commit 8ab0646

Please sign in to comment.