Base64 encode and decode, line by line.
This commit is contained in:
commit
a992bb8f3f
5 changed files with 110 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
bin/
|
||||||
7
README.md
Normal file
7
README.md
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
# Base64 line-by-line
|
||||||
|
|
||||||
|
These applications encode and decode strins in Base64 by reading their inputs **line by line**.
|
||||||
|
|
||||||
|
Advantages:
|
||||||
|
- Ultra fast, not even a single memory allocation is performed
|
||||||
|
- Readable source code, it's just a function call and a loop over input
|
||||||
6
makefile
Normal file
6
makefile
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
all: build
|
||||||
|
|
||||||
|
build:
|
||||||
|
[ -d ./bin ] || mkdir bin
|
||||||
|
cc -o bin/b64-lbl-encode src/b64-lbl-encode.c
|
||||||
|
cc -o bin/b64-lbl-decode src/b64-lbl-decode.c
|
||||||
53
src/b64-lbl-decode.c
Normal file
53
src/b64-lbl-decode.c
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define BUFFER_LENGTH 50000
|
||||||
|
|
||||||
|
static const char *base64_chars =
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
"abcdefghijklmnopqrstuvwxyz"
|
||||||
|
"0123456789+/";
|
||||||
|
|
||||||
|
int base64_decode(const char *input, unsigned char *output, size_t *output_length) {
|
||||||
|
int input_length = strlen(input);
|
||||||
|
if (input_length % 4 != 0) return -1; // Base64 input must be a multiple of 4.
|
||||||
|
|
||||||
|
// Calculate output length
|
||||||
|
*output_length = input_length / 4 * 3;
|
||||||
|
if (input[input_length - 1] == '=') (*output_length)--;
|
||||||
|
if (input[input_length - 2] == '=') (*output_length)--;
|
||||||
|
|
||||||
|
for (int i = 0, j = 0; i < input_length; ) {
|
||||||
|
unsigned int a = input[i] == '=' ? 0 : strchr(base64_chars, input[i]) - base64_chars; i++;
|
||||||
|
unsigned int b = input[i] == '=' ? 0 : strchr(base64_chars, input[i]) - base64_chars; i++;
|
||||||
|
unsigned int c = input[i] == '=' ? 0 : strchr(base64_chars, input[i]) - base64_chars; i++;
|
||||||
|
unsigned int d = input[i] == '=' ? 0 : strchr(base64_chars, input[i]) - base64_chars; i++;
|
||||||
|
|
||||||
|
output[j++] = (a << 2) | (b >> 4);
|
||||||
|
if (j < *output_length) output[j++] = (b << 4) | (c >> 2);
|
||||||
|
if (j < *output_length) output[j++] = (c << 6) | d;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
char input[BUFFER_LENGTH];
|
||||||
|
unsigned char output[BUFFER_LENGTH]; // Maximum size for decoded output from a Base64 string
|
||||||
|
size_t output_length;
|
||||||
|
|
||||||
|
while (fgets(input, sizeof(input), stdin)) {
|
||||||
|
// Remove the newline character if present
|
||||||
|
input[strcspn(input, "\n")] = 0;
|
||||||
|
|
||||||
|
if (base64_decode(input, output, &output_length) == 0) {
|
||||||
|
fwrite(output, 1, output_length, stdout);
|
||||||
|
putchar('\n'); // Just to separate outputs if needed
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Error decoding: %s\n", input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
43
src/b64-lbl-encode.c
Normal file
43
src/b64-lbl-encode.c
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define BUFFER_LENGTH 50000
|
||||||
|
|
||||||
|
static const char *base64_chars =
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
"abcdefghijklmnopqrstuvwxyz"
|
||||||
|
"0123456789+/";
|
||||||
|
|
||||||
|
void base64_encode(const unsigned char *input, size_t input_length, char *output, size_t *output_length) {
|
||||||
|
int i, j;
|
||||||
|
*output_length = 4 * ((input_length + 2) / 3); // Calculate output size
|
||||||
|
|
||||||
|
for (i = 0, j = 0; i < input_length;) {
|
||||||
|
unsigned int a = i < input_length ? input[i++] : 0;
|
||||||
|
unsigned int b = i < input_length ? input[i++] : 0;
|
||||||
|
unsigned int c = i < input_length ? input[i++] : 0;
|
||||||
|
|
||||||
|
output[j++] = base64_chars[a >> 2];
|
||||||
|
output[j++] = base64_chars[((a & 3) << 4) | (b >> 4)];
|
||||||
|
output[j++] = (i > input_length + 1) ? '=' : base64_chars[((b & 15) << 2) | (c >> 6)];
|
||||||
|
output[j++] = (i > input_length) ? '=' : base64_chars[c & 63];
|
||||||
|
}
|
||||||
|
output[j] = '\0'; // Null-terminate the output string
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
char input[BUFFER_LENGTH];
|
||||||
|
char output[BUFFER_LENGTH*4/3]; // Maximum size for encoded output (4/3 per byte)
|
||||||
|
size_t output_length;
|
||||||
|
|
||||||
|
while (fgets(input, sizeof(input), stdin)) {
|
||||||
|
// Remove the newline character if present
|
||||||
|
input[strcspn(input, "\n")] = 0;
|
||||||
|
|
||||||
|
base64_encode((unsigned char *)input, strlen(input), output, &output_length);
|
||||||
|
printf("%s\n", output);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue