Import into DevLib.
[bertos.git] / dt / dnotifier.c
1 /*!
2  * \file
3  * <!--
4  * Copyright 2005 Develer S.r.l. (http://www.develer.com/)
5  * -->
6  *
7  * \version $Id$
8  *
9  * \brief Notifier obj (implementation).
10  *
11  * \version $Id$
12  * \author Bernardo Innocenti <bernie@develer.com>
13  * \author Francesco Sacchi <batt@develer.com>
14  */
15
16 /*#*
17  *#* $Log$
18  *#* Revision 1.1  2005/11/04 18:26:38  bernie
19  *#* Import into DevLib.
20  *#*
21  *#* Revision 1.5  2005/06/09 13:49:22  batt
22  *#* Reformat; correct some comments.
23  *#*
24  *#* Revision 1.4  2005/06/09 13:23:58  batt
25  *#* Add some comments.
26  *#*
27  *#* Revision 1.3  2005/06/08 17:32:33  batt
28  *#* Switch to new messaging system.
29  *#*
30  *#* Revision 1.2  2005/06/06 11:04:12  batt
31  *#* Add some comments.
32  *#*
33  *#* Revision 1.1  2005/05/26 08:32:53  batt
34  *#* Add new Develer widget system :)
35  *#*
36  *#*/
37
38 #include <cfg/debug.h>
39
40 #include <dt/dtag.h>
41 #include <dt/dnotifier.h>
42 #include <mware/list.h>
43
44 /*!
45  * Default update used to notify target: notify all trasparently all
46  * targets in the list.
47  */
48 static void notifier_update(DNotifier *n, dtag_t tag, dval_t val)
49 {
50         dnotify_targets(n, tag, val);
51 }
52
53 /*!
54  * Init.
55  */
56 void notifier_init(DNotifier *n)
57 {
58         // Init instance
59         n->update = notifier_update;
60         LIST_INIT(&n->targets);
61 }
62
63 /*!
64  * Search in the map a tag and a val corresponding to the ones supplied.
65  * If a match is found change them to the corresponding ones in the map.
66  * If map is NULL the filter is trasparent and all messages sent to filter
67  * will be forwarded to its target.
68  */
69 void filter_update(DFilter *f, dtag_t tag, dval_t val)
70 {
71
72         const DFilterMap *map = f->map;
73
74         if (map)
75         {
76                 while (map->src.tag != TAG_END)
77                 {
78                         if ((map->src.tag == tag) && (map->src.val == val))
79                         {
80                                 tag = map->dst.tag;
81                                 val = map->dst.val;
82                                 break;
83                         }
84                         /* TAG_ANY matches anything */
85                         if (map->src.tag == TAG_ANY)
86                                 break;
87                         map++;
88                 }
89
90                 if (map->src.tag != TAG_END)
91                         dnotify(f->target, tag, val);
92         }
93         else
94                 dnotify(f->target, tag, val);
95 }
96
97
98 /*!
99  * Search in the table a tag corresponding to the one supplied and a val
100  * that has at least the mask map supplied bits to one.
101  * If a match is found change them to the corresponding ones in the map.
102  * If map is NULL the filter is trasparent and all messages sent to filter
103  * will be forwarded to its target.
104  */
105 void filter_mask_update(DFilter *f, dtag_t tag, dval_t val)
106 {
107
108         const DFilterMap *map = f->map;
109         dfilter_mask_t mask;
110
111         if (map)
112         {
113                 while (map->src.tag != TAG_END)
114                 {
115                         mask = (dfilter_mask_t) map->src.val;
116                         if ((map->src.tag == tag) && ((mask & (dfilter_mask_t)val) == mask))
117                         {
118                                 tag = map->dst.tag;
119                                 val = map->dst.val;
120                                 break;
121                         }
122                         /* TAG_ANY matches anything */
123                         if (map->src.tag == TAG_ANY)
124                                 break;
125                         map++;
126                 }
127
128
129                 if (map->src.tag != TAG_END)
130                         dnotify(f->target, tag, val);
131         }
132         else
133                 dnotify(f->target, tag, val);
134 }
135
136
137 #define FILTER_MAGIC_ACTIVE 0xAA
138 /*!
139  * Init filter.
140  * If \a masked is true, all the fields value in \a map must be interpreted as a mask of bits.
141  */
142 void filter_init(DFilter *f, const DFilterMap *map, bool masked, DNotifier *source, DNotifier *target)
143 {
144         // Init instance
145         if (masked)
146                 f->update = (update_filter_ptr)filter_mask_update;
147         else
148                 f->update = (update_filter_ptr)filter_update;
149
150         /* set filter map and target */
151         f->map = map;
152         f->target = target;
153
154         /* these ensure that the filter is not inserted in more than one list */
155         ASSERT(f->magic != FILTER_MAGIC_ACTIVE);
156         DB(f->magic = FILTER_MAGIC_ACTIVE;)
157
158         /* Add the filter to source filter list */
159         ADDTAIL(&source->targets, &f->link);
160 }