├── .dockerignore ├── .github └── workflows │ ├── linuxtest.yml │ └── macostest.yml ├── .gitignore ├── .swift-format ├── .swiftlint.yml ├── CHANGELOG.md ├── Dockerfile ├── LICENSE ├── Package.swift ├── README.md ├── Sources └── BABAB │ ├── BitField.swift │ ├── BitmapAllocator.swift │ ├── ByteArray.swift │ ├── Extensions │ ├── BinaryInteger+Extras.swift │ ├── Bool+Extras.swift │ ├── FixedWidthInteger+Extras.swift │ └── UnsafeRawPointer+Extras.swift │ ├── HexDump.swift │ └── NumberSet.swift ├── Tests ├── BABABTests │ ├── BinaryInteger+ExtrasTests.swift │ ├── BitFieldTests.swift │ ├── BitmapAllocatorTests.swift │ ├── Bool+ExtrasTests.swift │ ├── ByteArrayTests.swift │ ├── FixedWidthInteger+ExtrasTests.swift │ ├── HexDumpTests.swift │ ├── NumberSetTests.swift │ └── XCTestManifests.swift └── LinuxMain.swift ├── docs.sh ├── docs ├── Extensions.html ├── Extensions │ ├── BinaryInteger.html │ ├── Bool.html │ ├── FixedWidthInteger.html │ ├── UnsafeMutableRawPointer.html │ └── UnsafeRawPointer.html ├── Functions.html ├── Structs.html ├── Structs │ ├── BitField.html │ ├── BitmapAllocator.html │ ├── ByteArray.html │ ├── ByteArrayIterator.html │ ├── DoubleBitmapAllocator.html │ ├── NumberSet.html │ └── NumberSetIterator.html ├── Typealiases.html ├── badge.svg ├── css │ ├── highlight.css │ └── jazzy.css ├── img │ ├── carat.png │ ├── dash.png │ ├── gh.png │ └── spinner.gif ├── index.html ├── js │ ├── jazzy.js │ ├── jazzy.search.js │ ├── jquery.min.js │ ├── lunr.min.js │ └── typeahead.jquery.js ├── search.json └── undocumented.json └── test.sh /.dockerignore: -------------------------------------------------------------------------------- 1 | DerivedData 2 | .* 3 | -------------------------------------------------------------------------------- /.github/workflows/linuxtest.yml: -------------------------------------------------------------------------------- 1 | name: TestLinux 2 | on: [push] 3 | jobs: 4 | build: 5 | name: Swift Linux ${{matrix.swift}} 6 | strategy: 7 | matrix: 8 | swift: ["5.2", "5.3", "5.4", "5.5", "latest"] 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v1 12 | - name: Run tests 13 | run: docker run --rm -v `pwd`:/babab/${{matrix.swift}} -w /babab/${{matrix.swift}} -t swift:${{matrix.swift}} swift test 14 | -------------------------------------------------------------------------------- /.github/workflows/macostest.yml: -------------------------------------------------------------------------------- 1 | name: TestMacos 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: macOS-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v1 12 | - name: Build 13 | run: swift build -c release 14 | - name: Run tests 15 | run: swift test -c release 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData 7 | .swiftpm 8 | Package.resolved 9 | *~ 10 | *.o 11 | \#* 12 | .\#* 13 | -------------------------------------------------------------------------------- /.swift-format: -------------------------------------------------------------------------------- 1 | { 2 | "fileScopedDeclarationPrivacy" : { 3 | "accessLevel" : "private" 4 | }, 5 | "indentation" : { 6 | "spaces" : 4 7 | }, 8 | "indentConditionalCompilationBlocks" : true, 9 | "indentSwitchCaseLabels" : true, 10 | "lineBreakAroundMultilineExpressionChainComponents" : false, 11 | "lineBreakBeforeControlFlowKeywords" : false, 12 | "lineBreakBeforeEachArgument" : false, 13 | "lineBreakBeforeEachGenericRequirement" : false, 14 | "lineLength" : 120, 15 | "maximumBlankLines" : 1, 16 | "prioritizeKeepingFunctionOutputTogether" : false, 17 | "respectsExistingLineBreaks" : true, 18 | "rules" : { 19 | "AllPublicDeclarationsHaveDocumentation" : false, 20 | "AlwaysUseLowerCamelCase" : true, 21 | "AmbiguousTrailingClosureOverload" : true, 22 | "BeginDocumentationCommentWithOneLineSummary" : true, 23 | "DoNotUseSemicolons" : true, 24 | "DontRepeatTypeInStaticProperties" : true, 25 | "FileScopedDeclarationPrivacy" : true, 26 | "FullyIndirectEnum" : true, 27 | "GroupNumericLiterals" : true, 28 | "IdentifiersMustBeASCII" : true, 29 | "NeverForceUnwrap" : false, 30 | "NeverUseForceTry" : false, 31 | "NeverUseImplicitlyUnwrappedOptionals" : false, 32 | "NoAccessLevelOnExtensionDeclaration" : true, 33 | "NoBlockComments" : true, 34 | "NoCasesWithOnlyFallthrough" : true, 35 | "NoEmptyTrailingClosureParentheses" : true, 36 | "NoLabelsInCasePatterns" : true, 37 | "NoLeadingUnderscores" : false, 38 | "NoParensAroundConditions" : true, 39 | "NoVoidReturnOnFunctionSignature" : true, 40 | "OneCasePerLine" : true, 41 | "OneVariableDeclarationPerLine" : true, 42 | "OnlyOneTrailingClosureArgument" : true, 43 | "OrderedImports" : true, 44 | "ReturnVoidInsteadOfEmptyTuple" : true, 45 | "UseLetInEveryBoundCaseVariable" : true, 46 | "UseShorthandTypeNames" : true, 47 | "UseSingleLinePropertyGetter" : true, 48 | "UseSynthesizedInitializer" : true, 49 | "UseTripleSlashForDocumentationComments" : true, 50 | "ValidateDocumentationComments" : false 51 | }, 52 | "tabWidth" : 8, 53 | "version" : 1 54 | } 55 | -------------------------------------------------------------------------------- /.swiftlint.yml: -------------------------------------------------------------------------------- 1 | vertical_whitespace: 2 | max_empty_lines: 2 3 | 4 | disabled_rules: 5 | - trailing_comma 6 | 7 | 8 | file_length: 9 | - 1000 10 | - 1300 11 | 12 | switch_case_alignment: 13 | indented_cases: true 14 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 0.0.2 4 | 5 | ### `BitField` 6 | - `BitArray` is now named `BitField` as it was never a real array, it was fixed witdth and composed of 7 | a fixed number of elements. 8 | 9 | - `BitField` - The `Element` accessed by the `subscript` [] is now a `Bool` instead of an `Int`. 10 | 11 | - The initialisers `init(_ rawValue: Int)` and `init(_ rawValue: UInt)` have been removed. 12 | 13 | ### `BinaryInteger` 14 | - Removed `hexNum()` method and add the following methods on `BinaryInteger`: 15 | `.binary(separator: Bool = false)` 16 | `.octal(separator: Bool = false)` 17 | `.hex(separator: Bool = false)` 18 | 19 | ### `NumberSet` 20 | - Added `NumberSet` to hold a `Set` of `UnsignedInteger` from value `0.. types. Treat UInt8/UInt16/UInt32/UInt64 as a field of bits. 9 | // 10 | 11 | /// A `BitArray` with 8 elements. 12 | @available(*, unavailable, renamed: "BitField8") 13 | public typealias BitArray8 = BitField 14 | 15 | /// A `BitArray` with 16 elements. 16 | @available(*, unavailable, renamed: "BitField16") 17 | public typealias BitArray16 = BitField 18 | 19 | /// A `BitArray` with 32 elements. 20 | @available(*, unavailable, renamed: "BitField32") 21 | public typealias BitArray32 = BitField 22 | 23 | /// A `BitArray` with 64 elements. 24 | @available(*, unavailable, renamed: "BitField64") 25 | public typealias BitArray64 = BitField 26 | 27 | @available(*, unavailable, renamed: "BitField") 28 | public typealias BitArray = BitField where T: FixedWidthInteger & UnsignedInteger 29 | 30 | /// A `BitField` with 8 elements. 31 | public typealias BitField8 = BitField 32 | 33 | /// A `BitField` with 16 elements. 34 | public typealias BitField16 = BitField 35 | 36 | /// A `BitField` with 32 elements. 37 | public typealias BitField32 = BitField 38 | 39 | /// A `BitField` with 64 elements. 40 | public typealias BitField64 = BitField 41 | 42 | 43 | 44 | /// A type that uses a fixed width, unsigned integer as storage for an array of bits. The number of bits is fixed and by 45 | /// default are set to zero. 46 | /// ``` 47 | /// Using fixed width arrays of bits can be used to implement bitfield like data structures. 48 | /// As an example, consider an 8-bit value that represents the following data 49 | /// 50 | /// +---------+---------+-------+-------+ 51 | /// | b7:4 | b2:3 | b1 | b0 | 52 | /// | Value 2 | Value 1 | Flag2 | Flag1 | 53 | /// +---------+---------+-------+-------+ 54 | /// 55 | /// struct Data { 56 | /// private var bits: BitField8 57 | /// 58 | /// var flag1: Bool { 59 | /// get { bits[0] } 60 | /// set { bits[0] = newValue } 61 | /// 62 | /// var flag2: Bool { bits[1] } 63 | /// 64 | /// var value1: Int { bits[2...3] } 65 | /// 66 | /// var value2: Int { 67 | /// get { bits[4...7] } 68 | /// set { buts[4...7] = newValue } 69 | /// } 70 | /// } 71 | /// ``` 72 | public struct BitField: RandomAccessCollection, MutableCollection, 73 | CustomStringConvertible { 74 | /// The `Index` type for a `BitField` is an `Int`. 75 | public typealias Index = Int 76 | /// The `Element` type for a `BitArry` is a `Bool` of value `true` or `false`. 77 | public typealias Element = Bool 78 | /// A sequence that represents a contiguous subrange of the collection’s elements. 79 | public typealias SubSequence = Self 80 | /// The underlying storage. 81 | public private(set) var rawValue: T 82 | 83 | /// The position of the first element in a nonempty array. Always zero. 84 | public var startIndex: Self.Index { 0 } 85 | /// The array’s “past the end” position—that is, the position one greater than the last valid subscript argument. 86 | /// This value is always equal to the `bitWidth` of the underlying storage. 87 | public var endIndex: Self.Index { rawValue.bitWidth } 88 | /// The number of elements in the array. This is fixed at the `bitWidth` of the underlying storage. 89 | public var count: Int { rawValue.bitWidth } 90 | 91 | /// Returns the position immediately before the given index. 92 | public func index(before index: Self.Index) -> Self.Index { 93 | return index - 1 94 | } 95 | 96 | /// Replaces the given index with its successor. 97 | public func index(after index: Self.Index) -> Self.Index { 98 | return index + 1 99 | } 100 | 101 | /// A textual representation of the array and its elements. 102 | public var description: String { 103 | rawValue.binary(separators: true) 104 | } 105 | 106 | /// Creates a new, empty array. All the elements are set to zero. 107 | public init() { 108 | rawValue = 0 109 | } 110 | 111 | /// Create a new array initialising the underlying storage to the supplied value. 112 | /// - parameter rawValue: The initial value to set the storage to. 113 | public init(_ rawValue: T) { 114 | self.rawValue = rawValue 115 | } 116 | 117 | /// Accesses the element at the specified position. 118 | /// - parameter index: The position of the element to access. `index` must be greater than or equal to startIndex 119 | /// and less than endIndex. 120 | /// - returns: The bit value of the element. 121 | /// - precondition: The index is in the valid range of `startIndex` up to but not including`endIndex`. 122 | public subscript(index: Index) -> Element { 123 | get { 124 | precondition(index >= startIndex) 125 | precondition(index < endIndex) 126 | 127 | return (rawValue & (T(1) << index) == 0) ? false : true 128 | } 129 | 130 | set(newValue) { 131 | precondition(index >= startIndex) 132 | precondition(index < endIndex) 133 | 134 | let mask: T = 1 << index 135 | if newValue { 136 | rawValue |= mask 137 | } else { 138 | rawValue &= ~mask 139 | } 140 | } 141 | } 142 | 143 | /// A subrange of the array's elements. 144 | /// ``` 145 | /// The result is a full-width array with the elements in the given range 146 | /// in the lowest bits of the returned array. 147 | /// If the original array 148 | /// 149 | /// let a = BitField16(0x0A50) // 0000101001010000 150 | /// let b = a[8..<16] // 0000000000001010 151 | /// 152 | /// ``` 153 | /// - parameter bounds: A range of integers. The bounds of the range must be valid indices of the array. 154 | /// - returns: A new array with the selected elements. 155 | /// - precondition: `bounds.lowerBound` >= 0. 156 | /// - precondition: `bounds.upperBound`<= The number of elements in the array. 157 | public subscript(bounds: Range) -> SubSequence { 158 | get { 159 | precondition(bounds.lowerBound >= startIndex) 160 | precondition(bounds.upperBound <= endIndex) 161 | 162 | let bitCount = bounds.upperBound - bounds.lowerBound 163 | guard bitCount > 0 else { return Self() } 164 | let mask = rawValue.maskFrom(bitCount: bitCount) 165 | let newRawValue = (self.rawValue >> bounds.lowerBound) & mask 166 | return Self(newRawValue) 167 | } 168 | set { 169 | precondition(bounds.lowerBound >= startIndex) 170 | precondition(bounds.upperBound <= endIndex) 171 | 172 | let bitCount = bounds.upperBound - bounds.lowerBound 173 | guard bitCount > 0 else { return } 174 | 175 | let mask = rawValue.maskFrom(bitCount: bitCount) 176 | let value = (newValue.rawValue & mask) << bounds.lowerBound 177 | self.rawValue &= ~(mask << bounds.lowerBound) 178 | self.rawValue |= value 179 | } 180 | } 181 | 182 | /// The integer value representing the array's elements. 183 | /// ``` 184 | /// The result is the integer value of the selected elements (bits) of the array. 185 | /// 186 | /// let a = BitField16(0x0A50) // 0000101001010000 187 | /// let b = a[8..<16] // b = 0xA 188 | /// print(b) // 10 189 | /// ``` 190 | /// - parameter bounds: A range of integers. The bounds of the range must be valid indices of the array. 191 | /// - returns: An integer representation of the selected elements. 192 | /// - precondition: `bounds.lowerBound` >= 0. 193 | /// - precondition: `bounds.upperBound`< The number of elements in the array. 194 | public subscript(bounds: ClosedRange) -> T { 195 | get { 196 | precondition(bounds.lowerBound >= startIndex) 197 | precondition(bounds.upperBound < endIndex) 198 | 199 | let bitCount = 1 + bounds.upperBound - bounds.lowerBound 200 | let mask = rawValue.maskFrom(bitCount: bitCount) 201 | return (self.rawValue >> bounds.lowerBound) & mask 202 | } 203 | set { 204 | precondition(bounds.lowerBound >= startIndex) 205 | precondition(bounds.upperBound < endIndex) 206 | 207 | let bitCount = 1 + bounds.upperBound - bounds.lowerBound 208 | guard bitCount > 0 else { return } 209 | 210 | let mask = rawValue.maskFrom(bitCount: bitCount) 211 | let value = (newValue & mask) << bounds.lowerBound 212 | self.rawValue &= ~(mask << bounds.lowerBound) 213 | self.rawValue |= value 214 | } 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /Sources/BABAB/BitmapAllocator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BitmapAllocator.swift 3 | // BABAB 4 | // 5 | // Created by Simon Evans on 03/11/2020. 6 | // Copyright © 2020 - 2021 Simon Evans. All rights reserved. 7 | // 8 | // Simple allocators that use a bitmap in a fixed width integer to store free/allocated blocks. 9 | // 10 | 11 | /// A type that allows for allocating and deallocating entries using an unsigned fixed width integer to hold the 12 | /// allocated entries. 13 | /// The entries are in the range of 0 to 2^(bitmap width). Thus an allocator with a `UInt8` bitmap will return entries 14 | /// in the range 0 - 255. 15 | protocol BitmapAllocatorProtocol { 16 | /// Returns the total number of entries that can be allocated. 17 | var entryCount: Int { get } 18 | /// Returns the number of entries that have not been allocated. 19 | var freeEntryCount: Int { get } 20 | /// Returns a Boolean value indicating whether the allocator has unallocated entries. 21 | var hasSpace: Bool { get } 22 | /// Returns the next free entry or `nil` if the allocator is full. 23 | mutating func allocate() -> Int? 24 | /// Frees the entry allowing it to be reused. 25 | mutating func free(entry: Int) 26 | } 27 | 28 | /// A bitmap allocatior with capacity for 8 items. 29 | public typealias BitmapAllocator8 = BitmapAllocator 30 | /// A bitmap allocatior with capacity for 16 items. 31 | public typealias BitmapAllocator16 = BitmapAllocator 32 | /// A bitmap allocatior with capacity for 32 items. 33 | public typealias BitmapAllocator32 = BitmapAllocator 34 | /// A bitmap allocatior with capacity for 64 items. 35 | public typealias BitmapAllocator64 = BitmapAllocator 36 | /// A bitmap allocatior with capacity for 128 items. 37 | public typealias BitmapAllocator128 = DoubleBitmapAllocator 38 | 39 | /// An allocator that uses an `UnsignedInteger` to store the allocated entries allowing upto `.bitWidth` entries to be 40 | /// allocated. 41 | public struct BitmapAllocator: 42 | BitmapAllocatorProtocol, CustomStringConvertible { 43 | private var bitmap: BitmapType // Bits 0: Allocated, 1: Free 44 | 45 | /// A textual description of the allocator. 46 | /// - returns: A zero padding binary representation of the bitmap. 47 | public var description: String { bitmap.binary() } 48 | /// - returns: The total number of entries that can be allocated. 49 | public var entryCount: Int { BitmapType.bitWidth } 50 | /// - returns: The number of entries that have not been allocated. 51 | public var freeEntryCount: Int { bitmap.nonzeroBitCount } 52 | /// - returns: A boolean value indicating whether the allocator has unallocated entries. 53 | public var hasSpace: Bool { bitmap != 0 } 54 | 55 | /// Creates a new, empty allocator. 56 | public init() { 57 | // Mark all the bits as free - set to 1 58 | bitmap = BitmapType.max 59 | } 60 | 61 | /// Allocate the next free entry. 62 | /// - returns: The next free entry or `nil` if the allocator is full. 63 | public mutating func allocate() -> Int? { 64 | let tzbc = bitmap.trailingZeroBitCount 65 | guard tzbc < entryCount else { return nil } 66 | bitmap &= ~BitmapType(1 << tzbc) 67 | return tzbc 68 | } 69 | 70 | /// Frees the entry allowing it to be reused. 71 | /// - parameter entry: The entry index to be freed. 72 | /// - precondition: The entry must be currently allocated. 73 | public mutating func free(entry: Int) { 74 | let bit: BitmapType = 1 << BitmapType(entry) 75 | precondition(bitmap & bit == 0) 76 | bitmap |= bit 77 | } 78 | } 79 | 80 | /// An allocator that uses 2 `UnsignedInteger`s to store the allocated entries allowing upto 2x `.bitWidth` entries to 81 | /// be allocated. 82 | public struct DoubleBitmapAllocator: 83 | BitmapAllocatorProtocol, CustomStringConvertible { 84 | private var bitmap0: BitmapType // Bits 0: Allocated, 1: Free 85 | private var bitmap1: BitmapType 86 | 87 | /// A textual description of the allocator. 88 | /// - returns: A zero padding binary representation of the bitmap. 89 | public var description: String { "\(bitmap1.binary())-\(bitmap0.binary())" } 90 | /// - returns: The total number of entries that can be allocated. 91 | public var entryCount: Int { 2 * BitmapType.bitWidth } 92 | /// - returns: The number of entries that have not been allocated. 93 | public var freeEntryCount: Int { bitmap0.nonzeroBitCount + bitmap1.nonzeroBitCount } 94 | /// - returns: A boolean value indicating whether the allocator has unallocated entries. 95 | public var hasSpace: Bool { bitmap0 != 0 || bitmap1 != 0 } 96 | 97 | /// Creates a new, empty allocator. 98 | public init() { 99 | // Set the bits to 1 to mark them as available 100 | bitmap0 = BitmapType.max 101 | bitmap1 = BitmapType.max 102 | } 103 | 104 | /// Allocate the next free entry. 105 | /// - returns: The next free entry or `nil` if the allocator is full. 106 | public mutating func allocate() -> Int? { 107 | let tzbc0 = bitmap0.trailingZeroBitCount 108 | if tzbc0 < BitmapType.bitWidth { 109 | bitmap0 &= ~(BitmapType(1 << tzbc0)) 110 | return tzbc0 111 | } 112 | 113 | let tzbc1 = bitmap1.trailingZeroBitCount 114 | if tzbc1 < BitmapType.bitWidth { 115 | bitmap1 &= ~(BitmapType(1 << tzbc1)) 116 | return tzbc1 + BitmapType.bitWidth 117 | } 118 | 119 | return nil 120 | } 121 | 122 | /// Frees the entry allowing it to be reused. 123 | /// - parameter entry: The entry index to be freed. 124 | /// - precondition: The entry must be currently allocated. 125 | public mutating func free(entry: Int) { 126 | if entry < BitmapType.bitWidth { 127 | let bit: BitmapType = 1 << BitmapType(entry) 128 | precondition(bitmap0 & bit == 0) 129 | bitmap0 |= bit 130 | } else { 131 | let bit: BitmapType = 1 << BitmapType(entry - BitmapType.bitWidth) 132 | precondition(bitmap1 & bit == 0) 133 | bitmap1 |= bit 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /Sources/BABAB/ByteArray.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ByteArray.swift 3 | // BABAB 4 | // 5 | // Created by Simon Evans on 23/06/2021. 6 | // Copyright © 2017 - 2021 Simon Evans. All rights reserved. 7 | // 8 | // ByteArray types. Treat UInt8/UInt16/UInt32/UInt64 as arrays of bytes. 9 | // 10 | 11 | public struct ByteArray { 12 | fileprivate(set) public var rawValue: T 13 | public var capacity: Int { (T.bitWidth / 8) - 1 } 14 | 15 | /// Creates a new, empty array. All the elements are set to zero. 16 | @inline(__always) 17 | public init() { 18 | rawValue = 0 19 | } 20 | 21 | @inline(__always) 22 | public init(rawValue: T) { 23 | self.rawValue = rawValue 24 | } 25 | } 26 | 27 | extension ByteArray: Sequence { 28 | public typealias Iterator = ByteArrayIterator 29 | public typealias Element = UInt8 30 | 31 | public func makeIterator() -> ByteArrayIterator { 32 | return ByteArrayIterator(array: self) 33 | } 34 | } 35 | 36 | extension ByteArray: MutableCollection { 37 | public typealias Index = Int 38 | 39 | /// The position of the first element in a nonempty array. Always zero. 40 | public var startIndex: Index { 0 } 41 | /// The array’s “past the end” position—that is, the position one greater than the last valid subscript argument. 42 | /// This value is always equal to the `bitWidth` of the underlying storage. 43 | public var endIndex: Index { Int(rawValue & 0xff) } 44 | /// The number of elements in the array. This is fixed at the `bitWidth` of the underlying storage. 45 | public var count: Int { Int(rawValue & 0xff) } 46 | 47 | /// Replaces the given index with its successor. 48 | public func index(after index: Index) -> Index { 49 | return index + 1 50 | } 51 | 52 | /// Accesses the element at the specified position. 53 | /// - parameter index: The position of the element to access. index must be greater than or equal to startIndex and 54 | /// less than endIndex. 55 | /// - returns: The bit value of the element. 56 | /// - precondition: The index is in the valid range of `startIndex` upto but not including`endIndex`. 57 | public subscript(index: Index) -> Element { 58 | get { 59 | precondition(index >= 0) 60 | precondition(index < count) 61 | 62 | let value = (rawValue >> T((index + 1) * 8)) & 0xff 63 | return Element(value) 64 | } 65 | 66 | set(newValue) { 67 | precondition(index >= 0) 68 | precondition(index < count) 69 | 70 | let shift = T((index + 1) * 8) 71 | rawValue |= (T(0xff) << shift) 72 | rawValue ^= T(~newValue) << shift 73 | } 74 | } 75 | 76 | mutating public func popFirst() -> Element? { 77 | guard count > 0 else { return nil } 78 | let newCount = count - 1 79 | rawValue >>= 8 80 | let element = UInt8(truncatingIfNeeded: rawValue) 81 | maskDataBits(newCount: newCount) 82 | return element 83 | } 84 | 85 | // Mask off the data bits, excluding the count bits with get set to 0, then set the 86 | // count to the new value. 87 | mutating fileprivate func maskDataBits(newCount: Int) { 88 | let mask = (rawValue.maskFrom(bitCount: newCount * 8) << 8) 89 | rawValue &= mask 90 | rawValue |= T(newCount) 91 | } 92 | 93 | mutating fileprivate func incrementCount() { 94 | rawValue += 1 95 | } 96 | } 97 | 98 | extension ByteArray: BidirectionalCollection { 99 | /// Returns the position immediately before the given index. 100 | public func index(before index: Index) -> Index { 101 | return index - 1 102 | } 103 | 104 | mutating public func popLast() -> Element? { 105 | guard count > 0 else { return nil } 106 | let newCount = count - 1 107 | let element = self[newCount] 108 | maskDataBits(newCount: newCount) 109 | return element 110 | } 111 | } 112 | 113 | extension ByteArray: RandomAccessCollection { 114 | 115 | } 116 | 117 | extension ByteArray: RangeReplaceableCollection { 118 | public typealias SubSequence = Self 119 | 120 | public init(_ sequence: __owned S) where S.Element == Element { 121 | var elementCount = 0 122 | rawValue = 0 123 | var value = sequence.reduce(into: T(0), { 124 | elementCount += 1 125 | guard elementCount <= capacity else { fatalError("Sequence contains too many elements") } 126 | $0 |= T($1) << (elementCount * 8) 127 | }) 128 | value |= T(elementCount) 129 | rawValue = value 130 | } 131 | 132 | public init(repeating: Element, count: Int) { 133 | rawValue = 0 134 | precondition(count <= capacity) 135 | var value = T(0) 136 | for _ in 0..(_ subrange: Range, with newElements: C) 151 | where C: Collection, C.Element == Element { 152 | let newCount = self.count + newElements.count - subrange.count 153 | precondition(newCount <= self.capacity) 154 | 155 | for _ in 0..) -> ByteArray { 162 | get { 163 | precondition(bounds.startIndex >= self.startIndex) 164 | precondition(bounds.endIndex <= self.endIndex) 165 | 166 | let newCount = bounds.count 167 | let mask = (rawValue.maskFrom(bitCount: newCount * 8) << 8) 168 | var result = rawValue >> (bounds.startIndex * 8) 169 | result &= mask 170 | result |= T(newCount) 171 | 172 | return ByteArray(rawValue: result) 173 | } 174 | 175 | set { 176 | replaceSubrange(bounds, with: newValue) 177 | } 178 | } 179 | 180 | mutating public func append(_ newElement: Element) { 181 | precondition(count < capacity) 182 | let index = count 183 | incrementCount() 184 | self[index] = newElement 185 | } 186 | 187 | mutating public func insert(_ newElement: Element, at index: Int) { 188 | precondition(index >= 0, "Index of element to add should be non-negative") 189 | precondition(index <= endIndex, "Array index is out of range") 190 | precondition(count < capacity, "Can't insert any more elements") 191 | 192 | let shift = T(index + 1) * 8 193 | 194 | let upperMask = (T.max << shift) 195 | let lowerMask = ~upperMask 196 | 197 | let lowerBits = rawValue & lowerMask 198 | let upperBits = ((rawValue & upperMask) << 8) 199 | 200 | rawValue = lowerBits | (T(newElement) << shift) | upperBits 201 | incrementCount() 202 | } 203 | 204 | mutating public func insert(contentsOf newElements: S, at idx: Index) where S: Collection, UInt8 == S.Element { 205 | var index = idx 206 | for element in newElements { 207 | self.insert(element, at: index) 208 | index = self.index(after: index) 209 | } 210 | } 211 | 212 | mutating public func removeAll() { 213 | rawValue = 0 214 | } 215 | 216 | mutating public func removeAll(keepingCapacity keepCapacity: Bool) { 217 | rawValue = 0 218 | } 219 | 220 | @discardableResult 221 | mutating public func removeFirst() -> UInt8 { 222 | precondition(count > 0, "No elements available to remove.") 223 | return popFirst()! 224 | } 225 | 226 | mutating public func removeFirst(_ elements: Int) { 227 | if elements == 0 { return } 228 | precondition(elements >= 0, "Number of elements to remove should be non-negative") 229 | precondition(elements <= count, "Can't remove more items from a collection than it has") 230 | let newCount = count - elements 231 | rawValue >>= (T(elements) * 8) 232 | maskDataBits(newCount: newCount) 233 | } 234 | 235 | @discardableResult 236 | mutating public func removeLast() -> Element { 237 | precondition(count > 0, "No elements available to remove.") 238 | return popLast()! 239 | } 240 | 241 | mutating public func removeLast(_ elements: Int) { 242 | if elements == 0 { return } 243 | precondition(elements >= 0, "Number of elements to remove should be non-negative") 244 | precondition(elements <= count, "Can't remove more items from a collection than it has") 245 | maskDataBits(newCount: count - elements) 246 | } 247 | 248 | @discardableResult 249 | mutating public func remove(at index: Int) -> Element { 250 | precondition(index >= 0, "Index of element to remove should be non-negative") 251 | precondition(index < count, "Can't remove more items from a collection than it has") 252 | 253 | let element = self[index] 254 | let shift = T(index + 1) * 8 255 | let upperMask = (T.max << shift) 256 | let lowerMask = ~upperMask 257 | 258 | let upperBits = (rawValue >> 8) & upperMask 259 | let lowerBits = rawValue & lowerMask 260 | 261 | rawValue = upperBits | lowerBits 262 | rawValue -= 1 263 | return element 264 | } 265 | } 266 | 267 | extension ByteArray: Equatable { 268 | static public func == (lhs: ByteArray, rhs: ByteArray) -> Bool { lhs.rawValue == rhs.rawValue } 269 | } 270 | 271 | extension ByteArray: CustomStringConvertible { 272 | public var description: String { 273 | return "[" + self.map { "\($0)" }.joined(separator: ", ") + "]" 274 | } 275 | } 276 | 277 | extension ByteArray: CustomDebugStringConvertible { 278 | public var debugDescription: String { rawValue.hex(separators: true) } 279 | } 280 | 281 | public struct ByteArrayIterator: IteratorProtocol { 282 | private var array: ByteArray 283 | public typealias Element = UInt8 284 | 285 | public init(array: ByteArray) { 286 | self.array = array 287 | } 288 | 289 | mutating public func next() -> Element? { 290 | return array.popFirst() 291 | } 292 | } 293 | -------------------------------------------------------------------------------- /Sources/BABAB/Extensions/BinaryInteger+Extras.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BinaryInteger+Extras.swift 3 | // BABAB 4 | // 5 | // Created by Simon Evans on 26/03/2021. 6 | // Copyright © 2021 Simon Evans. All rights reserved. 7 | // 8 | 9 | extension BinaryInteger { 10 | /// Creates a new Integer value from the given Boolean. 11 | /// - parameter value: A `Bool` used to initialise the value. 12 | public init(_ value: Bool) { 13 | self = value ? 1 : 0 14 | } 15 | 16 | /// Returns a `String` of the binary representation zero padded to the width of the value. 17 | /// 18 | /// The value passed is converted to its `String` representation using base-16 19 | /// and then zero padded upto the width of the parameter if necessary. A `UInt8` 20 | /// will be padded to 8 characters, a `UInt64` will be padded upto 64 characters. 21 | /// ``` 22 | /// UInt8(1).binary() // '00000001' 23 | /// UInt8(0x12).binary() // '00010011' 24 | /// UInt16(0x1234).binary() // '0001001000110100' 25 | /// ``` 26 | /// 27 | /// The `separator` flag determines if a `_` should be added between every 4 digits. 28 | /// ``` 29 | /// UInt8(1).binary(separator: true) // '0000_0001' 30 | /// UInt16(0x1234).binary(separator: true) // '0001_0010_0011_0100' 31 | /// ``` 32 | /// 33 | /// - parameter value: The numeric value to convert. 34 | /// - parameter separators: `Boolean` flag to control `_` added between every 4 digits. The default is `false`. 35 | /// - returns: The zero padded value as a `String`. 36 | public func binary(separators: Bool = false) -> String { 37 | var num = String(self, radix: 2) 38 | let width = self.bitWidth 39 | if num.count < width { 40 | num = String(repeating: "0", count: width - num.count) + num 41 | } 42 | return separators ? insertSeperators(string: num) : num 43 | } 44 | 45 | /// Returns a `String` of the octal representation zero padded to the width of the value. 46 | /// 47 | /// The value passed is converted to its `String` representation using base-8 48 | /// and then zero padded upto the width of the parameter if necessary. A `UInt8` 49 | /// will be padded to 3 characters, a `UInt64` will be padded upto 22 characters. 50 | /// ``` 51 | /// UInt8(1).octal() // '00000001' 52 | /// UInt8(0x12).octal() // '00010011' 53 | /// UInt16(0x1234).octal() // '0001001000110100' 54 | /// ``` 55 | /// 56 | /// The `separator` flag determines if a `_` should be added between every 4 digits. 57 | /// ``` 58 | /// UInt8(1).octal(separator: true) // '0000_0001' 59 | /// UInt16(0x1234).octal(separator: true) // '0001_0010_0011_0100' 60 | /// ``` 61 | /// 62 | /// - parameter value: The numeric value to convert. 63 | /// - parameter separators: `Boolean` flag to control `_` added between every 4 digits. The default is `false`. 64 | /// - returns: The zero padded value as a `String`. 65 | public func octal(separators: Bool = false) -> String { 66 | var num = String(self, radix: 8) 67 | let width = (self.bitWidth + 2) / 3 68 | if num.count < width { 69 | num = String(repeating: "0", count: width - num.count) + num 70 | } 71 | return separators ? insertSeperators(string: num) : num 72 | } 73 | 74 | /// Returns a `String` of the hexadecimal representation zero padded to the width of the value. 75 | /// 76 | /// The value passed is converted to its `String` representation using base-16 77 | /// and then zero padded upto the width of the parameter if necessary. A `UInt8` 78 | /// will be padded to 2 characters, a `UInt64` will be padded upto 16 characters. 79 | /// ``` 80 | /// UInt8(1).hex() // '01' 81 | /// UInt8(0x12).hex() // '12' 82 | /// UInt32(0x1234).hex() // '00001234' 83 | /// ``` 84 | /// 85 | /// The `separator` flag determines if a `_` should be added between every 4 digits. 86 | /// ``` 87 | /// UInt8(1).hex(separator: true) // '01' 88 | /// UInt32(0x1234).hex(separator: true) // '0000_1234' 89 | /// ``` 90 | /// 91 | /// - parameter value: The numeric value to convert. 92 | /// - parameter separators: `Boolean` flag to control `_` added between every 4 digits. The default is `false`. 93 | /// - returns: The zero padded value as a `String`. 94 | public func hex(separators: Bool = false) -> String { 95 | var num = String(self, radix: 16) 96 | let width = (self.bitWidth + 3) / 4 97 | if num.count < width { 98 | num = String(repeating: "0", count: width - num.count) + num 99 | } 100 | return separators ? insertSeperators(string: num) : num 101 | } 102 | } 103 | 104 | private func insertSeperators(string: String) -> String { 105 | let underscores = (string.count / 4) 106 | 107 | guard underscores > 0 else { return string } 108 | var result = string 109 | var position = 4 110 | for _ in 1...underscores { 111 | let index = result.index(result.endIndex, offsetBy: -position) 112 | if index > result.startIndex { 113 | result.insert(Character("_"), at: index) 114 | position += 5 115 | } 116 | } 117 | return result 118 | } 119 | -------------------------------------------------------------------------------- /Sources/BABAB/Extensions/Bool+Extras.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Bool.swift 3 | // BABAB 4 | // 5 | // Created by Simon Evans on 26/03/2021. 6 | // Copyright © 2021 Simon Evans. All rights reserved. 7 | // 8 | 9 | extension Bool { 10 | /// Creates a new Boolean value from the given Integer. 11 | /// - parameter value: An `Int` used to initialise the `Bool`. 12 | /// - precondition: `value` is equal to 0 or 1. 13 | public init(_ value: T) { 14 | precondition(value == 0 || value == 1) 15 | self = (value == 1) ? true : false 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Sources/BABAB/Extensions/FixedWidthInteger+Extras.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FixedWidthInteger+Extras.swift 3 | // BABAB 4 | // 5 | // Created by Simon Evans on 25/06/2021. 6 | // Copyright © 2021 Simon Evans. All rights reserved. 7 | // 8 | 9 | extension FixedWidthInteger { 10 | 11 | public func bit(_ index: Int) -> Bool { 12 | precondition(index >= 0 && index < self.bitWidth, "Bit must be in range 0-\(self.bitWidth)") 13 | let mask = Self(1 << Self(index)) 14 | return self & mask != 0 15 | } 16 | 17 | mutating public func bit(_ index: Int, _ newValue: Bool) { 18 | precondition(index >= 0 && index < self.bitWidth, "Bit must be in range 0-\(self.bitWidth)") 19 | let mask = Self(1 << Self(index)) 20 | if newValue { 21 | self |= mask 22 | } else { 23 | self &= ~mask 24 | } 25 | } 26 | 27 | @inlinable 28 | public var lowestBitSet: Int? { 29 | guard self != 0 else { return nil } 30 | return self.trailingZeroBitCount 31 | } 32 | 33 | @inlinable 34 | public var highestBitSet: Int? { 35 | guard self != 0 else { return nil } 36 | return (self.bitWidth - self.leadingZeroBitCount) - 1 37 | } 38 | 39 | @inlinable 40 | @discardableResult 41 | public mutating func clearLowestBitSet() -> Int? { 42 | guard let bit = lowestBitSet else { return nil } 43 | self.bit(bit, false) 44 | return bit 45 | } 46 | 47 | @inlinable 48 | @discardableResult 49 | public mutating func clearHighestBitSet() -> Int? { 50 | guard let bit = highestBitSet else { return nil } 51 | self.bit(bit, false) 52 | return bit 53 | } 54 | 55 | public init(littleEndianBytes: C) where C.Element == UInt8, C.Index == Int { 56 | let count = Self.bitWidth / 8 57 | precondition(littleEndianBytes.count >= count) 58 | 59 | var value = Self(0) 60 | var shift = 0 61 | for idx in littleEndianBytes.startIndex..<(littleEndianBytes.startIndex + count) { 62 | value |= Self(littleEndianBytes[idx]) << shift 63 | shift += 8 64 | } 65 | self = value 66 | } 67 | 68 | public init(bigEndianBytes: C) where C.Element == UInt8, C.Index == Int { 69 | let count = Self.bitWidth / 8 70 | precondition(bigEndianBytes.count >= count) 71 | 72 | var value = Self(0) 73 | for idx in bigEndianBytes.startIndex..<(bigEndianBytes.startIndex + count) { 74 | value <<= 8 75 | value |= Self(bigEndianBytes[idx]) 76 | } 77 | self = value 78 | } 79 | } 80 | 81 | extension FixedWidthInteger { 82 | public func maskFrom(bitCount: Int) -> Self { 83 | if bitCount == Self.bitWidth { 84 | return Self.max 85 | } else { 86 | return Self(1 << Self(bitCount)) - Self(1) 87 | } 88 | } 89 | } 90 | 91 | extension FixedWidthInteger where Self: UnsignedInteger { 92 | public init?(bcd: Self) { 93 | var bcd = bcd 94 | var value = Self(0) 95 | var multiplier = Self(1) 96 | let nibbles = Self.bitWidth / 4 97 | for _ in 1...nibbles { 98 | let nibble = bcd & 0xf 99 | guard nibble <= 9 else { return nil } 100 | bcd >>= 4 101 | value += (nibble * multiplier) 102 | multiplier *= 10 103 | } 104 | self = value 105 | } 106 | 107 | public var bcdValue: Self? { 108 | var value = self 109 | var shift = Self(0) 110 | var result = Self(0) 111 | 112 | while value > 0 { 113 | guard (Self.bitWidth - Int(shift)) >= 4 else { return nil } 114 | let nibble = value % 10 115 | result |= (nibble << shift) 116 | value /= 10 117 | shift += 4 118 | } 119 | return result 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /Sources/BABAB/Extensions/UnsafeRawPointer+Extras.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UnsafeRawPointer.swift 3 | // BABAB 4 | // 5 | // Created by Simon Evans on 26/03/2021. 6 | // Copyright © 2021 Simon Evans. All rights reserved. 7 | // 8 | 9 | #if os(Linux) 10 | import Glibc 11 | #elseif os(macOS) 12 | import Darwin 13 | #endif 14 | 15 | extension UnsafeRawPointer { 16 | /// Returns a new instance of the given type, constructed from the raw memory at the specified offset. 17 | /// The type to be loaded must be a trivial type. 18 | /// ``` 19 | /// The memory at this pointer plus offset does not need to be properly aligned for accessing T. 20 | /// It must be initialized to T or another type that is layout compatible with T. 21 | /// The returned instance is unassociated with the value in the memory referenced by this pointer. 22 | /// ``` 23 | /// - parameter offset: The offset from this pointer, in bytes. `offset`. The default is zero. 24 | /// - parameter type: The type of the instance to create. 25 | /// - returns: A new instance of type T, read from the raw bytes at offset. 26 | public func unalignedLoad(fromByteOffset offset: Int = 0, as type: T.Type) -> T { 27 | var value = T(0) 28 | memcpy(&value, self.advanced(by: offset), MemoryLayout.size) 29 | return value 30 | } 31 | } 32 | 33 | extension UnsafeMutableRawPointer { 34 | /// Stores a trivial type into raw memory at the specified offset. 35 | /// ``` 36 | /// The type T to be stored must be a trivial type. The memory must be uninitialized, initialized to T, 37 | /// or initialized to another trivial type that is layout compatible with T. 38 | /// ``` 39 | /// - parameter value: The value to store as raw bytes. 40 | /// - parameter offset: The offset from this pointer, in bytes. The default is zero. 41 | /// - parameter type: The type of value. 42 | public func unalignedStoreBytes(of value: T, toByteOffset offset: Int, as type: T.Type) { 43 | var value = value 44 | memcpy(self.advanced(by: offset), &value, MemoryLayout.size) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Sources/BABAB/HexDump.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HexDump.swift 3 | // BABAB 4 | // 5 | // Created by Simon Evans on 26/03/2021. 6 | // Copyright © 2021 Simon Evans. All rights reserved. 7 | // 8 | // Functions for hexDumps of collections and memory buffers. 9 | // 10 | 11 | private let bytesPerLine = 16 12 | 13 | public func hexDump( 14 | _ buffer: S, startAddress: A, showASCII: Bool = false 15 | ) -> String 16 | where S.Element == UInt8 { 17 | 18 | guard buffer.count > 0 else { return "" } 19 | let offset = Int(startAddress % A(bytesPerLine)) 20 | var address = startAddress - A(offset) 21 | var iterator = buffer.makeIterator() 22 | 23 | var output = "\(startAddress.hex()): " 24 | let firstLineCount = min(buffer.count, bytesPerLine - offset) 25 | dumpMemoryLine(&iterator, offset: offset, count: firstLineCount, into: &output, showASCII: showASCII) 26 | var totalBytes = buffer.count - firstLineCount 27 | output += "\n" 28 | address += A(bytesPerLine) 29 | 30 | while totalBytes > 0 { 31 | output += "\(address.hex()): " 32 | let count = min(totalBytes, bytesPerLine) 33 | dumpMemoryLine(&iterator, offset: 0, count: count, into: &output, showASCII: showASCII) 34 | totalBytes -= count 35 | output += "\n" 36 | address += A(bytesPerLine) 37 | } 38 | output.removeLast() // Remove trailing "\n" 39 | return output 40 | } 41 | 42 | public func hexDump(_ buffer: S, showASCII: Bool = false) -> String 43 | where S.Element == UInt8 { 44 | 45 | guard buffer.count > 0 else { return "" } 46 | var iterator = buffer.makeIterator() 47 | var totalBytes = buffer.count 48 | var output = "" 49 | 50 | while totalBytes > 0 { 51 | let count = min(totalBytes, bytesPerLine) 52 | dumpMemoryLine(&iterator, offset: 0, count: count, into: &output, showASCII: showASCII) 53 | output += "\n" 54 | totalBytes -= count 55 | } 56 | output.removeLast() // Remove trailing "\n" 57 | return output 58 | } 59 | 60 | private func dumpMemoryLine( 61 | _ buffer: inout I, offset: Int, count: Int, into line: inout String, showASCII: Bool 62 | ) 63 | where I.Element == UInt8 { 64 | 65 | precondition(1...bytesPerLine ~= count) 66 | var ascii = "" 67 | if offset > 0 { 68 | if showASCII { ascii = String(repeating: " ", count: offset) } 69 | line += String(repeating: " ", count: offset) 70 | } 71 | 72 | for position in offset..<(offset + count) { 73 | guard let byte = buffer.next() else { break } 74 | 75 | line += byte.hex() 76 | // Show '-' separator between columns 8 & 9 instead of a space 77 | if position == 7 && count > 1 { 78 | line += "-" 79 | } else { 80 | line += " " 81 | } 82 | 83 | if showASCII { 84 | let character = (byte >= 32 && byte < 127) ? Character(UnicodeScalar(byte)) : "." 85 | ascii.append(character) 86 | } 87 | } 88 | if showASCII { 89 | let remaining = bytesPerLine - (count + offset) 90 | if remaining > 0 { line += String(repeating: " ", count: remaining) } 91 | line.append(ascii) 92 | } else { 93 | line.removeLast() // Remove trailing " " 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /Sources/BABAB/NumberSet.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NumberSet.swift 3 | // BABAB 4 | // 5 | // Created by Simon Evans on 25/06/2021. 6 | // Copyright © 2021 Simon Evans. All rights reserved. 7 | // 8 | 9 | /// `NumberSet` uses a specified unsigned `FixedWidthInteger` as the storage for a Set containing the numbers 10 | /// 0...`bitWidth`. eg a `UInt8` can contain the numbers `0...7`, a `UInt64` can store `0...63`. 11 | /// The storage uses a bit per number where bit[`x`] is used to store `x`. This gives an ordering 12 | /// of the set from lowest to highest. 13 | /// The `rawValue` property represents the underlying storage and can be easily interpreted. 14 | /// ``` 15 | /// rawValue = 0b1001_0001 [0, 4, 7] 16 | /// ``` 17 | public struct NumberSet: SetAlgebra { 18 | /// The elements stored in the `NumberSet` are of type `Int`. 19 | public typealias Element = Int 20 | 21 | /// The underlying storage. Read only. 22 | private(set) public var rawValue: T 23 | /// A Boolean value that indicates whether the set is empty. 24 | public var isEmpty: Bool { rawValue == 0 } 25 | /// The number of elements in the set. 26 | public var count: Int { rawValue.nonzeroBitCount } 27 | /// The total number of elements that the set can contain without allocating new storage. 28 | public var capacity: Int { T.bitWidth } 29 | /// The first element of the collection. 30 | /// 31 | /// If the collection is empty, the value of this property is `nil`. 32 | public var first: Int? { rawValue.lowestBitSet } 33 | 34 | /// Creates an empty set. 35 | @inline(__always) 36 | public init() { 37 | self.rawValue = 0 38 | } 39 | 40 | /// Creates a new set from a finite sequence of items. 41 | /// - parameter sequence: The elements to use as members of the new set. 42 | public init(_ sequence: __owned S) where S.Element == Element { 43 | self.rawValue = sequence.reduce(into: T(0), { $0 |= T(1 << T($1)) }) 44 | } 45 | 46 | /// Create a new set from a literal value. 47 | /// 48 | /// Use this initialiser to create a new set. Member `x` corresponds to bit x. To create a set 49 | /// containing the numbers 1 and 5: 50 | /// ``` 51 | /// let numberSet = Set(rawValue: 0b0010_0010) 52 | /// print(numberSet) 53 | /// // prints [1, 5] 54 | /// ``` 55 | /// - parameter rawValue: A literal with the members of the new set represented by the appropaite bit being set. 56 | @inline(__always) 57 | public init(rawValue: T) { 58 | self.rawValue = rawValue 59 | } 60 | 61 | /// Inserts the given element in the set if it is not already present. 62 | /// 63 | /// - parameter newMember: An element to insert into the set. 64 | /// - returns: (true, newMember) if newMember was not contained in the set. If an element equal to 65 | /// newMember was already contained in the set, the method returns (false, oldMember), where oldMember 66 | /// is the element that was equal to newMember. 67 | /// In some cases, oldMember may be distinguishable from newMember by identity comparison or some other means. 68 | @discardableResult 69 | mutating public func insert(_ newMember: __owned Int) -> (inserted: Bool, memberAfterInsert: Int) { 70 | if rawValue.bit(newMember) { return (false, newMember) } 71 | 72 | rawValue.bit(newMember, true) 73 | return (true, newMember) 74 | } 75 | 76 | /// Inserts the given element into the set unconditionally. 77 | /// 78 | /// - parameter newMember: An element to insert into the set. 79 | /// - returns: An element equal to newMember if the set already contained such a member; otherwise, `nil`. 80 | /// In some cases, the returned element may be distinguishable from newMember by identity comparison or some 81 | /// other means. 82 | mutating public func update(with newMember: __owned Int) -> Int? { 83 | if rawValue.bit(newMember) { return newMember } 84 | 85 | rawValue.bit(newMember, true) 86 | return nil 87 | } 88 | 89 | /// Removes the specified element from the set. 90 | /// 91 | /// - parameter member: The element to remove from the set. 92 | /// - returns: The value of the member parameter if it was a member of the set; otherwise, `nil`. 93 | mutating public func remove(_ member: Int) -> Int? { 94 | guard rawValue.bit(member) else { return nil } 95 | rawValue.bit(member, false) 96 | return member 97 | } 98 | 99 | /// Removes the first element of the set. 100 | /// 101 | /// A `NumberSet` is not an ordered collection so the “first” element may is always the element with the lowest 102 | /// numeric value. The set must not be empty. 103 | /// Complexity: O(1). 104 | /// - returns: A member of the set. This memeber is the element with the lowest numeric value. 105 | @discardableResult 106 | mutating public func removeFirst() -> Int { 107 | return rawValue.clearLowestBitSet()! 108 | } 109 | 110 | /// Removes the element at the given index of the set. 111 | /// 112 | /// - parameter position: The index of the member to remove. position must be a valid index of the set, 113 | /// and must not be equal to the set’s end index. 114 | /// - returns: The element that was removed from the set. 115 | @discardableResult 116 | mutating public func remove(at position: Int) -> Int { 117 | precondition(position >= 0) 118 | precondition(position < T.bitWidth) 119 | var position = position 120 | for bitIndex in 0.. Bool { rawValue.bit(member) } 145 | 146 | /// Returns the minimum element in the sequence. 147 | /// - returns: The sequence’s minimum element. If the sequence has no elements, returns `nil`. 148 | @inline(__always) 149 | public func min() -> Int? { self.rawValue.lowestBitSet } 150 | 151 | /// Returns the maximum element in the sequence. 152 | /// - returns: The sequence’s maximum element. If the sequence has no elements, returns `nil`. 153 | @inline(__always) 154 | public func max() -> Int? { self.rawValue.highestBitSet } 155 | 156 | /// Returns a Boolean value that indicates whether this set has no members in common with the given set. 157 | /// 158 | /// - parameter other: Another `NumberSet` of the same type as the current `NumberSet`. 159 | /// - returns: `true` if the set has no elements in common with other; otherwise, `false`. 160 | @inline(__always) 161 | public func isDisjoint(with other: Self) -> Bool { 162 | return self.rawValue & other.rawValue == 0 163 | } 164 | 165 | /// Returns a new set containing the elements of this set that do not occur in the given set. 166 | /// 167 | /// - parameter other: Another `NumberSet` of the same type as the current `NumberSet`. 168 | /// - returns: A new set. 169 | @inline(__always) 170 | public func subtracting(_ other: Self) -> Self { 171 | return Self(rawValue: self.rawValue & ~other.rawValue) 172 | } 173 | 174 | /// Returns a new set with the elements of both this and the given set. 175 | /// 176 | /// - parameter other: Another `NumberSet` of the same type as the current `NumberSet`. 177 | /// - returns: A new set with the unique elements of this set and `other`. 178 | @inline(__always) 179 | __consuming public func union(_ other: __owned Self) -> Self { 180 | return Self(rawValue: self.rawValue | other.rawValue) 181 | } 182 | 183 | /// Returns a new set with the elements that are common to both this set and the given set. 184 | /// 185 | /// - parameter other: Another `NumberSet` of the same type as the current `NumberSet`. 186 | /// - returns: A new set. 187 | @inline(__always) 188 | __consuming public func intersection(_ other: Self) -> Self { 189 | return Self(rawValue: self.rawValue & other.rawValue) 190 | } 191 | 192 | /// Returns a new set with the elements that are either in this set or in the given set, but not in both. 193 | /// 194 | /// - parameter other: Another `NumberSet` of the same type as the current `NumberSet`. 195 | /// - returns: A new set. 196 | @inline(__always) 197 | __consuming public func symmetricDifference(_ other: __owned Self) -> Self { 198 | return Self(rawValue: self.rawValue ^ other.rawValue) 199 | } 200 | 201 | /// Removes the elements of the given set from this set. 202 | /// 203 | /// - parameter other: Another `NumberSet` of the same type as the current `NumberSet`. 204 | @inline(__always) 205 | mutating public func subtract(_ other: Self) { 206 | self.rawValue &= ~other.rawValue 207 | } 208 | 209 | /// Adds the elements of the given set to the set. 210 | /// 211 | /// - parameter other: Another `NumberSet` of the same type as the current `NumberSet`. 212 | @inline(__always) 213 | mutating public func formUnion(_ other: __owned Self) { 214 | self.rawValue |= other.rawValue 215 | } 216 | 217 | /// Inserts the elements of the given sequence into the set. 218 | /// 219 | /// - parameter other: A sequence of elements. `other` must be finite. 220 | public mutating func formUnion(_ other: S) where Element == S.Element, S: Sequence { 221 | self.rawValue |= other.reduce(into: T(0), { $0 |= T(1 << T($1)) }) 222 | } 223 | 224 | /// Removes the elements of this set that aren’t also in the given set. 225 | /// 226 | /// - parameter other: Another `NumberSet` of the same type as the current `NumberSet`. 227 | @inline(__always) 228 | mutating public func formIntersection(_ other: Self) { 229 | self.rawValue &= other.rawValue 230 | } 231 | 232 | /// Removes the elements of the set that are also in the given set and adds the members of the given set that are 233 | /// not already in the set. 234 | /// 235 | /// - parameter other: Another `NumberSet` of the same type as the current `NumberSet`. 236 | @inline(__always) 237 | mutating public func formSymmetricDifference(_ other: __owned Self) { 238 | self.rawValue ^= other.rawValue 239 | } 240 | } 241 | 242 | extension NumberSet { 243 | /// Returns a Boolean value indicating whether two sets have equal elements. 244 | /// - parameter lhs: A `NumberSet` 245 | /// - parameter rhs: Another `NumberSet` of the same type. 246 | /// - returns: `true` if the `lhs` and `rhs` have the same elements; otherwise, `false`. 247 | public static func == (lhs: Self, rhs: Self) -> Bool { 248 | lhs.rawValue == rhs.rawValue 249 | } 250 | } 251 | 252 | extension NumberSet: Sequence { 253 | /// Returns an iterator over the members of the set.. 254 | public func makeIterator() -> NumberSetIterator { 255 | return NumberSetIterator(rawValue: rawValue) 256 | } 257 | } 258 | 259 | extension NumberSet: CustomStringConvertible { 260 | /// A string that represents the contents of the set. 261 | public var description: String { 262 | return "[" + self.map { "\($0)" }.joined(separator: ", ") + "]" 263 | } 264 | } 265 | 266 | /// An `Iterator` that return the elements of a `NumberSet`. 267 | public struct NumberSetIterator: IteratorProtocol { 268 | private var rawValue: T 269 | /// The elements returned by the `NumberSetIterator` are of type `Int`. 270 | public typealias Element = Int 271 | 272 | /// Creates a new iterator from the specified value. 273 | /// 274 | /// - parameter rawValue: An unsigned `FixedWidhtInteger` with a bit represeting each element that will 275 | /// be returned by the iterator. 276 | public init(rawValue: T) { 277 | self.rawValue = rawValue 278 | } 279 | 280 | /// Advances to the next element and returns it, or `nil` if no next element exists. 281 | /// 282 | /// The next element returned is represented by the lowest bit that is set and is cleared before returning. 283 | /// Once all of the bits are clear then all subsequent calls return `nil`. 284 | public mutating func next() -> Element? { 285 | return rawValue.clearLowestBitSet() 286 | } 287 | } 288 | -------------------------------------------------------------------------------- /Tests/BABABTests/BinaryInteger+ExtrasTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BinaryInteger+ExtrasTests.swift 3 | // BABABTests 4 | // 5 | // Created by Simon Evans on 26/06/2021. 6 | // 7 | 8 | import BABAB 9 | import XCTest 10 | 11 | class BinaryIntegerExtrasTests: XCTestCase { 12 | func testInit() { 13 | XCTAssertEqual(Int(false), 0) 14 | XCTAssertEqual(UInt8(true), 1) 15 | } 16 | 17 | func testHex() { 18 | XCTAssertEqual(UInt8.min.hex(), "00") 19 | XCTAssertEqual(UInt8.max.hex(), "ff") 20 | XCTAssertEqual(UInt16.min.hex(), "0000") 21 | XCTAssertEqual(UInt16.max.hex(), "ffff") 22 | XCTAssertEqual(UInt32.min.hex(), "00000000") 23 | XCTAssertEqual(UInt32.max.hex(), "ffffffff") 24 | XCTAssertEqual(UInt64.min.hex(), "0000000000000000") 25 | XCTAssertEqual(UInt64.max.hex(), "ffffffffffffffff") 26 | XCTAssertEqual(UInt8.min.hex(separators: true), "00") 27 | XCTAssertEqual(UInt8.max.hex(separators: true), "ff") 28 | XCTAssertEqual(UInt16.min.hex(separators: true), "0000") 29 | XCTAssertEqual(UInt16.max.hex(separators: true), "ffff") 30 | XCTAssertEqual(UInt32.min.hex(separators: true), "0000_0000") 31 | XCTAssertEqual(UInt32.max.hex(separators: true), "ffff_ffff") 32 | XCTAssertEqual(UInt64.min.hex(separators: true), "0000_0000_0000_0000") 33 | XCTAssertEqual(UInt64.max.hex(separators: true), "ffff_ffff_ffff_ffff") 34 | } 35 | 36 | func testOctal() { 37 | XCTAssertEqual(UInt8.min.octal(), "000") 38 | XCTAssertEqual(UInt8.max.octal(), "377") 39 | XCTAssertEqual(UInt16.min.octal(), "000000") 40 | XCTAssertEqual(UInt16.max.octal(), "177777") 41 | XCTAssertEqual(UInt32.min.octal(), "00000000000") 42 | XCTAssertEqual(UInt32.max.octal(), "37777777777") 43 | XCTAssertEqual(UInt64.min.octal(), "0000000000000000000000") 44 | XCTAssertEqual(UInt64.max.octal(), "1777777777777777777777") 45 | XCTAssertEqual(UInt8.min.octal(separators: true), "000") 46 | XCTAssertEqual(UInt8.max.octal(separators: true), "377") 47 | XCTAssertEqual(UInt16.min.octal(separators: true), "00_0000") 48 | XCTAssertEqual(UInt16.max.octal(separators: true), "17_7777") 49 | XCTAssertEqual(UInt32.min.octal(separators: true), "000_0000_0000") 50 | XCTAssertEqual(UInt32.max.octal(separators: true), "377_7777_7777") 51 | XCTAssertEqual(UInt64.min.octal(separators: true), "00_0000_0000_0000_0000_0000") 52 | XCTAssertEqual(UInt64.max.octal(separators: true), "17_7777_7777_7777_7777_7777") 53 | } 54 | 55 | func testBinary() { 56 | XCTAssertEqual(UInt8.min.binary(), "00000000") 57 | XCTAssertEqual(UInt8.max.binary(), "11111111") 58 | XCTAssertEqual(UInt16.min.binary(), "0000000000000000") 59 | XCTAssertEqual(UInt16.max.binary(), "1111111111111111") 60 | XCTAssertEqual(UInt32.min.binary(), "00000000000000000000000000000000") 61 | XCTAssertEqual(UInt32.max.binary(), "11111111111111111111111111111111") 62 | XCTAssertEqual(UInt64.min.binary(), "0000000000000000000000000000000000000000000000000000000000000000") 63 | XCTAssertEqual(UInt64.max.binary(), "1111111111111111111111111111111111111111111111111111111111111111") 64 | XCTAssertEqual(UInt8.min.binary(separators: true), "0000_0000") 65 | XCTAssertEqual(UInt8.max.binary(separators: true), "1111_1111") 66 | XCTAssertEqual(UInt16.min.binary(separators: true), "0000_0000_0000_0000") 67 | XCTAssertEqual(UInt16.max.binary(separators: true), "1111_1111_1111_1111") 68 | XCTAssertEqual(UInt32.min.binary(separators: true), "0000_0000_0000_0000_0000_0000_0000_0000") 69 | XCTAssertEqual(UInt32.max.binary(separators: true), "1111_1111_1111_1111_1111_1111_1111_1111") 70 | XCTAssertEqual(UInt64.min.binary(separators: true), 71 | "0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000") 72 | XCTAssertEqual(UInt64.max.binary(separators: true), 73 | "1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111") 74 | } 75 | 76 | static var allTests = [ 77 | ("testInit", testInit), 78 | ("testHex", testHex), 79 | ("testOctal", testOctal), 80 | ("testBinary", testBinary), 81 | ] 82 | } 83 | -------------------------------------------------------------------------------- /Tests/BABABTests/BitFieldTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BitFieldTests.swift 3 | // BABABTests 4 | // 5 | // Created by Simon Evans on 27/03/2021. 6 | // 7 | 8 | import BABAB 9 | import XCTest 10 | 11 | final class BitFieldTests: XCTestCase { 12 | 13 | func testBitField() { 14 | var bitField = BitField8() 15 | XCTAssertEqual(bitField.startIndex, 0) 16 | XCTAssertEqual(bitField.endIndex, 8) 17 | XCTAssertEqual(bitField.count, 8) 18 | 19 | bitField = BitField(0) 20 | XCTAssertFalse(bitField[0]) 21 | XCTAssertFalse(bitField[7]) 22 | XCTAssertEqual(bitField.rawValue, 0) 23 | XCTAssertEqual(bitField.description, "0000_0000") 24 | 25 | bitField[0] = true 26 | bitField[7] = bitField[0] 27 | XCTAssertTrue(bitField[0]) 28 | XCTAssertTrue(bitField[7]) 29 | XCTAssertEqual(bitField.rawValue, 129) 30 | XCTAssertEqual("\(bitField)", "1000_0001") 31 | 32 | bitField = BitField8(UInt8(0)) 33 | var flag = false 34 | for idx in bitField.indices { 35 | bitField[idx] = flag 36 | flag.toggle() 37 | } 38 | 39 | XCTAssertEqual(bitField.rawValue, 0xAA) 40 | for (idx, element) in bitField.enumerated() { 41 | bitField[idx] = !element 42 | } 43 | XCTAssertEqual(bitField.rawValue, 0x55) 44 | bitField[0...3] = 0 45 | XCTAssertEqual(bitField.rawValue, 0x50) 46 | bitField[4...7] = ~(bitField[4...7]) 47 | XCTAssertEqual(bitField.rawValue, 0xA0) 48 | bitField[0...3] = bitField[4...7] 49 | XCTAssertEqual(bitField.rawValue, 0xAA) 50 | XCTAssertEqual("\(bitField)", "1010_1010") 51 | } 52 | 53 | func testSubSequence() { 54 | var allBitsSet = BitField16(UInt16.max) 55 | XCTAssertEqual(allBitsSet[0..<0].rawValue, 0) 56 | XCTAssertEqual(allBitsSet[0..<16].rawValue, UInt16.max) 57 | XCTAssertEqual(allBitsSet[0..<8].rawValue, 0xff) 58 | XCTAssertEqual(allBitsSet[8..<16].rawValue, 0xff) 59 | 60 | allBitsSet[0..<8] = BitField16(0x5555) 61 | XCTAssertEqual(allBitsSet.rawValue, 0xff55) 62 | allBitsSet[8..<16] = BitField16(0xAA) 63 | XCTAssertEqual(allBitsSet.rawValue, 0xAA55) 64 | } 65 | 66 | static var allTests = [ 67 | ("testBitField", testBitField), 68 | ("testSubSequence", testSubSequence), 69 | ] 70 | } 71 | -------------------------------------------------------------------------------- /Tests/BABABTests/BitmapAllocatorTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BitmapAllocatorTests.swift 3 | // BABABTests 4 | // 5 | // Created by Simon Evans on 27/03/2021. 6 | // 7 | 8 | import BABAB 9 | import XCTest 10 | 11 | final class BitmapAllocatorTests: XCTestCase { 12 | 13 | func testBitmapAllocator() { 14 | var allocator = BitmapAllocator() 15 | XCTAssertEqual(allocator.entryCount, 8) 16 | XCTAssertEqual(allocator.freeEntryCount, 8) 17 | XCTAssertEqual(allocator.hasSpace, true) 18 | XCTAssertEqual("\(allocator)", "11111111") 19 | 20 | XCTAssertEqual(allocator.allocate(), 0) 21 | XCTAssertEqual(allocator.allocate(), 1) 22 | XCTAssertEqual(allocator.allocate(), 2) 23 | XCTAssertEqual(allocator.freeEntryCount, 5) 24 | XCTAssertEqual("\(allocator)", "11111000") 25 | 26 | allocator.free(entry: 0) 27 | XCTAssertEqual(allocator.freeEntryCount, 6) 28 | XCTAssertEqual("\(allocator)", "11111001") 29 | 30 | for _ in 1...6 { 31 | XCTAssertNotNil(allocator.allocate()) 32 | } 33 | // All allocated now 34 | XCTAssertNil(allocator.allocate()) 35 | XCTAssertEqual(allocator.freeEntryCount, 0) 36 | XCTAssertEqual("\(allocator)", "00000000") 37 | } 38 | 39 | func testDoubleBitmapAllocator() { 40 | var allocator = DoubleBitmapAllocator() 41 | XCTAssertEqual(allocator.entryCount, 32) 42 | XCTAssertEqual(allocator.freeEntryCount, 32) 43 | XCTAssertEqual(allocator.hasSpace, true) 44 | XCTAssertEqual("\(allocator)", "1111111111111111-1111111111111111") 45 | 46 | XCTAssertEqual(allocator.allocate(), 0) 47 | XCTAssertEqual(allocator.allocate(), 1) 48 | XCTAssertEqual(allocator.allocate(), 2) 49 | XCTAssertEqual(allocator.freeEntryCount, 29) 50 | XCTAssertEqual("\(allocator)", "1111111111111111-1111111111111000") 51 | 52 | for _ in 1...16 { 53 | XCTAssertNotNil(allocator.allocate()) 54 | } 55 | XCTAssertEqual("\(allocator)", "1111111111111000-0000000000000000") 56 | XCTAssertEqual(allocator.freeEntryCount, 13) 57 | 58 | allocator.free(entry: 3) 59 | allocator.free(entry: 12) 60 | XCTAssertEqual("\(allocator)", "1111111111111000-0001000000001000") 61 | XCTAssertEqual(allocator.freeEntryCount, 15) 62 | 63 | for _ in 1...15 { 64 | XCTAssertNotNil(allocator.allocate()) 65 | } 66 | // All allocated now 67 | XCTAssertNil(allocator.allocate()) 68 | XCTAssertEqual(allocator.freeEntryCount, 0) 69 | XCTAssertEqual("\(allocator)", "0000000000000000-0000000000000000") 70 | XCTAssertFalse(allocator.hasSpace) 71 | 72 | allocator.free(entry: 30) 73 | XCTAssertEqual("\(allocator)", "0100000000000000-0000000000000000") 74 | XCTAssertTrue(allocator.hasSpace) 75 | } 76 | 77 | static var allTests = [ 78 | ("testBitmapAllocator", testBitmapAllocator), 79 | ("testDoubleBitmapAllocator", testDoubleBitmapAllocator), 80 | ] 81 | } 82 | -------------------------------------------------------------------------------- /Tests/BABABTests/Bool+ExtrasTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Bool+ExtrasTests.swift 3 | // BABABTests 4 | // 5 | // Created by Simon Evans on 26/06/2021. 6 | // Copyright © 2021 Simon Evans. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class BoolExtrasTests: XCTestCase { 12 | 13 | func testInit() { 14 | XCTAssertTrue(Bool(1)) 15 | XCTAssertFalse(Bool(0)) 16 | XCTAssertFalse(Bool(UInt.min)) 17 | } 18 | 19 | static var allTests = [ 20 | ("testInit", testInit), 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /Tests/BABABTests/ByteArrayTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ByteArrayTests.swift 3 | // BABABTests 4 | // 5 | // Created by Simon Evans on 26/06/2021. 6 | // Copyright © 2021 Simon Evans. All rights reserved. 7 | // 8 | 9 | import BABAB 10 | import XCTest 11 | 12 | class ByteArrayTests: XCTestCase { 13 | func testInit() { 14 | do { 15 | let array = ByteArray() 16 | XCTAssertEqual(array.capacity, 0) 17 | XCTAssertEqual(array.count, 0) 18 | XCTAssertEqual(array.rawValue, 0) 19 | } 20 | 21 | do { 22 | let array = ByteArray(repeating: 0x55, count: 0) 23 | XCTAssertEqual(array.capacity, 3) 24 | XCTAssertEqual(array.count, 0) 25 | XCTAssertEqual(array.rawValue, 0x0) 26 | } 27 | 28 | do { 29 | let array = ByteArray(repeating: 0x55, count: 2) 30 | XCTAssertEqual(array.count, 2) 31 | XCTAssertEqual(array.rawValue, 0x555502) 32 | } 33 | 34 | do { 35 | let array = ByteArray(rawValue: 0x0102_0303) 36 | XCTAssertEqual(array.count, 3) 37 | XCTAssertEqual(array.description, "[3, 2, 1]") 38 | } 39 | 40 | do { 41 | let array = ByteArray([]) 42 | XCTAssertEqual(array.count, 0) 43 | XCTAssertEqual(array.rawValue, 0) 44 | XCTAssertEqual(array.description, "[]") 45 | } 46 | 47 | do { 48 | let array = ByteArray([2, 4, 6, 8, 10]) 49 | XCTAssertEqual(array.count, 5) 50 | XCTAssertEqual(array.description, "[2, 4, 6, 8, 10]") 51 | } 52 | } 53 | 54 | func testCapacity() { 55 | do { 56 | var array = ByteArray([]) 57 | XCTAssertEqual(array.capacity, 0) 58 | array.reserveCapacity(0) 59 | array.removeAll(keepingCapacity: true) 60 | XCTAssertEqual(array.rawValue, 0) 61 | } 62 | do { 63 | var array = ByteArray([1]) 64 | XCTAssertEqual(array.capacity, 1) 65 | array.reserveCapacity(1) 66 | array.removeAll(keepingCapacity: false) 67 | XCTAssertEqual(array.rawValue, 0) 68 | } 69 | do { 70 | var array = ByteArray([2, 3]) 71 | XCTAssertEqual(array.capacity, 3) 72 | array.reserveCapacity(2) 73 | array.removeAll(keepingCapacity: true) 74 | XCTAssertEqual(array.rawValue, 0) 75 | } 76 | do { 77 | var array = ByteArray([0xA1, 0xB2, 0xC3]) 78 | XCTAssertEqual(array.capacity, 7) 79 | array.reserveCapacity(6) 80 | array.removeAll(keepingCapacity: false) 81 | XCTAssertEqual(array.rawValue, 0) 82 | } 83 | } 84 | 85 | func testEqual() { 86 | XCTAssertTrue(ByteArray() == ByteArray()) 87 | XCTAssertTrue(ByteArray() == ByteArray(rawValue: 0)) 88 | XCTAssertTrue(ByteArray() == ByteArray([])) 89 | XCTAssertTrue(ByteArray() == ByteArray(repeating: 0xFF, count: 0)) 90 | XCTAssertTrue(ByteArray([1]) == ByteArray(rawValue: 0x0101)) 91 | 92 | XCTAssertFalse(ByteArray() != ByteArray()) 93 | XCTAssertTrue(ByteArray() != ByteArray(rawValue: 0x0101)) 94 | XCTAssertTrue(ByteArray(repeating: 0x03, count: 1) != ByteArray([3, 4])) 95 | } 96 | 97 | func testSubscript() { 98 | var array = ByteArray([1, 2, 3, 4]) 99 | XCTAssertEqual(array[0], 1) 100 | XCTAssertEqual(array[3], 4) 101 | array[0] = 9 102 | XCTAssertEqual(array[0], 9) 103 | } 104 | 105 | func testAdding() { 106 | var array = ByteArray() 107 | array.append(1) 108 | array.append(3) 109 | array.append(5) 110 | XCTAssertEqual(array.description, "[1, 3, 5]") 111 | array.insert(2, at: 0) 112 | XCTAssertEqual(array.description, "[2, 1, 3, 5]") 113 | array.insert(8, at: 4) 114 | XCTAssertEqual(array.description, "[2, 1, 3, 5, 8]") 115 | 116 | array = ByteArray([1, 6]) 117 | array.insert(contentsOf: [7, 8, 9], at: 1) 118 | XCTAssertEqual(array.description, "[1, 7, 8, 9, 6]") 119 | } 120 | 121 | func testRemove() { 122 | var array = ByteArray([1, 2, 3, 4, 5, 6, 7]) 123 | XCTAssertEqual(array.description, "[1, 2, 3, 4, 5, 6, 7]") 124 | XCTAssertEqual(array.removeFirst(), 1) 125 | XCTAssertEqual(array.description, "[2, 3, 4, 5, 6, 7]") 126 | XCTAssertEqual(array.rawValue, 0x07_0605_0403_0206) 127 | 128 | XCTAssertEqual(array.removeFirst(), 2) 129 | XCTAssertEqual(array.description, "[3, 4, 5, 6, 7]") 130 | XCTAssertEqual(array.rawValue, 0x0706_0504_0305) 131 | 132 | array.removeFirst(3) 133 | XCTAssertEqual(array.count, 2) 134 | XCTAssertEqual(array.description, "[6, 7]") 135 | XCTAssertEqual(array.rawValue, 0x070602) 136 | 137 | array.removeAll() 138 | XCTAssertEqual(array.description, "[]") 139 | XCTAssertEqual(array.rawValue, 0) 140 | 141 | array = ByteArray([1, 2, 3, 4, 5, 6, 7]) 142 | XCTAssertEqual(array.removeLast(), 7) 143 | XCTAssertEqual(array.count, 6) 144 | XCTAssertEqual(array.rawValue, 0x06_0504_0302_0106) 145 | array.removeLast(4) 146 | XCTAssertEqual(array.count, 2) 147 | XCTAssertEqual(array.rawValue, 0x020102) 148 | XCTAssertEqual(array.removeLast(), 2) 149 | XCTAssertEqual(array.removeLast(), 1) 150 | XCTAssertEqual(array.count, 0) 151 | XCTAssertEqual(array.rawValue, 0) 152 | 153 | array = ByteArray([1, 2, 3, 4, 5, 6, 7]) 154 | XCTAssertEqual(array.remove(at: 0), 1) 155 | XCTAssertEqual(array.count, 6) 156 | XCTAssertEqual(array.description, "[2, 3, 4, 5, 6, 7]") 157 | XCTAssertEqual(array.rawValue, 0x07_0605_0403_0206) 158 | 159 | XCTAssertEqual(array.remove(at: 3), 5) 160 | XCTAssertEqual(array.count, 5) 161 | XCTAssertEqual(array.description, "[2, 3, 4, 6, 7]") 162 | XCTAssertEqual(array.rawValue, 0x0706_0403_0205) 163 | 164 | XCTAssertEqual(array.remove(at: 4), 7) 165 | XCTAssertEqual(array.count, 4) 166 | XCTAssertEqual(array.description, "[2, 3, 4, 6]") 167 | XCTAssertEqual(array.rawValue, 0x06_0403_0204) 168 | 169 | XCTAssertEqual(array.remove(at: array.index(before: array.endIndex)), 6) 170 | XCTAssertEqual(array.count, 3) 171 | XCTAssertEqual(array.description, "[2, 3, 4]") 172 | XCTAssertEqual(array.rawValue, 0x0403_0203) 173 | 174 | XCTAssertEqual(array.remove(at: array.index(after: array.startIndex)), 3) 175 | XCTAssertEqual(array.count, 2) 176 | XCTAssertEqual(array.description, "[2, 4]") 177 | XCTAssertEqual(array.rawValue, 0x040202) 178 | 179 | XCTAssertEqual(array.remove(at: array.startIndex), 2) 180 | XCTAssertEqual(array.count, 1) 181 | XCTAssertEqual(array.description, "[4]") 182 | XCTAssertEqual(array.rawValue, 0x0401) 183 | } 184 | 185 | func testPop() { 186 | var array = ByteArray([1, 2, 3, 4, 5, 6, 7]) 187 | XCTAssertEqual(array.popFirst(), 1) 188 | XCTAssertEqual(array.rawValue, 0x07_0605_0403_0206) 189 | XCTAssertEqual(array.popFirst(), 2) 190 | XCTAssertEqual(array.rawValue, 0x0706_0504_0305) 191 | XCTAssertEqual(array.popLast(), 7) 192 | XCTAssertEqual(array.rawValue, 0x06_0504_0304) 193 | XCTAssertEqual(array.popFirst(), 3) 194 | XCTAssertEqual(array.rawValue, 0x0605_0403) 195 | XCTAssertEqual(array.popLast(), 6) 196 | XCTAssertEqual(array.rawValue, 0x050402) 197 | XCTAssertEqual(array.popLast(), 5) 198 | XCTAssertEqual(array.rawValue, 0x0401) 199 | XCTAssertEqual(array.popFirst(), 4) 200 | XCTAssertEqual(array.rawValue, 0x0) 201 | XCTAssertNil(array.popFirst()) 202 | XCTAssertNil(array.popLast()) 203 | } 204 | 205 | func testSequence() { 206 | var baIterator = ByteArray([1, 2, 3]).makeIterator() 207 | 208 | XCTAssertEqual(baIterator.next(), 1) 209 | XCTAssertEqual(baIterator.next(), 2) 210 | XCTAssertEqual(baIterator.next(), 3) 211 | XCTAssertNil(baIterator.next()) 212 | XCTAssertNil(baIterator.next()) 213 | 214 | baIterator = ByteArray().makeIterator() 215 | XCTAssertNil(baIterator.next()) 216 | } 217 | 218 | 219 | func testRangeReplaceable() { 220 | typealias TestType = ByteArray 221 | var array = ByteArray([1, 2, 3, 4, 5, 6]) 222 | 223 | XCTAssertEqual(array[0...1].description, "[1, 2]") 224 | XCTAssertEqual(array[array.startIndex..? 124 | 40 41 42 43 44 45 46 47-48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO 125 | 50 51 52 53 54 55 56 57-58 59 5a 5b 5c 5d 5e 5f PQRSTUVWXYZ[\]^_ 126 | 60 61 62 63 64 65 66 67-68 69 6a 6b 6c 6d 6e 6f `abcdefghijklmno 127 | 70 71 72 73 74 75 76 77-78 79 7a 7b 7c 7d 7e 7f pqrstuvwxyz{|}~. 128 | 80 81 82 83 84 85 86 87-88 89 8a 8b 8c 8d 8e 8f ................ 129 | 90 91 92 93 94 95 96 97-98 99 9a 9b 9c 9d 9e 9f ................ 130 | a0 a1 a2 a3 a4 a5 a6 a7-a8 a9 aa ab ac ad ae af ................ 131 | b0 b1 b2 b3 b4 b5 b6 b7-b8 b9 ba bb bc bd be bf ................ 132 | c0 c1 c2 c3 c4 c5 c6 c7-c8 c9 ca cb cc cd ce cf ................ 133 | d0 d1 d2 d3 d4 d5 d6 d7-d8 d9 da db dc dd de df ................ 134 | e0 e1 e2 e3 e4 e5 e6 e7-e8 e9 ea eb ec ed ee ef ................ 135 | f0 f1 f2 f3 f4 f5 f6 f7-f8 f9 fa fb fc fd fe ff ................ 136 | """# 137 | XCTAssertEqual(hexDump(allBytes, showASCII: true), largeDump2) 138 | 139 | let largeDump3 = #""" 140 | 0000000000003039: 00 01 02 03 04 05 06 ....... 141 | 0000000000003040: 07 08 09 0a 0b 0c 0d 0e-0f 10 11 12 13 14 15 16 ................ 142 | 0000000000003050: 17 18 19 1a 1b 1c 1d 1e-1f 20 21 22 23 24 25 26 ......... !"#$%& 143 | 0000000000003060: 27 28 29 2a 2b 2c 2d 2e-2f 30 31 32 33 34 35 36 '()*+,-./0123456 144 | 0000000000003070: 37 38 39 3a 3b 3c 3d 3e-3f 40 41 42 43 44 45 46 789:;<=>?@ABCDEF 145 | 0000000000003080: 47 48 49 4a 4b 4c 4d 4e-4f 50 51 52 53 54 55 56 GHIJKLMNOPQRSTUV 146 | 0000000000003090: 57 58 59 5a 5b 5c 5d 5e-5f 60 61 62 63 64 65 66 WXYZ[\]^_`abcdef 147 | 00000000000030a0: 67 68 69 6a 6b 6c 6d 6e-6f 70 71 72 73 74 75 76 ghijklmnopqrstuv 148 | 00000000000030b0: 77 78 79 7a 7b 7c 7d 7e-7f 80 81 82 83 84 85 86 wxyz{|}~........ 149 | 00000000000030c0: 87 88 89 8a 8b 8c 8d 8e-8f 90 91 92 93 94 95 96 ................ 150 | 00000000000030d0: 97 98 99 9a 9b 9c 9d 9e-9f a0 a1 a2 a3 a4 a5 a6 ................ 151 | 00000000000030e0: a7 a8 a9 aa ab ac ad ae-af b0 b1 b2 b3 b4 b5 b6 ................ 152 | 00000000000030f0: b7 b8 b9 ba bb bc bd be-bf c0 c1 c2 c3 c4 c5 c6 ................ 153 | 0000000000003100: c7 c8 c9 ca cb cc cd ce-cf d0 d1 d2 d3 d4 d5 d6 ................ 154 | 0000000000003110: d7 d8 d9 da db dc dd de-df e0 e1 e2 e3 e4 e5 e6 ................ 155 | 0000000000003120: e7 e8 e9 ea eb ec ed ee-ef f0 f1 f2 f3 f4 f5 f6 ................ 156 | 0000000000003130: f7 f8 f9 fa fb fc fd fe-ff ......... 157 | """# 158 | XCTAssertEqual(hexDump(allBytes, startAddress: UInt(12345), showASCII: true), largeDump3) 159 | } 160 | 161 | func testColumnSeparator() { 162 | 163 | // Single byte, no separator 164 | let byte: [UInt8] = [0x30] 165 | XCTAssertEqual(hexDump(byte), "30") 166 | XCTAssertEqual(hexDump(byte, startAddress: UInt8(0)), "00: 30") 167 | XCTAssertEqual(hexDump(byte, startAddress: UInt8(6)), "06: 30") 168 | XCTAssertEqual(hexDump(byte, startAddress: UInt8(7)), "07: 30") 169 | XCTAssertEqual(hexDump(byte, startAddress: UInt8(8)), "08: 30") 170 | 171 | // Two bytes, separator between columns 7 & 8 172 | let bytes: [UInt8] = [0x30, 0x31] 173 | 174 | XCTAssertEqual(hexDump(bytes), "30 31") 175 | XCTAssertEqual(hexDump(bytes, startAddress: UInt8(0)), "00: 30 31") 176 | XCTAssertEqual(hexDump(bytes, startAddress: UInt8(6)), "06: 30 31") 177 | XCTAssertEqual(hexDump(bytes, startAddress: UInt8(7)), "07: 30-31") 178 | XCTAssertEqual(hexDump(bytes, startAddress: UInt8(8)), "08: 30 31") 179 | } 180 | 181 | static var allTests = [ 182 | ("testEmptyCollections", testEmptyCollections), 183 | ("testStartAddress", testStartAddress), 184 | ("testShowASCII", testShowASCII), 185 | ("testDumpMemory", testDumpMemory), 186 | ("testColumnSeparator", testColumnSeparator), 187 | ] 188 | } 189 | -------------------------------------------------------------------------------- /Tests/BABABTests/NumberSetTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NumberSetTests.swift 3 | // BABABTests 4 | // 5 | // Created by Simon Evans on 26/06/2021. 6 | // 7 | 8 | import BABAB 9 | import XCTest 10 | 11 | class NumberSetTests: XCTestCase { 12 | let set0 = NumberSet() 13 | let set1 = NumberSet([1, 2, 3]) 14 | let set2 = NumberSet([3, 4, 5]) 15 | let set3 = NumberSet([7, 8, 9]) 16 | let set4 = NumberSet([0, 1, 2, 3, 4, 5, 6]) 17 | let set5 = NumberSet([3]) 18 | let set6 = NumberSet([1, 2, 3, 4]) 19 | let setAll = NumberSet(rawValue: UInt16.max) 20 | 21 | func testInit() { 22 | var testSet = NumberSet() 23 | XCTAssertTrue(testSet.isEmpty) 24 | XCTAssertEqual(testSet.description, "[]") 25 | 26 | XCTAssertFalse(testSet.contains(0)) 27 | XCTAssertFalse(testSet.contains(7)) 28 | testSet.insert(0) 29 | testSet.insert(3) 30 | testSet.insert(6) 31 | XCTAssertTrue(testSet.contains(0)) 32 | XCTAssertFalse(testSet.contains(1)) 33 | XCTAssertEqual(testSet.rawValue, 0b0100_1001) 34 | XCTAssertEqual(testSet.description, "[0, 3, 6]") 35 | 36 | testSet = NumberSet(rawValue: 0b1010_1010) 37 | XCTAssertEqual(testSet.description, "[1, 3, 5, 7]") 38 | 39 | XCTAssertEqual(NumberSet([1, 3, 5, 7]).rawValue, 0b1010_1010) 40 | } 41 | 42 | func testProperties() { 43 | // .isEmpty 44 | XCTAssertTrue(self.set0.isEmpty) 45 | XCTAssertFalse(self.set1.isEmpty) 46 | 47 | // .count 48 | XCTAssertEqual(self.set0.count, 0) 49 | XCTAssertEqual(self.set1.count, 3) 50 | XCTAssertEqual(self.setAll.count, 16) 51 | 52 | // .capacity 53 | XCTAssertEqual(self.set0.capacity, 16) 54 | XCTAssertEqual(self.setAll.capacity, 16) 55 | 56 | // .first 57 | XCTAssertNil(self.set0.first) 58 | XCTAssertEqual(self.set1.first, 1) 59 | XCTAssertEqual(self.setAll.first, 0) 60 | 61 | // != 62 | XCTAssertNotEqual(self.set0, self.set1) 63 | XCTAssertNotEqual(self.set0, self.setAll) 64 | } 65 | 66 | func testMinMax() { 67 | XCTAssertNil(self.set0.min()) 68 | XCTAssertNil(self.set0.max()) 69 | 70 | XCTAssertEqual(self.set5.min(), 3) 71 | XCTAssertEqual(self.set5.max(), 3) 72 | 73 | XCTAssertEqual(self.setAll.min(), 0) 74 | XCTAssertEqual(self.setAll.max(), 15) 75 | } 76 | 77 | func testUpdates() { 78 | var testSet = NumberSet() 79 | 80 | // Insert '0', check before and after insert. 81 | XCTAssertFalse(testSet.contains(0)) 82 | var (inserted, afterInsert) = testSet.insert(0) 83 | XCTAssertTrue(inserted) 84 | XCTAssertTrue(testSet.contains(0)) 85 | XCTAssertEqual(afterInsert, 0) 86 | XCTAssertFalse(testSet.isEmpty) 87 | 88 | // Insert '0', check it was already inserted. 89 | (inserted, afterInsert) = testSet.insert(0) 90 | XCTAssertFalse(inserted) 91 | XCTAssertEqual(afterInsert, 0) 92 | XCTAssertTrue(testSet.contains(0)) 93 | 94 | // Check removal of non-existant member returns nil. 95 | XCTAssertFalse(testSet.contains(1)) 96 | XCTAssertNil(testSet.remove(1)) 97 | 98 | // Check removal of existing member returns the member. 99 | XCTAssertEqual(testSet.remove(0), 0) 100 | XCTAssertFalse(testSet.contains(0)) 101 | XCTAssertTrue(testSet.isEmpty) 102 | 103 | // Check removal of already removed member returns nil. 104 | XCTAssertNil(testSet.remove(0)) 105 | 106 | XCTAssertNil(testSet.update(with: 3)) 107 | XCTAssertEqual(testSet.update(with: 3), 3) 108 | } 109 | 110 | func testRemove() { 111 | do { 112 | var testSet = NumberSet([1, 2, 3]) 113 | XCTAssertFalse(testSet.isEmpty) 114 | testSet.removeAll() 115 | XCTAssertTrue(testSet.isEmpty) 116 | } 117 | 118 | do { 119 | var testSet = NumberSet([4, 9, 12, 3, 7, 5, 8, 15, 16]) 120 | XCTAssertEqual(testSet.removeFirst(), 3) 121 | XCTAssertEqual(testSet.removeFirst(), 4) 122 | XCTAssertEqual(testSet.removeFirst(), 5) 123 | XCTAssertEqual(testSet, [7, 8, 9, 12, 15, 16]) 124 | XCTAssertEqual(testSet.remove(at: 2), 9) 125 | XCTAssertEqual(testSet.remove(at: 0), 7) 126 | XCTAssertEqual(testSet.remove(at: 0), 8) 127 | XCTAssertEqual(testSet.remove(at: 1), 15) 128 | XCTAssertEqual(testSet.remove(at: 1), 16) 129 | XCTAssertEqual(testSet.removeFirst(), 12) 130 | } 131 | } 132 | 133 | func testUnion() { 134 | XCTAssertEqual(self.set1.union(self.set0), self.set1) 135 | XCTAssertEqual(self.set0.union(self.set1), self.set1) 136 | XCTAssertEqual(self.set1.union(self.setAll), self.setAll) 137 | XCTAssertEqual(self.set1.union(self.set2), [1, 2, 3, 4, 5]) 138 | XCTAssertEqual(self.set2.union(self.set3), [3, 4, 5, 7, 8, 9]) 139 | 140 | do { 141 | var set1Copy = self.set1 142 | set1Copy.formUnion(self.set0) 143 | XCTAssertEqual(set1Copy, self.set1) 144 | } 145 | 146 | do { 147 | var set0Copy = self.set0 148 | set0Copy.formUnion(self.set1) 149 | XCTAssertEqual(set0Copy, self.set1) 150 | } 151 | 152 | do { 153 | var set1Copy = self.set1 154 | set1Copy.formUnion(self.set2) 155 | XCTAssertEqual(set1Copy, [1, 2, 3, 4, 5]) 156 | } 157 | 158 | do { 159 | var set2Copy = self.set2 160 | set2Copy.formUnion(self.set3) 161 | XCTAssertEqual(set2Copy, [3, 4, 5, 7, 8, 9]) 162 | } 163 | 164 | do { 165 | var set2Copy = self.set2 166 | set2Copy.formUnion([]) 167 | XCTAssertEqual(set2Copy, set2) 168 | set2Copy.formUnion([7, 8, 9]) 169 | XCTAssertEqual(set2Copy, [3, 4, 5, 7, 8, 9]) 170 | } 171 | 172 | do { 173 | var set0Copy = self.set0 174 | set0Copy.formUnion([]) 175 | XCTAssertEqual(set0Copy, []) 176 | set0Copy.formUnion([0, 7, 15]) 177 | XCTAssertEqual(set0Copy, [0, 7, 15]) 178 | } 179 | } 180 | 181 | func testDisjoint() { 182 | XCTAssertTrue(self.set0.isDisjoint(with: self.set0)) 183 | XCTAssertFalse(self.set1.isDisjoint(with: self.set1)) 184 | XCTAssertFalse(self.set1.isDisjoint(with: self.set2)) 185 | XCTAssertTrue(self.set1.isDisjoint(with: self.set3)) 186 | } 187 | 188 | func testIntersection() { 189 | XCTAssertEqual(self.set0.intersection(self.set0), self.set0) 190 | XCTAssertEqual(self.set1.intersection(self.set1), self.set1) 191 | XCTAssertEqual(self.set1.intersection(self.set2), self.set5) 192 | XCTAssertEqual(self.set0.intersection(self.set1), self.set0) 193 | XCTAssertEqual(self.set1.intersection(self.set3), self.set0) 194 | 195 | do { 196 | var set0Copy = self.set0 197 | set0Copy.formIntersection(self.set0) 198 | XCTAssertEqual(set0Copy, self.set0) 199 | } 200 | do { 201 | var set1Copy = self.set1 202 | set1Copy.formIntersection(self.set1) 203 | XCTAssertEqual(set1Copy, self.set1) 204 | } 205 | do { 206 | var set1Copy = self.set1 207 | set1Copy.formIntersection(self.set2) 208 | XCTAssertEqual(set1Copy, self.set5) 209 | } 210 | do { 211 | var set0Copy = self.set0 212 | set0Copy.formIntersection(self.set1) 213 | XCTAssertEqual(set0Copy, self.set0) 214 | } 215 | do { 216 | var set1Copy = self.set1 217 | set1Copy.formIntersection(self.set3) 218 | XCTAssertEqual(set1Copy, self.set0) 219 | } 220 | } 221 | 222 | func testSubtract() { 223 | XCTAssertEqual(self.set0.subtracting(self.set0), self.set0) 224 | XCTAssertEqual(self.set1.subtracting(self.set1), self.set0) 225 | XCTAssertEqual(self.set1.subtracting(self.set0), self.set1) 226 | XCTAssertEqual(self.set1.subtracting(self.set2), [1, 2]) 227 | XCTAssertEqual(self.set2.subtracting(self.set1), [4, 5]) 228 | XCTAssertEqual(self.set4.subtracting(self.set1), [0, 4, 5, 6]) 229 | 230 | do { 231 | var set0Copy = self.set0 232 | set0Copy.subtract(self.set0) 233 | XCTAssertEqual(set0Copy, self.set0) 234 | } 235 | do { 236 | var set1Copy = self.set1 237 | set1Copy.subtract(self.set1) 238 | XCTAssertEqual(set1Copy, self.set0) 239 | } 240 | do { 241 | var set1Copy = self.set1 242 | set1Copy.subtract(self.set0) 243 | XCTAssertEqual(set1Copy, self.set1) 244 | } 245 | do { 246 | var set1Copy = self.set1 247 | set1Copy.subtract(self.set2) 248 | XCTAssertEqual(set1Copy, [1, 2]) 249 | } 250 | do { 251 | var set2Copy = self.set2 252 | set2Copy.subtract(self.set1) 253 | XCTAssertEqual(set2Copy, [4, 5]) 254 | } 255 | do { 256 | var set4Copy = self.set4 257 | set4Copy.subtract(self.set1) 258 | XCTAssertEqual(set4Copy, [0, 4, 5, 6]) 259 | } 260 | } 261 | 262 | func testSymmetricDifference() { 263 | XCTAssertEqual(self.set0.symmetricDifference(self.set0), self.set0) 264 | XCTAssertEqual(self.set0.symmetricDifference(self.set1), self.set1) 265 | XCTAssertEqual(self.set1.symmetricDifference(self.set2), [1, 2, 4, 5]) 266 | XCTAssertEqual(self.set1.symmetricDifference(self.set3), [1, 2, 3, 7, 8, 9]) 267 | XCTAssertEqual(self.set1.symmetricDifference(self.set6), [4]) 268 | 269 | do { 270 | var set0Copy = self.set0 271 | set0Copy.formSymmetricDifference(self.set0) 272 | XCTAssertEqual(set0Copy, self.set0) 273 | } 274 | do { 275 | var set0Copy = self.set0 276 | set0Copy.formSymmetricDifference(self.set1) 277 | XCTAssertEqual(set0Copy, self.set1) 278 | } 279 | do { 280 | var set1Copy = self.set1 281 | set1Copy.formSymmetricDifference(self.set2) 282 | XCTAssertEqual(set1Copy, [1, 2, 4, 5]) 283 | } 284 | do { 285 | var set1Copy = self.set1 286 | set1Copy.formSymmetricDifference(self.set3) 287 | XCTAssertEqual(set1Copy, [1, 2, 3, 7, 8, 9]) 288 | } 289 | do { 290 | var set1Copy = self.set1 291 | set1Copy.formSymmetricDifference(self.set6) 292 | XCTAssertEqual(set1Copy, [4]) 293 | } 294 | } 295 | 296 | func testNumberSetIterator() { 297 | do { 298 | var iterator = NumberSetIterator(rawValue: UInt(0)) 299 | XCTAssertNil(iterator.next()) 300 | XCTAssertNil(iterator.next()) 301 | } 302 | 303 | do { 304 | var iterator = NumberSetIterator(rawValue: UInt64(1 << 50) | UInt64(1)) 305 | XCTAssertEqual(iterator.next(), 0) 306 | XCTAssertEqual(iterator.next(), 50) 307 | XCTAssertNil(iterator.next()) 308 | } 309 | } 310 | 311 | static var allTests = [ 312 | ("testInit", testInit), 313 | ("testProperties", testProperties), 314 | ("testMinMax", testMinMax), 315 | ("testUpdates", testUpdates), 316 | ("testUnion", testUnion), 317 | ("testDisjoint", testDisjoint), 318 | ("testIntersection", testIntersection), 319 | ("testSubtract", testSubtract), 320 | ("testSymmetricDifference", testSymmetricDifference), 321 | ("testNumberSetIterator", testNumberSetIterator), 322 | ] 323 | } 324 | -------------------------------------------------------------------------------- /Tests/BABABTests/XCTestManifests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | #if !canImport(ObjectiveC) 4 | public func allTests() -> [XCTestCaseEntry] { 5 | return [ 6 | testCase(BitFieldTests.allTests), 7 | testCase(HexDumpTests.allTests), 8 | testCase(BitmapAllocatorTests.allTests), 9 | testCase(BinaryIntegerExtrasTests.allTests), 10 | testCase(BoolExtrasTests.allTests), 11 | testCase(FixedWidthIntegerExtrasTests.allTests), 12 | testCase(NumberSetTests.allTests), 13 | testCase(ByteArrayTests.allTests), 14 | ] 15 | } 16 | #endif 17 | -------------------------------------------------------------------------------- /Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | import BABABTests 2 | import XCTest 3 | 4 | var tests = [XCTestCaseEntry]() 5 | tests += BABABTests.allTests() 6 | XCTMain(tests) 7 | -------------------------------------------------------------------------------- /docs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | jazzy --clean --author "Simon Evans" --author_url https://github.com/spevans --github_url https://github.com/spevans/swift-babab --module BABAB --output docs 3 | rm -r docs/docsets 4 | -------------------------------------------------------------------------------- /docs/Extensions/Bool.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Bool Extension Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 |
20 |

