Skip to content

Commit 4d35fa2

Browse files
committed
Merge branch 'develop' into release-1.0.0
2 parents 889afdb + 9c1e408 commit 4d35fa2

14 files changed

Lines changed: 428 additions & 103 deletions

.jazzy.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,18 @@ readme: README.md
99
github_url: https://github.com/tsolomko/BitByteData
1010
github_file_prefix: https://github.com/tsolomko/BitByteData/tree/develop
1111
theme: fullwidth
12+
13+
custom_categories:
14+
- name: Reading bytes
15+
children:
16+
- ByteReader
17+
- name: Reading bits (and bytes)
18+
children:
19+
- BitReader
20+
- LsbBitReader
21+
- MsbBitReader
22+
- name: Writing bits (and bytes)
23+
children:
24+
- BitWriter
25+
- LsbBitWriter
26+
- MsbBitWriter

Sources/BitReader.swift

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,62 @@
55

66
import Foundation
77

8+
/// A type that contains functions for reading `Data` bit-by-bit and byte-by-byte.
89
public protocol BitReader: class {
910

11+
/// True, if reader's BIT pointer is aligned with the BYTE border.
1012
var isAligned: Bool { get }
1113

14+
/// Creates an instance for reading `data`.
1215
init(data: Data)
1316

14-
func bits(count: Int) -> [UInt8]
17+
/// Reads bit and returns it, advancing by one BIT position.
18+
func bit() -> UInt8
1519

16-
// TODO: Rename?
17-
func intFromBits(count: Int) -> Int
20+
/// Reads `count` bits and returns them as an array of `UInt8`, advancing by `count` BIT positions.
21+
func bits(count: Int) -> [UInt8]
1822

19-
func bit() -> Int
23+
/// Reads `count` bits and returns them as a `Int` number, advancing by `count` BIT positions.
24+
func int(fromBits count: Int) -> Int
2025

26+
/// Aligns reader's BIT pointer to the BYTE border, i.e. moves BIT pointer to the first BIT of the next BYTE.
2127
func align()
2228

23-
// TODO: Describe preconditions.
29+
// MARK: ByteReader's methods.
2430

31+
/// Reads byte and returns it, advancing by one BYTE position.
2532
func byte() -> UInt8
2633

34+
/// Reads `count` bytes and returns them as an array of `UInt8`, advancing by `count` BYTE positions.
2735
func bytes(count: Int) -> [UInt8]
2836

37+
/// Reads 8 bytes and returns them as a `UInt64` number, advancing by 8 BYTE positions.
2938
func uint64() -> UInt64
3039

40+
/// Reads 4 bytes and returns them as a `UInt32` number, advancing by 4 BYTE positions.
3141
func uint32() -> UInt32
3242

43+
/// Reads 2 bytes and returns them as a `UInt16` number, advancing by 2 BYTE positions.
3344
func uint16() -> UInt16
3445

3546
}
47+
48+
extension BitReader {
49+
50+
/**
51+
- Warning: Doesn't check if there is any data left.
52+
*/
53+
public func bits(count: Int) -> [UInt8] {
54+
guard count > 0
55+
else { return [] }
56+
57+
var array = [UInt8]()
58+
array.reserveCapacity(count)
59+
for _ in 0..<count {
60+
array.append(self.bit())
61+
}
62+
63+
return array
64+
}
65+
66+
}

Sources/BitWriter.swift

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,34 @@
55

66
import Foundation
77

8+
/// A type that contains functions for writing `Data` bit-by-bit (and byte-by-byte).
89
public protocol BitWriter {
910

11+
/// Data which contains writer's output (the last byte in progress is not included).
1012
var data: Data { get }
1113

12-
init()
13-
14+
/// True, if writer's BIT pointer is aligned with the BYTE border.
1415
var isAligned: Bool { get }
1516

17+
/// Creates an instance for writing.
18+
init()
19+
20+
/// Writes `bit`, advancing by one BIT position.
1621
func write(bit: UInt8)
1722

23+
/// Writes `bits`, advancing by `bits.count` BIT positions.
1824
func write(bits: [UInt8])
1925

20-
// TODO: Describe, what will happen if `bitsCount` is smaller than actual amount of `number`'s bits.
21-
// TODO: Describe, that `number` is processed in the same order as `BitWriter`'s.
26+
/// Writes `number`, using and advancing by `bitsCount` BIT positions.
2227
func write(number: Int, bitsCount: Int)
2328

29+
/// Writes `byte`, advancing by one BYTE position.
2430
func append(byte: UInt8)
2531

26-
// TODO: Describe, that it doesn't check if it actually needs to align.
32+
/**
33+
Aligns writer's BIT pointer to the BYTE border, i.e. moves BIT pointer to the first BIT of the next BYTE,
34+
filling all skipped BIT positions with zeros.
35+
*/
2736
func align()
2837

2938
}

