Skip to content

Commit

Permalink
Added a new Pointer class to help manage pointers in C ports. Updated…
Browse files Browse the repository at this point in the history
… LibOgg to use this new pointer class.
  • Loading branch information
neumatho committed Sep 24, 2024
1 parent 71bd761 commit fd53ef2
Show file tree
Hide file tree
Showing 17 changed files with 626 additions and 294 deletions.
164 changes: 164 additions & 0 deletions Source/NostalgicPlayerKit/Utility/CMemory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
/******************************************************************************/
/* This source, or parts thereof, may be used in any software as long the */
/* license of NostalgicPlayer is keep. See the LICENSE file for more */
/* information. */
/******************************************************************************/
using System;
using System.Runtime.CompilerServices;
using System.Text;

namespace Polycode.NostalgicPlayer.Kit.Utility
{
/// <summary>
/// C like memory methods
/// </summary>
public static class CMemory
{
/********************************************************************/
/// <summary>
///
/// </summary>
/********************************************************************/
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Pointer<T> MAlloc<T>(int size)
{
return new Pointer<T>(new T[size]);
}



/********************************************************************/
/// <summary>
///
/// </summary>
/********************************************************************/
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Pointer<T> Realloc<T>(Pointer<T> ptr, int newSize)
{
T[] newArray = new T[newSize];
Array.Copy(ptr.Buffer, ptr.Offset, newArray, 0, Math.Min(newSize, ptr.Buffer.Length - ptr.Offset));

return new Pointer<T>(newArray);
}



/********************************************************************/
/// <summary>
///
/// </summary>
/********************************************************************/
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Free<T>(Pointer<T> ptr)
{
}



/********************************************************************/
/// <summary>
///
/// </summary>
/********************************************************************/
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void MemMove<T>(Pointer<T> dest, Pointer<T> source, int length)
{
Array.Copy(source.Buffer, source.Offset, dest.Buffer, dest.Offset, length);
}



/********************************************************************/
/// <summary>
///
/// </summary>
/********************************************************************/
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void MemCpy<T>(Pointer<T> dest, Pointer<T> source, int length)
{
Array.Copy(source.Buffer, source.Offset, dest.Buffer, dest.Offset, length);
}



/********************************************************************/
/// <summary>
///
/// </summary>
/********************************************************************/
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void MemCpy<T>(T[] dest, string str, int length)
{
Array.Copy(Encoding.ASCII.GetBytes(str), dest, length);
}



/********************************************************************/
/// <summary>
///
/// </summary>
/********************************************************************/
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int MemCmp(Pointer<byte> ptr1, Pointer<byte> ptr2, int length)
{
for (int i = 0; i < length; i++)
{
if (ptr1[i] < ptr2[i])
return -1;

if (ptr1[i] > ptr2[i])
return 1;
}

return 0;
}



/********************************************************************/
/// <summary>
///
/// </summary>
/********************************************************************/
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int MemCmp(Pointer<byte> ptr1, string compareString, int length)
{
return MemCmp(ptr1, new Pointer<byte>(Encoding.ASCII.GetBytes(compareString)), length);
}



/********************************************************************/
/// <summary>
///
/// </summary>
/********************************************************************/
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void MemSet<T>(Pointer<T> ptr, T value, int length)
{
ptr.Buffer.AsSpan(ptr.Offset, length).Fill(value);
}



/********************************************************************/
/// <summary>
///
/// </summary>
/********************************************************************/
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Pointer<T> MemChr<T>(Pointer<T> ptr, T ch, int count)
{
int searchLength = Math.Min(count, ptr.Buffer.Length - ptr.Offset);

for (int i = 0; i < searchLength; i++)
{
if (ptr[i].Equals(ch))
return new Pointer<T>(ptr.Buffer, ptr.Offset + i);
}

return new Pointer<T>();
}
}
}
149 changes: 149 additions & 0 deletions Source/NostalgicPlayerKit/Utility/Pointer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/******************************************************************************/
/* This source, or parts thereof, may be used in any software as long the */
/* license of NostalgicPlayer is keep. See the LICENSE file for more */
/* information. */
/******************************************************************************/
using System;

