ObjFW  Check-in [43cadc9699]

Overview
Comment:Add support for Base64 decoding.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 43cadc969980ab232e88c0e8e749aab30c86dd823f989de3fef13b3d3d3a2dc1
User & Date: js on 2011-02-05 16:48:46
Other Links: manifest | tags
Context
2011-02-05
17:27
Add tests for Base64. check-in: 7ecfb859b9 user: js tags: trunk
16:48
Add support for Base64 decoding. check-in: 43cadc9699 user: js tags: trunk
15:15
Add support for Base64 encoding. check-in: 7459fabb87 user: js tags: trunk
Changes

Modified src/OFDataArray.h from [5fefeb5d65] to [77e68189e1].

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
 * specified file.
 *
 * \param path The path of the file
 * \return A new autoreleased OFDataArray
 */
+ dataArrayWithContentsOfFile: (OFString*)path;










/**
 * Initializes an already allocated OFDataArray whose items all have the same
 * size.
 *
 * \param is The size of each element in the OFDataArray
 * \return An initialized OFDataArray
 */
- initWithItemSize: (size_t)is;

/**
 * Initializes an already allocated OFDataArray with an item size of 1,
 * containing the data of the specified file.
 *
 * \param path The path of the file
 * \return An initialized OFDataArray
 */
- initWithContentsOfFile: (OFString*)path;










/**
 * \return The number of items in the OFDataArray
 */
- (size_t)count;

/**
 * \return The size of each item in the OFDataArray in bytes







>
>
>
>
>
>
>
>
>


















>
>
>
>
>
>
>
>
>







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
 * specified file.
 *
 * \param path The path of the file
 * \return A new autoreleased OFDataArray
 */
+ dataArrayWithContentsOfFile: (OFString*)path;

/**
 * Creates a new OFDataArray with an item size of 1, containing the data of the
 * Base64-encoded string.
 *
 * \param str The string with the Base64-encoded data
 * \return A new autoreleased OFDataArray
 */
+ dataArrayWithBase64EncodedString: (OFString*)str;

/**
 * Initializes an already allocated OFDataArray whose items all have the same
 * size.
 *
 * \param is The size of each element in the OFDataArray
 * \return An initialized OFDataArray
 */
- initWithItemSize: (size_t)is;

/**
 * Initializes an already allocated OFDataArray with an item size of 1,
 * containing the data of the specified file.
 *
 * \param path The path of the file
 * \return An initialized OFDataArray
 */
- initWithContentsOfFile: (OFString*)path;

/**
 * Initializes an already allocated OFDataArray with an item size of 1,
 * containing the data of the Base64-encoded string.
 *
 * \param str The string with the Base64-encoded data
 * \return A initialized OFDataArray
 */
- initWithBase64EncodedString: (OFString*)str;

/**
 * \return The number of items in the OFDataArray
 */
- (size_t)count;

/**
 * \return The size of each item in the OFDataArray in bytes

Modified src/OFDataArray.m from [cb8976524d] to [9cc6f38d56].

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
	return [[[self alloc] initWithItemSize: is] autorelease];
}

+ dataArrayWithContentsOfFile: (OFString*)path
{
	return [[[self alloc] initWithContentsOfFile: path] autorelease];
}






- init
{
	Class c = isa;
	[self release];
	@throw [OFNotImplementedException newWithClass: c
					      selector: _cmd];
}

- initWithItemSize: (size_t)is
{
	self = [super init];

	@try {
		if (is == 0)
			@throw [OFInvalidArgumentException newWithClass: isa
							       selector: _cmd];

		data = NULL;
		itemSize = is;

	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- initWithContentsOfFile: (OFString*)path
{
	self = [super init];

	@try {
		OFFile *file = [[OFFile alloc] initWithPath: path
						       mode: @"rb"];

		itemSize = 1;


		@try {
			char *buf = [self allocMemoryWithSize: of_pagesize];

			while (![file isAtEndOfStream]) {
				size_t size;








>
>
>
>
>


















<

>















>

>







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
	return [[[self alloc] initWithItemSize: is] autorelease];
}

+ dataArrayWithContentsOfFile: (OFString*)path
{
	return [[[self alloc] initWithContentsOfFile: path] autorelease];
}

+ dataArrayWithBase64EncodedString: (OFString*)str
{
	return [[[self alloc] initWithBase64EncodedString: str] autorelease];
}

- init
{
	Class c = isa;
	[self release];
	@throw [OFNotImplementedException newWithClass: c
					      selector: _cmd];
}

- initWithItemSize: (size_t)is
{
	self = [super init];

	@try {
		if (is == 0)
			@throw [OFInvalidArgumentException newWithClass: isa
							       selector: _cmd];


		itemSize = is;
		data = NULL;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- initWithContentsOfFile: (OFString*)path
{
	self = [super init];

	@try {
		OFFile *file = [[OFFile alloc] initWithPath: path
						       mode: @"rb"];

		itemSize = 1;
		data = NULL;

		@try {
			char *buf = [self allocMemoryWithSize: of_pagesize];

			while (![file isAtEndOfStream]) {
				size_t size;

96
97
98
99
100
101
102
















103
104
105
106
107
108
109
		} @finally {
			[file release];
		}
	} @catch (id e) {
		[self release];
		@throw e;
	}

















	return self;
}

- (size_t)count
{
	return count;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
		} @finally {
			[file release];
		}
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- initWithBase64EncodedString: (OFString*)str
{
	self = [super init];

	itemSize = 1;
	data = NULL;

	if (!of_base64_decode(self, [str cString], [str cStringLength])) {
		Class c = isa;
		[self release];
		@throw [OFInvalidEncodingException newWithClass: c];
	}

	return self;
}

- (size_t)count
{
	return count;

Modified src/base64.h from [6b049639b8] to [a2c286eeff].

10
11
12
13
14
15
16

17





18
19

20
21
22
23
24
25

26
27
28
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */


#include <stddef.h>






@class OFString;


#ifdef __cplusplus
extern "C" {
#endif
extern const char of_base64_table[64];
extern OFString *of_base64_encode(const char *buf, size_t len);

#ifdef __cplusplus
}
#endif







>
|
>
>
>
>
>


>






>



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
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "objfw-defs.h"

#ifdef OF_OBJFW_RUNTIME
# import <objfw-rt.h>
#else
# import <objc/objc.h>
#endif

@class OFString;
@class OFDataArray;

#ifdef __cplusplus
extern "C" {
#endif
extern const char of_base64_table[64];
extern OFString *of_base64_encode(const char *buf, size_t len);
extern BOOL of_base64_decode(OFDataArray *data, const char *str, size_t len);
#ifdef __cplusplus
}
#endif

Modified src/base64.m from [9111828109] to [cd2f786421].

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



























































 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFString.h"

#import "base64.h"

const char of_base64_table[64] = {
	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
	'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b',
	'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
	'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
	'4', '5', '6', '7', '8', '9', '+', '/'
};












OFString*
of_base64_encode(const char *buf, size_t len)
{
	OFMutableString *ret = [OFMutableString string];
	size_t i, rest;

	char tb[4];
	uint32_t sb;

	rest = len % 3;

	for (i = 0; i < len - rest; i += 3) {
		sb = (buf[i] << 16) | (buf[i + 1] << 8) | buf[i + 2];

		tb[0] = of_base64_table[(sb & 0xFC0000) >> 18];
		tb[1] = of_base64_table[(sb & 0x03F000) >> 12];
		tb[2] = of_base64_table[(sb & 0x000FC0) >> 6];
		tb[3] = of_base64_table[(sb & 0x00003F)];

		[ret appendCStringWithoutUTF8Checking: tb
					       length: 4];
	}

	switch (rest) {
	case 1:;
		tb[0] = of_base64_table[buf[i] >> 2];
		tb[1] = of_base64_table[(buf[i] & 3) << 4];
		tb[2] = tb[3] = '=';

		[ret appendCStringWithoutUTF8Checking: tb
					       length: 4];

		break;
	case 2:;
		sb = (buf[i] << 16) | (buf[i + 1] << 8);

		tb[0] = of_base64_table[(sb & 0xFC0000) >> 18];
		tb[1] = of_base64_table[(sb & 0x03F000) >> 12];
		tb[2] = of_base64_table[(sb & 0x000FC0) >> 6];
		tb[3] = '=';

		[ret appendCStringWithoutUTF8Checking: tb
					       length: 4];

		break;
	}

	return ret;
}


































































