Reputation: 25
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
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
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
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
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