📄 ra.c
字号:
/************************************************************************
* raDelete
* purpose: Delete an element from RA
* input : raH - Handle of the RA object
* output : delElem - Element in RA to delete
* return : Negative value on failure
************************************************************************/
int raDelete(IN HRA raH, IN RAElement delElem)
{
raHeader* ra = (raHeader *)raH;
int location;
if (delElem == NULL) return RV_ERROR_UNKNOWN;
location = raGetByPtr(raH, (void*)delElem);
if (location < 0 || location > ra->maxNumOfElements) return RV_ERROR_UNKNOWN;
if (ra->threadSafe)
RvLockGet(&ra->lock);
if (raElemIsVacant(raH, location) == RV_TRUE)
{
RvLogExcep(&ra->log,
(&ra->log, "raDelete (%s): %d already deleted or was never used", ra->name, location));
if (ra->threadSafe)
RvLockRelease(&ra->lock);
return RV_ERROR_UNINITIALIZED;
}
/* Add the element to the vacant list */
ra->curNumOfElements--;
#if defined(RV_RA_SUPPORT_WORKING_SET)
if (ra->firstVacantElement == NULL)
{
/* We don't have a free list -> this element is the only vacant one */
ra->firstVacantElement = delElem;
}
if (ra->workingSetElement != NULL)
{
vacantNode* prev = ((vacantNode *)(ra->workingSetElement))->prev;
if (prev != NULL)
prev->next = (vacantNode *)delElem;
else
ra->firstVacantElement = delElem;
((vacantNode *)delElem)->prev = prev;
((vacantNode *)(ra->workingSetElement))->prev = (vacantNode *)delElem;
((vacantNode *)delElem)->next = (vacantNode *)(ra->workingSetElement);
if (ra->workingSetDistance == ra->workingSetSize)
ra->workingSetElement = delElem;
else
ra->workingSetDistance++;
}
else
{
((vacantNode *)delElem)->prev = NULL;
((vacantNode *)delElem)->next = NULL;
ra->workingSetElement = delElem;
ra->workingSetDistance = 0;
}
#else
((vacantNode *)delElem)->next = NULL;
((vacantNode *)delElem)->nodeIndex = location;
if (ra->lastVacantElement != NULL)
((vacantNode *)ra->lastVacantElement)->next = (vacantNode *)delElem;
else
{
/* ra->lastVacantElement==NULL means that ra->firstVacantElement is also
equal to NULL, so after this delete location just only one element
will be in this RA, in such situation both ra->firstVacantElement &
ra->lastVacantElement should point to the deleted element
*/
ra->firstVacantElement = delElem;
}
ra->lastVacantElement = delElem;
#endif
((vacantNode*)delElem)->nodeIndex = location;
setBitFalse(BIT_VECTOR(ra), location); /* make it free */
RvLogInfo(&ra->log,
(&ra->log, "raDelete (%s): %d current elements, Deleted 0x%p, location %d", ra->name, ra->curNumOfElements, delElem, location));
if (ra->threadSafe)
RvLockRelease(&ra->lock);
return RV_OK;
}
/************************************************************************
* raDeleteLocation
* purpose: Delete an element from RA by its location
* input : raH - Handle of the RA object
* output : location - Location of the element in RA
* return : Negative value on failure
************************************************************************/
int raDeleteLocation(IN HRA raH, IN int location)
{
raHeader* ra = (raHeader *)raH;
RAElement deletedElement;
#if 0
#ifdef RV_RA_DEBUG
/* todo: if we're going to change rtGet() to accept only valid parameters */
/* Some validity checks for debug mode */
if (ra == NULL) return RV_ERROR_UNKNOWN;
if (location < 0 || location > ra->maxNumOfElements)
{
RvLogExcep(&ra->log,
(&ra->log, "raDeleteLocation (%s): Bad location %d [0-%d]", ra->name, location, ra->maxNumOfElements));
return RV_ERROR_UNKNOWN;
}
if (raElemIsVacant(raH, location) == RV_TRUE)
{
RvLogExcep(&ra->log,
(&ra->log, "raDeleteLocation (%s): Element %d already vacant", ra->name, location));
return RV_ERROR_UNKNOWN;
}
#endif
#endif
if (location < 0 || location > ra->maxNumOfElements) return RV_ERROR_UNKNOWN;
if (raElemIsVacant(raH, location) == RV_TRUE) return RV_ERROR_UNKNOWN;
deletedElement = (RAElement)RV_RA_ELEM_DATA(ra, location);
return raDelete(raH, deletedElement);
}
#ifdef RV_RA_DEBUG
/************************************************************************
* raGet
* purpose: Get the pointer to an RA element by its location
* input : raH - Handle of the RA object
* output : location - Location of the element in RA
* return : Pointer to the RA element
* In release mode, no checks are done for the validity or the
* vacancy of the location.
************************************************************************/
RAElement raGet(IN HRA raH, IN int location)
{
raHeader* ra = (raHeader *)raH;
if (ra == NULL) return NULL;
if ((location < 0) || (unsigned)location >= (unsigned)(ra->maxNumOfElements))
{
#if 1
/* todo: if we're going to change rtGet() to accept only valid parameters */
RvLogExcep(&ra->log,
(&ra->log, "raGet (%s): Bad location %d [0-%d]", ra->name, location, ra->maxNumOfElements));
#endif
return NULL;
}
if (raElemIsVacant(raH, location) == RV_TRUE)
{
RvLogExcep(&ra->log,
(&ra->log, "raGet (%s): Element %d is vacant", ra->name, location));
return NULL;
}
return (RAElement)RV_RA_ELEM_DATA(raH, location);
}
#endif /* RV_RA_DEBUG */
/************************************************************************
* raGetByPtr
* purpose: Get the location of an RA element by its element pointer
* input : raH - Handle of the RA object
* output : ptr - Pointer to the RA element's value
* return : Location of the element on success
* Negative value on failure
************************************************************************/
int raGetByPtr(IN HRA raH, IN void *ptr)
{
raHeader *ra = (raHeader *)raH;
int location;
int position;
#ifdef RV_RA_DEBUG
/* Make sure the given pointer is a valid element */
if (!ra) return RV_ERROR_UNKNOWN;
if (((char *)ptr < (char *)(ra->arrayLocation)) ||
((char *)ptr > (char *)(ra->arrayLocation) + ra->maxNumOfElements*(ra->sizeofElement)))
{
RvLogExcep(&ra->log,
(&ra->log, "raGetByPtr (%s): Pointer 0x%p out of bounds [0x%p-0x%p]",
ra->name, (RvUint32)ptr, (RvUint32)ra->arrayLocation,
(RvUint32)((char *)(ra->arrayLocation) + ra->maxNumOfElements*(ra->sizeofElement))));
return RV_ERROR_UNKNOWN;
}
#endif
/* Calculate the location of the element */
location = (int)((RvUint8 *)ptr - ra->arrayLocation);
#ifdef RV_RA_DEBUG
/* Make sure the pointer is aligned properly */
if (location % ra->sizeofElement != 0)
{ /* alignment */
RvLogExcep(&ra->log,
(&ra->log, "raGetByPtr (%s): Pointer 0x%p not aligned", ra->name, (RvUint32)ptr));
return RV_ERROR_UNKNOWN;
}
#endif
position = location/(ra->sizeofElement);
#ifdef RV_RA_DEBUG
/* Make sure element is not vacant */
if (raElemIsVacant(raH, position))
{
RvLogExcep(&ra->log,
(&ra->log, "raGetByPtr (%s): Element %d id vacant", ra->name, position));
return RV_ERROR_UNKNOWN;
}
#endif
return position;
}
/************************************************************************
* raElemIsVacant
* purpose: Check if an element is vacant inside RA or not
* input : raH - Handle of the RA object
* location - Location of RA element to check
* output : none
* return : RV_TRUE if element is vacant
* RV_FALSE if element is used
* Negative value on failure
************************************************************************/
int raElemIsVacant(
IN HRA raH,
IN int location)
{
raHeader *ra = (raHeader *)raH;
if (!ra || location<0 || location>ra->maxNumOfElements) return RV_ERROR_UNKNOWN;
return ((getBit((BIT_VECTOR(ra)), (location))) != 0) ? (RV_FALSE):(RV_TRUE);
}
/************************************************************************
* raGetName
* purpose: Get the name of the RA object
* input : raH - Handle of the RA object
* output : none
* return : Name of the RA
************************************************************************/
const char* raGetName(IN HRA raH)
{
raHeader *ra = (raHeader *)raH;
return (const char *)(ra->name);
}
/************************************************************************
* raGetNext
* purpose: Get the next used element in RA.
* This function can be used to implement search or "doall"
* functions on RA.
* input : raH - Handle of the RA object
* cur - Current RA location whose next we're looking for
* If negative, then emaGetNext() will return the first
* used element.
* output : none
* return : Location of the next used element on success
* Negative value when no more used elements are left
************************************************************************/
int raGetNext(
IN HRA raH,
IN int cur)
{
raHeader* ra = (raHeader *)raH;
int i;
if (cur < 0)
i = 0;
else
i = cur + 1;
if (i >= ra->maxNumOfElements) return RV_ERROR_UNKNOWN; /* out of bounds */
while ((i < ra->maxNumOfElements) && raElemIsVacant(raH, i))
i++;
if (i < ra->maxNumOfElements)
return i;
else
return RV_ERROR_UNKNOWN;
}
/************************************************************************
* raGetStatistics
* purpose: Get statistics information about RA.
* input : raH - Handle of the RA object
* output : stats - Statistics information
* return : Non-negative value on success
* Negative value on failure
************************************************************************/
int raGetStatistics(IN HRA raH, OUT RvRaStatistics* stats)
{
raHeader* ra = (raHeader *)raH;
if (ra == NULL) return RV_ERROR_UNKNOWN;
stats->cur = ra->curNumOfElements;
stats->maxUsage = ra->maxUsage;
stats->max = ra->maxNumOfElements;
return 0;
}
/* todo: continue from here */
/* Desc: returns current number of elements.
*/
int
raCurSize(HRA raH)
{
raHeader *ra = (raHeader *)raH;
if (!raH) return RV_ERROR_UNKNOWN;
return ra->curNumOfElements;
}
/* Desc: returns number of elements that can be added to array.
*/
int
raFreeSize(HRA raH)
{
if (!raH) return RV_ERROR_UNKNOWN;
return ((raHeader *)raH)->maxNumOfElements -
((raHeader *)raH)->curNumOfElements;
}
/* Desc: returns maximum number of elements.
*/
int
raMaxSize(HRA raH)
{
if (!raH) return RV_ERROR_UNKNOWN;
return ((raHeader *)raH)->maxNumOfElements;
}
int /* Maximum usage of array */
raMaxUsage(HRA raH)
{
if (!raH) return RV_ERROR_UNKNOWN;
return ((raHeader *)raH)->maxUsage;
}
/* returns size of element */
int
raElemSize(HRA raH)
{
if (!raH) return RV_ERROR_UNKNOWN;
return ((raHeader *)raH)->sizeofElement;
}
RAECompare
raFCompare(HRA raH)
{
if (!raH) return NULL;
return ((raHeader *)raH)->compare;
}
/* Desc: find element by key.
Returns: location of element or RV_ERROR_UNKNOWN.
*/
int
raFind(HRA raH, void *param)
{
raHeader *ra = (raHeader *)raH;
int i;
if (!ra) return RV_ERROR_UNKNOWN;
for (i=0; i<ra->maxNumOfElements; i++)
if (!raElemIsVacant(raH, i)) {
if ((ra->compare && ra->compare((RAElement)RV_RA_ELEM_DATA(ra, i), param)) ||
RV_RA_ELEM_DATA(ra, i) == param) /* address comparison if no compare fuction */
return i;
}
return RV_ERROR_UNKNOWN;
}
int
raCompare(HRA raH, RAECompare compare, void *param)
{
raHeader *ra = (raHeader *)raH;
int i;
/*if (!ra) return RV_ERROR_UNKNOWN;*/
for (i=0; i<ra->maxNumOfElements; i++)
if (!raElemIsVacant(raH, i)) {
if ((compare && compare((RAElement)RV_RA_ELEM_DATA(ra, i), param)) ||
RV_RA_ELEM_DATA(ra, i) == param) /* address comparison if no compare fuction */
return i;
}
return RV_ERROR_UNKNOWN;
}
#ifdef __cplusplus
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -