2 // Copyright (C) 2008 Tim Blechmann
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; see the file COPYING. If not, write to
16 // the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 // Boston, MA 02111-1307, USA.
19 #ifndef OSC_RESPONDER_HPP
20 #define OSC_RESPONDER_HPP
25 #include "branch_hints.hpp"
27 #include <boost/tuple/tuple.hpp>
29 #include "osc/OscReceivedElements.h"
38 virtual ~osc_responder()
41 virtual void run(osc::ReceivedMessageArgumentIterator begin
,
42 osc::ReceivedMessageArgumentIterator
const & end
) = 0;
48 typedef std::string string
;
49 typedef std::size_t size_t;
50 typedef std::multimap
<string
, osc_responder
*> responder_map_t
;
53 static bool is_pattern(const char * pattern
)
57 if (unlikely(*pattern
== 0))
59 if (unlikely((*pattern
== '?') or (*pattern
== '*')))
65 static unsigned int first_pattern_char(const char * pattern
)
67 assert(is_pattern(pattern
));
72 if (unlikely((*pattern
== '?') or (*pattern
== '*')))
80 static bool match_pattern(const char * pattern
, const char * address
)
82 const char pc
= *pattern
;
83 const char ac
= *address
;
85 if ((pc
== 0) and (ac
== 0))
88 if ((pc
== 0) or (ac
== 0))
92 return match_pattern(++pattern
, ++address
);
98 if (match_pattern(pattern
+1, address
+1))
102 return *(pattern
+1) == 0;
109 return match_pattern(++pattern
, ++address
);
112 void add_responder(string
const & address
, osc_responder
* resp
)
114 responder_map
.insert(std::make_pair(address
, resp
));
117 void remove_responder(string
const & address
, osc_responder
* resp
)
119 assert(exists(responder_map
, address
));
121 responder_map_t::iterator it
, end
;
122 boost::tie(it
, end
) = responder_map
.equal_range(address
);
124 for(; it
!= end
; ++it
)
126 if (it
->second
== resp
)
128 responder_map
.erase(it
);
135 void handle_packet(const char * data
, size_t length
)
139 handle_bundle(data
, length
);
141 handle_message(data
, length
);
145 void handle_message(const char * data
, size_t length
)
147 osc::ReceivedMessage
msg(osc::ReceivedPacket(data
, length
));
148 handle_message(msg
.AddressPattern(), msg
.ArgumentsBegin(), msg
.ArgumentsEnd());
151 void handle_bundle(const char * data
, size_t length
)
153 osc::ReceivedBundle
bundle(osc::ReceivedPacket(data
, length
));
154 handle_bundle(bundle
.ElementsBegin(), bundle
.ElementsEnd());
157 void handle_bundle(osc::ReceivedBundleElementIterator
const & begin
,
158 osc::ReceivedBundleElementIterator
const & end
)
160 for (osc::ReceivedBundleElementIterator it
= begin
; it
!= end
; ++it
)
164 osc::ReceivedBundle
bundle(*it
);
165 handle_bundle(bundle
.ElementsBegin(), bundle
.ElementsEnd());
169 osc::ReceivedMessage
msg(*it
);
170 handle_message(msg
.AddressPattern(), msg
.ArgumentsBegin(), msg
.ArgumentsEnd());
175 void handle_message(char const * pattern
, osc::ReceivedMessageArgumentIterator
const & begin
,
176 osc::ReceivedMessageArgumentIterator
const & end
)
178 if (is_pattern(pattern
))
179 handle_pattern(pattern
, begin
, end
);
181 handle_address(pattern
, begin
, end
);
185 void handle_pattern(const char * pattern
, osc::ReceivedMessageArgumentIterator
const & begin
,
186 osc::ReceivedMessageArgumentIterator
const & end
)
188 responder_map_t::iterator it
;
189 const unsigned int pattern_begin
= first_pattern_char(pattern
);
191 const string
pattern_root(pattern
, pattern_begin
);
193 it
= responder_map
.lower_bound(pattern_root
);
195 for(; it
!= responder_map
.end(); ++it
)
197 if (match_pattern(pattern
, it
->first
.c_str()))
199 osc_responder
* resp
= it
->second
;
200 resp
->run(begin
, end
);
204 if (it
->first
.compare(0, pattern_begin
, pattern_root
))
209 void handle_address(const char * address
, osc::ReceivedMessageArgumentIterator
const & begin
,
210 osc::ReceivedMessageArgumentIterator
const & end
)
212 responder_map_t::iterator it
, it_end
;
213 boost::tie(it
, it_end
) = responder_map
.equal_range(address
);
215 for(; it
!= it_end
; ++it
)
217 osc_responder
* resp
= it
->second
;
218 resp
->run(begin
, end
);
222 responder_map_t responder_map
;
225 } /* namespace nova */
227 #endif /* OSC_RESPONDER_HPP */