⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ra.c

📁 基于h323协议的软phone
💻 C
📖 第 1 页 / 共 2 页
字号:


/************************************************************************
 * 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 + -