diff options
author | Vicent Martà <vicent@github.com> | 2012-10-10 15:00:32 -0700 |
---|---|---|
committer | Vicent Martà <vicent@github.com> | 2012-10-10 15:00:32 -0700 |
commit | 9206976fc7cf2daa2db475a6b8fd03a838622112 (patch) | |
tree | 931f03b6538edff286e1d5c41696c72619c2bdbb /src/buffer.c | |
parent | aeba5e175a58eebc5eae43adaa40955d2a9f55c3 (diff) | |
parent | 2d3579bea699847b560e99a5107b12eac8d172ad (diff) | |
download | libgit2-9206976fc7cf2daa2db475a6b8fd03a838622112.tar.gz |
Merge pull request #971 from arrbee/base64-encoder
Add git_buf_put_base64 to buffer API
Diffstat (limited to 'src/buffer.c')
-rw-r--r-- | src/buffer.c | 40 |
1 files changed, 40 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; |