64 lines
1.3 KiB
Go
64 lines
1.3 KiB
Go
package tape
|
|
|
|
import "fmt"
|
|
|
|
type Tag byte; const (
|
|
SI Tag = 0 << 5 // Small integer
|
|
LI Tag = 1 << 5 // Large integer
|
|
FP Tag = 2 << 5 // Floating point
|
|
SBA Tag = 3 << 5 // Small byte array
|
|
LBA Tag = 4 << 5 // Large byte array
|
|
OTA Tag = 5 << 5 // One-tag array
|
|
KTV Tag = 6 << 5 // Key-tag-value table
|
|
TNMask Tag = 0xE0 // The entire TN bitfield
|
|
CNMask Tag = 0x1F // The entire CN bitfield
|
|
CNLimit Tag = 32 // All valid CNs are < CNLimit
|
|
)
|
|
|
|
func (tag Tag) TN() int {
|
|
return int(tag >> 5)
|
|
}
|
|
|
|
func (tag Tag) CN() int {
|
|
return int(tag & CNMask)
|
|
}
|
|
|
|
func (tag Tag) WithCN(cn int) Tag {
|
|
return (tag & TNMask) | Tag(cn % 32)
|
|
}
|
|
|
|
func (tag Tag) WithoutCN() Tag {
|
|
return tag.WithCN(0)
|
|
}
|
|
|
|
func (tag Tag) Is(other Tag) bool {
|
|
return tag.TN() == other.TN()
|
|
}
|
|
|
|
func (tag Tag) String() string {
|
|
tn := fmt.Sprint(tag.TN())
|
|
switch tag.WithoutCN() {
|
|
case SI: tn = "SI"
|
|
case LI: tn = "LI"
|
|
case FP: tn = "FP"
|
|
case SBA: tn = "SBA"
|
|
case LBA: tn = "LBA"
|
|
case OTA: tn = "OTA"
|
|
case KTV: tn = "KTV"
|
|
}
|
|
return fmt.Sprintf("%s:%d", tn, tag.CN())
|
|
}
|
|
|
|
// BufferTag returns the appropriate tag for a buffer.
|
|
func BufferTag(value []byte) Tag {
|
|
return bufferLenTag(len(value))
|
|
}
|
|
|
|
func bufferLenTag(length int) Tag {
|
|
if length < int(CNLimit) {
|
|
return SBA.WithCN(length)
|
|
} else {
|
|
return LBA.WithCN(IntBytes(uint64(length)))
|
|
}
|
|
}
|