signal-caster.cpp 4.64 KB
Newer Older
1
2
3
4
// -*- c++-mode -*-
// Copyright 2010 François Bleibel Thomas Moulard, Olivier Stasse
//
// This file is part of dynamic-graph.
5
6
7
// dynamic-graph is free software:
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
8
//
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27
28
29
30
31
32
33

#include <dynamic-graph/signal-caster.h>
#include <dynamic-graph/dynamic-graph-api.h>
#include <exception>
#include <boost/lambda/bind.hpp>
#include <string>
#include <sstream>
#include <algorithm>
34
#include <dynamic-graph/exception-signal.h>
35

Thomas Moulard's avatar
Thomas Moulard committed
36
37
#include <dynamic-graph/linear-algebra.h>

38
39
40
namespace dynamicgraph
{

Thomas Moulard's avatar
Thomas Moulard committed
41
  SignalCaster::SignalCaster ()
42
43
  {}

Thomas Moulard's avatar
Thomas Moulard committed
44
  SignalCaster::~SignalCaster ()
45
46
  {}

47
48
49
50
51
52
  void SignalCaster::destroy()
  {
    delete instance_;
    instance_ = 0;
  }

53
54
55
56
57
58
  void
  SignalCaster::registerCast (const std::type_info& type,
			      SignalCaster::displayer_type displayer,
			      SignalCaster::caster_type caster,
			      SignalCaster::tracer_type tracer)
  {
Thomas Moulard's avatar
Thomas Moulard committed
59
    if (existsCast (type))
60
      {
Thomas Moulard's avatar
Thomas Moulard committed
61
62
	// If type name has already been registered for same type, do not throw.
	if (type_info_[type.name()] != &type)
florent's avatar
florent committed
63
	  {
Thomas Moulard's avatar
Thomas Moulard committed
64
65
66
67
68
69
70
71
72
73
74
75
	    std::string typeName(type.name());
	    std::ostringstream os;
	    os << "cast already registered for typename " << typeName << "\n"
	       << "and types differ: " << &type << " != "
	       << type_info_[type.name()]
	       << ".\n"
	       << "A possible reason is that the dynamic"
	       << " library defining this type\n"
	       << "has been loaded several times, defining different symbols"
	       << " for the same type.";
	    throw ExceptionSignal(ExceptionSignal::GENERIC,
				  os.str());
florent's avatar
florent committed
76
	  }
77
      }
Thomas Moulard's avatar
Thomas Moulard committed
78
79
    functions_[type.name()] = cast_functions_type(displayer,caster, tracer);
    type_info_[type.name()] = &type;
80
81
82
83
84
  }

  void
  SignalCaster::unregisterCast (const std::type_info& type)
  {
Thomas Moulard's avatar
Thomas Moulard committed
85
    size_t n = functions_.erase(type.name ());
86
87
88
89
90
91
92
93
    if (0 == n) // erase did not find element
      // TODO: throw Cast not registered exception
      throw ExceptionSignal(ExceptionSignal::GENERIC);
  }

  bool
  SignalCaster::existsCast (const std::type_info& type) const
  {
Thomas Moulard's avatar
Thomas Moulard committed
94
    return functions_.find (type.name ()) != functions_.end ();
95
96
97
98
99
100
101
102
  }

  SignalCaster::cast_functions_type&
  SignalCaster::getCast (const std::string& type_name)
  {
    std::map<std::string, cast_functions_type>::iterator it =
      functions_.find(type_name);

Thomas Moulard's avatar
Thomas Moulard committed
103
    if (it == functions_.end ())
104
      //TODO: throw "cast not registered" exception
Nicolas Mansard's avatar
Nicolas Mansard committed
105
      throw ExceptionSignal(ExceptionSignal::BAD_CAST, "Cast not registered");
106
107
    return it->second;
  }
108

109
110
  void SignalCaster::disp (const boost::any& object, std::ostream& os)
  {
Thomas Moulard's avatar
Thomas Moulard committed
111
112
113
    getCast(object.type ().name ()).get<0> () (object, os);


114
  }
115

116
117
118
  void
  SignalCaster::trace(const boost::any& object, std::ostream& os)
  {
Thomas Moulard's avatar
Thomas Moulard committed
119
120
121
122
123
    getCast(object.type ().name ()).get<2> () (object, os);
  }

  std::vector<std::string>
  SignalCaster::listTypenames() const
124
125
126
  {
    std::vector<std::string> typeList;
    for (std::map<std::string, cast_functions_type>::const_iterator iter =
Thomas Moulard's avatar
Thomas Moulard committed
127
	   functions_.begin(); iter != functions_.end(); iter++)
128
129
130
      typeList.push_back(iter->first);
    return typeList;
  }
131

132
133
134
  boost::any
  SignalCaster::cast (const std::type_info& type, std::istringstream& iss)
  {
Thomas Moulard's avatar
Thomas Moulard committed
135
    return getCast(type.name ()).get<1> () (iss);
136
  }
137

138
  /// Singleton on the library-wide instance of SignalCaster
139
  SignalCaster* SignalCaster::getInstance(void)
140
  {
141
142
143
144
    if (instance_ == 0) {
      instance_ = new SignalCaster;
    }
    return instance_;
145
  }
146
  SignalCaster* SignalCaster::instance_ = 0;
147
148

} // namespace dynamicgraph