BABAB Docs (79% documented)

21 |

View on GitHub

22 |

23 |

24 | 25 |
26 |

27 |
28 |
29 |
30 | 35 |
36 |
37 | 130 |
131 |
132 |
133 |

Bool

134 |
135 |
136 | 137 |
extension Bool
138 | 139 |
140 |
141 | 142 |
143 |
144 |
145 |
    146 |
  • 147 |
    148 | 149 | 150 | 151 | init(_:) 152 | 153 |
    154 |
    155 |
    156 |
    157 |
    158 |
    159 |

    Creates a new Boolean value from the given Integer.

    160 |
    161 |

    Precondition

    162 | value is equal to 0 or 1. 163 | 164 |
    165 | 166 |
    167 |
    168 |

    Declaration

    169 |
    170 |

    Swift

    171 |
    public init<T>(_ value: T) where T : BinaryInteger
    172 | 173 |
    174 |
    175 |
    176 |

    Parameters

    177 | 178 | 179 | 180 | 185 | 190 | 191 | 192 |
    181 | 182 | value 183 | 184 | 186 |
    187 |

    An Int used to initialise the Bool.

    188 |
    189 |
    193 |
    194 |
    195 |
    196 |
  • 197 |
198 |
199 |
200 |
201 | 205 |
206 |
207 | 208 | 209 | 210 | -------------------------------------------------------------------------------- /docs/Extensions/UnsafeMutableRawPointer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | UnsafeMutableRawPointer Extension Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 |
20 |

