• This repository has been archived on 15/Nov/2020
  • Stars
    star
    171
  • Rank 215,277 (Top 5 %)
  • Language
    Swift
  • License
    MIT License
  • Created over 7 years ago
  • Updated about 5 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

String Scanner in pure Swift (supports unicode)

SwiftScanner

Build Status codecov Platform Platform Language: Swift CocoaPods Carthage

SwiftScanner

SwiftScanner is a pure native Swift implementation of a string scanner; with no dependecies, full unicode support (who does not love emoji?), lots of useful featurs and swift in mind, StringScanner is a good alternative to built-in Apple's NSScanner.

β˜…β˜… Star our github repository to help us! β˜…β˜…

Related Projects

I'm also working on several other projects you may like. Take a look below:

Library Description
SwiftDate The best way to manage date/timezones in Swift
Hydra Write better async code: async/await & promises
FlowKit A new declarative approach to table managment. Forget datasource & delegates.
SwiftRichString Elegant & Painless NSAttributedString in Swift
SwiftLocation Efficient location manager
SwiftMsgPack Fast/efficient msgPack encoder/decoder

Main Features

SwiftScanner is initialized with a string and mantain an internal index used to navigate backward and forward through the string using two main concepts:

  • scan to return string which also increment the internal index
  • peek to return a string without incrementing the internal index

Results of these operations returns collected String or Indexes. If operation fail due to an error (ie. eof, notFound, invalidInt...) and exception is thrown, in pure Swift style.

API Documentation

Other

scan functions

#### `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 functions

Peek functions are the same as concept of scan() but unless it it does not update internal scanner's position index. These functions usually return only starting index of matched pattern.

#### `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)
}

Other Functions

#### `func match(_ char: UnicodeScalar) -> Bool` Return false if the scalar at the current position don't match given scalar. Advance scanner's `position` to the end of the match if match.
let scanner = StringScanner("πŸ’ͺ and 😎")
let match = scanner.match("😎") // return false
#### `func match(_ match: String) -> Bool` Return false if scalars starting at the current position don't match scalars in given string. Advance scanner's `position` to the end of the match string if match.
let scanner = StringScanner("I'm very πŸ’ͺ and 😎 Go!")
scanner.match("I'm very") // return true
#### `func reset()` Move scanner's internal `position` to the start of the string. #### `func peekAtEnd()` Move to the index's end index. #### `func skip(length: Int = 1) throws` Attempt to advance scanner's by length If operation is not possible (reached the end of the string) it throws and current scanner's `position` of the index did not change If operation succeded scanner's `position` is updated. #### `func back(length: Int = 1) throws` Attempt to advance the position back by length If operation fails scanner's `position` is not touched If operation succeded scaner's `position` is modified according to new value ## Installation You can install Swiftline using CocoaPods, carthage and Swift package manager

CocoaPods

use_frameworks!
pod 'SwiftScanner'

Carthage

github 'malcommac/SwiftScanner'

Swift Package Manager

Add swiftline as dependency in your Package.swift

  import PackageDescription

  let package = Package(name: "YourPackage",
    dependencies: [
      .Package(url: "https://github.com/malcommac/SwiftScanner.git", majorVersion: 0),
    ]
  )
## Tests Tests can be found [here](https://github.com/malcommac/SwiftScanner/tree/master/Tests).

Run them with

swift test
## Requirements

Current version is compatible with:

  • Swift 4.x >= 1.0.4

  • Swift 3.x: up to 1.0.3

  • iOS 8 or later

  • macOS 10.10 or later

  • watchOS 2.0 or later

  • tvOS 9.0 or later

  • ...and virtually any platform which is compatible with Swift 3 and implements the Swift Foundation Library

## Credits & License SwiftScanner is owned and maintained by [Daniele Margutti](http://www.danielemargutti.com/).

As open source creation any help is welcome!

The code of this library is licensed under MIT License; you can use it in commercial products without any limitation.

The only requirement is to add a line in your Credits/About section with the text below:

Portions SwiftScanner - http://github.com/malcommac/SwiftScanner
Created by Daniele Margutti and licensed under MIT License.

More Repositories

1

SwiftDate

πŸ” Toolkit to parse, validate, manipulate, compare and display dates, time & timezones in Swift.
Swift
7,500
star
2

SwiftLocation

βš“οΈ Async/Await CLLocationManager Wrapper for Apple Platforms
Swift
3,334
star
3

SwiftRichString

πŸ‘©β€πŸŽ¨ Elegant Attributed String composition in Swift sauce
Swift
3,046
star
4

Hydra

⚑️ Lightweight full-featured Promises, Async & Await Library in Swift
Swift
1,971
star
5

Repeat

πŸ•¦ Modern Timer in Swift, Debouncer and Throttler (alternative to NSTimer) made with GCD
Swift
1,456
star
6

UIWindowTransitions

πŸƒβ€β™‚οΈ Animated transitions for UIWindow's rootViewController property
Swift
465
star
7

