Livt packages
Livt.Base
Version 1.2.1
Foundational bit, array, string, conversion, formatting, and timing helpers for Livt hardware designs.
Published files (32)
src/Format.lvt
namespace Livt.Format
/**
* Fixed-width string formatting helpers for machine values.
*
* The returned strings have compile-time-known lengths for fixed-size output
* APIs such as UART transmit helpers. Decimal output is zero-padded. Signed
* decimal output uses a leading sign.
*/
component Format
{
// Owned decimal workspace; callers serialize formatting operations.
decimalDigits: byte[10]
places: uint[10]
/**
* Initializes constant decimal places without division circuitry.
*/
new()
{
places[0] = 1000000000 as uint
places[1] = 100000000 as uint
places[2] = 10000000 as uint
places[3] = 1000000 as uint
places[4] = 100000 as uint
places[5] = 10000 as uint
places[6] = 1000 as uint
places[7] = 100 as uint
places[8] = 10 as uint
places[9] = 1 as uint
}
/**
* Extracts ten digits using at most nine scheduled subtractions per place.
* Supports the full uint domain; each request overwrites all digit storage.
*/
fn EncodeDecimal(value: uint)
{
var remaining = value
for (var index = 0; index < 10; index++) {
var place = places[index]
var digit = 0
while (remaining >= place) {
state {
remaining = remaining - place
digit++
}
}
decimalDigits[index] = (0x30 + digit) as byte
}
}
/**
* Returns the ASCII digit for value in 0..9.
* Values outside 0..9 return '?'.
*/
fn Digit(value: int) byte
{
if (value < 0) {
return 0x3F
}
if (value > 9) {
return 0x3F
}
var ascii: int = 0x30 + value
return ascii as byte
}
/**
* Returns the uppercase ASCII hex digit for value in 0..15.
* Values outside 0..15 return '?'.
*/
fn HexDigit(value: int) byte
{
if (value < 0) {
return 0x3F
}
if (value < 10) {
var digit: int = 0x30 + value
return digit as byte
}
if (value < 16) {
var letter: int = 0x41 + value - 10
return letter as byte
}
return 0x3F
}
/**
* Formats a byte as three zero-padded decimal digits.
* Examples: 0 -> "000", 7 -> "007", 42 -> "042", 255 -> "255".
*/
public fn ToStringByte(value: byte) string[3]
{
this.EncodeDecimal(value as uint)
var buf: byte[3]
for (var index = 0; index < 3; index++) {
buf[index] = decimalDigits[index + 7]
}
return buf.Decode()
}
/**
* Formats an int as a sign plus ten zero-padded decimal digits.
* Examples: 42 -> "+0000000042", -42 -> "-0000000042".
*
* Supports the full signed int domain, including its minimum value.
*/
public fn ToStringInt(value: int) string[11]
{
var magnitude = value as uint
var buf: byte[11]
buf[0] = 0x2B
if (value < 0) {
buf[0] = 0x2D
magnitude = (0 as uint) - magnitude
}
this.EncodeDecimal(magnitude)
for (var index = 0; index < 10; index++) {
buf[index + 1] = decimalDigits[index]
}
return buf.Decode()
}
/**
* Formats a uint as ten zero-padded decimal digits.
* Examples: 42 -> "0000000042", 255 -> "0000000255".
*/
public fn ToStringUInt(value: uint) string[10]
{
this.EncodeDecimal(value)
var buf: byte[10]
for (var index = 0; index < 10; index++) {
buf[index] = decimalDigits[index]
}
return buf.Decode()
}
/**
* Formats a byte as two uppercase hexadecimal digits.
* Example: 0xAF -> "AF".
*/
public fn ToHexByte(value: byte) string[2]
{
var n: int = value as int
var hi: int = (n >> 4) & 15
var lo: int = n & 15
var buf: byte[2]
buf[0] = this.HexDigit(hi)
buf[1] = this.HexDigit(lo)
return buf.Decode()
}
/**
* Formats a byte as eight binary digits.
* Example: 0x05 -> "00000101".
*/
public fn ToBinaryByte(value: byte) string[8]
{
var n: int = value as int
var buf: byte[8]
buf[0] = this.Digit((n >> 7) & 1)
buf[1] = this.Digit((n >> 6) & 1)
buf[2] = this.Digit((n >> 5) & 1)
buf[3] = this.Digit((n >> 4) & 1)
buf[4] = this.Digit((n >> 3) & 1)
buf[5] = this.Digit((n >> 2) & 1)
buf[6] = this.Digit((n >> 1) & 1)
buf[7] = this.Digit(n & 1)
return buf.Decode()
}
}