| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416 | 
							- /*
 
-  * Public Domain Software
 
-  *
 
-  * I (Matthias Ladkau) am the author of the source code in this file.
 
-  * I have placed the source code in this file in the public domain.
 
-  *
 
-  * For further information see: http://creativecommons.org/publicdomain/zero/1.0/
 
-  */
 
- package bitutil
 
- import (
 
- 	"bytes"
 
- 	"encoding/binary"
 
- 	"math"
 
- )
 
- /*
 
- Different types of list packing
 
- */
 
- const (
 
- 	packListType2Bit = 0x1
 
- 	packListType3Bit = 0x2
 
- 	packListType6Bit = 0x3
 
- 	packListTypeVar  = 0x0
 
- )
 
- /*
 
- PackList packs a given list to a string. Depending on the given highest number the
 
- list is packed in the most efficient way.
 
- */
 
- func PackList(unpackedlist []uint64, highest uint64) string {
 
- 	// Depending on the highest number convert to given list
 
- 	switch {
 
- 	case highest <= 3:
 
- 		list := make([]byte, len(unpackedlist))
 
- 		for i, num := range unpackedlist {
 
- 			list[i] = byte(num)
 
- 		}
 
- 		return PackList2Bit(list)
 
- 	case highest <= 7:
 
- 		list := make([]byte, len(unpackedlist))
 
- 		for i, num := range unpackedlist {
 
- 			list[i] = byte(num)
 
- 		}
 
- 		return PackList3Bit(list)
 
- 	case highest <= 63:
 
- 		list := make([]byte, len(unpackedlist))
 
- 		for i, num := range unpackedlist {
 
- 			list[i] = byte(num)
 
- 		}
 
- 		return PackList6Bit(list)
 
- 	case highest <= math.MaxUint8:
 
- 		list := make([]byte, len(unpackedlist))
 
- 		for i, num := range unpackedlist {
 
- 			list[i] = byte(num)
 
- 		}
 
- 		return PackList8Bit(list)
 
- 	case highest <= math.MaxUint16:
 
- 		list := make([]uint16, len(unpackedlist))
 
- 		for i, num := range unpackedlist {
 
- 			list[i] = uint16(num)
 
- 		}
 
- 		return PackList16Bit(list)
 
- 	case highest <= math.MaxUint32:
 
- 		list := make([]uint32, len(unpackedlist))
 
- 		for i, num := range unpackedlist {
 
- 			list[i] = uint32(num)
 
- 		}
 
- 		return PackList32Bit(list)
 
- 	}
 
- 	return PackList64Bit(unpackedlist)
 
- }
 
- /*
 
- UnpackList unpacks a list from a packed string.
 
- */
 
- func UnpackList(packedlist string) []uint64 {
 
- 	plist := []byte(packedlist)
 
- 	if len(plist) == 0 {
 
- 		return nil
 
- 	}
 
- 	if plist[0]&0xC0 == packListTypeVar {
 
- 		return UnpackBigList(packedlist)
 
- 	}
 
- 	res := UnpackSmallList(packedlist)
 
- 	ret := make([]uint64, len(res))
 
- 	for i, item := range res {
 
- 		ret[i] = uint64(item)
 
- 	}
 
- 	return ret
 
- }
 
- /*
 
- PackList8Bit packs a list of 8 bit numbers.
 
- */
 
- func PackList8Bit(list []uint8) string {
 
- 	var bb bytes.Buffer
 
- 	bb.WriteByte(0x00)
 
- 	for i := 0; i < len(list); i++ {
 
- 		binary.Write(&bb, binary.LittleEndian, list[i])
 
- 	}
 
- 	return bb.String()
 
- }
 
- /*
 
- PackList16Bit packs a list of 16 bit numbers.
 
- */
 
- func PackList16Bit(list []uint16) string {
 
- 	var bb bytes.Buffer
 
- 	bb.WriteByte(0x01)
 
- 	for i := 0; i < len(list); i++ {
 
- 		binary.Write(&bb, binary.LittleEndian, list[i])
 
- 	}
 
- 	return bb.String()
 
- }
 
- /*
 
- PackList32Bit packs a list of 32 bit numbers.
 
- */
 
- func PackList32Bit(list []uint32) string {
 
- 	var bb bytes.Buffer
 
- 	bb.WriteByte(0x02)
 
- 	for i := 0; i < len(list); i++ {
 
- 		binary.Write(&bb, binary.LittleEndian, list[i])
 
- 	}
 
- 	return bb.String()
 
- }
 
- /*
 
- PackList64Bit packs a list of 64 bit numbers.
 
- */
 
