bits manipulation

V

Vince

Hi,

I have a BYTE array and I have "mapped" every bits with a string, a type
and an offest:

For istance my array is 20 bytes long and I did this :

first name :
offset 0 (bits)
length 8*10 (bits) - every charater is coded on 8 bytes
type string

age :
offset 80
length 7 (bits) - I assume we cannot leave more than 128 years
type numeric


and now I would like to do something like :

fstname = GetString("first name");
age = GetNumeric("age");

of
SetData("first name", "john");
SetData("age", 27);

I know how to do the map thing but how can I manipulate easily bits ?
 
R

Raghu Uppalli

What are you trying to do? Save memory? Process faster? Unfortunately
this solution doesnt help in either of the causes.

Please update with a little more context and we'll try to help
 
V

Vince

Raghu Uppalli a écrit :
What are you trying to do? Save memory? Process faster? Unfortunately
this solution doesnt help in either of the causes.

Please update with a little more context and we'll try to help

I am reading files(BYTE array) on a smart card and I need to associate
to each chunk some data and some type.
For instance for a smart card of type 1 information like name, age and
so on are stored on a certain position and on defined number of bits.
On another smart card, these information are stored with a different
offset. So I need to access data transparently without playing
each time with bits manipulation.

I need to be able to get my data jut by specifying a key (string).
The goal is to specify the smart card mapping in a XML file so that
I don't have to recompile everytyme I have a new type of smart card.
So now with a std::map I associate to a key a tag, an offset, a size and
a length.


So finally I have an array like this


------------------------------
|0|1|2|3|4|5|6|7|8|9|10|11|12|
------------------------------
< name >< age >

So I associate the name tag to offset 0 to 8 and the type is a string
and age to offset 9 to 12 as a numeric.


I need after to be able to do

strname = myarray.GetString("name");
or nAge = myarray.GetNumeric("age");






Hope this helps
 
M

Malte Starostik

Vince said:
I am reading files(BYTE array) on a smart card and I need to associate
to each chunk some data and some type.

The card can't be that smart when it only allows for 10-character names
(or less than that if the name requires a multibyte encoding) - SCNR ;)
But seriously, what would you think if you had a long name and someone
decided it's okay to truncate it for the sake of saving a few bytes? I
think it's insulting.

[rationale snipped]
So finally I have an array like this


------------------------------
|0|1|2|3|4|5|6|7|8|9|10|11|12|
------------------------------
< name >< age >

So I associate the name tag to offset 0 to 8 and the type is a string
and age to offset 9 to 12 as a numeric.


I need after to be able to do

strname = myarray.GetString("name");
or nAge = myarray.GetNumeric("age");

Okay, somehow I feel like giving a complete example :)

#include <cassert>
#include <iostream>
#include <limits>
#include <string>
#include <vector>

typedef std::vector< unsigned char > card_data;

unsigned char extract( const card_data& data, size_t offset,
size_t bits )
{
assert( data.size() >= ( offset + bits + 7 ) / 8 );

// grab a byte (or less) from an arbitrary bit offset into data
unsigned char result =
( data[ offset / 8 ] << offset % 8 ) & ( 0xff << offset % 8 );
if ( bits > 8 - offset % 8 )
result |= ( ( data[ offset / 8 + 1 ] >> ( 8 - offset % 8 ) )
& ( 0xff >> ( 8 - offset % 8 ) ) );
return result >> ( 8 - bits % 8 ) % 8;
}

std::string get_string( const card_data& data, size_t offset,
size_t length )
{
std::string result;
for ( card_data::size_type i = 0; i < ( length + 7 ) / 8; ++i )
{
if ( char c = extract( data, 8 * i + offset,
std::min( length - 8 * i, 8u ) ) )
result += c;
else break;
}
return result;
}

template< typename T >
T get_numeric( const card_data& data, size_t offset, size_t length )
{
assert( ( length + 7 ) / 8 <= sizeof( T ) );

T result = 0;
// Assuming big-endian bit order.
// Take care to handle other formats properly
for ( size_t i = 0; i < ( length + 7 ) / 8; ++i )
result |= extract( data, 8 * i + offset,
std::min( length - 8 * i, 8u ) )
<< ( length - std::min( 8 * ( i + 1 ), length ) );
// sign-extend if needed
if ( std::numeric_limits< T >::is_signed &&
result & ( 1 << ( length - 1 ) ) )
result |= T( -1 ) << length;
return result;
}

int main()
{
card_data test;
// This was of course was read from the card
test.push_back( 0x25 );
test.push_back( 0x37 );
test.push_back( 0xb4 );
test.push_back( 0x37 );
test.push_back( 0x00 );
test.push_back( 0x7f ); // all-1 padding for no particular reason
test.push_back( 0xff );
test.push_back( 0xff );
test.push_back( 0xff );
test.push_back( 0xff );
test.push_back( 0x9e );
// Look up the offset/length in your card description database
// according to the card type and field name
// For the fun of it, let's not start on a byte boundary
std::cout << get_string( test, 1, 80 ) << " is "
<< get_numeric< unsigned >( test, 81, 7 )
<< " years old" << std::endl;
std::string s;
std::getline( std::cin, s );
}

Cheers,
Malte
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,040
Latest member
papereejit

Latest Threads

Top