You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

275 lines
9.3 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import Foundation
// MARK: -
class BarcodeValidator {
// MARK: -
struct ValidationResult {
let isValid: Bool
let formattedContent: String
let errorMessage: String?
let expectedLength: Int?
let allowedCharacters: String?
}
// MARK: -
static func validateBarcode(_ content: String, type: BarcodeType) -> ValidationResult {
let cleanedContent = content.replacingOccurrences(of: " ", with: "")
switch type {
case .ean13:
return validateEAN13(cleanedContent)
case .ean8:
return validateEAN8(cleanedContent)
case .upce:
return validateUPCE(cleanedContent)
case .code39:
return validateCode39(cleanedContent)
case .code128:
return validateCode128(cleanedContent)
case .itf14:
return validateITF14(cleanedContent)
case .pdf417:
return validatePDF417(cleanedContent)
}
}
// MARK: - EAN-13
private static func validateEAN13(_ content: String) -> ValidationResult {
// EAN-13: 13
let pattern = "^[0-9]{13}$"
let isValid = content.range(of: pattern, options: .regularExpression) != nil
if isValid {
return ValidationResult(
isValid: true,
formattedContent: formatEAN13(content),
errorMessage: nil,
expectedLength: 13,
allowedCharacters: "numbers_0_9".localized
)
} else {
return ValidationResult(
isValid: false,
formattedContent: content,
errorMessage: "ean_13_must_be_13_digits".localized,
expectedLength: 13,
allowedCharacters: "numbers_0_9".localized
)
}
}
// MARK: - EAN-8
private static func validateEAN8(_ content: String) -> ValidationResult {
// EAN-8: 8
let pattern = "^[0-9]{8}$"
let isValid = content.range(of: pattern, options: .regularExpression) != nil
if isValid {
return ValidationResult(
isValid: true,
formattedContent: formatEAN8(content),
errorMessage: nil,
expectedLength: 8,
allowedCharacters: "numbers_0_9".localized
)
} else {
return ValidationResult(
isValid: false,
formattedContent: content,
errorMessage: "ean_8_must_be_8_digits".localized,
expectedLength: 8,
allowedCharacters: "numbers_0_9".localized
)
}
}
// MARK: - UPC-E
private static func validateUPCE(_ content: String) -> ValidationResult {
// UPC-E: 8
let pattern = "^[0-9]{8}$"
let isValid = content.range(of: pattern, options: .regularExpression) != nil
if isValid {
return ValidationResult(
isValid: true,
formattedContent: formatUPCE(content),
errorMessage: nil,
expectedLength: 8,
allowedCharacters: "numbers_0_9".localized
)
} else {
return ValidationResult(
isValid: false,
formattedContent: content,
errorMessage: "upc_e_must_be_8_digits".localized,
expectedLength: 8,
allowedCharacters: "numbers_0_9".localized
)
}
}
// MARK: - Code 39
private static func validateCode39(_ content: String) -> ValidationResult {
// Code 39:
let pattern = "^[A-Z0-9\\s\\-\\+\\.\\/\\$\\(\\)\\%\\s]+$"
let isValid = content.range(of: pattern, options: .regularExpression) != nil
if isValid {
return ValidationResult(
isValid: true,
formattedContent: formatCode39(content),
errorMessage: nil,
expectedLength: nil,
allowedCharacters: "code_39_characters".localized
)
} else {
return ValidationResult(
isValid: false,
formattedContent: content,
errorMessage: "code_39_only_contains".localized,
expectedLength: nil,
allowedCharacters: "code_39_characters".localized
)
}
}
// MARK: - Code 128
private static func validateCode128(_ content: String) -> ValidationResult {
// Code 128: ASCII
let pattern = "^[\\x00-\\x7F]+$"
let isValid = content.range(of: pattern, options: .regularExpression) != nil
if isValid {
return ValidationResult(
isValid: true,
formattedContent: formatCode128(content),
errorMessage: nil,
expectedLength: nil,
allowedCharacters: "code_128_characters".localized
)
} else {
return ValidationResult(
isValid: false,
formattedContent: content,
errorMessage: "code_128_only_contains".localized,
expectedLength: nil,
allowedCharacters: "code_128_characters".localized
)
}
}
// MARK: - ITF-14
private static func validateITF14(_ content: String) -> ValidationResult {
// ITF-14: 14
let pattern = "^[0-9]{14}$"
let isValid = content.range(of: pattern, options: .regularExpression) != nil
if isValid {
return ValidationResult(
isValid: true,
formattedContent: formatITF14(content),
errorMessage: nil,
expectedLength: 14,
allowedCharacters: "numbers_0_9".localized
)
} else {
return ValidationResult(
isValid: false,
formattedContent: content,
errorMessage: "itf_14_must_be_14_digits".localized,
expectedLength: 14,
allowedCharacters: "numbers_0_9".localized
)
}
}
// MARK: - PDF417
private static func validatePDF417(_ content: String) -> ValidationResult {
// PDF417: ASCII
let pattern = "^[\\x00-\\x7F]+$"
let isValid = content.range(of: pattern, options: .regularExpression) != nil
if isValid {
return ValidationResult(
isValid: true,
formattedContent: formatPDF417(content),
errorMessage: nil,
expectedLength: nil,
allowedCharacters: "pdf417_characters".localized
)
} else {
return ValidationResult(
isValid: false,
formattedContent: content,
errorMessage: "pdf417_only_contains".localized,
expectedLength: nil,
allowedCharacters: "pdf417_characters".localized
)
}
}
// MARK: -
private static func formatEAN13(_ content: String) -> String {
// EAN-13:
let formatted = content.enumerated().map { index, char in
if index == 0 || index == 6 || index == 12 {
return " \(char)"
}
return String(char)
}.joined()
return formatted.trimmingCharacters(in: .whitespaces)
}
private static func formatEAN8(_ content: String) -> String {
// EAN-8:
let formatted = content.enumerated().map { index, char in
if index == 0 || index == 4 {
return " \(char)"
}
return String(char)
}.joined()
return formatted.trimmingCharacters(in: .whitespaces)
}
private static func formatUPCE(_ content: String) -> String {
// UPC-E:
let formatted = content.enumerated().map { index, char in
if index == 0 || index == 4 {
return " \(char)"
}
return String(char)
}.joined()
return formatted.trimmingCharacters(in: .whitespaces)
}
private static func formatCode39(_ content: String) -> String {
// Code 39:
return content.trimmingCharacters(in: .whitespaces)
}
private static func formatCode128(_ content: String) -> String {
// Code 128:
return content.trimmingCharacters(in: .whitespaces)
}
private static func formatITF14(_ content: String) -> String {
// ITF-14:
let formatted = content.enumerated().map { index, char in
if index == 0 || index == 5 || index == 10 {
return " \(char)"
}
return String(char)
}.joined()
return formatted.trimmingCharacters(in: .whitespaces)
}
private static func formatPDF417(_ content: String) -> String {
// PDF417:
return content.trimmingCharacters(in: .whitespaces)
}
}