Created
December 21, 2013 02:05
-
-
Save Beyondcow/8064557 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "base64.h" | |
static const char _base64EncodingTable[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |
static const short _base64DecodingTable[256] = { | |
-2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -1, -2, -1, -1, -2, -2, | |
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, | |
-1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 62, -2, -2, -2, 63, | |
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -2, -2, -2, -2, -2, -2, | |
-2, 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, -2, -2, -2, -2, -2, | |
-2, 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, -2, -2, -2, -2, -2, | |
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, | |
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, | |
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, | |
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, | |
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, | |
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, | |
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, | |
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2 | |
}; | |
@implementation NSString (base64) | |
- (NSString *)encodeBase64; | |
{ | |
return [[self dataUsingEncoding:NSUTF8StringEncoding] encodeBase64]; | |
} | |
- (NSData *)decodeBase64ToData; | |
{ | |
const char * objPointer = [self cStringUsingEncoding:NSASCIIStringEncoding]; | |
if (objPointer == NULL) return nil; | |
size_t intLength = strlen(objPointer); | |
int intCurrent; | |
int i = 0, j = 0, k; | |
unsigned char * objResult = (unsigned char *)calloc(intLength, sizeof(unsigned char)); | |
// Run through the whole string, converting as we go | |
while ( ((intCurrent = *objPointer++) != '\0') && (intLength-- > 0) ) { | |
if (intCurrent == '=') { | |
if (*objPointer != '=' && ((i % 4) == 1)) {// || (intLength > 0)) { | |
// the padding character is invalid at this point -- so this entire string is invalid | |
free(objResult); | |
objResult=NULL; | |
return nil; | |
} | |
continue; | |
} | |
intCurrent = _base64DecodingTable[intCurrent]; | |
if (intCurrent == -1) { | |
// we're at a whitespace -- simply skip over | |
continue; | |
} else if (intCurrent == -2) { | |
// we're at an invalid character | |
free(objResult); | |
objResult=NULL; | |
return nil; | |
} | |
switch (i % 4) { | |
case 0: | |
objResult[j] = intCurrent << 2; | |
break; | |
case 1: | |
objResult[j++] |= intCurrent >> 4; | |
objResult[j] = (intCurrent & 0x0f) << 4; | |
break; | |
case 2: | |
objResult[j++] |= intCurrent >>2; | |
objResult[j] = (intCurrent & 0x03) << 6; | |
break; | |
case 3: | |
objResult[j++] |= intCurrent; | |
break; | |
} | |
i++; | |
} | |
// mop things up if we ended on a boundary | |
k = j; | |
if (intCurrent == '=') { | |
switch (i % 4) { | |
case 1: | |
// Invalid state | |
free(objResult); | |
objResult=NULL; | |
return nil; | |
case 2: | |
k++; | |
// flow through | |
case 3: | |
objResult[k] = 0; | |
} | |
} | |
#if __has_feature(objc_arc) | |
return [[NSData alloc] initWithBytesNoCopy:objResult length:j freeWhenDone:YES]; | |
#else | |
return [[[NSData alloc] initWithBytesNoCopy:objResult length:j freeWhenDone:YES] autorelease]; | |
#endif | |
} | |
- (NSString *)decodeBase64ToString; | |
{ | |
NSData *d=[self decodeBase64ToData]; | |
return [NSString stringWithUTF8String:[d bytes]]; | |
} | |
@end | |
@implementation NSData (base64) | |
- (NSString *)encodeBase64; | |
{ | |
const unsigned char * objRawData = [self bytes]; | |
char * objPointer; | |
char * strResult; | |
// Get the Raw Data length and ensure we actually have data | |
size_t intLength = [self length]; | |
if (intLength == 0) return nil; | |
// Setup the String-based Result placeholder and pointer within that placeholder | |
strResult = (char *)calloc(((intLength + 2) / 3) * 4, sizeof(char)); | |
objPointer = strResult; | |
// Iterate through everything | |
while (intLength > 2) { // keep going until we have less than 24 bits | |
*objPointer++ = _base64EncodingTable[objRawData[0] >> 2]; | |
*objPointer++ = _base64EncodingTable[((objRawData[0] & 0x03) << 4) + (objRawData[1] >> 4)]; | |
*objPointer++ = _base64EncodingTable[((objRawData[1] & 0x0f) << 2) + (objRawData[2] >> 6)]; | |
*objPointer++ = _base64EncodingTable[objRawData[2] & 0x3f]; | |
// we just handled 3 octets (24 bits) of data | |
objRawData += 3; | |
intLength -= 3; | |
} | |
// now deal with the tail end of things | |
if (intLength != 0) { | |
*objPointer++ = _base64EncodingTable[objRawData[0] >> 2]; | |
if (intLength > 1) { | |
*objPointer++ = _base64EncodingTable[((objRawData[0] & 0x03) << 4) + (objRawData[1] >> 4)]; | |
*objPointer++ = _base64EncodingTable[(objRawData[1] & 0x0f) << 2]; | |
*objPointer++ = '='; | |
} else { | |
*objPointer++ = _base64EncodingTable[(objRawData[0] & 0x03) << 4]; | |
*objPointer++ = '='; | |
*objPointer++ = '='; | |
} | |
} | |
NSString *strToReturn = [[NSString alloc] initWithBytesNoCopy:strResult length:objPointer - strResult encoding:NSASCIIStringEncoding freeWhenDone:YES]; | |
#if __has_feature(objc_arc) | |
return strToReturn; | |
#else | |
return [strToReturn autorelease]; | |
#endif | |
} | |
@end | |
const char *b64_encode(const unsigned char *bytes, int length) | |
{ | |
const unsigned char *objRawData = bytes; | |
char * objPointer; | |
char * strResult; | |
// Get the Raw Data length and ensure we actually have data | |
size_t intLength = length; | |
if (intLength == 0) return ""; | |
// Setup the String-based Result placeholder and pointer within that placeholder | |
strResult = (char *)calloc(((intLength + 2) / 3) * 4 + 1 , sizeof(char)); | |
objPointer = strResult; | |
memset(strResult, 0, (((intLength + 2) / 3) * 4 + 1) * sizeof(char) ); | |
// Iterate through everything | |
while (intLength > 2) { // keep going until we have less than 24 bits | |
*objPointer++ = _base64EncodingTable[objRawData[0] >> 2]; | |
*objPointer++ = _base64EncodingTable[((objRawData[0] & 0x03) << 4) + (objRawData[1] >> 4)]; | |
*objPointer++ = _base64EncodingTable[((objRawData[1] & 0x0f) << 2) + (objRawData[2] >> 6)]; | |
*objPointer++ = _base64EncodingTable[objRawData[2] & 0x3f]; | |
// we just handled 3 octets (24 bits) of data | |
objRawData += 3; | |
intLength -= 3; | |
} | |
// now deal with the tail end of things | |
if (intLength != 0) { | |
*objPointer++ = _base64EncodingTable[objRawData[0] >> 2]; | |
if (intLength > 1) { | |
*objPointer++ = _base64EncodingTable[((objRawData[0] & 0x03) << 4) + (objRawData[1] >> 4)]; | |
*objPointer++ = _base64EncodingTable[(objRawData[1] & 0x0f) << 2]; | |
*objPointer++ = '='; | |
} else { | |
*objPointer++ = _base64EncodingTable[(objRawData[0] & 0x03) << 4]; | |
*objPointer++ = '='; | |
*objPointer++ = '='; | |
} | |
} | |
//strResult[objPointer - strResult]=0; | |
return strResult; | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@interface NSString (base64) | |
- (NSString *)encodeBase64; | |
- (NSData *)decodeBase64ToData; | |
- (NSString *)decodeBase64ToString; | |
@end | |
@interface NSData (base64) | |
- (NSString *)encodeBase64; | |
@end | |
#ifdef __cplusplus | |
extern "C" { | |
#endif | |
const char *b64_encode(const unsigned char *bytes, int length); | |
#ifdef __cplusplus | |
} | |
#endif | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment