SwiftRadix

SwiftRadix

CI Build Status Platforms - macOS 10.10+ | iOS 9+ | tvOS 9+ | watchOS 2+ | visionOS 1+ | Linux License: MIT

一个轻量级的库,可用于使用简单、清晰的函数式语法,将整数与基数字符串(二进制、十六进制、八进制或任何进制)相互转换。

兼容所有 Apple 平台和 Linux。

摘要

常用方法

统一的库,包含多种构造方法,所有方法都以内联方式提供库的所有功能。

选项 1:函数 选项 2:类别方法 返回值
Radix(T, base:) .radix(base:) Radix<T>(base: n) 其中 n 是 2...36
Binary(T) .binary Radix<T>(base: 2)
Octal(T) .octal Radix<T>(base: 8)
Hex(T) .hex Radix<T>(base: 16)

为了简化本文档,以下大多数示例将使用 Hex() / .hex

// convert to or from hex strings

255.hex.stringValue                                 // "FF"
255.hex.stringValue(prefix: true)                   // "0xFF"
255.hex.stringValue(prefix: true, uppercase: false) // "0xff"
"FF".hex?.value                                     // Optional(255)
"0xFF".hex?.value                                   // Optional(255)
"ZZ".hex?.value                                     // nil (not valid hex string, so init fails)

// work with arrays of any integer type, or hex strings and convert between them

[0, 255, 0, 255].hex.stringValue                       // "00 FF 00 FF"
[0, 255, 0, 255].hex.stringValues                      // ["00", "FF", "00", "FF"]
[0, 255, 0, 255].hex.stringValue(prefixes: true)       // "0x00 0xFF 0x00 0xFF"
[0, 255, 0, 255].hex.stringValues(prefixes: true)      // ["0x00", "0xFF", "0x00", "0xFF"]

[0, 255, 0, 255].hex.stringValueArrayLiteral           // "[0x0, 0xFF, 0x0, 0xFF]"
[0, 255, 0, 255].hex.stringValueArrayLiteral(padTo: 2) // "[0x00, 0xFF, 0x00, 0xFF]"

[0, 65535, 4000].hex.stringValue                       // "0 FFFF FA0"
[0, 65535, 4000].hex.stringValue(padTo: 2)             // "00 FFFF FA0"
[0, 65535, 4000].hex.stringValue(padToEvery: 2)        // "00 FFFF 0FA0"
[0, 65535, 4000].hex.stringValue(padToEvery: 4)        // "0000 FFFF 0FA0"

["00", "FF", "ZZ"].hex.values                          // [Optional(0), Optional(255), nil]

// test for equatability or perform math operations with great flexibility,
// without needing to extract the .value first, casting or converting

UInt8(123).hex == Int16(123)      // true
"FF".hex == 255                   // true

123.hex + 10.binary - 10          // 123

安装

Swift 包管理器 (SPM)

  1. 使用 Swift 包管理器添加 SwiftRadix 作为依赖项。

    • 在应用项目或框架中,在 Xcode 中

      • 选择菜单:File → Swift Packages → Add Package Dependency...
      • 输入此 URL:https://github.com/orchetect/SwiftRadix
    • 在 Swift 包中,将其添加到 Package.swift 依赖项

      .package(url: "https://github.com/orchetect/SwiftRadix", from: "1.3.0")

Cocoapods

pod 'SwiftRadix'

文档

前提

其核心是一个名为 Radix 的新泛型类型,它包装任何 BinaryInteger 值及其关联的基数(进制)。

Radix<T: BinaryInteger>

// constructors

Radix(0xFF, base: 16)                // Radix<Int>(255)?
Radix(UInt8(0xFF), base: 16)         // Radix<UInt8>(255)?
Radix<UInt8>(0xFF, base: 16)         // Radix<UInt8>(255)?

Radix(0b1111, base: 2)               // Radix<Int>(15)?

// category method to construct

0xFF.radix(base: 16)                 // Radix<Int>(255)?
0xFF.radix(base: 16, as: UInt8.self) // Radix<UInt8>(255)?