namespace Polycode.NostalgicPlayer.Kit.Utility
{
/// <summary>
/// This holds a buffer and a start offset. Can be used in C ports, where
/// there are a lot of pointer calculations. By using this, you don't need
/// to hold the offset by yourself and pass it around.
///
/// It is almost similar to Span, except that with this, you can also use
/// negative indexes to retrieve the data, which is used by some C programs
/// </summary>
public struct Pointer<T> : IEquatable<Pointer<T>>
{
/********************************************************************/
/// <summary>
/// Constructor
/// </summary>
/********************************************************************/
public Pointer(T[] buffer) : this(buffer, 0)
{
}



/********************************************************************/
/// <summary>
/// Constructor
/// </summary>
/********************************************************************/
public Pointer(T[] buffer, int offset)
{
Buffer = buffer;
Offset = offset;
}



/********************************************************************/
/// <summary>
/// Return the whole buffer
/// </summary>
/********************************************************************/
public T[] Buffer { get; private set; }



/********************************************************************/
/// <summary>
/// Return the offset in the buffer where the first item starts
/// </summary>
/********************************************************************/
public int Offset { get; private set; }



/********************************************************************/
/// <summary>
/// Clear the pointer
/// </summary>
/********************************************************************/
public void SetToNull()
{
Buffer = null;
Offset = 0;
}



/********************************************************************/
/// <summary>
/// Check to see if the pointer is null
/// </summary>
/********************************************************************/
public bool IsNull => Buffer == null;



/********************************************************************/
/// <summary>
/// Return or set the item at the index given
/// </summary>
/********************************************************************/
public T this[int index]
{
get => Buffer[Offset + index];
set => Buffer[Offset + index] = value;
}



/********************************************************************/
/// <summary>
/// Return a new pointer where the original pointer is incremented by
/// the value given
/// </summary>
/********************************************************************/
public static Pointer<T> operator + (Pointer<T> ptr, int increment)
{
return new Pointer<T>(ptr.Buffer, ptr.Offset + increment);
}



/********************************************************************/
/// <summary>
/// Return the current pointer with the current offset, but the
/// offset will be incremented by one afterwards
/// </summary>
/********************************************************************/
public static Pointer<T> operator ++ (Pointer<T> ptr)
{
return ptr + 1;
}



/********************************************************************/
/// <summary>
/// Will calculate the difference between the two pointers. Both
/// pointers need to use the same buffer
/// </summary>
/********************************************************************/
public static int operator - (Pointer<T> ptr1, Pointer<T> ptr2)
{
if (ptr1.Buffer != ptr2.Buffer)
throw new ArgumentException("Both pointers need to use the same buffer");

return ptr1.Offset - ptr2.Offset;
}

#region IEquatable implementation
/********************************************************************/
/// <summary>
/// Compare two pointers
/// </summary>
/********************************************************************/
public bool Equals(Pointer<T> other)
{
return (Buffer == other.Buffer) && (Offset == other.Offset);
}
#endregion
}
}
10 changes: 6 additions & 4 deletions Source/Ports/LibOgg/Containers/OggPack_Buffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
/* license of NostalgicPlayer is keep. See the LICENSE file for more */
/* information. */
/******************************************************************************/
using Polycode.NostalgicPlayer.Kit.Utility;

namespace Polycode.NostalgicPlayer.Ports.LibOgg.Containers
{
/// <summary>
Expand All @@ -16,9 +18,9 @@ internal class OggPack_Buffer
public c_int EndBit;

/// <summary></summary>
public byte[] Buffer;
public Pointer<byte> Buffer;
/// <summary></summary>
public int Ptr;
public Pointer<byte> Ptr;
/// <summary></summary>
public c_long Storage;

Expand All @@ -32,8 +34,8 @@ public void Clear()
EndByte = 0;
EndBit = 0;

Buffer = null;
Ptr = 0;
Buffer.SetToNull();
Ptr.SetToNull();
Storage = 0;
}
}
Expand Down
6 changes: 3 additions & 3 deletions Source/Ports/LibOgg/Containers/Ogg_IoVec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
/* license of NostalgicPlayer is keep. See the LICENSE file for more */
/* information. */
/******************************************************************************/
using Polycode.NostalgicPlayer.Kit.Utility;

namespace Polycode.NostalgicPlayer.Ports.LibOgg.Containers
{
/// <summary>
Expand All @@ -11,9 +13,7 @@ namespace Polycode.NostalgicPlayer.Ports.LibOgg.Containers
public class Ogg_IoVec
{
/// <summary></summary>
public byte[] Base;
/// <summary></summary>
public int Offset;
public Pointer<byte> Base;
/// <summary></summary>
public size_t Len;
}
Expand Down
6 changes: 3 additions & 3 deletions Source/Ports/LibOgg/Containers/Ogg_Packet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
/* license of NostalgicPlayer is keep. See the LICENSE file for more */
/* information. */
/******************************************************************************/
using Polycode.NostalgicPlayer.Kit.Utility;

namespace Polycode.NostalgicPlayer.Ports.LibOgg.Containers
{
/// <summary>
Expand All @@ -12,9 +14,7 @@ namespace Polycode.NostalgicPlayer.Ports.LibOgg.Containers
public class Ogg_Packet
{
/// <summary></summary>
public byte[] Packet;
/// <summary></summary>
public int Offset;
public Pointer<byte> Packet;
/// <summary></summary>
public c_long Bytes;
/// <summary></summary>
Expand Down
Loading

0 comments on commit fd53ef2

Please sign in to comment.