- func PackList64Bit(list []uint64) string {
 
- 	var bb bytes.Buffer
 
- 	bb.WriteByte(0x03)
 
- 	for i := 0; i < len(list); i++ {
 
- 		binary.Write(&bb, binary.LittleEndian, list[i])
 
- 	}
 
- 	return bb.String()
 
- }
 
- /*
 
- UnpackBigList unpacks a list which has large values.
 
- */
 
- func UnpackBigList(packedlist string) []uint64 {
 
- 	var ret []uint64
 
- 	plist := []byte(packedlist)
 
- 	numlist := plist[1:]
 
- 	reader := bytes.NewReader(numlist)
 
- 	if plist[0] == 0x00 {
 
- 		var item uint8
 
- 		size := len(numlist)
 
- 		ret = make([]uint64, size)
 
- 		for i := 0; i < size; i++ {
 
- 			binary.Read(reader, binary.LittleEndian, &item)
 
- 			ret[i] = uint64(item)
 
- 		}
 
- 	} else if plist[0] == 0x01 {
 
- 		var item uint16
 
- 		size := len(numlist) / 2
 
- 		ret = make([]uint64, size)
 
- 		for i := 0; i < size; i++ {
 
- 			binary.Read(reader, binary.LittleEndian, &item)
 
- 			ret[i] = uint64(item)
 
- 		}
 
- 	} else if plist[0] == 0x02 {
 
- 		var item uint32
 
- 		size := len(numlist) / 4
 
- 		ret = make([]uint64, size)
 
- 		for i := 0; i < size; i++ {
 
- 			binary.Read(reader, binary.LittleEndian, &item)
 
- 			ret[i] = uint64(item)
 
- 		}
 
- 	} else if plist[0] == 0x03 {
 
- 		size := len(numlist) / 8
 
- 		ret = make([]uint64, size)
 
- 		binary.Read(reader, binary.LittleEndian, ret)
 
- 	}
 
- 	return ret
 
- }
 
- /*
 
- PackList2Bit packs a list of bytes into a string using 2 bits for each item.
 
- (Items must be between 1 and 3)
 
- */
 
- func PackList2Bit(list []byte) string {
 
- 	if len(list) == 0 {
 
- 		return ""
 
- 	}
 
- 	// Packing the list with 2 bit items reduces the size by a factor of 4
 
- 	ret := make([]byte, int(math.Ceil(float64(1)/3+float64(len(list)-1)/4)))
 
- 	if len(list) == 1 {
 
- 		ret[0] = list2byte2bit(packListType2Bit, list[0], 0, 0)
 
- 	} else if len(list) == 2 {
 
- 		ret[0] = list2byte2bit(packListType2Bit, list[0], list[1], 0)
 
- 	} else {
 
- 		ret[0] = list2byte2bit(packListType2Bit, list[0], list[1], list[2])
 
- 		j := 1
 
- 		for i := 3; i < len(list); i += 4 {
 
- 			if len(list[i:]) == 1 {
 
- 				ret[j] = list2byte2bit(list[i], 0, 0, 0)
 
- 			} else if len(list[i:]) == 2 {
 
- 				ret[j] = list2byte2bit(list[i], list[i+1], 0, 0)
 
- 			} else if len(list[i:]) == 3 {
 
- 				ret[j] = list2byte2bit(list[i], list[i+1], list[i+2], 0)
 
- 			} else {
 
- 				ret[j] = list2byte2bit(list[i], list[i+1], list[i+2], list[i+3])
 
- 			}
 
- 			j++
 
- 		}
 
- 	}
 
- 	return string(ret)
 
- }
 
- /*
 
- PackList3Bit packs a list of bytes into a string using 3 bits for each item.
 
- (Items must be between 1 and 7)
 
- */
 
- func PackList3Bit(list []byte) string {
 
- 	if len(list) == 0 {
 
- 		return ""
 
- 	}
 
- 	// Packing the list with 2 bit items reduces the size by a factor of 2
 
- 	ret := make([]byte, int(math.Ceil(float64(len(list))/2)))
 
- 	if len(list) == 1 {
 
- 		ret[0] = list2byte3bitAndHeader(packListType3Bit, list[0], 0)
 
- 	} else {
 
- 		ret[0] = list2byte3bitAndHeader(packListType3Bit, list[0], list[1])
 
- 		j := 1
 
- 		for i := 2; i < len(list); i += 2 {
 
- 			if len(list[i:]) == 1 {
 
- 				ret[j] = list2byte3bitAndHeader(0, list[i], 0)
 
- 			} else {
 
- 				ret[j] = list2byte3bitAndHeader(0, list[i], list[i+1])
 
- 			}
 
- 			j++
 
- 		}
 
- 	}
 
- 	return string(ret)
 
- }
 
