ece922ad95bca4bcfec39b0b45188a2b925fefa7
[deeprace] / libs / goat3d / src / util.c
1 /*
2 goat3d - 3D scene, and animation file format library.
3 Copyright (C) 2013-2023  John Tsiombikas <nuclear@member.fsf.org>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include <stdlib.h>
19 #include "util.h"
20
21 static int b64bits(int c);
22
23 int calc_b64_size(const char *s)
24 {
25         int len = strlen(s);
26         const char *end = s + len;
27         while(end > s && *--end == '=') len--;
28         return len * 3 / 4;
29 }
30
31
32 GOAT3DAPI void *goat3d_b64decode(const char *str, void *buf, int *bufsz)
33 {
34         unsigned char *dest, *end;
35         unsigned char acc;
36         int bits, sz;
37         unsigned int gidx;
38
39         if(buf) {
40                 sz = *bufsz;
41         } else {
42                 sz = calc_b64_size(str);
43                 if(!(buf = malloc(sz))) {
44                         return 0;
45                 }
46                 if(bufsz) *bufsz = sz;
47         }
48         dest = buf;
49         end = (unsigned char*)buf + sz;
50
51         sz = 0;
52         gidx = 0;
53         acc = 0;
54         while(*str) {
55                 if((bits = b64bits(*str++)) == -1) {
56                         continue;
57                 }
58
59                 switch(gidx++ & 3) {
60                 case 0:
61                         acc = bits << 2;
62                         break;
63                 case 1:
64                         if(dest < end) *dest = acc | (bits >> 4);
65                         dest++;
66                         acc = bits << 4;
67                         break;
68                 case 2:
69                         if(dest < end) *dest = acc | (bits >> 2);
70                         dest++;
71                         acc = bits << 6;
72                         break;
73                 case 3:
74                         if(dest < end) *dest = acc | bits;
75                         dest++;
76                 default:
77                         break;
78                 }
79         }
80
81         if(gidx & 3) {
82                 if(dest < end) *dest = acc;
83                 dest++;
84         }
85
86         if(bufsz) *bufsz = dest - (unsigned char*)buf;
87         return buf;
88 }
89
90 static int b64bits(int c)
91 {
92         if(c >= 'A' && c <= 'Z') {
93                 return c - 'A';
94         }
95         if(c >= 'a' && c <= 'z') {
96                 return c - 'a' + 26;
97         }
98         if(c >= '0' && c <= '9') {
99                 return c - '0' + 52;
100         }
101         if(c == '+') return 62;
102         if(c == '/') return 63;
103
104         return -1;
105 }
106
107 GOAT3DAPI void goat3d_bswap32(void *buf, int count)
108 {
109         int i;
110         register uint32_t x;
111         uint32_t *ptr = buf;
112
113         for(i=0; i<count; i++) {
114                 x = *ptr;
115                 *ptr++ = (x >> 24) | (x << 24) | ((x >> 8) & 0xff00) | ((x << 8) & 0xff0000);
116         }
117 }