Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Idiomatic way to port C bitfiddling to Python

How would you port the following C code in a Pythonic way (especially the bit fiddling part in Get2, Get3, ...)

switch(mem[pos-1])
{
  ...
  case 0x10: pos+=Get2(&mem[pos+0x02])+0x04; break;
  case 0x11: pos+=Get3(&mem[pos+0x0F])+0x12; break;
  case 0x16: pos+=Get4(&mem[pos+0x00])+0x04; break;
  ...
  case 0x20: pos+=0x02; break;
}

...

//////////////////////////////////////////////////////////
// Conversion routines to fetch bytes in Big Endian order
//////////////////////////////////////////////////////////

unsigned int Get2(unsigned char *pointer)
{
  return (pointer[0] | (pointer[1]<<8));
}

unsigned int Get3(unsigned char *pointer)
{
  return (pointer[0] | (pointer[1]<<8) | (pointer[2]<<16));
}

unsigned int Get4(unsigned char *pointer)
{
  return (pointer[0] | (pointer[1]<<8) | (pointer[2]<<16) | (pointer[3]<<24));
}

This is what I've got so far:

    x = struct.unpack('B', mem[pos-1])[0]

    if x == 0x10:
        # pos += ???
        continue

    if x == 0x11:
        # pos += ???
        continue

    if x == 0x16:
        # pos += ???
        continue

    if x == 0x20: 
        pos += 0x02
        continue
like image 814
ChristopheD Avatar asked Jan 22 '26 10:01

ChristopheD


1 Answers

If you're just getting one unsigned byte, just do

x = ord(mem[pos - 1])

on Python 2 or

x = mem[pos - 1]

on Python 3.

Instead of select / case, You want a dictionary.

positions = {0x10: do_10, 0x11: do_12, 0x16: do_16}

Where do_10 etc. are functions:

def do_10(pos):
    # This actually would need an endianness character
    return struct.unpack('H', mem[pos + 0x02])[0] + 0x04

You use it like this:

pos += positions[mem[pos - 1]](pos)

If you want to define the functions right in the dictionary, you can:

positions = {
    # This actually would need an endianness character
    0x10: (lambda pos: struct.unpack('H', mem[pos + 0x02])[0] + 0x04)
    # ...
    }
like image 183
agf Avatar answered Jan 24 '26 22:01

agf



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!