Categories

base64 encoder/decoder for objective-c 编码及解码

base64是广为使用的一种编码及解码方式, 通常用于网络传输和邮件传输中,使用base64可以将标点符号以及多字节文字等特殊字符编码以便传输,以下是base64 编码解码的objective-c代码, 可以用于desktop和iphone程序当中

头文件

?Download base64.h
1
2
3
4
5
6
7
#include <UIKit/UIKit.h>
 
extern size_t EstimateBas64EncodedDataSize(size_t inDataSize);
extern size_t EstimateBas64DecodedDataSize(size_t inDataSize);
 
extern bool Base64EncodeData(const void *inInputData, size_t inInputDataSize, char *outOutputData, size_t *ioOutputDataSize, BOOL wrapped);
extern bool Base64DecodeData(const void *inInputData, size_t inInputDataSize, void *ioOutputData, size_t *ioOutputDataSize);

实现文件

?Download base64.m
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
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#include "Base64Transcoder.h"
 
#include <math.h>
 
const UInt8 kBase64EncodeTable[64] = {
	/*  0 */ 'A',	/*  1 */ 'B',	/*  2 */ 'C',	/*  3 */ 'D', 
	/*  4 */ 'E',	/*  5 */ 'F',	/*  6 */ 'G',	/*  7 */ 'H', 
	/*  8 */ 'I',	/*  9 */ 'J',	/* 10 */ 'K',	/* 11 */ 'L', 
	/* 12 */ 'M',	/* 13 */ 'N',	/* 14 */ 'O',	/* 15 */ 'P', 
	/* 16 */ 'Q',	/* 17 */ 'R',	/* 18 */ 'S',	/* 19 */ 'T', 
	/* 20 */ 'U',	/* 21 */ 'V',	/* 22 */ 'W',	/* 23 */ 'X', 
	/* 24 */ 'Y',	/* 25 */ 'Z',	/* 26 */ 'a',	/* 27 */ 'b', 
	/* 28 */ 'c',	/* 29 */ 'd',	/* 30 */ 'e',	/* 31 */ 'f', 
	/* 32 */ 'g',	/* 33 */ 'h',	/* 34 */ 'i',	/* 35 */ 'j', 
	/* 36 */ 'k',	/* 37 */ 'l',	/* 38 */ 'm',	/* 39 */ 'n', 
	/* 40 */ 'o',	/* 41 */ 'p',	/* 42 */ 'q',	/* 43 */ 'r', 
	/* 44 */ 's',	/* 45 */ 't',	/* 46 */ 'u',	/* 47 */ 'v', 
	/* 48 */ 'w',	/* 49 */ 'x',	/* 50 */ 'y',	/* 51 */ 'z', 
	/* 52 */ '0',	/* 53 */ '1',	/* 54 */ '2',	/* 55 */ '3', 
	/* 56 */ '4',	/* 57 */ '5',	/* 58 */ '6',	/* 59 */ '7', 
	/* 60 */ '8',	/* 61 */ '9',	/* 62 */ '+',	/* 63 */ '/'
};
 
/*
-1 = Base64 end of data marker.
-2 = White space (tabs, cr, lf, space)
-3 = Noise (all non whitespace, non-base64 characters) 
-4 = Dangerous noise
-5 = Illegal noise (null byte)
*/
 
const SInt8 kBase64DecodeTable[128] = {
	/* 0x00 */ -5, 	/* 0x01 */ -3, 	/* 0x02 */ -3, 	/* 0x03 */ -3,
	/* 0x04 */ -3, 	/* 0x05 */ -3, 	/* 0x06 */ -3, 	/* 0x07 */ -3,
	/* 0x08 */ -3, 	/* 0x09 */ -2, 	/* 0x0a */ -2, 	/* 0x0b */ -2,
	/* 0x0c */ -2, 	/* 0x0d */ -2, 	/* 0x0e */ -3, 	/* 0x0f */ -3,
	/* 0x10 */ -3, 	/* 0x11 */ -3, 	/* 0x12 */ -3, 	/* 0x13 */ -3,
	/* 0x14 */ -3, 	/* 0x15 */ -3, 	/* 0x16 */ -3, 	/* 0x17 */ -3,
	/* 0x18 */ -3, 	/* 0x19 */ -3, 	/* 0x1a */ -3, 	/* 0x1b */ -3,
	/* 0x1c */ -3, 	/* 0x1d */ -3, 	/* 0x1e */ -3, 	/* 0x1f */ -3,
	/* ' ' */ -2,	/* '!' */ -3,	/* '"' */ -3,	/* '#' */ -3,
	/* '$' */ -3,	/* '%' */ -3,	/* '&' */ -3,	/* ''' */ -3,
	/* '(' */ -3,	/* ')' */ -3,	/* '*' */ -3,	/* '+' */ 62,
	/* ',' */ -3,	/* '-' */ -3,	/* '.' */ -3,	/* '/' */ 63,
	/* '0' */ 52,	/* '1' */ 53,	/* '2' */ 54,	/* '3' */ 55,
	/* '4' */ 56,	/* '5' */ 57,	/* '6' */ 58,	/* '7' */ 59,
	/* '8' */ 60,	/* '9' */ 61,	/* ':' */ -3,	/* ';' */ -3,
	/* '<' */ -3,	/* '=' */ -1,	/* '>' */ -3,	/* '?' */ -3,
	/* '@' */ -3,	/* 'A' */ 0,	/* 'B' */  1,	/* 'C' */  2,
	/* 'D' */  3,	/* 'E' */  4,	/* 'F' */  5,	/* 'G' */  6,
	/* 'H' */  7,	/* 'I' */  8,	/* 'J' */  9,	/* 'K' */ 10,
	/* 'L' */ 11,	/* 'M' */ 12,	/* 'N' */ 13,	/* 'O' */ 14,
	/* 'P' */ 15,	/* 'Q' */ 16,	/* 'R' */ 17,	/* 'S' */ 18,
	/* 'T' */ 19,	/* 'U' */ 20,	/* 'V' */ 21,	/* 'W' */ 22,
	/* 'X' */ 23,	/* 'Y' */ 24,	/* 'Z' */ 25,	/* '[' */ -3,
	/* '\' */ -3,	/* ']' */ -3,	/* '^' */ -3,	/* '_' */ -3,
	/* '`' */ -3,	/* 'a' */ 26,	/* 'b' */ 27,	/* 'c' */ 28,
	/* 'd' */ 29,	/* 'e' */ 30,	/* 'f' */ 31,	/* 'g' */ 32,
	/* 'h' */ 33,	/* 'i' */ 34,	/* 'j' */ 35,	/* 'k' */ 36,
	/* 'l' */ 37,	/* 'm' */ 38,	/* 'n' */ 39,	/* 'o' */ 40,
	/* 'p' */ 41,	/* 'q' */ 42,	/* 'r' */ 43,	/* 's' */ 44,
	/* 't' */ 45,	/* 'u' */ 46,	/* 'v' */ 47,	/* 'w' */ 48,
	/* 'x' */ 49,	/* 'y' */ 50,	/* 'z' */ 51,	/* '{' */ -3,
	/* '|' */ -3,	/* '}' */ -3,	/* '~' */ -3,	/* 0x7f */ -3
};
 
const UInt8 kBits_00000011 = 0x03;
const UInt8 kBits_00001111 = 0x0F;
const UInt8 kBits_00110000 = 0x30;
const UInt8 kBits_00111100 = 0x3C;
const UInt8 kBits_00111111 = 0x3F;
const UInt8 kBits_11000000 = 0xC0;
const UInt8 kBits_11110000 = 0xF0;
const UInt8 kBits_11111100 = 0xFC;
 
size_t EstimateBas64EncodedDataSize(size_t inDataSize)
{
size_t theEncodedDataSize = (int)ceil(inDataSize / 3.0) * 4;
theEncodedDataSize = theEncodedDataSize / 72 * 74 + theEncodedDataSize % 72;
return(theEncodedDataSize);
}
 
size_t EstimateBas64DecodedDataSize(size_t inDataSize)
{
size_t theDecodedDataSize = (int)ceil(inDataSize / 4.0) * 3;
//theDecodedDataSize = theDecodedDataSize / 72 * 74 + theDecodedDataSize % 72;
return(theDecodedDataSize);
}
 
bool Base64EncodeData(const void *inInputData, size_t inInputDataSize, char *outOutputData, size_t *ioOutputDataSize, BOOL wrapped)
{
size_t theEncodedDataSize = EstimateBas64EncodedDataSize(inInputDataSize);
if (*ioOutputDataSize < theEncodedDataSize)
	return(false);
*ioOutputDataSize = theEncodedDataSize;
const UInt8 *theInPtr = (const UInt8 *)inInputData;
UInt32 theInIndex = 0, theOutIndex = 0;
for (; theInIndex < (inInputDataSize / 3) * 3; theInIndex += 3)
	{
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_11111100) >> 2];
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_00000011) << 4 | (theInPtr[theInIndex + 1] & kBits_11110000) >> 4];
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex + 1] & kBits_00001111) << 2 | (theInPtr[theInIndex + 2] & kBits_11000000) >> 6];
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex + 2] & kBits_00111111) >> 0];
	if (wrapped && (theOutIndex % 74 == 72))
		{
		outOutputData[theOutIndex++] = '\r';
		outOutputData[theOutIndex++] = '\n';
		}
	}
const size_t theRemainingBytes = inInputDataSize - theInIndex;
if (theRemainingBytes == 1)
	{
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_11111100) >> 2];
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_00000011) << 4 | (0 & kBits_11110000) >> 4];
	outOutputData[theOutIndex++] = '=';
	outOutputData[theOutIndex++] = '=';
	if (wrapped && (theOutIndex % 74 == 72))
		{
		outOutputData[theOutIndex++] = '\r';
		outOutputData[theOutIndex++] = '\n';
		}
	}
else if (theRemainingBytes == 2)
	{
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_11111100) >> 2];
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_00000011) << 4 | (theInPtr[theInIndex + 1] & kBits_11110000) >> 4];
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex + 1] & kBits_00001111) << 2 | (0 & kBits_11000000) >> 6];
	outOutputData[theOutIndex++] = '=';
	if (wrapped && (theOutIndex % 74 == 72))
		{
		outOutputData[theOutIndex++] = '\r';
		outOutputData[theOutIndex++] = '\n';
		}
	}
return(true);
}
 
bool Base64DecodeData(const void *inInputData, size_t inInputDataSize, void *ioOutputData, size_t *ioOutputDataSize)
{
memset(ioOutputData, '.', *ioOutputDataSize);
 
size_t theDecodedDataSize = EstimateBas64DecodedDataSize(inInputDataSize);
if (*ioOutputDataSize < theDecodedDataSize)
	return(false);
*ioOutputDataSize = 0;
const UInt8 *theInPtr = (const UInt8 *)inInputData;
UInt8 *theOutPtr = (UInt8 *)ioOutputData;
size_t theInIndex = 0, theOutIndex = 0;
UInt8 theOutputOctet;
size_t theSequence = 0;
for (; theInIndex < inInputDataSize; )
	{
	SInt8 theSextet = 0;
 
	SInt8 theCurrentInputOctet = theInPtr[theInIndex];
	theSextet = kBase64DecodeTable[theCurrentInputOctet];
	if (theSextet == -1)
		break;
	while (theSextet == -2)
		{
		theCurrentInputOctet = theInPtr[++theInIndex];
		theSextet = kBase64DecodeTable[theCurrentInputOctet];
		}
	while (theSextet == -3)
		{
		theCurrentInputOctet = theInPtr[++theInIndex];
		theSextet = kBase64DecodeTable[theCurrentInputOctet];
		}
	if (theSequence == 0)
		{
		theOutputOctet = (theSextet >= 0 ? theSextet : 0) << 2 & kBits_11111100;
		}
	else if (theSequence == 1)
		{
		theOutputOctet |= (theSextet >- 0 ? theSextet : 0) >> 4 & kBits_00000011;
		theOutPtr[theOutIndex++] = theOutputOctet;
		}
	else if (theSequence == 2)
		{
		theOutputOctet = (theSextet >= 0 ? theSextet : 0) << 4 & kBits_11110000;
		}
	else if (theSequence == 3)
		{
		theOutputOctet |= (theSextet >= 0 ? theSextet : 0) >> 2 & kBits_00001111;
		theOutPtr[theOutIndex++] = theOutputOctet;
		}
	else if (theSequence == 4)
		{
		theOutputOctet = (theSextet >= 0 ? theSextet : 0) << 6 & kBits_11000000;
		}
	else if (theSequence == 5)
		{
		theOutputOctet |= (theSextet >= 0 ? theSextet : 0) >> 0 & kBits_00111111;
		theOutPtr[theOutIndex++] = theOutputOctet;
		}
	theSequence = (theSequence + 1) % 6;
	if (theSequence != 2 && theSequence != 4)
		theInIndex++;
	}
*ioOutputDataSize = theOutIndex;
return(true);
}
原创文章如转载,请注明
转载自:FLYBLOG [http://www.flyblog.info]

本文链接地址:http://www.flyblog.info/catprogramming/376.html

3 Responses to “base64 encoder/decoder for objective-c 编码及解码”

  • yile lv says:

    乖乖! 這裡簡直就是寶庫啊!!!!

    活活活活~~~

    阿彌陀佛~~

  • flyblog says:

    记录下来,自己再用的时候方便

  • yile says:

    小僧:
    前輩!
    您得這個Base64 怎麼用?

    fly:
    EstimateBas64EncodedDataSize/EstimateBas64DecodedDataSize 计算一下所需要buffer得大小,
    然后调用Base64EncodeData / Base64DecodeData 编码或者解码数据就可以了

Leave a Reply