BABAB Docs (79% documented)

21 |

View on GitHub

22 |

23 |

24 | 25 |
26 |

27 |
28 |
29 |
30 | 35 |
36 |
37 | 130 |
131 |
132 |
133 |

UnsafeMutableRawPointer

134 |
135 |
136 | 137 |
extension UnsafeMutableRawPointer
138 | 139 |
140 |
141 | 142 |
143 |
144 |
145 |
    146 |
  • 147 |
    148 | 149 | 150 | 151 | unalignedStoreBytes(of:toByteOffset:as:) 152 | 153 |
    154 |
    155 |
    156 |
    157 |
    158 |
    159 |

    Stores a trivial type into raw memory at the specified offset.

    160 |
    The type T to be stored must be a trivial type. The memory must be uninitialized, initialized to T,
    161 | or initialized to another trivial type that is layout compatible with T.
    162 | 
    163 | 164 |
    165 |
    166 |

    Declaration

    167 |
    168 |

    Swift

    169 |
    public func unalignedStoreBytes<T>(of value: T, toByteOffset offset: Int, as type: T.Type)
    170 | 171 |
    172 |
    173 |
    174 |

    Parameters

    175 | 176 | 177 | 178 | 183 | 188 | 189 | 190 | 195 | 200 | 201 | 202 | 207 | 212 | 213 | 214 |
    179 | 180 | value 181 | 182 | 184 |
    185 |

    The value to store as raw bytes.

    186 |
    187 |
    191 | 192 | offset 193 | 194 | 196 |
    197 |

    The offset from this pointer, in bytes. The default is zero.

    198 |
    199 |
    203 | 204 | type 205 | 206 | 208 |
    209 |

    The type of value.

    210 |
    211 |
    215 |
    216 |
    217 |
    218 |
  • 219 |
