drc: handle upto 64k page size
[pcsx_rearmed.git] / deps / libretro-common / encodings / encoding_base64.c
1 /*
2   https://github.com/superwills/NibbleAndAHalf
3   base64.h -- Fast base64 encoding and decoding.
4   version 1.0.0, April 17, 2013 143a
5   Copyright (C) 2013 William Sherif
6   This software is provided 'as-is', without any express or implied
7   warranty.  In no event will the authors be held liable for any damages
8   arising from the use of this software.
9   Permission is granted to anyone to use this software for any purpose,
10   including commercial applications, and to alter it and redistribute it
11   freely, subject to the following restrictions:
12   1. The origin of this software must not be misrepresented; you must not
13      claim that you wrote the original software. If you use this software
14      in a product, an acknowledgment in the product documentation would be
15      appreciated but is not required.
16   2. Altered source versions must be plainly marked as such, and must not be
17      misrepresented as being the original software.
18   3. This notice may not be removed or altered from any source distribution.
19   William Sherif
20   will.sherif@gmail.com
21   YWxsIHlvdXIgYmFzZSBhcmUgYmVsb25nIHRvIHVz
22
23
24   Modified for RetroArch formatting, logging, and header files.
25 */
26
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <encodings/base64.h>
31
32 const static char* b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
33
34 /* maps A=>0,B=>1.. */
35 const static unsigned char unb64[]={
36   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
37   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
38   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
39   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
40   0,   0,   0,  62,   0,   0,   0,  63,  52,  53,
41  54,  55,  56,  57,  58,  59,  60,  61,   0,   0,
42   0,   0,   0,   0,   0,   0,   1,   2,   3,   4,
43   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
44  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
45  25,   0,   0,   0,   0,   0,   0,  26,  27,  28,
46  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
47  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
48  49,  50,  51,   0,   0,   0,   0,   0,   0,   0,
49   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
50   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
51   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
52   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
53   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
54   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
55   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
56   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
57   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
58   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
59   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
60   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
61   0,   0,   0,   0,   0,   0,
62 }; /* This array has 256 elements */
63
64 /*
65    Converts binary data of length=len to base64 characters.
66    Length of the resultant string is stored in flen
67    (you must pass pointer flen).
68 */
69 char* base64(const void* binaryData, int len, int *flen)
70 {
71    char* res;
72    int byteNo; /* I need this after the loop */
73    const unsigned char* bin = (const unsigned char*) binaryData;
74    int rc                   = 0; /* result counter */
75    int modulusLen           = len % 3 ;
76    /* 2 gives 1 and 1 gives 2, but 0 gives 0. */
77    int pad                  = ((modulusLen&1)<<1) + ((modulusLen&2)>>1);
78
79    *flen                    = 4*(len + pad)/3;
80    if (!(res = (char*) malloc(*flen + 1))) /* and one for the NULL */
81       return 0;
82   
83    for (byteNo=0; byteNo <= len-3; byteNo+=3)
84    {
85       unsigned char BYTE0            = bin[byteNo];
86       unsigned char BYTE1            = bin[byteNo+1];
87       unsigned char BYTE2            = bin[byteNo+2];
88
89       res[rc++] = b64[BYTE0 >> 2];
90       res[rc++] = b64[((0x3&BYTE0)<<4) + (BYTE1 >> 4)];
91       res[rc++] = b64[((0x0f&BYTE1)<<2) + (BYTE2>>6)];
92       res[rc++] = b64[0x3f&BYTE2];
93    }
94   
95    if (pad==2)
96    {
97       res[rc++] = b64[bin[byteNo] >> 2];
98       res[rc++] = b64[(0x3&bin[byteNo])<<4];
99       res[rc++] = '=';
100       res[rc++] = '=';
101    }
102    else if (pad==1)
103    {
104       res[rc++] = b64[bin[byteNo] >> 2];
105       res[rc++] = b64[((0x3&bin[byteNo])<<4) + (bin[byteNo+1] >> 4)];
106       res[rc++] = b64[(0x0f&bin[byteNo+1])<<2];
107       res[rc++] = '=';
108    }
109   
110    res[rc]=0; /* NULL TERMINATOR! ;) */
111    return res;
112 }
113
114 unsigned char* unbase64(const char* ascii, int len, int *flen)
115 {
116    int charNo;
117    unsigned char *bin;
118    const unsigned char *safeAsciiPtr = (const unsigned char*) ascii;
119    int cb                            = 0;
120    int pad                           = 0;
121
122    if (len < 2) /* 2 accesses below would be OOB (Out Of Bounds). */
123    {
124       /* catch empty string, return NULL as result. */
125       /* ERROR: You passed an invalid base64 string (too short). 
126        * You get NULL back. */
127       *flen = 0;
128       return 0;
129    }
130
131    if (safeAsciiPtr[len-1]=='=')
132       ++pad;
133    if (safeAsciiPtr[len-2]=='=')
134       ++pad;
135   
136    *flen = 3*len/4 - pad;
137    if (!(bin = (unsigned char*)malloc(*flen)))
138       return 0;
139   
140    for (charNo=0; charNo <= len-4-pad; charNo+=4)
141    {
142       int A = unb64[safeAsciiPtr[charNo]];
143       int B = unb64[safeAsciiPtr[charNo+1]];
144       int C = unb64[safeAsciiPtr[charNo+2]];
145       int D = unb64[safeAsciiPtr[charNo+3]];
146     
147       bin[cb++] = (A<<2) | (B>>4);
148       bin[cb++] = (B<<4) | (C>>2);
149       bin[cb++] = (C<<6) | (D);
150    }
151   
152    if (pad==1)
153    {
154       int A = unb64[safeAsciiPtr[charNo]];
155       int B = unb64[safeAsciiPtr[charNo+1]];
156       int C = unb64[safeAsciiPtr[charNo+2]];
157     
158       bin[cb++] = (A<<2) | (B>>4);
159       bin[cb++] = (B<<4) | (C>>2);
160    }
161    else if (pad==2)
162    {
163       int A = unb64[safeAsciiPtr[charNo]];
164       int B = unb64[safeAsciiPtr[charNo+1]];
165     
166       bin[cb++] = (A<<2) | (B>>4);
167    }
168   
169    return bin;
170 }
171