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
10 KiB

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: NSLocalizedString("numbers_0_9", comment: "Numbers 0-9")
)
} else {
return ValidationResult(
isValid: false,
formattedContent: content,
errorMessage: NSLocalizedString("ean_13_must_be_13_digits", comment: "EAN-13 must be 13 digits"),
expectedLength: 13,
allowedCharacters: NSLocalizedString("numbers_0_9", comment: "Numbers 0-9")
)
}
}
// 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: NSLocalizedString("numbers_0_9", comment: "Numbers 0-9")
)
} else {
return ValidationResult(
isValid: false,
formattedContent: content,
errorMessage: NSLocalizedString("ean_8_must_be_8_digits", comment: "EAN-8 must be 8 digits"),
expectedLength: 8,
allowedCharacters: NSLocalizedString("numbers_0_9", comment: "Numbers 0-9")
)
}
}
// 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: NSLocalizedString("numbers_0_9", comment: "Numbers 0-9")
)
} else {
return ValidationResult(
isValid: false,
formattedContent: content,
errorMessage: NSLocalizedString("upc_e_must_be_8_digits", comment: "UPC-E must be 8 digits"),
expectedLength: 8,
allowedCharacters: NSLocalizedString("numbers_0_9", comment: "Numbers 0-9")
)
}
}
// 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: NSLocalizedString("code_39_characters", comment: "Code 39 allowed characters")
)
} else {
return ValidationResult(
isValid: false,
formattedContent: content,
errorMessage: NSLocalizedString("code_39_only_contains", comment: "Code 39 only contains specific characters"),
expectedLength: nil,
allowedCharacters: NSLocalizedString("code_39_characters", comment: "Code 39 allowed characters")
)
}
}
// 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: NSLocalizedString("code_128_characters", comment: "Code 128 allowed characters")
)
} else {
return ValidationResult(
isValid: false,
formattedContent: content,
errorMessage: NSLocalizedString("code_128_only_contains", comment: "Code 128 only contains ASCII characters"),
expectedLength: nil,
allowedCharacters: NSLocalizedString("code_128_characters", comment: "Code 128 allowed characters")
)
}
}
// 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: NSLocalizedString("numbers_0_9", comment: "Numbers 0-9")
)
} else {
return ValidationResult(
isValid: false,
formattedContent: content,
errorMessage: NSLocalizedString("itf_14_must_be_14_digits", comment: "ITF-14 must be 14 digits"),
expectedLength: 14,
allowedCharacters: NSLocalizedString("numbers_0_9", comment: "Numbers 0-9")
)
}
}
// 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: NSLocalizedString("pdf417_characters", comment: "PDF417 allowed characters")
)
} else {
return ValidationResult(
isValid: false,
formattedContent: content,
errorMessage: NSLocalizedString("pdf417_only_contains", comment: "PDF417 only contains ASCII characters"),
expectedLength: nil,
allowedCharacters: NSLocalizedString("pdf417_characters", comment: "PDF417 allowed characters")
)
}
}
// 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)
}
}