coreutils

General Software Utilities
git clone http://git.omkov.net/coreutils
Log | Tree | Refs | README | LICENCE | Download

AuthorJamozed <[email protected]>
Date2021-02-05 11:53:24
Commit7ce4bd4e51828ad792d9b0eed936957d469db1b4
Parent2b96ababa2b0cf4e8c2bd4465841007e9848f271

base64: Implement base64 decoding

Diffstat

M src/base64.c | 59 +++++++++++++++++++++++++++++++++++++++--------------------

1 files changed, 39 insertions, 20 deletions

diff --git a/src/base64.c b/src/base64.c
index 6ec968c..4b42fd8 100644
--- a/src/base64.c
+++ b/src/base64.c
@@ -1,4 +1,4 @@
-// base64.c, version 0.1.0
+// base64.c, version 1.0.0
 // OMKOV coreutils base64
 // Copyright (C) 2021, Jakob Wakeling
 // All rights reserved.
@@ -31,17 +31,19 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
 */
 
 /*
-	TODO Implement Base64 decoding.
+	TODO Improve or replace fgetb64.
 */
 
+#include "lib/base64.h"
 #include "lib/error.h"
 #include "lib/optget.h"
 
+#include <ctype.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
 
-#define VERSION "0.1.0"
+#define VERSION "1.0.0"
 
 static struct lop lops[] = {
 	{ "help",    ARG_NUL, 256 },
@@ -57,6 +59,8 @@ static inline int base64(const char *file);
 static void encodeBase64(FILE *fi);
 static void decodeBase64(FILE *fi);
 
+static inline size_t fgetb64(uint8_t *buf, size_t len, FILE *fi);
+
 static void hlp(void);
 static void ver(void);
 
@@ -92,41 +96,56 @@ static inline int base64(const char *file) {
 	if (fi != stdin) { fclose(fi); } return 0;
 }
 
-/* Encode base64 using fixed size buffers. */
+/* Encode base64 using fixed size buffers */
 static void encodeBase64(FILE *fi) {
 	uint8_t ibuf[BUFSIZ * 6]; int l = 0;
 	uint8_t obuf[BUFSIZ * 8 + (BUFSIZ * 8 / 76)];
 
 	for (size_t c; (c = fread(ibuf, 1, sizeof (ibuf), fi)) != 0;) {
-		uint8_t *i = ibuf; uint8_t *j = obuf;
+		register uint8_t *i = ibuf, *o = obuf;
 
-		while (c >= 3) {
-			*j++ = B64E[i[0] >> 2];
-			*j++ = B64E[((i[0] & 0x03) << 4) | (i[1] >> 4)];
-			*j++ = B64E[((i[1] & 0x0F) << 2) | (i[2] >> 6)];
-			*j++ = B64E[i[2] & 0x3F]; i += 3;
+		for (; c >= 3; c -= 3) {
+			*o++ = B64E[i[0] >> 2];
+			*o++ = B64E[((i[0] & 0x03) << 4) | (i[1] >> 4)];
+			*o++ = B64E[((i[1] & 0x0F) << 2) | (i[2] >> 6)];
+			*o++ = B64E[i[2] & 0x3F]; i += 3;
 
-			c -= 3; l += 4; if (l == 76) { *j++ = '\n'; l = 0; }
+			l += 4; if (l == 76) { *o++ = '\n'; l = 0; }
 		}
 
 		if (c) {
-			*j++ = B64E[i[0] >> 2];
-			if (c == 1) { *j++ = B64E[(i[0] & 0x03) << 4]; *j++ = '='; }
+			*o++ = B64E[i[0] >> 2];
+			
+			if (c == 1) {
+				*o++ = B64E[(i[0] & 0x03) << 4]; *o++ = '=';
+			}
 			else {
-				*j++ = B64E[((i[0] & 0x03) << 4) | (i[1] >> 4)];
-				*j++ = B64E[(i[1] & 0x0F) << 2];
-			} *j++ = '='; l += 4;
+				*o++ = B64E[((i[0] & 0x03) << 4) | (i[1] >> 4)];
+				*o++ = B64E[(i[1] & 0x0F) << 2];
+			} *o++ = '='; l += 4;
 		}
 
-		fwrite(obuf, 1, j - obuf, stdout);
+		fwrite(obuf, 1, o - obuf, stdout);
 	}
 
 	if (l) { fputc('\n', stdout); } return;
 }
 
-/* Decode base64 using fixed size buffers. */
+/* Decode base64 using fixed size buffers */
 static void decodeBase64(FILE *fi) {
-	return;
+	uint8_t ibuf[BUFSIZ * 8]; uint8_t obuf[BUFSIZ * 6];
+	
+	for (size_t c; (c = fgetb64(ibuf, sizeof (ibuf), fi)) != 0;) {
+		c = b64decode(obuf, ibuf, c); fwrite(obuf, 1, c, stdout);
+	}
+}
+
+/* Read valid Base64 characters from a file */
+static inline size_t fgetb64(uint8_t *buf, size_t len, FILE *fi) {
+	size_t i = 0; for (int c; (c = fgetc(fi)) != EOF;) {
+		if (isalnum(c) || c == '+' || c == '/') { buf[i++] = c; }
+		if (i == len) { break; }
+	} return i;
 }
 
 /* Print help information */
@@ -134,7 +153,7 @@ static void hlp(void) {
 	puts("base64 - base64 encode or decode data\n");
 	puts("usage: base64 [-d] [file]\n");
 	puts("options:");
-	puts("  -d         Decode data (unimplemented)");
+	puts("  -d         Decode data");
 	puts("  --help     Display help information");
 	puts("  --version  Display version information");
 	return;