220 |
221 |
222 |
223 | 227 |
228 |
229 | 230 | 231 | 232 | -------------------------------------------------------------------------------- /docs/Extensions/UnsafeRawPointer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | UnsafeRawPointer Extension Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 |
20 |

BABAB Docs (79% documented)

21 |

View on GitHub

22 |

23 |

24 | 25 |
26 |

27 |
28 |
29 |
30 | 35 |
36 |
37 | 130 |
131 |
132 |
133 |

UnsafeRawPointer

134 |
135 |
136 | 137 |
extension UnsafeRawPointer
138 | 139 |
140 |
141 | 142 |
143 |
144 |
145 |
    146 |
  • 147 |
    148 | 149 | 150 | 151 | unalignedLoad(fromByteOffset:as:) 152 | 153 |
    154 |
    155 |
    156 |
    157 |
    158 |
    159 |

    Returns a new instance of the given type, constructed from the raw memory at the specified offset. 160 | The type to be loaded must be a trivial type.

    161 |
    The memory at this pointer plus offset does not need to be properly aligned for accessing T.
    162 | It must be initialized to T or another type that is layout compatible with T.
    163 | The returned instance is unassociated  with the value in the memory referenced by this pointer.
    164 | 
    165 | 166 |
    167 |
    168 |

    Declaration

    169 |
    170 |

    Swift

    171 |
    public func unalignedLoad<T>(fromByteOffset offset: Int = 0, as type: T.Type) -> T where T : FixedWidthInteger
    172 | 173 |
    174 |
    175 |
    176 |

    Parameters

    177 | 178 | 179 | 180 | 185 | 190 | 191 | 192 | 197 | 202 | 203 | 204 |
    181 | 182 | offset 183 | 184 | 186 |
    187 |

    The offset from this pointer, in bytes. offset. The default is zero.

    188 |
    189 |
    193 | 194 | type 195 | 196 | 198 |
    199 |

    The type of the instance to create.

    200 |
    201 |
    205 |
    206 |
    207 |

    Return Value

    208 |

    A new instance of type T, read from the raw bytes at offset.

    209 |
    210 |
    211 |
    212 |
  • 213 |
