1 /*** category.h -- categorial view on objects, this is NOT OO
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.
38 #ifndef INCLUDED_category_h_
39 #define INCLUDED_category_h_
43 enum cat_morphism_kind_e {
45 cat_mk_lc = 0, /* whether or not lcrecord header is used */
48 cat_mk_aseq, /* associative seqs */
49 cat_mk_aset, /* associative sets aka dicts */
50 number_of_cat_morphism_kinds,
53 typedef struct cat_morphism_s *cat_morphism_t;
54 typedef enum cat_morphism_kind_e cat_morphism_kind_t;
56 extern_inline bool __bit_set_p(int number, char bit);
57 extern_inline char __nbits_right_of(int number, char bit);
58 extern_inline void *cat_morphism(const void*, cat_morphism_kind_t);
59 extern_inline void *const*cat_morphisms(const void*);
60 extern cat_morphism_t morphisms;
63 /* a double lookup approach
64 * this is the complete list of morphisms (views) that an object can have */
65 struct cat_morphism_s {
73 struct __cat_morphism_lrec_s {
74 struct lrecord_header lh;
78 struct __cat_morphism_lcrec_s {
79 struct lcrecord_header lch;
85 __bit_set_p(int number, char bit)
87 /* return whether bit BIT is set in NUMBER
89 * the right most bit has bit number 0 */
90 return ((1<<bit) & number) != 0;
93 #if defined HAVE_ASM_EAX && defined HAVE_ASM_CL && \
94 defined HAVE_ASM_ADCB && defined HAVE_ASM_SARL
96 __nbits_right_of(int number, char bit)
98 /* return the number of set bits in NUMBER right of BIT
100 * bit count starts at 0 and on the right */
101 /* we just stuff `BIT' into CNT which goes to cx */
102 register char cnt = bit;
105 #if !defined HAVE_ASM_RETVAL_IN_EBX
106 " pushl %%ebx /* save EBX ([nmsk]) */\n"
107 #endif /* HAVE_ASM_RETVAL_IN_EBX */
108 /* initialise AX directly */
110 " sall %[cnt], %%eax /* CL has value of BIT */\n"
112 " andl %%eax, %[nmsk] /* nmsk <- 1<<bit - 1*/\n"
113 " xorb %[cnt], %[cnt] /* cnt <- 0 */\n"
116 " sarl $1, %[nmsk] /* shift right and */\n"
117 " adcb $0, %[cnt] /* add 1 if carry was set*/\n"
119 " sarl $1, %[nmsk] /* shift right and */\n"
120 " adcb $0, %[cnt] /* add 1 if carry was set*/\n"
122 " sarl $1, %[nmsk] /* shift right and */\n"
123 " adcb $0, %[cnt] /* add 1 if carry was set*/\n"
125 " sarl $1, %[nmsk] /* shift right and */\n"
126 /* maybe %[nmsk] is zero meanwhile, check for it and
129 " adcb $0, %[cnt] /* add 1 if carry was set*/\n"
131 " sarl $1, %[nmsk] /* shift right and */\n"
132 " adcb $0, %[cnt] /* add 1 if carry was set*/\n"
134 " sarl $1, %[nmsk] /* shift right and */\n"
135 /* maybe %[nmsk] is zero meanwhile, check for it and
138 " adcb $0, %[cnt] /* add 1 if carry was set*/\n"
140 " sarl $1, %[nmsk] /* shift right and */\n"
141 /* maybe %[nmsk] is zero meanwhile, check for it and
144 " adcb $0, %[cnt] /* add 1 if carry was set*/\n"
146 " sarl $1, %[nmsk] /* shift right and */\n"
148 " adcb $0, %[cnt] /* add 1 if carry was set*/\n"
149 #if !defined HAVE_ASM_RETVAL_IN_EBX
150 " popl %%ebx /* restore EBX */\n"
152 : [cnt] "+c" (cnt) /* <- bit is in here */
153 : [nmsk] "d" (number)
157 #else /* !all the above */
159 __nbits_right_of(int number, char bit)
161 register char cnt = 0;
163 for(n = number & ((1<<bit)-1); n ; n >>= 1)
169 #if 1 /* using the global shit */
170 extern_inline void*const*
171 cat_morphisms(const void *obj)
173 /* returns a pointer to the array of implementations or
174 * NULL if there are none */
175 if (((const struct lrecord_header*)obj)->morphisms & cat_mk_lc) {
176 return &((const struct __cat_morphism_lcrec_s*)obj)->foo;
178 return &((const struct __cat_morphism_lrec_s*)obj)->foo;
183 cat_morphism(const void *obj, cat_morphism_kind_t kind)
185 unsigned int flags = ((const struct lrecord_header*)obj)->morphisms;
187 if (!__bit_set_p(flags, kind)) {
188 int type = ((const struct lrecord_header*)obj)->type;
191 return morphisms[type].seq_impl;
193 return morphisms[type].set_impl;
195 return morphisms[type].aseq_impl;
197 return morphisms[type].aset_impl;
198 /* list them all here */
201 case number_of_cat_morphism_kinds:
206 void *const*mph = cat_morphisms(obj);
207 return mph[__nbits_right_of(flags, kind)-(flags&1)];
211 #endif /* INCLUDED_category_h_ */