Created
March 17, 2014 02:04
-
-
Save Virtlink/9592717 to your computer and use it in GitHub Desktop.
Helper methods for copying data between linear and circular arrays.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Diagnostics.Contracts; | |
namespace Virtlink | |
{ | |
/// <summary> | |
/// Helper methods for working with circular arrays. | |
/// </summary> | |
/// <example> | |
/// Usage example: | |
/// <code> | |
/// byte[] source = new byte[] { 0xAA, 0xBB, 0xCC, 0xDD }; | |
/// byte[] destination = new byte[6]; | |
/// CircularArray.CopyToCircular(source, 0, destination, 4, source.Length); | |
/// // Result: | |
/// // { 0xCC, 0xDD, 0x00, 0x00, 0xAA, 0xBB } | |
/// </code> | |
/// </example> | |
/// <remarks> | |
/// Created by Virtlink. Original source code on GitHub: | |
/// <see href="https://gist.github.com/Virtlink/9592717"/>. | |
/// </remarks> | |
public static class CircularArray | |
{ | |
/// <summary> | |
/// Copies data from a linear array to a circular array. | |
/// </summary> | |
/// <param name="sourceArray">The linear source array.</param> | |
/// <param name="sourceIndex">The zero-based offset | |
/// in <paramref name="sourceArray"/> at which to start reading.</param> | |
/// <param name="destinationArray">The circular destination array.</param> | |
/// <param name="destinationIndex">The zero-based offset | |
/// in <paramref name="destinationArray"/> at which to start writing.</param> | |
/// <param name="length">The number of elements to copy.</param> | |
public static void CopyToCircular<T>( | |
T[] sourceArray, | |
int sourceIndex, | |
T[] destinationArray, | |
int destinationIndex, | |
int length) | |
{ | |
#region Contract | |
Contract.Requires<ArgumentNullException>(sourceArray != null); | |
Contract.Requires<ArgumentOutOfRangeException>(sourceIndex >= 0); | |
Contract.Requires<ArgumentOutOfRangeException>(destinationIndex >= 0); | |
Contract.Requires<ArgumentOutOfRangeException>(sourceIndex + length <= sourceArray.Length); | |
Contract.Requires<ArgumentOutOfRangeException>(length <= destinationArray.Length); | |
#endregion | |
if (length == 0) | |
return; | |
// The source is a continuous range. | |
if (destinationIndex + length <= destinationArray.Length) | |
{ | |
// The destination is a continuous range. | |
// |---11111--------| => |-------11111----| | |
int toCopy = length; | |
Array.Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, toCopy); | |
} | |
else | |
{ | |
// The destination is split into two ranges. | |
// |---11122--------| => |22-----------111| | |
int toCopy = destinationArray.Length - destinationIndex; | |
Array.Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, toCopy); | |
Array.Copy(sourceArray, sourceIndex + toCopy, destinationArray, 0, length - toCopy); | |
} | |
} | |
/// <summary> | |
/// Copies data from a circular array to a linear array. | |
/// </summary> | |
/// <param name="sourceArray">The circular source array.</param> | |
/// <param name="sourceIndex">The zero-based offset | |
/// in <paramref name="sourceArray"/> at which to start reading.</param> | |
/// <param name="destinationArray">The linear destination array.</param> | |
/// <param name="destinationIndex">The zero-based offset | |
/// in <paramref name="destinationArray"/> at which to start writing.</param> | |
/// <param name="length">The number of elements to copy.</param> | |
public static void CopyFromCircular<T>( | |
T[] sourceArray, | |
int sourceIndex, | |
T[] destinationArray, | |
int destinationIndex, | |
int length) | |
{ | |
#region Contract | |
Contract.Requires<ArgumentNullException>(sourceArray != null); | |
Contract.Requires<ArgumentOutOfRangeException>(sourceIndex >= 0); | |
Contract.Requires<ArgumentOutOfRangeException>(destinationIndex >= 0); | |
Contract.Requires<ArgumentOutOfRangeException>(length < sourceArray.Length); | |
Contract.Requires<ArgumentOutOfRangeException>(destinationIndex + length <= destinationArray.Length); | |
#endregion | |
if (length == 0) | |
return; | |
// The destination is a continuous range. | |
if (sourceIndex + length <= sourceArray.Length) | |
{ | |
// The source is a continuous range. | |
// |---11111--------| => |-------11111----| | |
int toCopy = length; | |
Array.Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, toCopy); | |
} | |
else | |
{ | |
// The source is split into two ranges. | |
// |222-----------11| => |-------11222----| | |
int toCopy = sourceArray.Length - sourceIndex; | |
Array.Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, toCopy); | |
Array.Copy(sourceArray, 0, destinationArray, destinationIndex + toCopy, length - toCopy); | |
} | |
} | |
/// <summary> | |
/// Copies data from one circular array to another circular array. | |
/// </summary> | |
/// <param name="sourceArray">The circular source array.</param> | |
/// <param name="sourceIndex">The zero-based offset | |
/// in <paramref name="sourceArray"/> at which to start reading.</param> | |
/// <param name="destinationArray">The circular destination array.</param> | |
/// <param name="destinationIndex">The zero-based offset | |
/// in <paramref name="destinationArray"/> at which to start writing.</param> | |
/// <param name="length">The number of elements to copy.</param> | |
public static void CopyCircular<T>( | |
T[] sourceArray, | |
int sourceIndex, | |
T[] destinationArray, | |
int destinationIndex, | |
int length) | |
{ | |
#region Contract | |
Contract.Requires<ArgumentNullException>(sourceArray != null); | |
Contract.Requires<ArgumentOutOfRangeException>(sourceIndex >= 0); | |
Contract.Requires<ArgumentOutOfRangeException>(destinationIndex >= 0); | |
Contract.Requires<ArgumentOutOfRangeException>(length < sourceArray.Length); | |
Contract.Requires<ArgumentOutOfRangeException>(length < destinationArray.Length); | |
#endregion | |
if (length == 0) | |
return; | |
if (sourceIndex + length <= sourceArray.Length) | |
{ | |
// The source is a continuous range. | |
if (destinationIndex + length <= destinationArray.Length) | |
{ | |
// The destination is a continuous range. | |
// |---11111--------| => |-------11111----| | |
int toCopy = length; | |
Array.Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, toCopy); | |
} | |
else | |
{ | |
// The destination is split into two ranges. | |
// |---11122--------| => |22-----------111| | |
int toCopy = destinationArray.Length - destinationIndex; | |
Array.Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, toCopy); | |
Array.Copy(sourceArray, sourceIndex + toCopy, destinationArray, 0, length - toCopy); | |
} | |
} | |
else | |
{ | |
// The source is split into two ranges. | |
if (destinationIndex + length <= destinationArray.Length) | |
{ | |
// The destination is a continuous range. | |
// |222-----------11| => |-------11222----| | |
int toCopy = sourceArray.Length - sourceIndex; | |
Array.Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, toCopy); | |
Array.Copy(sourceArray, 0, destinationArray, destinationIndex + toCopy, length - toCopy); | |
} | |
else | |
{ | |
// The destination is split into two ranges. | |
if (sourceArray.Length - sourceIndex < destinationArray.Length - destinationIndex) | |
{ | |
// |22233---------11| => |33---------11222| | |
int toCopy1 = sourceArray.Length - sourceIndex; | |
int toCopy2 = destinationArray.Length - (destinationIndex + toCopy1); | |
Array.Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, toCopy1); | |
Array.Copy(sourceArray, 0, destinationArray, destinationIndex + toCopy1, toCopy2); | |
Array.Copy(sourceArray, 0 + toCopy2, destinationArray, 0, length - toCopy1 - toCopy2); | |
} | |
else if (sourceArray.Length - sourceIndex > destinationArray.Length - destinationIndex) | |
{ | |
// |33---------11222| => |22233---------11| | |
int toCopy1 = destinationArray.Length - destinationIndex; | |
int toCopy2 = sourceArray.Length - (sourceIndex + toCopy1); | |
Array.Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, toCopy1); | |
Array.Copy(sourceArray, sourceIndex + toCopy1, destinationArray, 0, toCopy2); | |
Array.Copy(sourceArray, 0, destinationArray, 0 + toCopy2, length - toCopy1 - toCopy2); | |
} | |
else | |
{ | |
// |222---------1111| => |222---------1111| | |
int toCopy = destinationArray.Length - destinationIndex; | |
Array.Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, toCopy); | |
Array.Copy(sourceArray, 0, destinationArray, 0, length - toCopy); | |
} | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment