SwiftScanner 1.1.0

SwiftScanner 1.1.0

测试已测试
Lang语言 SwiftSwift
许可证 MIT
发布最新发布2018年10月
SPM支持 SPM

Daniele Margutti 维护。



SwiftScanner

Build Status codecov Platform Platform Language: Swift CocoaPods Carthage

SwiftScanner

SwiftScanner 是一个纯 Swift 实现的字符串扫描器,无依赖项,完全支持 Unicode(谁不喜欢表情符号呢?),很多实用功能和Swift特性,StringScanner是 苹果内置的NSScanner的良好替代品。

★★ 请为我们的GitHub仓库点星,以帮助我们! ★★

你可能也会喜欢


喜欢 SwiftRichString 吗?我还在工作于几个其他的开源库。

查看这里

  • SwiftDate - iOS, macOS, tvOS 和 watchOS 的全功能日期和时区管理
  • Hydra - 强效的 Promise, Async/Await 库
  • SwiftLocation - CoreLocation 和信标监控库
  • SwiftScanner - 支持完全 Unicode 的纯Swift字符串扫描器
  • SwiftSimplify - 高性能Swift Polyline 简化库
  • SwiftMsgPack - Swift中的MsgPack 编码/解码器

主要特性

SwiftScanner 使用字符串进行初始化,并维护一个内部索引,用于使用两个主要概念来回导航字符串:

  • scan 返回字符串并递增内部索引
  • peek 返回字符串但不递增内部索引

这些操作的结果返回收集到的字符串或索引。如果由于错误(例如 eofnotFoundinvalidInt...)而失败并抛出异常,则按照纯 Swift 风格。

API 文档

其他

scan 函数

#### `func scanChar() throws -> UnicodeScalar` `scanChar` allows you to scan the next character after the current's scanner `position` and return it as `UnicodeScalar`. If operation succeded internal scanner's `position` is advanced by 1 character (as unicode). If operation fails an exception is thrown.

Example:

let scanner = StringScanner("Hello this is SwiftScanner") let firstChar = try! scanner.scanChar() // get 'H'
#### `func scanInt() throws -> Int` Scan the next integer value after the current scanner's `position`; consume scalars from {0...9} until a non numeric value is encountered. Return the integer representation in base 10. Throw `.invalidInt` if scalar at current position is not in allowed range (may also return `.eof`). If operation succeded internal scanner's `position` is advanced by the number of character which represent an integer. If operation fails an exception is thrown.

Example:

let scanner = StringScanner("15 apples") let parsedInt = try! scanner.scanInt() // get Int=15
#### `func scanFloat() throws -> Float` Scan for a float value (in format ##.##) and convert it to a valid Floast. If scan succeded scanner's `position` is updated at the end of the represented string, otherwise an exception (`.invalidFloat`, `.eof`) is thrown and index is not touched.

Example:

let scanner = StringScanner("45.54 $") let parsedFloat = try! scanner.scanFloat() // get Int=45.54
#### `func scanHexInt(digits: BitDigits) throws -> Int` Scan an HEX digit expressed in these formats:
  • 0x[VALUE] (example: 0x0000000000564534)
  • 0X[VALUE] (example: 0x0929)
  • #[VALUE] (example: #1602)

If scan succeded scanner's position is updated at the end of the represented string, otherwise an exception ((.notFound, ).invalidHex, .eof) is thrown and index is not touched.

Example:

let scanner = StringScanner("#1602") let value = try! scanner.scanHexInt(.bit16) // get Int=5634  let scanner = StringScanner("#0x0929") let value = try! scanner.scanHexInt(.bit16) // get Int=2345  let scanner = StringScanner("#0x0000000000564534") let value = try! scanner.scanHexInt(.bit64) // get Int=5653812
#### `public func scan(upTo char: UnicodeScalar) throws -> String?` Scan until given character is found starting from current scanner `position` till the end of the source string. Scanner's `position` is updated only if character is found and set just before it. Throw an exception if `.eof` is reached or `.notFound` if char was not found (in this case scanner's position is not updated)

