diff --git a/base.go b/base.go index d910c23..b8383bd 100644 --- a/base.go +++ b/base.go @@ -22,16 +22,29 @@ var ( ) // NewBase generates a new base2n config -func NewBase(off, til uint16, bit uint8) (*Base, error) { +func NewBase(off, til uint16, bit uint8) (bs Base, err error) { + bs = Base{ + off: off, + til: til, + bit: bit, + } + err = bs.check() + return +} + +func (bs Base) check() error { + off := bs.off + til := bs.til + bit := bs.bit if off == 0 { - return nil, ErrZeroOffsetStart + return ErrZeroOffsetStart } if bit >= 16 || bit == 0 { - return nil, ErrInvalidBitSize + return ErrInvalidBitSize } offe := uint32(off) + 1< 0x10000 { - return nil, ErrOffsetOverflow + return ErrOffsetOverflow } tile := uint32(til) // [til, tile) if bit > 8 && bit%2 == 0 { @@ -40,14 +53,10 @@ func NewBase(off, til uint16, bit uint8) (*Base, error) { tile += uint32(bit) } if tile > 0x10000 { - return nil, ErrTailOverflow + return ErrTailOverflow } if tile > uint32(off) && tile <= offe { - return nil, ErrTailInCodingArea + return ErrTailInCodingArea } - return &Base{ - off: off, - til: til, - bit: bit, - }, nil + return nil } diff --git a/code.go b/code.go index 018f991..67e82e9 100644 --- a/code.go +++ b/code.go @@ -1,9 +1,9 @@ package unibase2n -func (bs *Base) Encode(data []byte) []byte { +func (bs Base) Encode(data []byte) []byte { return nil } -func (bs *Base) Decode(data []byte) []byte { +func (bs Base) Decode(data []byte) []byte { return nil } diff --git a/conv.go b/conv.go index 286948c..b2600e9 100644 --- a/conv.go +++ b/conv.go @@ -16,7 +16,7 @@ func UTF82UTF16BE(b []byte) ([]byte, error) { return format.NewEncoder().Bytes(b) } -func (bs *Base) EncodeToString(b []byte) string { +func (bs Base) EncodeToString(b []byte) string { out, err := UTF16BE2UTF8(bs.Encode(b)) if err != nil { return "" @@ -24,11 +24,11 @@ func (bs *Base) EncodeToString(b []byte) string { return BytesToString(out) } -func (bs *Base) EncodeFromString(s string) []byte { +func (bs Base) EncodeFromString(s string) []byte { return bs.Encode(StringToBytes(s)) } -func (bs *Base) EncodeString(s string) string { +func (bs Base) EncodeString(s string) string { out, err := UTF16BE2UTF8(bs.Encode(StringToBytes(s))) if err != nil { return "" @@ -36,11 +36,11 @@ func (bs *Base) EncodeString(s string) string { return BytesToString(out) } -func (bs *Base) DecodeToString(d []byte) string { +func (bs Base) DecodeToString(d []byte) string { return BytesToString(bs.Decode(d)) } -func (bs *Base) DecodeFromString(s string) []byte { +func (bs Base) DecodeFromString(s string) []byte { d, err := UTF82UTF16BE(StringToBytes(s)) if err != nil { return nil @@ -48,7 +48,7 @@ func (bs *Base) DecodeFromString(s string) []byte { return bs.Decode(d) } -func (bs *Base) DecodeString(s string) string { +func (bs Base) DecodeString(s string) string { d, err := UTF82UTF16BE(StringToBytes(s)) if err != nil { return "" diff --git a/define.go b/define.go new file mode 100644 index 0000000..835344e --- /dev/null +++ b/define.go @@ -0,0 +1,25 @@ +package unibase2n + +var ( + // Base16384 CJK Unified Ideographs + // see https://github.com/fumiama/base16384 + Base16384, _ = NewBase(0x4e00, 0x3d00, 14) + // Base8192 谚文音節 Hangul Syllables + Base8192, _ = NewBase(0xac00, 0xcc00, 13) + // Base256 谚文字母 Hangul Jamo + Base256, _ = NewBase(0x1100, 0, 8) + // BaseMath (256) 數學運算符 Mathematical Operators + BaseMath, _ = NewBase(0x2200, 0, 8) + // Base128 帶圈或括號的字母數字 Enclosed Alphanumerics + Base128, _ = NewBase(0x2460, 0x24f4, 7) + // Base64 箭頭 Arrows + Base64, _ = NewBase(0x2190, 0x21d0, 6) + // Base64Gua 六十四卦 YiJing Hexagram Symbols + Base64Gua, _ = NewBase(0x3400, 0x262f, 6) + // Base32 方塊元素 Block Elements + Base32, _ = NewBase(0x2580, 0x259f, 5) + // Base16 漢文訓讀點 Kanbun Kundoku Den + Base16, _ = NewBase(0x3190, 0, 4) + // Base8 八卦 YiJing Hexagram Symbols + Base8, _ = NewBase(0x2630, 0x2689, 3) +) diff --git a/pack.go b/pack.go index 31b149c..eb37689 100644 --- a/pack.go +++ b/pack.go @@ -2,67 +2,44 @@ package unibase2n import ( "encoding/binary" + "errors" "unsafe" ) type Pack uint64 var ( - // Base16384 CJK Unified Ideographs - // see https://github.com/fumiama/base16384 - Base16384 = newbasepack(0x4e00, 0x3d00, 14) - // Base8192 谚文音節 Hangul Syllables - Base8192 = newbasepack(0xac00, 0xcc00, 13) - // Base256 谚文字母 Hangul Jamo - Base256 = newbasepack(0x1100, 0, 8) - // BaseMath (256) 數學運算符 Mathematical Operators - BaseMath = newbasepack(0x2200, 0, 8) - // Base128 帶圈或括號的字母數字 Enclosed Alphanumerics - Base128 = newbasepack(0x2460, 0x24f4, 7) - // Base64 箭頭 Arrows - Base64 = newbasepack(0x2190, 0x21d0, 6) - // Base64Gua 六十四卦 YiJing Hexagram Symbols - Base64Gua = newbasepack(0x3400, 0x262f, 6) - // Base32 方塊元素 Block Elements - Base32 = newbasepack(0x2580, 0x259f, 5) - // Base16 漢文訓讀點 Kanbun Kundoku Den - Base16 = newbasepack(0x3190, 0, 4) - // Base8 八卦 YiJing Hexagram Symbols - Base8 = newbasepack(0x2630, 0x2689, 3) + ErrInvalidPack = errors.New("invalid pack") ) -func newbasepack(off, til uint16, bit uint8) Pack { - b, err := NewBase(off, til, bit) - if err != nil { - panic(err) - } - return b.Pack() -} - // New base2n from a packed config -func New(pack Pack) *Base { - b := &Base{} +func New(pack Pack) (bs Base, err error) { + if pack&0xff == 0 && pack&0xff000000_00000000 == 0 { + err = ErrInvalidPack + return + } ismele := isLittleEndian() isitle := pack&0xffffff != 0 if ismele == isitle { // same endian - *(*Pack)(unsafe.Pointer(b)) = pack - return b + *(*Pack)(unsafe.Pointer(&bs)) = pack + } else { + field := (*[8]byte)(unsafe.Pointer(&pack)) + if isitle { // packed in little endian but I am big + bs.off = binary.BigEndian.Uint16(field[6:8]) + bs.til = binary.BigEndian.Uint16(field[4:6]) + } else { // packed in big endian but I am little + bs.off = binary.LittleEndian.Uint16(field[6:8]) + bs.til = binary.LittleEndian.Uint16(field[4:6]) + } + bs.bit = field[3] } - field := (*[8]byte)(unsafe.Pointer(&pack)) - if isitle { // packed in little endian but I am big - b.off = binary.BigEndian.Uint16(field[6:8]) - b.til = binary.BigEndian.Uint16(field[4:6]) - } else { // packed in big endian but I am little - b.off = binary.LittleEndian.Uint16(field[6:8]) - b.til = binary.LittleEndian.Uint16(field[4:6]) - } - b.bit = field[3] - return b + err = bs.check() + return } // Pack this config into an integer -func (bs *Base) Pack() Pack { - return *(*Pack)(unsafe.Pointer(bs)) +func (bs Base) Pack() Pack { + return *(*Pack)(unsafe.Pointer(&bs)) } func isLittleEndian() bool { diff --git a/pack_test.go b/pack_test.go index c32e73e..40ca199 100644 --- a/pack_test.go +++ b/pack_test.go @@ -12,15 +12,24 @@ func TestPackUnpack(t *testing.T) { t.Fatal(err) } p := bs.Pack() - bs1 := New(p) + bs1, err := New(p) + if err != nil { + t.Fatal(err) + } assert.Equal(t, bs, bs1) ismele := isLittleEndian() if ismele { // simulate be pack -> le unpack - bs2 := New(0x1234567808000000) + bs2, err := New(0x1234567808000000) + if err != nil { + t.Fatal(err) + } assert.Equal(t, bs, bs2) } else { // simulate le pack -> be unpack - bs2 := New(0x0000000878563412) + bs2, err := New(0x0000000878563412) + if err != nil { + t.Fatal(err) + } assert.Equal(t, bs, bs2) } } diff --git a/uint128be.go b/uint128be.go new file mode 100644 index 0000000..2efcdb4 --- /dev/null +++ b/uint128be.go @@ -0,0 +1,6 @@ +package unibase2n + +type usgnint128 struct { + a uint64 + b uint64 +}