/
types.go
124 lines (109 loc) · 3.85 KB
/
types.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package hdf5
import (
"fmt"
"io"
"reflect"
"github.com/batchatco/go-thrower"
)
// Each type implements this interface.
type typeManager interface {
parse(hr heapReader, c caster, attr *attribute, bitFields uint32, f remReader, d remReader)
defaultFillValue(obj *object, objFillValue []byte, undefinedFillValue bool) []byte
alloc(hr heapReader, c caster, r io.Reader, attr *attribute, dimensions []uint64) interface{}
cdlTypeString(sh sigHelper, name string, attr *attribute, origNames map[string]bool) string
goTypeString(sh sigHelper, name string, attr *attribute, origNames map[string]bool) string
}
type heapReader interface {
readGlobalHeap(heapAddress uint64, index uint32) (remReader, uint64)
}
type caster interface {
cast(attr attribute) reflect.Type
}
type sigHelper interface {
findSignature(signature string, name string, origNames map[string]bool,
printer printerType) string
}
type printerType func(class uint8, helper sigHelper, name string, attr *attribute,
origNames map[string]bool) string
var dispatch = []typeManager{
// 0-4
fixedPointManager,
floatingPointManager,
timeManager,
stringManager,
bitfieldManager,
// 5-9
opaqueManager,
compoundManager,
referenceManager,
enumManager,
vlenManager,
// 10
arrayManager,
}
func getDispatch(class uint8) typeManager {
if int(class) >= len(dispatch) {
fail(fmt.Sprintf("Unknown class: %d", class))
}
return dispatch[class]
}
// parse is a wrapper around the table lookup of the type to get the interface
func parse(class uint8, hr heapReader, c caster, attr *attribute, bitFields uint32, f remReader, d remReader) {
getDispatch(class).parse(hr, c, attr, bitFields, f, d)
}
// defaultFillValue is a wrapper around the table lookup of the type to get the interface
func defaultFillValue(class uint8, obj *object, objFillValue []byte, undefinedFillValue bool) []byte {
return getDispatch(class).defaultFillValue(obj, objFillValue, undefinedFillValue)
}
func alloc(class uint8, hr heapReader, c caster, r io.Reader, attr *attribute, dimensions []uint64) interface{} {
return getDispatch(class).alloc(hr, c, r, attr, dimensions)
}
func cdlTypeString(class uint8, sh sigHelper, name string, attr *attribute, origNames map[string]bool) string {
return getDispatch(class).cdlTypeString(sh, name, attr, origNames)
}
func goTypeString(class uint8, sh sigHelper, name string, attr *attribute, origNames map[string]bool) string {
return getDispatch(class).goTypeString(sh, name, attr, origNames)
}
func printDatatype(hr heapReader, c caster, bf remReader, df remReader, objCount int64, attr *attribute) {
assert(bf.Rem() >= 8, "short data")
b0 := read8(bf)
b1 := read8(bf)
b2 := read8(bf)
b3 := read8(bf)
bitFields := uint32(b1) | (uint32(b2) << 8) | (uint32(b3) << 16)
dtversion := (b0 >> 4) & 0b1111
dtclass := b0 & 0b1111
dtlength := read32(bf)
logger.Infof("* length=%d dtlength=%d dtversion=%d class=%s flags=%s",
bf.Rem(), dtlength,
dtversion, typeNames[dtclass], binaryToString(uint64(bitFields)))
switch dtversion {
case dtversionStandard:
logger.Info("Standard datatype")
case dtversionArray:
logger.Info("Array-encoded datatype")
case dtversionPacked:
logger.Info("VAX and/or packed datatype")
case dtversionV4:
if maxDTVersion == dtversionV4 {
// allowed
logger.Info("Undocumented datatype version 4")
break
}
fallthrough
default:
logger.Error(fmt.Sprint("Unknown datatype version: ", dtversion))
thrower.Throw(ErrUnsupportedDataTypeVersion)
}
attr.dtversion = dtversion
attr.class = dtclass
attr.length = dtlength
assert(attr.length != 0, "attr length can't be zero")
parse(dtclass, hr, c, attr, bitFields, bf, df)
if df != nil && df.Rem() > 0 {
// It is normal for there to be extra data, not sure why yet.
// It does not break any unit tests, so the extra data seems unnecessary.
logger.Info("did not read all data", df.Rem(), typeNames[dtclass])
skip(df, df.Rem())
}
}