copy NSData into int32_t variable

梦想与她 提交于 2019-12-12 00:29:20

问题


I have a big NSDictionary full of entries that are all of type NSData. I have several entries that need to be of type int32_t however I am not 100% sure how to copy the data in the entries of the NSDictionary across..

is it as simple as doing the following -

.h

//..
int32_t myint;
}
@property (assign) int32_t myint;
//..

.m

//..
@synthesize cardID;
//..
- (void)assignSearchData:(NSData*)searchData
{
myint = [searchData objectForKey:@"IntKey"];
}
//..

or do I need some type of data conversion inside my method?

and a quick side question, have I even declared the int32_t correctly? I have looked for an example in the docs and on here but am struggling to find one.


回答1:


Well, you can access the raw bytes in the data object directly.

void const *dataPtr = [data bytes];

Now that you have a pointer to raw memory, you can copy it any way you want (these rules apply to any data transfer, not just iOS). If you need to consider alignment boundaries, you need to use memcpy.

int32_t myInt;
memcpy(&myInt, dataPtr);

Otherwise, if on an architecture that allows integer manipulation across alignment boundaries...

int32_t myInt = *(int32_t const *)dataPtr;

Now, ARM supports access across alignment boundaries, but it's much slower. I have not done a performance comparison, but you are not continuing to use the mal-alignged pointer, so it may be better than the memcpy function call (though, to be honest, that is probably way too much performance consideration for you).

The biggest concern is byte-order of the data. If it's provided by you, then do whatever you want, but you should prefer one standard.

If it's coming from a third party, it's probably in network byte order (aka big-endian). You may need to convert to your host endian representation. Fortunately, that's straight forward with hton and ntoh and their friends.

FWIW, Intel is little-endian, and network-byte-order is big-endian, modern Macs and iOS devices are little-endian, older Macs are big-endian.

// Convert from network order to host order.
// Does the right thing wherever your code is running
myInt = ntohl(myInt);

In short, either...

int32_t myInt = ntohl(*(int32_t const *)[data bytes]);

or

int32_t myInt;
memcpy(&myInt, [data bytes);
myInt = ntohl(myInt);

So, the data has to get in there somehow. It's, the inverse...

int32_t myInt = 42;
myInt = htonl(myInt);
NSData *data = [NSData dataWithBytesNoCopy:&myInt length:sizeof(myInt) freeWhenDone:NO];

Of course, use the right Data initializer... that one will just use those raw bytes on the stack, so you better not use it after the stack unwinds.

You don't have to worry about alignment on the data you send, unless you are guaranteeing the receiver that the data will be aligned to some boundary.




回答2:


Yes, int32_t is fine. So you have a stream of byes. What you need to know is what he layout of the bytes are. It you know what the data is it will be pretty easy to construct it.

Given a NSData object with a length of 4 (size of int32_t), then you would :

int32_t val;
if([data length] == sizeof(uint32_t)) {
    void *bytes = [data bytes];
    // if the layout is same as iOS then
    memcpy(&val, bytes, sizeof(int32_t) );
}

if that is not the case, then you can try:

unsigned char val[4] = {0,0,0,0};
if([data length] == sizeof(uint32_t)) {
    memcpy(val, bytes, sizeof(int32_t) );
    then rearrange the bytes
}


来源:https://stackoverflow.com/questions/11874359/copy-nsdata-into-int32-t-variable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!