Created
July 16, 2015 08:08
-
-
Save steipete/56ead1db6c81dd8134c8 to your computer and use it in GitHub Desktop.
After playing around with dispatch_io (https://gist.github.com/steipete/b22babbf3014e29c19f0), I ended up with this. Upside: Uses way less memory, controllable caching, similar performance, simpler code and supports priority donation implicitly since everything's sync.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static NSData *PSPDFCalculateSHA256FromFileURL(NSURL *fileURL, CC_LONG dataLength, NSError **error) { | |
NSCParameterAssert(fileURL); | |
NSData *shaData; | |
int fd = open(fileURL.path.UTF8String, O_RDONLY); | |
if (fd < 0) { | |
if (error) *error = [NSError pspdf_errorWithCode:PSPDFErrorCodeUnableToOpenPDF description:@"Failed to open file for calculating SHA256."]; | |
return nil; | |
} | |
// Disable cache, since we only need this once. | |
fcntl(fd, F_NOCACHE, 1); | |
// Enable read-ahead so system fetches data while we calculate the SHA. | |
fcntl(fd, F_RDAHEAD, 1); | |
// Prepare SHA hash | |
CC_SHA256_CTX ctx; | |
CC_SHA256_Init(&ctx); | |
// Start read and block until we are done. | |
size_t const bufferSize = 1024*1025*4; | |
char *buffer; | |
if (!(buffer = malloc(bufferSize * sizeof(char)))) { | |
if (error) *error = [NSError pspdf_errorWithCode:PSPDFErrorCodeOutOfMemory description:@"Unable to allocate buffer for calculating hash."]; | |
goto cleanup; | |
} | |
errno = 0; // just to be safe | |
size_t bytes = 0; | |
while (dataLength > 0) { | |
ssize_t bytes_read_max = MIN(bufferSize, dataLength); | |
ssize_t bytes_read = read(fd, buffer, bytes_read_max); | |
if (bytes_read == -1) { | |
if (errno == EINTR) | |
continue; | |
} | |
if (bytes_read <= 0) { | |
if (error) *error = [NSError pspdf_errorWithCode:PSPDFErrorCodeUnableToOpenPDF description:[NSString stringWithFormat:@"Failed to read data for calculating SHA256. errno: %d", errno]]; | |
goto cleanup; | |
} else { | |
CC_SHA256_Update(&ctx, (const void *)buffer, (CC_LONG)bytes_read); | |
} | |
bytes += bytes_read; | |
dataLength -= bytes_read; | |
} | |
// Finalize SHA256 calculation unless there's an error. | |
unsigned char sha256[CC_SHA256_DIGEST_LENGTH]; | |
CC_SHA256_Final(sha256, &ctx); | |
shaData = [NSData dataWithBytes:sha256 length:CC_SHA256_DIGEST_LENGTH]; | |
cleanup: | |
free(buffer); | |
close(fd); | |
return shaData; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment