@@ 1,6 1,28 @@
+#include <stdint.h>
#include <janet.h>
+extern ssize_t base_64_encode(const uint8_t*, size_t, uint8_t*, size_t);
+
+static Janet Baseenc_base64Encode(int argc, Janet argv[]) {
+ janet_arity(argc, 1, 2);
+ JanetByteView data = janet_getbytes(argv, 0);
+ JanetBuffer *buf;
+ if (argc > 1) {
+ buf = janet_getbuffer(argv, 1);
+ } else {
+ buf = janet_buffer((data.len * 4 + 3) / 3);
+ }
+
+ ssize_t len = base_64_encode(&data.bytes[0], (size_t)data.len, &buf->data[0], (size_t)buf->capacity);
+ if (len == -1) {
+ janet_panic("buffer overflow");
+ }
+ buf->count = (int32_t)len;
+ return janet_wrap_buffer(buf);
+}
+
static const JanetReg Baseenc_cfuns[] = {
+ { "base64-encode", Baseenc_base64Encode, NULL },
{ NULL, NULL, NULL },
};
@@ 1,9 1,62 @@
const std = @import("std");
-export fn add(a: i32, b: i32) i32 {
- return a + b;
+const EncDecError = error{
+ BufferOverflow,
+};
+
+const Base64 = struct {
+ const pad = @as(u8, '=');
+ const alphabet: *const [64]u8 =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ++
+ "abcdefghijklmnopqrstuvwxyz" ++
+ "0123456789+/";
+ fn encode(in: []const u8, out: []u8) EncDecError!usize {
+ var i = @as(usize, 0);
+ var j = @as(usize, 0);
+ while (i < in.len) {
+ if (j + 4 > out.len) return EncDecError.BufferOverflow;
+ const a = @intCast(u32, in[i]);
+ const b = if (i + 1 < in.len) @intCast(u32, in[i + 1]) else 0;
+ const c = if (i + 2 < in.len) @intCast(u32, in[i + 2]) else 0;
+ out[j] = alphabet[a >> 2];
+ out[j + 1] = alphabet[(a << 4 & 0b110000) | (b >> 4 & 0b001111)];
+ out[j + 2] = alphabet[(b << 2 & 0b111100) | (c >> 6 & 0b000011)];
+ out[j + 3] = alphabet[c & 0b111111];
+ if (i + 1 >= in.len) {
+ out[j + 2] = pad;
+ out[j + 3] = pad;
+ } else if (i + 2 >= in.len) {
+ out[j + 3] = pad;
+ }
+
+ i += 3;
+ j += 4;
+ }
+
+ return j;
+ }
+
+ fn decode(in: []const u8, out: []u8) EncDecError!usize {
+ _ = in;
+ _ = out;
+ return EncDecError.BufferOverflow;
+ }
+};
+
+export fn base_64_encode(in_buf: [*]const u8, in_len: usize, out_buf: [*]u8, out_len: usize) isize {
+ const in = in_buf[0..in_len];
+ const out = out_buf[0..out_len];
+
+ return @intCast(isize, Base64.encode(in, out) catch |err| switch (err) {
+ EncDecError.BufferOverflow => return -1,
+ });
}
-test "basic add functionality" {
- try std.testing.expect(add(3, 7) == 10);
+export fn base_64_decode(in_buf: [*]const u8, in_len: usize, out_buf: [*]u8, out_len: usize) isize {
+ const in = in_buf[0..in_len];
+ const out = out_buf[0..out_len];
+
+ return @intCast(isize, Base64.decode(in, out) catch |err| switch (err) {
+ EncDecError.BufferOverflow => return -1,
+ });
}