Bitter

Swift 4 compatible License: MIT Travis CI

摘要

Bitter 库为所有基本的 Swift Int 类型扩展了一些有用的位操作方法。该库的目标是通过使用有意义的简写方法,使处理位和位运算的代码更简洁易读。例如,使用 Bitter,您将能够替换以下代码:

var i:UInt32 = 0xAABBCCDD
let tmp = (i & (0xFF << 16)) >> 16 // Let's swap the 2nd and 3rd byte...
i = (i & ~(0xFF << 16)) | ((i & (0xFF << 8)) << 8)
i = (i & ~(0xFF << 8)) | (tmp << 8)
i = (i & ~((0x1 << 3) << 8)) | (i & ((0x1 << 3) << 8)) // Set the 4th bit of the 2nd byte

为以下代码:

let tmp = i[2] // Let's swap the 2nd and 3rd byte!
i[2] = i[1]
i[1] = tmp 
i[1] = i[1].setb3(1) // Set the 4th bit of the 2nd byte
i[1] = i[1].setb3(0).setb4(1).setb5(0).setb6(1) // Let's set some other bit

安装

如果您想手动安装 Bitter,只需将 Sources/Bitter 中的所有 Swift 文件包含到您的项目中,或者将其作为 git 子模块加载。

Bitter 也支持所有主要的依赖管理工具:CocoaPods、Carthage 和 SwiftPM。

要通过 CocoaPods 在您的项目中使用 Bitter,请将其添加到您的 PodFile

use_frameworks!

pod 'Bitter'

并使用 pod install 更新您的工作区。

Bitter 也可通过 Carthage 获得。要安装,只需写入您的 Cartfile

github "uraimo/Bitter"

使用 carthage update 下载框架并将其添加到您的嵌入式二进制文件中。

如果您使用 Swift Package Manager,只需将其添加到您的 Package.swift 的依赖项中

// swift-tools-version:4.0
import PackageDescription

let package = Package(
    ...
    dependencies: [
        .package(url: "https://github.com/uraimo/Bitter.git", from: "4.0.0")
    ]
)

无论您以何种方式将 Bitter 添加到您的项目中,都使用 import Bitter 导入它。

用法

让我们看看 Bitter 提供了什么

Int 类型转换

每次您想要将包含位模式的 Int 转换为较小的 Int 时,您都需要执行截断位转换,因为如果您的整数内容大于接收类型允许的大小(例如,尝试 Int8(1000)),转换将直接在运行时失败。 请允许我重申,我们正在执行位截断,而不是十进制截断转换。

位模式截断转换可以使用构造器 init(truncatingIfNeeded:) 轻松执行,但如果您需要经常这样做,您的代码将很快变得不可读。

使用 Bitter,每个 Intn/UIntn 类型都获得了一些方法,可以执行到较小 Int 类型的截断位模式转换,或者针对较大和相同大小/不同符号性的 Int 类型的简单位模式转换:.to8、toU8、to16、toU16、to32、toU32、to64、toU64。 toUn 方法执行到无符号 Int 的转换,而数字指的是类型的大小,例如 .toU16 会将当前整数转换为 UInt16,并在必要时截断位模式。

让我们看一个例子

var i:Int32 = 50000
var u8:UInt8 = i.toU8   //81, Without Bitter: var u8:UInt8 = UInt8(truncatingIfNeeded:i)

Bitter 在混合类型表达式中也很有用,使代码更简洁

class Test{
    var content:UInt32=0

    func shiftAndResizeMe(howMuch:Int)->UInt16{
        return  (content << howMuch.toU32).toU16  //Without Bitter: return UInt16(truncatingIfNeeded:(content << UInt32(truncatingIfNeeded:howMuch)))
    }
}

特定字节下标

虽然检索和修改多字节 Int 中的单个字节很容易,但总是编写相同的代码有点烦人,Bitter 为每个 Int 类型添加了用于寻址单个字节的下标。 遵循与 Int 转换相同的安全至上原则,尝试修改超出当前类型范围的字节将在运行时导致错误。

让我们看一些例子

var i:UInt32 = 0xAABBCCDD

//Let's swap the two bytes
let tmp = i[2]           //Without Bitter: let tmp = (i & (0xFF << 16)) >> 16
i[2] = i[1]              //                i = (i & ~(0xFF << 16)) | ((i & (0xFF << 8)) << 8)
i[1] = tmp               //                i = (i & ~(0xFF << 8)) | (tmp << 8)

// Let's set to 0 the second bit of the second byte
i[1] &= 0b11111101       //Without Bitter: i = i & (0b11111101 << 8)

// Let's change the fourth byte
i[4] = 0xAA   //Error! There is no 4th byte!

对于小端多字节 Int,下标索引从 LSB 到 MSB 开始,如果对 Int 应用了大端转换,则方向相反。

修改特定位

每个 Int 类型(无论有符号还是无符号)都获得了 8 个属性和 8 个函数,允许在整数的第一个字节中设置或获取单个位。 它们应该与字节下标结合使用

var i:UInt32 = 0xAABBCCDD
i[2].b2 //0
i[2].b3 //1

i[2] = i[2].setb2(1).setb3(0)
i[2].b2 //1
i[2].b3 //0

.bN 属性返回特定位置的位的值,而 .setbN(value) 函数设置整数中的特定位(索引指的是 8 个最低有效位)并返回修改后的 8 位整数(如果在内容大于 8 位的整数上使用,则其余部分将被截断)。

考虑到每个 .setbN(value) 函数都返回一个新的整数,这些函数可以串联起来以修改多个位。 此函数可以与字节索引下标结合使用,如上所示,在右侧,我们为数组的位置 2 构建一个新的字节值,然后将其分配给同一数组的相同位置。

其他功能

Bitter 还为 Int 类型添加了一些其他扩展

位运算

要了解有关 Swift 中的位运算的更多信息,请参阅我的博客上的文章“在 Swift 中处理位集合”(已更新至 Swift 4.0)。

贡献

首先,感谢您考虑为本项目做出贡献,欢迎所有 PR!

请注意,此库的源代码不是直接用 Swift 编写的,而是使用 Sourcery 生成的。

主要的 Bitter 模板位于 Templates/Bitter.stencilcompile.sh 脚本将负责下载 Sourcery 并将 stencil 模板编译为 Swift 源代码。

早于 3.x 的版本使用 GYB 模板编译器。