Kyle
Kyle

Reputation: 17677

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?

Upvotes: 31

Views: 20867

Answers (4)

Mecki
Mecki

Reputation: 133019

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

Upvotes: 78

Gossamer
Gossamer

Reputation: 309

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.

Upvotes: 0

Jared Pochtar
Jared Pochtar

Reputation: 4985

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.

Upvotes: 1

RJ.
RJ.

Reputation: 289

Since NSMutableData is toll-free bridged with CFMutableDataRef, you can use the CFDataDeleteBytes() function:

NSMutableData *data = ...
CFDataDeleteBytes((CFMutableDataRef)data, CFRangeMake(3, 4));

Upvotes: 3

Related Questions