Refactur UIDs

This commit is contained in:
Frederik Carlier
2018-06-19 22:54:05 +02:00
parent 22fbc6afa5
commit 2b4fe6595e
3 changed files with 115 additions and 118 deletions

View File

@@ -9,65 +9,57 @@ namespace plistcil.test
[Fact]
public void ByteUidTest()
{
var uid = new UID("byte", (byte)0xAB);
var uid = new UID((byte)0xAB);
Assert.Equal(new byte[] { 0xAB }, uid.Bytes);
Assert.Equal("byte", uid.Name);
}
[Fact]
public void SByteUidTest()
{
var uid = new UID("sbyte", unchecked((sbyte)0xAB));
Assert.Equal(new byte[] { 0xAB }, uid.Bytes);
Assert.Equal("sbyte", uid.Name);
var uid = new UID("test", unchecked((sbyte)0x0F));
Assert.Equal(new byte[] { 0x0F }, uid.Bytes);
}
[Fact]
public void ShortUidTest()
{
var uid = new UID("short", unchecked((short)0xABCD));
Assert.Equal(new byte[] { 0xAB, 0xCD }, uid.Bytes);
Assert.Equal("short", uid.Name);
var uid = new UID("test", unchecked((short)0x0F0F));
Assert.Equal(new byte[] { 0x0F, 0x0F }, uid.Bytes);
}
[Fact]
public void UShortUidTest()
{
var uid = new UID("ushort", 0xABCDu);
var uid = new UID(0xABCDu);
Assert.Equal(new byte[] { 0xAB, 0xCD }, uid.Bytes);
Assert.Equal("ushort", uid.Name);
}
[Fact]
public void UIntUidTest()
{
var uid = new UID("uint", 0xABCDEF00u);
var uid = new UID(0xABCDEF00u);
Assert.Equal(new byte[] { 0xAB, 0xCD, 0xEF, 0x00 }, uid.Bytes);
Assert.Equal("uint", uid.Name);
}
[Fact]
public void IntUidTest()
{
var uid = new UID("int", 0xABCDEF00);
var uid = new UID(0xABCDEF00);
Assert.Equal(new byte[] { 0xAB, 0xCD, 0xEF, 0x00 }, uid.Bytes);
Assert.Equal("int", uid.Name);
}
[Fact]
public void ULongUidTest()
{
var uid = new UID("ulong", 0xABCDEF0000EFCDABu);
var uid = new UID(0xABCDEF0000EFCDABu);
Assert.Equal(new byte[] { 0xAB, 0xCD, 0xEF, 0x00, 0x00, 0xEF, 0xCD, 0xAB }, uid.Bytes);
Assert.Equal("ulong", uid.Name);
}
[Fact]
public void LongUidTest()
{
var uid = new UID("int", 0xABCDEF0000EFCDAB);
var uid = new UID(0xABCDEF0000EFCDAB);
Assert.Equal(new byte[] { 0xAB, 0xCD, 0xEF, 0x00, 0x00, 0xEF, 0xCD, 0xAB }, uid.Bytes);
Assert.Equal("int", uid.Name);
}
[Theory]
@@ -75,24 +67,16 @@ namespace plistcil.test
[InlineData(new byte[] { 0xAB, 0xCD })]
[InlineData(new byte[] { 0xAB, 0xCD, 0xEF, 0xFE })]
[InlineData(new byte[] { 0xAB, 0xCD, 0xEF, 0xFE, 0xFE, 0xEF, 0xCD, 0xAB })]
[InlineData(new byte[] { 0x00 })]
[InlineData(new byte[] { 0x00, 0x00 })]
[InlineData(new byte[] { 0x00, 0xCD })]
[InlineData(new byte[] { 0x00, 0x00, 0x00, 0x00 })]
[InlineData(new byte[] { 0x00, 0x00, 0x00, 0xCD })]
[InlineData(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 })]
[InlineData(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCD })]
public void UidFromArrayTest(byte[] array)
{
var uid = new UID("array", array);
var uid = new UID(array);
Assert.Equal(array, uid.Bytes);
Assert.Equal("array", uid.Name);
}
[Fact]
public void BinaryRoundTripTest()
{
var original = new UID("0", 0xabcd);
var original = new UID(0xabcd);
using (MemoryStream stream = new MemoryStream())
{
@@ -106,14 +90,14 @@ namespace plistcil.test
[Fact]
public void XmlRoundTripTest()
{
var original = new UID("0", 0xabcd);
var original = new UID(0xabcd);
var plist = original.ToXmlPropertyList();
// UIDs don't exist in XML property lists, but they are represented as strings
// for compability purposes
var roundtrip = XmlPropertyListParser.ParseString(plist) as NSString;
Assert.Equal("0000abcd", roundtrip.ToObject());
Assert.Equal("abcd", roundtrip.ToObject());
}
}
}

