SwiftRadix 1.3.1

SwiftRadix 1.3.1

Steffan Andrews 维护。



  • 作者:
  • Steffan Andrews

SwiftRadix

SwiftRadix

CI Build Status Platforms - macOS | iOS | tvOS | watchOS License: MIT

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

摘要

常见用法

统一库,包含多种构造函数,每个函数都提供了库的所有功能。

选项 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"
"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 Package Manager 将 SwiftRadix 添加为依赖项。

    • 在一个应用程序项目或框架中,在 Xcode

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

      .package(url: "https://github.com/orchetect/SwiftRadix", from: "1.1.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)?

然而,对于常见的基数(二进制基数-2、八进制基数-8、十六进制基数-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 或不带有前缀。

由于如果字符串不是有效的十六进制,则构造函数会失败并返回 nil,因此该构造函数返回 Optional

如果没有指定整型类型,则默认为 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 = "7F"                      // can also set the hex String and get value...
h.value                                   // 127, type Int

如果需要统一的字符串格式化,可以指定前导0的个数

    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

也可以将前导0填充到每个数字位置的第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

数组和数据处理扩展

[二进整数]

任何整数数组都可以转换为等价的 [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]

它还可以展开为连接的 StringString 数组。

[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 }

  • 获取指定位置(从右到左)的半字节(4位)值
  • 索引属性也可用于获取或设置半字节值
  • 基数无关
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

  • 一个便捷属性,用于返回值的原始字节数据,形式为数组[UInt8],基于系统字节序。
  • 基数无关
let bytes = 0xFF00.hex.bytes

bytes // [0x00, 0xFF]

作者

由一系列🐹穿着 trench coat 的小仓鼠编写,自称 @orchetect

许可证

版权协议为 MIT 协议。详情请见 LICENSE

该库以前被称为 SwiftHex。

贡献

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