Skip to content

Commit

Permalink
Include Initial Code for Barcode and Barcode Parser
Browse files Browse the repository at this point in the history
  • Loading branch information
xremix committed Jun 26, 2017
1 parent ad1eb89 commit 59f9456
Show file tree
Hide file tree
Showing 10 changed files with 304 additions and 9 deletions.
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# SwiftGS1Barcode
A GS1 Barcode Library and Parser for Swift Edit

CocoaPod
https://github.com/xremix/SwiftGS1Barcode
## CocoaPod
https://github.com/xremix/SwiftGS1Barcode

## Deployment Steps:
- Update Version
- Push Code to Git
- Create Release on Git
- `pod lib lint`
- `pod trunk push SwiftGS1Barcode.podspec`
4 changes: 2 additions & 2 deletions SwiftGS1Barcode.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'SwiftGS1Barcode'
s.version = '0.0.3'
s.version = '0.1.0'
s.summary = 'A GS1 Barcode Library and Parser for Swift'

s.description = <<-DESC
Expand All @@ -15,4 +15,4 @@ A GS1 Barcode Library and Parser for Swift. It allows to pass strings and valida
s.ios.deployment_target = '9.0'
s.source_files = 'SwiftGS1Barcode/*.swift'

end
end
24 changes: 24 additions & 0 deletions SwiftGS1Barcode.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@

/* Begin PBXBuildFile section */
64754CFE1F010A1000B22B62 /* GS1Barcode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64754CFD1F010A1000B22B62 /* GS1Barcode.swift */; };
64754D001F010E8400B22B62 /* BarcodeParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64754CFF1F010E8400B22B62 /* BarcodeParser.swift */; };
64754D021F010E9100B22B62 /* Barcode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64754D011F010E9100B22B62 /* Barcode.swift */; };
64754D041F010EA000B22B62 /* SimpleBarcode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64754D031F010EA000B22B62 /* SimpleBarcode.swift */; };
64754D061F010EBB00B22B62 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64754D051F010EBB00B22B62 /* StringExtension.swift */; };
64754D081F010ECA00B22B62 /* DateExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64754D071F010ECA00B22B62 /* DateExtension.swift */; };
64754D0A1F010EFA00B22B62 /* SwiftGS1Barcode.podspec in Resources */ = {isa = PBXBuildFile; fileRef = 64754D091F010EFA00B22B62 /* SwiftGS1Barcode.podspec */; };
64AE611D1F01081800F3B9C0 /* SwiftGS1Barcode.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 64AE61131F01081800F3B9C0 /* SwiftGS1Barcode.framework */; };
64AE61221F01081800F3B9C0 /* SwiftGS1BarcodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64AE61211F01081800F3B9C0 /* SwiftGS1BarcodeTests.swift */; };
64AE61241F01081800F3B9C0 /* SwiftGS1Barcode.h in Headers */ = {isa = PBXBuildFile; fileRef = 64AE61161F01081800F3B9C0 /* SwiftGS1Barcode.h */; settings = {ATTRIBUTES = (Public, ); }; };
Expand All @@ -25,6 +31,12 @@

