usi.cpp 8.1 KB

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