frequencies/preamble_utils.go (93 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 frequencies
import (
"encoding/binary"
"errors"
)
const (
// ###### DO NOT MESS WITH THIS FROM HERE ...
// Preamble byte Addresses
_PREAMBLE_LONGS_BYTE = 0
_SER_VER_BYTE = 1
_FAMILY_BYTE = 2
_LG_MAX_MAP_SIZE_BYTE = 3
_LG_CUR_MAP_SIZE_BYTE = 4
_FLAGS_BYTE = 5
// _EMPTY_FLAG_MASK flag bit masks
// due to a mistake different bits were used in C++ and Java to indicate empty sketch
// therefore both are set and checked for compatibility with historical binary format
_EMPTY_FLAG_MASK = 5
_SER_VER = 1
)
func checkPreambleSize(preamble []byte) (int64, error) {
if len(preamble) < 8 {
return 0, errors.New("preamble is too small")
}
pre0 := int64(binary.LittleEndian.Uint64(preamble))
preLongs := int(pre0 & 0x3F)
required := max(preLongs<<3, 8)
if len(preamble) < required {
return 0, errors.New("preamble is too small")
}
return pre0, nil
}
func insertPreLongs(preLongs, pre0 int64) int64 {
mask := int64(0x3F)
return (preLongs & mask) | (^mask & pre0)
}
func insertSerVer(serVer, pre0 int64) int64 {
shift := _SER_VER_BYTE << 3
mask := int64(0xFF)
return ((serVer & mask) << shift) | (^(mask << shift) & pre0)
}
func insertFamilyID(familyID, pre0 int64) int64 {
shift := _FAMILY_BYTE << 3
mask := int64(0xFF)
return ((familyID & mask) << shift) | (^(mask << shift) & pre0)
}
func insertLgMaxMapSize(lgMaxMapSize, pre0 int64) int64 {
shift := _LG_MAX_MAP_SIZE_BYTE << 3
mask := int64(0xFF)
return ((lgMaxMapSize & mask) << shift) | (^(mask << shift) & pre0)
}
func insertLgCurMapSize(lgCurMapSize, pre0 int64) int64 {
shift := _LG_CUR_MAP_SIZE_BYTE << 3
mask := int64(0xFF)
return ((lgCurMapSize & mask) << shift) | (^(mask << shift) & pre0)
}
func insertFlags(flags, pre0 int64) int64 {
shift := _FLAGS_BYTE << 3
mask := int64(0xFF)
return ((flags & mask) << shift) | (^(mask << shift) & pre0)
}
func insertActiveItems(activeItems, pre1 int64) int64 {
mask := int64(0xFFFFFFFF)
return (activeItems & mask) | (^mask & pre1)
}
func extractPreLongs(pre0 int64) int {
mask := int64(0x3F)
return int(pre0 & mask)
}
func extractSerVer(pre0 int64) int {
shift := _SER_VER_BYTE << 3
mask := int64(0xFF)
return int((pre0 >> shift) & mask)
}
func extractFamilyID(pre0 int64) int {
shift := _FAMILY_BYTE << 3
mask := int64(0xFF)
return int((pre0 >> shift) & mask)
}
func extractLgMaxMapSize(pre0 int64) int {
shift := _LG_MAX_MAP_SIZE_BYTE << 3
mask := int64(0xFF)
return int((pre0 >> shift) & mask)
}
func extractLgCurMapSize(pre0 int64) int {
shift := _LG_CUR_MAP_SIZE_BYTE << 3
mask := int64(0xFF)
return int((pre0 >> shift) & mask)
}
func extractFlags(pre0 int64) int {
shift := _FLAGS_BYTE << 3
mask := int64(0xFF)
return int((pre0 >> shift) & mask)
}
func extractActiveItems(pre1 int64) int {
mask := int64(0xFFFFFFFF)
return int(pre1 & mask)
}