Rob Keniger
Rob Keniger

Reputation: 46020

Is there a way to create a CFData object from a file using memory-mapped file access?

I am restricted to using CoreFoundation in a particular app, and don't have access to NSData.

I need to access data from a file using memory mapping because the file could be quite large. With NSData, I can achieve this using the +dataWithContentsOfURL:options:error: method, passing in the NSDataReadingMappedAlways option.

Is it possible to do this with CFData? The only function I can find to actually create a CFData object directly from a file is the CFURLCreateDataAndPropertiesFromResource() function, which does not have any option to set the memory mapping flag.

Is there a lower-level way to load a CFData object from a file using memory-mapped reads? Do I have to drop down to mmap or something?

Upvotes: 3

Views: 2359

Answers (2)

abarnert
abarnert

Reputation: 365717

This is more of a comment than an answer, but it's too long to fit in a comment, so…

In general, when you don't know how to do something from Cocoa/Foundation, it's often worth looking at how the GNUstep equivalent is implemented. Of course GNUstep doesn't implement 100% of the latest version of Foundation, and it's written directly on top of POSIX rather than CoreFoundation, so it isn't always helpful… but often it is.

In NSData.m, there's no +dataWithContentsOfURL:options:error:, but there is a +dataWithContentsOfMappedFile: (and of course -initWithContentsOfMappedFile:) method, and the implementation of the NSDataMappedFile class that it depends on.

Ultimately, the NSDataMappedFile is a pretty simple wrapper around an mmap, and the NSData methods just create an NSDataMappedFile and call its -initWithContentsOfMappedFile:. The only real complexity is the fallback code (which makes sure to fake the mmap and just call [NSData initWithContentsOfFile:])—code which you explicitly don't want.

So, that's a good clue that you want to implement this exactly the way Kevin Ballard suggested.

Upvotes: 3

Lily Ballard
Lily Ballard

Reputation: 185671

You can create a CFData() from a byte buffer and a count. Given this, you should just be able to mmap() the file in question, and then pass the mapped byte buffer over to CFDataCreateWithBytesNoCopy(). The only real complication is you'll need to use a CFAllocatorRef that knows how to munmap() as the bytesDeallocator.

Upvotes: 5

Related Questions