Skip to content

Commit 50ac31f

Browse files
committed
Add methods to read/write uint from/to Buffer.
1 parent 7c23942 commit 50ac31f

File tree

3 files changed

+719
-0
lines changed

3 files changed

+719
-0
lines changed

buffer_integer.go

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
// Copyright (c) 2021 Hirotsuna Mizuno. All rights reserved.
2+
// Use of this source code is governed by the MIT license that can be found in
3+
// the LICENSE file.
4+
5+
package bitarray
6+
7+
import (
8+
"encoding/binary"
9+
)
10+
11+
// Uint8 returns up to 8 bits from the beginning of the buffer as a uint8 value.
12+
// If buf.Len() is greater than 8, only the first 8 bits are used. If buf.Len()
13+
// is less than 8, it is treated as an integer with that number of bits. For
14+
// example, if buf.Len() == 5, it returns a 5-bit integer, 0 to 31(=0b11111), as
15+
// a uint8 value.
16+
func (buf *Buffer) Uint8() uint8 {
17+
if buf.nBits == 0 {
18+
return 0
19+
}
20+
n, off := 8, 0
21+
if buf.nBits < 8 {
22+
n, off = buf.nBits, 8-buf.nBits
23+
}
24+
b := make([]byte, 1)
25+
copyBits(b, buf.b, off, buf.off, n)
26+
27+
return b[0]
28+
}
29+
30+
// PutUint8 sets a uint8 value v within up to 8 bits from the beginning of the
31+
// buffer. If buf.Len() is greater than 8, only the first 8 bits are updated. If
32+
// buf.Len() is less than 8, only the LSBs of v are written.
33+
func (buf *Buffer) PutUint8(v uint8) {
34+
if buf.nBits == 0 {
35+
return
36+
}
37+
n, off := 8, 0
38+
if buf.nBits < 8 {
39+
n, off = buf.nBits, 8-buf.nBits
40+
}
41+
b := []byte{v}
42+
copyBits(buf.b, b, buf.off, off, n)
43+
}
44+
45+
// Uint16 returns up to 16 bits from the beginning of the buffer as a uint16
46+
// value. If buf.Len() is greater than 16, only the first 16 bits are used. If
47+
// buf.Len() is less than 16, it is treated as an integer with that number of
48+
// bits. For example, if buf.Len() == 5, it returns a 5-bit integer, 0 to
49+
// 31(=0b11111), as a uint16 value.
50+
func (buf *Buffer) Uint16() uint16 {
51+
if buf.nBits == 0 {
52+
return 0
53+
}
54+
n, off := 16, 0
55+
if buf.nBits < 16 {
56+
n, off = buf.nBits, 16-buf.nBits
57+
}
58+
b := make([]byte, 2)
59+
copyBits(b, buf.b, off, buf.off, n)
60+
61+
return binary.BigEndian.Uint16(b)
62+
}
63+
64+
// PutUint16 sets a uint16 value v within up to 16 bits from the beginning of
65+
// the buffer. If buf.Len() is greater than 16, only the first 16 bits are
66+
// updated. If buf.Len() is less than 16, only the LSBs of v are written.
67+
func (buf *Buffer) PutUint16(v uint16) {
68+
if buf.nBits == 0 {
69+
return
70+
}
71+
n, off := 16, 0
72+
if buf.nBits < 16 {
73+
n, off = buf.nBits, 16-buf.nBits
74+
}
75+
b := make([]byte, 2)
76+
binary.BigEndian.PutUint16(b, v)
77+
copyBits(buf.b, b, buf.off, off, n)
78+
}
79+
80+
// Uint32 returns up to 32 bits from the beginning of the buffer as a uint32
81+
// value. If buf.Len() is greater than 32, only the first 32 bits are used. If
82+
// buf.Len() is less than 32, it is treated as an integer with that number of
83+
// bits. For example, if buf.Len() == 5, it returns a 5-bit integer, 0 to
84+
// 31(=0b11111), as a uint32 value.
85+
func (buf *Buffer) Uint32() uint32 {
86+
if buf.nBits == 0 {
87+
return 0
88+
}
89+
n, off := 32, 0
90+
if buf.nBits < 32 {
91+
n, off = buf.nBits, 32-buf.nBits
92+
}
93+
b := make([]byte, 4)
94+
copyBits(b, buf.b, off, buf.off, n)
95+
96+
return binary.BigEndian.Uint32(b)
97+
}
98+
99+
// PutUint32 sets a uint32 value v within up to 32 bits from the beginning of
100+
// the buffer. If buf.Len() is greater than 32, only the first 32 bits are
101+
// updated. If buf.Len() is less than 32, only the LSBs of v are written.
102+
func (buf *Buffer) PutUint32(v uint32) {
103+
if buf.nBits == 0 {
104+
return
105+
}
106+
n, off := 32, 0
107+
if buf.nBits < 32 {
108+
n, off = buf.nBits, 32-buf.nBits
109+
}
110+
b := make([]byte, 4)
111+
binary.BigEndian.PutUint32(b, v)
112+
copyBits(buf.b, b, buf.off, off, n)
113+
}
114+
115+
// Uint64 returns up to 64 bits from the beginning of the buffer as a uint64
116+
// value. If buf.Len() is greater than 64, only the first 64 bits are used. If
117+
// buf.Len() is less than 64, it is treated as an integer with that number of
118+
// bits. For example, if buf.Len() == 5, it returns a 5-bit integer, 0 to
119+
// 31(=0b11111), as a uint64 value.
120+
func (buf *Buffer) Uint64() uint64 {
121+
if buf.nBits == 0 {
122+
return 0
123+
}
124+
n, off := 64, 0
125+
if buf.nBits < 64 {
126+
n, off = buf.nBits, 64-buf.nBits
127+
}
128+
b := make([]byte, 8)
129+
copyBits(b, buf.b, off, buf.off, n)
130+
131+
return binary.BigEndian.Uint64(b)
132+
}
133+
134+
// PutUint64 sets a uint64 value v within up to 64 bits from the beginning of
135+
// the buffer. If buf.Len() is greater than 64, only the first 64 bits are
136+
// updated. If buf.Len() is less than 64, only the LSBs of v are written.
137+
func (buf *Buffer) PutUint64(v uint64) {
138+
if buf.nBits == 0 {
139+
return
140+
}
141+
n, off := 64, 0
142+
if buf.nBits < 64 {
143+
n, off = buf.nBits, 64-buf.nBits
144+
}
145+
b := make([]byte, 8)
146+
binary.BigEndian.PutUint64(b, v)
147+
copyBits(buf.b, b, buf.off, off, n)
148+
}

