| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408 |
- /** BEGIN COPYRIGHT BLOCK
- * 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; version 2 of the License.
- *
- * 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., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * In addition, as a special exception, Red Hat, Inc. gives You the additional
- * right to link the code of this Program with code not covered under the GNU
- * General Public License ("Non-GPL Code") and to distribute linked combinations
- * including the two, subject to the limitations in this paragraph. Non-GPL Code
- * permitted under this exception must only link to the code of this Program
- * through those well defined interfaces identified in the file named EXCEPTION
- * found in the source code files (the "Approved Interfaces"). The files of
- * Non-GPL Code may instantiate templates or use macros or inline functions from
- * the Approved Interfaces without causing the resulting work to be covered by
- * the GNU General Public License. Only Red Hat, Inc. may make changes or
- * additions to the list of Approved Interfaces. You must obey the GNU General
- * Public License in all respects for all of the Program code and other code used
- * in conjunction with the Program except the Non-GPL Code covered by this
- * exception. If you modify this file, you may extend this exception to your
- * version of the file, but you are not obligated to do so. If you do not wish to
- * provide this exception without modification, you must delete this exception
- * statement from your version and license this file solely under the GPL without
- * exception.
- *
- *
- * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
- * Copyright (C) 2005 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- #include "base/systems.h"
- #include "netsite.h"
- #include "assert.h"
- #include "libaccess/usi.h"
- /*
- * Description (usiAlloc)
- *
- * This function is used to initialize a USIList_t structure to
- * reference an array of unsigned integers, where the size of the
- * array is specified. The caller is responsible for initializing
- * the specified number of values in the array.
- *
- * Arguments:
- *
- * uilptr - pointer to list head
- * count - number of entries to allocate
- *
- * Returns:
- *
- * If successful, a pointer to the USI_t array now referenced by the
- * list head (uilptr) is returned. An error is indicated by a null
- * return value.
- */
- USI_t * usiAlloc(USIList_t * uilptr, int count)
- {
- /* Is there space already allocated for this list? */
- if (uilptr->uil_size > 0) {
- /* If it's not big enough to hold the desired size, free it */
- if (count > uilptr->uil_size) {
- FREE(uilptr->uil_list);
- UILINIT(uilptr);
- }
- }
- /* Do we need space? */
- if (uilptr->uil_size < count) {
- /* Yes, allocate space for the specified number of values */
- uilptr->uil_list = (USI_t *)MALLOC(sizeof(USI_t) * count);
- if (uilptr->uil_list == 0) {
- /* Error - no memory available */
- uilptr->uil_count = 0;
- return 0;
- }
- uilptr->uil_size = count;
- }
- uilptr->uil_count = count;
- return uilptr->uil_list;
- }
- /*
- * Description (usiInsert)
- *
- * This function is called to insert a specified USI_t value into
- * a given list of USI_t values. The values are maintained in an
- * array, where they are kept in ascending order. Duplicate values
- * are rejected.
- *
- * Arguments:
- *
- * uilptr - pointer to list head
- * usi - value to be inserted
- *
- * Returns:
- *
- * If the specified value is already in the list, zero is returned.
- * If the value is successfully inserted into the list, +1 is
- * returned. An error is indicated by a negative return value.
- */
- int usiInsert(USIList_t * uilptr, USI_t usi)
- {
- int ilow, ihigh, i;
- USI_t * ids;
- ids = uilptr->uil_list;
- /* Binary search for specified group id */
- i = 0;
- for (ilow = 0, ihigh = uilptr->uil_count; ilow != ihigh; ) {
- i = (ilow + ihigh) >> 1;
- if (usi == ids[i]) {
- /* The value is already in the list */
- return 0;
- }
- if (usi > ids[i]) {
- ilow = i + 1;
- }
- else {
- ihigh = i;
- }
- }
- /* Check for empty list */
- if (uilptr->uil_count <= 0) {
- /* Any space allocated for the list yet? */
- if (uilptr->uil_size <= 0) {
- /* No, allocate some initial space */
- ids = (USI_t *) MALLOC(sizeof(USI_t) * 4);
- if (ids == 0) {
- /* Error - no memory available */
- return -1;
- }
- uilptr->uil_size = 4;
- uilptr->uil_list = ids;
- }
- /* Value will be inserted at ilow, which is zero */
- }
- else {
- /*
- * Set ilow to the index at which the specified value
- * should be inserted.
- */
- if (usi > ids[i]) ++i;
- ilow = i;
- /* Is there space for another value? */
- if (uilptr->uil_count >= uilptr->uil_size) {
- /* No, expand the array to hold more values */
- ids = (USI_t *)REALLOC(ids,
- (uilptr->uil_size + 4) * sizeof(USI_t));
- if (ids == 0) {
- /* Error - no memory available */
- return -1;
- }
- uilptr->uil_size += 4;
- uilptr->uil_list = ids;
- }
- /* Copy higher values up */
- for (i = uilptr->uil_count; i > ilow; --i) {
- ids[i] = ids[i-1];
- }
- }
- /* Add the new value */
- ids[ilow] = usi;
- uilptr->uil_count += 1;
- return 1;
- }
- /*
- * Description (usiPresent)
- *
- * This function is called to check whether a specified USI_t value
- * is present in a given list.
- *
- * Arguments:
- *
- * uilptr - pointer to list head
- * usi - value to check for
- *
- * Returns:
- *
- * The return value is the index of the value in the list, plus one,
- * if the value is present in the list, 0 if it is not.
- */
- int usiPresent(USIList_t * uilptr, USI_t usi)
- {
- int ilow, ihigh, i;
- USI_t * ids;
- ids = uilptr->uil_list;
- /* Binary search for specified group id */
- i = 0;
- for (ilow = 0, ihigh = uilptr->uil_count; ilow != ihigh; ) {
- i = (ilow + ihigh) >> 1;
- if (usi == ids[i]) {
- /* The value is in the list */
- return i + 1;
- }
- if (usi > ids[i]) {
- ilow = i + 1;
- }
- else {
- ihigh = i;
- }
- }
- /* The value was not found */
- return 0;
- }
- /*
- * Description (usiRemove)
- *
- * This function is called to remove a specified USI_t value from
- * a given list. The list is compressed when the value is removed.
- *
- * Arguments:
- *
- * uilptr - pointer to list head
- * usi - value to be removed
- *
- * Returns:
- *
- * Returns the value returned by usiPresent(uilptr, usi).
- */
- int usiRemove(USIList_t * uilptr, USI_t usi)
- {
- USI_t * ids;
- int i, j;
- i = usiPresent(uilptr, usi);
- if (i > 0) {
- /* Compress the remaining values */
- ids = uilptr->uil_list;
- for (j = i ; j < uilptr->uil_count; ++j) {
- ids[j-1] = ids[j];
- }
- /* Decrement the number of values and free space if none left */
- if (--uilptr->uil_count <= 0) {
- FREE(uilptr->uil_list);
- UILINIT(uilptr);
- }
- }
- return i;
- }
- /*
- * Description (uilDuplicate)
- *
- * This function is called to make a duplicate of a specified
- * source list, in a given destination list. Any existing list
- * referenced by the destination list head is either overwritten
- * or replaced with a newly allocated list. The values in the
- * source list are copied to the destination. Note that the
- * destination list area may be larger than the source list area
- * on return, i.e. their uil_size values may differ.
- *
- * Arguments:
- *
- * dstptr - pointer to destination list head
- * srcptr - pointer to source list head
- *
- * Returns:
- *
- * The number of elements in the source and destination lists is
- * returned if successful. An error is indicated by a negative
- * return value.
- */
- int uilDuplicate(USIList_t * dstptr, USIList_t * srcptr)
- {
- USI_t * idlist;
- USI_t * srclist;
- int count;
- int i;
- count = srcptr->uil_count;
- srclist = srcptr->uil_list;
- /* Allocate enough space in the destination list */
- idlist = usiAlloc(dstptr, count);
- if ((idlist == 0) && (count > 0)) {
- /* Error - insufficient memory */
- return -1;
- }
- /* Copy source values to destination */
- for (i = 0; i < count; ++i) {
- idlist[i] = srclist[i];
- }
- /* Return number of entries in destination list */
- return count;
- }
- /*
- * Description (uilMerge)
- *
- * This function is called to merge the values in a source list
- * into a destination list. That is, any values in the source
- * list which are not in the destination list will be inserted
- * in it.
- *
- * Arguments:
- *
- * dstptr - pointer to destination list head
- * srcptr - pointer to source list head
- *
- * Returns:
- *
- * The resulting number of elements in the destination list is
- * returned if successful. An error is indicated by a negative
- * return value.
- */
- int uilMerge(USIList_t * dstptr, USIList_t * srcptr)
- {
- USIList_t mglist; /* list head for merged list */
- USI_t * srclist = srcptr->uil_list;
- USI_t * dstlist = dstptr->uil_list;
- int isrc, idst;
- int scnt, dcnt;
- int rv;
- UILINIT(&mglist);
- scnt = srcptr->uil_count;
- dcnt = dstptr->uil_count;
- isrc = 0;
- idst = 0;
- while ((isrc < scnt) && (idst < dcnt)) {
- if (srclist[isrc] >= dstlist[idst]) {
- rv = usiInsert(&mglist, dstlist[idst]);
- if (rv < 0) goto punt;
- if (srclist[isrc] == dstlist[idst]) ++isrc;
- ++idst;
- }
- else if (srclist[isrc] < dstlist[idst]) {
- rv = usiInsert(&mglist, srclist[isrc]);
- if (rv < 0) goto punt;
- ++isrc;
- }
- }
- while (isrc < scnt) {
- rv = usiInsert(&mglist, srclist[isrc]);
- if (rv < 0) goto punt;
- ++isrc;
- }
- while (idst < dcnt) {
- rv = usiInsert(&mglist, dstlist[idst]);
- if (rv < 0) goto punt;
- ++idst;
- }
- UILREPLACE(dstptr, &mglist);
- return dstptr->uil_count;
- punt:
- UILFREE(&mglist);
- return rv;
- }
|