Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Unified Diff: common/data/base128/base128.go

Issue 2538553003: Add base128 encoding library. (Closed)
Patch Set: Fix nits Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | common/data/base128/base128_test.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: common/data/base128/base128.go
diff --git a/common/data/base128/base128.go b/common/data/base128/base128.go
new file mode 100644
index 0000000000000000000000000000000000000000..81b62673fd067eb0c8e9f06079ae74b3c63d977c
--- /dev/null
+++ b/common/data/base128/base128.go
@@ -0,0 +1,108 @@
+// Copyright 2016 The LUCI Authors. All rights reserved.
+// Use of this source code is governed under the Apache License, Version 2.0
+// that can be found in the LICENSE file.
+
+// Package base128 implements base128 encoding and decoding.
+//
+// Encoded results are UTF8-safe, and will retain the same memcmp sorting
+// properties of the input data.
+package base128
+
+import "errors"
+
+var (
+ // ErrLength is returned from the Decode* methods if the input has an
+ // impossible length.
+ ErrLength = errors.New("base128: invalid length base128 string")
+
+ // ErrBit is returned from the Decode* methods if the input has a byte with
+ // the high-bit set (e.g. 0x80). This will never be the case for strings
+ // produced from the Encode* methods in this package.
+ ErrBit = errors.New("base128: high bit set in base128 string")
+)
+
+// 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 base128 encoding.
+func Encode(dst, src []byte) int {
+ ret := EncodedLen(len(src))
+ if len(dst) < ret {
+ panic("dst has insufficient length")
+ }
+ dst = dst[:0]
+ whichByte := uint(1)
+ bufByte := byte(0)
+ for _, v := range src {
+ dst = append(dst, bufByte|(v>>whichByte))
+ bufByte = (v&(1<<whichByte) - 1) << (7 - whichByte)
+ if whichByte == 7 {
+ dst = append(dst, bufByte)
+ bufByte = 0
+ whichByte = 0
+ }
+ whichByte++
+ }
+ dst = append(dst, bufByte)
+ return ret
+}
+
+// Decode decodes src into DecodedLen(len(src)) bytes, returning the actual
+// number of bytes written to dst.
+//
+// If Decode encounters invalid input, it returns an error describing the
+// failure.
+func Decode(dst, src []byte) (int, error) {
+ dLen := DecodedLen(len(src))
+ if EncodedLen(dLen) != len(src) {
+ return 0, ErrLength
+ }
+ if len(dst) < dLen {
+ panic("dst has insufficient length")
+ }
+ dst = dst[:0]
+ whichByte := uint(1)
+ bufByte := byte(0)
+ for _, v := range src {
+ if (v & 0x80) != 0 {
+ return len(dst), ErrBit
+ }
+ if whichByte > 1 {
+ dst = append(dst, bufByte|(v>>(8-whichByte)))
+ }
+ bufByte = v << whichByte
+ if whichByte == 8 {
+ whichByte = 0
+ }
+ whichByte++
+ }
+ return len(dst), nil
+}
+
+// DecodeString returns the bytes represented by the base128 string s.
+func DecodeString(s string) ([]byte, error) {
+ src := []byte(s)
+ dst := make([]byte, DecodedLen(len(src)))
+ if _, err := Decode(dst, src); err != nil {
+ return nil, err
+ }
+ return dst, nil
+}
+
+// DecodedLen returns the number of bytes `encLen` encoded bytes decodes to.
+func DecodedLen(encLen int) int {
+ return (encLen * 7 / 8)
+}
+
+// EncodedLen returns the number of bytes that `dataLen` bytes will encode to.
+func EncodedLen(dataLen int) int {
+ return (((dataLen * 8) + 6) / 7)
+}
+
+// EncodeToString returns the base128 encoding of src.
+func EncodeToString(src []byte) string {
+ dst := make([]byte, EncodedLen(len(src)))
+ Encode(dst, src)
+ return string(dst)
+}
« no previous file with comments | « no previous file | common/data/base128/base128_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698