3

Trying to convert my app to Swift from C++

C++:

static QWORD load64(const OCTET *x)
{
char i;
QWORD u=0;
    for(i=7; i>=0; --i) {
        u <<= 8;
        u |= x[i];
    }
    return u;
}

Swift:

func load64(x: UInt8) -> UInt64 {
    var u: UInt64 = 0;
    for var i=7; i>=0; --i {
        u <<= 8;
        u |= x[i];
    }
    return u;
}

But this line doesnt work in Swift:

u |= x[i];

And I can't seem to find any reference to selecting a specific bit from an integer... anyone know how?

Wyllow Wulf
  • 410
  • 4
  • 23

3 Answers3

2

It is possible to use the |= operator in Swift, and it works the same as in C/C++.

The problem is that load64() in the C++ code essentially takes an array of OCTETs as an argument and accesses the array using a subscript. The Swift version takes a UInt8 as an argument, and you can't subscript an integer in Swift, just as you can't do that in C or C++.

As far as I can tell, the point of the C++ code is to build a 64-bit unsigned int from an array of 8 bytes provided in the array passed in as an argument. To get this to work in Swift, load64() will need to take an array of bytes as an argument, not just a single byte.

As an aside, if you have a large code base in C++ or C that you want to use in Swift, you don't have to re-write it in Swift. You may be able to write a C/C++ wrapper with a simplified interface and invoke it from Swift. I have a basic proof-of-concept tutorial on how to do that here: http://www.swiftprogrammer.info/swift_call_cpp.html

BTW, here is a Swift version of load64(), worked for me:

func load64(x: [UInt8]) -> UInt64 {
    var u: UInt64 = 0;
    for var i=7; i>=0; --i {
        u <<= 8;
        u |= UInt64(x[i]);
    }
    return u;
} 
Anatoli P
  • 4,791
  • 1
  • 18
  • 22
  • *"You may be able to write a C/C++ wrapper"* - good suggestion there! Cheers. – Tony Delroy Sep 17 '15 at 03:34
  • im sorry i had a bit of an error in my swift code. the function actually loads an integer value from a much larger array by passing a pointer. this is some other definition code: `#define readLane(x, y) load64((OCTET*)state+sizeof(tKeccakLane)*i(x, y))` state is a 200-bye array – Wyllow Wulf Sep 17 '15 at 04:28
  • i will however try the wrapper idea or find another way to go about this – Wyllow Wulf Sep 17 '15 at 04:28
0

I don't know if swift supports |= as you've attempted, but according to the docs (first match for "swift bitwise-or" on google), it should supports:

let u = u | x[i]

Their example:

let someBits: UInt8 = 0b10110010
let moreBits: UInt8 = 0b01011110
let combinedbits = someBits | moreBits // equals 11111110

Separately, your C++ code will get stuck in an infinite loop on any system with unsigned chars.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • The bitwise OR assignment operator isn't the problem, it's the x[i]... im trying to get the i bit of integer x – Wyllow Wulf Sep 17 '15 at 03:09
  • Found a couple options... x & (1 << i) ? 1 : 0; (x >> i) & 1; – Wyllow Wulf Sep 17 '15 at 03:17
  • Found a couple options... `x & (1 << i) ? 1 : 0; (x >> i) & 1; (x & (0x01 << i)) ? 1 : 0;` i think this will work... but any ideas for the opposite, to assign to a specific bit? – Wyllow Wulf Sep 17 '15 at 03:25
  • @WilliamElliott: you can assign to a specific bit by ORing with a number that contains it, which you can create by bitshifting 1 left however-many times. – Tony Delroy Sep 17 '15 at 03:33
0

With more bits you'd typically use a struct in C/C++:

struct MyBitsAndPieces
{
    unsigned char bit0 :1;
    unsigned char bit1 :1;
    ...
};

You can then access individual bits:

struct MyBitsAndPieces baps = 2;
if (baps.bit1 == 1)
{
}

A similar thing can be done in Swift:

struct MyBitsAndPieces: OptionSet
{
    let rawValue: UInt8

    static let bit0 = MyBitsAndPieces(rawValue: 1 << 0)
    static let bit1 = MyBitsAndPieces(rawValue: 1 << 1)
    ...
}

You can initialise and check a bit using:

let baps = MyBitsAndPieces(rawValue: 2)
if baps.contains(.bit1)
{
}
meaning-matters
  • 21,929
  • 10
  • 82
  • 142