NSMutableData remove bytes? - objective-c

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.

Related

how to Transpose NSData in 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

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 :)

Getting size of a pointer after memory allocation

I've been reading about sizeof, malloc, and malloc_size, but for some reason I cannot get it to work properly in objective c.
What I'm trying to do is to dynamically allocate memory and then check the size of the pointer.
I tried doing this:
void *pointer = malloc( sizeof(void) * 8 );
long test1 = malloc_size(pointer); // Its value is 16
long test2 = sizeof(pointer); // Its value is 8
The link below answer exactly the same question but it doesn't work for me.
EDIT:
I also tried using
char *malloc( sizeof(char) * 8)
but it didn't work either.
malloc_size is returning the correct answer - malloc returns a block of at least the size you request, but it may be (a little) larger. This is just a facet of the way dynamic memory is managed, it parallels the way disk files are made up of allocation blocks. A quick test on 64-bit Intel suggests malloc's allocation unit is probably 16 bytes.
pointer is of type of *, so no matter what memory is malloced to pointer, sizeof(pointer) should be fixed value, it's 4 (32bit sys) or 8 (64bit sys).

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.

How can I reverse the byte order of an NSInteger or NSUInteger in objective-c

This is a somewhat of a follow up to this posting but with a different question so I felt I should ask in a separate thread.
I am at the point where I have four consecutive bytes in memory that I have read in from a file. I'd like to store these as a bit array (the actual int value of them does not matter until later). When I print out what is in my int, I notice that it seems to be stored in reverse order (little endian).
Does anyone have a good method for reversing the order of the bytes. Then once reversed, picking out consecutive bits spanning two bytes and converting back to an int?
unsigned char data[] = { 0x00, 0x02, 0x45, 0x28 };
NSInteger intData = *((NSInteger *)data);
NSLog(#"data:%08x", intData); // data:28450200
Cocoa (or to be exact the Foundation framework) has functions to swap the endianness of bytes: NSSwapInt, NSSwapShort, NSSwapLong, and NSSwapLongLong. These swap around the bytes no matter what - they make big-endian integers from small-endian integers and vice versa.
If you know which format you have there are other functions that swap it to the native endianness: NSSwapLittleIntToHost and NSSwapBigIntToHost. There are also the reverse functions which swap from the native format to little or big endian format: NSSwapHostIntToLittle and NSSwapHostIntToBig. Those are available for the other integer types and floating point types as well. What they do is they call the primitive swap functions on the values if necessary. So NSSwapLittleIntToHost doesn’t do anything while NSSwapBigIntToHost returns the result of NSSwapInt on a little endian machine.
Note that these take parameters of the compilers integer types and not the NSInteger type. So depending on wether you’re generating 32bit or 64bit code you have to use different functions if you are using NSInteger.
You also should not cast your byte array to an integer pointer and dereference that. It would be better to assemble the integer using bit shift operations. Your code will only work if NSInteger is 32 bit wide. If it is 64 bit then your number will be garbage or your program might even crash. But even if you are using an integer type that is always 32 bit wide (int32_t from the C99 <stdint.h> header for example) this might not work as expected.