Example:

let scanner = StringScanner("Hello <bold>Daniele</bold>") let partialString = try! scanner.scan(upTo: "<bold>") // get "Hello "
#### `func scan(upTo charSet: CharacterSet) throws -> String?` Scan until given character's is found. Index is reported before the start of the sequence, scanner's `position` is updated only if sequence is found. Throw an exception if `.eof` is reached or `.notFound` if sequence was not found.

Example:

let scanner = StringScanner("Hello, I've at least 15 apples") let partialString = try! scanner.scan(upTo: CharacterSet.decimalDigits) // get "Hello, I've at least "
#### `func scan(untilIn charSet: CharacterSet) throws -> String?` Scan, starting from scanner's `position` until the next character of the scanner is contained into given character set. Scanner's `position` is updated automatically at the end of the sequence if validated, otherwise it will not touched.

Example:

let scanner = StringScanner("HELLO i'm mark") let partialString = try! scanner.scan(untilIn: CharacterSet.lowercaseLetters) // get "HELLO"
#### `func scan(upTo string: String) throws -> String?` Scan, starting from scanner's `position` until specified string is encountered. Scanner's `position` is updated automatically at the end of the sequence if validated, otherwise it will not touched.

Example:

let scanner = StringScanner("This is a simple test I've made") let partialString = try! scanner.scan(upTo: "I've") // get "This is a simple test "
#### `func scan(untilTrue test: ((UnicodeScalar) -> (Bool))) -> String` Scan and consume at the scalar starting from current `position`, testing it with function test. If test returns `true`, the `position` increased. If `false`, the function returns.

Example:

