Re: Decoding FxPlug custom params from FCP-XML
site_archiver@lists.apple.com Delivered-To: Pro-apps-dev@lists.apple.com Thanks! This helps tremendously! bob. On Apr 27, 2010, at 3:26 PM, Steve Christensen wrote:
Since I noticed my name mentioned at the beginning of the thread, I figured I'd jump in. I only do the encoding side in my case, but did find that I have to run the parameter value through an archiver twice before UUEncoding, like this:
// archive the original object into a data blob NSMutableData* archivedValue = [NSMutableData data]; NSMutableData* archivedData = [NSMutableData data]; NSKeyedArchiver* archiver;
archiver = [[[NSKeyedArchiver alloc] initForWritingWithMutableData:archivedValue] autorelease]; [archiver encodeObject:parameterValue]; [archiver finishEncoding];
// then archive the data blob archiver = [[[NSKeyedArchiver alloc] initForWritingWithMutableData:archivedData] autorelease]; [archiver encodeObject:archivedValue]; [archiver finishEncoding];
return UUEncode(archivedData, false);
I have also appended the UUEncode/UUDecode functions I'm using. At this point I don't remember the origins of any original sources, but I had used them to create a version to my liking. I added an extra parameter to turn on/off the standard feature of adding a line break, since it is not included when encoding for FCP.
steve
On Apr 27, 2010, at 10:11 AM, Robert Monaghan wrote:
Hi Eryk!
I am about to implement some of this kind of code too. Is there a boiler-plate code sample for the uuencode/decode that Apple can point to?
Thanks
Bob
Sent from my iPhone
On Apr 27, 2010, at 9:43, Kristian Harms <kha@vizrt.com> wrote:
Thank you Eryk.
It was indeed a length-related issue. The NSKeyedUnarchiver's init no longer throws.
Regarding the uuencoding, am I right in guessing you have rolled your own implementation? The reason is that it doesn't seem to have been encoded using any of the uuencoding implementations I have found, which insert a newline at regular intervals in the encoded data. It would be nice if you could document any peculiarities of your uuencode.
Best regards, Kristian Harms
Den 2010-04-26 11:02 PM, skrev Eryk Vershen:
Kristian,
From the link you gave it is clear you had Paul's response; that should be the right thing to do. I agree the uudecode shouldn't have a problem. The string of bytes that NSKeyedUnarchiver mentions in the error is the string 'bplist00' (i.e. the start of a binary plist). I believe keyed archives are stored using plists these days, so that seems right.
Perhaps you've messed up the length of the data?
It's probably complaining because it's having a failure reading the plist (qua plist).
-eryk
On Apr 26, 2010, at 12:15 PM, Kristian Harms wrote:
Hi,
I'm doing something similar to what Steve Christensen asked about in this email to the list, a year ago:
http://lists.apple.com/archives/Pro-apps-dev/2009/Feb/msg00036.html
In brief, I want to grab from the FCP XML the parameter value for any custom parameters in my FxPlugs and deserialise them. However, when I come to the point where I instantiate the NSKeyedUnarchiver with my NSData, which I have uudecoded based on the string I acquire from the XML, I actually get an Objective-C exception, of type NSInvalidArgumentException, and with reason:
*** -[NSKeyedUnarchiver initForReadingWithData:]: incomprehensible archive (0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x30, 0x30)
This happens on the init call itself, and not on the [unarchiver decodeObject] call that the link above recommends doing next.
I'm stumped as to how to procede. There are no obvious things I've done that could compromise the data -- the only point where a character encoding is involved is when I extract the char* from the NSString holding the uuencoded data, but uuencoded data should be representable as 7-bit ascii anyway, so choosing utf8, latin1 or even ascii should work fine there. There are no character encodings involved after the point where I uudecode.
Version info: Running FCP 7.0.2 and plugin compiled using FxPlug SDK 1.2.5, on top of OS X 10.5.
//-------------------------------------------------------------------------------- NSInteger UUEncodeStringBufferSize(NSInteger dataLength, bool hasNewlines) { return (dataLength * 4 / 3) + (((dataLength + 44) / 45) * (1 + (hasNewlines ? 2 : 0))) + 1; }
//-------------------------------------------------------------------------------- NSInteger UUEncode(const uint8_t* dataBuffer, NSInteger dataLength, uint8_t* stringBuffer, bool hasNewlines) { #define EncodeByte_(ch) ((ch) != 0) ? (((ch) & 0x3f) + ' ') : '`'
NSInteger dataIndex = 0; NSInteger stringIndex = 0; NSInteger lineLength;
// break up the data into lines of up to 45 bytes... while ((lineLength = MIN(dataLength - dataIndex, 45)) > 0) { // encode the line length stringBuffer[stringIndex++] = EncodeByte_(lineLength);
// encode the data bytes for the current line for (; lineLength > 0; lineLength -= 3) { NSUInteger data0 = dataBuffer[dataIndex + 0], data1 = 0, data2 = 0;
// handle buffers that aren't an even multiple of 3 by avoiding reads off the end switch (lineLength) { default: data2 = dataBuffer[dataIndex + 2];
case 2: data1 = dataBuffer[dataIndex + 1];
case 1: break; }
stringBuffer[stringIndex + 0] = EncodeByte_((data0 >> 2)); stringBuffer[stringIndex + 1] = EncodeByte_((data0 << 4) | (data1 >> 4)); stringBuffer[stringIndex + 2] = EncodeByte_((data1 << 2) | (data2 >> 6)); stringBuffer[stringIndex + 3] = EncodeByte_((data2 & 0x3f));
dataIndex += 3; stringIndex += 4; }
// the uuencode spec puts "\r\n" at the end of each line but there might be cases where they're not included if (hasNewlines) { stringBuffer[stringIndex + 0] = '\r'; stringBuffer[stringIndex + 1] = '\n'; stringIndex += 2; } }
stringBuffer[stringIndex] = '\0';
return stringIndex; }
//-------------------------------------------------------------------------------- NSString* UUEncode(const NSData* data, bool hasNewlines) { if (data != nil) { NSInteger dataLength = [data length]; uint8_t stringBuffer[UUEncodeStringBufferSize(dataLength)];
UUEncode(static_cast<const uint8_t*>([data bytes]), dataLength, stringBuffer, hasNewlines);
return [NSString stringWithCString:reinterpret_cast<char*>(stringBuffer) encoding:NSASCIIStringEncoding]; }
return nil; }
//-------------------------------------------------------------------------------- NSInteger UUDecode(const uint8_t* stringBuffer, NSInteger stringLength, uint8_t* dataBuffer, bool hasNewlines) { #define DecodeByte_(ch) ((ch) - ' ') & 0x3f
NSInteger dataIndex = 0; NSInteger stringIndex = 0;
while (stringIndex < stringLength) { // decode the length of the current line NSInteger lineLength = DecodeByte_(stringBuffer[stringIndex++]);
// decode the data bytes for the current line for (; lineLength > 0; lineLength -= 3) { NSUInteger string0 = DecodeByte_(stringBuffer[stringIndex + 0]); NSUInteger string1 = DecodeByte_(stringBuffer[stringIndex + 1]); NSUInteger string2 = DecodeByte_(stringBuffer[stringIndex + 2]); NSUInteger string3 = DecodeByte_(stringBuffer[stringIndex + 3]);
dataBuffer[dataIndex++] = (string0 << 2) | (string1 >> 4); if (lineLength >= 2) { dataBuffer[dataIndex++] = (string1 << 4) | (string2 >> 2); if (lineLength >= 3) { dataBuffer[dataIndex++] = (string2 << 6) | (string3 >> 0); } }
stringIndex += 4; }
// the uuencode spec puts "\r\n" at the end of each line but there might be cases where they're not included if (hasNewlines) stringIndex += 2; }
return dataIndex; }
//-------------------------------------------------------------------------------- NSData* UUDecode(const NSString* string, bool hasNewlines) { if (string != nil) { NSInteger stringLength = [string length]; uint8_t stringBuffer[stringLength + 1];
if ([string getCString:(char*)stringBuffer maxLength:(stringLength + 1) encoding:NSASCIIStringEncoding]) { uint8_t dataBuffer[stringLength]; NSInteger dataLength = UUDecode(stringBuffer, stringLength, dataBuffer, hasNewlines);
return [NSData dataWithBytes:dataBuffer length:dataLength]; } }
return nil; }
_______________________________________________ Do not post admin requests to the list. They will be ignored. Pro-apps-dev mailing list (Pro-apps-dev@lists.apple.com) Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/pro-apps-dev/site_archiver%40lists.ap... This email sent to site_archiver@lists.apple.com
participants (1)
-
Robert Monaghan