aboutsummaryrefslogtreecommitdiff
path: root/libbb/atlas_bb64.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbb/atlas_bb64.c')
-rw-r--r--libbb/atlas_bb64.c126
1 files changed, 126 insertions, 0 deletions
diff --git a/libbb/atlas_bb64.c b/libbb/atlas_bb64.c
new file mode 100644
index 0000000..bcd073b
--- /dev/null
+++ b/libbb/atlas_bb64.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2013 RIPE NCC <atlas@ripe.net>
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+#define BUF_CHUNK 256
+
+struct buf
+{
+ size_t offset;
+ size_t size;
+ size_t maxsize;
+ unsigned char *buf;
+ int fd;
+};
+
+void buf_init(struct buf *buf, int fd)
+{
+ buf->maxsize= 0;
+ buf->size= 0;
+ buf->offset= 0;
+ buf->buf= NULL;
+ buf->fd= fd;
+}
+
+int buf_add(struct buf *buf, const void *data, size_t len )
+{
+ size_t maxsize;
+ void *newbuf;
+
+ if (buf->size+len <= buf->maxsize)
+ {
+ /* Easy case, just add data */
+ memcpy(buf->buf+buf->size, data, len);
+ buf->size += len;
+ return 0;
+ }
+
+ /* Just get a new buffer */
+ maxsize= buf->size-buf->offset + len + BUF_CHUNK;
+
+ newbuf= malloc(maxsize);
+ if (!newbuf)
+ {
+ fprintf(stderr, "unable to allocate %ld bytes\n", maxsize);
+ return (1);
+ }
+
+ if (buf->offset < buf->size)
+ {
+ /* Copy existing data */
+ memcpy(newbuf, buf->buf+buf->offset, buf->size-buf->offset);
+ buf->size -= buf->offset;
+ buf->offset= 0;
+ }
+ else
+ {
+ buf->size= buf->offset= 0;
+ }
+ buf->maxsize= maxsize;
+ free(buf->buf);
+ buf->buf= newbuf;
+
+ memcpy(buf->buf+buf->size, data, len);
+ buf->size += len;
+ return 0;
+}
+
+int buf_add_b64(struct buf *buf, void *data, size_t len, int mime_nl)
+{
+ char b64[]=
+ "ABCDEFGHIJKLMNOP"
+ "QRSTUVWXYZabcdef"
+ "ghijklmnopqrstuv"
+ "wxyz0123456789+/";
+ int i;
+ uint8_t *p;
+ uint32_t v;
+ char str[4];
+
+ p= data;
+
+ for (i= 0; i+3 <= len; i += 3, p += 3)
+ {
+ v= (p[0] << 16) + (p[1] << 8) + p[2];
+ str[0]= b64[(v >> 18) & 63];
+ str[1]= b64[(v >> 12) & 63];
+ str[2]= b64[(v >> 6) & 63];
+ str[3]= b64[(v >> 0) & 63];
+ buf_add(buf, str, 4);
+ if(mime_nl)
+ if (i % 48 == 45)
+ buf_add(buf, "\n", 1);
+ }
+ switch(len-i)
+ {
+ case 0: break; /* Nothing to do */
+ case 1:
+ v= (p[0] << 16);
+ str[0]= b64[(v >> 18) & 63];
+ str[1]= b64[(v >> 12) & 63];
+ str[2]= '=';
+ str[3]= '=';
+ buf_add(buf, str, 4);
+ break;
+ case 2:
+ v= (p[0] << 16) + (p[1] << 8);
+ str[0]= b64[(v >> 18) & 63];
+ str[1]= b64[(v >> 12) & 63];
+ str[2]= b64[(v >> 6) & 63];
+ str[3]= '=';
+ buf_add(buf, str, 4);
+ break;
+ default:
+ fprintf(stderr, "bad state in buf_add_b64");
+ }
+}
+
+void buf_cleanup(struct buf *buf)
+{
+ if(buf->maxsize)
+ free(buf->buf);
+ buf->buf = NULL;
+ buf->offset= buf->size= buf->maxsize= 0;
+}