>


|






>
>
>
>
>
>
>
>
>
>
>





|
>








|
|
|
|






|
|
|






|


|
|
|










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFString.h"
#import "OFDataArray.h"
#import "base64.h"

const char of_base64_encode_table[64] = {
	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
	'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b',
	'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
	'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
	'4', '5', '6', '7', '8', '9', '+', '/'
};

const signed char of_base64_decode_table[128] = {
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54,
	55, 56, 57, 58, 59, 60, 61, -1, -1, -1,  0, -1, -1, -1,  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, -1, -1, -1, -1, -1, -1, 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, -1, -1, -1, -1, -1
};

OFString*
of_base64_encode(const char *buf, size_t len)
{
	OFMutableString *ret = [OFMutableString string];
	size_t i;
	uint8_t rest;
	char tb[4];
	uint32_t sb;

	rest = len % 3;

	for (i = 0; i < len - rest; i += 3) {
		sb = (buf[i] << 16) | (buf[i + 1] << 8) | buf[i + 2];

		tb[0] = of_base64_encode_table[(sb & 0xFC0000) >> 18];
		tb[1] = of_base64_encode_table[(sb & 0x03F000) >> 12];
		tb[2] = of_base64_encode_table[(sb & 0x000FC0) >> 6];
		tb[3] = of_base64_encode_table[sb & 0x00003F];

		[ret appendCStringWithoutUTF8Checking: tb
					       length: 4];
	}

	switch (rest) {
	case 1:
		tb[0] = of_base64_encode_table[buf[i] >> 2];
		tb[1] = of_base64_encode_table[(buf[i] & 3) << 4];
		tb[2] = tb[3] = '=';

		[ret appendCStringWithoutUTF8Checking: tb
					       length: 4];

		break;
	case 2:
		sb = (buf[i] << 16) | (buf[i + 1] << 8);

		tb[0] = of_base64_encode_table[(sb & 0xFC0000) >> 18];
		tb[1] = of_base64_encode_table[(sb & 0x03F000) >> 12];
		tb[2] = of_base64_encode_table[(sb & 0x000FC0) >> 6];
		tb[3] = '=';

		[ret appendCStringWithoutUTF8Checking: tb
					       length: 4];

		break;
	}

	return ret;
}

BOOL
of_base64_decode(OFDataArray *data, const char *str, size_t len)
{
	uint8_t *buf = (uint8_t*)str;
	size_t i;

	if ((len & 3) != 0)
		return NO;

	for (i = 0; i < len; i += 4) {
		uint32_t sb = 0;
		uint8_t cnt = 3;
		char db[3];
		char tmp;

		if (buf[i] > 0x7F || buf[i + 1] > 0x7F ||
		    buf[i + 2] > 0x7F || buf[i + 3] > 0x7F)
			return NO;

		if (buf[i] == '=' || buf[i + 1] == '=' ||
		    (buf[i + 2] == '=' && buf[i + 3] != '='))
			return NO;

		if (buf[i + 2] == '=')
			cnt--;
		if (buf[i + 3] == '=')
			cnt--;

		if ((tmp = of_base64_decode_table[buf[i]]) == -1)
			return NO;

		sb |= tmp << 18;

		if ((tmp = of_base64_decode_table[buf[i + 1]]) == -1)
			return NO;

		sb |= tmp << 12;

		if ((tmp = of_base64_decode_table[buf[i + 2]]) == -1)
			return NO;

		sb |= tmp << 6;

		if ((tmp = of_base64_decode_table[buf[i + 3]]) == -1)
			return NO;

		sb |= tmp;

		db[0] = (sb & 0xFF0000) >> 16;
		db[1] = (sb & 0x00FF00) >> 8;
		db[2] = sb & 0x0000FF;

		[data addNItems: cnt
		     fromCArray: db];
	}

	return YES;
}