但是,对于常用进制(二进制 base-2、八进制 base-8、十六进制 base-16),您可能永远不需要直接构造 Radix。相反,在常用类型和集合上提供了便捷的函数式类别方法来简化这些操作。

255.binary            // == Radix<Int>(0b11111111, base: 2)
"0b11111111".binary   // == Radix<Int>(255, base: 2)?

255.octal             // == Radix<Int>(0o377, base: 8)
"0o377".octal         // == Radix<Int>(255, base: 8)?

255.hex               // == Radix<Int>(0xFF, base: 16)
"0xFF".hex            // == Radix<Int>(255, base: 16)?

255.radix(base: 5)    // == Radix<Int>(255, base: 5)
"2010".radix(base: 5) // == Radix<Int>(255, base: 5)?

当它们组合使用时,您将在 README 的下方看到它们的功能有多强大和优雅。

代理构造器

两种调用样式,产生相同的结果。

// proxy constructor function
Hex(123)                  // Radix<Int>(123, base: 16)

// functional category property
123.hex                   // Radix<Int>(123, base: 16)

可以使用任何 BinaryInteger 类型。

Int(123).hex              // Radix<Int>(123)
Int8(123).hex             // Radix<Int8>(123)
UInt8(123).hex            // Radix<UInt8>(123)
Int16(123).hex            // Radix<Int16>(123)
UInt16(123).hex           // Radix<UInt16>(123)
Int32(123).hex            // Radix<Int32>(123)
UInt32(123).hex           // Radix<UInt32>(123)
Int64(123).hex            // Radix<Int64>(123)
UInt64(123).hex           // Radix<UInt64>(123)

可以使用有效的十六进制字符串,可以包含前缀 0x 或不包含。

此构造器返回一个 Optional,因为如果字符串不是有效的十六进制,构造器将失败并返回 nil

如果未指定整数类型,则类型将默认为 Int

Hex("FF")                 // Radix<Int>(255)?
"FF".hex                  // Radix<Int>(255)?
"0xFF".hex                // Radix<Int>(255)?

"ZZZZ".hex                // nil ; not a valid hex string

要指定 Int 以外的整数类型,请使用 as: 指定。

Hex("FF", as: UInt8.self)      // Radix<UInt8>(255)?
"FF".hex(as: UInt8.self)       // Radix<UInt8>(255)?

Hex("FFFFFF", as: UInt8.self)  // nil -- 0xFFFFFF does not fit in UInt8, so init fails
"FFFFFF".hex(as: UInt8.self)   // nil -- 0xFFFFFF does not fit in UInt8, so init fails

获取和设置值

可以使用各种方法

let h = 255.hex                               // Radix<Int>(255)
h.value                                       // Int(255)
h.stringValue                                 // "FF"
h.stringValue(prefix: true)                   // "0xFF"
h.stringValue(prefix: true, uppercase: false) // "0xff"

h.stringValue = "7F"                          // can also set the hex String and get value...
h.value                                       // 127, type Int

如果您需要统一的字符串格式,可以指定填充到 n 个前导零。

    0xF.hex.stringValue           // "F"
    0xF.hex.stringValue(padTo: 2) // "0F"
    0xF.hex.stringValue(padTo: 3) // "00F"

 0xFFFF.hex.stringValue(padTo: 3) // "FFFF" - has no effect; it's > 3 places

也可以每隔 n 位数字位置填充前导零。

    0xF.hex.stringValue(padToEvery: 2) // "0F"
   0xFF.hex.stringValue(padToEvery: 2) // "FF"
  0xFFF.hex.stringValue(padToEvery: 2) // "0FFF"
 0xFFFF.hex.stringValue(padToEvery: 2) // "FFFF"

    0x1.hex.stringValue(padToEvery: 4) // "0001"
0x12345.hex.stringValue(padToEvery: 4) // "00012345"

除了填充之外,字符串还可以每隔 n 位数字位置分割,并且可以与填充结合使用。

    0xF.hex.stringValue(padTo: 8, splitEvery: 4)      // "0000 000F"
0x123AB.hex.stringValue(padToEvery: 2, splitEvery: 2) // "01 23 AB"

可等性

可以使用典型的运算符(==!=><)直接测试 Radix<T> 的可等性,而无需访问 .value 属性。这使得语法更简洁、更方便。

