1
0

usi.cpp 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. #ifdef HAVE_CONFIG_H
  39. # include <config.h>
  40. #endif
  41. #include "base/systems.h"
  42. #include "netsite.h"
  43. #include "assert.h"
  44. #include "libaccess/usi.h"
  45. /*
  46. * Description (usiAlloc)
  47. *
  48. * This function is used to initialize a USIList_t structure to
  49. * reference an array of unsigned integers, where the size of the
  50. * array is specified. The caller is responsible for initializing
  51. * the specified number of values in the array.
  52. *
  53. * Arguments:
  54. *
  55. * uilptr - pointer to list head
  56. * count - number of entries to allocate
  57. *
  58. * Returns:
  59. *
  60. * If successful, a pointer to the USI_t array now referenced by the
  61. * list head (uilptr) is returned. An error is indicated by a null
  62. * return value.
  63. */
  64. USI_t * usiAlloc(USIList_t * uilptr, int count)
  65. {
  66. /* Is there space already allocated for this list? */
  67. if (uilptr->uil_size > 0) {
  68. /* If it's not big enough to hold the desired size, free it */
  69. if (count > uilptr->uil_size) {
  70. FREE(uilptr->uil_list);
  71. UILINIT(uilptr);
  72. }
  73. }
  74. /* Do we need space? */
  75. if (uilptr->uil_size < count) {
  76. /* Yes, allocate space for the specified number of values */
  77. uilptr->uil_list = (USI_t *)MALLOC(sizeof(USI_t) * count);
  78. if (uilptr->uil_list == 0) {
  79. /* Error - no memory available */
  80. uilptr->uil_count = 0;
  81. return 0;
  82. }
  83. uilptr->uil_size = count;
  84. }
  85. uilptr->uil_count = count;
  86. return uilptr->uil_list;
  87. }
  88. /*
  89. * Description (usiInsert)
  90. *
  91. * This function is called to insert a specified USI_t value into
  92. * a given list of USI_t values. The values are maintained in an
  93. * array, where they are kept in ascending order. Duplicate values
  94. * are rejected.
  95. *
  96. * Arguments:
  97. *
  98. * uilptr - pointer to list head
  99. * usi - value to be inserted
  100. *
  101. * Returns:
  102. *
  103. * If the specified value is already in the list, zero is returned.
  104. * If the value is successfully inserted into the list, +1 is
  105. * returned. An error is indicated by a negative return value.
  106. */
  107. int usiInsert(USIList_t * uilptr, USI_t usi)
  108. {
  109. int ilow, ihigh, i;
  110. USI_t * ids;
  111. ids = uilptr->uil_list;
  112. /* Binary search for specified group id */
  113. i = 0;
  114. for (ilow = 0, ihigh = uilptr->uil_count; ilow != ihigh; ) {
  115. i = (ilow + ihigh) >> 1;
  116. if (usi == ids[i]) {
  117. /* The value is already in the list */
  118. return 0;
  119. }
  120. if (usi > ids[i]) {
  121. ilow = i + 1;
  122. }
  123. else {
  124. ihigh = i;
  125. }
  126. }
  127. /* Check for empty list */
  128. if (uilptr->uil_count <= 0) {
  129. /* Any space allocated for the list yet? */
  130. if (uilptr->uil_size <= 0) {
  131. /* No, allocate some initial space */
  132. ids = (USI_t *) MALLOC(sizeof(USI_t) * 4);
  133. if (ids == 0) {
  134. /* Error - no memory available */
  135. return -1;
  136. }
  137. uilptr->uil_size = 4;
  138. uilptr->uil_list = ids;
  139. }
  140. /* Value will be inserted at ilow, which is zero */
  141. }
  142. else {
  143. /*
  144. * Set ilow to the index at which the specified value
  145. * should be inserted.
  146. */
  147. if (usi > ids[i]) ++i;
  148. ilow = i;
  149. /* Is there space for another value? */
  150. if (uilptr->uil_count >= uilptr->uil_size) {
  151. /* No, expand the array to hold more values */
  152. ids = (USI_t *)REALLOC(ids,
  153. (uilptr->uil_size + 4) * sizeof(USI_t));
  154. if (ids == 0) {
  155. /* Error - no memory available */
  156. return -1;
  157. }
  158. uilptr->uil_size += 4;
  159. uilptr->uil_list = ids;
  160. }
  161. /* Copy higher values up */
  162. for (i = uilptr->uil_count; i > ilow; --i) {
  163. ids[i] = ids[i-1];
  164. }
  165. }
  166. /* Add the new value */
  167. ids[ilow] = usi;
  168. uilptr->uil_count += 1;
  169. return 1;
  170. }
  171. /*
  172. * Description (usiPresent)
  173. *
  174. * This function is called to check whether a specified USI_t value
  175. * is present in a given list.
  176. *
  177. * Arguments:
  178. *
  179. * uilptr - pointer to list head
  180. * usi - value to check for
  181. *
  182. * Returns:
  183. *
  184. * The return value is the index of the value in the list, plus one,
  185. * if the value is present in the list, 0 if it is not.
  186. */
  187. int usiPresent(USIList_t * uilptr, USI_t usi)
  188. {
  189. int ilow, ihigh, i;
  190. USI_t * ids;
  191. ids = uilptr->uil_list;
  192. /* Binary search for specified group id */
  193. i = 0;
  194. for (ilow = 0, ihigh = uilptr->uil_count; ilow != ihigh; ) {
  195. i = (ilow + ihigh) >> 1;
  196. if (usi == ids[i]) {
  197. /* The value is in the list */
  198. return i + 1;
  199. }
  200. if (usi > ids[i]) {
  201. ilow = i + 1;
  202. }
  203. else {
  204. ihigh = i;
  205. }
  206. }
  207. /* The value was not found */
  208. return 0;
  209. }
  210. /*
  211. * Description (usiRemove)
  212. *
  213. * This function is called to remove a specified USI_t value from
  214. * a given list. The list is compressed when the value is removed.
  215. *
  216. * Arguments:
  217. *
  218. * uilptr - pointer to list head
  219. * usi - value to be removed
  220. *
  221. * Returns:
  222. *
  223. * Returns the value returned by usiPresent(uilptr, usi).
  224. */
  225. int usiRemove(USIList_t * uilptr, USI_t usi)
  226. {
  227. USI_t * ids;
  228. int i, j;
  229. i = usiPresent(uilptr, usi);
  230. if (i > 0) {
  231. /* Compress the remaining values */
  232. ids = uilptr->uil_list;
  233. for (j = i ; j < uilptr->uil_count; ++j) {
  234. ids[j-1] = ids[j];
  235. }
  236. /* Decrement the number of values and free space if none left */
  237. if (--uilptr->uil_count <= 0) {
  238. FREE(uilptr->uil_list);
  239. UILINIT(uilptr);
  240. }
  241. }
  242. return i;
  243. }
  244. /*
  245. * Description (uilDuplicate)
  246. *
  247. * This function is called to make a duplicate of a specified
  248. * source list, in a given destination list. Any existing list
  249. * referenced by the destination list head is either overwritten
  250. * or replaced with a newly allocated list. The values in the
  251. * source list are copied to the destination. Note that the
  252. * destination list area may be larger than the source list area
  253. * on return, i.e. their uil_size values may differ.
  254. *
  255. * Arguments:
  256. *
  257. * dstptr - pointer to destination list head
  258. * srcptr - pointer to source list head
  259. *
  260. * Returns:
  261. *
  262. * The number of elements in the source and destination lists is
  263. * returned if successful. An error is indicated by a negative
  264. * return value.
  265. */
  266. int uilDuplicate(USIList_t * dstptr, USIList_t * srcptr)
  267. {
  268. USI_t * idlist;
  269. USI_t * srclist;
  270. int count;
  271. int i;
  272. count = srcptr->uil_count;
  273. srclist = srcptr->uil_list;
  274. /* Allocate enough space in the destination list */
  275. idlist = usiAlloc(dstptr, count);
  276. if ((idlist == 0) && (count > 0)) {
  277. /* Error - insufficient memory */
  278. return -1;
  279. }
  280. /* Copy source values to destination */
  281. for (i = 0; i < count; ++i) {
  282. idlist[i] = srclist[i];
  283. }
  284. /* Return number of entries in destination list */
  285. return count;
  286. }
  287. /*
  288. * Description (uilMerge)
  289. *
  290. * This function is called to merge the values in a source list
  291. * into a destination list. That is, any values in the source
  292. * list which are not in the destination list will be inserted
  293. * in it.
  294. *
  295. * Arguments:
  296. *
  297. * dstptr - pointer to destination list head
  298. * srcptr - pointer to source list head
  299. *
  300. * Returns:
  301. *
  302. * The resulting number of elements in the destination list is
  303. * returned if successful. An error is indicated by a negative
  304. * return value.
  305. */
  306. int uilMerge(USIList_t * dstptr, USIList_t * srcptr)
  307. {
  308. USIList_t mglist; /* list head for merged list */
  309. USI_t * srclist = srcptr->uil_list;
  310. USI_t * dstlist = dstptr->uil_list;
  311. int isrc, idst;
  312. int scnt, dcnt;
  313. int rv;
  314. UILINIT(&mglist);
  315. scnt = srcptr->uil_count;
  316. dcnt = dstptr->uil_count;
  317. isrc = 0;
  318. idst = 0;
  319. while ((isrc < scnt) && (idst < dcnt)) {
  320. if (srclist[isrc] >= dstlist[idst]) {
  321. rv = usiInsert(&mglist, dstlist[idst]);
  322. if (rv < 0) goto punt;
  323. if (srclist[isrc] == dstlist[idst]) ++isrc;
  324. ++idst;
  325. }
  326. else if (srclist[isrc] < dstlist[idst]) {
  327. rv = usiInsert(&mglist, srclist[isrc]);
  328. if (rv < 0) goto punt;
  329. ++isrc;
  330. }
  331. }
  332. while (isrc < scnt) {
  333. rv = usiInsert(&mglist, srclist[isrc]);
  334. if (rv < 0) goto punt;
  335. ++isrc;
  336. }
  337. while (idst < dcnt) {
  338. rv = usiInsert(&mglist, dstlist[idst]);
  339. if (rv < 0) goto punt;
  340. ++idst;
  341. }
  342. UILREPLACE(dstptr, &mglist);
  343. return dstptr->uil_count;
  344. punt:
  345. UILFREE(&mglist);
  346. return rv;
  347. }