I'm reading data from disk using an external C library that loads numeric data into a void * buffer (I also have to know the total size of the buffer), and I want to transform this data into an array of Perl scalars in XS code.
The problem is the data can be stored in an arbitrary number of bits per unit (bps) - 8, 16, or 32, and can be either integer or floating point (or unknown). Due to my lack of C-fu I'm creating Perl SV's and de-referencing C pointers using dumb if statements..
// buffer <- void* pre-loaded data /* SAMPLEFORMAT * 1 = unsigned integer data * 2 = two’s complement signed integer data * 3 = IEEE floating point data [IEEE] * 4 = undefined data format */ if ( fmt == 3 && bps == 32 ) { // Floating-point if ( av_store( array, i, newSVnv( (double)(((float*)buffer)[i]) ) ) == NULL ) ok = 0; } else if ( bps == 8 ) { // Char if ( av_store( array, i, newSViv( (int)(((char*)buffer)[i]) ) ) == NULL ) ok = 0; } // Int else if ( bps == 16 ) { if ( av_store( array, i, newSViv( (int)(((uint16*)buffer)[i]) ) ) == NULL ) ok = 0; } else { if ( av_store( array, i, newSViv( (int)(((int*)buffer)[i]) ) ) == NULL ) ok = 0; } ...
Is there a better way of doing this? I feel like my code is very inelegant and bound to break.
Update: added 'unpack' to the title.
In reply to C types and SV's and unpack by blakew
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |