Expanded open file functionality to use available apps.
[pithos-ios] / Classes / Base64.m
1 //
2 //  Base64.m
3 //  OpenStack
4 //
5 //  Created by Mike Mayo on 8/17/10.
6 //  The OpenStack project is provided under the Apache 2.0 license.
7 //
8
9 #import "Base64.h"
10
11
12 #define ArrayLength(x) (sizeof(x)/sizeof(*(x)))
13
14 static char encodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
15 static char decodingTable[128];
16
17 @implementation Base64
18
19 + (void) initialize {
20     if (self == [Base64 class]) {
21         memset(decodingTable, 0, ArrayLength(decodingTable));
22         for (NSInteger i = 0; i < ArrayLength(encodingTable); i++) {
23             decodingTable[encodingTable[i]] = i;
24         }
25     }
26 }
27
28
29 + (NSString*) encode:(const uint8_t*) input length:(NSInteger) length {
30     NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
31     uint8_t* output = (uint8_t*)data.mutableBytes;
32     
33     for (NSInteger i = 0; i < length; i += 3) {
34         NSInteger value = 0;
35         for (NSInteger j = i; j < (i + 3); j++) {
36             value <<= 8;
37             
38             if (j < length) {
39                 value |= (0xFF & input[j]);
40             }
41         }
42         
43         NSInteger index = (i / 3) * 4;
44         output[index + 0] =                    encodingTable[(value >> 18) & 0x3F];
45         output[index + 1] =                    encodingTable[(value >> 12) & 0x3F];
46         output[index + 2] = (i + 1) < length ? encodingTable[(value >> 6)  & 0x3F] : '=';
47         output[index + 3] = (i + 2) < length ? encodingTable[(value >> 0)  & 0x3F] : '=';
48     }
49     
50     return [[[NSString alloc] initWithData:data
51                                   encoding:NSASCIIStringEncoding] autorelease];
52 }
53
54
55 + (NSString*) encode:(NSData*) rawBytes {
56     return [self encode:(const uint8_t*) rawBytes.bytes length:rawBytes.length];
57 }
58
59
60 + (NSData*) decode:(const char*) string length:(NSInteger) inputLength {
61     if ((string == NULL) || (inputLength % 4 != 0)) {
62         return nil;
63     }
64     
65     while (inputLength > 0 && string[inputLength - 1] == '=') {
66         inputLength--;
67     }
68     
69     NSInteger outputLength = inputLength * 3 / 4;
70     NSMutableData* data = [NSMutableData dataWithLength:outputLength];
71     uint8_t* output = data.mutableBytes;
72     
73     NSInteger inputPoint = 0;
74     NSInteger outputPoint = 0;
75     while (inputPoint < inputLength) {
76         char i0 = string[inputPoint++];
77         char i1 = string[inputPoint++];
78         char i2 = inputPoint < inputLength ? string[inputPoint++] : 'A'; /* 'A' will decode to \0 */
79         char i3 = inputPoint < inputLength ? string[inputPoint++] : 'A';
80         
81         output[outputPoint++] = (decodingTable[i0] << 2) | (decodingTable[i1] >> 4);
82         if (outputPoint < outputLength) {
83             output[outputPoint++] = ((decodingTable[i1] & 0xf) << 4) | (decodingTable[i2] >> 2);
84         }
85         if (outputPoint < outputLength) {
86             output[outputPoint++] = ((decodingTable[i2] & 0x3) << 6) | decodingTable[i3];
87         }
88     }
89     
90     return data;
91 }
92
93
94 + (NSData*) decode:(NSString*) string {
95     return [self decode:[string cStringUsingEncoding:NSASCIIStringEncoding] length:string.length];
96 }
97
98 @end