let scanner = StringScanner("Never be satisfied 💪 and always push yourself! 😎 Do the things people say cannot be done") let delimiters = CharacterSet(charactersIn: "💪😎") while !scanner.isAtEnd { let block = scanner.scan(untilTrue: { char in return (delimiters.contains(char) == false) }) // Print:  // "Never be satisfied " (first iteration)  // "and always push yourself!" (second iteration)  // "Do the things people say cannot be done" (third iteration)  print("Block: \(block)") try scanner.skip() // push over the character }
#### `func scan(length: Int=1) -> String` Read next length characters and accumulate it If operation is succeded scanner's `position` are updated according to consumed scalars. If fails an exception is thrown and `position` is not updated.

Example:

let scanner = StringScanner("Never be satisfied") let partialString = scanner.scan(5) // "Never"

peek 函数

Peek 函数类似于 scan() 的概念,但除非它还更新内部扫描器的 position 索引。这些函数通常仅返回匹配模式的 起始索引

#### `func peek(upTo char: UnicodeScalar) -> String.UnicodeScalarView.Index` Peek until chracter is found starting from current scanner's `position`. Scanner's `position` is never updated. Throw an exception if `.eof` is reached or `.notFound` if char was not found.

Example:

let scanner = StringScanner("Never be satisfied") let index = try! scanner.peek(upTo: "b") // return 6
#### `func peek(upTo charSet: CharacterSet) -> String.UnicodeScalarView.Index` Peek until one the characters specified by set is encountered Index is reported before the start of the sequence, but scanner's `position` is never updated. Throw an exception if .eof is reached or .notFound if sequence was not found

Example:

let scanner = StringScanner("You are in queue: 123 is your position") let index = try! scanner.peek(upTo: CharacterSet.decimalDigits) // return 18
#### `func peek(untilIn charSet: CharacterSet) -> String.UnicodeScalarView.Index` Peek until the next character of the scanner is contained into given. Scanner's `position` is never updated.

Example:

let scanner = StringScanner("654 apples") let index = try! scanner.peek(untilIn: CharacterSet.decimalDigits) // return 3
#### `func peek(upTo string: String) -> String.UnicodeScalarView.Index` Iterate until specified string is encountered without updating indexes. Scanner's `position` is never updated but it's reported the index just before found occourence.

Example:

let scanner = StringScanner("654 apples in the bug") let index = try! scanner.peek(upTo: "in") // return 11
#### `func peek(untilTrue test: ((UnicodeScalar) -> (Bool))) -> String.UnicodeScalarView.Index` Peeks at the scalar at the current position, testing it with function test. It only peeks so current scanner's `position` is not increased at the end of the operation

Example:

let scanner = StringScanner("I'm very 💪 and 😎 Go!") let delimiters = CharacterSet(charactersIn: "💪😎") while !scanner.isAtEnd { let prevIndex = scanner.position let finalIndex = scanner.peek(untilTrue: { char in return (delimiters.contains(char) == false) }) // Distance will return:  // - 9 (first iteration)  // - 5 (second iteration)  // - 4 (third iteration)  let distance = scanner.string.distance(from: prevIndex, to: finalIndex) try scanner.skip(length: distance + 1) }

其他函数

#### `func match(_ char: UnicodeScalar) -> Bool` 如果当前位置的字符与给定字符不匹配,则返回 false。如果匹配,则将扫描器的 `position` 移动到匹配的末尾。
let scanner = StringScanner("💪 and 😎") let match = scanner.match("😎") // 返回 false
#### `func match(_ match: String) -> Bool` 如果从当前位置开始的字符与给定字符串中的字符不匹配,则返回 false。如果匹配,则将扫描器的 `position` 移动到匹配字符串的末尾。
let scanner = StringScanner("I'm very 💪 and 😎 Go!") scanner.match("I'm very") // 返回 true
#### `func reset()` 将扫描器的内部 `position` 移动到字符串的开始处。 #### `func peekAtEnd()` 移动到索引的末尾。 #### `func skip(length: Int = 1) throws` 尝试根据长度前进扫描器。如果操作不可行(已到达字符串末尾),则抛出异常并且当前扫描器的 `position` 没有变化。如果操作成功,则更新扫描器的 `position`。 #### `func back(length: Int = 1) throws` 尝试根据长度后退位置。如果操作失败,扫描器的 `position` 不会被触及。如果操作成功,根据新值修改扫描器的 `position`。 ## Installation 您可以使用 CocoaPods、Carthage 和 Swift 包管理器来安装 Swiftline

CocoaPods

use_frameworks!
pod 'SwiftScanner'

Carthage

github 'malcommac/SwiftScanner'

Swift Package Manager

在您的 Package.swift 中将 swiftline 添加为依赖

  import PackageDescription

  let package = Package(name: "YourPackage",
    dependencies: [
      .Package(url: "https://github.com/malcommac/SwiftScanner.git", majorVersion: 0),
    ]
  )
## 测试 测试可以在这里找到:[点击这里](https://github.com/malcommac/SwiftScanner/tree/master/Tests)。

使用以下命令运行它们:

swift test 
## 需求 当前版本与以下系统兼容:

  • Swift 4.x >= 1.0.4

  • Swift 3.x: up to 1.0.3

  • iOS 8 或更高版本

  • macOS 10.10 或更高版本

  • watchOS 2.0 或更高版本

  • tvOS 9.0 或更高版本

  • ...以及几乎任何与 Swift 3 兼容且实现了 Swift Foundation 库的平台

## 信用 & 许可 SwiftScanner 由 [Daniele Margutti](http://www.danielemargutti.com/) 所有并维护。

作为开源创建,任何帮助都受到欢迎!

该库的代码采用 MIT 许可证;您可以在商业产品中使用它而没有任何限制。

唯一的要求是在您的“关于”或“信用”部分中添加以下文本的一行:

SwiftScanner 部分摘自古登 https://github.com/malcommac/SwiftScanner 由 Daniele Margutti 创建并采用 MIT 许可证。