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