hll/to_slice_impl.go (142 lines of code) (raw):
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package hll
import (
"encoding/binary"
"fmt"
)
func toHllByteArr(impl hllArray, compact bool) ([]byte, error) {
auxBytes := 0
if impl.GetTgtHllType() == TgtHllTypeHll4 {
auxHashMap := impl.getAuxHashMap()
if auxHashMap != nil {
if compact {
auxBytes = auxHashMap.getCompactSizeBytes()
} else {
auxBytes = auxHashMap.getUpdatableSizeBytes()
}
} else {
if compact {
auxBytes = 0
} else {
auxBytes = 4 << lgAuxArrInts[impl.GetLgConfigK()]
}
}
}
totalBytes := hllByteArrStart + impl.getHllByteArrBytes() + auxBytes
byteArr := make([]byte, totalBytes)
err := insertHll(impl, byteArr, compact)
return byteArr, err
}
func toCouponSlice(impl hllCoupon, dstCompact bool) ([]byte, error) {
srcCouponCount := impl.getCouponCount()
srcLgCouponArrInts := impl.getLgCouponArrInts()
srcCouponArrInts := 1 << srcLgCouponArrInts
list := impl.GetCurMode() == curModeList
if dstCompact {
//Src Heap, Src Updatable, Dst Compact
dataStart := impl.getMemDataStart()
bytesOut := dataStart + (srcCouponCount << 2)
byteArrOut := make([]byte, bytesOut)
copyCommonListAndSet(impl, byteArrOut)
insertCompactFlag(byteArrOut, dstCompact)
itr := impl.iterator()
cnt := 0
for itr.nextValid() {
p, err := itr.getPair()
if err != nil {
return nil, err
}
binary.LittleEndian.PutUint32(byteArrOut[dataStart+(cnt<<2):dataStart+(cnt<<2)+4], uint32(p))
cnt++
}
if list {
insertListCount(byteArrOut, srcCouponCount)
} else {
insertHashSetCount(byteArrOut, srcCouponCount)
}
return byteArrOut, nil
} else {
//Src Heap, Src Updatable, Dst Updatable
dataStart := impl.getMemDataStart()
bytesOut := dataStart + (srcCouponArrInts << 2)
byteArrOut := make([]byte, bytesOut)
copyCommonListAndSet(impl, byteArrOut)
for _, v := range impl.getCouponIntArr() {
binary.LittleEndian.PutUint32(byteArrOut[dataStart:dataStart+4], uint32(v))
dataStart += 4
}
if list {
insertListCount(byteArrOut, srcCouponCount)
} else {
insertHashSetCount(byteArrOut, srcCouponCount)
}
return byteArrOut, nil
}
}
func copyCommonListAndSet(impl hllCoupon, dst []byte) {
insertPreInts(dst, impl.getPreInts())
insertSerVer(dst)
insertFamilyID(dst)
insertLgK(dst, impl.GetLgConfigK())
insertLgArr(dst, impl.getLgCouponArrInts())
insertEmptyFlag(dst, impl.IsEmpty())
insertOooFlag(dst, impl.isOutOfOrder())
insertCurMode(dst, impl.GetCurMode())
insertTgtHllType(dst, impl.GetTgtHllType())
}
func insertHll(impl hllArray, dst []byte, compact bool) error {
insertCommonHll(impl, dst, compact)
hllByteArr := impl.getHllByteArr()
copy(dst[hllByteArrStart:], hllByteArr)
if impl.getAuxHashMap() != nil {
return insertAux(impl, dst, compact)
} else {
return insertAuxCount(dst, 0)
}
}
func insertCommonHll(impl hllArray, dst []byte, compact bool) {
insertPreInts(dst, impl.getPreInts())
insertSerVer(dst)
insertFamilyID(dst)
insertLgK(dst, impl.GetLgConfigK())
insertEmptyFlag(dst, impl.IsEmpty())
insertCompactFlag(dst, compact)
insertOooFlag(dst, impl.isOutOfOrder())
insertCurMin(dst, impl.getCurMin())
insertCurMode(dst, impl.GetCurMode())
insertTgtHllType(dst, impl.GetTgtHllType())
insertHipAccum(dst, impl.getHipAccum())
insertKxQ0(dst, impl.getKxQ0())
insertKxQ1(dst, impl.getKxQ1())
insertNumAtCurMin(dst, impl.getNumAtCurMin())
insertRebuildCurMinNumKxQFlag(dst, impl.isRebuildCurMinNumKxQFlag())
}
func insertAux(impl hllArray, dst []byte, compact bool) error {
auxHashMap := impl.getAuxHashMap()
auxCount := auxHashMap.getAuxCount()
err := insertAuxCount(dst, auxCount)
if err != nil {
return err
}
insertLgArr(dst, auxHashMap.getLgAuxArrInts())
auxStart := impl.getAuxStart()
if compact {
itr := auxHashMap.iterator()
cnt := 0
for itr.nextValid() {
p, err := itr.getPair()
if err != nil {
return err
}
binary.LittleEndian.PutUint32(dst[auxStart+(cnt<<2):auxStart+(cnt<<2)+4], uint32(p))
cnt++
}
if cnt != auxCount {
return fmt.Errorf("corruption, should not happen: %d != %d", cnt, auxCount)
}
} else {
auxInts := 1 << auxHashMap.getLgAuxArrInts()
auxArr := auxHashMap.getAuxIntArr()
for i, v := range auxArr[:auxInts] {
binary.LittleEndian.PutUint32(dst[auxStart+(i<<2):auxStart+(i<<2)+4], uint32(v))
}
}
return nil
}