ImageSizeFetcher

Finds the type/size of an image given its URL by fetching as little data as needed
Swift
442
star
8

Owl

A declarative type-safe framework for building fast and flexible lists with UITableViews & UICollectionViews
Swift
434
star
9

ScrollStackController

🧩 Easy scrollable layouts in UIKit - an UIStackView which scroll and uses root views of child view controllers.
Swift
426
star
10

Flow

Declarative approach to populate and manage UITableViews (see https://github.com/malcommac/FlowKit)
Swift
423
star
11

SwiftSimplify

πŸ₯· High-performance polyline simplification library - port of simplify.js
Swift
293
star
12

DMLazyScrollView

Lazy Loading UIScrollView for iOS (with support for infinite scrolling)
Objective-C
293
star
13

DMPagerViewController

DMPagerViewController is page navigation controller like the one used in Twitter or Tinder
Objective-C
278
star
14

FlowKit

A declarative type-safe framework for building fast and flexible list with Tables & Collection
Swift
211
star
15

DMCircularScrollView

Infinite/Circular Scrolling Implementation for UIScrollView
Objective-C
205
star
16

ScrollingStackContainer

Efficient Scrolling UIStackView in Swift - DEPRECATED (use ScrollStackController)
Swift
198
star
17

SwiftMsgPack

πŸ’¬ Fast & Lightweight MsgPack Serializer & Deserializer for Swift
Swift
154
star
18

DMSlidingCell

Swipe To Reveal UITableViewCell Implementation as like in Twitter
Objective-C
152
star
19

DMSplitView

New NSSplitView class with multiple subviews resize behaviors and animated transitions
Objective-C
116
star
20

DMScrollingTicker

Advanced horizontal scrolling ticker for iOS
Objective-C
110
star
21

DMDynamicWaterfall

UICollectionView Waterfall Layout with UIKit Dynamics
Objective-C
109
star
22

DMTabBar

XCode 4.x like inspector segmented control
Objective-C
108
star
23

HermesNetwork

Swift
73
star
24

DMInspectorPalette

Animated NSScrollView with collapsible sections like in XCode Inspector
Objective-C
61
star
25

SwiftUnistroke

✍️ $1 Unistroke Gesture Recognizer in Swift
Swift
53
star
26

UAParserSwift

πŸ—Ί User-Agent Parser based upon ua-parser.js
Swift
39
star
27

DMPageControl

An high customizable alternative to UIPageControl
39
star
28

DMTwitterOAuth

Twitter OAuth Library (Callback URL Login)
Objective-C
37
star
29

DMScrollViewStack

DMScrollViewStack is a UIScrollView subclass that efficiently handles a vertical stack of multiple scrollviews
Objective-C
33
star
30

DMLocationManager

Location Manager for iOS made simple
Objective-C
27
star
31

DMPathBar

XCode's Yosemite like path bar of OS X
Objective-C
25
star
32

Swift-Coding-Guidelines

A repository to collect best practices when programming with Swift
20
star
33

xcbetarunner

Run & Debug projects [easily] with stable Xcode on beta iOSΒ devices
Swift
17
star
34

GitLabSwift

πŸ›΅ Async/Await GitLab REST APIs v4 for Swift
Swift
14
star
35

DMCacheBox

Fast advanced caching system for Objective-C (Cocoa/iOS compatible)
Objective-C
14
star
36

RealEventsBus

🚎 Simple type-safe event bus implementation in swift
Swift
13
star
37

DMMultiDelegatesProxy

Multiple delegate architecture made using NSProxy
Objective-C
10
star
38

Glider-Old

✈️ Fast & powerful logger for Swift
Swift
9
star
39

NSSplitView-Animatable

NSSplitView Category to perform simple animations with dividers
Objective-C
9
star
40

CircularScroller

Efficient and Lightweight endless UIScrollView implementation in Swift
Swift
7
star
41

DMAPNServer

APN - Apple Push Notification Server in PHP
PHP
6
star
42

DMCoreDataUtils

Utilities methods for Apple's Core Data Storage
Objective-C
6
star
43

SlidingSheet

Configurable Bottom Sheet for UIKit - like AirBnb and Apple Maps
Swift
4
star
44

sentry-cocoa-sdk-xcframeworks

A mirror for https://github.com/getsentry/sentry-cocoa to add support for binary (xcframework) distribution with swift package manager.
Shell
4
star
45

CAKeyFrameAnimation-Evaluators

Easily specify CAKeyFrameAnimation curves using C functions or ObjC Class
Objective-C
3
star
46

ZoomableListController

Apple's iOS Weather App List Imitation written in Swift
Swift
2
star
47

MeetingBot

Your next call on Mac status bar
Swift
2
star
48

Konsole

In-app Swift tools for great iOS developers
1
star
49

DMGrid

A simple 2D Grid class made in Objective-C
Objective-C
1
star
50

Envy

Type safe environment variables from shell processes and .env files
1
star