214 |
215 |
216 |
217 | 221 |
222 |
223 | 224 | 225 | 226 | -------------------------------------------------------------------------------- /docs/Functions.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Functions Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 |
20 |

BABAB Docs (79% documented)

21 |

View on GitHub

22 |

23 |

24 | 25 |
26 |

27 |
28 |
29 |
30 | 35 |
36 |
37 | 130 |
131 |
132 |
133 |

Functions

134 |

The following functions are available globally.

135 | 136 |
137 |
138 |
139 |
    140 |
  • 141 |
    142 | 143 | 144 | 145 | hexDump(_:startAddress:showASCII:) 146 | 147 |
    148 |
    149 |
    150 |
    151 |
    152 |
    153 |

    Undocumented

    154 | 155 |
    156 |
    157 |

    Declaration

    158 |
    159 |

    Swift

    160 |
    public func hexDump<S: Sequence & Collection, A: FixedWidthInteger & UnsignedInteger>(
    161 |     _ buffer: S, startAddress: A, showASCII: Bool = false
    162 | ) -> String
    163 | where S.Element == UInt8
    164 | 165 |
    166 |
    167 |
    168 |
    169 |
  • 170 |
  • 171 |
    172 | 173 | 174 | 175 | hexDump(_:showASCII:) 176 | 177 |
    178 |
    179 |
    180 |
    181 |
    182 |
    183 |

    Undocumented

    184 | 185 |
    186 |
    187 |

    Declaration

    188 |
    189 |

    Swift

    190 |
    public func hexDump<S: Sequence & Collection>(_ buffer: S, showASCII: Bool = false) -> String
    191 | where S.Element == UInt8
    192 | 193 |
    194 |
    195 |
    196 |
    197 |
  • 198 |
