Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • cellframe/cellframe-sdk
  • MIKA83/cellframe-sdk
2 results
Show changes
Showing
with 8432 additions and 0 deletions
/*******************************************************************************
fragment.c
Implements fragment classes and objects.
These structures are transparently implemented - with open access/update.
Uses opaque objects to encode generics ...
Author: brian.monahan@hpe.com
(c) Copyright 2017 Hewlett Packard Enterprise Development LP
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "utils.h"
#include "alloc.h"
#include "fragment.h"
/*******************************************************************************
Memory Management
*******************************************************************************/
static MemMgr_t *fragCls_MemMgr = NULL;
static MemMgr_t *fragObj_MemMgr = NULL;
/*******************************************************************************
Static Method prototypes
*******************************************************************************/
// Memory management helper
static void ensureMemMgmt();
static FragCompare_t
fragmentCompare(CompareFn_t posnCompFn,
Posn_t thisLower,
Posn_t thisUpper,
Posn_t otherLower,
Posn_t otherUpper);
/*******************************************************************************
Fragment Class Methods
*******************************************************************************/
//
// Create a new fragment system class (FragCls_t)
// - This provides a coordinated set of related methods:
//
// - Parametric methods:
// posnCompFn : positionPos comparison function
// adjCompFn : adjacency comparison function
// objCombFn : object combination function
// finalObjFn : finalise object function
FragCls_t *new_FC(CompareFn_t posnCompFn, AdjCompareFn_t adjCompFn, CombineFn_t objCombFn, VoidFn_t finalObjFn) {
// ensure that the allocation structures exist ...
ensureMemMgmt();
// check integrity
if (posnCompFn == NULL) {
diagnostic("new_FC : Null position comparison function given");
error_exit();
}
if (adjCompFn == NULL) {
diagnostic("new_FC : Null adjacency comparison function given");
error_exit();
}
if (objCombFn == NULL) {
diagnostic("new_FC : Null object combination function given");
error_exit();
}
// defaults
finalObjFn = (finalObjFn == NULL ? nullVoidFn : finalObjFn);
// allocate new class
FragCls_t *newCls = allocateObject_MM(fragCls_MemMgr);
// set attributes
newCls->posnCompFn = posnCompFn;
newCls->adjCompFn = adjCompFn;
newCls->objCombFn = objCombFn;
newCls->finalObjFn = finalObjFn;
return newCls;
}
// Deallocate fragment class
void deallocate_FC(void *item) {
if (item == NULL) return;
// ensure that the allocation structures exist ...
ensureMemMgmt();
FragCls_t *fragCls = (FragCls_t *)item;
// Nullify object
NULLIFY_OBJ(fragCls, FragCls_t)
// recycle the current fragment object
deallocateObject_MM(fragCls_MemMgr, sizeof(FragCls_t), fragCls);
}
// Clones object
FragCls_t *clone_FC(FragCls_t *fragCls) {
return new_FC(fragCls->posnCompFn, fragCls->adjCompFn, fragCls->objCombFn, fragCls->finalObjFn);
}
/*******************************************************************************
Fragment Object Methods
*******************************************************************************/
// Create a new fragment + value objects
// - note that fragCls should be non-null.
Frag_t *new_Frag(FragCls_t *fragCls, Posn_t lower, Posn_t upper, Object_t value) {
req_NonNull(fragCls);
// ensure that the allocation structures exist ...
ensureMemMgmt();
// allocate new Tree
Frag_t *newObj = allocateObject_MM(fragObj_MemMgr);
// set attributes
newObj->class = fragCls;
newObj->lower = lower;
newObj->upper = upper;
newObj->value = value;
return newObj;
}
// Deallocate fragment object
// - deallocate the frag object
void deallocate_Frag(void *item) {
if (item == NULL) return;
// ensure that the allocation structures exist ...
ensureMemMgmt();
// Cast to appropriate object
Frag_t *fragObj = (Frag_t *)item;
// nullify object
NULLIFY_OBJ(fragObj, Frag_t);
// recycle the current fragment object
deallocateObject_MM(fragObj_MemMgr, sizeof(Frag_t), fragObj);
}
// Deallocate fragment object
// - deallocate the frag object (incl. the value)
void deallocateAll_Frag(void *item) {
if (item == NULL) return;
// ensure that the allocation structures exist ...
ensureMemMgmt();
// Cast to appropriate object
Frag_t *fragObj = (Frag_t *)item;
VoidFn_t finalFn = fragObj->class->finalObjFn;
// Call the finalisation/deallocation function for the object value.
finalFn((void *)fragObj->value);
// nullify object
NULLIFY_OBJ(fragObj, Frag_t);
// recycle the current fragment object
deallocateObject_MM(fragObj_MemMgr, sizeof(Frag_t), fragObj);
}
// Fragment comparisons
FragCompare_t compare_Frag(Frag_t *thisFrag, Frag_t *otherFrag) {
// check for nulls
if (thisFrag == NULL) return FRAGMENT_UNDEF;
if (otherFrag == NULL) return FRAGMENT_UNDEF;
// check consistency of fragment class
if (thisFrag->class != otherFrag->class) return FRAGMENT_UNDEF;
CompareFn_t posnCompFn = thisFrag->class->posnCompFn;
// Assume that: thisLower <= thisUpper
Posn_t thisLower = thisFrag->lower;
Posn_t thisUpper = thisFrag->upper;
// Assume that: otherLower <= otherUpper
Posn_t otherLower = otherFrag->lower;
Posn_t otherUpper = otherFrag->upper;
return fragmentCompare(posnCompFn, thisLower, thisUpper, otherLower, otherUpper);
}
FragCompare_t compareEnds_Frag(FragCls_t *fragCls, Posn_t thisLower, Posn_t thisUpper, Posn_t otherLower, Posn_t otherUpper) {
req_NonNull(fragCls);
req_NonZero(thisLower);
req_NonZero(thisUpper);
req_NonZero(otherLower);
req_NonZero(otherUpper);
CompareFn_t posnCompFn = fragCls->posnCompFn;
return fragmentCompare(posnCompFn, thisLower, thisUpper, otherLower, otherUpper);
}
/*******************************************************************************
Show fragment
*******************************************************************************/
static char showFragmentBuf[LINE_BUFSIZE+1];
// Showing fragments
char *show_Frag(void *item) {
if (item == NULL) return NULL_STR;
Frag_t *curFrag = (Frag_t *)item;
sprintf(showFragmentBuf, "0x%lu = (lower: %i, upper: %i, value: 0x%lu)"
, (Ptr_t)curFrag
, (int)curFrag->lower
, (int)curFrag->upper
, (Object_t)curFrag->value
);
return showFragmentBuf;
}
/*******************************************************************************
Static Method prototypes
*******************************************************************************/
// ensure the allocation of memory management resources
static void ensureMemMgmt() {
if (fragCls_MemMgr == NULL) {
fragCls_MemMgr = new_MM(sizeof(FragCls_t));
fragObj_MemMgr = new_MM(sizeof(Frag_t));
}
}
// fragment comparison code ...
static FragCompare_t fragmentCompare(CompareFn_t posnCompFn,
Posn_t thisLower,
Posn_t thisUpper,
Posn_t otherLower,
Posn_t otherUpper) {
if (posnCompFn(thisLower, otherLower) <= 0) {
// thisLower <= otherLower
if (posnCompFn(otherUpper, thisUpper) <= 0) {
// thisLower <= otherLower <= otherUpper <= thisUpper
return FRAGMENT_CONTAINS;
}
else {
// thisUpper < otherUpper
if (posnCompFn(thisUpper, otherLower) < 0) {
// thisLower <= thisUpper < otherLower <= otherUpper
return FRAGMENT_DISJOINT;
}
else {
// thisLower <= otherLower <= thisUpper < otherUpper
return FRAGMENT_OVERLAPS;
}
}
}
else {
// otherLower < thisLower
if (posnCompFn(thisUpper, otherUpper) <= 0) {
// otherLower < thisLower <= thisUpper <= otherUpper
return FRAGMENT_CONTAINED;
}
else {
// otherUpper < thisUpper
if (posnCompFn(otherUpper, thisLower) < 0) {
// otherLower <= otherUpper < thisLower <= thisUpper
return FRAGMENT_DISJOINT;
}
else {
// otherLower < thisLower <= otherUpper < thisUpper
return FRAGMENT_OVERLAPS;
}
}
}
}
#ifndef __FRAGMENT_H__
#define __FRAGMENT_H__
/*******************************************************************************
fragment.h
Fragment classes and objects
Author: brian.monahan@hpe.com
(c) Copyright 2017 Hewlett Packard Enterprise Development LP
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
#include "utils.h"
/*******************************************************************************
Classes and Types
*******************************************************************************/
// Fragment Objects
typedef struct fragmentObj Frag_t;
// Fragment System Class
// - specifies comparisons
typedef struct fragmentClass FragCls_t;
// Type of value combiners
typedef Object_t (*CombineFn_t) (Object_t objA, Object_t objB);
// Type of adjacency comparison outcomes (AdjData_t)
// - let acf(pa, pb) = ov, where acf is an adjacency comparison function.
// Then: ov is one of these outcome values, as specified below:
typedef enum {
ADJACENCY_UNDEF, // outcome not defined
LESS_THAN_NOT_ADJACENT, // pa < pb and pa is not adjacent to pb
LESS_THAN_ADJACENT, // pa < pb and pa is adjacent to pb
ADJACENCY_EQUAL, // pa == pb
GREATER_THAN_ADJACENT, // pa > pb and pa is adjacent to pb
GREATER_THAN_NOT_ADJACENT // pa > pb and pa is not adjacent to pb
}
AdjData_t;
// Type of adjacency comparison functions
typedef AdjData_t (*AdjCompareFn_t) (Posn_t pa, Posn_t pb);
// Fragment comparisons ... (subsumption of fragments)
typedef enum {
FRAGMENT_UNDEF, // Undefined/unspecified outcome
FRAGMENT_CONTAINED, // specified fragment is contained in other fragment
FRAGMENT_CONTAINS, // specified fragment contains other fragment
FRAGMENT_OVERLAPS, // specified fragment overlaps with other fragment
FRAGMENT_DISJOINT // specified fragment is disjoint from other fragment
}
FragCompare_t;
/*******************************************************************************
Structural definitions for fragmentClass and fragmentObj
- transparent definitions
- allows open access and update for these shared objects
*******************************************************************************/
struct fragmentClass {
CompareFn_t posnCompFn; // position comparison function
AdjCompareFn_t adjCompFn; // adjacency comparison functio
CombineFn_t objCombFn; // object combination function
VoidFn_t finalObjFn; // finalise object function
};
struct fragmentObj {
FragCls_t *class;
Posn_t lower;
Posn_t upper;
Object_t value;
};
/*******************************************************************************
Fragment Class Methods
*******************************************************************************/
//
// Create a new fragment class (FragCls_t)
// - This provides a coordinated set of related methods:
//
// - Parametric methods:
// posnCompFn : position comparison function
// adjCompFn : adjacency comparison function
// objCombFn : object combination function
// finalObjFn : finalise object function
FragCls_t *new_FC(CompareFn_t posnCompFn, AdjCompareFn_t adjCompFn, CombineFn_t objCombFn, VoidFn_t finalObjFn);
// Deallocate fragment class
void deallocate_FC(void *item);
// Clones object
FragCls_t *clone_FC(FragCls_t *fragCls);
/*******************************************************************************
Fragment Object Methods
*******************************************************************************/
// Create new fragment object (Frag_t)
// - Note: explicit fragment class pointer links to data specific operations.
Frag_t *new_Frag(FragCls_t *fragCls, Posn_t lower, Posn_t upper, Object_t value);
// Deallocate fragment object
void deallocate_Frag(void *item); // deallocate the frag object itself
void deallocateAll_Frag(void *item); // deallocate the frag object (incl. the value)
// Fragment comparisons ...
FragCompare_t compare_Frag(Frag_t *thisFrag, Frag_t *otherFrag);
FragCompare_t compareEnds_Frag(FragCls_t *fragCls, Posn_t thisLower, Posn_t thisUpper, Posn_t otherLower, Posn_t otherUpper);
// Showing fragments
char *show_Frag(void *item);
#endif
This diff is collapsed.
#ifndef __FRAGMENT_MAP_H__
#define __FRAGMENT_MAP_H__
/*******************************************************************************
fragmentMap.h
Provides fragment maps e.g. a map from fragments to a space of values.
A fragment is a pair consisting of a fragment and its valuation.
In essence, we have each map M with functional typing: Fragments -> Value
so that:
M = { intv |-> v | intv in S }
The domain of the map is a set of closed fragments, based upon some finite
discrete linearly ordered set of points (e.g. subset of the integers, finite
subset of strings).
A closed fragment of points is characterised by a pair [lower, upper] which
is defined by: { x | lower <= x <= upper }
Note that when upper = lower, then [lower, upper] is the singleton set {x}
where x = lower = upper.
We want to also merge adjacent fragments and therefore combine map values
for _adjacent_ fragments. If VCF is the value combiner operation, then:
{ ... [a, b] |-> v1, [b', c] |=> v2 ... } (where b and b' are adjacent)
Becomes:
{ ... [a,c] |-> (v1 VCF v2) ... }
(An example of "multiset rewriting reduction")
Two fragments are _adjacent_ iff:
A.upper + 1 = B.lower OR B.upper + 1 = A.lower
We can always merge two adjacent fragments to make a larger fragment.
[3, 7] \/ [8, 10] =
[3, 5] \/ [6, 10] = [3, 10]
An fragment map M is said to be _reduced_ when the domain of M is a set of
disjoint, non-adjacent closed fragments.
NOTE: The NULL_KEY is not a valid key here.
Author: brian.monahan@hpe.com
(c) Copyright 2017 Hewlett Packard Enterprise Development LP
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
#include "utils.h"
#include "fragment.h"
/*******************************************************************************
Classes and Types
*******************************************************************************/
typedef enum {
NULL_FRAG_MAP = 180, // Trivial fragment map i.e. single fragment mode.
LINEAR_LIST_FRAG_MAP, // Use Linear List implementation for fragment map
BINARY_TREE_FRAG_MAP // Use Binary Tree implementation for fragment map
}
FragMapKind_t;
// Fragment Maps
typedef struct fragmentMap FragMap_t;
/*******************************************************************************
Fragment Map Methods
*******************************************************************************/
// Create a new fragment map (FragMap_t)
FragMap_t *new_FM(FragCls_t *fragCls, FragMapKind_t fragKind);
// Deallocate fragment map
void deallocate_FM(void *item);
// Add a point mapping to given fragment map
// - Adds the point to the mapping and then reduces the domain set
// by combining with adjacent fragments in the mapping.
// - Returns TRUE if addition was successful, FALSE otherwise.
Boolean_t addPoint_FM(FragMap_t *fragMap, Posn_t point, Object_t value);
// Add a consistent fragment to given fragment map
// - Adds the fragment to the mapping and then reduces the domain set
// by combining with adjacent fragments in the mapping.
// - Returns TRUE if addition was successful, FALSE otherwise.
Boolean_t addFragment_FM(FragMap_t *fragMap, Posn_t lower, Posn_t upper, Object_t value);
// Lookup covering fragment for a given point.
// - This determines the fragment that covers the given point, and returns it.
// - Returns NULL if not found
Frag_t *lookupFragment_FM(FragMap_t *fragMap, Posn_t point);
// Size of fragment map - i.e. number of disjoint fragments
int getSize_FM(FragMap_t *fragMap);
// Get the first fragment
// - Returns NULL if empty
Frag_t *getFirstFragment_FM(FragMap_t *fragMap);
// Enumerate fragment point mappings
// - Checks if map is locked (i.e. being enumerated).
// - Enumerates fragment objects in order.
// - Returns NULL, when completed.
// - Changes are locked out during enumeration.
Boolean_t isLocked_FM(FragMap_t *fragMap); // Checks if map is locked.
Frag_t *start_EnumMap_FM(FragMap_t *fragMap); // Initialises enumeration + locks mapping.
Frag_t *next_EnumMap_FM(FragMap_t *fragMap); // Gets the next fragment element (othwrwise NULL)
void stop_EnumMap_FM(FragMap_t *fragMap); // Stops the enumeration + unlocks mapping.
#endif
/* hashFusion.c
HashFusion Library
Author: brian.monahan@hpe.com
(c) Copyright 2017 Hewlett Packard Enterprise Development LP
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include "utils.h"
#include "alloc.h"
#include "position.h"
#include "linkedList.h"
#include "stringbuffer.h"
#include "bytevector.h"
#include "matrix.h"
#include "fragment.h"
#include "fragmentMap.h"
#include "hashFusion.h"
////////////////////////////////////////////////////////////////////////////////
// Hash Fusion types and structures
////////////////////////////////////////////////////////////////////////////////
struct hashFusion {
CompareFn_t posnCompFn; // Position comparison function
AdjCompareFn_t adjCompFn; // Adjacency comparison function
HFuseAccum_t accumType; // Accumulation type
HashSpec_t hashSpec; // Hash specifier
int dim; // Dimension of matrices (dependant upon hashSpec)
int digestLen; // Length of digest (dependant upon hashSpec)
Digest_t *digest; // Final digest value -- weak reference (NO allocation)
int blockCount; // Current total of blocks
Key_t maxPosition; // Max position
HFuseState_t state; // Current state
FragMap_t *fragments; // Fragment map structure
};
////////////////////////////////////////////////////////////////////////////////
// Memory management
////////////////////////////////////////////////////////////////////////////////
MemMgr_t *hashFusion_MemMgr = NULL;
////////////////////////////////////////////////////////////////////////////////
// Static method prototypes
////////////////////////////////////////////////////////////////////////////////
static void ensureMemMgmt();
// Mapping from to FragMapKind_t
static FragMapKind_t toFragMapKind(HFuseAccum_t accumKind);
// Matrix combination utility
static Object_t matrixCombiner(Object_t a, Object_t b);
// Extract result
static Boolean_t tryExtractResult(HFuse_t *hFuse);
// Show utilities
static void initShowList(StringBuf_t *sBuf, ShowFn_t showFn);
static void showList(HFuse_t *hFuse);
////////////////////////////////////////////////////////////////////////////////
// Methods
////////////////////////////////////////////////////////////////////////////////
// Allocate a new HashFusion object.
//
// Parameters:
// CompareFn_t posnCompFn // Key comparison function
// AdjCompareFn_t adjCompFn // Adjacency comparison function
// HFuseAccum_t hfAccumType // HashFusion accumulation type (specifies method to accumulate)
// HashSpec_t hSpec // Hash function specifier
HFuse_t *new_HF(CompareFn_t posnCompFn, AdjCompareFn_t adjCompFn, HFuseAccum_t hfAccumType, HashSpec_t hSpec) {
// Ensure that the allocation structures exist
ensureMemMgmt();
HFuse_t *newHF = allocateObject_MM(hashFusion_MemMgr);
FragCls_t *fragCls = new_FC(posnCompFn, adjCompFn, matrixCombiner, deallocateMatrix);
FragMapKind_t fragKind = toFragMapKind(hfAccumType);
int digestLen = getDigestLength_DG(hSpec);
newHF->posnCompFn = posnCompFn;
newHF->adjCompFn = adjCompFn;
newHF->accumType = hfAccumType;
newHF->hashSpec = hSpec;
newHF->dim = calcDimension(digestLen); // calculate dimension
newHF->digestLen = digestLen;
newHF->digest = NULL; // weak reference (NO allocation)
newHF->blockCount = 0;
newHF->maxPosition = 0;
newHF->state = Initial_HFuseState;
newHF->fragments = new_FM(fragCls, fragKind);
return newHF;
}
// Deallocate/recycle Hash Fusion object
void deallocate_HF(HFuse_t *hFuse) {
if (hFuse == NULL) return;
// ensure that the allocation structures exist ...
ensureMemMgmt();
// deallocate fragments
deallocate_FM(hFuse->fragments);
// nullify elements
NULLIFY_OBJ(hFuse, HFuse_t);
deallocateObject_MM(hashFusion_MemMgr, sizeof(HFuse_t), hFuse);
}
// Resets the given hash fusion object
// - Giving NULL parameters implies reuse of existing parameters.
void reset_HF(HFuse_t *hFuse, CompareFn_t posnCompFn, AdjCompareFn_t adjCompFn, HFuseAccum_t accumType, HashSpec_t hSpec) {
req_NonNull(hFuse);
// Ensure that the allocation structures exist
ensureMemMgmt();
// Set parameters
posnCompFn = (posnCompFn == NULL ? hFuse->posnCompFn : posnCompFn);
adjCompFn = (adjCompFn == NULL ? hFuse->adjCompFn : adjCompFn);
accumType = (accumType == ZERO_VAL ? hFuse->accumType : accumType);
hSpec = (hSpec == ZERO_VAL ? hFuse->hashSpec : hSpec);
// deallocate fragment map
deallocate_FM(hFuse->fragments);
FragCls_t *fragCls = new_FC(posnCompFn, adjCompFn, matrixCombiner, deallocateMatrix);
FragMapKind_t fragKind = toFragMapKind(accumType);
int digestLen = getDigestLength_DG(hSpec);
hFuse->posnCompFn = posnCompFn;
hFuse->adjCompFn = adjCompFn;
hFuse->accumType = accumType;
hFuse->hashSpec = hSpec;
hFuse->dim = calcDimension(digestLen); // calculate dimension
hFuse->digestLen = digestLen;
hFuse->digest = NULL; // weak ref.
hFuse->blockCount = 0;
hFuse->maxPosition = 0;
hFuse->state = Initial_HFuseState;
}
// Inspect current state ...
HFuseState_t getState_HF(HFuse_t *hFuse) {
req_NonNull(hFuse);
return hFuse->state;
}
// Show current state ...
char *showState_HF(HFuse_t *hFuse) {
req_NonNull(hFuse);
// process current state
switch (hFuse->state) {
case NULL_HFuseState: return "NULL state";
case Initial_HFuseState: return "Initialised";
case Partial_HFuseState: return "Partial";
case Complete_HFuseState: return "Complete";
default:
diagnostic("hashFusion.showState_HF : Unknown state: %i", hFuse->state);
codeError_exit();
}
}
// Gets current accumulation type
HFuseAccum_t getAccumType_HF(HFuse_t *hFuse) {
req_NonNull(hFuse);
return hFuse->accumType;
}
// Gets current Hash Spec
HashSpec_t getHashSpec_HF(HFuse_t *hFuse) {
req_NonNull(hFuse);
return hFuse->hashSpec;
}
// Gets Digest - if defined
// - This clones the mTree's digest object into given digest, dgst.
// - Returns TRUE only if digest was cloned.
Boolean_t getDigest_HF(Digest_t *dgst, HFuse_t *hFuse) {
req_NonNull(dgst);
req_NonNull(hFuse);
if (hFuse->digest == NULL || hFuse->state != Complete_HFuseState) {
return FALSE;
}
else {
clone_DG(dgst, hFuse->digest);
return TRUE;
}
}
// Gets the total number of blocks so far.
int getNumBlocks_HF(HFuse_t *hFuse) {
req_NonNull(hFuse);
return hFuse->blockCount;
}
// Gets the number of fragments ...
int getNumFragments_HF(HFuse_t *hFuse) {
req_NonNull(hFuse);
return getSize_FM(hFuse->fragments);
}
// Show hash fragments info by appending to stringbuffer
// - uses specified show function showFn
// - set indent string
// - set compact display
// - set max length (if positive)
void show_HF(HFuse_t *hFuse, StringBuf_t *sBuf, ShowFn_t showFn) {
req_NonNull(hFuse);
req_NonNull(sBuf);
showFn = (showFn == NULL ? show_Frag : showFn);
initShowList(sBuf, showFn);
showList(hFuse);
}
// show attributes
static char *show_indent = " "; // indent string
static Boolean_t show_compact_display = FALSE;
static int show_max_length = -1;
void setShowIndent_HF(char * indent) {
show_indent = indent;
}
void setShowCompact_HF(Boolean_t isCompact) {
show_compact_display = asBoolean(isCompact);
}
void setShowMaxLength_HF(int maxLength) {
show_max_length = maxLength;
}
////////////////////////////////////////////////////////////////////////////////
// Adding blocks, hashes and fragments
////////////////////////////////////////////////////////////////////////////////
// Calculate hash from data block
Boolean_t calcDataHash_HF(Digest_t *digest, Key_t position, ByteVec_t *dataVec) {
req_NonNull(digest);
req_NonNull(dataVec);
req_Pos(position); // Strictly positive keys ...
// Hash the data and place it in digest
return hashBV_DG(digest, dataVec);
}
// Adds data block into sequence
// - Position is 1-based and runs from 1 to max value K (with no gaps)
// - Returns TRUE if successful
Boolean_t addDataBlock_HF(HFuse_t *hFuse, Key_t position, ByteVec_t *dataVec) {
req_NonNull(hFuse);
req_NonNull(dataVec);
req_Pos(position); // Strictly positive keys ...
// Allocate a temporary digest
HashSpec_t hSpec = hFuse->hashSpec;
int dim = hFuse->dim;
int digestLen = hFuse->digestLen;
Digest_t *tempDigest = new_DG(hSpec);
// Hash the data and place it in digest
if (!hashBV_DG(tempDigest, dataVec)) {
deallocate_DG(tempDigest);
return FALSE;
}
Boolean_t status = addDataHash_HF(hFuse, position, tempDigest);
// deallocate temp. digest object
deallocate_DG(tempDigest);
return status;
}
// Adds data hash into sequence
// - Position is 1-based and runs from 1 to max value K (with no gaps)
// - Returns TRUE if successful
Boolean_t addDataHash_HF(HFuse_t *hFuse, Key_t position, Digest_t *digest) {
return addDataRange_HF(hFuse, position, position, digest);
}
// Adds data hash for range into sequence
// - Position is 1-based and runs from 1 to max value K (with no gaps)
// - Returns TRUE if successful
Boolean_t addDataRange_HF(HFuse_t *hFuse, Key_t lower, Key_t upper, Digest_t *digest) {
req_NonNull(hFuse);
req_NonNull(digest);
req_Pos(lower); // Strictly positive keys ...
req_Pos(upper); // Strictly positive keys ...
int dim = hFuse->dim; // dimension
int digestLen = hFuse->digestLen; // digest length
ByteVec_t *tempBV = allocate_BV(digestLen+1);
// extract hash value into byte vector from the digest ...
if (!getHashValue_DG(digest, tempBV)) {
diagnostic("addDataRange_HF: Digest could not be extracted to bytevector");
codeError_exit();
}
// Allocate fresh matrix of appropriate dimension
Matrix_t *matrix = allocateTriMatrix(dim);
// creating matrix version of hash digest value ...
// - This automatically deals with any padding
insertContent(matrix, tempBV);
// deallocate the temporaries
deallocate_BV(tempBV);
if (lower == upper) {
// Adding a single point ...
if (!addPoint_FM(hFuse->fragments, lower, (Object_t)matrix)) {
return FALSE;
}
}
else {
// Adding range ...
if (!addFragment_FM(hFuse->fragments, lower, upper, (Object_t)matrix)) {
return FALSE;
}
}
// updating blockCount and maxPosition ...
hFuse->blockCount += 1;
hFuse->maxPosition = keyMax(hFuse->posnCompFn, upper, hFuse->maxPosition);
hFuse->state = Partial_HFuseState;
// try to extract result ...
tryExtractResult(hFuse);
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////
// Show functions for enumerated functions:
////////////////////////////////////////////////////////////////////////////////
char *show_HFuseAccum(HFuseAccum_t val) {
switch (val) {
case DIRECT_ACCUM_HF: return "DIRECT_ACCUM_HF";
case LINEAR_LIST_ACCUM_HF: return "LINEAR_LIST_ACCUM_HF";
case TREE_SET_ACCUM_HF: return "TREE_SET_ACCUM_HF";
default:
diagnostic("Unrecognised value (of type HFuseAccum_t): %i", val);
error_exit();
}
}
char *show_HFuseState(HFuseState_t val) {
switch (val) {
case NULL_HFuseState: return "NULL_HFuseState";
case Initial_HFuseState: return "Initial_HFuseState";
case Partial_HFuseState: return "Partial_HFuseStateF";
case Complete_HFuseState: return "Complete_HFuseState";
default:
diagnostic("Unrecognised value (of type HFuseState_t): %i", val);
error_exit();
}
}
////////////////////////////////////////////////////////////////////////////////
// Static methods
////////////////////////////////////////////////////////////////////////////////
static void ensureMemMgmt() {
if (hashFusion_MemMgr == NULL) {
hashFusion_MemMgr = new_MM(sizeof(HFuse_t));
}
}
// Mapping from HFuseAccum_t to FragMapKind_t
static FragMapKind_t toFragMapKind(HFuseAccum_t accumKind) {
switch (accumKind) {
case DIRECT_ACCUM_HF: return LINEAR_LIST_FRAG_MAP;
case LINEAR_LIST_ACCUM_HF: return LINEAR_LIST_FRAG_MAP;
case TREE_SET_ACCUM_HF: return BINARY_TREE_FRAG_MAP;
default: return LINEAR_LIST_FRAG_MAP;
}
}
// Matrix combination utility
static Object_t matrixCombiner(Object_t a, Object_t b) {
Matrix_t *matA = (Matrix_t *)a;
Matrix_t *matB = (Matrix_t *)b;
int dim = getDimension(matA);
Matrix_t *matC = allocateTriMatrix(dim);
multiply(matC, matA, matB);
return (Object_t)matC;
}
// Extract result
static Boolean_t tryExtractResult(HFuse_t *hFuse) {
req_NonNull(hFuse);
if (hFuse->maxPosition == hFuse->blockCount) {
HashSpec_t hSpec = hFuse->hashSpec;
FragMap_t *fragMap = hFuse->fragments;
// Should now have only one element in the fragments list ...
int curLength = getSize_FM(fragMap);
if (curLength != 1) {
diagnostic("hashFusion.addDataBlock_HF: Currently have %i fragments, should instead have only 1 when Complete", curLength);
codeError_exit();
}
// Fetch the top fragment ...
Frag_t *firstFrag = getFirstFragment_FM(fragMap);
Matrix_t *fragMatrix = (Matrix_t *)firstFrag->value;
int digestSize = getDigestLength_DG(hSpec);
ByteVec_t *tempBV = allocate_BV(1+digestSize);
// extracting content into bytevector from matrix
extractContent(tempBV, fragMatrix);
setLength_BV(tempBV, digestSize);
// allocate or reset the digest object.
if (hFuse->digest == NULL) {
hFuse->digest = new_DG(hSpec);
}
else {
reset_DG(hFuse->digest, 0);
}
// transfer hash value to digest ...
if (!setHashValue_DG(hFuse->digest, tempBV)) {
diagnostic("hashFusion.addDataBlock_HF: The operation setHashValue_DG failed for digest");
codeError_exit();
}
// set state to Complete
hFuse->state = Complete_HFuseState;
// finally deallocate temporary bytevector
deallocate_BV(tempBV);
return TRUE;
}
else {
// hard reset of digest ...
deallocate_DG(hFuse->digest);
hFuse->digest = NULL;
return FALSE;
}
}
/*******************************************************************************
Showing Hash Fusion fragments
*******************************************************************************/
static StringBuf_t *curSBuf = NULL;
static ShowFn_t curShowFn = NULL;
static void initShowList(StringBuf_t *sBuf, ShowFn_t showFn) {
req_NonNull(sBuf);
curSBuf = sBuf;
curShowFn = showFn;
}
static void showList(HFuse_t *hFuse) {
req_NonNull(hFuse);
int numFragments = getNumFragments_HF(hFuse);
addItems_SB(curSBuf, "%sHFuse <state:%s, fragments:%i, blockCount:%i, maxPosition:%i, digest:%s>\n"
, show_indent
, showState_HF(hFuse)
, numFragments
, hFuse->blockCount
, hFuse->maxPosition
, showFingerprint_DG(hFuse->digest, 8)
);
if (show_compact_display || numFragments == 0) return;
// Show fragments
addItems_SB(curSBuf, "\n%sFragments (%i):\n", show_indent, numFragments);
int count = 0;
FragMap_t *fragMap = hFuse->fragments;
Frag_t *curFrag = start_EnumMap_FM(fragMap);
while (curFrag != NULL) {
addItems_SB(curSBuf, "%s %i: %s\n", show_indent, count+1, curShowFn(curFrag));
curFrag = next_EnumMap_FM(fragMap);
count += 1;
if (count > 100) {
diagnostic("showList: count exceeded limit %i, Seems to be a loop ...", count);
error_exit();
}
}
addItems_SB(curSBuf, "%sEnd.\n", show_indent);
// check that the actual number of fragments (count) and the calculated number of fragments (numFragments) agree ...
if (count != numFragments) {
print_SB(curSBuf);
diagnostic("showList : NumFragments = %i, actual num. fragments = %i", numFragments, count);
error_exit();
}
//stop_EnumMap_FM(fragMap);
}
#ifndef __HASHFUSION_H__
#define __HASHFUSION_H__
/*******************************************************************************
hashFusion.h
HashFusion Library
Author: brian.monahan@hpe.com
(c) Copyright 2017 Hewlett Packard Enterprise Development LP
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
#include "utils.h"
#include "bytevector.h"
#include "stringbuffer.h"
#include "fragment.h"
#include "hashlib.h"
/*******************************************************************************
Hash Fusion object type
- This corresponds to a Merkle Hash Tree
*******************************************************************************/
typedef struct hashFusion HFuse_t;
/*******************************************************************************
Hash Fusion Accumulation Type
+ Provides implmentation to accumulate hash objects in sequence.
+ Types of accumulation structure:
- Free Form: Accumulate hashes directly in sequence. Effectively combines hashes
as given with no gaps.
- Linear List: Builds a linear list of fragments. Useful for small numbers of
blocks.
- Balanced Binary Tree: Builds a self-balancing tree structure (with O(lg N)
access and insert behaviour). This is a scalable solution suitable for
large files.
*******************************************************************************/
typedef enum {
DIRECT_ACCUM_HF = 100, // Direct accumulation structure (i.e. only accumulate directly at either end).
LINEAR_LIST_ACCUM_HF, // Linear list accumulation structure
TREE_SET_ACCUM_HF // Balanced binary tree accumulation structure
}
HFuseAccum_t;
/*******************************************************************************
Hash Fusion state
*******************************************************************************/
// Hash Fusion state values
// - a complete sequence means there are no missing blocks (i.e. no gaps between 0 and current max position).
// - even if we have a complete sequence, there could still be more input.
//
// Operations cycle: init->partial <-> complete
typedef enum {
NULL_HFuseState = 10, // Not a valid state (i.e. uninitialised)
Initial_HFuseState, // Initial state (empty sequence)
Partial_HFuseState, // Partial state (partial sequence) - in progress/under construction
Complete_HFuseState // Complete state (completed initial sequence, but there could be more input ...)
}
HFuseState_t;
/*******************************************************************************
Methods
*******************************************************************************/
// Allocate a new HashFusion object.
// Parameters:
// CompareFn_t keyCompFn // Key comparison function
// AdjCompareFn_t adjCompFn // Adjacency comparison function
// HFuseAccum_t hfAccumType // HashFusion accumulation type (specifies method to accumulate)
// HashSpec_t hSpec // Hash function specifier
HFuse_t *new_HF(CompareFn_t keyCompFn, AdjCompareFn_t adjCompFn, HFuseAccum_t hfAccumType, HashSpec_t hSpec);
// Deallocate/recycle HashFusion object
void deallocate_HF(HFuse_t *hFuse);
// Resets the given HashFusion object
// - Giving NULL parameters implies reuse of existing parameters.
void reset_HF(HFuse_t *hFuse, CompareFn_t keyCompFn, AdjCompareFn_t adjCompFn, HFuseAccum_t hfAccumType, HashSpec_t hSpec);
// Inspect current state ...
HFuseState_t getState_HF(HFuse_t *hFuse);
// Show current state ...
char *showState_HF(HFuse_t *hFuse);
// Gets current accumulation type
HFuseAccum_t getAccumType_HF(HFuse_t *hFuse);
// Gets current Hash Spec
HashSpec_t getHashSpec_HF(HFuse_t *hFuse);
// Gets Digest - if defined
// - This clones the digest object into given digest, dgst.
// - Returns TRUE only if digest was cloned.
Boolean_t getDigest_HF(Digest_t *dgst, HFuse_t *hFuse);
// Gets the total number of blocks so far.
int getNumBlocks_HF(HFuse_t *hFuse);
// Gets the number of fragments ...
int getNumFragments_HF(HFuse_t *hFuse);
////////////////////////////////////////////////////////////////////////////////
// Hash joining ...
////////////////////////////////////////////////////////////////////////////////
// Calculate hash from data block
Boolean_t calcDataHash_HF(Digest_t *digest, Key_t position, ByteVec_t *dataVec);
// Adds data block into sequence
// - Position is 1-based and runs from 1 to max value K (with no gaps)
// - Returns TRUE if successful
Boolean_t addDataBlock_HF(HFuse_t *hFuse, Key_t position, ByteVec_t *dataVec);
// Adds data hash into sequence
// - Position is 1-based and runs from 1 to max value K (with no gaps)
// - Returns TRUE if successful
Boolean_t addDataHash_HF(HFuse_t *hFuse, Key_t position, Digest_t *digest);
// Adds data hash for range into sequence
// - Position is 1-based and runs from 1 to max value K (with no gaps)
// - Returns TRUE if successful
Boolean_t addDataRange_HF(HFuse_t *hFuse, Key_t lower, Key_t upper, Digest_t *digest);
////////////////////////////////////////////////////////////////////////////////
// Show functions
////////////////////////////////////////////////////////////////////////////////
// Show hash fragments info by appending to stringbuffer
// - uses specified show function showFn
// - set indent string
// - set compact display
// - set max length (if positive)
void show_HF(HFuse_t *hFuse, StringBuf_t *sbuf, ShowFn_t showFn);
void setShowIndent_HF(char * indent);
void setShowCompact_HF(Boolean_t isCompact);
void setShowMaxLength_HF(int maxLength);
// Show functions for enumerated functions:
char *show_HFuseAccum(HFuseAccum_t val);
char *show_HFuseState(HFuseState_t val);
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#ifndef __INDEX_MAP_H__
#define __INDEX_MAP_H__
#include "utils.h"
#include "bytevector.h"
#include "stringbuffer.h"
/*******************************************************************************
linearMap.h
Linear indexed maps
- Encodes a mapping as a linear linked list.
- Keys are encoded as unsigned longs (e.g. can contain void *)
- Key comparison is UNORDERED and is literal equality.
Author: brian.monahan@hpe.com
(c) Copyright 2017 Hewlett Packard Enterprise Development LP
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
typedef struct linearMap LinearMap_t;
// prototypes
// generates new LinearMap_t
LinearMap_t *new_LM();
// Deallocate linear map
void deallocate_LM(void *item);
// Set object finaliser function ...
// - No finalisation happens for data items unless this is set.
void setFinaliser_LM(LinearMap_t *lmap, VoidFn_t finalObjFn);
// Looks up entry in map using the key
void *getEntry_LM(LinearMap_t *lmap, unsigned long key);
// Adds/updates entry under key to given linearMap
void addEntry_LM(LinearMap_t *lmap, unsigned long key, void *entry);
// Removes existing entry in given linearMap under key
// - returns the object removed (if key exists)
void *removeEntry_LM(LinearMap_t *lmap, unsigned long key);
// Calculate size
int size_LM(LinearMap_t *lmap);
// Clear existing map
void clear_LM(LinearMap_t *lmap);
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.