annotate base64.c @ 728:1fa3820b1a84 libavutil

ARM asm for AV_RN*() ARMv6 and later support unaligned loads and stores for single word/halfword but not double/multiple. GCC is ignorant of this and will always use bytewise accesses for unaligned data. Casting to an int32_t pointer is dangerous since a load/store double or multiple instruction might be used (this happens with some code in FFmpeg). Implementing the AV_[RW]* macros with inline asm using only supported instructions gives fast and safe unaligned accesses. ARM RVCT does the right thing with generic code. This gives an overall speedup of up to 10%.
author mru
date Sat, 18 Apr 2009 00:00:28 +0000
parents 3f3e69baaaf8
children 0795a743bda1
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
244
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
1 /*
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
2 * Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.com)
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
3 *
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
4 * This file is part of FFmpeg.
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
5 *
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
6 * FFmpeg is free software; you can redistribute it and/or
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
7 * modify it under the terms of the GNU Lesser General Public
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
8 * License as published by the Free Software Foundation; either
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
9 * version 2.1 of the License, or (at your option) any later version.
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
10 *
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
11 * FFmpeg is distributed in the hope that it will be useful,
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
14 * Lesser General Public License for more details.
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
15 *
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
16 * You should have received a copy of the GNU Lesser General Public
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
17 * License along with FFmpeg; if not, write to the Free Software
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
19 */
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
20
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
21 /**
642
70bdd5501662 Use full internal pathname in doxygen @file directives.
diego
parents: 636
diff changeset
22 * @file libavutil/base64.c
636
c04808220c83 spelling/grammar/consistency review part II
diego
parents: 616
diff changeset
23 * @brief Base64 encode/decode
244
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
24 * @author Ryan Martell <rdm4@martellventures.com> (with lots of Michael)
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
25 */
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
26
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
27 #include "common.h"
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
28 #include "base64.h"
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
29
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
30 /* ---------------- private code */
428
a092b8236682 Add a couple of missing consts.
diego
parents: 401
diff changeset
31 static const uint8_t map2[] =
244
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
32 {
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
33 0x3e, 0xff, 0xff, 0xff, 0x3f, 0x34, 0x35, 0x36,
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
34 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff,
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
35 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01,
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
36 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
37 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
38 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
39 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1a, 0x1b,
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
40 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
41 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
42 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
43 };
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
44
659
d3cd35bec3d0 Cosmetics: "* out" -> "*out" for consistency with the other
stefano
parents: 658
diff changeset
45 int av_base64_decode(uint8_t *out, const char *in, int out_size)
244
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
46 {
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
47 int i, v;
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
48 uint8_t *dst = out;
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
49
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
50 v = 0;
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
51 for (i = 0; in[i] && in[i] != '='; i++) {
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
52 unsigned int index= in[i]-43;
581
95c9067ebb73 uses FF_ARRAY_ELEMS() where appropriate
aurel
parents: 505
diff changeset
53 if (index>=FF_ARRAY_ELEMS(map2) || map2[index] == 0xff)
244
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
54 return -1;
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
55 v = (v << 6) + map2[index];
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
56 if (i & 3) {
656
eadb97de8dc0 Cosmetics: consistently prefer "size" over "len"/"length" for the
stefano
parents: 655
diff changeset
57 if (dst - out < out_size) {
244
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
58 *dst++ = v >> (6 - 2 * (i & 3));
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
59 }
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
60 }
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
61 }
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
62
505
29eecf0241bd Remove unnecessary parentheses from return calls.
diego
parents: 428
diff changeset
63 return dst - out;
244
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
64 }
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
65
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
66 /*****************************************************************************
636
c04808220c83 spelling/grammar/consistency review part II
diego
parents: 616
diff changeset
67 * b64_encode: Stolen from VLC's http.c.
c04808220c83 spelling/grammar/consistency review part II
diego
parents: 616
diff changeset
68 * Simplified by Michael.
c04808220c83 spelling/grammar/consistency review part II
diego
parents: 616
diff changeset
69 * Fixed edge cases and made it work from data (vs. strings) by Ryan.
244
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
70 *****************************************************************************/
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
71
658
cc7c1ea68a52 Cosmetics: rename the "size" parameter of av_base64_encode() to "in_size".
stefano
parents: 657
diff changeset
72 char *av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size)
244
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
73 {
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
74 static const char b64[] =
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
75 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
76 char *ret, *dst;
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
77 unsigned i_bits = 0;
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
78 int i_shift = 0;
658
cc7c1ea68a52 Cosmetics: rename the "size" parameter of av_base64_encode() to "in_size".
stefano
parents: 657
diff changeset
79 int bytes_remaining = in_size;
244
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
80
658
cc7c1ea68a52 Cosmetics: rename the "size" parameter of av_base64_encode() to "in_size".
stefano
parents: 657
diff changeset
81 if (in_size >= UINT_MAX / 4 ||
cc7c1ea68a52 Cosmetics: rename the "size" parameter of av_base64_encode() to "in_size".
stefano
parents: 657
diff changeset
82 out_size < (in_size+2) / 3 * 4 + 1)
244
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
83 return NULL;
657
50112fafa1ef Cosmetics: prefer out/in over buf/src for the parameter names of
stefano
parents: 656
diff changeset
84 ret = dst = out;
401
07e951242617 Reindent the code after last commit
lucabe
parents: 400
diff changeset
85 while (bytes_remaining) {
657
50112fafa1ef Cosmetics: prefer out/in over buf/src for the parameter names of
stefano
parents: 656
diff changeset
86 i_bits = (i_bits << 8) + *in++;
401
07e951242617 Reindent the code after last commit
lucabe
parents: 400
diff changeset
87 bytes_remaining--;
07e951242617 Reindent the code after last commit
lucabe
parents: 400
diff changeset
88 i_shift += 8;
244
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
89
401
07e951242617 Reindent the code after last commit
lucabe
parents: 400
diff changeset
90 do {
07e951242617 Reindent the code after last commit
lucabe
parents: 400
diff changeset
91 *dst++ = b64[(i_bits << 6 >> i_shift) & 0x3f];
07e951242617 Reindent the code after last commit
lucabe
parents: 400
diff changeset
92 i_shift -= 6;
07e951242617 Reindent the code after last commit
lucabe
parents: 400
diff changeset
93 } while (i_shift > 6 || (bytes_remaining == 0 && i_shift > 0));
07e951242617 Reindent the code after last commit
lucabe
parents: 400
diff changeset
94 }
07e951242617 Reindent the code after last commit
lucabe
parents: 400
diff changeset
95 while ((dst - ret) & 3)
07e951242617 Reindent the code after last commit
lucabe
parents: 400
diff changeset
96 *dst++ = '=';
244
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
97 *dst = '\0';
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
98
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
99 return ret;
9a977b2c7069 Move base64.[ch] to libavutil.
diego
parents:
diff changeset
100 }
654
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
101
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
102 #ifdef TEST
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
103
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
104 #undef printf
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
105
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
106 #define MAX_DATA_SIZE 1024
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
107 #define MAX_ENCODED_SIZE 2048
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
108
716
3f3e69baaaf8 Mark non-exported functions in test and example programs as static.
diego
parents: 659
diff changeset
109 static int test_encode_decode(const uint8_t *data, unsigned int data_size,
3f3e69baaaf8 Mark non-exported functions in test and example programs as static.
diego
parents: 659
diff changeset
110 const char *encoded_ref)
654
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
111 {
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
112 char encoded[MAX_ENCODED_SIZE];
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
113 uint8_t data2[MAX_DATA_SIZE];
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
114 int data2_size, max_data2_size = MAX_DATA_SIZE;
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
115
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
116 if (!av_base64_encode(encoded, MAX_ENCODED_SIZE, data, data_size)) {
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
117 printf("Failed: cannot encode the input data\n");
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
118 return 1;
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
119 }
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
120 if (encoded_ref && strcmp(encoded, encoded_ref)) {
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
121 printf("Failed: encoded string differs from reference\n"
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
122 "Encoded:\n%s\nReference:\n%s\n", encoded, encoded_ref);
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
123 return 1;
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
124 }
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
125
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
126 if ((data2_size = av_base64_decode(data2, encoded, max_data2_size)) < 0) {
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
127 printf("Failed: cannot decode the encoded string\n"
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
128 "Encoded:\n%s\n", encoded);
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
129 return 1;
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
130 }
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
131 if (memcmp(data2, data, data_size)) {
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
132 printf("Failed: encoded/decoded data differs from original data\n");
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
133 return 1;
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
134 }
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
135
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
136 printf("Passed!\n");
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
137 return 0;
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
138 }
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
139
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
140 int main(void)
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
141 {
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
142 int i, error_count = 0;
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
143 struct test {
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
144 const uint8_t *data;
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
145 const char *encoded_ref;
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
146 } tests[] = {
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
147 { "", ""},
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
148 { "1", "MQ=="},
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
149 { "22", "MjI="},
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
150 { "333", "MzMz"},
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
151 { "4444", "NDQ0NA=="},
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
152 { "55555", "NTU1NTU="},
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
153 { "666666", "NjY2NjY2"},
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
154 { "abc:def", "YWJjOmRlZg=="},
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
155 };
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
156
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
157 printf("Encoding/decoding tests\n");
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
158 for (i = 0; i < FF_ARRAY_ELEMS(tests); i++)
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
159 error_count += test_encode_decode(tests[i].data, strlen(tests[i].data), tests[i].encoded_ref);
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
160
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
161 return error_count;
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
162 }
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
163
b751ac480294 Add a new test program for base64, based on that removed in r17024.
stefano
parents: 653
diff changeset
164 #endif