Skip to content

Commit aa12d37

Browse files
authored
Merge pull request #7 from Cosmo/development
Development
2 parents 72c0ab8 + 4d5fbe8 commit aa12d37

File tree

5 files changed

+202
-172
lines changed

5 files changed

+202
-172
lines changed

.gitignore

+11-79
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,5 @@
1-
2-
# Created by https://www.gitignore.io/api/macos,swift,xcode,swiftpm,carthage,cocoapods
3-
# Edit at https://www.gitignore.io/?templates=macos,swift,xcode,swiftpm,carthage,cocoapods
4-
5-
### Carthage ###
6-
# Carthage
7-
#
8-
# Add this line if you want to avoid checking in source code from Carthage dependencies.
9-
# Carthage/Checkouts
10-
11-
Carthage/Build
12-
13-
### CocoaPods ###
14-
## CocoaPods GitIgnore Template
15-
16-
# CocoaPods - Only use to conserve bandwidth / Save time on Pushing
17-
# - Also handy if you have a large number of dependant pods
18-
# - AS PER https://guides.cocoapods.org/using/using-cocoapods.html NEVER IGNORE THE LOCK FILE
19-
Pods/
20-
21-
### macOS ###
22-
# General
23-
.DS_Store
24-
.AppleDouble
25-
.LSOverride
26-
27-
# Icon must end with two \r
28-
Icon
29-
30-
# Thumbnails
31-
._*
32-
33-
# Files that might appear in the root of a volume
34-
.DocumentRevisions-V100
35-
.fseventsd
36-
.Spotlight-V100
37-
.TemporaryItems
38-
.Trashes
39-
.VolumeIcon.icns
40-
.com.apple.timemachine.donotpresent
41-
42-
# Directories potentially created on remote AFP share
43-
.AppleDB
44-
.AppleDesktop
45-
Network Trash Folder
46-
Temporary Items
47-
.apdisk
48-
49-
### Swift ###
501
# Xcode
2+
#
513
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
524

535
## Build generated
@@ -81,32 +33,37 @@ timeline.xctimeline
8133
playground.xcworkspace
8234

8335
# Swift Package Manager
36+
#
8437
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
8538
# Packages/
8639
# Package.pins
8740
# Package.resolved
8841
.build/
89-
# Add this line if you want to avoid checking in Xcode SPM integration.
90-
# .swiftpm/xcode
9142

9243
# CocoaPods
44+
#
9345
# We recommend against adding the Pods directory to your .gitignore. However
9446
# you should judge for yourself, the pros and cons are mentioned at:
9547
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
48+
#
9649
# Pods/
50+
#
9751
# Add this line if you want to avoid checking in source code from the Xcode workspace
9852
# *.xcworkspace
9953

10054
# Carthage
55+
#
10156
# Add this line if you want to avoid checking in source code from Carthage dependencies.
10257
# Carthage/Checkouts
10358

59+
Carthage/Build
10460

10561
# Accio dependency management
10662
Dependencies/
10763
.accio/
10864

10965
# fastlane
66+
#
11067
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
11168
# screenshots whenever they are needed.
11269
# For more information about the recommended setup visit:
@@ -118,35 +75,10 @@ fastlane/screenshots/**/*.png
11875
fastlane/test_output
11976

12077
# Code Injection
78+
#
12179
# After new code Injection tools there's a generated folder /iOSInjectionProject
12280
# https://github.com/johnno1962/injectionforxcode
12381

12482
iOSInjectionProject/
125-
126-
### SwiftPM ###
127-
Packages
128-
xcuserdata
129-
*.xcodeproj
130-
131-
132-
### Xcode ###
133-
# Xcode
134-
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
135-
136-
## User settings
137-
138-
## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
139-
140-
## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
141-
142-
## Xcode Patch
143-
*.xcodeproj/*
144-
!*.xcodeproj/project.pbxproj
145-
!*.xcodeproj/xcshareddata/
146-
!*.xcworkspace/contents.xcworkspacedata
147-
/*.gcno
148-
149-
### Xcode Patch ###
150-
**/xcshareddata/WorkspaceSettings.xcsettings
151-
152-
# End of https://www.gitignore.io/api/macos,swift,xcode,swiftpm,carthage,cocoapods
83+
.DS_Store
84+
.swiftpm

README.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ try binary.readBits(quantitiy: 4)
3232

3333
## Example
3434

