toRadixString method
Return the radix encoding of the current LogicValue as a sequence
of radix characters prefixed by the length and encoding format.
Output format is: <len>'<format><encoded-value>
.
ofRadixString can parse a String produced by toRadixString and construct a LogicValue.
Here is the number 1492 printed as a radix string:
- Binary:
15'b101_1101_0100
- Quaternary:
15'q11_3110
- Octal:
15'o2724
- Decimal:
10'd1492
- Hex:
15'h05d4
Separators are output according to chunkSize
starting from the
LSB(right), default is 4 characters. The default separator is '_'.
sepChar
can be set to another character, but not in radixStringChars,
otherwise it will throw an exception.
chunkSize
= default:61'h2_9ebc_5f06_5bf7
chunkSize
= 10:61'h29e_bc5f065bf7
Leading 0s are omitted in the output string:
25'h1
When a LogicValue has 'x' or 'z' bits, then the radix characters those bits overlap will be expanded into binary form with '<' '>' bracketing them as follows:
35'h7_ZZZZ_Z<zzz0><100z>Z
Such a LogicValue cannot be converted to a Decimal (10) radix string and will throw an exception.
If the leading bits are 'z', then the output radix character is 'Z' no matter what the length. When leading, 'Z' indicates one or more 'z' bits to fill the first radix character.
9'bz_zzzz_zzzz = 9'hZZZ
Implementation
String toRadixString(
{int radix = 2, int chunkSize = 4, String sepChar = '_'}) {
if (radixStringChars.contains(sepChar)) {
throw LogicValueConversionException('separation character invalid');
}
final radixStr = switch (radix) {
2 => "'b",
4 => "'q",
8 => "'o",
10 => "'d",
16 => "'h",
_ => throw LogicValueConversionException('Unsupported radix: $radix')
};
final String reversedStr;
if (isValid) {
final radixString =
toBigInt().toUnsigned(width).toRadixString(radix).toUpperCase();
reversedStr = _reverse(radixString);
} else if (radix == 10) {
final span = (width * math.log(2) / math.log(radix)).floor();
if (toRadixString().contains(RegExp('[xX]'))) {
reversedStr = 'X' * span;
} else {
reversedStr = 'Z' * span;
}
} else {
final span = (math.log(radix) / math.log(2)).ceil();
final extendedStr =
LogicValue.of(this, width: span * (width / span).ceil());
final buf = StringBuffer();
for (var i = (extendedStr.width ~/ span) - 1; i >= 0; i--) {
final binaryChunk = extendedStr.slice((i + 1) * span - 1, i * span);
var chunkString = binaryChunk.toString(includeWidth: false);
if (i == extendedStr.width ~/ span - 1) {
final chunkWidth = chunkString.length;
chunkString = chunkString.substring(
chunkWidth - (width - i * span), chunkWidth);
}
final s = [
if (chunkString == 'z' * chunkString.length)
(span == 1 ? 'z' : 'Z')
else if (chunkString == 'x' * chunkString.length)
(span == 1 ? 'x' : 'X')
else if (chunkString.contains('z') | chunkString.contains('x'))
'>${_reverse(chunkString)}<'
else
binaryChunk.toBigInt().toUnsigned(span).toRadixString(radix)
].first;
buf.write(_reverse(s));
}
reversedStr = _reverse(buf.toString());
}
final spaceString = _reverse(reversedStr
.replaceAllMapped(
RegExp('((>(.){$chunkSize}<)|([a-zA-Z0-9])){$chunkSize}'),
(match) => '${match.group(0)}$sepChar')
.replaceAll('$sepChar<', '<'));
final fullString = spaceString[0] == sepChar
? spaceString.substring(1, spaceString.length)
: spaceString;
return '$width$radixStr$fullString';
}