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 时,您都需要执行截断位转换,因为如果您的整数内容大于接收类型允许的大小(例如,尝试 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 类型添加了一些其他扩展
双重否定运算符 ~~
:这个新运算符具有与 C 或类似语言中的 !! 相同的功能,它将每个不等于 0 的整数值转换为 1,并保持值 0 不变。 当您想将表达式的结果转换为标准的 C 0/1 整数布尔值以在另一个表达式中使用它时,它非常有用。
Int 类型的 size
静态属性:MemoryLayout<IntN>.stride
的简写
mask(bits:msb:)
静态方法:它创建一个设置了请求的位数的位掩码,从最高有效位开始或不开始。 例如,调用 Int16.mask(5,msb:true)
将返回 0xF800
或二进制 1111100000000000
,而 Int16.mask(5,msb:false)
将返回 0x001F
,因为这五个位将从最低有效位位置开始设置。
要了解有关 Swift 中的位运算的更多信息,请参阅我的博客上的文章“在 Swift 中处理位集合”(已更新至 Swift 4.0)。
首先,感谢您考虑为本项目做出贡献,欢迎所有 PR!
请注意,此库的源代码不是直接用 Swift 编写的,而是使用 Sourcery 生成的。
主要的 Bitter 模板位于 Templates/Bitter.stencil
,compile.sh
脚本将负责下载 Sourcery 并将 stencil 模板编译为 Swift 源代码。
早于 3.x 的版本使用 GYB 模板编译器。