NSMutableData increment the underneath pointer and pass it to other APIs - objective-c

I have been given a task to replace all uint_8 * to NSMutableData.
In the existing code, a lot of pointer arithmetic is done on uint8_t and then passed onto other APIs which also accept uint8_t *.
However, when replacing uint_8 * with NSMutableData, how do I pointer arithmetic on NSMutableData?
One approach is
convert NSMutableData to uint8_t *.
do pointer arithmetic on uint8_t *.
convert uint8_t * back to NSMutableData and pass it to other APIs.
however, when converting uint8_t * to NSMutableData, I do not have length.
How to solve this?
Old code
func(uint8_t *p);
func2() {
uint8_t *p; //points to some piece of memory
func(p+10); //pass base address+ 10 bytes
}
New Code
func(NSMutableData *p);
func2() {
NSMutableData *data = [[NSMutableData alloc]
initWithLength:size];
// now, how to pass data + 10 bytes to func
func(???)
}

Related

get float value from nsdata objective-c iOS

I am trying to get a float value from a NSData object which contains several hex values. e.g. EC 51 38 41
From this 4 Byte values i want to get the float value 11.52. How do i have to do this in xcode?
I have tried it with NSScanner (scanFloat, scanHexFloat), NSNumberformatter and NSNumber, i created an Byte Array and tried float myFloat = *(float*)&myByteArray. All these Options i found here at stackoverflow.
I tested it in Windows with C# and there it was no problem:
byte[] bytes = new byte[4] { 0xEC, 0x51, 0x38, 0x41 };
float myFloat = System.BitConverter.ToSingle(bytes, 0);
Does anybody know how i have to do this in xcode???
Thanks, Benjamin
When converting binary data from a foreign protocol always make sure to include proper swapping for endianness:
uint32_t hostData = CFSwapInt32BigToHost(*(const uint32_t *)[data bytes]);
float value = *(float *)(&hostData);
You have to know the endianness of the encoded data. You might need to use CFSwapInt32LittleToHost instead.
NSData * data = ...; // loaded from bluetooth
float z;
[data getBytes:&z length:sizeof(float)];
Try this.
I have tries it with NSScanner (scanFloat, scanHexFloat), NSNumberformatter and NSNumber
You're barking up the wrong tree here. NSScanner is for scanning strings. NSNumber is not the same as NSData, and NSNumberFormatter won't work with NSData either.
NSData is a container for plain old binary data. You've apparently got a float stored in an NSData instance; if you want to access it, you'll need to get the data's bytes and then interpret those bytes however you like, e.g. by casting to float:
float *p = (float*)[myData bytes]; // -bytes returns a void* that points to the data
float f = *p;

Best way to release memory allocated using malloc

I have function to convert an integer into byte array (for iPhone). To add dynamicity I have allocate the array using malloc. But I think this will leak memory. What's best way to manage this memory,
+ (unsigned char *) intToByteArray:(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;
}
return arr;
}
When calling,
int x = 500;
unsigned char * bytes = [Util intToByteArray:x];
I want to avoid the call free(bytes) since, the calling function do not know or explicitly knows, the memory is allocated and not freed.
A few things:
The char type (and signed char and unsigned char) all have a size of 1 by definition, so sizeof(unsigned char) is unnecessary.
It looks like you just want to get the byte representation of an int object, if this is the case, it is not necessary to allocate more space for it, simply take the address of the int and cast it to a pointer to unsigned char *. If the byte order is wrong you can use the NSSwapInt function to swap the order of the bytes in the int and then take the address and cast to unsigned char *. For example:
int someInt = 0x12345678;
unsigned char *bytes = (unsigned char *) &someInt;
This cast is legal and reading from bytes is legal up until sizeof(int) bytes are read. This is accessing the “object representation”.
If you insist on using malloc, then you simply need to pass the buffer to free when you are done, as in:
free(bytes);
The name of your method does not imply the correct ownership of the returned buffer. If your method returns something that the caller is responsible for freeing, it is conventional to name the method using new, copy, or sometimes create. A more suitable name would be copyBytesFromInt: or something similar. Otherwise you could have the method accept a pre-allocated buffer and call the method getBytes:fromInt:, for example:
+ (void) getBytes:(unsigned char *) bytes fromInt:(int) num
{
for (int i = sizeof(num) - 1 ; i >= 0; i --) {
bytes[i] = num & 0xFF;
num = num >> 8;
}
}
You could wrap your bytes into a NSData instance:
NSData *data = [NSData dataWithBytesNoCopy:bytes length:sizeof(num) freeWhenDone:YES];
Make sure your method follows the usual object ownership rules.
Just call free(bytes); when you are done with the bytes (either at the end of method or in dealloc of the class)
since you want to avoid the free call, you could wrap your byte[] in a NSData object:
NSData *d = [NSData dataWithBytesNoCopy:bytes length:num freeWhenDone:YES];
The conventional way of handling this is for the caller to pass in an allocated byte buffer. That way the caller is responsible for freeing it. Something like:
int x = 500;
char *buffer = malloc(x * sizeof(char));
[Util int:x toByteArray:buffer];
…
free(buffer);
I would also consider creating an NSData to hold the bytes, this would take care of memory management for you, while still allowing you to alter the byte buffer:
+ (NSData *) intToByteArray:(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;
}
return [NSData dataWithBytesNoCopy:arr length:num freeWhenDone:YES];
}

How to store struct information on a uint64_t for Game Center challenges

I'm trying to store some game related information on the uint64_t context property of GKScore - to create a better gaming experience with the new Game Center Challenges. However, I'm not getting it right. I built a struct like below:
typedef struct{
unsigned int gameMode;
unsigned int destroyed;
unsigned int duration;
} GameInfo;
I try the following:
uint64_t myContext
GameInfo info;
info.gameMode = 2;
info.destroyed = 50;
info.duration = 100;
NSData *data = [NSData dataWithBytes:&info length:sizeof(info)];
[data getBytes:&myContext length:sizeof(myContext)];
to pack the struct to a NSData and then write the bytes to myContext.
Then, I try to recreate the information using the 64bit integer as follows:
NSData *newData = [NSData dataWithBytes:&myContext length:sizeof(myContext)];
GameInfo *result = (GameInfo*) [newData bytes];
however, when I log out the values, I see that I'm only able to capture the first two values (gameMode and destroyed). If I add more variables to the struct, I still only capture the first 2 variables.
What am I doing wrong? Is there a smarter way to do this?
You are trying to pack 96 bits of data (3 unsigned ints on iOS / ARM) into a 64 bit container. So you see the first two 32-bit values and not the third.
Maybe you could try using shorts or chars, depending on the range of values your struct will hold, and try to get the stuct's size down to < 64 bits. I think 3 char on ARM will get aligned out to 48 bits (might be wrong about that if so please let me know!). So maybe use short anyway.
EDIT: example of possible way to change your struct, assuming you'll only store 16-bit values in each field:
typedef struct{
uint16_t gameMode;
uint16_t destroyed;
uint16_t duration;
} GameInfo;

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.

Caching the struct Object

How do I create a cache for a struct pointer object in Objective-C? Is there any third party component for caching objects as Java and .NET have?
I have the following struct:
typedef struct _news {
references
char *headline;
char *story_url;
} news;
I have a double pointer for the above struct in an interface class. I would like to cache it for some time using Objective-C.
Are you searching for something like this?
// save
NSMutableData *data = [[NSMutableData alloc] init];
[data appendBytes:&p length:sizeof(news)];
// read
struct news *begin = (struct news *)[data bytes];