Skip to content

Instantly share code, notes, and snippets.

@natecook1000
Forked from davepeck/BinaryDataScanner.swift
Last active August 29, 2015 14:04
Show Gist options
  • Save natecook1000/c3ed7164340dbbd45baa to your computer and use it in GitHub Desktop.
Save natecook1000/c3ed7164340dbbd45baa to your computer and use it in GitHub Desktop.
import Foundation
/*
Toying with tools to help read binary formats.
I've seen lots of approaches in swift that create
an intermediate object per-read (usually another NSData)
but even if these are lightweight under the hood,
it seems like overkill. Plus this taught me about <()>
*/
protocol BinaryReadable {
var littleEndian: Self { get }
var bigEndian: Self { get }
}
extension UInt8: BinaryReadable {
var littleEndian: UInt8 { return self }
var bigEndian: UInt8 { return self }
}
extension UInt16: BinaryReadable {}
extension UInt32: BinaryReadable {}
extension UInt64: BinaryReadable {}
class BinaryDataScanner {
let data: NSData
let littleEndian: Bool
let encoding: NSStringEncoding
var current: ConstUnsafePointer<()>
var remaining: Int
init(data: NSData, littleEndian: Bool, encoding: NSStringEncoding) {
self.data = data
self.littleEndian = littleEndian
self.encoding = encoding
self.current = self.data.bytes
self.remaining = self.data.length
}
func read<T: BinaryReadable>() -> T? {
let byteCount = sizeof(T)
println(byteCount)
println(remaining)
if remaining < byteCount {
return nil
}
let tCurrent = ConstUnsafePointer<T>(current)
let v = tCurrent.memory
current = ConstUnsafePointer<()>(tCurrent.successor())
remaining -= byteCount
return littleEndian ? v.littleEndian : v.bigEndian
}
func readNullTerminatedString() -> String? {
var string:String? = nil
var tCurrent = ConstUnsafePointer<UInt8>(current)
var count: Int = 0
// scan
while (remaining > 0 && tCurrent.memory != 0) {
remaining -= 1
count += 1
tCurrent = tCurrent.successor()
}
// create string if available
if (remaining > 0 && tCurrent.memory == 0) {
string = NSString(bytes: current, length: count, encoding: encoding) as String
current = ConstUnsafePointer<()>(tCurrent.successor())
remaining -= 1
}
return string
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment