--- /dev/null
+package core.encoding.base64
+
+encode :: (data: [] u8, allocator := context.allocator) -> [] u8 {
+ out := make([..] u8, allocator=allocator);
+
+ for i: range.{0, data.count - 2, 3} {
+ c1 := data[i + 0];
+ c2 := data[i + 1];
+ c3 := data[i + 2];
+
+ out << encode_map[c1 >> 2];
+ out << encode_map[((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4)];
+ out << encode_map[((c2 & 0xf) << 2) | ((c3 & 0xc0) >> 6)];
+ out << encode_map[c3 & 0x3f];
+ }
+
+ if data.count % 3 == 1 {
+ c := data[data.count - 1];
+ out << encode_map[c >> 2];
+ out << encode_map[(c & 0x3) << 4];
+ out << #char "=";
+ out << #char "=";
+
+ } elseif data.count % 3 == 2 {
+ c1 := data[data.count - 2];
+ c2 := data[data.count - 1];
+ out << encode_map[c1 >> 2];
+ out << encode_map[((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4)];
+ out << encode_map[(c2 & 0xf) << 2];
+ out << #char "=";
+ }
+
+ return out;
+}
+
+decode :: (data: [] u8, allocator := context.allocator) -> [] u8 {
+ if data.count % 4 != 0 do return null_str;
+
+ out := make([..] u8, allocator=allocator);
+
+ for i: range.{0, data.count, 4} {
+ c1 := data[i + 0];
+ c2 := data[i + 1];
+ c3 := data[i + 2];
+ c4 := data[i + 3];
+
+ v1 := decode_map[c1 - #char "+"];
+ v2 := decode_map[c2 - #char "+"];
+ v3 := decode_map[c3 - #char "+"];
+ v4 := decode_map[c4 - #char "+"];
+
+ o1 := (v1 << 2) | ((v2 & 0x30) >> 4);
+ o2 := ((v2 & 0xf) << 4) | ((v3 & 0x3c) >> 2);
+ o3 := ((v3 & 0x3) << 6) | (v4 & 0x3f);
+
+ out << o1;
+ if c3 != #char "=" do out << o2;
+ if c4 != #char "=" do out << o3;
+ }
+
+ return out;
+}
+
+
+#local
+encode_map := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+// Use as:
+// decode_map[ch - #char "+"];
+#local
+decode_map := u8.[
+ 62, // +
+ 0, 0, 0, // , - . Invalid
+ 63, // /
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // 0-9
+ 0, 0, 0, 0, 0, 0, 0, // : ; < = > ? @ Invalid
+
+ // A-Z
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25,
+
+ 0, 0, 0, 0, 0, 0, // [ \ ] ^ _ `
+
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51,
+];
+
#inject Date {
month_durations := u32.[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
+ make :: (year, month, day: i32) -> Date {
+ return .{ year, month - 1, day - 1 };
+ }
+
add_months :: (d: Date, days: i32) -> Date {
nd := d;
}
before :: (d1, d2: Date) -> bool {
- if d1.year != d2.year do return d1.year < d2.year;
+ if d1.year != d2.year do return d1.year < d2.year;
if d1.month != d2.month do return d1.month < d2.month;
return d1.day < d2.day;
}
after :: (d1, d2: Date) -> bool {
- if d1.year != d2.year do return d1.year > d2.year;
+ if d1.year != d2.year do return d1.year > d2.year;
if d1.month != d2.month do return d1.month > d2.month;
return d1.day > d2.day;
}