buffer_integer_example_test.go

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
// Copyright (c) 2021 Hirotsuna Mizuno. All rights reserved.
2+
// Use of this source code is governed by the MIT license that can be found in
3+
// the LICENSE file.
4+
5+
package bitarray_test
6+
7+
import (
8+
"fmt"
9+
10+
"github.com/tunabay/go-bitarray"
11+
)
12+
13+
func ExampleBuffer_Uint8() {
14+
b := []byte{0b_1100_1010, 0b_1111_0000}
15+
buf := bitarray.NewBufferFromByteSlice(b)
16+
17+
fmt.Println(buf.Slice(4, 12).Uint8()) // 1010 1111
18+
fmt.Println(buf.Slice(8, 12).Uint8()) // 1111
19+
fmt.Println(buf.Slice(4, 10).Uint8()) // 1010 11
20+
21+
// Output:
22+
// 175
23+
// 15
24+
// 43
25+
}
26+
27+
func ExampleBuffer_PutUint8() {
28+
b := make([]byte, 2)
29+
buf := bitarray.NewBufferFromByteSlice(b)
30+
31+
buf.Slice(4, 12).PutUint8(255) // 11111111
32+
fmt.Printf("%08b\n", b)
33+
buf.Slice(0, 6).PutUint8(42) // 101010
34+
buf.SliceToEnd(13).PutUint8(7) // 111
35+
fmt.Printf("%08b\n", b)
36+
37+
// Output:
38+
// [00001111 11110000]
39+
// [10101011 11110111]
40+
}
41+
42+
func ExampleBuffer_Uint16() {
43+
b := []byte{0x12, 0x34, 0x56}
44+
buf := bitarray.NewBufferFromByteSlice(b)
45+
46+
fmt.Printf("%04x\n", buf.Slice(4, 20).Uint16())
47+
fmt.Printf("%04x\n", buf.Slice(8, 20).Uint16())
48+
49+
// Output:
50+
// 2345
51+
// 0345
52+
}
53+
54+
func ExampleBuffer_PutUint16() {
55+
b := make([]byte, 3)
56+
buf := bitarray.NewBufferFromByteSlice(b)
57+
58+
buf.Slice(4, 20).PutUint16(0xffff)
59+
fmt.Printf("%08b\n", b)
60+
buf.Slice(10, 16).PutUint16(0b1010)
61+
fmt.Printf("%08b\n", b)
62+
63+
// Output:
64+
// [00001111 11111111 11110000]
65+
// [00001111 11001010 11110000]
66+
}
67+
68+
func ExampleBuffer_Uint32() {
69+
b := []byte{0x12, 0x34, 0x56, 0x78, 0x9a}
70+
buf := bitarray.NewBufferFromByteSlice(b)
71+
72+
fmt.Printf("%08x\n", buf.Slice(4, 36).Uint32())
73+
fmt.Printf("%08x\n", buf.Slice(8, 20).Uint32())
74+
75+
// Output:
76+
// 23456789
77+
// 00000345
78+
}
79+
80+
func ExampleBuffer_PutUint32() {
81+
b := make([]byte, 5)
82+
buf := bitarray.NewBufferFromByteSlice(b)
83+
84+
buf.Slice(4, 36).PutUint32(0xff00ffff)
85+
fmt.Printf("%08b\n", b)
86+
buf.Slice(16, 28).PutUint32(0xf0c)
87+
fmt.Printf("%08b\n", b)
88+
89+
// Output:
90+
// [00001111 11110000 00001111 11111111 11110000]
91+
// [00001111 11110000 11110000 11001111 11110000]
92+
}
93+
94+
func ExampleBuffer_Uint64() {
95+
b := []byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12}
96+
buf := bitarray.NewBufferFromByteSlice(b)
97+
98+
fmt.Printf("%016x\n", buf.Slice(4, 68).Uint64())
99+
fmt.Printf("%016x\n", buf.Slice(12, 24).Uint64())
100+
101+
// Output:
102+
// 23456789abcdef01
103+
// 0000000000000456
104+
}
105+
106+
func ExampleBuffer_PutUint64() {
107+
b := make([]byte, 9)
108+
buf := bitarray.NewBufferFromByteSlice(b)
109+
110+
buf.Slice(4, 68).PutUint64(0x1234567812345678)
111+
fmt.Printf("%x\n", b)
112+
buf.Slice(12, 24).PutUint64(0xabc)
113+
fmt.Printf("%x\n", b)
114+
115+
// Output:
116+
// 012345678123456780
117+
// 012abc678123456780
118+
}

0 commit comments

Comments
 (0)