UInt32+Extension.swift 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. //
  2. // UInt32Extension.swift
  3. // CryptoSwift
  4. //
  5. // Created by Marcin Krzyzanowski on 02/09/14.
  6. // Copyright (c) 2014 Marcin Krzyzanowski. All rights reserved.
  7. //
  8. #if os(Linux)
  9. import Glibc
  10. #else
  11. import Darwin
  12. #endif
  13. protocol _UInt32Type { }
  14. extension UInt32: _UInt32Type {}
  15. /** array of bytes */
  16. extension UInt32 {
  17. public func bytes(totalBytes: Int = MemoryLayout<UInt32>.size) -> Array<UInt8> {
  18. return arrayOfBytes(value: self, length: totalBytes)
  19. }
  20. /** Int with array bytes (little-endian) */
  21. public static func with<T: Collection>(_ bytes: T) -> UInt32 where T.Iterator.Element == UInt8, T.Index == Int {
  22. return bytes.toInteger()
  23. }
  24. }
  25. /** Shift bits */
  26. extension UInt32 {
  27. /** Shift bits to the left. All bits are shifted (including sign bit) */
  28. fileprivate mutating func shiftLeft(by count: UInt32) {
  29. if (self == 0) {
  30. return
  31. }
  32. let bitsCount = UInt32(MemoryLayout<UInt32>.size * 8)
  33. let shiftCount = Swift.min(count, bitsCount - 1)
  34. var shiftedValue:UInt32 = 0;
  35. for bitIdx in 0..<bitsCount {
  36. // if bit is set then copy to result and shift left 1
  37. let bit = 1 << bitIdx
  38. if ((self & bit) == bit) {
  39. shiftedValue = shiftedValue | (bit << shiftCount)
  40. }
  41. }
  42. if (shiftedValue != 0 && count >= bitsCount) {
  43. // clear last bit that couldn't be shifted out of range
  44. shiftedValue = shiftedValue & (~(1 << (bitsCount - 1)))
  45. }
  46. self = shiftedValue
  47. }
  48. /** Shift bits to the right. All bits are shifted (including sign bit) */
  49. fileprivate mutating func shiftRight(by count: UInt32) {
  50. if (self == 0) {
  51. return
  52. }
  53. let bitsCount = UInt32(MemoryLayout<UInt32>.size * 8)
  54. if (count >= bitsCount) {
  55. return
  56. }
  57. let maxBitsForValue = UInt32(floor(log2(Double(self)) + 1))
  58. let shiftCount = Swift.min(count, maxBitsForValue - 1)
  59. var shiftedValue:UInt32 = 0;
  60. for bitIdx in 0..<bitsCount {
  61. // if bit is set then copy to result and shift left 1
  62. let bit = 1 << bitIdx
  63. if ((self & bit) == bit) {
  64. shiftedValue = shiftedValue | (bit >> shiftCount)
  65. }
  66. }
  67. self = shiftedValue
  68. }
  69. }
  70. /** shift left and assign with bits truncation */
  71. public func &<<= (lhs: inout UInt32, rhs: UInt32) {
  72. lhs.shiftLeft(by: rhs)
  73. }
  74. /** shift left with bits truncation */
  75. public func &<< (lhs: UInt32, rhs: UInt32) -> UInt32 {
  76. var l = lhs;
  77. l.shiftLeft(by: rhs)
  78. return l
  79. }
  80. /** shift right and assign with bits truncation */
  81. func &>>= (lhs: inout UInt32, rhs: UInt32) {
  82. lhs.shiftRight(by: rhs)
  83. }
  84. /** shift right and assign with bits truncation */
  85. func &>> (lhs: UInt32, rhs: UInt32) -> UInt32 {
  86. var l = lhs;
  87. l.shiftRight(by: rhs)
  88. return l
  89. }