let h1 = 10.hex        // Radix<Int>
let h2 = 20.hex        // Radix<Int>

h1.value == h2.value   // this works but it's easier to just do this...
h1 == h2               // false

它们可以非常灵活地进行比较 - 甚至可以直接在不同的整数类型之间进行比较,而无需强制转换或转换。

let h1 = 10.hex        // Radix<Int>
let h2 = 20.hex        // Radix<Int>
h1 == h2               // false  (comparing Radix<Int> with Radix<Int>)
h1 > 20                // true   (comparing Radix<Int> with Int)
h1 != UInt8(20)        // true   (comparing Radix<Int> with UInt8)

// even though "FF".hex produces an Optional,
// the comparison still works safely without requiring the optional to be unwrapped first
"FF".hex == 255        // true
"FF".hex == 255.hex    // true
"ZZ".hex == 255.hex    // false - optional is nil

其他运算符

支持其他运算符,允许直接进行赋值和位运算。

位移

传统的二进制位左/右移可以直接在 Radix 上使用。

0b0100.hex << 1        // 0b1000
0b0100.hex >> 1        // 0b0010

Array 和 Data 的扩展

[BinaryInteger]

任何整数数组都可以转换为等效的 [Radix<T>] 数组

let a = [1, 2].hex           // [Radix<Int>(1), Radix<Int>(2)]

let arr: [UInt8] = [3, 4]
let b = arr.hex              // [Radix<UInt8>(3), Radix<UInt8>(4)]

// and back again:

a.values                     // [1, 2] of type [Int]
b.values                     // [3, 4] of type [UInt8]

它也可以展平成一个连接的 String 或一个 String 数组

[0, 255, 0, 255].hex.stringValue                 // "00 FF 00 FF"
[0, 255, 0, 255].hex.stringValue(prefix: true)   // "0x00 0xFF 0x00 0xFF"

[0, 255, 0, 255].hex.stringValues                // ["00", "FF", "00", "FF"]
[0, 255, 0, 255].hex.stringValues(prefix: true)  // ["0x00", "0xFF", "0x00", "0xFF"]

[String]

String 数组也可以转换为 Radix<T>? 数组。 .values 属性生成一个解包的 [Optional<T>] 数组。

["00", "0xFF", "ZZ"].hex.values   // [Optional(0), Optional(255), nil]

也可以轻松生成 Swift 源代码兼容的数组字面量。

let arr = [0, 2, 255]

arr.hex.stringValueArrayLiteral    // "[0x0, 0x2, 0xFF]"
arr.binary.stringValueArrayLiteral // "[0b0, 0b10, 0b11111111]"

Data

在调试控制台的二进制数据或以人类可读的格式轻松呈现数据时非常有用。

let d = Data([0x1, 0x2, 0x3, 0xFF])

d.hex.stringValue(padTo: 2)                          // "01 02 03 FF"

位和字节访问器

用于读取和操作底层整数值的各种附加方法。

方法:.bit(Int)

下标:[bit: Int] { get set }

var h = 0b1100.binary

h.bit(0)                  // 0b0.binary
h.bit(2)                  // 0b1.binary

h[bit: 0]                 // 0b0 (type T, which is Int in this case)
h[bit: 2]                 // 0b1 (type T, which is Int in this case)
h[bit: 2] = 0b0
h.value                   // == 0b1000

半字节

方法:.nibble(Int)

下标:[nibble: Int] { get set }

var h = 0x1234.hex

h.nibble(0)               // 0x4.hex
h.nibble(3)               // 0x1.hex

h[nibble: 0]              // 0x4 (type T, which is Int in this case)
h[nibble: 3]              // 0x1 (type T, which is Int in this case)
h[nibble: 3] = 0xF
h.value                   // == 0xF234

字节

.bytes

let bytes = 0xFF00.hex.bytes

bytes // [0x00, 0xFF]

作者

由一群穿着外套并自称 @orchetect 的 🐹 仓鼠编写。

许可证

根据 MIT 许可证获得许可。有关详细信息,请参阅 LICENSE

贡献

欢迎贡献。请随时发布 Issue 进行讨论。