You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ag...@apache.org on 2013/03/15 21:45:42 UTC
ios commit: [CB-2652] Make FileReader.readAs*() functions run on a
background thread
Updated Branches:
refs/heads/master b6e3bb46f -> f9ba26e3d
[CB-2652] Make FileReader.readAs*() functions run on a background thread
Also refactored to remove copy/paste.
Project: http://git-wip-us.apache.org/repos/asf/cordova-ios/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-ios/commit/f9ba26e3
Tree: http://git-wip-us.apache.org/repos/asf/cordova-ios/tree/f9ba26e3
Diff: http://git-wip-us.apache.org/repos/asf/cordova-ios/diff/f9ba26e3
Branch: refs/heads/master
Commit: f9ba26e3da6fbc36c8ddd8c5bf7af4111e12e78a
Parents: b6e3bb4
Author: Andrew Grieve <ag...@chromium.org>
Authored: Mon Mar 11 22:09:16 2013 -0400
Committer: Andrew Grieve <ag...@chromium.org>
Committed: Fri Mar 15 16:44:07 2013 -0400
----------------------------------------------------------------------
CordovaLib/Classes/CDVFile.h | 1 +
CordovaLib/Classes/CDVFile.m | 305 +++++++++++------------------
CordovaLib/Classes/CDVPluginResult.m | 10 +-
3 files changed, 120 insertions(+), 196 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/f9ba26e3/CordovaLib/Classes/CDVFile.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVFile.h b/CordovaLib/Classes/CDVFile.h
index e3fdc83..eaf8cbe 100644
--- a/CordovaLib/Classes/CDVFile.h
+++ b/CordovaLib/Classes/CDVFile.h
@@ -21,6 +21,7 @@
#import "CDVPlugin.h"
enum CDVFileError {
+ NO_ERROR = 0,
NOT_FOUND_ERR = 1,
SECURITY_ERR = 2,
ABORT_ERR = 3,
http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/f9ba26e3/CordovaLib/Classes/CDVFile.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVFile.m b/CordovaLib/Classes/CDVFile.m
index e491ef8..bb12309 100644
--- a/CordovaLib/Classes/CDVFile.m
+++ b/CordovaLib/Classes/CDVFile.m
@@ -1053,238 +1053,161 @@ NSString* const kCDVAssetsLibraryPrefix = @"assets-library://";
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
}
+- (void)readFileWithPath:(NSString*)path start:(NSInteger)start end:(NSInteger)end callback:(void (^)(NSData *, NSString * mimeType, CDVFileError))callback
+{
+ if (path == nil) {
+ callback(nil, nil, SYNTAX_ERR);
+ } else {
+ [self.commandDelegate runInBackground:^ {
+ if ([path hasPrefix:kCDVAssetsLibraryPrefix]) {
+ // In this case, we need to use an asynchronous method to retrieve the file.
+ // Because of this, we can't just assign to `result` and send it at the end of the method.
+ // Instead, we return after calling the asynchronous method and send `result` in each of the blocks.
+ ALAssetsLibraryAssetForURLResultBlock resultBlock = ^(ALAsset * asset) {
+ if (asset) {
+ // We have the asset! Get the data and send it off.
+ ALAssetRepresentation* assetRepresentation = [asset defaultRepresentation];
+ Byte* buffer = (Byte*)malloc ([assetRepresentation size]);
+ NSUInteger bufferSize = [assetRepresentation getBytes:buffer fromOffset:0.0 length:[assetRepresentation size] error:nil];
+ NSData* data = [NSData dataWithBytesNoCopy:buffer length:bufferSize freeWhenDone:YES];
+ NSString* MIMEType = (__bridge_transfer NSString*)UTTypeCopyPreferredTagWithClass ((__bridge CFStringRef)[assetRepresentation UTI], kUTTagClassMIMEType);
+
+ callback (data, MIMEType, NO_ERROR);
+ } else {
+ callback (nil, nil, NOT_FOUND_ERR);
+ }
+ };
+ ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError * error) {
+ // Retrieving the asset failed for some reason. Send the appropriate error.
+ NSLog (@"Error: %@", error);
+ callback (nil, nil, SECURITY_ERR);
+ };
+
+ ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init];
+ [assetsLibrary assetForURL:[NSURL URLWithString:path] resultBlock:resultBlock failureBlock:failureBlock];
+ } else {
+ NSString* mimeType = [self getMimeTypeFromPath:path];
+ if (mimeType == nil) {
+ mimeType = @"*/*";
+ }
+ NSFileHandle* file = [NSFileHandle fileHandleForReadingAtPath:path];
+ if (start > 0) {
+ [file seekToFileOffset:start];
+ }
+
+ NSData* readData;
+ if (end < 0) {
+ readData = [file readDataToEndOfFile];
+ } else {
+ readData = [file readDataOfLength:(end - start)];
+ }
+
+ [file closeFile];
+
+ callback (readData, mimeType, readData != nil ? NO_ERROR:NOT_FOUND_ERR);
+ }
+ }];
+ }
+}
+
/* read and return file data
* IN:
* NSArray* arguments
* 0 - NSString* fullPath
- * 1 - NSString* encoding - NOT USED, iOS reads and writes using UTF8!
- * 2 - NSString* start - OPTIONAL, only provided when not == 0.
- * 3 - NSString* end - OPTIONAL, only provided when not == length.
+ * 1 - NSString* encoding
+ * 2 - NSString* start
+ * 3 - NSString* end
*/
- (void)readAsText:(CDVInvokedUrlCommand*)command
{
// arguments
- NSString* argPath = [command.arguments objectAtIndex:0];
- NSInteger start = 0;
- NSInteger end = -1;
-
- if ([command.arguments count] >= 3) {
- start = [[command.arguments objectAtIndex:2] integerValue];
- }
- if ([command.arguments count] >= 4) {
- end = [[command.arguments objectAtIndex:3] integerValue];
+ NSString* path = [command argumentAtIndex:0];
+ NSString* encoding = [command argumentAtIndex:1];
+ NSInteger start = [[command argumentAtIndex:2] integerValue];
+ NSInteger end = [[command argumentAtIndex:3] integerValue];
+
+ // TODO: implement
+ if (![@"UTF-8" isEqualToString:encoding]) {
+ NSLog(@"Only UTF-8 encodings are currently supported by readAsText");
+ CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:ENCODING_ERR];
+ [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+ return;
}
- // NSString* encoding = [command.arguments objectAtIndex:2]; // not currently used
- CDVPluginResult* result = nil;
-
- NSFileHandle* file = [NSFileHandle fileHandleForReadingAtPath:argPath];
-
- if ([argPath hasPrefix:kCDVAssetsLibraryPrefix]) {
- // can't read assets-library URLs as text
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_READABLE_ERR];
- } else if (!file) {
- // invalid path entry
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR];
- } else {
- if (start > 0) {
- [file seekToFileOffset:start];
- }
-
- NSData* readData;
- if (end < 0) {
- readData = [file readDataToEndOfFile];
- } else {
- readData = [file readDataOfLength:(end - start)];
- }
-
- [file closeFile];
- NSString* pNStrBuff = nil;
- if (readData) {
- pNStrBuff = [[NSString alloc] initWithBytes:[readData bytes] length:[readData length] encoding:NSUTF8StringEncoding];
- } else {
- // return empty string if no data
- pNStrBuff = @"";
- }
+ [self readFileWithPath:path start:start end:end callback:^(NSData * data, NSString * mimeType, CDVFileError errorCode) {
+ CDVPluginResult* result = nil;
+ if (data != nil) {
+ NSString* str = [[NSString alloc] initWithBytesNoCopy:(void*)[data bytes] length:[data length] encoding:NSUTF8StringEncoding freeWhenDone:NO];
+ // Check that UTF8 conversion did not fail.
+ if (str != nil) {
+ result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:str];
+ result.associatedObject = data;
+ } else {
+ errorCode = ENCODING_ERR;
+ }
+ }
+ if (result == nil) {
+ result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode];
+ }
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:pNStrBuff];
- }
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+ [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+ }];
}
/* Read content of text file and return as base64 encoded data url.
* IN:
* NSArray* arguments
* 0 - NSString* fullPath
- * 1 - NSString* start - OPTIONAL, only provided when not == 0.
- * 2 - NSString* end - OPTIONAL, only provided when not == length.
+ * 1 - NSString* start
+ * 2 - NSString* end
*
* Determines the mime type from the file extension, returns ENCODING_ERR if mimetype can not be determined.
*/
- (void)readAsDataURL:(CDVInvokedUrlCommand*)command
{
- // arguments
- NSString* argPath = [command.arguments objectAtIndex:0];
- NSInteger start = 0;
- NSInteger end = -1;
-
- if ([command.arguments count] >= 2) {
- start = [[command.arguments objectAtIndex:1] integerValue];
- }
- if ([command.arguments count] >= 3) {
- end = [[command.arguments objectAtIndex:2] integerValue];
- }
-
- CDVFileError errCode = ABORT_ERR;
- __block CDVPluginResult* result = nil;
-
- if (!argPath) {
- errCode = SYNTAX_ERR;
- } else if ([argPath hasPrefix:kCDVAssetsLibraryPrefix]) {
- // In this case, we need to use an asynchronous method to retrieve the file.
- // Because of this, we can't just assign to `result` and send it at the end of the method.
- // Instead, we return after calling the asynchronous method and send `result` in each of the blocks.
- ALAssetsLibraryAssetForURLResultBlock resultBlock = ^(ALAsset * asset) {
- if (asset) {
- // We have the asset! Get the data and send it off.
- ALAssetRepresentation* assetRepresentation = [asset defaultRepresentation];
- Byte* buffer = (Byte*)malloc ([assetRepresentation size]);
- NSUInteger bufferSize = [assetRepresentation getBytes:buffer fromOffset:0.0 length:[assetRepresentation size] error:nil];
- NSData* data = [NSData dataWithBytesNoCopy:buffer length:bufferSize freeWhenDone:YES];
- NSString* mimeType = [self getMimeTypeFromPath:[assetRepresentation filename]];
- NSString* dataString = [NSString stringWithFormat:@"data:%@;base64,%@", mimeType, [data base64EncodedString]];
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:dataString];
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
- } else {
- // We couldn't find the asset. Send the appropriate error.
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR];
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
- }
- };
- ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError * error) {
- // Retrieving the asset failed for some reason. Send the appropriate error.
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[error localizedDescription]];
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
- };
-
- ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init];
- [assetsLibrary assetForURL:[NSURL URLWithString:argPath] resultBlock:resultBlock failureBlock:failureBlock];
- return;
- } else {
- NSString* mimeType = [self getMimeTypeFromPath:argPath];
- if (!mimeType) {
- // can't return as data URL if can't figure out the mimeType
- errCode = ENCODING_ERR;
- } else {
- NSFileHandle* file = [NSFileHandle fileHandleForReadingAtPath:argPath];
- if (start > 0) {
- [file seekToFileOffset:start];
- }
-
- NSData* readData;
- if (end < 0) {
- readData = [file readDataToEndOfFile];
- } else {
- readData = [file readDataOfLength:(end - start)];
- }
-
- [file closeFile];
- if (readData) {
- NSString* output = [NSString stringWithFormat:@"data:%@;base64,%@", mimeType, [readData base64EncodedString]];
+ NSString* path = [command argumentAtIndex:0];
+ NSInteger start = [[command argumentAtIndex:1] integerValue];
+ NSInteger end = [[command argumentAtIndex:2] integerValue];
+
+ [self readFileWithPath:path start:start end:end callback:^(NSData * data, NSString * mimeType, CDVFileError errorCode) {
+ CDVPluginResult* result = nil;
+ if (data != nil) {
+ // TODO: Would be faster to base64 encode directly to the final string.
+ NSString* output = [NSString stringWithFormat:@"data:%@;base64,%@", mimeType, [data base64EncodedString]];
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:output];
} else {
- errCode = NOT_FOUND_ERR;
+ result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode];
}
- }
- }
- if (!result) {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:errCode];
- }
- // NSLog(@"readAsDataURL return: %@", jsString);
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+
+ [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+ }];
}
/* Read content of text file and return as an arraybuffer
* IN:
* NSArray* arguments
* 0 - NSString* fullPath
- * 1 - NSString* start - OPTIONAL, only provided when not == 0.
- * 2 - NSString* end - OPTIONAL, only provided when not == length.
+ * 1 - NSString* start
+ * 2 - NSString* end
*/
- (void)readAsArrayBuffer:(CDVInvokedUrlCommand*)command
{
- // arguments
- NSString* argPath = [command.arguments objectAtIndex:0];
- NSInteger start = 0;
- NSInteger end = -1;
-
- if ([command.arguments count] >= 2) {
- start = [[command.arguments objectAtIndex:1] integerValue];
- }
- if ([command.arguments count] >= 3) {
- end = [[command.arguments objectAtIndex:2] integerValue];
- }
+ NSString* path = [command argumentAtIndex:0];
+ NSInteger start = [[command argumentAtIndex:1] integerValue];
+ NSInteger end = [[command argumentAtIndex:2] integerValue];
- CDVFileError errCode = ABORT_ERR;
- __block CDVPluginResult* result = nil;
-
- if (!argPath) {
- errCode = SYNTAX_ERR;
- } else if ([argPath hasPrefix:kCDVAssetsLibraryPrefix]) {
- // In this case, we need to use an asynchronous method to retrieve the file.
- // Because of this, we can't just assign to `result` and send it at the end of the method.
- // Instead, we return after calling the asynchronous method and send `result` in each of the blocks.
- ALAssetsLibraryAssetForURLResultBlock resultBlock = ^(ALAsset * asset) {
- if (asset) {
- // We have the asset! Get the data and send it off.
- ALAssetRepresentation* assetRepresentation = [asset defaultRepresentation];
- Byte* buffer = (Byte*)malloc ([assetRepresentation size]);
- NSUInteger bufferSize = [assetRepresentation getBytes:buffer fromOffset:0.0 length:[assetRepresentation size] error:nil];
- NSData* data = [NSData dataWithBytesNoCopy:buffer length:bufferSize freeWhenDone:YES];
+ [self readFileWithPath:path start:start end:end callback:^(NSData * data, NSString * mimeType, CDVFileError errorCode) {
+ CDVPluginResult* result = nil;
+ if (data != nil) {
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArrayBuffer:data];
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
} else {
- // We couldn't find the asset. Send the appropriate error.
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR];
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+ result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode];
}
- };
- ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError * error) {
- // Retrieving the asset failed for some reason. Send the appropriate error.
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[error localizedDescription]];
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
- };
-
- ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init];
- [assetsLibrary assetForURL:[NSURL URLWithString:argPath] resultBlock:resultBlock failureBlock:failureBlock];
- return;
- } else {
- NSFileHandle* file = [NSFileHandle fileHandleForReadingAtPath:argPath];
- if (start > 0) {
- [file seekToFileOffset:start];
- }
-
- NSData* readData;
- if (end < 0) {
- readData = [file readDataToEndOfFile];
- } else {
- readData = [file readDataOfLength:(end - start)];
- }
-
- [file closeFile];
- if (readData) {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArrayBuffer:readData];
- } else {
- errCode = NOT_FOUND_ERR;
- }
- }
- if (!result) {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:errCode];
- }
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+ [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+ }];
}
/* helper function to get the mimeType from the file extension
http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/f9ba26e3/CordovaLib/Classes/CDVPluginResult.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVPluginResult.m b/CordovaLib/Classes/CDVPluginResult.m
index ffc96a2..af7c528 100644
--- a/CordovaLib/Classes/CDVPluginResult.m
+++ b/CordovaLib/Classes/CDVPluginResult.m
@@ -35,10 +35,10 @@ static NSArray* org_apache_cordova_CommandStatusMsgs;
id messageFromArrayBuffer(NSData* data)
{
- return @ {
+ return @{
@"CDVType" : @"ArrayBuffer",
@"data" :[data base64EncodedString]
- }
+ };
}
id massageMessage(id message)
@@ -57,10 +57,10 @@ id messageFromMultipart(NSArray* theMessages)
[messages replaceObjectAtIndex:i withObject:massageMessage([messages objectAtIndex:i])];
}
- return @ {
+ return @{
@"CDVType" : @"MultiPart",
@"messages" : messages
- }
+ };
}
+ (void)initialize
@@ -141,7 +141,7 @@ id messageFromMultipart(NSArray* theMessages)
+ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageToErrorObject:(int)errorCode
{
- NSDictionary* errDict = @ {@"code" :[NSNumber numberWithInt:errorCode]}
+ NSDictionary* errDict = @{@"code" :[NSNumber numberWithInt:errorCode]};
return [[self alloc] initWithStatus:statusOrdinal message:errDict];
}