 
 // MARK: Mm - Move
 
-private func moveTo (numbers: [CGFloat], lastCommand: SVGCommand?, coords: Coordinates) -> [SVGCommand] {
-    return take(numbers, 2, lastCommand) {
-        (nums:Slice<CGFloat>, last: SVGCommand?) -> SVGCommand in
-        return SVGCommand(nums[0], nums[1], type: .Move)
-    }
+private func moveTo (numbers: Slice<CGFloat>, last: SVGCommand?, coords: Coordinates) -> SVGCommand {
+    return SVGCommand(numbers[0], numbers[1], type: .Move)
 }
 
 // MARK: Ll - Line
 
-private func lineTo (numbers: [CGFloat], lastCommand: SVGCommand?, coords: Coordinates) -> [SVGCommand] {
-    return take(numbers, 2, lastCommand) {
-        (nums:Slice<CGFloat>, last: SVGCommand?) -> SVGCommand in
-        return SVGCommand(nums[0], nums[1], type: .Line)
-    }
+private func lineTo (numbers: Slice<CGFloat>, last: SVGCommand?, coords: Coordinates) -> SVGCommand {
+    return SVGCommand(numbers[0], numbers[1], type: .Line)
 }
 
 // MARK: Vv - Vertical Line
 
-private func lineToVertical (numbers: [CGFloat], lastCommand: SVGCommand?, coords: Coordinates) -> [SVGCommand] {
-    return take(numbers, 1, lastCommand) {
-        (nums:Slice<CGFloat>, last: SVGCommand?) -> SVGCommand in
-        return SVGCommand(coords == .Absolute ? last?.point.x ?? 0 : 0, nums[0], type: .Line)
-    }
+private func lineToVertical (numbers: Slice<CGFloat>, last: SVGCommand?, coords: Coordinates) -> SVGCommand {
+    return SVGCommand(coords == .Absolute ? last?.point.x ?? 0 : 0, numbers[0], type: .Line)
 }
 
 // MARK: Hh - Horizontal Line
 
-private func lineToHorizontal (numbers: [CGFloat], lastCommand: SVGCommand?, coords: Coordinates) -> [SVGCommand] {
-    return take(numbers, 1, lastCommand) {
-        (nums:Slice<CGFloat>, last: SVGCommand?) -> SVGCommand in
-        return SVGCommand(nums[0], coords == .Absolute ? last?.point.y ?? 0 : 0, type: .Line)
-    }
+private func lineToHorizontal (numbers: Slice<CGFloat>, last: SVGCommand?, coords: Coordinates) -> SVGCommand {
+    return SVGCommand(numbers[0], coords == .Absolute ? last?.point.y ?? 0 : 0, type: .Line)
 }
 
 // MARK: Qq - Quadratic Curve To
 
-private func quadBroken (numbers: [CGFloat], lastCommand: SVGCommand?, coords: Coordinates) -> [SVGCommand] {
-    return take(numbers, 4, lastCommand) {
-        (nums:Slice<CGFloat>, last: SVGCommand?) -> SVGCommand in
-        return SVGCommand(nums[0], nums[1], nums[2], nums[3])
-    }
+private func quadBroken (numbers: Slice<CGFloat>, last: SVGCommand?, coords: Coordinates) -> SVGCommand {
+    return SVGCommand(numbers[0], numbers[1], numbers[2], numbers[3])
 }
 
 // MARK: Tt - Smooth Quadratic Curve To
 
-private func quadSmooth (numbers: [CGFloat], lastCommand: SVGCommand?, coords: Coordinates) -> [SVGCommand] {
-    return take(numbers, 2, lastCommand) {
-        (nums:Slice<CGFloat>, last: SVGCommand?) -> SVGCommand in
-        let lastControl = last?.control1 ?? CGPoint()
-        let lastPoint = last?.point ?? CGPoint()
-        var control = lastPoint - lastControl
-        if coords == .Absolute {
-            control = control + lastPoint
-        }
-        return SVGCommand(control.x, control.y, nums[0], nums[1])
-    }
+private func quadSmooth (numbers: Slice<CGFloat>, last: SVGCommand?, coords: Coordinates) -> SVGCommand {
+    let lastControl = last?.control1 ?? CGPoint()
+    let lastPoint = last?.point ?? CGPoint()
+    var control = lastPoint - lastControl
+    if coords == .Absolute {
+        control = control + lastPoint
+    }
+    return SVGCommand(control.x, control.y, numbers[0], numbers[1])
 }
 
 // MARK: Cc - Cubic Curve To
 
-private func cubeBroken (numbers: [CGFloat], lastCommand: SVGCommand?, coords: Coordinates) -> [SVGCommand] {
-    return take(numbers, 6, lastCommand) {
-        (nums:Slice<CGFloat>, last: SVGCommand?) -> SVGCommand in
-        return SVGCommand(nums[0], nums[1], nums[2], nums[3], nums[4], nums[5])
-    }
+private func cubeBroken (numbers: Slice<CGFloat>, last: SVGCommand?, coords: Coordinates) -> SVGCommand {
+    return SVGCommand(numbers[0], numbers[1], numbers[2], numbers[3], numbers[4], numbers[5])
 }
 
 // MARK: Ss - Smooth Cubic Curve To
 
-private func cubeSmooth (numbers: [CGFloat], lastCommand: SVGCommand?, coords: Coordinates) -> [SVGCommand] {
-    return take(numbers, 4, lastCommand) {
-        (nums:Slice<CGFloat>, last: SVGCommand?) -> SVGCommand in
-        var lastControl = last?.control2 ?? CGPoint()
-        let lastPoint = last?.point ?? CGPoint()
-        if (last?.type ?? .Line) != .CubeCurve {
-            lastControl = lastPoint
-        }
-        var control = lastPoint - lastControl
-        if coords == .Absolute {
-            control = control + lastPoint
-        }
-        return SVGCommand(control.x, control.y, nums[0], nums[1], nums[2], nums[3])
-    }
-}
+private func cubeSmooth (numbers: Slice<CGFloat>, last: SVGCommand?, coords: Coordinates) -> SVGCommand {
+    var lastControl = last?.control2 ?? CGPoint()
+    let lastPoint = last?.point ?? CGPoint()
+    if (last?.type ?? .Line) != .CubeCurve {
+        lastControl = lastPoint
+    }
+    var control = lastPoint - lastControl
+    if coords == .Absolute {
+        control = control + lastPoint
+    }
+    return SVGCommand(control.x, control.y, numbers[0], numbers[1], numbers[2], numbers[3])
+}

    
    for var i = 0; i < count; i += stride {
        let nums = numbers[i..<i + stride]
        lastCommand = callback(nums, lastCommand)
        out.append(lastCommand!)
    }
    


public class SVGPath {
    public var commands: [SVGCommand] = []
    private var builder: SVGCommandBuilder = moveTo
    private var coords: Coordinates = .Absolute
    private var stride: Int = 2
    private var numbers = ""

    public init (_ string: String) {
        for char in string {
            switch char {
            case "M": use(.Absolute, 2, moveTo)
            case "m": use(.Relative, 2, moveTo)
            case "L": use(.Absolute, 2, lineTo)
            case "l": use(.Relative, 2, lineTo)
            case "V": use(.Absolute, 1, lineToVertical)
            case "v": use(.Relative, 1, lineToVertical)
            case "H": use(.Absolute, 1, lineToHorizontal)
            case "h": use(.Relative, 1, lineToHorizontal)
            case "Q": use(.Absolute, 4, quadBroken)
            case "q": use(.Relative, 4, quadBroken)
            case "T": use(.Absolute, 2, quadSmooth)
            case "t": use(.Relative, 2, quadSmooth)
            case "C": use(.Absolute, 6, cubeBroken)
            case "c": use(.Relative, 6, cubeBroken)
            case "S": use(.Absolute, 4, cubeSmooth)
            case "s": use(.Relative, 4, cubeSmooth)
            default: numbers.append(char)
            }
        }
        finishLastCommand()
    }
    
    private func use (coords: Coordinates, _ stride: Int, _ builder: SVGCommandBuilder) {
        finishLastCommand()
        self.builder = builder
        self.coords = coords
        self.stride = stride
    }
    
    private func finishLastCommand () {
        for command in take(SVGPath.parseNumbers(numbers), stride, coords, commands.last, builder) {
            commands.append(coords == .Relative ? command.relativeTo(commands.last) : command)
        }
        numbers = ""
    }