/* Begin PBXFileReference section */
64754CFD1F010A1000B22B62 /* GS1Barcode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GS1Barcode.swift; sourceTree = "<group>"; };
64754CFF1F010E8400B22B62 /* BarcodeParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BarcodeParser.swift; sourceTree = "<group>"; };
64754D011F010E9100B22B62 /* Barcode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Barcode.swift; sourceTree = "<group>"; };
64754D031F010EA000B22B62 /* SimpleBarcode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SimpleBarcode.swift; sourceTree = "<group>"; };
64754D051F010EBB00B22B62 /* StringExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringExtension.swift; sourceTree = "<group>"; };
64754D071F010ECA00B22B62 /* DateExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateExtension.swift; sourceTree = "<group>"; };
64754D091F010EFA00B22B62 /* SwiftGS1Barcode.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SwiftGS1Barcode.podspec; sourceTree = "<group>"; };
64AE61131F01081800F3B9C0 /* SwiftGS1Barcode.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftGS1Barcode.framework; sourceTree = BUILT_PRODUCTS_DIR; };
64AE61161F01081800F3B9C0 /* SwiftGS1Barcode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SwiftGS1Barcode.h; sourceTree = "<group>"; };
64AE61171F01081800F3B9C0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
Expand Down Expand Up @@ -55,6 +67,7 @@
64AE61091F01081800F3B9C0 = {
isa = PBXGroup;
children = (
64754D091F010EFA00B22B62 /* SwiftGS1Barcode.podspec */,
64AE61151F01081800F3B9C0 /* SwiftGS1Barcode */,
64AE61201F01081800F3B9C0 /* SwiftGS1BarcodeTests */,
64AE61141F01081800F3B9C0 /* Products */,
Expand All @@ -76,6 +89,11 @@
64AE61161F01081800F3B9C0 /* SwiftGS1Barcode.h */,
64AE61171F01081800F3B9C0 /* Info.plist */,
64754CFD1F010A1000B22B62 /* GS1Barcode.swift */,
64754CFF1F010E8400B22B62 /* BarcodeParser.swift */,
64754D011F010E9100B22B62 /* Barcode.swift */,
64754D031F010EA000B22B62 /* SimpleBarcode.swift */,
64754D051F010EBB00B22B62 /* StringExtension.swift */,
64754D071F010ECA00B22B62 /* DateExtension.swift */,
);
path = SwiftGS1Barcode;
sourceTree = "<group>";
Expand Down Expand Up @@ -185,6 +203,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
64754D0A1F010EFA00B22B62 /* SwiftGS1Barcode.podspec in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -202,7 +221,12 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
64754D041F010EA000B22B62 /* SimpleBarcode.swift in Sources */,
64754D081F010ECA00B22B62 /* DateExtension.swift in Sources */,
64754CFE1F010A1000B22B62 /* GS1Barcode.swift in Sources */,
64754D061F010EBB00B22B62 /* StringExtension.swift in Sources */,
64754D001F010E8400B22B62 /* BarcodeParser.swift in Sources */,
64754D021F010E9100B22B62 /* Barcode.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
27 changes: 27 additions & 0 deletions SwiftGS1Barcode/Barcode.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// Barcode.swift
// SwiftGS1Barcode
//
// Created by Toni Hoffmann on 26.06.17.
// Copyright © 2017 Toni Hoffmann. All rights reserved.
//

import UIKit

protocol Barcode {
// Properties
var raw: String? {get set}

// Initializers
init()
init(raw: String)

// Functions
func validate() -> Bool
func parse() -> Bool

// Static Functions
// static func tryParse(raw: String) -> Bool
// static func parse(raw:String ) ->Barcode

}
56 changes: 56 additions & 0 deletions SwiftGS1Barcode/BarcodeParser.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//
// BarcodeParser.swift
// SwiftGS1Barcode
//
// Created by Toni Hoffmann on 26.06.17.
// Copyright © 2017 Toni Hoffmann. All rights reserved.
//

import UIKit

class GS1BarcodeParser: NSObject {
static func reduce(data: String?, by node: GS1Node)->String?{
if data == nil{
return data
}

var length = (node.value?.length ?? 0) + (node.identifier.length)
if (node.type == .GroupSeperatorBased || node.type == .GroupSeperatorBasedInt) && length < data!.length{
length += 1
}
return data!.substring(from: length)
}
static func parseGS1Node(node: GS1Node, data: String)->GS1Node{
print("Parsing node of type \(node.type.description) with identifier \(node.identifier)")
switch node.type {
case .GTIN:
node.value = data.substring(node.identifier.length, length: node.type.fixedValueLength!)
// GETINIndicatorDigit
break
case .GroupSeperatorBased, .GroupSeperatorBasedInt:
if !data.contains("\u{1D}") {
node.value = data.substring(from: node.identifier.length)
}else{
let toi = data.index(of: "\u{1D}")
let to = data.distance(from: data.startIndex, to: toi ?? data.startIndex)

node.value = data.substring(node.identifier.length, to: to)
}
if node.type == .GroupSeperatorBasedInt{
node.rawValue = Int(node.value!)
}

case .Date:
node.rawValue = NSDate.from(
year: Int("20" + data.substring(2, length: 2)),
month: Int(data.substring(4, length: 2)),
day: Int(data.substring(6, length: 2))
)
node.value = data.substring(2, length: 6)
}
if node.rawValue == nil{
node.rawValue = node.value
}
return node
}
}
25 changes: 25 additions & 0 deletions SwiftGS1Barcode/DateExtension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// DateExtension.swift
// SwiftGS1Barcode
//
// Created by Toni Hoffmann on 26.06.17.
// Copyright © 2017 Toni Hoffmann. All rights reserved.
//

import UIKit

extension NSDate{
static func from(year: Int?, month: Int?, day: Int?)->NSDate{

var dateComponents = DateComponents()
dateComponents.year = year
dateComponents.month = month
dateComponents.day = day

// Create date from components
let userCalendar = NSCalendar.current
let someDateTime = userCalendar.date(from: dateComponents)
return someDateTime! as NSDate

}
}
90 changes: 86 additions & 4 deletions SwiftGS1Barcode/GS1Barcode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,100 @@

import UIKit

class GS1Barcode: NSObject {
class GS1BarcodePretty: GS1Barcode{

}

enum GS1Type: String{
case GTIN
case GroupSeperatorBased
case GroupSeperatorBasedInt
case Date
var description: String{
return self.rawValue
}
var fixedValueLength: Int?{
if self == .GTIN{
return 14
}
return nil
}
}

class GS1Node: NSObject{
var identifier: String
var type: GS1Type
var value: String?
var rawValue: Any?
var dateValue: NSDate?{ return rawValue as? NSDate }
var intValue: Int?{ return rawValue as? Int }

init(identifier: String, type: GS1Type){
self.identifier = identifier
self.type = type
}
}

struct GS1Nodes{
var gtinNode = GS1Node(identifier: "01", type: .GTIN)
var lotNumberNode = GS1Node(identifier: "10", type: .GroupSeperatorBased)
var expirationDateNode = GS1Node(identifier: "17", type: .Date)
var serialNumberNode = GS1Node(identifier: "21", type: .GroupSeperatorBased)
var amountNode = GS1Node(identifier: "30", type: .GroupSeperatorBasedInt)
}

class GS1Barcode: NSObject, Barcode {
var raw: String?
var nodes = GS1Nodes()

var gtin: String?{ get {return nodes.gtinNode.value} }
var lotNumber: String?{ get {return nodes.lotNumberNode.value} }
var expirationDate: NSDate?{ get {return nodes.expirationDateNode.dateValue} }
var serialNumber: String?{ get {return nodes.serialNumberNode.value} }
var amount: Int?{ get {return nodes.amountNode.intValue} }

required override init() {
super.init()
}
required init(raw: String) {
super.init()
self.raw = raw
_ = parse()
}
func validate() -> Bool {
return raw != nil && raw! != ""
return gtin != nil
}
func parse()->Bool {
return validate()

func parse() ->Bool{
var data = raw

if data != nil{
while data!.characters.count > 0 {
if(data!.startsWith("\u{1D}")){
data = data!.substring(from: 1)
}

if(data!.startsWith(nodes.gtinNode.identifier)){
nodes.gtinNode = GS1BarcodeParser.parseGS1Node(node: nodes.gtinNode, data: data!)
data = GS1BarcodeParser.reduce(data: data, by: nodes.gtinNode)
}else if(data!.startsWith(nodes.lotNumberNode.identifier)){
nodes.lotNumberNode = GS1BarcodeParser.parseGS1Node(node: nodes.lotNumberNode, data: data!)
data = GS1BarcodeParser.reduce(data: data, by: nodes.lotNumberNode)
}else if(data!.startsWith(nodes.expirationDateNode.identifier)){
nodes.expirationDateNode = GS1BarcodeParser.parseGS1Node(node: nodes.expirationDateNode, data: data!)
data = GS1BarcodeParser.reduce(data: data, by: nodes.expirationDateNode)
}else if(data!.startsWith(nodes.serialNumberNode.identifier)){
nodes.serialNumberNode = GS1BarcodeParser.parseGS1Node(node: nodes.serialNumberNode, data: data!)
data = GS1BarcodeParser.reduce(data: data, by: nodes.serialNumberNode)
}else if(data!.startsWith(nodes.amountNode.identifier)){
nodes.amountNode = GS1BarcodeParser.parseGS1Node(node: nodes.amountNode, data: data!)
data = GS1BarcodeParser.reduce(data: data, by: nodes.amountNode)
}else{
print("Do not know identifier. Canceling Parsing")
return false
}
}
}
return true
}
}
2 changes: 1 addition & 1 deletion SwiftGS1Barcode/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>0.0.3</string>
<string>0.1.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
Expand Down
26 changes: 26 additions & 0 deletions SwiftGS1Barcode/SimpleBarcode.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// SimpleBarcode.swift
// SwiftGS1Barcode
//
// Created by Toni Hoffmann on 26.06.17.
// Copyright © 2017 Toni Hoffmann. All rights reserved.
//

import UIKit

class SimpleBarcode: NSObject, Barcode {
var raw: String?
required override init() {
super.init()
}
required init(raw: String) {
self.raw = raw
}
func validate() -> Bool {
return raw != nil && raw! != ""
}
func parse()->Bool {
return validate()
}

}
48 changes: 48 additions & 0 deletions SwiftGS1Barcode/StringExtension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//
// StringExtension.swift
// SwiftGS1Barcode
//
// Created by Toni Hoffmann on 26.06.17.
// Copyright © 2017 Toni Hoffmann. All rights reserved.
//

import UIKit

extension String{
func substring(_ from: Int, length: Int)->String{
let start = self.index(self.startIndex, offsetBy: from)
let end = self.index(start, offsetBy: length)
let range = start..<end


return self.substring(with: range) // play
}
func substring(_ from: Int, to: Int)->String{
return self.substring(from, length: to-from)
}
func substring(from: Int)->String{
return self.substring(from, length: self.length - from)
}

func substring(to: Int)->String{
return self.substring(0, length: to)
}
func substring(to: String)->String{
if let index = self.index(of: to){
return self.substring(to:index)
}
return self
}
func index(of string: String, options: CompareOptions = .literal) -> Index? {
return range(of: string, options: options)?.lowerBound
}

func startsWith(_ subString: String)->Bool{
return self.hasPrefix(subString)
}
var length: Int{
get{
return self.characters.count
}
}
}

0 comments on commit 59f9456

Please sign in to comment.