View File

@@ -316,7 +316,7 @@ namespace Claunia.PropertyList
{
//UID (v1.0 and later)
int length = objInfo + 1;
return new UID(obj.ToString(), bytes.Slice(offset + 1, length));
return new UID(bytes.Slice(offset + 1, length));
}
case 0xA:
{

View File

@@ -36,20 +36,28 @@ namespace Claunia.PropertyList
public class UID : NSObject
{
readonly ulong value;
readonly byte length;
readonly string name;
/// <summary>
/// Initializes a new instance of the <see cref="Claunia.PropertyList.UID"/> class.
/// </summary>
/// <param name="name">Name.</param>
/// <param name="bytes">Bytes.</param>
[Obsolete("UIDs have not meaningful names")]
public UID(String name, ReadOnlySpan<byte> bytes)
{
if (bytes.Length != 1 && bytes.Length != 2 && bytes.Length != 4 && bytes.Length != 8)
throw new ArgumentException("Type argument is not valid.");
this.name = name;
this.length = (byte)bytes.Length;
this.value = (ulong)BinaryPropertyListParser.ParseLong(bytes);
}
/// <summary>
/// Initializes a new instance of the <see cref="Claunia.PropertyList.UID"/> class.
/// </summary>
/// <param name="bytes">Bytes.</param>
public UID(ReadOnlySpan<byte> bytes)
{
if (bytes.Length != 1 && bytes.Length != 2 && bytes.Length != 4 && bytes.Length != 8)
throw new ArgumentException("Type argument is not valid.");
this.value = (ulong)BinaryPropertyListParser.ParseLong(bytes);
}
@@ -58,11 +66,19 @@ namespace Claunia.PropertyList
/// </summary>
/// <param name="name">Name.</param>
/// <param name="number">Unsigned 8-bit number.</param>
[Obsolete("UIDs have no meaningful names")]
public UID(String name, byte number)
{
this.name = name;
this.value = number;
this.length = 1;
}
/// <summary>
/// Initializes a new instance of the <see cref="Claunia.PropertyList.UID"/> class using an unsigned 8-bit number.
/// </summary>
/// <param name="number">Unsigned 8-bit number.</param>
public UID(byte number)
{
this.value = number;
}
/// <summary>
@@ -70,11 +86,10 @@ namespace Claunia.PropertyList
/// </summary>
/// <param name="name">Name.</param>
/// <param name="number">Unsigned 8-bit number.</param>
[Obsolete("UIDs must be unsigned values")]
public UID(String name, sbyte number)
{
this.name = name;
this.value = (ulong)number;
this.length = 1;
}
/// <summary>
@@ -82,16 +97,20 @@ namespace Claunia.PropertyList
/// </summary>
/// <param name="name">Name.</param>
/// <param name="number">Unsigned 16-bit number.</param>
[Obsolete("UIDs have no meaningful names")]
public UID(String name, ushort number)
{
this.name = name;
this.value = number;
if (number <= byte.MaxValue)
this.length = 1;
else
{
this.length = 2;
}
/// <summary>
/// Initializes a new instance of the <see cref="Claunia.PropertyList.UID"/> class using an unsigned 16-bit number.
/// </summary>
/// <param name="name">Name.</param>
/// <param name="number">Unsigned 16-bit number.</param>
public UID(ushort number)
{
this.value = number;
}
/// <summary>
@@ -99,16 +118,10 @@ namespace Claunia.PropertyList
/// </summary>
/// <param name="name">Name.</param>
/// <param name="number">Signed 16-bit number.</param>
[Obsolete("UIDs must be unsigned values")]
public UID(String name, short number)
{
this.name = name;
this.value = (ulong)number;
if (number >= sbyte.MinValue && number <= sbyte.MaxValue)
this.length = 1;
else
{
this.length = 2;
}
}
/// <summary>
@@ -116,20 +129,19 @@ namespace Claunia.PropertyList
/// </summary>
/// <param name="name">Name.</param>
/// <param name="number">Unsigned 32-bit number.</param>
[Obsolete("UIDs have no meaningful names")]
public UID(String name, uint number)
{
this.name = name;
this.value = number;
if (number <= byte.MaxValue)
this.length = 1;
else if (number <= ushort.MaxValue)
{
this.length = 2;
}
else
/// <summary>
/// Initializes a new instance of the <see cref="Claunia.PropertyList.UID"/> class using an unsigned 32-bit number.
/// </summary>
/// <param name="number">Unsigned 32-bit number.</param>
public UID(uint number)
{
this.length = 4;
}
this.value = number;
}
/// <summary>
@@ -137,20 +149,10 @@ namespace Claunia.PropertyList
/// </summary>
/// <param name="name">Name.</param>
/// <param name="number">Signed 32-bit number.</param>
[Obsolete("UIDs must be unsigned values")]
public UID(String name, int number)
{
this.name = name;
this.value = (ulong)number;
if (number >= sbyte.MinValue && number <= sbyte.MaxValue)
this.length = 1;
if (number >= short.MinValue && number <= short.MaxValue)
{
this.length = 2;
}
else
{
this.length = 4;
}
}
/// <summary>
@@ -158,24 +160,19 @@ namespace Claunia.PropertyList
/// </summary>
/// <param name="name">Name.</param>
/// <param name="number">Unsigned 64-bit number.</param>
[Obsolete("UIDs have no meaningful names")]
public UID(String name, ulong number)
{
this.name = name;
this.value = number;
if (number <= byte.MaxValue)
this.length = 1;
else if (number <= ushort.MaxValue)
{
this.length = 2;
}
else if (number <= uint.MaxValue)
/// <summary>
/// Initializes a new instance of the <see cref="Claunia.PropertyList.UID"/> class using an unsigned 64-bit number.
/// </summary>
/// <param name="number">Unsigned 64-bit number.</param>
public UID(ulong number)
{
this.length = 4;
}
else
{
this.length = 8;
}
this.value = number;
}
/// <summary>
@@ -183,24 +180,10 @@ namespace Claunia.PropertyList
/// </summary>
/// <param name="name">Name.</param>
/// <param name="number">Signed 64-bit number.</param>
[Obsolete("UIDs must be unsigned values")]
public UID(String name, long number)
{
this.name = name;
this.value = (ulong)number;
if (number >= sbyte.MinValue && number <= sbyte.MaxValue)
this.length = 1;
if (number >= short.MinValue && number <= short.MaxValue)
{
this.length = 2;
}
if (number >= int.MinValue && number <= int.MaxValue)
{
this.length = 4;
}
else
{
this.length = 8;
}
}
/// <summary>
@@ -211,15 +194,47 @@ namespace Claunia.PropertyList
{
get
{
byte[] bytes = new byte[this.length];
byte[] bytes = new byte[this.ByteCount];
this.GetBytes(bytes);
return bytes;
}
}
/// <summary>
/// Gets the number of bytes required to represent this <see cref="UID"/>.
/// </summary>
public int ByteCount
{
get
{
if (this.value <= byte.MaxValue)
{
return 1;
}
else if (this.value <= ushort.MaxValue)
{
return 2;
}
else if (this.value <= uint.MaxValue)
{
return 4;
}
else
{
return 8;
}
}
}
/// <summary>
/// Writes the bytes required to represent this <see cref="UID"/> to a byte span.
/// </summary>
/// <param name="bytes">
/// The byte span to which to write the byte representation of this UID.
/// </param>
public void GetBytes(Span<byte> bytes)
{
switch (this.length)
switch (this.ByteCount)
{
case 1:
bytes[0] = (byte)this.value;
@@ -246,11 +261,12 @@ namespace Claunia.PropertyList
/// Gets the name.
/// </summary>
/// <value>The name.</value>
[Obsolete("UIDs have no meaningful names")]
public string Name
{
get
{
return name;
return this.value.ToString();
}
}
@@ -264,7 +280,7 @@ namespace Claunia.PropertyList
{
Indent(xml, level);
xml.Append("<string>");
Span<byte> bytes = stackalloc byte[this.length];
Span<byte> bytes = stackalloc byte[this.ByteCount];
this.GetBytes(bytes);
foreach (byte b in bytes)
xml.Append(String.Format("{0:x2}", b));
@@ -273,8 +289,8 @@ namespace Claunia.PropertyList
internal override void ToBinary(BinaryPropertyListWriter outPlist)
{
outPlist.Write(0x80 + this.length - 1);
Span<byte> bytes = stackalloc byte[this.length];
outPlist.Write(0x80 + this.ByteCount - 1);
Span<byte> bytes = stackalloc byte[this.ByteCount];
this.GetBytes(bytes);
outPlist.Write(bytes);
}
@@ -283,7 +299,7 @@ namespace Claunia.PropertyList
{
Indent(ascii, level);
ascii.Append("\"");
Span<byte> bytes = stackalloc byte[this.length];
Span<byte> bytes = stackalloc byte[this.ByteCount];
this.GetBytes(bytes);
foreach (byte b in bytes)
ascii.Append(String.Format("{0:x2}", b));
@@ -314,17 +330,14 @@ namespace Claunia.PropertyList
if (uid == null)
return false;
return uid.name == name
&& uid.length == length
&& uid.value == value;
return uid.value == value;
}
#if HAS_HASHCODE
/// <inheritdoc/>
public override int GetHashCode()
{
return HashCode.Combine(this.name, this.length, this.value);
return this.value.GetHashCode();
}
#endif
}
}