1 /*** seq.h -- generic sequence service
3 * Copyright (C) 2008 Sebastian Freundt
5 * Author: Sebastian Freundt <hroptatyr@sxemacs.org>
7 * This file is part of SXEmacs.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the author nor the names of any contributors
21 * may be used to endorse or promote products derived from this
22 * software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
31 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
33 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
34 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 * A sequence is defined like in maths: A mapping of an somewhat ordered
38 * index set into a target space. The target space hereby is usually the
39 * universe of lisp objects, the index set hereby is usually undefined,
40 * i.e. varying from sequence to sequence, moreover it's possibly infinite
41 * and all we use is the `somewhat ordered' property, so it makes sense to
42 * talk about the `next element' of a sequence.
44 * Sequences have the following operations:
45 * - iter_init - initialise an iterator through the sequence
46 * - iter_fini - finalise an iterator
47 * - iter_next - return the next element of the sequence
49 * Finite sequences have the following operations:
50 * - length - return the length of a sequence
51 * - iter_init - initialise an iterator through the sequence
52 * - iter_fini - finalise an iterator
53 * - iter_next - return the next element of the sequence
54 * - iter_reset - reset the iterator, next iter_next() call will give the
56 * - explode - given a pointer to an object array offload some elements
57 * of the sequence there
61 #ifndef INCLUDED_seq_h_
62 #define INCLUDED_seq_h_
68 #ifdef ALL_DEBUG_FLAGS
70 #define SEQ_DEBUG_FLAG
73 #define __SEQ_DEBUG__(args...) fprintf(stderr, "SEQ " args)
74 #ifndef SEQ_DEBUG_FLAG
75 #define SEQ_DEBUG(args...)
77 #define SEQ_DEBUG(args...) __SEQ_DEBUG__(args)
79 #define SEQ_CRITICAL(args...) __SEQ_DEBUG__("CRITICAL: " args)
81 typedef struct seq_s *seq_t;
82 typedef struct seq_iter_s *seq_iter_t;
83 typedef struct seq_impl_s *seq_impl_t;
85 typedef size_t(*seq_length_f)(const seq_t);
86 typedef void(*seq_iter_init_f)(seq_t, seq_iter_t);
87 typedef void(*seq_iter_next_f)(seq_iter_t, void**);
88 typedef void(*seq_iter_fini_f)(seq_iter_t);
89 typedef void(*seq_iter_reset_f)(seq_iter_t);
90 typedef size_t(*seq_explode_f)(void*restrict[], size_t, const seq_t);
92 /* return the sequence implementation of an object */
93 extern_inline seq_impl_t seq_impl(const void*);
94 /* ... the same, but throw an error if the object has none */
95 extern_inline seq_impl_t seq_impl_err(const void*);
97 extern_inline size_t seq_length(const seq_t);
98 extern_inline bool seq_infinite_p(const seq_t);
99 extern_inline bool seq_empty_p(const seq_t);
101 extern_inline void seq_iter_init(seq_t, seq_iter_t);
102 extern_inline void seq_iter_fini(seq_iter_t);
103 extern_inline void seq_iter_next(seq_iter_t, void**);
104 extern_inline void seq_iter_reset(seq_iter_t);
105 extern_inline size_t seq_explode(void*restrict[], size_t, const seq_t);
107 extern seq_impl_t seq_unsupp;
111 seq_length_f length_f;
112 seq_iter_init_f iter_init_f;
113 seq_iter_fini_f iter_fini_f;
114 seq_iter_next_f iter_next_f;
115 seq_iter_reset_f iter_reset_f;
116 seq_explode_f explode_f;
120 struct lcrecord_header lheader;
122 /* the dual approach */
131 extern seq_impl_t seq_unsupported, seq_empty;
135 extern_inline seq_impl_t
136 seq_impl(const void *obj)
138 if (UNLIKELY(INTP((Lisp_Object)obj) || CHARP((Lisp_Object)obj))) {
140 } else if (UNLIKELY(NILP((Lisp_Object)obj))) {
143 return cat_morphism(obj, cat_mk_seq);
146 extern_inline seq_impl_t
147 seq_impl_err(const void *obj)
149 if (UNLIKELY(INTP((Lisp_Object)obj) || CHARP((Lisp_Object)obj))) {
150 (void)dead_wrong_type_argument(Qsequencep, (Lisp_Object)obj);
152 } else if (UNLIKELY(NILP((Lisp_Object)obj))) {
155 return cat_morphism(obj, cat_mk_seq);
159 seq_length(const seq_t d)
161 /* return the length of a finite sequence
162 * may be applied to any sequence and in case of an infinite one this
163 * returns (size_t)-1 */
164 seq_impl_t si = seq_impl(d);
167 return si->length_f(d);
169 /* is this right here? */
170 return wrong_type_argument(Qsequencep, (Lisp_Object)d);
175 seq_empty_p(const seq_t d)
177 return seq_length(d) == 0;
181 seq_infinite_p(const seq_t d)
183 return seq_length(d) == (size_t)-1;
187 seq_iter_init(seq_t d, seq_iter_t di)
189 seq_impl_t si = seq_impl(d);
192 si->iter_init_f(d, di);
194 /* is this right here? */
195 (void)wrong_type_argument(Qsequencep, (Lisp_Object)d);
201 seq_iter_next(seq_iter_t di, void **elt)
203 seq_impl(di->seq)->iter_next_f(di, elt);
208 seq_iter_fini(seq_iter_t di)
210 seq_impl(di->seq)->iter_fini_f(di);
215 seq_iter_reset(seq_iter_t di)
217 seq_impl(di->seq)->iter_reset_f(di);
222 seq_explode(void *restrict tgt[], size_t ntgt, const seq_t s)
224 /* put up to NTGT values of S into TGT, return the number of put elements */
225 seq_impl_t si = seq_impl(s);
228 return si->explode_f(tgt, ntgt, s);
230 (void)wrong_type_argument(Qsequencep, (const Lisp_Object)s);
236 extern void seq_LTX_init(void);
237 extern void seq_LTX_reinit(void);
238 extern void seq_LTX_deinit(void);
240 #endif /* INCLUDED_seq_h_ */