mirror of
https://github.com/claunia/plist-cil.git
synced 2025-12-16 19:14:26 +00:00
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,7 +318,7 @@ namespace Claunia.PropertyList
|
||||
{
|
||||
//UID (v1.0 and later)
|
||||
int length = objInfo + 1;
|
||||
return new UID(obj.ToString(), CopyOfRange(bytes, offset + 1, offset + 1 + length));
|
||||
return new UID(bytes.Slice(offset + 1, length));
|
||||
}
|
||||
case 0xA:
|
||||
{
|
||||
|
||||
@@ -391,6 +391,16 @@ namespace Claunia.PropertyList
|
||||
count += bytes.Length;
|
||||
}
|
||||
|
||||
internal void Write(Span<byte> bytes)
|
||||
{
|
||||
#if SPAN_NATIVE
|
||||
outStream.Write(bytes);
|
||||
count += bytes.Length;
|
||||
#else
|
||||
this.Write(bytes.ToArray());
|
||||
#endif
|
||||
}
|
||||
|
||||
internal void WriteBytes(long value, int bytes)
|
||||
{
|
||||
// write low-order bytes big-endian style
|
||||
|
||||
248
plist-cil/UID.cs
248
plist-cil/UID.cs
@@ -23,7 +23,7 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Buffers.Binary;
|
||||
using System.Text;
|
||||
|
||||
namespace Claunia.PropertyList
|
||||
@@ -35,20 +35,30 @@ namespace Claunia.PropertyList
|
||||
/// @author Natalia Portillo
|
||||
public class UID : NSObject
|
||||
{
|
||||
readonly byte[] bytes;
|
||||
readonly string name;
|
||||
readonly ulong value;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Claunia.PropertyList.UID"/> class.
|
||||
/// </summary>
|
||||
/// <param name="name">Name.</param>
|
||||
/// <param name="bytes">Bytes.</param>
|
||||
public UID(String name, byte[] bytes)
|
||||
[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)
|
||||
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.bytes = bytes;
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -56,10 +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.bytes = new[] { number };
|
||||
this.value = number;
|
||||
}
|
||||
|
||||
/// <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>
|
||||
@@ -67,10 +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.bytes = new[] { (byte)number };
|
||||
this.value = (ulong)number;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -78,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;
|
||||
if(number <= byte.MaxValue)
|
||||
this.bytes = new[] { (byte)number };
|
||||
else
|
||||
{
|
||||
this.bytes = BitConverter.GetBytes(number);
|
||||
Array.Reverse(this.bytes);
|
||||
}
|
||||
this.value = number;
|
||||
}
|
||||
|
||||
/// <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>
|
||||
@@ -95,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;
|
||||
if(number >= sbyte.MinValue && number <= sbyte.MaxValue)
|
||||
this.bytes = new[] { (byte)number };
|
||||
else
|
||||
{
|
||||
this.bytes = BitConverter.GetBytes(number);
|
||||
Array.Reverse(this.bytes);
|
||||
}
|
||||
this.value = (ulong)number;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -112,21 +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;
|
||||
if(number <= byte.MaxValue)
|
||||
this.bytes = new[] { (byte)number };
|
||||
else if(number <= ushort.MaxValue)
|
||||
{
|
||||
this.bytes = BitConverter.GetBytes((ushort)number);
|
||||
Array.Reverse(this.bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.bytes = BitConverter.GetBytes(number);
|
||||
Array.Reverse(this.bytes);
|
||||
}
|
||||
this.value = number;
|
||||
}
|
||||
|
||||
/// <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.value = number;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -134,21 +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;
|
||||
if(number >= sbyte.MinValue && number <= sbyte.MaxValue)
|
||||
this.bytes = new[] { (byte)number };
|
||||
if(number >= short.MinValue && number <= short.MaxValue)
|
||||
{
|
||||
this.bytes = BitConverter.GetBytes((short)number);
|
||||
Array.Reverse(this.bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.bytes = BitConverter.GetBytes(number);
|
||||
Array.Reverse(this.bytes);
|
||||
}
|
||||
this.value = (ulong)number;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -156,26 +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;
|
||||
if(number <= byte.MaxValue)
|
||||
this.bytes = new[] { (byte)number };
|
||||
else if(number <= ushort.MaxValue)
|
||||
{
|
||||
this.bytes = BitConverter.GetBytes((ushort)number);
|
||||
Array.Reverse(this.bytes);
|
||||
}
|
||||
else if(number <= uint.MaxValue)
|
||||
{
|
||||
this.bytes = BitConverter.GetBytes((uint)number);
|
||||
Array.Reverse(this.bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.bytes = BitConverter.GetBytes(number);
|
||||
Array.Reverse(this.bytes);
|
||||
}
|
||||
this.value = number;
|
||||
}
|
||||
|
||||
/// <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.value = number;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -183,26 +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;
|
||||
if(number >= sbyte.MinValue && number <= sbyte.MaxValue)
|
||||
this.bytes = new[] { (byte)number };
|
||||
if(number >= short.MinValue && number <= short.MaxValue)
|
||||
{
|
||||
this.bytes = BitConverter.GetBytes((short)number);
|
||||
Array.Reverse(this.bytes);
|
||||
}
|
||||
if(number >= int.MinValue && number <= int.MaxValue)
|
||||
{
|
||||
this.bytes = BitConverter.GetBytes((int)number);
|
||||
Array.Reverse(this.bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.bytes = BitConverter.GetBytes(number);
|
||||
Array.Reverse(this.bytes);
|
||||
}
|
||||
this.value = (ulong)number;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -213,19 +194,79 @@ namespace Claunia.PropertyList
|
||||
{
|
||||
get
|
||||
{
|
||||
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.ByteCount)
|
||||
{
|
||||
case 1:
|
||||
bytes[0] = (byte)this.value;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
BinaryPrimitives.WriteUInt16BigEndian(bytes, (ushort)this.value);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
BinaryPrimitives.WriteUInt32BigEndian(bytes, (uint)this.value);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
BinaryPrimitives.WriteUInt64BigEndian(bytes, this.value);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
[Obsolete("UIDs have no meaningful names")]
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return name;
|
||||
return this.value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,6 +280,8 @@ namespace Claunia.PropertyList
|
||||
{
|
||||
Indent(xml, level);
|
||||
xml.Append("<string>");
|
||||
Span<byte> bytes = stackalloc byte[this.ByteCount];
|
||||
this.GetBytes(bytes);
|
||||
foreach (byte b in bytes)
|
||||
xml.Append(String.Format("{0:x2}", b));
|
||||
xml.Append("</string>");
|
||||
@@ -246,7 +289,9 @@ namespace Claunia.PropertyList
|
||||
|
||||
internal override void ToBinary(BinaryPropertyListWriter outPlist)
|
||||
{
|
||||
outPlist.Write(0x80 + bytes.Length - 1);
|
||||
outPlist.Write(0x80 + this.ByteCount - 1);
|
||||
Span<byte> bytes = stackalloc byte[this.ByteCount];
|
||||
this.GetBytes(bytes);
|
||||
outPlist.Write(bytes);
|
||||
}
|
||||
|
||||
@@ -254,6 +299,8 @@ namespace Claunia.PropertyList
|
||||
{
|
||||
Indent(ascii, level);
|
||||
ascii.Append("\"");
|
||||
Span<byte> bytes = stackalloc byte[this.ByteCount];
|
||||
this.GetBytes(bytes);
|
||||
foreach (byte b in bytes)
|
||||
ascii.Append(String.Format("{0:x2}", b));
|
||||
ascii.Append("\"");
|
||||
@@ -272,13 +319,24 @@ namespace Claunia.PropertyList
|
||||
/// <see cref="Claunia.PropertyList.UID"/>; otherwise, <c>false</c>.</returns>
|
||||
public override bool Equals(NSObject obj)
|
||||
{
|
||||
if (!(obj is UID))
|
||||
return Equals((object)obj);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var uid = obj as UID;
|
||||
|
||||
if (uid == null)
|
||||
return false;
|
||||
|
||||
if (((UID)obj).Name != name)
|
||||
return false;
|
||||
return uid.value == value;
|
||||
}
|
||||
|
||||
return ArrayEquals(((UID)obj).Bytes, bytes);
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.value.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
<AssemblyOriginatorKeyFile>plist-cil.snk</AssemblyOriginatorKeyFile>
|
||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(OS)' == 'Windows_NT'">
|
||||
|
||||
Reference in New Issue
Block a user