Generics.swift 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. //
  2. // Generics.swift
  3. // CryptoSwift
  4. //
  5. // Created by Marcin Krzyzanowski on 02/09/14.
  6. // Copyright (c) 2014 Marcin Krzyzanowski. All rights reserved.
  7. //
  8. /** Protocol and extensions for integerFromBitsArray. Bit hakish for me, but I can't do it in any other way */
  9. protocol Initiable {
  10. init(_ v: Int)
  11. init(_ v: UInt)
  12. }
  13. extension Int:Initiable {}
  14. extension UInt:Initiable {}
  15. extension UInt8:Initiable {}
  16. extension UInt16:Initiable {}
  17. extension UInt32:Initiable {}
  18. extension UInt64:Initiable {}
  19. /** build bit pattern from array of bits */
  20. func integerFromBitsArray<T: UnsignedIntegerType>(bits: [Bit]) -> T
  21. {
  22. var bitPattern:T = 0
  23. for (idx,b) in bits.enumerate() {
  24. if (b == Bit.One) {
  25. let bit = T(UIntMax(1) << UIntMax(idx))
  26. bitPattern = bitPattern | bit
  27. }
  28. }
  29. return bitPattern
  30. }
  31. /// Initialize integer from array of bytes.
  32. /// This method may be slow
  33. func integerWithBytes<T: IntegerType where T:ByteConvertible, T: BitshiftOperationsType>(bytes: [UInt8]) -> T {
  34. var bytes = bytes.reverse() as Array<UInt8> //FIXME: check it this is equivalent of Array(...)
  35. if bytes.count < sizeof(T) {
  36. let paddingCount = sizeof(T) - bytes.count
  37. if (paddingCount > 0) {
  38. bytes += [UInt8](count: paddingCount, repeatedValue: 0)
  39. }
  40. }
  41. if sizeof(T) == 1 {
  42. return T(truncatingBitPattern: UInt64(bytes.first!))
  43. }
  44. var result: T = 0
  45. for byte in bytes.reverse() {
  46. result = result << 8 | T(byte)
  47. }
  48. return result
  49. }
  50. /// Array of bytes, little-endian representation. Don't use if not necessary.
  51. /// I found this method slow
  52. func arrayOfBytes<T>(value:T, length:Int? = nil) -> [UInt8] {
  53. let totalBytes = length ?? sizeof(T)
  54. let valuePointer = UnsafeMutablePointer<T>.alloc(1)
  55. valuePointer.memory = value
  56. let bytesPointer = UnsafeMutablePointer<UInt8>(valuePointer)
  57. var bytes = [UInt8](count: totalBytes, repeatedValue: 0)
  58. for j in 0..<min(sizeof(T),totalBytes) {
  59. bytes[totalBytes - 1 - j] = (bytesPointer + j).memory
  60. }
  61. valuePointer.destroy()
  62. valuePointer.dealloc(1)
  63. return bytes
  64. }
  65. // MARK: - shiftLeft
  66. // helper to be able tomake shift operation on T
  67. func << <T:SignedIntegerType>(lhs: T, rhs: Int) -> Int {
  68. let a = lhs as! Int
  69. let b = rhs
  70. return a << b
  71. }
  72. func << <T:UnsignedIntegerType>(lhs: T, rhs: Int) -> UInt {
  73. let a = lhs as! UInt
  74. let b = rhs
  75. return a << b
  76. }
  77. // Generic function itself
  78. // FIXME: this generic function is not as generic as I would. It crashes for smaller types
  79. func shiftLeft<T: SignedIntegerType where T: Initiable>(value: T, count: Int) -> T {
  80. if (value == 0) {
  81. return 0;
  82. }
  83. let bitsCount = (sizeofValue(value) * 8)
  84. let shiftCount = Int(Swift.min(count, bitsCount - 1))
  85. var shiftedValue:T = 0;
  86. for bitIdx in 0..<bitsCount {
  87. let bit = T(IntMax(1 << bitIdx))
  88. if ((value & bit) == bit) {
  89. shiftedValue = shiftedValue | T(bit << shiftCount)
  90. }
  91. }
  92. if (shiftedValue != 0 && count >= bitsCount) {
  93. // clear last bit that couldn't be shifted out of range
  94. shiftedValue = shiftedValue & T(~(1 << (bitsCount - 1)))
  95. }
  96. return shiftedValue
  97. }
  98. // for any f*** other Integer type - this part is so non-Generic
  99. func shiftLeft(value: UInt, count: Int) -> UInt {
  100. return UInt(shiftLeft(Int(value), count: count)) //FIXME: count:
  101. }
  102. func shiftLeft(value: UInt8, count: Int) -> UInt8 {
  103. return UInt8(shiftLeft(UInt(value), count: count))
  104. }
  105. func shiftLeft(value: UInt16, count: Int) -> UInt16 {
  106. return UInt16(shiftLeft(UInt(value), count: count))
  107. }
  108. func shiftLeft(value: UInt32, count: Int) -> UInt32 {
  109. return UInt32(shiftLeft(UInt(value), count: count))
  110. }
  111. func shiftLeft(value: UInt64, count: Int) -> UInt64 {
  112. return UInt64(shiftLeft(UInt(value), count: count))
  113. }
  114. func shiftLeft(value: Int8, count: Int) -> Int8 {
  115. return Int8(shiftLeft(Int(value), count: count))
  116. }
  117. func shiftLeft(value: Int16, count: Int) -> Int16 {
  118. return Int16(shiftLeft(Int(value), count: count))
  119. }
  120. func shiftLeft(value: Int32, count: Int) -> Int32 {
  121. return Int32(shiftLeft(Int(value), count: count))
  122. }
  123. func shiftLeft(value: Int64, count: Int) -> Int64 {
  124. return Int64(shiftLeft(Int(value), count: count))
  125. }