Mark452452
Mark452452

Reputation: 25

C code to check if unsigned short contains a particular byte

I have an unsigned short value. It is binary data sampled from a radio source. I'd like to check if the data contains a particular byte, a signature byte.

To illustrate, the unsigned short might be

0100 1010 0111 0101 /* 0x4A75 */

and I want to check if it contains the byte

1010 0111 /* 0xA7 */

anywhere. The data being checked will change each time I check but the signature will be constant.

Can anyone help?

Thanks.

Upvotes: 0

Views: 264

Answers (4)

user3793679
user3793679

Reputation:

If you are desperate for speed, a (mere!) 8192 bytes of memory will give you a bit for every possible value :-)

As @jxh suggests, for 256 bytes you can construct a table to shift off bits which cannot match. Construction of the table requires something like:

enum { patt = 0xA7 } ;
int8_t sht[256] ;

for (int i = 0 ; i < 256 ; ++i)
  {
    int8_t  s ;
    uint8_t b, m ;

    b = i ;
    s = 0 ;
    m = 0xFF ;

    while (b != (patt & m))
      {
        b >>= 1 ;
        m >>= 1 ;
        s  += 1 ;
      } ;

    sht[i] = s ;
  } ;

And then to use it, something like:

  uint16_t data ;
  int8_t a, s ;

  s = 0 ;
  a = -1 ;

  while (1)
    {
      int8_t t ;

      t = sht[data & 0xFF] ;

      if (t == 0)
        {
          a = s ;
          break ;
        }

      s += t ;
      if (s > 8)
        break ;

      data >>= t ;
    } ;

This accumulates in s the location of the 0xA7, but even if you don't need that, it's useful because it stops the loop.

Doing a little timing on random values, I found the simple shift approach takes about 3 times as long as the shift-table, and about 5.5 times as long as the bit-vector lookup approach.

[For completeness: if the pattern you are looking for were to be < 0x80, then you'd need to change the mask (currently 0xFF) and the maximum useful shift (currently 8).]

Upvotes: 0

Ludo6431
Ludo6431

Reputation: 164

Just bit shift to the right 8 times (the 9-th one isn't used) and check for equality.

#include <stdio.h>

int main(){
    unsigned short data = 0x4a75;
    unsigned char byte = 0xa7;
    int i;

    for(i = 0; i <= 16 - 8; i++){
        if(byte == (unsigned char)data){
            printf("found signature (offset %i)\n", i);
            break;
        }
        data >>= 1;
    }

    return 0;
}

Upvotes: 1

Fiddling Bits
Fiddling Bits

Reputation: 8861

Instead of bit shifting, you can also use lookup tables:

const unsigned short signature[3] = {0xA700, 0x0A70, 0x00A7};
const unsigned short mask[3] = {0xFF00, 0x0FF0, 0x00FF};

You can analyze the data to see if it has the signature in a simple for loop:

bool signatureFound = false;
int i;

for(i = 0; i < 3; i++)
{
    if((data & mask[i]) == signature[i])
    {
        signatureFound = true;
        break;
    }
}

Upvotes: 0

ouah
ouah

Reputation: 145899

Compare the least significant byte of your short object with 0xA7 (i.e., 1010 0111) in a loop and shift your short value one bit to the right at each loop iteration.

Upvotes: 2

Related Questions