diff options
-rw-r--r-- | Source/SPDataImport.m | 4 | ||||
-rw-r--r-- | Source/SPExportFile.m | 2 | ||||
-rw-r--r-- | Source/SPExporter.m | 2 | ||||
-rw-r--r-- | Source/SPFileHandle.h | 21 | ||||
-rw-r--r-- | Source/SPFileHandle.m | 209 |
5 files changed, 108 insertions, 130 deletions
diff --git a/Source/SPDataImport.m b/Source/SPDataImport.m index 8ce41afc..64f314a9 100644 --- a/Source/SPDataImport.m +++ b/Source/SPDataImport.m @@ -389,7 +389,7 @@ [[NSFileManager defaultManager] removeItemAtPath:filename error:nil]; return; } - fileIsCompressed = [sqlFileHandle isCompressed]; + fileIsCompressed = ([sqlFileHandle compressionFormat] != SPNoCompression); // Grab the file length fileTotalLength = (NSUInteger)[[[[NSFileManager defaultManager] attributesOfItemAtPath:filename error:NULL] objectForKey:NSFileSize] longLongValue]; @@ -752,7 +752,7 @@ // Grab the file length and status fileTotalLength = (NSUInteger)[[[[NSFileManager defaultManager] attributesOfItemAtPath:filename error:NULL] objectForKey:NSFileSize] longLongValue]; if (!fileTotalLength) fileTotalLength = 1; - fileIsCompressed = [csvFileHandle isCompressed]; + fileIsCompressed = ([csvFileHandle compressionFormat] != SPNoCompression); // If importing a bzipped file, use indeterminate progress bars as no progress is available BOOL useIndeterminate = NO; diff --git a/Source/SPExportFile.m b/Source/SPExportFile.m index 132e1028..5d1c040d 100644 --- a/Source/SPExportFile.m +++ b/Source/SPExportFile.m @@ -191,7 +191,7 @@ return; } - [[self exportFileHandle] setShouldWriteWithCompressionFormat:fileCompressionFormat]; + [[self exportFileHandle] setCompressionFormat:fileCompressionFormat]; } #pragma mark - diff --git a/Source/SPExporter.m b/Source/SPExporter.m index 195d900d..db5cf809 100644 --- a/Source/SPExporter.m +++ b/Source/SPExporter.m @@ -95,7 +95,7 @@ exportOutputCompressFile = compress; - [[[self exportOutputFile] exportFileHandle] setShouldWriteWithCompressionFormat:(compress) ? [self exportOutputCompressionFormat] : SPNoCompression]; + [[[self exportOutputFile] exportFileHandle] setCompressionFormat:(compress) ? [self exportOutputCompressionFormat] : SPNoCompression]; } /** diff --git a/Source/SPFileHandle.h b/Source/SPFileHandle.h index 23162385..5622b1b6 100644 --- a/Source/SPFileHandle.h +++ b/Source/SPFileHandle.h @@ -28,6 +28,7 @@ // // More info at <https://github.com/sequelpro/sequelpro> +union SPSomeFileHandle; /** * @class SPFileHandle SPFileHandle.h * @@ -39,7 +40,7 @@ */ @interface SPFileHandle : NSObject { - void *wrappedFile; + union SPSomeFileHandle *wrappedFile; char *wrappedFilePath; NSMutableData *buffer; @@ -53,7 +54,6 @@ BOOL dataWritten; BOOL allDataWritten; BOOL fileIsClosed; - BOOL useCompression; SPFileCompressionFormat compressionFormat; } @@ -69,7 +69,7 @@ #pragma mark Initialisation // Returns a file handle initialised with a file -- (id)initWithFile:(void *)theFile fromPath:(const char *)path mode:(int)mode; +- (id)initWithFile:(FILE *)theFile fromPath:(const char *)path mode:(int)mode; #pragma mark - #pragma mark Data reading @@ -87,7 +87,11 @@ #pragma mark Data writing // Set whether data should be written in the supplied compression format (defaults to NO on a fresh object) -- (void)setShouldWriteWithCompressionFormat:(SPFileCompressionFormat)useCompressionFormat; +// This has no influence on reading data. +- (void)setCompressionFormat:(SPFileCompressionFormat)useCompressionFormat; + +// Returns the compression format being used. Currently gzip or bzip2 only. +- (SPFileCompressionFormat)compressionFormat; // Write the provided data to the file - (void)writeData:(NSData *)data; @@ -98,13 +102,4 @@ // Prevents further access to the file - (void)closeFile; -#pragma mark - -#pragma mark File information - -// Returns whether compression is enabled on the file -- (BOOL)isCompressed; - -// Returns the compression format being used. Currently gzip or bzip2 only. -- (SPFileCompressionFormat)compressionFormat; - @end diff --git a/Source/SPFileHandle.m b/Source/SPFileHandle.m index 3971e18b..3e0489a4 100644 --- a/Source/SPFileHandle.m +++ b/Source/SPFileHandle.m @@ -37,6 +37,12 @@ // waits until some has been written out. This can affect speed and memory usage. #define SPFH_MAX_WRITE_BUFFER_SIZE 1048576 +union SPSomeFileHandle { + FILE *file; + BZFILE *bzfile; + gzFile *gzfile; +}; + @interface SPFileHandle () - (void)_writeBufferToData; @@ -57,14 +63,14 @@ * theFile is a FILE when compression is disabled, a gzFile when gzip compression is enabled * or a BZFILE when bzip2 compression is enabled. */ -- (id)initWithFile:(void *)theFile fromPath:(const char *)path mode:(int)mode +- (id)initWithFile:(FILE *)theFile fromPath:(const char *)path mode:(int)mode { if ((self = [super init])) { dataWritten = NO; allDataWritten = YES; fileIsClosed = NO; - wrappedFile = theFile; + wrappedFile = malloc(sizeof(*wrappedFile)); //FIXME ivar can be moved to .m file with "modern objc", replacing the opaque struct pointer wrappedFilePath = malloc(strlen(path) + 1); strcpy(wrappedFilePath, path); @@ -83,65 +89,62 @@ bufferPosition = 0; endOfFile = NO; - useCompression = NO; compressionFormat = SPNoCompression; + processingThread = nil; // If in read mode, set up the buffer if (fileMode == O_RDONLY) { - - int i, c; - char bzbuf[4]; - const char *charFileMode = fileMode == O_WRONLY ? "wb" : "rb"; - - BZFILE *bzfile; - gzFile *gzfile = gzopen(path, charFileMode); - - // Set gzip buffer - gzbuffer(gzfile, 131072); - - // Get the first 4 bytes from the file - for (i = 0; (c = getc(wrappedFile)) != EOF && i < 4; bzbuf[i++] = c); - - rewind(wrappedFile); - - // Test to see if the file is gzip compressed - BOOL isGzip = !gzdirect(gzfile); - - // Test to see if the first 2 bytes extracted from the file match the Bzip2 signature/magic number - // (BZ). The 3rd byte should be either 'h' (Huffman encoding) or 0 (Bzip1 - deprecated) to - // indicate the Bzip version. Finally, the 4th byte should be a number between 1 and 9 that indicates - // the block size used. - - BOOL isBzip2 = ((bzbuf[0] == 'B') && (bzbuf[1] == 'Z')) && - ((bzbuf[2] == 'h') || (bzbuf[2] == '0')) && - ((bzbuf[3] >= 0x31) && (bzbuf[3] <= 0x39)); - - if (isBzip2) bzfile = BZ2_bzopen(path, charFileMode); - - useCompression = isGzip || isBzip2; - - if (useCompression) { - if (isGzip) { + // Test for GZIP (by opening the file with gz and checking what happens) + { + gzFile *gzfile = gzopen(path, "rb"); + + // Set gzip buffer + gzbuffer(gzfile, 131072); + + // Test to see if the file is gzip compressed + if(!gzdirect(gzfile)) { compressionFormat = SPGzipCompression; - wrappedFile = gzfile; + wrappedFile->gzfile = gzfile; } - else if (isBzip2) { - compressionFormat = SPBzip2Compression; - wrappedFile = bzfile; + else { + // ...not gzip gzclose(gzfile); } + } + // Test for BZ (by checking the file header) + if(compressionFormat == SPNoCompression) { + char bzbuf[4]; + int i, c; - fclose(theFile); + // Get the first 4 bytes from the file + for (i = 0; (c = getc(theFile)) != EOF && i < 4; bzbuf[i++] = c); + + rewind(theFile); + + // Test to see if the first 2 bytes extracted from the file match the Bzip2 signature/magic number + // (BZ). The 3rd byte should be either 'h' (Huffman encoding) or 0 (Bzip1 - deprecated) to + // indicate the Bzip version. Finally, the 4th byte should be a number between 1 and 9 that indicates + // the block size used. + + BOOL isBzip2 = ((bzbuf[0] == 'B') && (bzbuf[1] == 'Z')) && + ((bzbuf[2] == 'h') || (bzbuf[2] == '0')) && + ((bzbuf[3] >= 0x31) && (bzbuf[3] <= 0x39)); + + if (isBzip2) { + compressionFormat = SPBzip2Compression; + wrappedFile->bzfile = BZ2_bzopen(path, "rb"); + } + } + // Default to plain + if(compressionFormat == SPNoCompression) { + wrappedFile->file = theFile; } else { - gzclose(gzfile); + fclose(theFile); } - - processingThread = nil; } // In write mode, set up a thread to handle writing in the background else if (fileMode == O_WRONLY) { - useCompression = NO; processingThread = [[NSThread alloc] initWithTarget:self selector:@selector(_writeBufferToData) object:nil]; [processingThread setName:@"SPFileHandle data writing thread"]; [processingThread start]; @@ -204,17 +207,15 @@ { long dataLength = 0; void *data = malloc(length); - - if (useCompression) { - if (compressionFormat == SPGzipCompression) { - dataLength = gzread(wrappedFile, data, (unsigned)length); - } - else if (compressionFormat == SPBzip2Compression) { - dataLength = BZ2_bzread(wrappedFile, data, (int)length); - } + + if (compressionFormat == SPGzipCompression) { + dataLength = gzread(wrappedFile->gzfile, data, (unsigned)length); + } + else if (compressionFormat == SPBzip2Compression) { + dataLength = BZ2_bzread(wrappedFile->bzfile, data, (int)length); } else { - dataLength = fread(data, 1, length, wrappedFile); + dataLength = fread(data, 1, length, wrappedFile->file); } return [NSMutableData dataWithBytesNoCopy:data length:dataLength freeWhenDone:YES]; @@ -235,13 +236,16 @@ */ - (NSUInteger)realDataReadLength { - if ((fileMode == O_WRONLY) || (compressionFormat == SPBzip2Compression)) return 0; + if (fileMode == O_WRONLY) return 0; - if (useCompression && (compressionFormat == SPGzipCompression)) { - return gzoffset(wrappedFile); + if (compressionFormat == SPGzipCompression) { + return gzoffset(wrappedFile->gzfile); + } + else if(compressionFormat == SPBzip2Compression) { + return 0; } else { - return ftell(wrappedFile); + return ftell(wrappedFile->file); } } @@ -253,40 +257,34 @@ * to NO on a fresh object. If this is called after data has been * written, an exception is thrown. */ -- (void)setShouldWriteWithCompressionFormat:(SPFileCompressionFormat)useCompressionFormat +- (void)setCompressionFormat:(SPFileCompressionFormat)useCompressionFormat { if (compressionFormat == useCompressionFormat) return; // Regardless of the supplied argument, close the current file according to how it was previously opened - if (useCompression) { - if (compressionFormat == SPGzipCompression) { - gzclose(wrappedFile); - } - else if (compressionFormat == SPBzip2Compression) { - BZ2_bzclose(wrappedFile); - } + if (compressionFormat == SPGzipCompression) { + gzclose(wrappedFile->gzfile); + } + else if (compressionFormat == SPBzip2Compression) { + BZ2_bzclose(wrappedFile->bzfile); } else { - fclose(wrappedFile); + fclose(wrappedFile->file); } if (dataWritten) [NSException raise:NSInternalInconsistencyException format:@"Cannot change compression settings when data has already been written."]; - useCompression = ((useCompressionFormat == SPGzipCompression) || (useCompressionFormat == SPBzip2Compression)); - compressionFormat = useCompressionFormat; - if (useCompression) { - if (compressionFormat == SPGzipCompression) { - wrappedFile = gzopen(wrappedFilePath, "wb"); - gzbuffer(wrappedFile, 131072); - } - else if (compressionFormat == SPBzip2Compression) { - wrappedFile = BZ2_bzopen(wrappedFilePath, "wb"); - } - } + if (compressionFormat == SPGzipCompression) { + wrappedFile->gzfile = gzopen(wrappedFilePath, "wb"); + gzbuffer(wrappedFile->gzfile, 131072); + } + else if (compressionFormat == SPBzip2Compression) { + wrappedFile->bzfile = BZ2_bzopen(wrappedFilePath, "wb"); + } else { - wrappedFile = fopen(wrappedFilePath, "wb"); + wrappedFile->file = fopen(wrappedFilePath, "wb"); } } @@ -345,16 +343,14 @@ if (!fileIsClosed) { [self synchronizeFile]; - if (useCompression) { - if (compressionFormat == SPGzipCompression) { - gzclose(wrappedFile); - } - else if (compressionFormat == SPBzip2Compression) { - BZ2_bzclose(wrappedFile); - } - } + if (compressionFormat == SPGzipCompression) { + gzclose(wrappedFile->gzfile); + } + else if (compressionFormat == SPBzip2Compression) { + BZ2_bzclose(wrappedFile->bzfile); + } else { - fclose(wrappedFile); + fclose(wrappedFile->file); } if (processingThread) { @@ -372,14 +368,6 @@ #pragma mark File information /** - * Returns whether compression is enabled on the file. - */ -- (BOOL)isCompressed -{ - return useCompression; -} - -/** * Returns the compression format being used. Currently gzip or bzip2 only. */ - (SPFileCompressionFormat)compressionFormat @@ -418,22 +406,16 @@ // Write out the data long bufferLengthWrittenOut = 0; - - if (useCompression) { - switch (compressionFormat) - { - case SPGzipCompression: - bufferLengthWrittenOut = gzwrite(wrappedFile, [dataToBeWritten bytes], (unsigned)[dataToBeWritten length]); - break; - case SPBzip2Compression: - bufferLengthWrittenOut = BZ2_bzwrite(wrappedFile, (void *)[dataToBeWritten bytes], (int)[dataToBeWritten length]); - break; - default: - break; - } - } - else { - bufferLengthWrittenOut = fwrite([dataToBeWritten bytes], 1, [dataToBeWritten length], wrappedFile); + + switch (compressionFormat) { + case SPGzipCompression: + bufferLengthWrittenOut = gzwrite(wrappedFile->gzfile, [dataToBeWritten bytes], (unsigned)[dataToBeWritten length]); + break; + case SPBzip2Compression: + bufferLengthWrittenOut = BZ2_bzwrite(wrappedFile->bzfile, (void *)[dataToBeWritten bytes], (int)[dataToBeWritten length]); + break; + default: + bufferLengthWrittenOut = fwrite([dataToBeWritten bytes], 1, [dataToBeWritten length], wrappedFile->file); } // Restore data to the buffer if it wasn't written out @@ -470,6 +452,7 @@ if (processingThread) SPClear(processingThread); + free(wrappedFile); free(wrappedFilePath); SPClear(buffer); |