BLOB to byte array conversion in objective C - objective-c

I have a table filed in which the value is stored as BLOB type . I need to get that as a binary array so that I can get different values from different byte positions in the BLOB. Any Help is appreciated.

// Get the start and length of the blob.
// (remember column indexes are 0-based when fetching the value
// but 1-base when binding - yeah cheers!)
uint8_t *data = (uint8_t *)sqlite3_column_blob(stmt, columnIndex);
size_t length = (size_t)sqlite3_column_bytes(stmt, columnIndex);
// And now you can access the data
unsigned sum = 0;
for (size_t i = 0; i < length; i++)
sum += data[i];

Related

Objective C: NSRange location value is not what it should be

I have this method which extracts data from NSData at a specific pointer. The method only extracts a certain amount of bytes, in this case it is 4 bytes as I return a uint32.
I pass in a pointer (int start) which is used to create the location for an NSRange, the length of the range is the size of a uint32, which creates the range as 4 bytes long.
This works perfectly fine, until the pointer gets to 2147483648. When it gets to this value, the range is not created with 2147483648 for the location value instead it is created as 18446744071562067968 which is out of bounds for the data, and causes an exception to occur halting my program which stops it from reading the rest of the data.
I have no idea what is causing it do what its doing, the start value is the correct value when it is passed into the method, but it changes when the range is created. It does not happen for any of the previous pointer values.
Have I done something silly in my code? Or is it a different problem? Help will be appreciated.
Thank you.
- (uint32)getUINT32ValueFromData:(NSData *)rawData pointer:(int)start {
uint32 value;
NSRange range;
int length = sizeof(uint32);
NSUInteger dataLength = rawData.length;
NSData *currentData;
NSUInteger remainingBytes = dataLength - start;
if (remainingBytes > length) {
range.location = start;
range.length = length;
//should be 2147483648, location in range is showing 18446744071562067968 which is out of bounds...
currentData = [rawData subdataWithRange:range];
uint32 hostData = CFSwapInt32BigToHost(*(const uint32 *)[currentData bytes]);
value = hostData;
pointer = start + length;
}
else
{
NSLog(#"Data Length Exceeded!");
}
return value;
}
It's seems to be an 32/64 bit and signed/unsigned mismatch issue.
You're using three different types
int is a 32 bit signed type
uint32 is a 32 bit unsigned type
NSUInteger is a 32/64 bit unsigned type depending on the processor architecture.
unit32 for the value is fine, but you should use NSUInteger for the offset into the NSData object.

Arbitrary precision bit manipulation (Objective C)

I need to do bit operations on representations of arbitrary precision numbers in Objective C. So far I have been using NSData objects to hold the numbers - is there a way to bit shift the content of those? If not, is there a different way to achieve this?
Using NSMutableData you can fetch the byte in a char, shift your bits and replace it with -replaceBytesInRange:withBytes:.
I don't see any other solution except for writing your own date holder class using a char * buffer to hold the raw data.
As you'll have spotted, Apple doesn't provide arbitrary precision support. Nothing is provided larger than the 1024-bit integers in vecLib.
I also don't think NSData provides shifts and rolls. So you're going to have to roll your own. E.g. a very naive version, which may have some small errors as I'm typing it directly here:
#interface NSData (Shifts)
- (NSData *)dataByShiftingLeft:(NSUInteger)bitCount
{
// we'll work byte by byte
int wholeBytes = bitCount >> 3;
int extraBits = bitCount&7;
NSMutableData *newData = [NSMutableData dataWithLength:self.length + wholeBytes + (extraBits ? 1 : 0)];
if(extraBits)
{
uint8_t *sourceBytes = [self bytes];
uint8_t *destinationBytes = [newData mutableBytes];
for(int index = 0; index < self.length-1; index++)
{
destinationBytes[index] =
(sourceBytes[index] >> (8-extraBits)) |
(sourceBytes[index+1] << extraBits);
}
destinationBytes[index] = roll >> (8-extraBits);
}
else
/* just copy all of self into the beginning of newData */
return newData;
}
#end
Of course, that assumes the number of bits you want to shift by is itself expressible as an NSUInteger, amongst other sins.

how to get char array-element in 2-dimensional array

I have 2-dimensional array like below.
unsigned char myArray[][48] = {
{0xfc,0x94,0x88,0x48,0x5f,0xa4,0x9a,0xfb,0x6e,0xf8,0xcd,0x01,0x47,0x64,0x03,0xd0,0x1f,0xb8,0xa3,0x85,0x84,0xa9,0x4a,0xc4,0x9e,0xea,0x26,0x09,0x62,0x96,0x91,0xa6},
{0xa9,0xc5,0x9a,0xb3,0x09,0x38,0x15,0xb3,0x22,0xb3,0x07,0x21,0x3e,0x39,0x35,0xc6,0x69,0x6e,0xf3,0x64,0xb0,0x0a,0x4c,0xcb,0x77,0xff,0x76,0x3c,0x37,0xf3,0x99,0x96},
{0x24,0x4d,0xc0,0x45,0xe0,0x50,0x1f,0x72,0x0f,0xb0,0xcc,0xb9,0xc6,0x72,0xa9,0x5a,0xf3,0x5a,0xd9,0xe2,0xc3,0x44,0xd9,0x25,0xf3,0x12,0x6a,0x0c,0x37,0x6a,0x3f,0xb6},
{0xd3,0x91,0x98,0xfd,0xcd,0x6e,0x01,0x44,0xfc,0xf7,0x5d,0x08,0xab,0xbc,0x43,0xab,0xd3,0x4a,0xd9,0x07,0xa7,0x8e,0xda,0xba,0xb5,0x8a,0x27,0xe1,0xc6,0x7a,0xfe,0xee},
{0x5f,0x08,0xcc,0x01,0x17,0xde,0xbb,0x99,0x19,0xf3,0x0d,0xd7,0x08,0x5f,0xcd,0xe3,0xe0,0x24,0x54,0xee,0x16,0x68,0xe1,0x64,0x41,0x58,0x09,0xd8,0xf7,0x93,0x8f,0xf1,0xf0,0x00,0xd7,0xd4,0x5b,0x6b,0x8d,0x1e,0x18,0x06,0x1f,0x70,0x6a,0x40,0x86,0x38}
};
When I get myArray[0], it's not 36 bytes as we see; instead, it is 48. How can I get 36 bytes as we see in the array without specifying its size, 36, while getting it.
{0xfc,0x94,0x88,0x48,0x5f,0xa4,0x9a,0xfb,0x6e,0xf8,0xcd,0x01,0x47,0x64,0x3,0xd0,0x1f,0xb8,0xa3,0x85,0x84,0xa9,0x4a,0xc4,0x9e,0xea,0x26,0x09,0x62,0x96,0x91,0xa6}
NSData *row1 = [NSData dataWithBytes:url[0]
length:(sizeof(myArray[0])/sizeof(unsigned char))];
There's only 32 bytes in the first 4 rows.
Since the values not provided are initialized to 0, you could search for the last non-zero backward, like:
unsigned char* data = myArray[n];
size_t len = sizeof(myArray[n]);
for (; len > 0; -- len)
if (data[len-1] != 0)
break;
NSData* row = [NSData dataWithBytes:data length:len];
This assumes there are no 0 at the end of your provided 32-byte sequence. If not, you have to provide an additional array recording the number of bytes each row.
NSData *row1 = [NSData dataWithBytes:myArray[0] length:36];
^_^

Binary conversion algorithm in objective-c

How do I get the value of a certain bit from a byte or integer? The only similar answer that I've been able to find is for a specific character inside a string. I am trying to convert a binary number to a decimal number, and perhaps there is a much simpler way to do this, but I was thinking of this: multiplying 2^(position of integer from right) by either a 1 or 0, depending on the value of the integer at the position previously mentioned. Any tips?
NSString * binary = #"0011010";
long value = strtol([b UTF8String], NULL, 2);
There are multiways of obtaining the value of bit within a byte or integer. It all depends on your needs.
One way would be to use a mask with bitwise operators.
int result = sourceValue & 8; // 8 -> 0x00001000
// result non zero if the 4th bit from the right is ON.
You can also shift bits one by one and read, say, the right-most bit.
for (int i = 0; i < 8; i++)
NSLog(#"Bit %d is %#", i, (sourceValue % 2 == 0) ? #"OFF" : #"ON");
sourceValue = sourceValue >> 1; // shift bits to the right for next loop.
}
Or if you just want the text representation for an integer, you could let NSNumber do the work:
NSString* myString = [[NSNumber numberWithInt:sourceValue] stringValue];

Problem while converting NSData to int

Using foundation and cocoa frameworks on Mac, I am trying to convert an NSData object in humanly understandable number.
Let say the NSData object is an image of NPIXEL. I know the binary data are coded in big endian and represent 32 bit integer (to be more precise 32 bit two complements integer). I write the piece of code bellow to convert the NSData into an int array. But the value I got are completely wrong (this does not means the measurement are bad, I used a special software to read the data and the value given by the software are different from the one I got with my code).
-(int *) GetArrayOfLongInt
{
//Get the total number of element into the Array
int Nelements=[self NPIXEL];
//CREATE THE ARRAY
int array[Nelements];
//FILL THE ARRAY
int32_t intValue;
int32_t swappedValue;
double Value;
int Nbit = abs(BITPIX)*GCOUNT*(PCOUNT + Nelements); Nbit/=sizeof(int32_t);
int i=0;
int step=sizeof(int32_t);
for(int bit=0; bit < Nbit; bit+=step)
{
[Img getBytes:&swappedValue range:NSMakeRange(bit,step)];
intValue= NSSwapBigIntToHost(swappedValue);
array[i]=intValue;
i++;
}
return array;
}
This piece of code (with minor change) work perfectly when the binary data represent float or double, but I dont when it is 16,32 or 64 bit integer. I also tried changingNSSapBigIntToHostintoNSSwapLittleInttoHost`. I even tried with long, but the results is still the same, I got bad values. What wrong I am doing ?
PS: Some of the variable in my code are already set elsewhere in my program. BITPIX is the bit size of each pixel. In this case 32. GCOUNT is equal to 1, PCOUNT 0 and Nelements is the total number of pixel I should have in my image.
Returning a pointer to a local variable is a very bad idea. array could get overwritten at any time (or if you were to write through the pointer, you could corrupt the stack). You probably want something like:
// CREATE THE ARRAY
int *array = malloc(Nelements * sizeof(int));
Your algorithm seems a bit overkill, too. Why not just copy out the whole array from the NSData object, and then byteswap the entries in place? Something like:
int32_t length = [Img length];
int32_t *array = malloc(length);
[Img getBytes:array length:length];
for (i = 0; i < length/sizeof(int32_t); i++)
{
array[i] = NSSwapBigIntToHost(array[i]);
}