[njs] Added base64 encoding for byte strings.
Dmitry Volyntsev
xeioex at nginx.com
Fri Mar 30 12:47:10 UTC 2018
details: http://hg.nginx.org/njs/rev/d35406201c78
branches:
changeset: 474:d35406201c78
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Fri Mar 30 15:46:38 2018 +0300
description:
Added base64 encoding for byte strings.
diffstat:
njs/njs_string.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
njs/njs_string.h | 4 +
2 files changed, 138 insertions(+), 0 deletions(-)
diffs (172 lines):
diff -r c685137c4e57 -r d35406201c78 njs/njs_string.c
--- a/njs/njs_string.c Fri Mar 30 15:46:38 2018 +0300
+++ b/njs/njs_string.c Fri Mar 30 15:46:38 2018 +0300
@@ -79,6 +79,8 @@ typedef struct {
} njs_string_replace_t;
+static void njs_encode_base64_core(nxt_str_t *dst, const nxt_str_t *src,
+ const u_char *basis, nxt_uint_t padding);
static nxt_noinline void njs_string_slice_prop(njs_string_prop_t *string,
njs_slice_prop_t *slice, njs_value_t *args, nxt_uint_t nargs);
static nxt_noinline void njs_string_slice_args(njs_slice_prop_t *slice,
@@ -119,6 +121,9 @@ static njs_ret_t njs_string_decode(njs_v
const uint32_t *reserve);
+#define njs_base64_encoded_length(len) (((len + 2) / 3) * 4)
+
+
njs_ret_t
njs_string_create(njs_vm_t *vm, njs_value_t *value, u_char *start,
uint32_t size, uint32_t length)
@@ -275,6 +280,135 @@ njs_string_hex(njs_vm_t *vm, njs_value_t
}
+static void
+njs_encode_base64(nxt_str_t *dst, const nxt_str_t *src)
+{
+ static u_char basis64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+ njs_encode_base64_core(dst, src, basis64, 1);
+}
+
+
+static void
+njs_encode_base64url(nxt_str_t *dst, const nxt_str_t *src)
+{
+ static u_char basis64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+
+ njs_encode_base64_core(dst, src, basis64, 0);
+}
+
+
+static void
+njs_encode_base64_core(nxt_str_t *dst, const nxt_str_t *src,
+ const u_char *basis, nxt_bool_t padding)
+{
+ u_char *d, *s, c0, c1, c2;
+ size_t len;
+
+ len = src->length;
+ s = src->start;
+ d = dst->start;
+
+ while (len > 2) {
+ c0 = s[0];
+ c1 = s[1];
+ c2 = s[2];
+
+ *d++ = basis[c0 >> 2];
+ *d++ = basis[((c0 & 0x03) << 4) | (c1 >> 4)];
+ *d++ = basis[((c1 & 0x0f) << 2) | (c2 >> 6)];
+ *d++ = basis[c2 & 0x3f];
+
+ s += 3;
+ len -= 3;
+ }
+
+ if (len > 0) {
+ c0 = s[0];
+ *d++ = basis[c0 >> 2];
+
+ if (len == 1) {
+ *d++ = basis[(c0 & 0x03) << 4];
+ if (padding) {
+ *d++ = '=';
+ *d++ = '=';
+ }
+
+ } else {
+ c1 = s[1];
+
+ *d++ = basis[((c0 & 0x03) << 4) | (c1 >> 4)];
+ *d++ = basis[(c1 & 0x0f) << 2];
+
+ if (padding) {
+ *d++ = '=';
+ }
+ }
+
+ }
+
+ dst->length = d - dst->start;
+}
+
+
+nxt_noinline njs_ret_t
+njs_string_base64(njs_vm_t *vm, njs_value_t *value, const nxt_str_t *src)
+{
+ nxt_str_t dst;
+
+ if (nxt_slow_path(src->length == 0)) {
+ vm->retval = njs_string_empty;
+ return NXT_OK;
+ }
+
+ dst.length = njs_base64_encoded_length(src->length);
+
+ dst.start = njs_string_alloc(vm, &vm->retval, dst.length, dst.length);
+ if (nxt_slow_path(dst.start == NULL)) {
+ njs_memory_error(vm);
+ return NXT_ERROR;
+ }
+
+ njs_encode_base64(&dst, src);
+
+ return NXT_OK;
+}
+
+
+nxt_noinline njs_ret_t
+njs_string_base64url(njs_vm_t *vm, njs_value_t *value, const nxt_str_t *src)
+{
+ size_t padding;
+ nxt_str_t dst;
+
+ if (nxt_slow_path(src->length == 0)) {
+ vm->retval = njs_string_empty;
+ return NXT_OK;
+ }
+
+ padding = src->length % 3;
+
+ /*
+ * Calculating the padding length: 0 -> 0, 1 -> 2, 2 -> 1.
+ */
+ padding = (4 >> padding) & 0x03;
+
+ dst.length = njs_base64_encoded_length(src->length) - padding;
+
+ dst.start = njs_string_alloc(vm, &vm->retval, dst.length, dst.length);
+ if (nxt_slow_path(dst.start == NULL)) {
+ njs_memory_error(vm);
+ return NXT_ERROR;
+ }
+
+ njs_encode_base64url(&dst, src);
+
+ return NXT_OK;
+}
+
+
void
njs_string_copy(njs_value_t *dst, njs_value_t *src)
{
diff -r c685137c4e57 -r d35406201c78 njs/njs_string.h
--- a/njs/njs_string.h Fri Mar 30 15:46:38 2018 +0300
+++ b/njs/njs_string.h Fri Mar 30 15:46:38 2018 +0300
@@ -124,6 +124,10 @@ njs_ret_t njs_string_new(njs_vm_t *vm, n
uint32_t size, uint32_t length);
njs_ret_t njs_string_hex(njs_vm_t *vm, njs_value_t *value,
const nxt_str_t *src);
+njs_ret_t njs_string_base64(njs_vm_t *vm, njs_value_t *value,
+ const nxt_str_t *src);
+njs_ret_t njs_string_base64url(njs_vm_t *vm, njs_value_t *value,
+ const nxt_str_t *src);
void njs_string_copy(njs_value_t *dst, njs_value_t *src);
njs_ret_t njs_string_validate(njs_vm_t *vm, njs_string_prop_t *string,
njs_value_t *value);
More information about the nginx-devel
mailing list