I\'ve an NSData object, the length is 4 bytes .These four bytes i\'m extracting from another NSData object using ,
fourByteData=[completeData subdataWithRang
Assuming _vertexData
is NSData
here
and you know what data (types) to expect in your buffer you can iterate thru this block with NSData's .length
property.
In this Example each data block was 32 Bytes (storing 8 x float values) and i was interested in logging starting at the 5th float value
float a,b,c,d; //prepare some values, no need to initialize
// loop thru assuming 8 floats are stored after each other
for (NSUInteger v = 0; v < _vertexData.length; v += sizeof(float)*8 ) {
// set a starting point for the range, here the 5th float
NSUInteger shift = v + (sizeof(float)*4);
// store result in a..
[_vertexData getBytes:&a range:NSMakeRange(shift,sizeof(a))];
// increase the starting point by the size of data before
shift += sizeof(a);
[_vertexData getBytes:&b range:NSMakeRange(shift,sizeof(b))];
shift += sizeof(b);
[_vertexData getBytes:&c range:NSMakeRange(shift,sizeof(c))];
shift += sizeof(c);
[_vertexData getBytes:&d range:NSMakeRange(shift,sizeof(d))];
fprintf(stderr, "r%f, g%f, b%f, a%f \n", a,b,c,d );
}
this could have been written much shorter, but for the sake of clarity and with less use of miss leading castings
maybe this helps someone
iOS integer stores LSB (lowest significant byte) in the first byte and MSB in the last byte. I have conversion routine to test all those things. check here,
Test ...
int i = 2342342;
NSData * d1 = [Util dataFromInt:i]; // {[MSB], ..., ... ,[LSB]} <0023bdc6>
NSData * d2 = [NSData dataWithBytes:&i length:4]; // {[LSB], ..., ... ,[MSB]} <c6bd2300>
int ci1 = [Util intFromData:d1];
int ci2 = [Util intFromDataReverse:d2];
Util.m
+ (NSData *) dataFromInt:(int)num {
unsigned char * arr = (unsigned char *) malloc(sizeof(num) * sizeof(unsigned char));
for (int i = sizeof(num) - 1 ; i >= 0; i --) {
arr[i] = num & 0xFF;
num = num >> 8;
}
NSData * data = [NSData dataWithBytes:arr length:sizeof(num)];
free(arr);
return data;
}
// {[MSB], ..., ... ,[LSB]}
+ (int) intFromData:(NSData *)data
{
int intSize = sizeof(int); // change it to fixe length
unsigned char * buffer = malloc(intSize * sizeof(unsigned char));
[data getBytes:buffer length:intSize];
int num = 0;
for (int i = 0; i < intSize; i++) {
num = (num << 8) + buffer[i];
}
free(buffer);
return num;
}
// {[LSB], ..., ... ,[MSB]}
+ (int) intFromDataReverse:(NSData *)data
{
int intSize = sizeof(int);// change it to fixe length
unsigned char * buffer = malloc(intSize * sizeof(unsigned char));
[data getBytes:buffer length:intSize];
int num = 0;
for (int i = intSize - 1; i >= 0; i--) {
num = (num << 8) + buffer[i];
}
free(buffer);
return num;
}
Is 268566528 the value you expect or perhaps you expect 528? If the correct value is 528 then the byte order is big-endian but the cpu is little-endian, the bytes need to be reversed.
So, if the correct value should be 528 then:
NSData *data4 = [completeData subdataWithRange:NSMakeRange(0, 4)];
int value = CFSwapInt32BigToHost(*(int*)([data4 bytes]));
Also note that network standard order is big-endian.
No you will get 16 bytes of data, since the range is from offset 0 and then 16 bytes.
If you had a NSData
instance with 4 bytes then you could do a simple type cast like this:
int value = *(int*)([data bytes]);
It depends on the Endianness notation of the data you want to convert, in relation to your device Endianness notation. wiki on Endianness
To keep it simple you need to check does two method
NSData *data4 = [completeData subdataWithRange:NSMakeRange(0, 4)];
int value = CFSwapInt32BigToHost(*(int*)([data4 bytes]));
or
NSData *data4 = [completeData subdataWithRange:NSMakeRange(0, 4)];
int value = CFSwapInt32LittleToHost(*(int*)([data4 bytes]));
And check which one make more sense when you parse the data.
- (unsigned)parseIntFromData:(NSData *)data{
NSString *dataDescription = [data description];
NSString *dataAsString = [dataDescription substringWithRange:NSMakeRange(1, [dataDescription length]-2)];
unsigned intData = 0;
NSScanner *scanner = [NSScanner scannerWithString:dataAsString];
[scanner scanHexInt:&intData];
return intData;
}
int numberOfChunks = [self parseIntFromData:data];