/*
* Copyright (c) 2020 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* $Id: //eng/uds-releases/jasper/src/uds/hashUtils.h#1 $
*/
#ifndef HASH_UTILS_H
#define HASH_UTILS_H 1
#include "compiler.h"
#include "common.h"
#include "geometry.h"
#include "numeric.h"
#include "uds.h"
// How various portions of a hash are apportioned. Size dependent.
enum {
MASTER_INDEX_BYTES_OFFSET = 0, // size 8
CHAPTER_INDEX_BYTES_OFFSET = 8, // size 6
SAMPLE_BYTES_OFFSET = 14, // size 2
MASTER_INDEX_BYTES_COUNT = 8,
CHAPTER_INDEX_BYTES_COUNT = 6,
SAMPLE_BYTES_COUNT = 2,
};
/**
* Extract the portion of a block name used by the chapter index.
*
* @param name The block name
*
* @return The chapter index bytes
**/
static INLINE uint64_t extractChapterIndexBytes(const UdsChunkName *name)
{
// Get the high order 16 bits, then the low order 32 bits
uint64_t bytes
= (uint64_t) getUInt16BE(&name->name[CHAPTER_INDEX_BYTES_OFFSET]) << 32;
bytes |= getUInt32BE(&name->name[CHAPTER_INDEX_BYTES_OFFSET + 2]);
return bytes;
}
/**
* Extract the portion of a block name used by the master index.
*
* @param name The block name
*
* @return The master index portion of the block name
**/
static INLINE uint64_t extractMasterIndexBytes(const UdsChunkName *name)
{
return getUInt64BE(&name->name[MASTER_INDEX_BYTES_OFFSET]);
}
/**
* Extract the portion of a block name used for sparse sampling.
*
* @param name The block name
*
* @return The sparse sample portion of the block name
**/
static INLINE uint32_t extractSamplingBytes(const UdsChunkName *name)
{
return getUInt16BE(&name->name[SAMPLE_BYTES_OFFSET]);
}
/**
* For a given block, find the chapter delta list to use
*
* @param name The block name to hash
* @param geometry The geometry to use
*
* @return The chapter delta list where we expect to find the given blockname
**/
static INLINE unsigned int hashToChapterDeltaList(const UdsChunkName *name,
const Geometry *geometry)
{
return (unsigned int) ((extractChapterIndexBytes(name)
>> geometry->chapterAddressBits)
& ((1 << geometry->chapterDeltaListBits) - 1));
}
/**
* For a given block, find the chapter delta address to use
*
* @param name The block name to hash
* @param geometry The geometry to use
*
* @return The chapter delta address to use
**/
static INLINE unsigned int hashToChapterDeltaAddress(const UdsChunkName *name,
const Geometry *geometry)
{
return (unsigned int) (extractChapterIndexBytes(name)
& ((1 << geometry->chapterAddressBits) - 1));
}
/**
* For a given block name, find the slot in the open chapter hash table
* where it is expected to reside.
*
* @param name The block name to hash
* @param slotCount The size of the hash table
*
* @return the record number in the index page where we expect to find
# the given blockname
**/
static INLINE unsigned int nameToHashSlot(const UdsChunkName *name,
unsigned int slotCount)
{
return (unsigned int) (extractChapterIndexBytes(name) % slotCount);
}
/**
* Convert a chunk name to hex to make it more readable.
*
* @param chunkName The chunk name
* @param hexData The resulting hexdata from the given chunk name
* @param hexDataLen The capacity of hexData
*
* @return UDS_SUCCESS,
* or UDS_INVALID_ARGUMENT if hexDataLen
* is too short.
**/
int chunkNameToHex(const UdsChunkName *chunkName,
char *hexData,
size_t hexDataLen)
__attribute__((warn_unused_result));
/**
* Convert chunk data to hex to make it more readable.
*
* @param chunkData The chunk data
* @param hexData The resulting hexdata from the given chunk data
* @param hexDataLen The capacity of hexData
*
* @return UDS_SUCCESS,
* or UDS_INVALID_ARGUMENT if hexDataLen
* is too short.
**/
int chunkDataToHex(const UdsChunkData *chunkData,
char *hexData,
size_t hexDataLen)
__attribute__((warn_unused_result));
/**
* Compute the number of bits required to store a field with the given
* maximum value.
*
* @param maxValue The maximum value of the field
*
* @return the number of bits required
**/
unsigned int computeBits(unsigned int maxValue)
__attribute__((warn_unused_result));
/**
* FOR TESTING. Set the portion of a block name used by the chapter index.
*
* @param name The block name
* @param value The value to store
**/
static INLINE void setChapterIndexBytes(UdsChunkName *name, uint64_t value)
{
// Store the high order bytes, then the low-order bytes
storeUInt16BE(&name->name[CHAPTER_INDEX_BYTES_OFFSET],
(uint16_t)(value >> 32));
storeUInt32BE(&name->name[CHAPTER_INDEX_BYTES_OFFSET + 2],
(uint32_t)value);
}
/**
* FOR TESTING. Set the bits used to find a chapter delta list
*
* @param name The block name
* @param geometry The geometry to use
* @param value The value to store
**/
static INLINE void setChapterDeltaListBits(UdsChunkName *name,
const Geometry *geometry,
uint64_t value)
{
uint64_t deltaAddress = hashToChapterDeltaAddress(name, geometry);
deltaAddress |= value << geometry->chapterAddressBits;
setChapterIndexBytes(name, deltaAddress);
}
/**
* FOR TESTING. Set the portion of a block name used by the master index.
*
* @param name The block name
* @param val The value to store
**/
static INLINE void setMasterIndexBytes(UdsChunkName *name, uint64_t val)
{
storeUInt64BE(&name->name[MASTER_INDEX_BYTES_OFFSET], val);
}
/**
* Set the portion of a block name used for sparse sampling.
*
* @param name The block name
* @param value The value to store
**/
static INLINE void setSamplingBytes(UdsChunkName *name, uint32_t value)
{
storeUInt16BE(&name->name[SAMPLE_BYTES_OFFSET], (uint16_t)value);
}
/**
* Special function wrapper required for compile-time assertions. This
* function will fail to compile if UDS_CHUNK_NAME_SIZE is not an integer
* multiple of 8.
**/
void hashUtilsCompileTimeAssertions(void);
#endif /* HASH_UTILS_H */