NSData+Base64.h
#import <Foundation/Foundation.h>
@interface NSData (Base64)
+ (NSData *)dataWithBase64EncodedString:(NSString *)string;
- (NSString *)base64EncodedStringWithWrapWidth:(NSUInteger)wrapWidth;
- (NSString *)base64EncodedString;
@end
NSData+Base64.m
#import "NSData+Base64.h"
@implementation NSData (Base64)
+ (NSData *)dataWithBase64EncodedString:(NSString *)string
{
const char lookup[] =
{
99, 99, 99, 99, 99,99, 99, 99, 99, 99,99, 99, 99, 99, 99,99,
99, 99, 99, 99, 99,99, 99, 99, 99, 99,99, 99, 99, 99, 99,99,
99, 99, 99, 99, 99,99, 99, 99, 99, 99,99, 62, 99, 99, 99,63,
52, 53, 54, 55, 56,57, 58, 59, 60, 61,99, 99, 99, 99, 99,99,
99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,14,
15, 16, 17, 18, 19,20, 21, 22, 23, 24,25, 99, 99, 99, 99,99,
99, 26, 27, 28, 29,30, 31, 32, 33, 34,35, 36, 37, 38, 39,40,
41, 42, 43, 44, 45,46, 47, 48, 49, 50,51, 99, 99, 99, 99,99
};
NSData *inputData = [stringdataUsingEncoding:NSASCIIStringEncodingallowLossyConversion:YES];
long long inputLength = [inputDatalength];
const unsignedchar *inputBytes = [inputData bytes];
long long maxOutputLength = (inputLength /4 + 1) * 3;
NSMutableData *outputData = [NSMutableDatadataWithLength:maxOutputLength];
unsigned char *outputBytes = (unsignedchar *)[outputData mutableBytes];
int accumulator = 0;
long long outputLength =0;
unsigned char accumulated[] = {0,0, 0, 0};
for (long long i = 0; i < inputLength; i++)
{
unsigned char decoded = lookup[inputBytes[i] &0x7F];
if (decoded != 99)
{
accumulated[accumulator] = decoded;
if (accumulator == 3)
{
outputBytes[outputLength++] = (accumulated[0] <<2) | (accumulated[1] >>4);
outputBytes[outputLength++] = (accumulated[1] <<4) | (accumulated[2] >>2);
outputBytes[outputLength++] = (accumulated[2] <<6) | accumulated[3];
}
accumulator = (accumulator +1) % 4;
}
}
//handle left-over data
if (accumulator > 0) outputBytes[outputLength] = (accumulated[0] <<2) | (accumulated[1] >>4);
if (accumulator > 1) outputBytes[++outputLength] = (accumulated[1] <<4) | (accumulated[2] >>2);
if (accumulator > 2) outputLength++;
//truncate data to match actual output length
outputData.length = outputLength;
return outputLength? outputData: nil;
}
- (NSString *)base64EncodedStringWithWrapWidth:(NSUInteger)wrapWidth
{
//ensure wrapWidth is a multiple of 4
wrapWidth = (wrapWidth /4) * 4;
constchar lookup[] ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
long long inputLength = [selflength];
const unsignedchar *inputBytes = [selfbytes];
long long maxOutputLength = (inputLength /3 + 1) * 4;
maxOutputLength += wrapWidth? (maxOutputLength / wrapWidth) *2: 0;
unsigned char *outputBytes = (unsignedchar *)malloc(maxOutputLength);
long long i;
long long outputLength =0;
for (i = 0; i < inputLength -2; i += 3)
{
outputBytes[outputLength++] = lookup[(inputBytes[i] &0xFC) >> 2];
outputBytes[outputLength++] = lookup[((inputBytes[i] &0x03) << 4) | ((inputBytes[i +1] & 0xF0) >>4)];
outputBytes[outputLength++] = lookup[((inputBytes[i +1] & 0x0F) <<2) | ((inputBytes[i + 2] & 0xC0) >> 6)];
outputBytes[outputLength++] = lookup[inputBytes[i +2] & 0x3F];
//add line break
if (wrapWidth && (outputLength + 2) % (wrapWidth + 2) == 0)
{
outputBytes[outputLength++] ='\r';
outputBytes[outputLength++] ='\n';
}
}
//handle left-over data
if (i == inputLength - 2)
{
// = terminator
outputBytes[outputLength++] = lookup[(inputBytes[i] &0xFC) >> 2];
outputBytes[outputLength++] = lookup[((inputBytes[i] &0x03) << 4) | ((inputBytes[i +1] & 0xF0) >>4)];
outputBytes[outputLength++] = lookup[(inputBytes[i +1] & 0x0F) <<2];
outputBytes[outputLength++] = '=';
}
else if (i == inputLength -1)
{
// == terminator
outputBytes[outputLength++] = lookup[(inputBytes[i] &0xFC) >> 2];
outputBytes[outputLength++] = lookup[(inputBytes[i] &0x03) << 4];
outputBytes[outputLength++] ='=';
outputBytes[outputLength++] ='=';
}
//truncate data to match actual output length
outputBytes =realloc(outputBytes, outputLength);
NSString *result = [[NSStringalloc] initWithBytesNoCopy:outputByteslength:outputLength encoding:NSASCIIStringEncodingfreeWhenDone:YES];
#if !__has_feature(objc_arc)
[resultautorelease];
#endif
return (outputLength >= 4)? result: nil;
}
- (NSString *)base64EncodedString
{
return [selfbase64EncodedStringWithWrapWidth:0];
}
@end
NSString+Base64.h
#import <Foundation/Foundation.h>
@interface NSString (Base64)
+ (NSString *)stringWithBase64EncodedString:(NSString *)string;
- (NSString *)base64EncodedStringWithWrapWidth:(NSUInteger)wrapWidth;
- (NSString *)base64EncodedString;
- (NSString *)base64DecodedString;
- (NSData *)base64DecodedData;
@end
NSstring+Base64.m
#import "NSString+Base64.h"
#import "NSData+Base64.h"
@implementation NSString (Base64)
+ (NSString *)stringWithBase64EncodedString:(NSString *)string
{
NSData *data = [NSDatadataWithBase64EncodedString:string];
if (data)
{
NSString *result = [[selfalloc] initWithData:dataencoding:NSUTF8StringEncoding];
#if !__has_feature(objc_arc)
[resultautorelease];
#endif
return result;
}
return nil;
}
- (NSString *)base64EncodedStringWithWrapWidth:(NSUInteger)wrapWidth
{
NSData *data = [selfdataUsingEncoding:NSUTF8StringEncodingallowLossyConversion:YES];
return [database64EncodedStringWithWrapWidth:wrapWidth];
}
- (NSString *)base64EncodedString
{
NSData *data = [selfdataUsingEncoding:NSUTF8StringEncodingallowLossyConversion:YES];
return [database64EncodedString];
}
- (NSString *)base64DecodedString
{
return [NSStringstringWithBase64EncodedString:self];
}
- (NSData *)base64DecodedData
{
return [NSDatadataWithBase64EncodedString:self];
}
@end