From e556a9624c67733c32329a095f6f508ea7b42a15 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Tue, 24 Jun 2014 20:11:46 -0400 Subject: [PATCH] yijing: initial commit, encoding only --- yijing/README.md | 7 +++ yijing/yijing.go | 110 ++++++++++++++++++++++++++++++++++++++++++ yijing/yijing_test.go | 54 +++++++++++++++++++++ 3 files changed, 171 insertions(+) create mode 100644 yijing/README.md create mode 100644 yijing/yijing.go create mode 100644 yijing/yijing_test.go diff --git a/yijing/README.md b/yijing/README.md new file mode 100644 index 0000000..d396001 --- /dev/null +++ b/yijing/README.md @@ -0,0 +1,7 @@ +A sha256 digest in hex + + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852 + +A sha256 digest in git status in Yi Jing + + ䷸䷻䷌䷄䷐䷩䷯䷼䷇䷁䷙䷚䷾䷿䷜䷈䷦䷖䷿䷹䷉䷂䷞䷮䷐䷞䷖䷤䷦䷹䷌䷌䷩䷉䷝䷙䷆䷷䷥䷒䷮䷅☲¦ diff --git a/yijing/yijing.go b/yijing/yijing.go new file mode 100644 index 0000000..3914779 --- /dev/null +++ b/yijing/yijing.go @@ -0,0 +1,110 @@ +// Copyright 2014 Emery Hemingway. All rights reserved. +// Use of this source code is governed by the GPLv3+. + +// Package yijing64 implements radix 64 Yijing encoding and decoding. +package yijing + +// ䷀ 0xE4 0xB7 0x80 +// ䷿ 0xE4 0xB7 0xBF + +// ☰ 0xE2 0x98 0xb0 +// ☷ 0xE2 0x98 0xb8 + +// ǀ 0xC7 0x80 +// ¦ 0xC2 0xa6 + +// full block is 0xE2, 0x96, 0x88 + +// EncodedLen returns the length of an encoding of n source bytes. +func EncodedLen(n int) (l int) { + if n == 0 { + return 0 + } + + l = ((n * 4) / 3) * 3 + + switch n % 3 { + case 0: + case 1: + l += 4 + case 2: + l += 5 + } + return l +} + +// Encode encodes src into EncodedLen(len(src)) +// bytes of dst. As a convenience, it returns the number +// of bytes written to dst, but this value is always EncodedLen(len(src)). +// Encode implements Yi Jing encoding. +func Encode(dst, src []byte) (n int) { + for len(src) > 0 { + dst[0] = 0xE4 + dst[1] = 0xB7 + dst[2] = 0x80 | (src[0] >> 2) + + switch len(src) { + + case 2: + dst[3] = 0xE4 + dst[4] = 0xB7 + dst[5] = 0x80 | ((src[0] & 0x03) << 4) | (src[1] >> 4) + + dst[6] = 0xE2 + dst[7] = 0x98 + dst[8] = 0xB0 | ((src[1] & 0x0F) >> 1) + + if (src[1] & 0xFE) == 0 { + dst[9] = 0xC7 + dst[10] = 0x80 + } else { + dst[9] = 0xC2 + dst[10] = 0xA6 + } + return n + 11 + + case 1: + if (src[0] & 0x02) == 0 { + dst[3] = 0xC7 + dst[4] = 0x80 + } else { + dst[3] = 0xC2 + dst[4] = 0xA6 + } + + if (src[0] & 0x01) == 0 { + dst[5] = 0xC7 + dst[6] = 0x80 + } else { + dst[5] = 0xC2 + dst[6] = 0xA6 + } + return n + 7 + } + + dst[3] = 0xE4 + dst[4] = 0xB7 + dst[5] = 0x80 | ((src[0] & 0x03) << 4) | (src[1] >> 4) + + dst[6] = 0xE4 + dst[7] = 0xB7 + dst[8] = 0x80 | ((src[1] & 0x0F) << 2) | (src[2] >> 4) + + dst[9] = 0xE4 + dst[10] = 0xB7 + dst[11] = 0x80 | (src[2] & 0x3F) + + n += 12 + + src = src[3:] + dst = dst[12:] + } + return n +} + +// EncodeToString returns the Yi Jing encoding of src. +func EncodeToString(src []byte) string { + dst := make([]byte, EncodedLen(len(src))) + Encode(dst, src) + return string(dst) +} diff --git a/yijing/yijing_test.go b/yijing/yijing_test.go new file mode 100644 index 0000000..590f683 --- /dev/null +++ b/yijing/yijing_test.go @@ -0,0 +1,54 @@ +package yijing + +import ( + "testing" +) + +type encDecTest struct { + enc string + dec []byte +} + +var encDecTests = []encDecTest{ + {"", []byte{}}, + {"䷀ǀǀ", []byte{0x00}}, + {"䷿¦¦", []byte{0xFF}}, + {"䷀䷀☰ǀ", []byte{0x00, 0x00}}, + {"䷿䷿☷¦", []byte{0xFF, 0xFF}}, + {"䷀䷀䷀䷀", []byte{0x00, 0x00, 0x00}}, + {"䷕䷕䷕䷕", []byte{0x55, 0x55, 0x55}}, + {"䷪䷪䷪䷪", []byte{0xAA, 0xAA, 0xAA}}, + {"䷿䷿䷿䷿", []byte{0xFF, 0xFF, 0xFF}}, + {"䷀䷀䷀䷀䷀䷀䷀䷀", []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {"䷿䷿䷿䷿䷿䷿䷿䷿", []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}, +} + +func TestEncode(t *testing.T) { + for i, test := range encDecTests { + dst := make([]byte, EncodedLen(len(test.dec))) + n := Encode(dst, test.dec) + if n != len(dst) { + t.Errorf("#%d: bad return value: got: %d want: %d", i, n, len(dst)) + } + if string(dst) != test.enc { + t.Errorf("#%d: got: %q want: %q", i, dst, test.enc) + } + } +} + +func BenchmarkEncode(b *testing.B) { + var c byte + for i := 0; i < b.N; i++ { + srcBuf := make([]byte, 27) + dstBuf := make([]byte, EncodedLen(27)) + for l := 0; l < 28; l++ { + src := srcBuf[:l] + for ; c < 255; c++ { + for j := 0; j < l; j++ { + src[j] = c + Encode(dstBuf, src) + } + } + } + } +}