199 |
200 |
201 |
202 | 206 |
207 |
208 | 209 | 210 | 211 | -------------------------------------------------------------------------------- /docs/Structs/ByteArrayIterator.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ByteArrayIterator Structure Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 |
20 |

BABAB Docs (79% documented)

21 |

View on GitHub

22 |

23 |

24 | 25 |
26 |

27 |
28 |
29 |
30 | 35 |
36 |
37 | 130 |
131 |
132 |
133 |

ByteArrayIterator

134 |
135 |
136 | 137 |
public struct ByteArrayIterator<T> : IteratorProtocol where T : FixedWidthInteger, T : UnsignedInteger
138 | 139 |
140 |
141 |

Undocumented

142 | 143 |
144 |
145 |
146 |
    147 |
  • 148 |
    149 | 150 | 151 | 152 | Element 153 | 154 |
    155 |
    156 |
    157 |
    158 |
    159 |
    160 | 161 |
    162 |
    163 |

    Declaration

    164 |
    165 |

    Swift

    166 |
    public typealias Element = UInt8
    167 | 168 |
    169 |
    170 |
    171 |
    172 |
  • 173 |
  • 174 |
    175 | 176 | 177 | 178 | init(array:) 179 | 180 |
    181 |
    182 |
    183 |
    184 |
    185 |
    186 |

    Undocumented

    187 | 188 |
    189 |
    190 |

    Declaration

    191 |
    192 |

    Swift

    193 |
    public init(array: ByteArray<T>)
    194 | 195 |
    196 |
    197 |
    198 |
    199 |
  • 200 |
  • 201 |
    202 | 203 | 204 | 205 | next() 206 | 207 |
    208 |
    209 |
    210 |
    211 |
    212 |
    213 | 214 |
    215 |
    216 |

    Declaration

    217 |
    218 |

    Swift

    219 |
    public mutating func next() -> Element?
    220 | 221 |
    222 |
    223 |
    224 |
    225 |
  • 226 |
