]> git.ipfire.org Git - thirdparty/nettle.git/commitdiff
(base64_encode): Encode from the end of the data
authorNiels Möller <nisse@lysator.liu.se>
Mon, 30 Sep 2002 19:32:42 +0000 (21:32 +0200)
committerNiels Möller <nisse@lysator.liu.se>
Mon, 30 Sep 2002 19:32:42 +0000 (21:32 +0200)
towards the start, in order to support overlapping areas.

Rev: src/nettle/base64.c:1.3
Rev: src/nettle/base64.h:1.5

base64.c
base64.h

index 4ec6c6af500ba2004a0a4bba8114cdbce50f5f08..7124060e9236707f7fc22ec400e3fe0a6e8776fe 100644 (file)
--- a/base64.c
+++ b/base64.c
@@ -26,6 +26,7 @@
 #include "base64.h"
 
 #include <assert.h>
+#include <stdlib.h>
 
 #define TABLE_INVALID -1
 #define TABLE_SPACE -2
@@ -56,42 +57,55 @@ static const signed char decode_table[256] =
   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 };
 
+#define ENCODE(x) (encode_table[0x3F & (x)])
+
 unsigned 
 base64_encode(uint8_t *dst,
               unsigned src_length,
               const uint8_t *src)
 {
-  uint8_t *out = dst;
+  unsigned dst_length = BASE64_ENCODE_LENGTH(src_length);
+  const uint8_t *in = src + src_length;
+  uint8_t *out = dst + dst_length;
+  unsigned left_over = src_length % 3;
 
-  while (src_length >= 3)
+  if (left_over)
     {
-      *out++ = encode_table[0x3F &  (src[0] >> 2)];
-      *out++ = encode_table[0x3F & ((src[0] << 4) | (src[1] >> 4))];
-      *out++ = encode_table[0x3F & ((src[1] << 2) | (src[2] >> 6))];
-      *out++ = encode_table[0x3F &   src[2]];
-      src += 3;
-      src_length -= 3;
-    }
+      switch(left_over)
+       {
+       case 1:
+         in--;
+         *--out = '=';
+         *--out = '=';
+         *--out = ENCODE(in[0] << 4);
+         *--out = ENCODE(in[0] >> 2);
+         break;
+         
+       case 2:
+         in-= 2;
+         *--out = '=';
+         *--out = ENCODE( in[1] << 2);
+         *--out = ENCODE((in[0] << 4) | (in[1] >> 4));
+         *--out = ENCODE( in[0] >> 2);
+         break;
 
-  switch (src_length) 
+       default:
+         abort();
+       }
+    }
+  
+  while (in > src)
     {
-    case 2:
-      *out++ = encode_table[0x3F &  (src[0] >> 2)];
-      *out++ = encode_table[0x3F & ((src[0] << 4) | (src[1] >> 4))];
-      *out++ = encode_table[0x3F &  (src[1] << 2)];
-      *out++ = '=';
-      break;
-    case 1:
-      *out++ = encode_table[0x3F & (src[0] >> 2)];
-      *out++ = encode_table[0x3F & (src[0] << 4)];
-      *out++ = '=';
-      *out++ = '=';
-      break;
-    case 0:
-      break;
+      in -= 3;
+      *--out = ENCODE( in[2]);
+      *--out = ENCODE((in[1] << 2) | (in[2] >> 6));
+      *--out = ENCODE((in[0] << 4) | (in[1] >> 4));
+      *--out = ENCODE( in[0] >> 2);
     }
 
-  return out - dst;
+  assert(out == dst);
+
+  return dst_length;
 }
 
 void
index e0f3c5f3c7eead5449d70f95e0126cdf4713b39f..d69c9ccdb72c2014ed601c412668066b69fe2357 100644 (file)
--- a/base64.h
+++ b/base64.h
@@ -33,6 +33,9 @@
 #define BASE64_BINARY_BLOCK_SIZE 3
 #define BASE64_TEXT_BLOCK_SIZE 4
 
+/* Overlapping source and destination is allowed, as long as the start
+ * of the source area is not later than the start of the destination
+ * area. */
 unsigned /* Returns the length of encoded data */
 base64_encode(uint8_t *dst,
               unsigned src_length,
@@ -53,6 +56,9 @@ struct base64_ctx /* Internal, do not modify */
 void
 base64_decode_init(struct base64_ctx *ctx);
 
+/* Overlapping source and destination is allowed, as long as the start
+ * of the source area is not before the start of the destination
+ * area. */
 unsigned /* Returns the length of decoded data */
 base64_decode_update(struct base64_ctx *ctx,
                      uint8_t *dst,