how to Transpose NSData in objective-c? - objective-c

I have a NSString which i have to convert into NSData. After converting into NSData, I need to transpose the NSData in objective-c.
How do i transpose NSData in objective -c ?
Thanks

It seems you wish to reverse the order of the bytes, here is an outline algorithm:
Use NSData's length to get the number of bytes
Allocate a C-array of type Byte to hold the bytes. Use one of the malloc() family.
Use getBytes:length: to get a copy of the bytes
Set a C Byte * variable, say frontPtr, to point at the first byte; set another, say rearPtr to point at the last byte.
Now iterate, exchanging the bytes referenced by the two pointers, then increment frontPtr, decrement rearPtr, and keep iterating while rearPtr > frontPtr.
Create a new NSData from the working buffer using NSData's + dataWithBytesNoCopy:length:freeWhenDone: passing YES as the last argument - this will take ownership of the malloc'ed buffer so there is no need for you to free it.
The algorithm simply moves two pointers from the ends of the buffer towards the middle exchanging bytes as it goes. The termination condition make it work for even and odd lengths (in the latter case the middle byte doesn't need to be swapped).
If one the other hand you didn't wish to reverse the order of the bytes, but instead reverse the order of bits in each byte Google "C bit reverse" and follow the same general structure as the above algorithm but do bit reversing in the loop.
If after coding the above you have a problem ask a new question, include your code, and explain your issue. Someone will undoubtedly help you.
HTH

Related

Can I use memchr safely with an internal UTF-8 char * returned from an NSString?

I'd like to use memchr instead of strlen to find the length of a C string potentially used as the backing string of an NSString. Is this safe to do, or do I risk reading memory that I don't own, causing a crash? Let's assume that the NSString will not be released before I'm done with the internal buffer.
memchr(s, 0, XXX) and strlen(s) should pretty much behave identically, save for mechr()'s ability to terminate after XXX bytes. But strnlen() can do that, too.
And that behavior is probably exactly what you don't want.
Neither function accounts for any kind of unicode encoding. Thus, the returned length will be the length-in-bytes and not the # of characters.
Use -length on the NSString if you want the string length. Beyond that, what are you trying to do?

Difference between sizeof and length of NSData

I'm confused. What is deference between sizeof and .length of NSData. Length is a count of characters? Right? but does it mean sizeof? Can anybody explain me more exactly plz
sizeof() is a language keyword that returns the storage size of a type and is evaluated at compile time.
For example:
NSData *obj = [NSData data];
NSLog(#"%lu", sizeof(obj));
would print either 4 on a 32-bit platform or 8 on a 64-bit platform as obj is a pointer and that's how much space a pointer takes on those platforms.
It's the same as:
NSLog(#"%lu", 4);
or
NSLog(#"%lu", 8);
depending on the platform being compiled on.
However NSData is an object that stores data and it provides the length method so you can interrogate how much data it is currently storing. It is evaluated at runtime.
NSLog(#"%lu", obj.length);
prints 0 as that NSData object is empty.
I'm not expert in iOS, but I tried to look a bit. It seems that .Length is "number of bytes contained in the receiver". While .sizeof represents "actual number of bytes that whole NSData structure occupies in memory".
In other languages it could behave differently - i.e. C#'s string: length will be 20 for 20 characters, but while C# uses Unicode - sizof() will return 40. However, other objects might behave in totally different manner....
I think that in your example sizeof() might however return two possible results - number of bytes occupied by NSData internal structures (like pointer(s) to the real data, counters etc.) WITH or WITHOUT size of contained data.
I suppose the best way would be to try to store some data and compare outputs of the two methods :) If NSData is simply pointer - the results of .sizeof will be just 4 or 8 - size of the pointer :)

Objective-C Packing Data using NSMutableData?

I need to put a short and integer at the begging of a message that i am sending to a java server. The server is expecting to read a short (message id) then an integer (message length). I've read in the stackoverflow that NSMutableData is similar to java ByteBuffer.
I am trying to pack the message into NSMutableData then send it.
So this is what I have but is not working !.
NSMutableData *data = [NSMutableData dataWithLength:(sizeof(short) + sizeof(int))];
short msg_id = 2;
int length = 198;
[data appendBytes:&msg_id length:sizeof(short)];
[data appendBytes:&length length:sizeof(int)];
send(sock, data, 6, 0);
The server is using Java ByteBuffer to read in the received data. So the bytes coming in is:
32,120,31,0,2,0
which is invalid.
The correct value so the ByteBuffer can read them as .getShort() and .getInt()
0,2,0,0,0,-66
You're basically putting stuff into the NSData object correctly, but you're not using it with the send function correctly. First off, as dreamlax suggests, use NSMutableData's -initWithCapacity initializer to get a capacity, not zeroed bytes.
Your data pointer is a pointer to an Objective-C (NSData) object, not a the actual raw byte buffer. The send function is a classic UNIX-y C function, and doesn't know anything about Objective-C objects. It expects a pointer to the actual bytes:
send(sock, [data bytes], [data length], 0);
Also, FWIW, note that endianness matters here if you're expecting to recover the multibyte fields on the server. Consider using HTONL and HTONS on the short and int values before putting them in the NSData buffer, assuming the server expects "network" byte order for its packet format (though maybe you control that).
I think your use of dataWithLength: will give you an NSMutableData object with 6 bytes all initialised to 0, but then you append 6 more bytes with actual values (so you'll end up with 12 bytes all up). I'm assuming here that short is 2 bytes and int is 4. I believe you want to use dataWithCapacity: to hint how much memory to reserve for your data that you are packing.
As quixoto has pointed out, you need to use the bytes method, which returns a pointer to the first byte of the actual data. The length method will return the number of bytes you have.
Another thing you need to watch out for is endianness. The position of the most significant byte is dependent on the underlying architecture.

NSMutableData remove bytes?

I can add bytes to a NSMutableData instance easily by using the appendData method, however I do not see any similar method for removing data? Am I overlooking something, or do I need to create a new object and copy over only the bytes I need?
Please see the documentation of the following method:
- (void)replaceBytesInRange:(NSRange)range
withBytes:(const void *)replacementBytes
length:(NSUInteger)replacementLength
Apple says the following:
If the length of range is not equal to
replacementLength, the receiver is
resized to accommodate the new bytes.
Any bytes past range in the receiver
are shifted to accommodate the new
bytes. You can therefore pass NULL for
replacementBytes and 0 for
replacementLength to delete bytes in
the receiver in the range range. You
can also replace a range (which might
be zero-length) with more bytes than
the length of the range, which has the
effect of insertion (or “replace some
and insert more”).
To remove 10 byte from the end, use:
data.length = data.length - 10;
It could also be done via replaceBytesInRange, but it's in fact much faster, because the bytes are not really removed. Instead only the internal size variable is changed and NSMutableData will behave as if the bytes were removed. IOW, this is a O(1) operation (that means it will always take equally long to perform, regardless of how many bytes you remove), and it is very fast.
To remove 10 byte from front, use:
[data replaceBytesInRange:NSMakeRange(0, 10) withBytes:NULL length:0];
To remove 10 bytes in the middle (e.g. after 20 bytes), use:
[data replaceBytesInRange:NSMakeRange(20, 10) withBytes:NULL length:0];
replaceBytesInRange is a O(n) operation, though. The time required to perform the operation depends on how many bytes the data object has and where you remove them, as all bytes right to the remove location must be shifted to the left. It is still pretty fast and only limited by the throughput of your computer's memory (RAM). If you have 10 MB of data and you remove 1 MB from front, 9 MB are copied to fill the gap of the just removed MB. So the speed of the operation depends on how fast your system can move 9 MB of RAM from one address to another one (which on my system takes 0.2 milliseconds for 9 MB).
Since NSMutableData is toll-free bridged with CFMutableDataRef, you can use the CFDataDeleteBytes() function:
NSMutableData *data = ...
CFDataDeleteBytes((CFMutableDataRef)data, CFRangeMake(3, 4));
If the data you want to remove is at the end, you can use
[NSMutableDataInstance setLength:[NSMutableDataInstance length] - n];
or with the obj-c 2.0 syntax
NSMutableDataInstance.length -= n;
for anything more complicated than that I'd recommend manipulating the raw data.
I see that this thread has the answer, but nevertheless this could be valuable add. To remove all bytes from NSMuttableData, you can create new Data and copy it to original:
[myData setData:[NSData dataWithBytes:NULL length:0]];
This works great.

Malloc'ed string contains garbage values

I just converted an Objective-C library to a C library in the hopes of making it cross platform. However, everything appears to do okay until I send this thing off to be processed.
It's at the point I get an error.
Looking back a few revisions, I noticed something in the debugger.
Right after a malloc'd string like so:
char *theString = malloc(SOME_SIZE * sizeof(char));
I would see that theString is \x03 and *theString is "3 '\003'".
I assumed at first that this was just weird memory since I haven't don a strcat or anything to it, but that odd starting character(s) carry through, and recurs at every other point that I perform a similar malloc.
In terms of normal processing, this is fine. Unfortunately, I don't understand what it is, otherwise, I'd just do something drastic like cutting off that first character or something.
Can someone explain to me what that is and how I deal with it if I want to convert it to an NSString safely?
The value returned by malloc is not guaranteed to be set to any specific value. It's only guaranteed to point to memory you own of length at least as long as you specified. If you want the memory initalized to some value you'll need to do it yourself. Or alternately use calloc which will zero out the memory.