-
-
Save krzyzanowskim/c84d039d1542c1a82731 to your computer and use it in GitHub Desktop.
// Playground - noun: a place where people can play | |
import Foundation | |
typealias Byte = UInt8 | |
protocol GenericIntegerType: IntegerType { | |
init(_ v: Int) | |
init(_ v: UInt) | |
init(_ v: Int8) | |
init(_ v: UInt8) | |
init(_ v: Int16) | |
init(_ v: UInt16) | |
init(_ v: Int32) | |
init(_ v: UInt32) | |
init(_ v: Int64) | |
init(_ v: UInt64) | |
} | |
protocol GenericSignedIntegerBitPattern { | |
init(bitPattern: UIntMax) | |
init(truncatingBitPattern: IntMax) | |
} | |
protocol GenericUnsignedIntegerBitPattern { | |
init(truncatingBitPattern: UIntMax) | |
} | |
extension Int:GenericIntegerType, GenericSignedIntegerBitPattern { | |
init(bitPattern: UIntMax) { | |
self.init(bitPattern: UInt(truncatingBitPattern: bitPattern)) | |
} | |
} | |
extension UInt:GenericIntegerType, GenericUnsignedIntegerBitPattern {} | |
extension Int8:GenericIntegerType, GenericSignedIntegerBitPattern { | |
init(bitPattern: UIntMax) { | |
self.init(bitPattern: UInt8(truncatingBitPattern: bitPattern)) | |
} | |
} | |
extension UInt8:GenericIntegerType, GenericUnsignedIntegerBitPattern {} | |
extension Int16:GenericIntegerType, GenericSignedIntegerBitPattern { | |
init(bitPattern: UIntMax) { | |
self.init(bitPattern: UInt16(truncatingBitPattern: bitPattern)) | |
} | |
} | |
extension UInt16:GenericIntegerType, GenericUnsignedIntegerBitPattern {} | |
extension Int32:GenericIntegerType, GenericSignedIntegerBitPattern { | |
init(bitPattern: UIntMax) { | |
self.init(bitPattern: UInt32(truncatingBitPattern: bitPattern)) | |
} | |
} | |
extension UInt32:GenericIntegerType, GenericUnsignedIntegerBitPattern {} | |
extension Int64:GenericIntegerType, GenericSignedIntegerBitPattern { | |
// init(bitPattern: UInt64) already defined | |
init(truncatingBitPattern: IntMax) { | |
self.init(truncatingBitPattern) | |
} | |
} | |
extension UInt64:GenericIntegerType, GenericUnsignedIntegerBitPattern { | |
// init(bitPattern: Int64) already defined | |
init(truncatingBitPattern: UIntMax) { | |
self.init(truncatingBitPattern) | |
} | |
} | |
func integerWithBytes<T: GenericIntegerType where T: UnsignedIntegerType, T: GenericUnsignedIntegerBitPattern>(bytes:[UInt8]) -> T? { | |
if (bytes.count < sizeof(T)) { | |
return nil | |
} | |
let maxBytes = sizeof(T) | |
var i:UIntMax = 0 | |
for (var j = 0; j < maxBytes; j++) { | |
i = i | T(bytes[j]).toUIntMax() << UIntMax(j * 8) | |
} | |
return T(truncatingBitPattern: i) | |
} | |
func integerWithBytes<T: GenericIntegerType where T: SignedIntegerType, T: GenericSignedIntegerBitPattern>(bytes:[UInt8]) -> T? { | |
if (bytes.count < sizeof(T)) { | |
return nil | |
} | |
let maxBytes = sizeof(T) | |
var i:IntMax = 0 | |
for (var j = 0; j < maxBytes; j++) { | |
i = i | T(bitPattern: UIntMax(bytes[j].toUIntMax())).toIntMax() << (j * 8).toIntMax() | |
} | |
return T(truncatingBitPattern: i) | |
} | |
let bytes:[UInt8] = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF] | |
integerWithBytes(bytes) as Int8? | |
integerWithBytes(bytes) as UInt8? | |
integerWithBytes(bytes) as Int16? | |
integerWithBytes(bytes) as UInt16? | |
integerWithBytes(bytes) as Int32? | |
integerWithBytes(bytes) as UInt32? | |
integerWithBytes(bytes) as Int64? | |
integerWithBytes(bytes) as UInt64? |
Hi Krzyzanowskim,
Great effort and useful area through!
I am doing some encryption algorithm and trying to do some shift operation using swift 2.0 like this but it always throws crash error (EXC_BAD_INSTRUCTION). It is a signed number. How to solve this issue, please assist. In Java and C it gives me this number : -2147483646
let n : Int = 10
let s : Int = 2
let sh = (n >> s) | (n << -s) //error
Hi @krzyzanowskim ,
I've found your gist and your blog article very useful, thanks!
While working on some bit representation, I think it's better to change the
T(bytes[j])
to
T(bytes[maxBytes - j - 1])
because the input array does not represent the correct byte order of the returned integer IMHO.
For example, with a decimal number 43605, having this binary representation
1010 1010 0101 0101
I think the correct byte array that integerWithBytes should accept is
[170, 85]
and not the reversed one
[85, 170]
Thank you,
Gabriele.
This is ridiculous. You've apparently gone to great lengths to do this as complicated as possible. It's a hell of a lot simpler just to say
func integerWithBytes<T: IntegerType>(bytes: [UInt8]) -> T? {
guard bytes.count >= sizeof(T) else { return nil }
return bytes.withUnsafeBufferPointer({ UnsafePointer<T>($0.baseAddress).memory })
}
@kballard , could you please elaborate on how to use that function with a practical example please?
I had to do this shudder https://gist.github.com/jcampbell05/f6b5611bd7f61840edb10500fa69fd09
This just works now: http://swift.sandbox.bluemix.net/#/repl/59ed541e3d125e6782506f1e
Thanks! this is more exercise than anything else, but yes It's worth to know how the things getting complicated when it comes to types.