// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System;
namespace SixLabors.Fonts.Tables.Cff {
///
/// A lightweight big-endian binary reader over a buffer,
/// used for reading Type 2 charstring data without allocations.
///
internal ref struct SimpleBinaryReader
{
private readonly ReadOnlySpan buffer;
///
/// Initializes a new instance of the struct.
///
/// The byte buffer to read from.
public SimpleBinaryReader(ReadOnlySpan buffer)
{
this.buffer = buffer;
this.Position = 0;
}
///
/// Gets the total length of the underlying buffer.
///
public readonly int Length => this.buffer.Length;
///
/// Gets or sets the current read position within the buffer.
///
// TODO: Bounds checks.
public int Position { get; set; }
///
/// Gets a value indicating whether there are remaining bytes to read.
///
/// if the position is within the buffer; otherwise, .
public readonly bool CanRead() => (uint)this.Position < this.buffer.Length;
///
/// Reads a single byte and advances the position.
///
/// The byte value.
public byte ReadByte() => this.buffer[this.Position++];
///
/// Reads a big-endian 16-bit signed integer and advances the position by 2 bytes.
///
/// The 16-bit signed integer value.
public int ReadInt16BE()
{
byte b1 = this.buffer[this.Position + 1];
byte b0 = this.buffer[this.Position];
this.Position += 2;
return (short)((b0 << 8) | b1);
}
///
/// Reads a big-endian 16.16 fixed-point number and advances the position by 4 bytes.
///
/// The floating-point value.
public float ReadFloatFixed1616()
{
// Read a BE int, we parse it later.
byte b3 = this.buffer[this.Position + 3];
byte b2 = this.buffer[this.Position + 2];
byte b1 = this.buffer[this.Position + 1];
byte b0 = this.buffer[this.Position];
this.Position += 4;
// This number is interpreted as a Fixed; that is, a signed number with 16 bits of fraction
float number = (short)((b0 << 8) | b1);
float fraction = (short)((b2 << 8) | b3) / 65536F;
return number + fraction;
}
}
}