35-
This shows how easy it is, to break down an [IPv4 header](https://en.wikipedia.org/wiki/IPv4#Header).
36-
3735
```swift
3836
let binary = Binary(bytes: [0b1_1_0_1_1_1_0_0])
3937
| | | | | | | |
@@ -47,6 +45,7 @@ let binary = Binary(bytes: [0b1_1_0_1_1_1_0_0])
4745
try binary.bit() // 1
4846
```
4947

48+
This shows how easy it is, to break down an [IPv4 header](https://en.wikipedia.org/wiki/IPv4#Header).
5049

5150
```swift
5251
let binary = Binary(bytes: [0x1B, 0x44, ])
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
import Foundation
22

3-
enum BinError: Error {
4-
case outOfBounds
5-
case notString
6-
}
7-
83
public struct Binary {
4+
/// Stores a reading cursor in bits.
5+
/// All methods starting with `read` will increment the value of `bitCursor`.
96
private var bitCursor: Int
7+
8+
/// Stores the binary content.
109
var bytesStore: [UInt8]
11-
private let byteSize = 8
1210

11+
/// Constant with number of bits in a byte (8)
12+
private let byteSize = UInt8.bitWidth
13+
14+
/// Initialize a new `Binary`.
1315
public init(bytes: [UInt8]) {
1416
self.bitCursor = 0
1517
self.bytesStore = bytes
@@ -36,17 +38,30 @@ public struct Binary {
3638
return bitCursor + (bytes * byteSize)
3739
}
3840

41+
/// Increments the `bitCursor`-value by the given `bits`.
42+
private mutating func incrementCursorBy(bits: Int) {
43+
bitCursor = incrementedCursorBy(bits: bits)
44+
}
45+
46+
/// Increments the `bitCursor`-value by the given `bytes`.
47+
private mutating func incrementCursorBy(bytes: Int) {
48+
bitCursor = incrementedCursorBy(bytes: bytes)
49+
}
50+
3951
/// Sets the reading cursor back to its initial value.
4052
public mutating func resetCursor() {
4153
self.bitCursor = 0
4254
}
4355

44-
// MARK: - Bit
56+
// MARK: - Get
57+
58+
/// All `get` methods give access to binary data at any given
59+
/// location — without incrementing the internal cursor.
4560

46-
/// Returns the binary value `0` or `1` of the given position.
61+
/// Returns an `UInt8` with the value of 0 or 1 of the given position.
4762
public func getBit(index: Int) throws -> UInt8 {
4863
guard (0..<(bytesStore.count)).contains(index / byteSize) else {
49-
throw BinError.outOfBounds
64+
throw BinaryError.outOfBounds
5065
}
5166
let byteCursor = index / byteSize
5267
let bitindex = 7 - (index % byteSize)
@@ -56,79 +71,114 @@ public struct Binary {
5671
/// Returns the `Int`-value of the given range.
5772
public mutating func getBits(range: Range<Int>) throws -> Int {
5873
guard (0...(bytesStore.count * byteSize)).contains(range.endIndex) else {
59-
throw BinError.outOfBounds
74+
throw BinaryError.outOfBounds
6075
}
6176
return try range.reversed().enumerated().reduce(0) {
6277
$0 + Int(try getBit(index: $1.element) << $1.offset)
6378
}
6479
}
6580

66-
/// Returns the binary value `0` or `1` of the given position and
67-
/// increments the reading cursor by one bit.
68-
public mutating func readBit() throws -> UInt8 {
69-
defer { bitCursor = incrementedCursorBy(bits: 1) }
70-
return try getBit(index: bitCursor)
71-
}
72-
73-
/// Returns the `Int`-value of the next n-bits (`quantitiy`)
74-
/// and increments the reading cursor by n-bits.
75-
public mutating func readBits(quantitiy: Int) throws -> Int {
76-
guard (0...(bytesStore.count * byteSize)).contains(bitCursor + quantitiy) else {
77-
throw BinError.outOfBounds
78-
}
79-
defer { bitCursor = incrementedCursorBy(bits: quantitiy) }
80-
return try (bitCursor..<(bitCursor + quantitiy)).reversed().enumerated().reduce(0) {
81-
$0 + Int(try getBit(index: $1.element) << $1.offset)
82-
}
83-
}
84-
85-
// MARK: - Byte
86-
8781
/// Returns the `UInt8`-value of the given `index`.
8882
public func getByte(index: Int) throws -> UInt8 {
8983
/// Check if `index` is within bounds of `bytes`
9084
guard (0..<(bytesStore.count)).contains(index) else {
91-
throw BinError.outOfBounds
85+
throw BinaryError.outOfBounds
9286
}
9387
return bytesStore[index]
9488
}
9589

9690
/// Returns an `[UInt8]` of the given `range`.
9791
public func getBytes(range: Range<Int>) throws -> [UInt8] {
9892
guard (0...(bytesStore.count)).contains(range.endIndex) else {
99-
throw BinError.outOfBounds
93+
throw BinaryError.outOfBounds
10094
}
10195
return Array(bytesStore[range])
10296
}
10397

104-
/// Returns the `UInt8`-value of the next byte and increments the reading cursor.
98+
// MARK: - Read
99+
100+
/// All `read*` methods return the next requested binary data
101+
/// and increment an internal cursor (or reading offset) to
102+
/// the end of the requested data, so the
103+
/// next `read*`-method can continue from there.
104+
105+
/// Returns an `UInt8` with the value of 0 or 1 of the given
106+
/// position and increments the reading cursor by one bit.
107+
public mutating func readBit() throws -> UInt8 {
108+
let result = try getBit(index: bitCursor)
109+
incrementCursorBy(bits: 1)
110+
return result
111+
}
112+
113+
/// Returns the `Int`-value of the next n-bits (`quantitiy`)
114+
/// and increments the reading cursor by n-bits.
115+
public mutating func readBits(quantitiy: Int) throws -> Int {
116+
guard (0...(bytesStore.count * byteSize)).contains(bitCursor + quantitiy) else {
117+
throw BinaryError.outOfBounds
118+
}
119+
let result = try (bitCursor..<(bitCursor + quantitiy)).reversed().enumerated().reduce(0) {
120+
$0 + Int(try getBit(index: $1.element) << $1.offset)
121+
}
122+
incrementCursorBy(bits: quantitiy)
123+
return result
124+
}
125+
126+
/// Returns the `UInt8`-value of the next byte and
127+
/// increments the reading cursor by 1 byte.
105128
public mutating func readByte() throws -> UInt8 {
106129
let result = try getByte(index: bitCursor / byteSize)
107-
bitCursor = incrementedCursorBy(bytes: 1)
130+
incrementCursorBy(bytes: 1)
108131
return result
109132
}
110133

111-
/// Returns an `[UInt8]` of the next n-bytes (`quantitiy`) and
134+
/// Returns a `[UInt8]` of the next n-bytes (`quantitiy`) and
112135
/// increments the reading cursor by n-bytes.
113136
public mutating func readBytes(quantitiy: Int) throws -> [UInt8] {
114137
let byteCursor = bitCursor / byteSize
115-
defer { bitCursor = incrementedCursorBy(bytes: quantitiy) }
138+
incrementCursorBy(bytes: quantitiy)
116139
return try getBytes(range: byteCursor..<(byteCursor + quantitiy))
117140
}
118141

119-
// MARK: - String
142+
/// Returns a `String` of the next n-bytes (`quantitiy`) and
143+
/// increments the reading cursor by n-bytes.
120144
public mutating func readString(quantitiyOfBytes quantitiy: Int, encoding: String.Encoding = .utf8) throws -> String {
121145
guard let result = String(bytes: try self.readBytes(quantitiy: quantitiy), encoding: encoding) else {
122-
throw BinError.notString
146+
throw BinaryError.notString
123147
}
124148
return result
125149
}
126150

127-
public mutating func getCharacter() throws -> Character {
151+
/// Returns the next byte as `Character` and
152+
/// increments the reading cursor by 1 byte.
153+
public mutating func readCharacter() throws -> Character {
128154
return Character(UnicodeScalar(try readByte()))
129155
}
130156

157+
/// Returns the `Bool`-value of the next bit and
158+
/// increments the reading cursor by 1 bit.
131159
public mutating func readBool() throws -> Bool {
132160
return try readBit() == 1
133161
}
162+
163+
/// Returns the `UInt8`-value of the next 4 bit and
164+
/// increments the reading cursor by 4 bits.
165+
public mutating func readNibble() throws -> UInt8 {
166+
return UInt8(try readBits(quantitiy: 4))
167+
}
168+
169+
// MARK: - Find
170+
171+
/// Returns indices of given `[UInt8]`.
172+
func indices(of sequence: [UInt8]) -> [Int] {
173+
let size = sequence.count
174+
return bytesStore.indices.dropLast(size - 1).filter {
175+
bytesStore[$0..<($0 + size)].elementsEqual(sequence)
176+
}
177+
}
178+
179+
/// Returns indices of given `String`.
180+
func indices(of string: String) -> [Int] {
181+
let sequence = [UInt8](string.utf8)
182+
return indices(of: sequence)
183+
}
134184
}

Sources/BinaryKit/BinaryError.swift

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//
2+
// File.swift
3+
//
4+
//
5+
// Created by Devran on 27.09.19.
6+
//
7+
8+
import Foundation
9+
10+
enum BinaryError: Error {
11+
case outOfBounds
12+
case notString
13+
}

0 commit comments

Comments
 (0)