autoc 1.4 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGES.md +3 -0
- data/README.md +149 -0
- data/cmake/AutoC.cmake +39 -0
- data/lib/autoc/allocators.rb +51 -0
- data/lib/autoc/association.rb +126 -0
- data/lib/autoc/box.rb +311 -0
- data/lib/autoc/cmake.rb +54 -0
- data/lib/autoc/collection.rb +83 -110
- data/lib/autoc/composite.rb +333 -0
- data/lib/autoc/cstring.rb +263 -0
- data/lib/autoc/function.rb +247 -0
- data/lib/autoc/hash_map.rb +328 -0
- data/lib/autoc/hash_set.rb +339 -0
- data/lib/autoc/hashers.rb +102 -0
- data/lib/autoc/list.rb +444 -0
- data/lib/autoc/module.rb +434 -0
- data/lib/autoc/openmp.rb +15 -0
- data/lib/autoc/primitive.rb +27 -0
- data/lib/autoc/ranges.rb +707 -0
- data/lib/autoc/record.rb +247 -0
- data/lib/autoc/scaffold/docs.rb +117 -0
- data/lib/autoc/scaffold/generic_value.rb +86 -0
- data/lib/autoc/scaffold/project.rb +75 -0
- data/lib/autoc/scaffold/test_cstring.rb +113 -0
- data/lib/autoc/scaffold/test_cstring_hash_set.rb +35 -0
- data/lib/autoc/scaffold/test_int_box.rb +22 -0
- data/lib/autoc/scaffold/test_int_hash_set.rb +448 -0
- data/lib/autoc/scaffold/test_int_list.rb +106 -0
- data/lib/autoc/scaffold/test_int_vector.rb +83 -0
- data/lib/autoc/scaffold/test_v2v_hash_map.rb +83 -0
- data/lib/autoc/scaffold/test_value_hash_set.rb +60 -0
- data/lib/autoc/scaffold/test_value_vector.rb +146 -0
- data/{test/test.rb → lib/autoc/scaffold/tests.rb} +179 -158
- data/lib/autoc/scaffold.rb +12 -0
- data/lib/autoc/sequential.rb +99 -0
- data/lib/autoc/set.rb +331 -0
- data/lib/autoc/std.rb +149 -0
- data/lib/autoc/type.rb +93 -531
- data/lib/autoc/vector.rb +290 -0
- data/lib/autoc.rb +4 -35
- metadata +55 -85
- data/.yardopts +0 -4
- data/CHANGES +0 -23
- data/README +0 -28
- data/doc/AutoC/Code.html +0 -523
- data/doc/AutoC/Collection.html +0 -1214
- data/doc/AutoC/HashMap.html +0 -1441
- data/doc/AutoC/HashSet.html +0 -916
- data/doc/AutoC/Iterators/Bidirectional.html +0 -204
- data/doc/AutoC/Iterators/Unidirectional.html +0 -200
- data/doc/AutoC/Iterators.html +0 -126
- data/doc/AutoC/List.html +0 -1039
- data/doc/AutoC/Maps.html +0 -290
- data/doc/AutoC/Module/File.html +0 -415
- data/doc/AutoC/Module/Header.html +0 -437
- data/doc/AutoC/Module/Source.html +0 -707
- data/doc/AutoC/Module.html +0 -948
- data/doc/AutoC/Priority.html +0 -138
- data/doc/AutoC/Queue.html +0 -1172
- data/doc/AutoC/Reference.html +0 -735
- data/doc/AutoC/Sets.html +0 -520
- data/doc/AutoC/String.html +0 -1394
- data/doc/AutoC/TreeMap.html +0 -1565
- data/doc/AutoC/TreeSet.html +0 -1447
- data/doc/AutoC/Type.html +0 -2148
- data/doc/AutoC/UserDefinedType.html +0 -1047
- data/doc/AutoC/Vector.html +0 -987
- data/doc/AutoC.html +0 -331
- data/doc/_index.html +0 -388
- data/doc/class_list.html +0 -51
- data/doc/css/common.css +0 -1
- data/doc/css/full_list.css +0 -58
- data/doc/css/style.css +0 -481
- data/doc/file.CHANGES.html +0 -117
- data/doc/file.README.html +0 -116
- data/doc/file_list.html +0 -61
- data/doc/frames.html +0 -17
- data/doc/index.html +0 -116
- data/doc/js/app.js +0 -243
- data/doc/js/full_list.js +0 -216
- data/doc/js/jquery.js +0 -4
- data/doc/method_list.html +0 -1307
- data/doc/top-level-namespace.html +0 -112
- data/lib/autoc/code.rb +0 -237
- data/lib/autoc/collection/hash_map.rb +0 -385
- data/lib/autoc/collection/hash_set.rb +0 -337
- data/lib/autoc/collection/iterator.rb +0 -39
- data/lib/autoc/collection/list.rb +0 -429
- data/lib/autoc/collection/map.rb +0 -41
- data/lib/autoc/collection/queue.rb +0 -517
- data/lib/autoc/collection/set.rb +0 -134
- data/lib/autoc/collection/tree_map.rb +0 -464
- data/lib/autoc/collection/tree_set.rb +0 -611
- data/lib/autoc/collection/vector.rb +0 -336
- data/lib/autoc/string.rb +0 -492
- data/test/test_auto.c +0 -7141
- data/test/test_auto.h +0 -753
- data/test/test_char_string.rb +0 -270
- data/test/test_int_list.rb +0 -35
- data/test/test_int_tree_set.rb +0 -111
- data/test/test_int_vector.rb +0 -34
- data/test/test_value_hash_map.rb +0 -162
- data/test/test_value_hash_set.rb +0 -173
- data/test/test_value_list.rb +0 -193
- data/test/test_value_queue.rb +0 -275
- data/test/test_value_tree_map.rb +0 -176
- data/test/test_value_tree_set.rb +0 -173
- data/test/test_value_vector.rb +0 -155
- data/test/value.rb +0 -80
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'autoc/std'
|
3
|
+
require 'autoc/module'
|
4
|
+
|
5
|
+
|
6
|
+
module AutoC
|
7
|
+
|
8
|
+
|
9
|
+
# Basic xor-shift incremental hasher
|
10
|
+
class Hasher
|
11
|
+
|
12
|
+
include STD
|
13
|
+
|
14
|
+
include Singleton
|
15
|
+
|
16
|
+
include Entity
|
17
|
+
|
18
|
+
def to_s = :size_t
|
19
|
+
|
20
|
+
def create(hasher) = "#{hasher} = AUTOC_HASHER_SEED"
|
21
|
+
|
22
|
+
def destroy(hasher) = nil
|
23
|
+
|
24
|
+
def update(hasher, value) = "#{hasher} = ((#{hasher} << 1) | (#{hasher} >> (sizeof(#{hasher})*CHAR_BIT - 1))) ^ (#{value})"
|
25
|
+
|
26
|
+
def result(hasher) = hasher
|
27
|
+
|
28
|
+
def initialize = dependencies << STDLIB_H
|
29
|
+
|
30
|
+
def render_forward_declarations(stream)
|
31
|
+
stream << %{
|
32
|
+
#include <limits.h>
|
33
|
+
#include <stddef.h>
|
34
|
+
#ifndef AUTOC_HASHER_SEED /* no seed is specified, using randomly generated one */
|
35
|
+
#define _AUTOC_RANDOMIZE_SEED
|
36
|
+
#define AUTOC_HASHER_SEED _autoc_hasher_seed
|
37
|
+
AUTOC_EXTERN void
|
38
|
+
#ifdef __POCC__
|
39
|
+
__cdecl
|
40
|
+
#endif
|
41
|
+
_autoc_hasher_randomize_seed(void); /* invoke default seed randomizer */
|
42
|
+
AUTOC_EXTERN size_t _autoc_hasher_seed;
|
43
|
+
#elif ~(~AUTOC_HASHER_SEED + 1) == 1 /* if macro value is unspecified on the command line it is implicitly set to 1 */
|
44
|
+
#undef AUTOC_HASHER_SEED
|
45
|
+
#define AUTOC_HASHER_SEED 0 /* set seed's default value */
|
46
|
+
#endif
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
def render_implementation(stream)
|
51
|
+
# Predefined C compiler macros datasheet: https://sourceforge.net/p/predef/wiki/Compilers/
|
52
|
+
stream << %{
|
53
|
+
#ifdef _AUTOC_RANDOMIZE_SEED
|
54
|
+
size_t _autoc_hasher_seed = 0; /* fallback default until _autoc_hasher_randomize_seed() is called */
|
55
|
+
#if defined(__cplusplus)
|
56
|
+
extern "C" void _autoc_hasher_randomize_seed(void);
|
57
|
+
#elif defined(__GNUC__) || defined(__clang__)
|
58
|
+
void _autoc_hasher_randomize_seed(void) __attribute__((__constructor__));
|
59
|
+
#elif defined(__POCC__)
|
60
|
+
#pragma startup _autoc_hasher_randomize_seed
|
61
|
+
#elif defined(_MSC_VER) || defined(__POCC__)
|
62
|
+
#pragma message("WARNING: _autoc_hasher_randomize_seed() will not be called automatically; either call it manually or compile this source as C++ in order to actually yield random seed")
|
63
|
+
#else
|
64
|
+
#warning _autoc_hasher_randomize_seed() will not be be called automatically; either call it manually or compile this source as C++ in order to actually yield random seed
|
65
|
+
#endif
|
66
|
+
#include <time.h>
|
67
|
+
#ifdef __POCC__
|
68
|
+
#include <stdlib.h>
|
69
|
+
#endif
|
70
|
+
void
|
71
|
+
#ifdef __POCC__
|
72
|
+
__cdecl
|
73
|
+
#endif
|
74
|
+
_autoc_hasher_randomize_seed(void) {
|
75
|
+
#if defined(__POCC__)
|
76
|
+
/* Pelles C check comes first as it might set _MSC_VER as well */
|
77
|
+
unsigned r;
|
78
|
+
_rand_s(&r);
|
79
|
+
_autoc_hasher_seed = r;
|
80
|
+
#elif defined(_MSC_VER)
|
81
|
+
unsigned r;
|
82
|
+
rand_s(&r);
|
83
|
+
_autoc_hasher_seed = r;
|
84
|
+
#else
|
85
|
+
srand(time(NULL));
|
86
|
+
_autoc_hasher_seed = rand();
|
87
|
+
#endif
|
88
|
+
}
|
89
|
+
#ifdef __cplusplus
|
90
|
+
static struct _hasher {
|
91
|
+
_hasher() {_autoc_hasher_randomize_seed();}
|
92
|
+
} _hasher;
|
93
|
+
#endif
|
94
|
+
|
95
|
+
#endif
|
96
|
+
}
|
97
|
+
end
|
98
|
+
|
99
|
+
end # Hasher
|
100
|
+
|
101
|
+
|
102
|
+
end
|
data/lib/autoc/list.rb
ADDED
@@ -0,0 +1,444 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
|
4
|
+
require 'autoc/ranges'
|
5
|
+
require 'autoc/sequential'
|
6
|
+
require 'autoc/collection'
|
7
|
+
|
8
|
+
|
9
|
+
module AutoC
|
10
|
+
|
11
|
+
|
12
|
+
using STD::Coercions
|
13
|
+
|
14
|
+
|
15
|
+
# Generator for singly linked collection of elements
|
16
|
+
class List < Collection
|
17
|
+
|
18
|
+
include Sequential
|
19
|
+
|
20
|
+
def _range_class = Range
|
21
|
+
|
22
|
+
def range = @range ||= _range_class.new(self, visibility: visibility)
|
23
|
+
|
24
|
+
attr_reader :_node, :_node_p, :_node_pp
|
25
|
+
|
26
|
+
# maintain_size:
|
27
|
+
# true: managed size field (extra memory consumption)
|
28
|
+
# false: computing #size function (slow, O(N))
|
29
|
+
def initialize(*args, maintain_size: true, **kws)
|
30
|
+
super(*args, **kws)
|
31
|
+
@_node = identifier(:_node, abbreviate: true)
|
32
|
+
@_node_p = _node.lvalue
|
33
|
+
@_node_pp = "#{_node}*".lvalue
|
34
|
+
@maintain_size = maintain_size
|
35
|
+
end
|
36
|
+
|
37
|
+
def maintain_size? = @maintain_size
|
38
|
+
|
39
|
+
def render_interface(stream)
|
40
|
+
stream << %{
|
41
|
+
/** @private */
|
42
|
+
typedef struct #{_node} #{_node};
|
43
|
+
}
|
44
|
+
if public?
|
45
|
+
stream << %{
|
46
|
+
/**
|
47
|
+
#{defgroup}
|
48
|
+
|
49
|
+
@brief Singly linked list of elements of type #{element}
|
50
|
+
|
51
|
+
For iteration over the list elements refer to @ref #{range}.
|
52
|
+
|
53
|
+
@see C++ [std::forward_list<T>](https://en.cppreference.com/w/cpp/container/forward_list)
|
54
|
+
|
55
|
+
@since 2.0
|
56
|
+
*/
|
57
|
+
}
|
58
|
+
stream << %{
|
59
|
+
/**
|
60
|
+
#{ingroup}
|
61
|
+
|
62
|
+
@brief Opaque structure holding state of the list
|
63
|
+
|
64
|
+
@since 2.0
|
65
|
+
*/
|
66
|
+
}
|
67
|
+
else
|
68
|
+
stream << PRIVATE
|
69
|
+
end
|
70
|
+
stream << %{
|
71
|
+
typedef struct {
|
72
|
+
#{_node_p} front; /**< @private */
|
73
|
+
#{'size_t size; /**< @private */' if maintain_size?}
|
74
|
+
} #{signature};
|
75
|
+
/** @private */
|
76
|
+
struct #{_node} {
|
77
|
+
#{element} element;
|
78
|
+
#{_node_p} next;
|
79
|
+
};
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def configure
|
86
|
+
super
|
87
|
+
method(:int, :_replace_first, { target: rvalue, value: element.const_rvalue }, visibility: :internal, constraint:-> { element.copyable? }).configure do
|
88
|
+
# Replace first found element with specified value in-place
|
89
|
+
code %{
|
90
|
+
#{element.lvalue} e = (#{element.lvalue})#{find_first.(target, value)};
|
91
|
+
if(e) {
|
92
|
+
#{element.destroy.('*e') if element.destructible?};
|
93
|
+
#{element.copy.('*e', value)};
|
94
|
+
return 1;
|
95
|
+
} else
|
96
|
+
return 0;
|
97
|
+
}
|
98
|
+
end
|
99
|
+
# Code template for locating the list node satisfying custom equality condition
|
100
|
+
def _locate_node_equal(eq)
|
101
|
+
%{
|
102
|
+
#{_node_p} curr;
|
103
|
+
#{_node_p} prev;
|
104
|
+
assert(target);
|
105
|
+
assert(prev_p);
|
106
|
+
assert(curr_p);
|
107
|
+
prev = NULL;
|
108
|
+
curr = target->front;
|
109
|
+
while(curr) {
|
110
|
+
if(#{eq}) {
|
111
|
+
#ifndef NDEBUG
|
112
|
+
if(prev)
|
113
|
+
assert(prev->next == curr);
|
114
|
+
else
|
115
|
+
assert(target->front == curr);
|
116
|
+
#endif
|
117
|
+
*prev_p = prev;
|
118
|
+
*curr_p = curr;
|
119
|
+
return 1;
|
120
|
+
}
|
121
|
+
prev = curr;
|
122
|
+
curr = curr->next;
|
123
|
+
}
|
124
|
+
return 0;
|
125
|
+
}
|
126
|
+
end
|
127
|
+
method(:int, :_locate_node, { target: const_rvalue, value: element.const_rvalue, prev_p: _node_pp, curr_p: _node_pp }, visibility: :internal, constraint:-> { element.comparable? }).configure do
|
128
|
+
# Locate node satisfying default element equality condition, return this and previous nodes
|
129
|
+
code _locate_node_equal(element.equal.('curr->element', value))
|
130
|
+
end
|
131
|
+
method(:void, :_pop_front, { target: rvalue }, visibility: :internal).configure do
|
132
|
+
# Destroy frontal node but keep the element intact
|
133
|
+
code %{
|
134
|
+
#{_node_p} curr;
|
135
|
+
assert(!#{empty.(target)});
|
136
|
+
curr = target->front; assert(curr);
|
137
|
+
target->front = target->front->next;
|
138
|
+
#{'--target->size;' if maintain_size?}
|
139
|
+
#{memory.free(:curr)};
|
140
|
+
}
|
141
|
+
end
|
142
|
+
method(_node_p, :_pull_node, { target: rvalue }, visibility: :internal).configure do
|
143
|
+
# Cut & return frontal node
|
144
|
+
code %{
|
145
|
+
#{_node_p} curr;
|
146
|
+
assert(!#{empty.(target)});
|
147
|
+
curr = target->front; assert(curr);
|
148
|
+
target->front = curr->next;
|
149
|
+
#{'--target->size;' if maintain_size?}
|
150
|
+
return curr;
|
151
|
+
}
|
152
|
+
end
|
153
|
+
method(:void, :_push_node, { target: rvalue, curr: _node_p }, visibility: :internal).configure do
|
154
|
+
# Push exising node with intact payload
|
155
|
+
code %{
|
156
|
+
assert(target);
|
157
|
+
curr->next = target->front;
|
158
|
+
target->front = curr;
|
159
|
+
#{'++target->size;' if maintain_size?}
|
160
|
+
}
|
161
|
+
end
|
162
|
+
method(element.const_lvalue, :view_front, { target: const_rvalue })
|
163
|
+
method(element, :take_front, { target: const_rvalue }, constraint:-> { element.copyable? })
|
164
|
+
view_front.configure do
|
165
|
+
dependencies << empty
|
166
|
+
inline_code %{
|
167
|
+
assert(!#{empty.(target)});
|
168
|
+
return &(target->front->element);
|
169
|
+
}
|
170
|
+
header %{
|
171
|
+
@brief Get a view of the front element
|
172
|
+
|
173
|
+
@param[in] target list to get element from
|
174
|
+
@return a view of a front element
|
175
|
+
|
176
|
+
This function is used to get a constant reference (in form of the C pointer) to the front value contained in `target`.
|
177
|
+
Refer to @ref #{take_front} to get an independent copy of that element.
|
178
|
+
|
179
|
+
It is generally not safe to bypass the constness and to alter the value in place (although no one prevents to).
|
180
|
+
|
181
|
+
@note List must not be empty (see @ref #{empty}).
|
182
|
+
|
183
|
+
@since 2.0
|
184
|
+
}
|
185
|
+
end
|
186
|
+
take_front.configure do
|
187
|
+
code %{
|
188
|
+
#{element} result;
|
189
|
+
#{element.const_lvalue} e;
|
190
|
+
assert(target);
|
191
|
+
assert(!#{empty.(target)});
|
192
|
+
e = #{view_front.(target)};
|
193
|
+
#{element.copy.(:result, '*e')};
|
194
|
+
return result;
|
195
|
+
}
|
196
|
+
header %{
|
197
|
+
@brief Get front element
|
198
|
+
|
199
|
+
@param[in] target list to get element from
|
200
|
+
@return a *copy* of a front element
|
201
|
+
|
202
|
+
This function is used to get a *copy* of the front value contained in `target`.
|
203
|
+
Refer to @ref #{view_front} to get a view of that element without making an independent copy.
|
204
|
+
|
205
|
+
This function requires the element type to be *copyable* (i.e. to have a well-defined copy operation).
|
206
|
+
|
207
|
+
@note List must not be empty (see @ref #{empty}).
|
208
|
+
|
209
|
+
@since 2.0
|
210
|
+
}
|
211
|
+
end
|
212
|
+
method(element, :pull_front, { target: rvalue }).configure do
|
213
|
+
code %{
|
214
|
+
#{element} result;
|
215
|
+
assert(target);
|
216
|
+
assert(!#{empty.(target)});
|
217
|
+
result = *#{view_front.(target)};
|
218
|
+
#{_pop_front.(target)};
|
219
|
+
return result;
|
220
|
+
}
|
221
|
+
header %{
|
222
|
+
@brief Extract front element
|
223
|
+
|
224
|
+
@param[in] target list to extract element from
|
225
|
+
@return front element
|
226
|
+
|
227
|
+
This function removes front element from the list and returns it.
|
228
|
+
Note that contrary to @ref #{take_front} no copy operation is performed - it is the contained value itself that is returned.
|
229
|
+
|
230
|
+
@note List must not be empty (see @ref #{empty}).
|
231
|
+
|
232
|
+
@since 2.0
|
233
|
+
}
|
234
|
+
end
|
235
|
+
method(:void, :drop_front, { target: rvalue }).configure do
|
236
|
+
if element.destructible?
|
237
|
+
code %{
|
238
|
+
#{element.lvalue} e;
|
239
|
+
assert(target);
|
240
|
+
assert(!#{empty.(target)});
|
241
|
+
e = (#{element.lvalue})#{view_front.(target)};
|
242
|
+
#{element.destroy.('*e')};
|
243
|
+
#{_pop_front.(target)};
|
244
|
+
}
|
245
|
+
else
|
246
|
+
code %{
|
247
|
+
assert(target);
|
248
|
+
assert(!#{empty.(target)});
|
249
|
+
#{_pop_front.(target)};
|
250
|
+
}
|
251
|
+
end
|
252
|
+
header %{
|
253
|
+
@brief Drop front element
|
254
|
+
|
255
|
+
@param[in] target list to drop element from
|
256
|
+
|
257
|
+
This function removes front element from the list and destroys it with the respective destructor.
|
258
|
+
|
259
|
+
@note List must not be empty (see @ref #{empty}).
|
260
|
+
|
261
|
+
@since 2.0
|
262
|
+
}
|
263
|
+
end
|
264
|
+
method(:void, :push_front, { target: rvalue, value: element.const_rvalue }, constraint:-> { element.copyable? }).configure do
|
265
|
+
code %{
|
266
|
+
#{_node_p} curr;
|
267
|
+
assert(target);
|
268
|
+
curr = #{memory.allocate(_node)};
|
269
|
+
curr->next = target->front;
|
270
|
+
target->front = curr;
|
271
|
+
#{'++target->size;' if maintain_size?}
|
272
|
+
#{element.copy.('curr->element', value)};
|
273
|
+
}
|
274
|
+
header %{
|
275
|
+
@brief Put element
|
276
|
+
|
277
|
+
@param[in] target vector to put element into
|
278
|
+
@param[in] value value to put
|
279
|
+
|
280
|
+
This function pushes a *copy* of the specified value to the front position of `target`.
|
281
|
+
It becomes a new front element.
|
282
|
+
|
283
|
+
This function requires the element type to be *copyable* (i.e. to have a well-defined copy operation).
|
284
|
+
|
285
|
+
@since 2.0
|
286
|
+
}
|
287
|
+
end
|
288
|
+
def _remove_first(locator)
|
289
|
+
%{
|
290
|
+
#{_node_p} curr;
|
291
|
+
#{_node_p} prev;
|
292
|
+
assert(target);
|
293
|
+
if(#{locator}) {
|
294
|
+
assert(curr);
|
295
|
+
if(prev) {
|
296
|
+
prev->next = curr->next;
|
297
|
+
} else {
|
298
|
+
target->front = curr->next;
|
299
|
+
}
|
300
|
+
#{element.destroy.('curr->element') if element.destructible?};
|
301
|
+
#{memory.free(:curr)};
|
302
|
+
#{'--target->size;' if maintain_size?}
|
303
|
+
return 1;
|
304
|
+
}
|
305
|
+
return 0;
|
306
|
+
}
|
307
|
+
end
|
308
|
+
method(:int, :remove_first, { target: rvalue, value: element.const_rvalue }, constraint:-> { element.comparable? }).configure do
|
309
|
+
code _remove_first(_locate_node.(target, value, :prev, :curr))
|
310
|
+
header %{
|
311
|
+
@brief Remove element
|
312
|
+
|
313
|
+
@param[in] target list to remove element from
|
314
|
+
@param[in] value value to search in list
|
315
|
+
@return non-zero value on successful removal and zero value otherwise
|
316
|
+
|
317
|
+
This function searches `target` for a first element equal to the specified `value` and removes it from the list.
|
318
|
+
The removed element is destroyed with respective destructor.
|
319
|
+
|
320
|
+
The function return value is non-zero if such element was found and removed and zero value otherwise.
|
321
|
+
|
322
|
+
This function requires the element type to be *comparable* (i.e. to have a well-defined equality operation).
|
323
|
+
|
324
|
+
@since 2.0
|
325
|
+
}
|
326
|
+
end
|
327
|
+
default_create.configure do
|
328
|
+
inline_code %{
|
329
|
+
assert(target);
|
330
|
+
target->front = NULL;
|
331
|
+
#{'target->size = 0;' if maintain_size?}
|
332
|
+
}
|
333
|
+
end
|
334
|
+
destroy.configure do
|
335
|
+
code %{
|
336
|
+
assert(target);
|
337
|
+
while(!#{empty.(target)}) #{drop_front.(target)};
|
338
|
+
}
|
339
|
+
end
|
340
|
+
copy.configure do
|
341
|
+
code %{
|
342
|
+
size_t i;
|
343
|
+
#{range} r;
|
344
|
+
#{element.const_lvalue}* t;
|
345
|
+
assert(target);
|
346
|
+
assert(source);
|
347
|
+
#{default_create.(target)};
|
348
|
+
t = #{memory.allocate(element.const_lvalue, size.(source))};
|
349
|
+
for(i = 0, r = #{range.new.(source)}; !#{range.empty.(:r)}; #{range.pop_front.(:r)}) {
|
350
|
+
t[i++] = #{range.view_front.(:r)};
|
351
|
+
}
|
352
|
+
while(i > 0) #{push_front.(target, '*t[(i--)-1]')}; /* put elements in reverse order since the list itself is a LIFO structure */
|
353
|
+
#{memory.free(:t)};
|
354
|
+
}
|
355
|
+
end
|
356
|
+
empty.configure do
|
357
|
+
inline_code %{
|
358
|
+
assert(target);
|
359
|
+
return target->front == NULL;
|
360
|
+
}
|
361
|
+
end
|
362
|
+
if maintain_size?
|
363
|
+
size.configure do
|
364
|
+
inline_code %{
|
365
|
+
assert(target);
|
366
|
+
return target->size;
|
367
|
+
}
|
368
|
+
end
|
369
|
+
else
|
370
|
+
size.configure do
|
371
|
+
code %{
|
372
|
+
#{range} r;
|
373
|
+
size_t size;
|
374
|
+
assert(target);
|
375
|
+
for(size = 0, r = #{range.new.(target)}; !#{range.empty.(:r)}; ++size, #{range.pop_front.(:r)});
|
376
|
+
return size;
|
377
|
+
}
|
378
|
+
end
|
379
|
+
end
|
380
|
+
end
|
381
|
+
end # List
|
382
|
+
|
383
|
+
|
384
|
+
class List::Range < ForwardRange
|
385
|
+
|
386
|
+
def render_interface(stream)
|
387
|
+
if public?
|
388
|
+
render_type_description(stream)
|
389
|
+
stream << %{
|
390
|
+
/**
|
391
|
+
#{ingroup}
|
392
|
+
@brief Opaque structure holding state of the list's range
|
393
|
+
@since 2.0
|
394
|
+
*/
|
395
|
+
}
|
396
|
+
else
|
397
|
+
stream << PRIVATE
|
398
|
+
end
|
399
|
+
stream << %{
|
400
|
+
typedef struct {
|
401
|
+
#{iterable._node_p} front; /**< @private */
|
402
|
+
} #{signature};
|
403
|
+
}
|
404
|
+
end
|
405
|
+
|
406
|
+
private
|
407
|
+
|
408
|
+
def configure
|
409
|
+
super
|
410
|
+
custom_create.configure do
|
411
|
+
inline_code %{
|
412
|
+
assert(range);
|
413
|
+
assert(iterable);
|
414
|
+
range->front = iterable->front;
|
415
|
+
}
|
416
|
+
end
|
417
|
+
empty.configure do
|
418
|
+
inline_code %{
|
419
|
+
assert(range);
|
420
|
+
return range->front == NULL;
|
421
|
+
}
|
422
|
+
end
|
423
|
+
pop_front.configure do
|
424
|
+
dependencies << empty
|
425
|
+
inline_code %{
|
426
|
+
assert(range);
|
427
|
+
assert(!#{empty.(range)});
|
428
|
+
range->front = range->front->next;
|
429
|
+
}
|
430
|
+
end
|
431
|
+
view_front.configure do
|
432
|
+
dependencies << empty
|
433
|
+
inline_code %{
|
434
|
+
assert(range);
|
435
|
+
assert(!#{empty.(range)});
|
436
|
+
return &range->front->element;
|
437
|
+
}
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
441
|
+
end # List
|
442
|
+
|
443
|
+
|
444
|
+
end
|