如何在golang中实现可变字节编码算法

时间:2017-09-05 03:15:53

标签: algorithm go

我正在做一些整数压缩的工作 我在c ++中实现了可变字节编码算法(参见下面的代码片段)。

我想知道如何在golang中实现它,因为我无法转换stringtune  在内存中int类型之间键入memcpy()

然后,我发现包binary.Write()中的encoding/binary可以进行序列化工作,可以将uint8编码为一个字节,unint16编码为2个字节,uint32编码为4种类型,依此类推。 / p>

但是如何使用3个字节来编码一个介于2097152和268435456之间的整数?

是否有类似代码段的转换方法?

void encode(int value, char* code_list, int& len) {

  int bit_value = 0;
  int bit_num = 0;

  if (value < 128) {
    bit_num = 1;
  } else if (value < 16384) {
    bit_num = 2;
    bit_value = 1;
  } else if (value < 2097152) {
    bit_num = 3;
    bit_value = 3;
  } else {
    bit_num = 4;
    bit_value = 7;
  }
  value <<= bit_num;
  value += bit_value;
  memcpy(code_list + len, (char*) &value, bit_num);
  len += bit_num;

}

1 个答案:

答案 0 :(得分:3)

您的编码使得第一个字节中最不重要的1位的计数告诉您编码值有多少字节。

这是您的代码的Go实现,它避免依赖于字节顺序(您的C版本所做的),并使用io.Writer而不是memcpy

请参阅:https://play.golang.org/p/jr0NypSnlW

package main

import (
    "fmt"
    "bytes"
    "io"
)

func encode(w io.Writer, n uint64) error {
    bytes := 0
    switch {
    case n < 128:
        bytes = 1
        n = (n << 1)
    case n < 16834:
        bytes = 2
        n = (n << 2) | 1
    case n < 2097152:
        bytes = 3
        n = (n << 3) | 3
    default:
        bytes = 4
        n = (n << 4) | 7
    }
    d := [4]byte{
        byte(n), byte(n>>8), byte(n>>16), byte(n>>24),
    }
    _, err := w.Write(d[:bytes])
    return err
}

func main() {
    xs := []uint64{0, 32, 20003, 60006, 300009}
    var b bytes.Buffer
    for _, x := range xs {
        if err := encode(&b, x); err != nil {
            panic(err)
        }
    }
    fmt.Println(b.Bytes())
}