- /*
 
- PackList6Bit packs a list of bytes into a string using 6 bits for each item.
 
- (Items must be between 1 and 63)
 
- */
 
- func PackList6Bit(list []byte) string {
 
- 	if len(list) == 0 {
 
- 		return ""
 
- 	}
 
- 	// Packing the list with 6 bit items does not reduce the factor
 
- 	ret := make([]byte, len(list))
 
- 	if len(list) == 1 {
 
- 		ret[0] = list2byte6bitAndHeader(packListType6Bit, list[0])
 
- 	} else {
 
- 		ret[0] = list2byte6bitAndHeader(packListType6Bit, list[0])
 
- 		for i := 1; i < len(list); i++ {
 
- 			ret[i] = list2byte6bitAndHeader(0, list[i])
 
- 		}
 
- 	}
 
- 	return string(ret)
 
- }
 
- /*
 
- UnpackSmallList unpacks a string into a list of bytes. Returns the list of bytes
 
- or a list of a single 0x00 byte if the numbers in the list are too big.
 
- */
 
- func UnpackSmallList(packedlist string) []byte {
 
- 	plist := []byte(packedlist)
 
- 	if len(plist) == 0 {
 
- 		return []byte{}
 
- 	}
 
- 	ltype := plist[0] & 0xC0 >> 6
 
- 	if ltype == packListType2Bit {
 
- 		return unpacklist2bit(plist)
 
- 	} else if ltype == packListType3Bit {
 
- 		return unpacklist3bit(plist)
 
- 	} else if ltype == packListType6Bit {
 
- 		return unpacklist6bit(plist)
 
- 	}
 
- 	// Must be gob encoded
 
- 	return []byte{00}
 
- }
 
- func unpacklist2bit(packedlist []byte) []byte {
 
- 	ret := make([]byte, 0, len(packedlist)*3)
 
- 	for i := 0; i < len(packedlist); i++ {
 
- 		b1, b2, b3, b4 := byte2list2bit(packedlist[i])
 
- 		if i > 0 && b1 != 0 {
 
- 			ret = append(ret, b1)
 
- 		}
 
- 		if b2 != 0 {
 
- 			ret = append(ret, b2)
 
- 		}
 
- 		if b3 != 0 {
 
- 			ret = append(ret, b3)
 
- 		}
 
- 		if b4 != 0 {
 
- 			ret = append(ret, b4)
 
- 		}
 
- 	}
 
- 	return ret
 
- }
 
- func unpacklist3bit(packedlist []byte) []byte {
 
- 	ret := make([]byte, 0, len(packedlist)*2)
 
- 	for i := 0; i < len(packedlist); i++ {
 
- 		b1, b2 := byte2list3bit(packedlist[i])
 
- 		if b1 != 0 {
 
- 			ret = append(ret, b1)
 
- 		}
 
- 		if b2 != 0 {
 
- 			ret = append(ret, b2)
 
- 		}
 
- 	}
 
- 	return ret
 
- }
 
- func unpacklist6bit(packedlist []byte) []byte {
 
- 	ret := make([]byte, 0, len(packedlist))
 
- 	for i := 0; i < len(packedlist); i++ {
 
- 		ret = append(ret, byte2list6bit(packedlist[i]))
 
- 	}
 
- 	return ret
 
- }
 
- func byte2list2bit(b byte) (b1 byte, b2 byte, b3 byte, b4 byte) {
 
- 	b1 = b & 0xC0 >> 6
 
- 	b2 = b & 0x30 >> 4
 
- 	b3 = b & 0x0C >> 2
 
- 	b4 = b & 0x03
 
- 	return b1, b2, b3, b4
 
- }
 
- func list2byte2bit(b1 byte, b2 byte, b3 byte, b4 byte) byte {
 
- 	return (b1 & 0x03 << 6) |
 
- 		(b2 & 0x03 << 4) |
 
- 		(b3 & 0x03 << 2) |
 
- 		(b4 & 0x03)
 
- }
 
- func list2byte3bitAndHeader(b1 byte, b2 byte, b3 byte) byte {
 
- 	return (b1 & 0x03 << 6) |
 
- 		(b2 & 0x07 << 3) |
 
- 		(b3 & 0x07)
 
- }
 
- func byte2list3bit(b byte) (b2 byte, b3 byte) {
 
- 	b2 = b & 0x38 >> 3
 
- 	b3 = b & 0x07
 
- 	return b2, b3
 
- }
 
- func list2byte6bitAndHeader(b1 byte, b2 byte) byte {
 
- 	return (b1 & 0x03 << 6) |
 
- 		(b2 & 0x3F)
 
- }
 
- func byte2list6bit(b byte) byte {
 
- 	return b & 0x3F
 
- }
 
 
  |