CommandLineToolkit

Форк
0
/
NumberValidator.swift 
72 строки · 3.1 Кб
1
import Foundation
2

3
class NumberValidator {
4
    private static let unsupportedCharacterSet = CharacterSet(charactersIn: "-+0123456789eE.").inverted
5
    private static let exponentialSeparator = CharacterSet(charactersIn: "eE")
6
    
7
    static let numberFormatter: NumberFormatter = {
8
        let formatter = NumberFormatter()
9
        formatter.numberStyle = .decimal
10
        formatter.locale = Locale(identifier: "en_US")
11
        return formatter
12
    }()
13
    
14
    enum `Error`: Swift.Error {
15
        case invalidNumber(String)
16
        case invalidIntPart(String)
17
        case invalidFractionalPart(String)
18
        case invalidExponentialPart(String)
19
    }
20
    
21
    static func validateStringRepresentationOfNumber(_ string: String) throws -> NSNumber {
22
        guard string.rangeOfCharacter(from: unsupportedCharacterSet) == nil else {
23
            throw Error.invalidNumber(string)
24
        }
25
        
26
        let parts = string.components(separatedBy: ".")
27
        
28
        if parts.count == 1 {
29
            let intAndExponentialParts = parts[0].components(separatedBy: exponentialSeparator)
30
            try validateIntPartOfNumber(intAndExponentialParts[0])
31
            if intAndExponentialParts.count == 2 {
32
                try validateExponentialPartOfNumber(intAndExponentialParts[1])
33
            } else if intAndExponentialParts.count > 2 {
34
                throw Error.invalidNumber(string)
35
            }
36
        } else if parts.count == 2 {
37
            try validateIntPartOfNumber(parts[0])
38
            let fractionalAndExponentialParts = parts[1].components(separatedBy: exponentialSeparator)
39
            try validateFractionalPartOfNumber(fractionalAndExponentialParts[0])
40
            if fractionalAndExponentialParts.count == 2 {
41
                try validateExponentialPartOfNumber(fractionalAndExponentialParts[1])
42
            } else if fractionalAndExponentialParts.count > 2 {
43
                throw Error.invalidNumber(string)
44
            }
45
        } else {
46
            throw Error.invalidNumber(string)
47
        }
48
        
49
        if let number = numberFormatter.number(from: string) {
50
            return number
51
        } else {
52
            throw Error.invalidNumber(string)
53
        }
54
    }
55
    
56
    static func validateIntPartOfNumber(_ string: String) throws {
57
        var intPart = string
58
        if intPart.starts(with: "-") { intPart.removeFirst() }
59
        guard intPart.rangeOfCharacter(from: CharacterSet(charactersIn: "+eE")) == nil else { throw Error.invalidIntPart(string) }
60
        guard !intPart.isEmpty else { throw Error.invalidIntPart(string) }
61
        if intPart.contains("+") { throw Error.invalidIntPart(string) }
62
        if intPart.starts(with: "0") && intPart.count > 1 { throw Error.invalidIntPart(string) }
63
    }
64
    
65
    static func validateFractionalPartOfNumber(_ fractionalPart: String) throws {
66
        guard !fractionalPart.isEmpty else { throw Error.invalidFractionalPart(fractionalPart) }
67
    }
68
    
69
    static func validateExponentialPartOfNumber(_ exponentialPart: String) throws {
70
        guard !exponentialPart.isEmpty else { throw Error.invalidExponentialPart(exponentialPart) }
71
    }
72
}
73

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.