using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace System.Unicode.Builder
{
internal static class BinaryWriterExtensions
{
public static void WriteUInt24(this BinaryWriter writer, int value)
{
if (value < 0 || value > 0xFFFFFF) throw new ArgumentOutOfRangeException(nameof(value));
writer.Write((byte)(value));
writer.Write((byte)(value >> 8));
writer.Write((byte)(value >> 16));
}
/// Writes code point in a custom, but compact encoding.
///
/// Unlike UTF-8, this encoding will consume at most 3 bytes.
/// It could ideally store values between 0x0 and 0x40409F, but this range is useless at the moment.
///
/// The binary writer to use.
/// The value to write
public static void WriteCodePoint(this BinaryWriter writer, int value)
{
if (value < 0 || value > 0x40407F) throw new ArgumentOutOfRangeException(nameof(value));
if (value < 0xA0) writer.Write((byte)value);
else if (value < 0x20A0)
{
value -= 0xA0;
writer.Write((byte)((byte)(value >> 8) | 0xA0));
writer.Write((byte)value);
}
else if (value < 0x40A0)
{
value -= 0x20A0;
writer.Write((byte)((byte)(value >> 8) | 0xC0));
writer.Write((byte)value);
}
else
{
value -= 0x40A0;
writer.Write((byte)((byte)(value >> 16) | 0xE0));
writer.Write((byte)(value >> 8));
writer.Write((byte)value);
}
}
/// Writes a character name alias.
/// We assume that character names will not exceed 64 bytes in length.
/// The writer to use.
/// The name alias value to write.
public static void WriteNameAliasToFile(this BinaryWriter writer, UnicodeNameAlias nameAlias)
{
// This method will stuff two extra bits together with the byte count, provided that this one doesn't exceed 64.
var bytes = Encoding.UTF8.GetBytes(nameAlias.Name);
if (bytes.Length > 64) throw new InvalidOperationException("Did not expect UTF-8 encoded name aliases to be longer than 64 bytes.");
writer.WritePackedLength((byte)(nameAlias.Kind - 1), nameAlias.Name.Length);
writer.Write(bytes);
}
/// Writes a character name, packing two information bits along with the length.
/// We assume that character names will not exceed 128 bytes in length.
/// The writer to use.
/// The name to write.
public static void WriteNamePropertyToFile(this BinaryWriter writer, string name)
{
var bytes = Encoding.UTF8.GetBytes(name);
if (bytes.Length > 128) throw new InvalidOperationException("Did not expect UTF-8 encoded name to be longer than 128 bytes.");
writer.Write((byte)(name.Length - 1)); // The most significant bit will always be cleared, because it will be used for other cases.
writer.Write(bytes);
}
/// Writes a 6 bits length packed with two extra bits.
/// The parameters have a restricted range, which must be respected.
/// The writer used to perform the operation.
/// The value of the two extra bits.
/// The length to write.
public static void WritePackedLength(this BinaryWriter writer, byte extraBits, int length)
{
if (extraBits > 3) throw new ArgumentOutOfRangeException(nameof(extraBits));
if (length < 1 || length > 64) throw new ArgumentOutOfRangeException(nameof(length));
writer.Write((byte)((extraBits << 6) | (length - 1)));
}
}
}