227 |
228 |
229 |
230 | 234 |
235 |
236 | 237 | 238 | 239 | -------------------------------------------------------------------------------- /docs/badge.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | documentation 17 | 18 | 19 | documentation 20 | 21 | 22 | 79% 23 | 24 | 25 | 79% 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /docs/css/highlight.css: -------------------------------------------------------------------------------- 1 | /* Credit to https://gist.github.com/wataru420/2048287 */ 2 | .highlight { 3 | /* Comment */ 4 | /* Error */ 5 | /* Keyword */ 6 | /* Operator */ 7 | /* Comment.Multiline */ 8 | /* Comment.Preproc */ 9 | /* Comment.Single */ 10 | /* Comment.Special */ 11 | /* Generic.Deleted */ 12 | /* Generic.Deleted.Specific */ 13 | /* Generic.Emph */ 14 | /* Generic.Error */ 15 | /* Generic.Heading */ 16 | /* Generic.Inserted */ 17 | /* Generic.Inserted.Specific */ 18 | /* Generic.Output */ 19 | /* Generic.Prompt */ 20 | /* Generic.Strong */ 21 | /* Generic.Subheading */ 22 | /* Generic.Traceback */ 23 | /* Keyword.Constant */ 24 | /* Keyword.Declaration */ 25 | /* Keyword.Pseudo */ 26 | /* Keyword.Reserved */ 27 | /* Keyword.Type */ 28 | /* Literal.Number */ 29 | /* Literal.String */ 30 | /* Name.Attribute */ 31 | /* Name.Builtin */ 32 | /* Name.Class */ 33 | /* Name.Constant */ 34 | /* Name.Entity */ 35 | /* Name.Exception */ 36 | /* Name.Function */ 37 | /* Name.Namespace */ 38 | /* Name.Tag */ 39 | /* Name.Variable */ 40 | /* Operator.Word */ 41 | /* Text.Whitespace */ 42 | /* Literal.Number.Float */ 43 | /* Literal.Number.Hex */ 44 | /* Literal.Number.Integer */ 45 | /* Literal.Number.Oct */ 46 | /* Literal.String.Backtick */ 47 | /* Literal.String.Char */ 48 | /* Literal.String.Doc */ 49 | /* Literal.String.Double */ 50 | /* Literal.String.Escape */ 51 | /* Literal.String.Heredoc */ 52 | /* Literal.String.Interpol */ 53 | /* Literal.String.Other */ 54 | /* Literal.String.Regex */ 55 | /* Literal.String.Single */ 56 | /* Literal.String.Symbol */ 57 | /* Name.Builtin.Pseudo */ 58 | /* Name.Variable.Class */ 59 | /* Name.Variable.Global */ 60 | /* Name.Variable.Instance */ 61 | /* Literal.Number.Integer.Long */ } 62 | .highlight .c { 63 | color: #999988; 64 | font-style: italic; } 65 | .highlight .err { 66 | color: #a61717; 67 | background-color: #e3d2d2; } 68 | .highlight .k { 69 | color: #000000; 70 | font-weight: bold; } 71 | .highlight .o { 72 | color: #000000; 73 | font-weight: bold; } 74 | .highlight .cm { 75 | color: #999988; 76 | font-style: italic; } 77 | .highlight .cp { 78 | color: #999999; 79 | font-weight: bold; } 80 | .highlight .c1 { 81 | color: #999988; 82 | font-style: italic; } 83 | .highlight .cs { 84 | color: #999999; 85 | font-weight: bold; 86 | font-style: italic; } 87 | .highlight .gd { 88 | color: #000000; 89 | background-color: #ffdddd; } 90 | .highlight .gd .x { 91 | color: #000000; 92 | background-color: #ffaaaa; } 93 | .highlight .ge { 94 | color: #000000; 95 | font-style: italic; } 96 | .highlight .gr { 97 | color: #aa0000; } 98 | .highlight .gh { 99 | color: #999999; } 100 | .highlight .gi { 101 | color: #000000; 102 | background-color: #ddffdd; } 103 | .highlight .gi .x { 104 | color: #000000; 105 | background-color: #aaffaa; } 106 | .highlight .go { 107 | color: #888888; } 108 | .highlight .gp { 109 | color: #555555; } 110 | .highlight .gs { 111 | font-weight: bold; } 112 | .highlight .gu { 113 | color: #aaaaaa; } 114 | .highlight .gt { 115 | color: #aa0000; } 116 | .highlight .kc { 117 | color: #000000; 118 | font-weight: bold; } 119 | .highlight .kd { 120 | color: #000000; 121 | font-weight: bold; } 122 | .highlight .kp { 123 | color: #000000; 124 | font-weight: bold; } 125 | .highlight .kr { 126 | color: #000000; 127 | font-weight: bold; } 128 | .highlight .kt { 129 | color: #445588; } 130 | .highlight .m { 131 | color: #009999; } 132 | .highlight .s { 133 | color: #d14; } 134 | .highlight .na { 135 | color: #008080; } 136 | .highlight .nb { 137 | color: #0086B3; } 138 | .highlight .nc { 139 | color: #445588; 140 | font-weight: bold; } 141 | .highlight .no { 142 | color: #008080; } 143 | .highlight .ni { 144 | color: #800080; } 145 | .highlight .ne { 146 | color: #990000; 147 | font-weight: bold; } 148 | .highlight .nf { 149 | color: #990000; } 150 | .highlight .nn { 151 | color: #555555; } 152 | .highlight .nt { 153 | color: #000080; } 154 | .highlight .nv { 155 | color: #008080; } 156 | .highlight .ow { 157 | color: #000000; 158 | font-weight: bold; } 159 | .highlight .w { 160 | color: #bbbbbb; } 161 | .highlight .mf { 162 | color: #009999; } 163 | .highlight .mh { 164 | color: #009999; } 165 | .highlight .mi { 166 | color: #009999; } 167 | .highlight .mo { 168 | color: #009999; } 169 | .highlight .sb { 170 | color: #d14; } 171 | .highlight .sc { 172 | color: #d14; } 173 | .highlight .sd { 174 | color: #d14; } 175 | .highlight .s2 { 176 | color: #d14; } 177 | .highlight .se { 178 | color: #d14; } 179 | .highlight .sh { 180 | color: #d14; } 181 | .highlight .si { 182 | color: #d14; } 183 | .highlight .sx { 184 | color: #d14; } 185 | .highlight .sr { 186 | color: #009926; } 187 | .highlight .s1 { 188 | color: #d14; } 189 | .highlight .ss { 190 | color: #990073; } 191 | .highlight .bp { 192 | color: #999999; } 193 | .highlight .vc { 194 | color: #008080; } 195 | .highlight .vg { 196 | color: #008080; } 197 | .highlight .vi { 198 | color: #008080; } 199 | .highlight .il { 200 | color: #009999; } 201 | -------------------------------------------------------------------------------- /docs/css/jazzy.css: -------------------------------------------------------------------------------- 1 | html, body, div, span, h1, h3, h4, p, a, code, em, img, ul, li, table, tbody, tr, td { 2 | background: transparent; 3 | border: 0; 4 | margin: 0; 5 | outline: 0; 6 | padding: 0; 7 | vertical-align: baseline; } 8 | 9 | body { 10 | background-color: #f2f2f2; 11 | font-family: Helvetica, freesans, Arial, sans-serif; 12 | font-size: 14px; 13 | -webkit-font-smoothing: subpixel-antialiased; 14 | word-wrap: break-word; } 15 | 16 | h1, h2, h3 { 17 | margin-top: 0.8em; 18 | margin-bottom: 0.3em; 19 | font-weight: 100; 20 | color: black; } 21 | 22 | h1 { 23 | font-size: 2.5em; } 24 | 25 | h2 { 26 | font-size: 2em; 27 | border-bottom: 1px solid #e2e2e2; } 28 | 29 | h4 { 30 | font-size: 13px; 31 | line-height: 1.5; 32 | margin-top: 21px; } 33 | 34 | h5 { 35 | font-size: 1.1em; } 36 | 37 | h6 { 38 | font-size: 1.1em; 39 | color: #777; } 40 | 41 | .section-name { 42 | color: gray; 43 | display: block; 44 | font-family: Helvetica; 45 | font-size: 22px; 46 | font-weight: 100; 47 | margin-bottom: 15px; } 48 | 49 | pre, code { 50 | font: 0.95em Menlo, monospace; 51 | color: #777; 52 | word-wrap: normal; } 53 | 54 | p code, li code { 55 | background-color: #eee; 56 | padding: 2px 4px; 57 | border-radius: 4px; } 58 | 59 | pre > code { 60 | padding: 0; } 61 | 62 | a { 63 | color: #0088cc; 64 | text-decoration: none; } 65 | a code { 66 | color: inherit; } 67 | 68 | ul { 69 | padding-left: 15px; } 70 | 71 | li { 72 | line-height: 1.8em; } 73 | 74 | img { 75 | max-width: 100%; } 76 | 77 | blockquote { 78 | margin-left: 0; 79 | padding: 0 10px; 80 | border-left: 4px solid #ccc; } 81 | 82 | .content-wrapper { 83 | margin: 0 auto; 84 | width: 980px; } 85 | 86 | header { 87 | font-size: 0.85em; 88 | line-height: 32px; 89 | background-color: #414141; 90 | position: fixed; 91 | width: 100%; 92 | z-index: 3; } 93 | header img { 94 | padding-right: 6px; 95 | vertical-align: -4px; 96 | height: 16px; } 97 | header a { 98 | color: #fff; } 99 | header p { 100 | float: left; 101 | color: #999; } 102 | header .header-right { 103 | float: right; 104 | margin-left: 16px; } 105 | 106 | #breadcrumbs { 107 | background-color: #f2f2f2; 108 | height: 21px; 109 | padding-top: 17px; 110 | position: fixed; 111 | width: 100%; 112 | z-index: 2; 113 | margin-top: 32px; } 114 | #breadcrumbs #carat { 115 | height: 10px; 116 | margin: 0 5px; } 117 | 118 | .sidebar { 119 | background-color: #f9f9f9; 120 | border: 1px solid #e2e2e2; 121 | overflow-y: auto; 122 | overflow-x: hidden; 123 | position: fixed; 124 | top: 70px; 125 | bottom: 0; 126 | width: 230px; 127 | word-wrap: normal; } 128 | 129 | .nav-groups { 130 | list-style-type: none; 131 | background: #fff; 132 | padding-left: 0; } 133 | 134 | .nav-group-name { 135 | border-bottom: 1px solid #e2e2e2; 136 | font-size: 1.1em; 137 | font-weight: 100; 138 | padding: 15px 0 15px 20px; } 139 | .nav-group-name > a { 140 | color: #333; } 141 | 142 | .nav-group-tasks { 143 | margin-top: 5px; } 144 | 145 | .nav-group-task { 146 | font-size: 0.9em; 147 | list-style-type: none; 148 | white-space: nowrap; } 149 | .nav-group-task a { 150 | color: #888; } 151 | 152 | .main-content { 153 | background-color: #fff; 154 | border: 1px solid #e2e2e2; 155 | margin-left: 246px; 156 | position: absolute; 157 | overflow: hidden; 158 | padding-bottom: 20px; 159 | top: 70px; 160 | width: 734px; } 161 | .main-content p, .main-content a, .main-content code, .main-content em, .main-content ul, .main-content table, .main-content blockquote { 162 | margin-bottom: 1em; } 163 | .main-content p { 164 | line-height: 1.8em; } 165 | .main-content section .section:first-child { 166 | margin-top: 0; 167 | padding-top: 0; } 168 | .main-content section .task-group-section .task-group:first-of-type { 169 | padding-top: 10px; } 170 | .main-content section .task-group-section .task-group:first-of-type .section-name { 171 | padding-top: 15px; } 172 | .main-content section .heading:before { 173 | content: ""; 174 | display: block; 175 | padding-top: 70px; 176 | margin: -70px 0 0; } 177 | .main-content .section-name p { 178 | margin-bottom: inherit; 179 | line-height: inherit; } 180 | .main-content .section-name code { 181 | background-color: inherit; 182 | padding: inherit; 183 | color: inherit; } 184 | 185 | .section { 186 | padding: 0 25px; } 187 | 188 | .highlight { 189 | background-color: #eee; 190 | padding: 10px 12px; 191 | border: 1px solid #e2e2e2; 192 | border-radius: 4px; 193 | overflow-x: auto; } 194 | 195 | .declaration .highlight { 196 | overflow-x: initial; 197 | padding: 0 40px 40px 0; 198 | margin-bottom: -25px; 199 | background-color: transparent; 200 | border: none; } 201 | 202 | .section-name { 203 | margin: 0; 204 | margin-left: 18px; } 205 | 206 | .task-group-section { 207 | margin-top: 10px; 208 | padding-left: 6px; 209 | border-top: 1px solid #e2e2e2; } 210 | 211 | .task-group { 212 | padding-top: 0px; } 213 | 214 | .task-name-container a[name]:before { 215 | content: ""; 216 | display: block; 217 | padding-top: 70px; 218 | margin: -70px 0 0; } 219 | 220 | .section-name-container { 221 | position: relative; 222 | display: inline-block; } 223 | .section-name-container .section-name-link { 224 | position: absolute; 225 | top: 0; 226 | left: 0; 227 | bottom: 0; 228 | right: 0; 229 | margin-bottom: 0; } 230 | .section-name-container .section-name { 231 | position: relative; 232 | pointer-events: none; 233 | z-index: 1; } 234 | .section-name-container .section-name a { 235 | pointer-events: auto; } 236 | 237 | .item { 238 | padding-top: 8px; 239 | width: 100%; 240 | list-style-type: none; } 241 | .item a[name]:before { 242 | content: ""; 243 | display: block; 244 | padding-top: 70px; 245 | margin: -70px 0 0; } 246 | .item code { 247 | background-color: transparent; 248 | padding: 0; } 249 | .item .token, .item .direct-link { 250 | display: inline-block; 251 | text-indent: -20px; 252 | padding-left: 3px; 253 | margin-left: 35px; 254 | font-size: 11.9px; 255 | transition: all 300ms; } 256 | .item .token-open { 257 | margin-left: 20px; } 258 | .item .discouraged { 259 | text-decoration: line-through; } 260 | .item .declaration-note { 261 | font-size: .85em; 262 | color: gray; 263 | font-style: italic; } 264 | 265 | .pointer-container { 266 | border-bottom: 1px solid #e2e2e2; 267 | left: -23px; 268 | padding-bottom: 13px; 269 | position: relative; 270 | width: 110%; } 271 | 272 | .pointer { 273 | background: #f9f9f9; 274 | border-left: 1px solid #e2e2e2; 275 | border-top: 1px solid #e2e2e2; 276 | height: 12px; 277 | left: 21px; 278 | top: -7px; 279 | -webkit-transform: rotate(45deg); 280 | -moz-transform: rotate(45deg); 281 | -o-transform: rotate(45deg); 282 | transform: rotate(45deg); 283 | position: absolute; 284 | width: 12px; } 285 | 286 | .height-container { 287 | display: none; 288 | left: -25px; 289 | padding: 0 25px; 290 | position: relative; 291 | width: 100%; 292 | overflow: hidden; } 293 | .height-container .section { 294 | background: #f9f9f9; 295 | border-bottom: 1px solid #e2e2e2; 296 | left: -25px; 297 | position: relative; 298 | width: 100%; 299 | padding-top: 10px; 300 | padding-bottom: 5px; } 301 | 302 | .aside, .language { 303 | padding: 6px 12px; 304 | margin: 12px 0; 305 | border-left: 5px solid #dddddd; 306 | overflow-y: hidden; } 307 | .aside .aside-title, .language .aside-title { 308 | font-size: 9px; 309 | letter-spacing: 2px; 310 | text-transform: uppercase; 311 | padding-bottom: 0; 312 | margin: 0; 313 | color: #aaa; 314 | -webkit-user-select: none; } 315 | .aside p:last-child, .language p:last-child { 316 | margin-bottom: 0; } 317 | 318 | .language { 319 | border-left: 5px solid #cde9f4; } 320 | .language .aside-title { 321 | color: #4b8afb; } 322 | 323 | .aside-warning, .aside-deprecated, .aside-unavailable { 324 | border-left: 5px solid #ff6666; } 325 | .aside-warning .aside-title, .aside-deprecated .aside-title, .aside-unavailable .aside-title { 326 | color: #ff0000; } 327 | 328 | .graybox { 329 | border-collapse: collapse; 330 | width: 100%; } 331 | .graybox p { 332 | margin: 0; 333 | word-break: break-word; 334 | min-width: 50px; } 335 | .graybox td { 336 | border: 1px solid #e2e2e2; 337 | padding: 5px 25px 5px 10px; 338 | vertical-align: middle; } 339 | .graybox tr td:first-of-type { 340 | text-align: right; 341 | padding: 7px; 342 | vertical-align: top; 343 | word-break: normal; 344 | width: 40px; } 345 | 346 | .slightly-smaller { 347 | font-size: 0.9em; } 348 | 349 | #footer { 350 | position: relative; 351 | top: 10px; 352 | bottom: 0px; 353 | margin-left: 25px; } 354 | #footer p { 355 | margin: 0; 356 | color: #aaa; 357 | font-size: 0.8em; } 358 | 359 | html.dash header, html.dash #breadcrumbs, html.dash .sidebar { 360 | display: none; } 361 | 362 | html.dash .main-content { 363 | width: 980px; 364 | margin-left: 0; 365 | border: none; 366 | width: 100%; 367 | top: 0; 368 | padding-bottom: 0; } 369 | 370 | html.dash .height-container { 371 | display: block; } 372 | 373 | html.dash .item .token { 374 | margin-left: 0; } 375 | 376 | html.dash .content-wrapper { 377 | width: auto; } 378 | 379 | html.dash #footer { 380 | position: static; } 381 | 382 | form[role=search] { 383 | float: right; } 384 | form[role=search] input { 385 | font: Helvetica, freesans, Arial, sans-serif; 386 | margin-top: 6px; 387 | font-size: 13px; 388 | line-height: 20px; 389 | padding: 0px 10px; 390 | border: none; 391 | border-radius: 1em; } 392 | .loading form[role=search] input { 393 | background: white url(../img/spinner.gif) center right 4px no-repeat; } 394 | form[role=search] .tt-menu { 395 | margin: 0; 396 | min-width: 300px; 397 | background: #fff; 398 | color: #333; 399 | border: 1px solid #e2e2e2; 400 | z-index: 4; } 401 | form[role=search] .tt-highlight { 402 | font-weight: bold; } 403 | form[role=search] .tt-suggestion { 404 | font: Helvetica, freesans, Arial, sans-serif; 405 | font-size: 14px; 406 | padding: 0 8px; } 407 | form[role=search] .tt-suggestion span { 408 | display: table-cell; 409 | white-space: nowrap; } 410 | form[role=search] .tt-suggestion .doc-parent-name { 411 | width: 100%; 412 | text-align: right; 413 | font-weight: normal; 414 | font-size: 0.9em; 415 | padding-left: 16px; } 416 | form[role=search] .tt-suggestion:hover, 417 | form[role=search] .tt-suggestion.tt-cursor { 418 | cursor: pointer; 419 | background-color: #4183c4; 420 | color: #fff; } 421 | form[role=search] .tt-suggestion:hover .doc-parent-name, 422 | form[role=search] .tt-suggestion.tt-cursor .doc-parent-name { 423 | color: #fff; } 424 | -------------------------------------------------------------------------------- /docs/img/carat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-babab/bc19c7e368cd98ffb3a5c690d9a8ae1ff19a10fe/docs/img/carat.png -------------------------------------------------------------------------------- /docs/img/dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-babab/bc19c7e368cd98ffb3a5c690d9a8ae1ff19a10fe/docs/img/dash.png -------------------------------------------------------------------------------- /docs/img/gh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-babab/bc19c7e368cd98ffb3a5c690d9a8ae1ff19a10fe/docs/img/gh.png -------------------------------------------------------------------------------- /docs/img/spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-babab/bc19c7e368cd98ffb3a5c690d9a8ae1ff19a10fe/docs/img/spinner.gif -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | BABAB Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |
19 |

BABAB Docs (79% documented)

20 |

View on GitHub

21 |

22 |

23 | 24 |
25 |

26 |
27 |
28 |
29 | 34 |
35 |
36 | 129 |
130 |
131 |
132 | 133 |

swift-babab

134 | 135 |

Macos 136 | Linux

137 | 138 |

Buffers, Arrays, Bits and Bytes.

139 | 140 |

Miscellaneous types and functions for manipulatin bits and bytes, small arrays of bytes utilising FixedWidthInteger for non-heap storage and other random things.

141 | 142 |

API Documentation

143 | 144 |

BitArray

145 | 146 |

BitmapAllocator

147 | 148 |

ByteArray

149 | 150 |

ByteArrayItertor

151 | 152 |

DoubleBitmapAllocator

153 | 154 |

HexDump

155 | 156 |

NumberSet

157 | 158 |

NumberSetIterator

159 | 160 |
161 |
162 | 166 |
167 |
168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /docs/js/jazzy.js: -------------------------------------------------------------------------------- 1 | window.jazzy = {'docset': false} 2 | if (typeof window.dash != 'undefined') { 3 | document.documentElement.className += ' dash' 4 | window.jazzy.docset = true 5 | } 6 | if (navigator.userAgent.match(/xcode/i)) { 7 | document.documentElement.className += ' xcode' 8 | window.jazzy.docset = true 9 | } 10 | 11 | function toggleItem($link, $content) { 12 | var animationDuration = 300; 13 | $link.toggleClass('token-open'); 14 | $content.slideToggle(animationDuration); 15 | } 16 | 17 | function itemLinkToContent($link) { 18 | return $link.parent().parent().next(); 19 | } 20 | 21 | // On doc load + hash-change, open any targetted item 22 | function openCurrentItemIfClosed() { 23 | if (window.jazzy.docset) { 24 | return; 25 | } 26 | var $link = $(`a[name="${location.hash.substring(1)}"]`).nextAll('.token'); 27 | $content = itemLinkToContent($link); 28 | if ($content.is(':hidden')) { 29 | toggleItem($link, $content); 30 | } 31 | } 32 | 33 | $(openCurrentItemIfClosed); 34 | $(window).on('hashchange', openCurrentItemIfClosed); 35 | 36 | // On item link ('token') click, toggle its discussion 37 | $('.token').on('click', function(event) { 38 | if (window.jazzy.docset) { 39 | return; 40 | } 41 | var $link = $(this); 42 | toggleItem($link, itemLinkToContent($link)); 43 | 44 | // Keeps the document from jumping to the hash. 45 | var href = $link.attr('href'); 46 | if (history.pushState) { 47 | history.pushState({}, '', href); 48 | } else { 49 | location.hash = href; 50 | } 51 | event.preventDefault(); 52 | }); 53 | 54 | // Clicks on links to the current, closed, item need to open the item 55 | $("a:not('.token')").on('click', function() { 56 | if (location == this.href) { 57 | openCurrentItemIfClosed(); 58 | } 59 | }); 60 | 61 | // KaTeX rendering 62 | if ("katex" in window) { 63 | $($('.math').each( (_, element) => { 64 | katex.render(element.textContent, element, { 65 | displayMode: $(element).hasClass('m-block'), 66 | throwOnError: false, 67 | trust: true 68 | }); 69 | })) 70 | } 71 | -------------------------------------------------------------------------------- /docs/js/jazzy.search.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | var $typeahead = $('[data-typeahead]'); 3 | var $form = $typeahead.parents('form'); 4 | var searchURL = $form.attr('action'); 5 | 6 | function displayTemplate(result) { 7 | return result.name; 8 | } 9 | 10 | function suggestionTemplate(result) { 11 | var t = '
'; 12 | t += '' + result.name + ''; 13 | if (result.parent_name) { 14 | t += '' + result.parent_name + ''; 15 | } 16 | t += '
'; 17 | return t; 18 | } 19 | 20 | $typeahead.one('focus', function() { 21 | $form.addClass('loading'); 22 | 23 | $.getJSON(searchURL).then(function(searchData) { 24 | const searchIndex = lunr(function() { 25 | this.ref('url'); 26 | this.field('name'); 27 | this.field('abstract'); 28 | for (const [url, doc] of Object.entries(searchData)) { 29 | this.add({url: url, name: doc.name, abstract: doc.abstract}); 30 | } 31 | }); 32 | 33 | $typeahead.typeahead( 34 | { 35 | highlight: true, 36 | minLength: 3, 37 | autoselect: true 38 | }, 39 | { 40 | limit: 10, 41 | display: displayTemplate, 42 | templates: { suggestion: suggestionTemplate }, 43 | source: function(query, sync) { 44 | const lcSearch = query.toLowerCase(); 45 | const results = searchIndex.query(function(q) { 46 | q.term(lcSearch, { boost: 100 }); 47 | q.term(lcSearch, { 48 | boost: 10, 49 | wildcard: lunr.Query.wildcard.TRAILING 50 | }); 51 | }).map(function(result) { 52 | var doc = searchData[result.ref]; 53 | doc.url = result.ref; 54 | return doc; 55 | }); 56 | sync(results); 57 | } 58 | } 59 | ); 60 | $form.removeClass('loading'); 61 | $typeahead.trigger('focus'); 62 | }); 63 | }); 64 | 65 | var baseURL = searchURL.slice(0, -"search.json".length); 66 | 67 | $typeahead.on('typeahead:select', function(e, result) { 68 | window.location = baseURL + result.url; 69 | }); 70 | }); 71 | -------------------------------------------------------------------------------- /docs/undocumented.json: -------------------------------------------------------------------------------- 1 | { 2 | "warnings": [ 3 | { 4 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/ByteArray.swift", 5 | "line": 11, 6 | "symbol": "ByteArray", 7 | "symbol_kind": "source.lang.swift.decl.struct", 8 | "warning": "undocumented" 9 | }, 10 | { 11 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/ByteArray.swift", 12 | "line": 12, 13 | "symbol": "ByteArray.rawValue", 14 | "symbol_kind": "source.lang.swift.decl.var.instance", 15 | "warning": "undocumented" 16 | }, 17 | { 18 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/ByteArray.swift", 19 | "line": 13, 20 | "symbol": "ByteArray.capacity", 21 | "symbol_kind": "source.lang.swift.decl.var.instance", 22 | "warning": "undocumented" 23 | }, 24 | { 25 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/ByteArray.swift", 26 | "line": 22, 27 | "symbol": "ByteArray.init(rawValue:)", 28 | "symbol_kind": "source.lang.swift.decl.function.method.instance", 29 | "warning": "undocumented" 30 | }, 31 | { 32 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/ByteArray.swift", 33 | "line": 27, 34 | "symbol": "ByteArray", 35 | "symbol_kind": "source.lang.swift.decl.extension", 36 | "warning": "undocumented" 37 | }, 38 | { 39 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/ByteArray.swift", 40 | "line": 36, 41 | "symbol": "ByteArray", 42 | "symbol_kind": "source.lang.swift.decl.extension", 43 | "warning": "undocumented" 44 | }, 45 | { 46 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/ByteArray.swift", 47 | "line": 76, 48 | "symbol": "ByteArray.popFirst()", 49 | "symbol_kind": "source.lang.swift.decl.function.method.instance", 50 | "warning": "undocumented" 51 | }, 52 | { 53 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/ByteArray.swift", 54 | "line": 98, 55 | "symbol": "ByteArray", 56 | "symbol_kind": "source.lang.swift.decl.extension", 57 | "warning": "undocumented" 58 | }, 59 | { 60 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/ByteArray.swift", 61 | "line": 104, 62 | "symbol": "ByteArray.popLast()", 63 | "symbol_kind": "source.lang.swift.decl.function.method.instance", 64 | "warning": "undocumented" 65 | }, 66 | { 67 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/ByteArray.swift", 68 | "line": 113, 69 | "symbol": "ByteArray", 70 | "symbol_kind": "source.lang.swift.decl.extension", 71 | "warning": "undocumented" 72 | }, 73 | { 74 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/ByteArray.swift", 75 | "line": 117, 76 | "symbol": "ByteArray", 77 | "symbol_kind": "source.lang.swift.decl.extension", 78 | "warning": "undocumented" 79 | }, 80 | { 81 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/ByteArray.swift", 82 | "line": 212, 83 | "symbol": "ByteArray.removeAll()", 84 | "symbol_kind": "source.lang.swift.decl.function.method.instance", 85 | "warning": "undocumented" 86 | }, 87 | { 88 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/ByteArray.swift", 89 | "line": 236, 90 | "symbol": "ByteArray.removeLast()", 91 | "symbol_kind": "source.lang.swift.decl.function.method.instance", 92 | "warning": "undocumented" 93 | }, 94 | { 95 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/ByteArray.swift", 96 | "line": 241, 97 | "symbol": "ByteArray.removeLast(_:)", 98 | "symbol_kind": "source.lang.swift.decl.function.method.instance", 99 | "warning": "undocumented" 100 | }, 101 | { 102 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/ByteArray.swift", 103 | "line": 267, 104 | "symbol": "ByteArray", 105 | "symbol_kind": "source.lang.swift.decl.extension", 106 | "warning": "undocumented" 107 | }, 108 | { 109 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/ByteArray.swift", 110 | "line": 271, 111 | "symbol": "ByteArray", 112 | "symbol_kind": "source.lang.swift.decl.extension", 113 | "warning": "undocumented" 114 | }, 115 | { 116 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/ByteArray.swift", 117 | "line": 277, 118 | "symbol": "ByteArray", 119 | "symbol_kind": "source.lang.swift.decl.extension", 120 | "warning": "undocumented" 121 | }, 122 | { 123 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/ByteArray.swift", 124 | "line": 281, 125 | "symbol": "ByteArrayIterator", 126 | "symbol_kind": "source.lang.swift.decl.struct", 127 | "warning": "undocumented" 128 | }, 129 | { 130 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/ByteArray.swift", 131 | "line": 285, 132 | "symbol": "ByteArrayIterator.init(array:)", 133 | "symbol_kind": "source.lang.swift.decl.function.method.instance", 134 | "warning": "undocumented" 135 | }, 136 | { 137 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/Extensions/FixedWidthInteger+Extras.swift", 138 | "line": 11, 139 | "symbol": "FixedWidthInteger.bit(_:)", 140 | "symbol_kind": "source.lang.swift.decl.function.method.instance", 141 | "warning": "undocumented" 142 | }, 143 | { 144 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/Extensions/FixedWidthInteger+Extras.swift", 145 | "line": 17, 146 | "symbol": "FixedWidthInteger.bit(_:_:)", 147 | "symbol_kind": "source.lang.swift.decl.function.method.instance", 148 | "warning": "undocumented" 149 | }, 150 | { 151 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/Extensions/FixedWidthInteger+Extras.swift", 152 | "line": 28, 153 | "symbol": "FixedWidthInteger.lowestBitSet", 154 | "symbol_kind": "source.lang.swift.decl.var.instance", 155 | "warning": "undocumented" 156 | }, 157 | { 158 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/Extensions/FixedWidthInteger+Extras.swift", 159 | "line": 34, 160 | "symbol": "FixedWidthInteger.highestBitSet", 161 | "symbol_kind": "source.lang.swift.decl.var.instance", 162 | "warning": "undocumented" 163 | }, 164 | { 165 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/Extensions/FixedWidthInteger+Extras.swift", 166 | "line": 41, 167 | "symbol": "FixedWidthInteger.clearLowestBitSet()", 168 | "symbol_kind": "source.lang.swift.decl.function.method.instance", 169 | "warning": "undocumented" 170 | }, 171 | { 172 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/Extensions/FixedWidthInteger+Extras.swift", 173 | "line": 49, 174 | "symbol": "FixedWidthInteger.clearHighestBitSet()", 175 | "symbol_kind": "source.lang.swift.decl.function.method.instance", 176 | "warning": "undocumented" 177 | }, 178 | { 179 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/Extensions/FixedWidthInteger+Extras.swift", 180 | "line": 55, 181 | "symbol": "FixedWidthInteger.init(littleEndianBytes:)", 182 | "symbol_kind": "source.lang.swift.decl.function.method.instance", 183 | "warning": "undocumented" 184 | }, 185 | { 186 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/Extensions/FixedWidthInteger+Extras.swift", 187 | "line": 68, 188 | "symbol": "FixedWidthInteger.init(bigEndianBytes:)", 189 | "symbol_kind": "source.lang.swift.decl.function.method.instance", 190 | "warning": "undocumented" 191 | }, 192 | { 193 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/Extensions/FixedWidthInteger+Extras.swift", 194 | "line": 82, 195 | "symbol": "FixedWidthInteger.maskFrom(bitCount:)", 196 | "symbol_kind": "source.lang.swift.decl.function.method.instance", 197 | "warning": "undocumented" 198 | }, 199 | { 200 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/Extensions/FixedWidthInteger+Extras.swift", 201 | "line": 92, 202 | "symbol": "FixedWidthInteger.init(bcd:)", 203 | "symbol_kind": "source.lang.swift.decl.function.method.instance", 204 | "warning": "undocumented" 205 | }, 206 | { 207 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/Extensions/FixedWidthInteger+Extras.swift", 208 | "line": 107, 209 | "symbol": "FixedWidthInteger.bcdValue", 210 | "symbol_kind": "source.lang.swift.decl.var.instance", 211 | "warning": "undocumented" 212 | }, 213 | { 214 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/HexDump.swift", 215 | "line": 13, 216 | "symbol": "hexDump(_:startAddress:showASCII:)", 217 | "symbol_kind": "source.lang.swift.decl.function.free", 218 | "warning": "undocumented" 219 | }, 220 | { 221 | "file": "/Users/spse/src/swift-babab/Sources/BABAB/HexDump.swift", 222 | "line": 42, 223 | "symbol": "hexDump(_:showASCII:)", 224 | "symbol_kind": "source.lang.swift.decl.function.free", 225 | "warning": "undocumented" 226 | } 227 | ], 228 | "source_directory": "/Users/spse/src/swift-babab" 229 | } -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | MACOS_TESTS="Failed" 4 | LINUX_5_2_TESTS="Failed" 5 | LINUX_5_3_TESTS="Failed" 6 | LINUX_5_4_TESTS="Failed" 7 | LINUX_5_5_TESTS="Failed" 8 | LINUX_LATEST_TESTS="Failed" 9 | LINUX_NIGHTLY_TESTS="Failed" 10 | NIGHTLY_TAG=swiftlang/swift:nightly-focal 11 | 12 | docker pull ${NIGHTLY_TAG} 13 | swift package clean 14 | swift test && MACOS_TESTS="Passed" 15 | 16 | docker run --rm -v `pwd`:/babab/5.2 -w /babab/5.2 -t swift:5.2 swift test --build-path=/tmp/.build && LINUX_5_2_TESTS="Passed" 17 | docker run --rm -v `pwd`:/babab/5.3 -w /babab/5.3 -t swift:5.3 swift test --build-path=/tmp/.build && LINUX_5_3_TESTS="Passed" 18 | docker run --rm -v `pwd`:/babab/5.4 -w /babab/5.4 -t swift:5.4 swift test --build-path=/tmp/.build && LINUX_5_4_TESTS="Passed" 19 | docker run --rm -v `pwd`:/babab/5.5 -w /babab/5.5 -t swift:5.5 swift test --build-path=/tmp/.build && LINUX_5_5_TESTS="Passed" 20 | docker run --rm -v `pwd`:/babab/latest -w /babab/latest -t swift:latest swift test --build-path=/tmp/.build && LINUX_LATEST_TESTS="Passed" 21 | docker run --rm -v `pwd`:/babab/nightly -w /babab/nightly -t ${NIGHTLY_TAG} swift test --build-path=/tmp/.build && LINUX_NIGHTLY_TESTS="Passed" 22 | 23 | echo 24 | echo macOS tests ${MACOS_TESTS} 25 | echo Linux-5.2 tests ${LINUX_5_2_TESTS} 26 | echo Linux-5.3 tests ${LINUX_5_3_TESTS} 27 | echo Linux-5.4 tests ${LINUX_5_4_TESTS} 28 | echo Linux-5.5 tests ${LINUX_5_5_TESTS} 29 | echo Linux latest tests ${LINUX_LATEST_TESTS} 30 | echo Linux nightly tests ${LINUX_NIGHTLY_TESTS} 31 | --------------------------------------------------------------------------------