2014-08-05 11:53:32 +01:00
|
|
|
package base
|
|
|
|
|
2014-09-18 21:03:04 +01:00
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"fmt"
|
|
|
|
)
|
|
|
|
|
2014-08-05 11:53:32 +01:00
|
|
|
// BinaryAttributeGroups contain only BinaryAttributes
|
|
|
|
// Compact each Attribute to a bit for better storage
|
|
|
|
type BinaryAttributeGroup struct {
|
2014-09-18 21:03:04 +01:00
|
|
|
parent DataGrid
|
|
|
|
attributes []Attribute
|
|
|
|
size int
|
|
|
|
alloc []byte
|
|
|
|
maxRow int
|
2014-08-05 11:53:32 +01:00
|
|
|
}
|
|
|
|
|
2014-09-18 21:03:04 +01:00
|
|
|
// String returns a human-readable summary.
|
2014-09-18 22:04:05 +01:00
|
|
|
func (b *BinaryAttributeGroup) String() string {
|
|
|
|
return "BinaryAttributeGroup"
|
2014-08-05 11:53:32 +01:00
|
|
|
}
|
|
|
|
|
2014-09-18 21:03:04 +01:00
|
|
|
// RowSizeInBytes returns the size of each row in bytes
|
|
|
|
// (rounded up to nearest byte).
|
|
|
|
func (b *BinaryAttributeGroup) RowSizeInBytes() int {
|
2014-09-18 22:04:05 +01:00
|
|
|
return (len(b.attributes) + 7) / 8
|
2014-08-05 11:53:32 +01:00
|
|
|
}
|
|
|
|
|
2014-09-18 21:03:04 +01:00
|
|
|
// Attributes returns a slice of Attributes in this BinaryAttributeGroup.
|
|
|
|
func (b *BinaryAttributeGroup) Attributes() []Attribute {
|
|
|
|
ret := make([]Attribute, len(b.attributes))
|
|
|
|
for i, a := range b.attributes {
|
|
|
|
ret[i] = a
|
|
|
|
}
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
|
|
|
// AddAttribute adds an Attribute to this BinaryAttributeGroup
|
|
|
|
func (b *BinaryAttributeGroup) AddAttribute(a Attribute) error {
|
|
|
|
b.attributes = append(b.attributes, a)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Storage returns a reference to the underlying storage.
|
|
|
|
//
|
|
|
|
// IMPORTANT: don't modify
|
|
|
|
func (b *BinaryAttributeGroup) Storage() []byte {
|
|
|
|
return b.alloc
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// internal methods
|
|
|
|
//
|
|
|
|
|
|
|
|
func (b *BinaryAttributeGroup) setStorage(a []byte) {
|
|
|
|
b.alloc = a
|
|
|
|
}
|
|
|
|
|
2014-08-05 11:53:32 +01:00
|
|
|
func (b *BinaryAttributeGroup) getByteOffset(col, row int) int {
|
2014-09-18 21:03:04 +01:00
|
|
|
return row*b.RowSizeInBytes() + col/8
|
2014-08-05 11:53:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (b *BinaryAttributeGroup) set(col, row int, val []byte) {
|
2014-09-18 21:03:04 +01:00
|
|
|
|
|
|
|
offset := b.getByteOffset(col, row)
|
2014-08-05 11:53:32 +01:00
|
|
|
|
|
|
|
// If the value is 1, OR it
|
|
|
|
if val[0] > 0 {
|
2014-09-18 21:03:04 +01:00
|
|
|
b.alloc[offset] |= (1 << (uint(col) % 8))
|
2014-08-05 11:53:32 +01:00
|
|
|
} else {
|
|
|
|
// Otherwise, AND its complement
|
2014-09-18 21:03:04 +01:00
|
|
|
b.alloc[offset] &= ^(1 << (uint(col) % 8))
|
2014-08-05 11:53:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
row++
|
|
|
|
if row > b.maxRow {
|
|
|
|
b.maxRow = row
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *BinaryAttributeGroup) get(col, row int) []byte {
|
2014-09-18 21:03:04 +01:00
|
|
|
offset := b.getByteOffset(col, row)
|
|
|
|
if b.alloc[offset]&(1<<(uint(col%8))) > 0 {
|
2014-08-05 11:53:32 +01:00
|
|
|
return []byte{1}
|
|
|
|
} else {
|
|
|
|
return []byte{0}
|
|
|
|
}
|
|
|
|
}
|
2014-09-18 21:03:04 +01:00
|
|
|
|
|
|
|
func (b *BinaryAttributeGroup) appendToRowBuf(row int, buffer *bytes.Buffer) {
|
|
|
|
for i, a := range b.attributes {
|
|
|
|
postfix := " "
|
|
|
|
if i == len(b.attributes)-1 {
|
|
|
|
postfix = ""
|
|
|
|
}
|
|
|
|
buffer.WriteString(fmt.Sprintf("%s%s",
|
|
|
|
a.GetStringFromSysVal(b.get(i, row)), postfix))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *BinaryAttributeGroup) resize(add int) {
|
|
|
|
newAlloc := make([]byte, len(b.alloc)+add)
|
|
|
|
copy(newAlloc, b.alloc)
|
|
|
|
b.alloc = newAlloc
|
|
|
|
}
|