Sources/ByteReader.swift

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,46 +5,88 @@
55

66
import Foundation
77

8+
/// A type that contains functions for reading `Data` byte-by-byte.
89
public class ByteReader {
910

11+
/// Size of the `data` (in bytes).
1012
public let size: Int
13+
14+
/// Data which is being read.
1115
public let data: Data
16+
17+
/// Offset to the byte in `data` which will be read next.
1218
public var offset: Int
1319

14-
// TODO: Rename?
15-
public var isAtTheEnd: Bool {
16-
return self.data.endIndex == self.offset
20+
/**
21+
True, if `offset` points at any position after the last byte in `data`.
22+
23+
- Note: It generally means that all bytes have been read.
24+
*/
25+
26+
public var isFinished: Bool {
27+
return self.data.endIndex <= self.offset
1728
}
1829

30+
/// Creates an instance for reading `data`.
1931
public init(data: Data) {
2032
self.size = data.count
2133
self.data = data
2234
self.offset = data.startIndex
2335
}
2436

37+
/**
38+
Reads byte and returns it, advancing by one position.
39+
40+
- Warning: Doesn't check if there is any data left. It is advisable to use `isFinished` BEFORE calling this method
41+
to check if the end is reached.
42+
*/
2543
public func byte() -> UInt8 {
2644
self.offset += 1
2745
return self.data[self.offset - 1]
2846
}
2947

48+
/**
49+
Reads `count` bytes and returns them as an array of `UInt8`, advancing by `count` positions.
50+
51+
- Warning: Doesn't check if there is any data left. It is advisable to use `isFinished` BEFORE calling this method
52+
to check if the end is reached.
53+
*/
3054
public func bytes(count: Int) -> [UInt8] {
3155
let result = self.data[self.offset..<self.offset + count].toArray(type: UInt8.self, count: count)
3256
self.offset += count
3357
return result
3458
}
3559

60+
/**
61+
Reads 8 bytes and returns them as a `UInt64` number, advancing by 8 positions.
62+
63+
- Warning: Doesn't check if there is any data left. It is advisable to use `isFinished` BEFORE calling this method
64+
to check if the end is reached.
65+
*/
3666
public func uint64() -> UInt64 {
3767
let result = self.data[self.offset..<self.offset + 8].to(type: UInt64.self)
3868
self.offset += 8
3969
return result
4070
}
4171

72+
/**
73+
Reads 4 bytes and returns them as a `UInt32` number, advancing by 4 positions.
74+
75+
- Warning: Doesn't check if there is any data left. It is advisable to use `isFinished` BEFORE calling this method
76+
to check if the end is reached.
77+
*/
4278
public func uint32() -> UInt32 {
4379
let result = self.data[self.offset..<self.offset + 4].to(type: UInt32.self)
4480
self.offset += 4
4581
return result
4682
}
4783

84+
/**
85+
Reads 2 bytes and returns them as a `UInt16` number, advancing by 2 positions.
86+
87+
- Warning: Doesn't check if there is any data left. It is advisable to use `isFinished` BEFORE calling this method
88+
to check if the end is reached.
89+
*/
4890
public func uint16() -> UInt16 {
4991
let result = self.data[self.offset..<self.offset + 2].to(type: UInt16.self)
5092
self.offset += 2

Sources/LsbBitReader.swift

Lines changed: 73 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,38 +5,47 @@
55

66
import Foundation
77

8+
/**
9+
A type that contains functions for reading `Data` bit-by-bit and byte-by-byte,
10+
assuming "LSB 0" bit numbering scheme.
11+
*/
812
public final class LsbBitReader: ByteReader, BitReader {
913

1014
private var bitMask: UInt8 = 1
1115

16+
/// True, if reader's BIT pointer is aligned with the BYTE border.
1217
public var isAligned: Bool {
1318
return self.bitMask == 1
1419
}
1520

16-
public func bits(count: Int) -> [UInt8] {
17-
guard count > 0 else {
18-
return []
19-
}
21+
/**
22+
Reads bit and returns it, advancing by one BIT position.
2023

21-
var array: [UInt8] = Array(repeating: 0, count: count)
22-
for i in 0..<count {
23-
array[i] = self.data[self.offset] & self.bitMask > 0 ? 1 : 0
24+
- Warning: Doesn't check if there is any data left. It is advisable to use `isFinished` BEFORE calling this method
25+
to check if the end is reached.
26+
*/
27+
public func bit() -> UInt8 {
28+
let bit: UInt8 = self.data[self.offset] & self.bitMask > 0 ? 1 : 0
2429

25-
if self.bitMask == 128 {
26-
self.offset += 1
27-
self.bitMask = 1
28-
} else {
29-
self.bitMask <<= 1
30-
}
30+
if self.bitMask == 128 {
31+
self.offset += 1
32+
self.bitMask = 1
33+
} else {
34+
self.bitMask <<= 1
3135
}
3236

33-
return array
37+
return bit
3438
}
3539

36-
public func intFromBits(count: Int) -> Int {
37-
guard count > 0 else {
38-
return 0
39-
}
40+
/**
41+
Reads `count` bits and returns them as a `Int` number, advancing by `count` BIT positions.
42+
43+
- Warning: Doesn't check if there is any data left. It is advisable to use `isFinished` BEFORE calling this method
44+
to check if the end is reached.
45+
*/
46+
public func int(fromBits count: Int) -> Int {
47+
guard count > 0
48+
else { return 0 }
4049

4150
var result = 0
4251
for i in 0..<count {
@@ -56,47 +65,78 @@ public final class LsbBitReader: ByteReader, BitReader {
5665
return result
5766
}
5867

59-
public func bit() -> Int {
60-
let bit = self.data[self.offset] & self.bitMask > 0 ? 1 : 0
61-
62-
if self.bitMask == 128 {
63-
self.offset += 1
64-
self.bitMask = 1
65-
} else {
66-
self.bitMask <<= 1
67-
}
68-
69-
return bit
70-
}
68+
/**
69+
Aligns reader's BIT pointer to the BYTE border, i.e. moves BIT pointer to the first BIT of the next BYTE.
7170

71+
- Note: If reader is already aligned, then does nothing.
72+
- Warning: Doesn't check if there is any data left. It is advisable to use `isFinished` AFTER calling this method
73+
to check if the end was reached.
74+
*/
7275
public func align() {
73-
guard self.bitMask != 1 else {
74-
return
75-
}
76+
guard self.bitMask != 1
77+
else { return }
78+
7679
self.bitMask = 1
7780
self.offset += 1
7881
}
7982

83+
// MARK: ByteReader's methods.
84+
85+
/**
86+
Reads byte and returns it, advancing by one BYTE position.
87+
88+
- Warning: Doesn't check if there is any data left. It is advisable to use `isFinished` BEFORE calling this method
89+
to check if the end is reached.
90+
- Precondition: Reader MUST be aligned.
91+
*/
8092
public override func byte() -> UInt8 {
8193
precondition(isAligned, "BitReader is not aligned.")
8294
return super.byte()
8395
}
8496

97+
/**
98+
Reads `count` bytes and returns them as an array of `UInt8`, advancing by `count` BYTE positions.
99+
100+
- Warning: Doesn't check if there is any data left. It is advisable to use `isFinished` BEFORE calling this method
101+
to check if the end is reached.
102+
- Precondition: Reader MUST be aligned.
103+
*/
85104
public override func bytes(count: Int) -> [UInt8] {
86105
precondition(isAligned, "BitReader is not aligned.")
87106
return super.bytes(count: count)
88107
}
89108

109+
/**
110+
Reads 8 bytes and returns them as a `UInt64` number, advancing by 8 BYTE positions.
111+
112+
- Warning: Doesn't check if there is any data left. It is advisable to use `isFinished` BEFORE calling this method
113+
to check if the end is reached.
114+
- Precondition: Reader MUST be aligned.
115+
*/
90116
public override func uint64() -> UInt64 {
91117
precondition(isAligned, "BitReader is not aligned.")
92118
return super.uint64()
93119
}
94120

121+
/**
122+
Reads 4 bytes and returns them as a `UInt32` number, advancing by 4 BYTE positions.
123+
124+
- Warning: Doesn't check if there is any data left. It is advisable to use `isFinished` BEFORE calling this method
125+
to check if the end is reached.
126+
- Precondition: Reader MUST be aligned.
127+
*/
95128
public override func uint32() -> UInt32 {
96129
precondition(isAligned, "BitReader is not aligned.")
97130
return super.uint32()
98131
}
99132

133+
/**
134+
Reads 2 bytes and returns them as a `UInt16` number, advancing by 2 BYTE positions.
135+
136+
- Warning: Doesn't check if there is any data left. It is advisable to use `isFinished` BEFORE calling this method
137+
to check if the end is reached.
138+
- Precondition: Reader MUST be aligned.
139+
*/
100140
public override func uint16() -> UInt16 {
101141
precondition(isAligned, "BitReader is not aligned.")
102142
return super.uint16()

0 commit comments

Comments
 (0)