aboutsummaryrefslogtreecommitdiff
path: root/bitreader.go
blob: 9d9a273f8352d697d8b61b94566a08d91a33aab6 (plain) (blame)
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
125
126
127
128
129
package main

import (
	"fmt"
	"math/bits"
	"strconv"
	"strings"
)

type ReaderType struct {
	data  []byte
	base  int
	index int
	lsb   bool
}

func Reader(data []byte) *ReaderType {
	return &ReaderType{
		data:  data,
		base:  0,
		index: 0,
		lsb:   false,
	}
}

func ReaderLSB(data []byte) *ReaderType {
	dataReversed := data
	for index, byteValue := range data {
		dataReversed[index] = bits.Reverse8(byteValue)
	}
	return &ReaderType{
		data:  dataReversed,
		base:  0,
		index: 0,
		lsb:   true,
	}
}

func (reader *ReaderType) SkipBits(bits int) error {
	if bits <= 0 {
		return fmt.Errorf("SkipBits Error: Bits value %d lower or equals than 0.", bits)
	}
	for reader.index+bits > 7 {
		reader.base++
		reader.index = 0
		bits -= 8
	}
	reader.index += bits
	return nil
}

func (reader *ReaderType) ReadBits32(bits int) (int, error) {
	if bits <= 0 {
		return -1, fmt.Errorf("ReadBits Error: Bits value %d lower or equals than 0.", bits)
	}
	if bits > 32 {
		return -1, fmt.Errorf("ReadBits Error: Bits value %d higher than 32.", bits)
	}
	err := reader.checkAvailableBits(bits)
	if err != nil {
		return -1, err
	}
	if reader.lsb {
		var output string
		// Go to last bit and read backwards from there
		reader.base += bits / 8
		reader.index += bits % 8
		if reader.index > 7 {
			reader.index -= 8
			reader.base++
		}
		for i := 0; i < bits; i++ {
			reader.index--
			if reader.index < 0 {
				reader.base--
				reader.index = 7
			}
			binary := fmt.Sprintf("%08b", reader.data[reader.base])
			binaryArr := strings.Split(binary, "")
			output += binaryArr[reader.index]
		}
		// Return to last bit after reading
		reader.base += bits / 8
		reader.index += bits % 8
		if reader.index > 7 {
			reader.index -= 8
		}
		// Conversion of string binary to int
		value, err := strconv.ParseUint(output, 2, 32)
		if err != nil {
			return -1, fmt.Errorf("%s", err)
		}
		return int(value), nil
	} else {
		var output string
		for i := 0; i < bits; i++ {
			binary := fmt.Sprintf("%08b", reader.data[reader.base])
			binaryArr := strings.Split(binary, "")
			output += binaryArr[reader.index]
			reader.index++
			if reader.index > 7 {
				reader.base++
				reader.index = 0
			}
		}
		// Conversion of string binary to int
		value, err := strconv.ParseUint(output, 2, 32)
		if err != nil {
			return -1, fmt.Errorf("%s", err)
		}
		return int(value), nil
	}
}

func (reader *ReaderType) ReadBit() (bool, error) {
	value, err := reader.ReadBits32(1)
	if err != nil {
		return false, fmt.Errorf("ReadBit Error: %s", err)
	}
	return value != 0, nil
}

func (reader *ReaderType) checkAvailableBits(bits int) error {
	availableBits := (len(reader.data)-reader.base)*8 - reader.index
	if availableBits < bits {
		return fmt.Errorf("BitReaderOutOfBounds: Wanted to read %d bit(s) but only %d bit(s) is/are available.", bits, availableBits)
	}
	return nil
}