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