234 lines
9.9 KiB
Swift
234 lines
9.9 KiB
Swift
//
|
|
// FileOperations.swift
|
|
// Docsis Toolkit
|
|
//
|
|
// Created by Kilian Hofmann on 19.06.17.
|
|
// Copyright © 2017 Kilian Hofmann. All rights reserved.
|
|
//
|
|
|
|
import Cocoa
|
|
|
|
class FileOperations: NSObject {
|
|
|
|
// MARK: - Timestamp related
|
|
// 15 in threshold indicates some error
|
|
|
|
static func encodeTimeStamp(stamp: String, threshold: String) -> UInt32 {
|
|
let mappingEncode: Dictionary<String, UInt32> = ["-" : 0, "62.81": 1, "58.21": 2, "57": 3, "59.81": 4, "55.21": 5, "54": 6, "56.81": 7, "52.21": 8, "51": 9]
|
|
let separated: Array<String> = stamp.components(separatedBy: ":")
|
|
let hours: UInt32 = UInt32(separated[0])! << 16
|
|
let minutes: UInt32 = UInt32(separated[1])! << 10
|
|
let seconds: UInt32 = UInt32(separated[2])! << 4
|
|
let thresholdI: UInt32 = mappingEncode[threshold] ?? 15
|
|
return hours | seconds | minutes | thresholdI
|
|
}
|
|
|
|
static func decodeTimestamp(stamp: UInt32) -> (String, String) {
|
|
let mappingDecode: Dictionary<UInt32, String> = [0: "-", 1: "62.81", 2: "58.21", 3: "57", 4: "59.81", 5: "55.21", 6: "54", 7: "56.81", 8: "52.21", 9: "51"]
|
|
let threshold: UInt32 = stamp & 0b1111
|
|
let seconds: UInt32 = (stamp >> 4) & 0b111111
|
|
let minutes: UInt32 = (stamp >> 10) & 0b111111
|
|
let hours: UInt32 = (stamp >> 16) & 0b11111
|
|
return ("\(hours):\(minutes):\(seconds)", mappingDecode[threshold] ?? "\(15)")
|
|
|
|
}
|
|
|
|
// MARK: - Loss log related
|
|
|
|
static func log(data: String, toLog path: String) {
|
|
let dataToWrite = encodeTimeStamp(stamp: data, threshold: "")
|
|
let file: UnsafeMutableRawPointer = UnsafeMutableRawPointer.allocate(bytes: 3, alignedTo: 1)
|
|
file.storeBytes(of: dataToWrite, as: UInt32.self)
|
|
file.deallocate(bytes: 3, alignedTo: 1)
|
|
do {
|
|
let fileData: NSMutableData = try NSMutableData(contentsOf: URL(fileURLWithPath: path))
|
|
fileData.append(file, length: 3)
|
|
fileData.write(to: URL(fileURLWithPath: path), atomically: true)
|
|
} catch _ {
|
|
let fileData: NSMutableData = NSMutableData()
|
|
fileData.append(file, length: 3)
|
|
fileData.write(to: URL(fileURLWithPath: path), atomically: true)
|
|
}
|
|
}
|
|
|
|
static func load(log Data: NSData) -> [String]? {
|
|
var returnString: [String] = []
|
|
var i: Int = 0
|
|
while i < Data.length {
|
|
let data: UnsafeMutableRawPointer = UnsafeMutableRawPointer.allocate(bytes: 3, alignedTo: 1)
|
|
Data.getBytes(data, range: NSRange(location: i, length: 3))
|
|
returnString.append("\(decodeTimestamp(stamp: data.load(as: UInt32.self)).0)\n")
|
|
data.deallocate(bytes: 3, alignedTo: 1)
|
|
i += 3
|
|
}
|
|
if returnString.count > 0 {
|
|
return returnString
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// MARK: - Frequency logging (encoding)
|
|
|
|
static func logUpstream(data: String, toFrequencyLog path: String) {
|
|
let separated: Array<String> = data.components(separatedBy: ";")
|
|
var encodedTime: UInt32 = encodeTimeStamp(stamp: separated[0], threshold: separated[2])
|
|
// NaN Used for -
|
|
var encodedPower: Int32 = Int32.min
|
|
if (Double(separated[1]) != nil) {
|
|
encodedPower = Int32(Double(Double(separated[1])! * 100.0))
|
|
}
|
|
var stringSize: UInt8 = UInt8(separated[3].lengthOfBytes(using: .ascii))
|
|
|
|
let fileContent: NSMutableData = NSMutableData()
|
|
fileContent.append(&stringSize, length: 1)
|
|
fileContent.append(&encodedTime, length: 3)
|
|
fileContent.append(&encodedPower, length: 4)
|
|
fileContent.append(separated[3].data(using: .ascii)!)
|
|
|
|
do {
|
|
let fileData: NSMutableData = try NSMutableData(contentsOf: URL(fileURLWithPath: path))
|
|
fileData.append(fileContent as Data)
|
|
fileData.write(to: URL(fileURLWithPath: path), atomically: true)
|
|
} catch _ {
|
|
fileContent.write(to: URL(fileURLWithPath: path), atomically: true)
|
|
}
|
|
}
|
|
|
|
static func logDownstream(data: String, toFrequencyLog path: String) {
|
|
let separated: Array<String> = data.components(separatedBy: ";")
|
|
var encodedTime: UInt32 = encodeTimeStamp(stamp: separated[0], threshold: "")
|
|
// NaN Used for -
|
|
var encodedPower: Int32 = Int32.min
|
|
if (Double(separated[1]) != nil) {
|
|
encodedPower = Int32(Double(Double(separated[1])! * 100.0))
|
|
}
|
|
var encodedSNR = UInt8(separated[2]) ?? UInt8.max
|
|
|
|
let fileContent: NSMutableData = NSMutableData()
|
|
fileContent.append(&encodedTime, length: 3)
|
|
fileContent.append(&encodedPower, length: 4)
|
|
fileContent.append(&encodedSNR, length: 1)
|
|
|
|
do {
|
|
let fileData: NSMutableData = try NSMutableData(contentsOf: URL(fileURLWithPath: path))
|
|
fileData.append(fileContent as Data)
|
|
fileData.write(to: URL(fileURLWithPath: path), atomically: true)
|
|
} catch _ {
|
|
fileContent.write(to: URL(fileURLWithPath: path), atomically: true)
|
|
}
|
|
}
|
|
|
|
// MARK: - Frequency loading (decoding)
|
|
|
|
static func loadUpstream(log data: NSData) -> [String]? {
|
|
var variableAdjust: Int = 0
|
|
var returnString: [String] = []
|
|
|
|
while variableAdjust < data.length {
|
|
// 1 for size
|
|
// 3 for time and threshold
|
|
// 4 for Power
|
|
// var String
|
|
|
|
let decodedSize: UInt8 = data.bytes.load(fromByteOffset: variableAdjust, as: UInt8.self)
|
|
variableAdjust += 1
|
|
|
|
let retTimePtr: UnsafeMutableRawPointer = UnsafeMutableRawPointer.allocate(bytes: 3, alignedTo: 1)
|
|
data.getBytes(retTimePtr, range: NSRange(location: variableAdjust, length: 3))
|
|
variableAdjust += 3
|
|
let encodedTime: UInt32 = retTimePtr.load(as: UInt32.self)
|
|
retTimePtr.deallocate(bytes: 3, alignedTo: 1)
|
|
|
|
let decodedTimeStamp = decodeTimestamp(stamp: encodedTime).0
|
|
let decodedThreshold = decodeTimestamp(stamp: encodedTime).1
|
|
|
|
let retPwrPtr: UnsafeMutableRawPointer = UnsafeMutableRawPointer.allocate(bytes: 4, alignedTo: 1)
|
|
data.getBytes(retPwrPtr, range: NSRange(location: variableAdjust, length: 4))
|
|
var decodedPower: Any = retPwrPtr.load(as: Int32.self)
|
|
retPwrPtr.deallocate(bytes: 4, alignedTo: 1)
|
|
if decodedPower as! Int32 == Int32.min {
|
|
decodedPower = "-"
|
|
}
|
|
variableAdjust += 4
|
|
|
|
let retStringPtr: UnsafeMutableRawPointer = UnsafeMutableRawPointer.allocate(bytes: Int(decodedSize), alignedTo: 1)
|
|
data.getBytes(retStringPtr, range: NSRange(location: variableAdjust, length: Int(decodedSize)))
|
|
var retString: String = String(cString: retStringPtr.assumingMemoryBound(to: UInt8.self))
|
|
retStringPtr.deallocate(bytes: Int(decodedSize), alignedTo: 1)
|
|
retString = retString.substring(to: retString.index(retString.startIndex, offsetBy: Int(decodedSize)))
|
|
variableAdjust += Int(decodedSize)
|
|
|
|
guard decodedPower is Int32 else {
|
|
returnString.append("\(decodedTimeStamp);\(decodedPower as! String);\(decodedThreshold);\(retString)")
|
|
continue
|
|
}
|
|
returnString.append("\(decodedTimeStamp);\((Double(decodedPower as! Int32) / 100.0));\(decodedThreshold);\(retString)")
|
|
}
|
|
if returnString.count > 0 {
|
|
return returnString
|
|
}
|
|
return nil
|
|
}
|
|
|
|
static func loadDownstream(log data: NSData) -> [String]? {
|
|
var variableAdjust: Int = 0
|
|
var returnString: [String] = []
|
|
|
|
while variableAdjust < data.length {
|
|
// 3 for time
|
|
// 4 for Power
|
|
// 1 for SNR
|
|
|
|
let retTimePtr: UnsafeMutableRawPointer = UnsafeMutableRawPointer.allocate(bytes: 3, alignedTo: 1)
|
|
data.getBytes(retTimePtr, range: NSRange(location: variableAdjust, length: 3))
|
|
variableAdjust += 3
|
|
let encodedTime: UInt32 = retTimePtr.load(as: UInt32.self)
|
|
|
|
let decodedTimeStamp = decodeTimestamp(stamp: encodedTime).0
|
|
|
|
let retPwrPtr: UnsafeMutableRawPointer = UnsafeMutableRawPointer.allocate(bytes: 4, alignedTo: 1)
|
|
data.getBytes(retPwrPtr, range: NSRange(location: variableAdjust, length: 4))
|
|
var decodedPower: Any = retPwrPtr.load(as: Int32.self)
|
|
retPwrPtr.deallocate(bytes: 4, alignedTo: 1)
|
|
if decodedPower as! Int32 == Int32.min {
|
|
decodedPower = "-"
|
|
}
|
|
variableAdjust += 4
|
|
|
|
var decodedSNR: Any = data.bytes.load(fromByteOffset: variableAdjust, as: UInt8.self)
|
|
if decodedSNR as! UInt8 == UInt8.max {
|
|
decodedSNR = "-"
|
|
}
|
|
variableAdjust += 1
|
|
|
|
var entry: String = ""
|
|
|
|
guard decodedPower is Int32 else {
|
|
entry.append("\(decodedTimeStamp);\(decodedPower as! String);")
|
|
guard decodedSNR is UInt8 else {
|
|
entry.append("\(decodedSNR as! String)")
|
|
returnString.append(entry)
|
|
continue
|
|
}
|
|
entry.append("\(decodedSNR as! UInt8)")
|
|
returnString.append(entry)
|
|
continue
|
|
}
|
|
entry.append("\(decodedTimeStamp);\((Double(decodedPower as! Int32) / 100.0));")
|
|
|
|
guard decodedSNR is UInt8 else {
|
|
entry.append("\(decodedSNR as! String)")
|
|
returnString.append(entry)
|
|
continue
|
|
}
|
|
entry.append("\(decodedSNR as! UInt8)")
|
|
|
|
returnString.append(entry)
|
|
}
|
|
if returnString.count > 0 {
|
|
return returnString
|
|
}
|
|
return nil
|
|
}
|
|
}
|