Mercurial > hg > octave-shane > gnulib-hg
annotate lib/gl_array_oset.c @ 6976:c77399b5682d
Ordered set data type implemented by an array.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Mon, 17 Jul 2006 11:28:35 +0000 |
parents | |
children | 1c4ed7637c24 |
rev | line source |
---|---|
6976
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
1 /* Ordered set data type implemented by an array. |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
2 Copyright (C) 2006 Free Software Foundation, Inc. |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
3 Written by Bruno Haible <bruno@clisp.org>, 2006. |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
4 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
5 This program is free software; you can redistribute it and/or modify |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
6 it under the terms of the GNU General Public License as published by |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
7 the Free Software Foundation; either version 2, or (at your option) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
8 any later version. |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
9 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
10 This program is distributed in the hope that it will be useful, |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
11 but WITHOUT ANY WARRANTY; without even the implied warranty of |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
13 GNU General Public License for more details. |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
14 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
15 You should have received a copy of the GNU General Public License |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
16 along with this program; if not, write to the Free Software Foundation, |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
18 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
19 #ifdef HAVE_CONFIG_H |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
20 # include <config.h> |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
21 #endif |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
22 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
23 /* Specification. */ |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
24 #include "gl_array_oset.h" |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
25 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
26 #include <stdlib.h> |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
27 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
28 #include "xalloc.h" |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
29 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
30 /* Checked size_t computations. */ |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
31 #include "xsize.h" |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
32 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
33 /* -------------------------- gl_oset_t Data Type -------------------------- */ |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
34 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
35 /* Concrete gl_oset_impl type, valid for this file only. */ |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
36 struct gl_oset_impl |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
37 { |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
38 struct gl_oset_impl_base base; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
39 /* An array of ALLOCATED elements, of which the first COUNT are used. |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
40 0 <= COUNT <= ALLOCATED. */ |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
41 const void **elements; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
42 size_t count; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
43 size_t allocated; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
44 }; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
45 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
46 static gl_oset_t |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
47 gl_array_create_empty (gl_oset_implementation_t implementation, |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
48 gl_setelement_compar_fn compar_fn) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
49 { |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
50 struct gl_oset_impl *set = |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
51 (struct gl_oset_impl *) xmalloc (sizeof (struct gl_oset_impl)); |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
52 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
53 set->base.vtable = implementation; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
54 set->base.compar_fn = compar_fn; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
55 set->elements = NULL; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
56 set->count = 0; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
57 set->allocated = 0; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
58 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
59 return set; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
60 } |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
61 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
62 static size_t |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
63 gl_array_size (gl_oset_t set) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
64 { |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
65 return set->count; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
66 } |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
67 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
68 static size_t |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
69 gl_array_indexof (gl_oset_t set, const void *elt) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
70 { |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
71 size_t count = set->count; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
72 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
73 if (count > 0) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
74 { |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
75 gl_setelement_compar_fn compar = set->base.compar_fn; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
76 size_t low = 0; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
77 size_t high = count; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
78 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
79 /* At each loop iteration, low < high; for indices < low the values |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
80 are smaller than ELT; for indices >= high the values are greater |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
81 than ELT. So, if the element occurs in the list, is at |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
82 low <= position < high. */ |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
83 do |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
84 { |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
85 size_t mid = low + (high - low) / 2; /* low <= mid < high */ |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
86 int cmp = (compar != NULL |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
87 ? compar (set->elements[mid], elt) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
88 : (set->elements[mid] > elt ? 1 : |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
89 set->elements[mid] < elt ? -1 : 0)); |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
90 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
91 if (cmp < 0) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
92 low = mid + 1; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
93 else if (cmp > 0) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
94 high = mid; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
95 else /* cmp == 0 */ |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
96 /* We have an element equal to ELT at index MID. */ |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
97 return mid; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
98 } |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
99 while (low < high); |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
100 } |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
101 return (size_t)(-1); |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
102 } |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
103 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
104 static bool |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
105 gl_array_search (gl_oset_t set, const void *elt) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
106 { |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
107 return gl_array_indexof (set, elt) != (size_t)(-1); |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
108 } |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
109 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
110 /* Ensure that set->allocated > set->count. */ |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
111 static void |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
112 grow (gl_oset_t set) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
113 { |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
114 size_t new_allocated; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
115 size_t memory_size; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
116 const void **memory; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
117 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
118 new_allocated = xtimes (set->allocated, 2); |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
119 new_allocated = xsum (new_allocated, 1); |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
120 memory_size = xtimes (new_allocated, sizeof (const void *)); |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
121 if (size_overflow_p (memory_size)) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
122 /* Overflow, would lead to out of memory. */ |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
123 xalloc_die (); |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
124 memory = (const void **) xrealloc (set->elements, memory_size); |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
125 if (memory == NULL) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
126 /* Out of memory. */ |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
127 xalloc_die (); |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
128 set->elements = memory; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
129 set->allocated = new_allocated; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
130 } |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
131 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
132 /* Add the given element ELT at the given position, |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
133 0 <= position <= gl_oset_size (set). */ |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
134 static inline void |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
135 gl_array_add_at (gl_oset_t set, size_t position, const void *elt) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
136 { |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
137 size_t count = set->count; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
138 const void **elements; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
139 size_t i; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
140 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
141 if (count == set->allocated) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
142 grow (set); |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
143 elements = set->elements; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
144 for (i = count; i > position; i--) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
145 elements[i] = elements[i - 1]; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
146 elements[position] = elt; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
147 set->count = count + 1; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
148 } |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
149 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
150 /* Remove the element at the given position, |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
151 0 <= position < gl_oset_size (set). */ |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
152 static inline void |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
153 gl_array_remove_at (gl_oset_t set, size_t position) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
154 { |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
155 size_t count = set->count; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
156 const void **elements; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
157 size_t i; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
158 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
159 elements = set->elements; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
160 for (i = position + 1; i < count; i++) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
161 elements[i - 1] = elements[i]; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
162 set->count = count - 1; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
163 } |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
164 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
165 static bool |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
166 gl_array_add (gl_oset_t set, const void *elt) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
167 { |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
168 size_t count = set->count; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
169 size_t low = 0; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
170 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
171 if (count > 0) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
172 { |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
173 gl_setelement_compar_fn compar = set->base.compar_fn; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
174 size_t high = count; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
175 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
176 /* At each loop iteration, low < high; for indices < low the values |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
177 are smaller than ELT; for indices >= high the values are greater |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
178 than ELT. So, if the element occurs in the list, is at |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
179 low <= position < high. */ |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
180 do |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
181 { |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
182 size_t mid = low + (high - low) / 2; /* low <= mid < high */ |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
183 int cmp = (compar != NULL |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
184 ? compar (set->elements[mid], elt) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
185 : (set->elements[mid] > elt ? 1 : |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
186 set->elements[mid] < elt ? -1 : 0)); |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
187 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
188 if (cmp < 0) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
189 low = mid + 1; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
190 else if (cmp > 0) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
191 high = mid; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
192 else /* cmp == 0 */ |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
193 return false; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
194 } |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
195 while (low < high); |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
196 } |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
197 gl_array_add_at (set, low, elt); |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
198 return true; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
199 } |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
200 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
201 static bool |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
202 gl_array_remove (gl_oset_t set, const void *elt) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
203 { |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
204 size_t index = gl_array_indexof (set, elt); |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
205 if (index != (size_t)(-1)) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
206 { |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
207 gl_array_remove_at (set, index); |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
208 return true; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
209 } |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
210 else |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
211 return false; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
212 } |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
213 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
214 static void |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
215 gl_array_free (gl_oset_t set) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
216 { |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
217 if (set->elements != NULL) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
218 free (set->elements); |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
219 free (set); |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
220 } |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
221 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
222 /* --------------------- gl_oset_iterator_t Data Type --------------------- */ |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
223 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
224 static gl_oset_iterator_t |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
225 gl_array_iterator (gl_oset_t set) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
226 { |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
227 gl_oset_iterator_t result; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
228 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
229 result.vtable = set->base.vtable; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
230 result.set = set; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
231 result.count = set->count; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
232 result.p = set->elements + 0; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
233 result.q = set->elements + set->count; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
234 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
235 return result; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
236 } |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
237 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
238 static bool |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
239 gl_array_iterator_next (gl_oset_iterator_t *iterator, const void **eltp) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
240 { |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
241 gl_oset_t set = iterator->set; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
242 if (iterator->count != set->count) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
243 { |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
244 if (iterator->count != set->count + 1) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
245 /* Concurrent modifications were done on the set. */ |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
246 abort (); |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
247 /* The last returned element was removed. */ |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
248 iterator->count--; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
249 iterator->p--; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
250 iterator->q--; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
251 } |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
252 if (iterator->p < iterator->q) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
253 { |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
254 const void **p = (const void **) iterator->p; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
255 *eltp = *p; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
256 iterator->p = p + 1; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
257 return true; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
258 } |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
259 else |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
260 return false; |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
261 } |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
262 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
263 static void |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
264 gl_array_iterator_free (gl_oset_iterator_t *iterator) |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
265 { |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
266 } |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
267 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
268 |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
269 const struct gl_oset_implementation gl_array_oset_implementation = |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
270 { |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
271 gl_array_create_empty, |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
272 gl_array_size, |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
273 gl_array_search, |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
274 gl_array_add, |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
275 gl_array_remove, |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
276 gl_array_free, |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
277 gl_array_iterator, |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
278 gl_array_iterator_next, |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
279 gl_array_iterator_free |
c77399b5682d
Ordered set data type implemented by an array.
Bruno Haible <bruno@clisp.org>
parents:
diff
changeset
|
280 }; |