about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorJoe DF <joedf@live.ca>2014-09-22 01:00:27 -0400
committerJoe DF <joedf@live.ca>2014-09-22 01:00:27 -0400
commit03332d7b509e0e2950aef579086064ecf02b654f (patch)
tree2a4fc063cc64345734b1d84f87bd84fd750d2af3
parent8805313bc5194f0dc9add7e7f2297eaeb8c8324b (diff)
downloadbase64-03332d7b509e0e2950aef579086064ecf02b654f.tar.gz
add initial version
-rw-r--r--.gitignore4
-rw-r--r--BuildRun.bat7
-rw-r--r--base64.c133
-rw-r--r--test.c128
4 files changed, 272 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index 58bcbf8..60ca861 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,7 @@
+*.exe

+*.lnk

+*.url

+

 # Windows image file caches

 Thumbs.db

 ehthumbs.db

diff --git a/BuildRun.bat b/BuildRun.bat
new file mode 100644
index 0000000..874ac75
--- /dev/null
+++ b/BuildRun.bat
@@ -0,0 +1,7 @@
+@echo off
+mkdir bin 2>NUL
+cls
+echo compiling...
+gcc test.c base64.c -o bin\test.exe
+echo running...
+bin\test.exe
\ No newline at end of file
diff --git a/base64.c b/base64.c
new file mode 100644
index 0000000..55b482f
--- /dev/null
+++ b/base64.c
@@ -0,0 +1,133 @@
+#include <stdlib.h>
+
+/*
+	base64.c - by Joe DF (joedf@ahkscript.org)
+	Released under the MIT License
+	
+	Revision: 00:06 2014-09-22
+	
+	Thank you for inspiration:
+	http://www.codeproject.com/Tips/813146/Fast-base-functions-for-encode-decode
+*/
+
+
+unsigned int b64_int(unsigned int ch);
+unsigned int b64e_size(unsigned int in_size);
+unsigned int b64d_size(unsigned int in_size);
+unsigned int b64_encode(const unsigned int* in, unsigned int in_len, unsigned char* out);
+unsigned int b64_decode(const unsigned char* in, unsigned int in_len, unsigned int* out);
+
+
+//Base64 char table - used internally for encoding
+unsigned char b64_chr[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+//Base64 char table functions - used internally for decoding
+unsigned int b64_int(unsigned int ch) {
+
+	// ASCII to base64_int
+	// 65-90  Upper Case  >>  0-25
+	// 97-122 Lower Case  >>  26-51
+	// 48-57  Numbers     >>  52-61
+	// 43     Plus (+)    >>  62
+	// 47     Slash (/)   >>  63
+	// 61     Equal (=)   >>  64~
+	if (ch==43)
+		return 62;
+	if (ch==47)
+		return 63;
+	if (ch==61)
+		return 64;
+	if ((ch>47) && (ch<58))
+		return ch + 4;
+	if ((ch>64) && (ch<91))
+		return ch - 'A';
+	if ((ch>96) && (ch<123))
+		return (ch - 'a') + 26;
+	return 0;
+}
+
+// in_size : the number bytes to be encoded.
+// Returns the recommended memory size to be allocated for the output buffer excluding the null byte
+unsigned int b64e_size(unsigned int in_size) {
+
+	// size equals 4*floor((1/3)*(in_size+2));
+	int i, j = 0;
+	for (i=0;i<in_size;i++) {
+		if (i % 3 == 0)
+			j += 1;
+	}
+	return (4*j);
+}
+
+// in_size : the number bytes to be decoded.
+// Returns the recommended memory size to be allocated for the output buffer excluding the null byte
+unsigned int b64d_size(unsigned int in_size) {
+
+	return ((3*in_size)/4);
+}
+
+// in : buffer of "raw" binary to be encoded.
+// in_len : number of bytes to be encoded.
+// out : pointer to buffer with enough memory, user is responsible for memory allocation, receives null-terminated string
+// returns size of output including null byte
+unsigned int b64_encode(const unsigned int* in, unsigned int in_len, unsigned char* out) {
+
+	unsigned int i=0, j=0, k=0, s[3];
+	
+	for (i=0;i<in_len;i++) {
+		s[j++]=*(in+i);
+		if (j==3) {
+			out[k+0] = b64_chr[ s[0]>>2 ];
+			out[k+1] = b64_chr[ ((s[0]&0x03)<<4)+((s[1]&0xF0)>>4) ];
+			out[k+2] = b64_chr[ ((s[1]&0x0F)<<2)+((s[2]&0xC0)>>6) ];
+			out[k+3] = b64_chr[ s[2]&0x3F ];
+			j=0; k+=4;
+		}
+	}
+	
+	if (j) {
+		if (j==1)
+			s[1] = 0;
+		out[k+0] = b64_chr[ s[0]>>2 ];
+		out[k+1] = b64_chr[ ((s[0]&0x03)<<4)+((s[1]&0xF0)>>4) ];
+		if (j==2)
+			out[k+2] = b64_chr[ ((s[1]&0x0F)<<2) ];
+		else
+			out[k+2] = '=';
+		out[k+3] = '=';
+		k+=4;
+	}
+
+	out[k] = '\0';
+	
+	return k;
+}
+
+// in : buffer of base64 string to be decoded.
+// in_len : number of bytes to be decoded.
+// out : pointer to buffer with enough memory, user is responsible for memory allocation, receives "raw" binary
+// returns size of output excluding null byte
+unsigned int b64_decode(const unsigned char* in, unsigned int in_len, unsigned int* out) {
+
+	unsigned int i=0, j=0, k=0, s[4];
+	
+	for (i=0;i<in_len;i++) {
+		s[j++]=b64_int(*(in+i));
+		if (j==4) {
+			out[k+0] = (s[0]<<2)+((s[1]&0x30)>>4);
+			if (s[2]!=64) {
+				out[k+1] = ((s[1]&0x0F)<<4)+((s[2]&0x3C)>>2);
+				if ((s[3]!=64)) {
+					out[k+2] = ((s[2]&0x03)<<6)+(s[3]); k+=3;
+				} else {
+					k+=2;
+				}
+			} else {
+				k+=1;
+			}
+			j=0;
+		}
+	}
+	
+	return k;
+}
diff --git a/test.c b/test.c
new file mode 100644
index 0000000..1a07c9c
--- /dev/null
+++ b/test.c
@@ -0,0 +1,128 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+//Test values
+///////////////////////////////////////////////////////////////
+#define STRING_A "9TrJ"
+#define STRING_B "9TrJUQ=="
+#define STRING_C "9TrJUfA="
+
+#define HEXNUM_A {0xF5,0x3A,0xC9}
+#define HEXNUM_B {0xF5,0x3A,0xC9,0x51}
+#define HEXNUM_C {0xF5,0x3A,0xC9,0x51,0xF0}
+
+#define HEXSTR_A "0xF5 0x3A 0xC9"
+#define HEXSTR_B "0xF5 0x3A 0xC9 0x51"
+#define HEXSTR_C "0xF5 0x3A 0xC9 0x51 0xF0"
+///////////////////////////////////////////////////////////////
+
+#define NELEMS(x)  (sizeof(x) / sizeof(x[0]))
+
+int test_b64_encode();
+int test_b64_decode();
+int hexputs(unsigned int* data, unsigned int len);
+int compare(int *a, int *b, int l);
+char *status(int boolean);
+
+int main() {
+	
+	puts("\nbase64.c [Test]");
+	puts("------------------------------------");
+	printf("%s           : %s\n",HEXSTR_A,STRING_A);
+	printf("%s      : %s\n",HEXSTR_B,STRING_B);
+	printf("%s : %s\n",HEXSTR_C,STRING_C);
+	puts("\nTesting b64_encode() ...\n");
+	test_b64_encode();
+	puts("\nTesting b64_decode() ...\n");
+	test_b64_decode();
+	puts("\n[END]");
+
+	return 0;
+}
+
+int test_b64_encode() {
+	
+	int test_a[] = HEXNUM_A;
+	int test_b[] = HEXNUM_B;
+	int test_c[] = HEXNUM_C;
+
+	int size_a = NELEMS(test_a);
+	int size_b = NELEMS(test_b);
+	int size_c = NELEMS(test_c);
+
+	int out_size_a = b64e_size(size_a) + 1;
+	int out_size_b = b64e_size(size_b) + 1;
+	int out_size_c = b64e_size(size_c) + 1;
+
+	unsigned char *out_a = malloc(out_size_a);
+	unsigned char *out_b = malloc(out_size_b);
+	unsigned char *out_c = malloc(out_size_c);
+
+  	out_size_a = b64_encode(test_a,size_a,out_a);
+  	out_size_b = b64_encode(test_b,size_b,out_b);
+  	out_size_c = b64_encode(test_c,size_c,out_c);
+
+  	printf("%s\t%s\n",status(!strcmp(out_a,STRING_A)),out_a);
+  	printf("%s\t%s\n",status(!strcmp(out_b,STRING_B)),out_b);
+  	printf("%s\t%s\n",status(!strcmp(out_c,STRING_C)),out_c);
+  	
+  	return 0;
+}
+
+int test_b64_decode() {
+	
+	char test_a[] = STRING_A;
+	char test_b[] = STRING_B;
+	char test_c[] = STRING_C;
+
+	int len_a = strlen(test_a);
+	int len_b = strlen(test_b);
+	int len_c = strlen(test_c);
+
+	int out_size_a = b64d_size(len_a) + 1;
+	int out_size_b = b64d_size(len_b) + 1;
+	int out_size_c = b64d_size(len_c) + 1;
+
+	unsigned int *out_a = malloc(out_size_a);
+	unsigned int *out_b = malloc(out_size_b);
+	unsigned int *out_c = malloc(out_size_c);
+
+  	out_size_a = b64_decode(test_a,len_a,out_a);
+  	out_size_b = b64_decode(test_b,len_b,out_b);
+  	out_size_c = b64_decode(test_c,len_c,out_c);
+	
+	int r_a[] = HEXNUM_A;
+	int r_b[] = HEXNUM_B;
+	int r_c[] = HEXNUM_C;
+
+  	printf("%s\t",status(compare(r_a,out_a,3))); hexputs(out_a,out_size_a);
+  	printf("%s\t",status(compare(r_b,out_b,4))); hexputs(out_b,out_size_b);
+  	printf("%s\t",status(compare(r_c,out_c,5))); hexputs(out_c,out_size_c);
+  	
+  	return 0;
+}
+
+int hexputs(unsigned int* data, unsigned int len) {
+	int i;
+	for (i=0;i<len;i++) {
+		printf("0x%X ",(int)data[i]);
+	}
+	printf("\n");
+	return 0;
+}
+
+int compare(int *a, int *b, int l) {
+	int i;
+	for (i=0;i<l;i++) {
+		if (a[i]!=b[i])
+			return 0;
+	}
+	return 1;
+}
+
+char *status(int boolean) {
+	if (boolean)
+		return "[PASS]";
+	return "[FAIL]";
+}
\ No newline at end of file