Re: Base-64 decode (was Property List Editor)
Re: Base-64 decode (was Property List Editor)
- Subject: Re: Base-64 decode (was Property List Editor)
- From: Steven Spencer <email@hidden>
- Date: Mon, 13 Jun 2005 00:33:09 +0100
It's a little after the event, however the following code might still
be useful.
Data spanning to 76 bytes per line (MIME) is left as an exercise for
the reader.
- Steve Spencer
Class Header
------------
#import <Foundation/Foundation.h>
@interface NSData (Extensions)
+ (NSData *)dataWithBase64Data:(NSData *)base64Data;
- (NSData *)initWithBase64Data:(NSData *)base64Data;
- (NSData *)base64EncodedData;
@end
Class
-----
#import "dataExtensions.h"
@implementation NSData (Extensions)
const unsigned char Base64Pad = '=';
const unsigned char Base64Encode[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static unsigned char Base64Decode[255];
+ (void)initialize
{
//Build decode table
unsigned int index;
for (index = 0; index < 255; index++)
Base64Decode[index] = 0;
for (index = 0; index < 64; index++)
Base64Decode[Base64Encode[index]] = index;
}
+ (NSData *)dataWithBase64Data:(NSData *)base64Data
{
return [[[[self class] alloc] initWithBase64Data:base64Data]
autorelease];
}
- (NSData *)initWithBase64Data:(NSData *)base64Data
{
unsigned char *inputBuffer = (unsigned char *)[base64Data bytes],
*outputBuffer;
unsigned int inputLength = [base64Data length];
unsigned int outputRemainder = 3, index, inputQuads;
unsigned char q1, q2, q3, q4;
NSMutableData *outputData;
if (inputLength >= 4 && 0 == inputLength %4) {
inputQuads = inputLength / 4;
if (Base64Pad == inputBuffer[inputLength -1]) {
inputQuads--;
outputRemainder--;
}
if (Base64Pad == inputBuffer[inputLength -2])
outputRemainder--;
outputData = [NSMutableData dataWithLength:(inputQuads * 3) +
outputRemainder];
outputBuffer = [outputData mutableBytes];
for (index = 0; index < inputQuads; index++) {
q1 = Base64Decode[*inputBuffer++];
q2 = Base64Decode[*inputBuffer++];
q3 = Base64Decode[*inputBuffer++];
q4 = Base64Decode[*inputBuffer++];
*outputBuffer++ = q1 << 2 | (q2 & 0x30) >> 4;
*outputBuffer++ = (q2 & 0xF) << 4 | (q3 & 0x3C) >> 2;
*outputBuffer++ = (q3 & 0x3) << 6 | (q4 & 0x3F);
}
if (2 == outputRemainder) {
q1 = Base64Decode[*inputBuffer++];
q2 = Base64Decode[*inputBuffer++];
q3 = Base64Decode[*inputBuffer++];
*outputBuffer++ = q1 << 2 | (q2 & 0x30) >> 4;
*outputBuffer++ = (q2 & 0xF) << 4 | (q3 & 0x3C) >> 2;
} else if (1 == outputRemainder) {
q1 = Base64Decode[*inputBuffer++];
q2 = Base64Decode[*inputBuffer++];
*outputBuffer++ = q1 << 2 | (q2 & 0x30) >> 4;
}
return [self initWithData:outputData];
}
return [self initWithData:[NSData data]];
}
- (NSData *)base64EncodedData;
{
unsigned int inputTriplets = [self length] / 3;
unsigned int inputRemainder = [self length] % 3;
unsigned int outputLength = inputTriplets * 4;
unsigned int index;
unsigned char *outputBuffer, *inputBuffer;
unsigned char t1, t2, t3;
NSMutableData *outputData;
if (0 != inputRemainder) outputLength += 4;
outputData = [NSMutableData dataWithLength:outputLength];
outputBuffer = [outputData mutableBytes];
inputBuffer = (unsigned char *)[self bytes];
for (index = 0; index < inputTriplets; index++) {
t1 = *inputBuffer++;
t2 = *inputBuffer++;
t3 = *inputBuffer++;
*outputBuffer++ = Base64Encode[t1 >> 2];
*outputBuffer++ = Base64Encode[(t1 & 0x3) << 4 | t2 >> 4];
*outputBuffer++ = Base64Encode[(t2 & 0xF) << 2 | t3 >> 6];
*outputBuffer++ = Base64Encode[t3 & 0x3F];
}
if (2 == inputRemainder) {
t1 = *inputBuffer++;
t2 = *inputBuffer++;
*outputBuffer++ = Base64Encode[t1 >> 2];
*outputBuffer++ = Base64Encode[(t1 & 0x3) << 4 | t2 >> 4];
*outputBuffer++ = Base64Encode[(t2 & 0xF) << 2];
*outputBuffer++ = Base64Pad;
} else if (1 == inputRemainder) {
t1 = *inputBuffer++;
*outputBuffer++ = Base64Encode[t1 >> 2];
*outputBuffer++ = Base64Encode[(t1 & 0x3) << 4];
*outputBuffer++ = Base64Pad;
*outputBuffer++ = Base64Pad;
}
return [outputData copy];
}
@end
Test Programme
--------------
#import <Foundation/Foundation.h>
#import "dataExtensions.h"
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
//Source
NSString *src = @"The quick brown fox jumps over the lazy dog.";
NSLog(@"%@", src);
NSData *srcData = [src dataUsingEncoding:NSASCIIStringEncoding];
//Encode
NSData *base64Data = [srcData base64EncodedData];
NSString *tgt = [[[NSString alloc] initWithData:base64Data
encoding:NSASCIIStringEncoding] autorelease];
NSLog(@"%@", tgt);
//Decode
NSData *decoded = [NSData dataWithBase64Data:base64Data];
NSString *rev = [[[NSString alloc] initWithData:decoded
encoding:NSASCIIStringEncoding] autorelease];
NSLog(@"%@", rev);
[pool release];
return 0;
}
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden