diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/buffer.c | 40 | ||||
-rw-r--r-- | src/buffer.h | 3 |
2 files changed, 43 insertions, 0 deletions
diff --git a/src/buffer.c b/src/buffer.c index 61cfaf9e2..ee2dd2804 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -186,6 +186,46 @@ int git_buf_puts_escaped( return 0; } +static const char b64str[64] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +int git_buf_put_base64(git_buf *buf, const char *data, size_t len) +{ + size_t extra = len % 3; + uint8_t *write, a, b, c; + const uint8_t *read = (const uint8_t *)data; + + ENSURE_SIZE(buf, buf->size + ((len * 4 + 3) / 3) + 1); + write = (uint8_t *)&buf->ptr[buf->size]; + + /* convert each run of 3 bytes into 4 output bytes */ + for (len -= extra; len > 0; len -= 3) { + a = *read++; + b = *read++; + c = *read++; + + *write++ = b64str[a >> 2]; + *write++ = b64str[(a & 0x03) << 4 | b >> 4]; + *write++ = b64str[(b & 0x0f) << 2 | c >> 6]; + *write++ = b64str[c & 0x3f]; + } + + if (extra > 0) { + a = *read++; + b = (extra > 1) ? *read++ : 0; + + *write++ = b64str[a >> 2]; + *write++ = b64str[(a & 0x03) << 4 | b >> 4]; + *write++ = (extra > 1) ? b64str[(b & 0x0f) << 2] : '='; + *write++ = '='; + } + + buf->size = ((char *)write) - buf->ptr; + buf->ptr[buf->size] = '\0'; + + return 0; +} + int git_buf_vprintf(git_buf *buf, const char *format, va_list ap) { int len; diff --git a/src/buffer.h b/src/buffer.h index 17922e408..94b7e0e22 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -154,4 +154,7 @@ bool git_buf_is_binary(const git_buf *buf); /* Unescape all characters in a buffer */ void git_buf_unescape(git_buf *buf); +/* Write data as base64 encoded in buffer */ +int git_buf_put_base64(git_buf *buf, const char *data, size_t len); + #endif |