cd1e9c972da57d71036a5b422c108e416e85ae62
[platform/core/uifw/dali-core.git] / dali / internal / event / common / type-registry-impl.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://floralicense.org/license/
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an AS IS BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 // CLASS HEADER
18 #include <dali/internal/event/common/type-registry-impl.h>
19
20 // EXTERNAL INCLUDES
21 #include <execinfo.h>
22 #include <cxxabi.h>
23 #include <string.h>
24 #include <sstream>
25
26 // INTERNAL INCLUDES
27 #include <dali/internal/event/common/thread-local-storage.h>
28 #include <dali/public-api/object/type-registry.h>
29 #include <dali/public-api/object/base-handle.h>
30 #include <dali/internal/event/actors/custom-actor-internal.h>
31
32 #include <dali/integration-api/debug.h>
33
34 namespace
35 {
36
37 #if defined(DEBUG_ENABLED)
38 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_TYPE_REGISTRY");
39 #endif
40
41 std::vector<std::string> SplitString(const std::string &s, char delim, std::vector<std::string> &elems)
42 {
43   std::stringstream ss(s);
44   std::string item;
45   while(std::getline(ss, item, delim))
46   {
47     elems.push_back(item);
48   }
49   return elems;
50 }
51
52 const int Demangle(const char* symbol, std::vector<std::string> &resolved)
53 {
54   int status = -4;
55
56   char* res = abi::__cxa_demangle(symbol, NULL, NULL, &status);
57
58   const char* const demangled_name = (status==0)?res:symbol;
59
60   std::string sDemangled(demangled_name);
61
62   free(res);
63
64   SplitString(sDemangled, ':', resolved);
65
66   return resolved.size();
67 }
68
69 const std::string DemangleShortName(const char *symbol)
70 {
71   std::vector<std::string> resolved;
72
73   Demangle(symbol, resolved);
74
75   if(resolved.size() > 0)
76   {
77     return resolved[ resolved.size() - 1 ];
78   }
79   else
80   {
81     return std::string(symbol);
82   }
83
84 }
85
86 } // namespace anon
87
88 namespace Dali
89 {
90
91 extern std::string Demangle(const char* symbol);
92
93 namespace Internal
94 {
95
96 TypeRegistry *TypeRegistry::Get()
97 {
98   static TypeRegistry *_reg(new TypeRegistry());
99   DALI_ASSERT_DEBUG(_reg);
100   return _reg;
101 }
102
103 TypeRegistry::TypeRegistry()
104 {
105
106 }
107
108 TypeRegistry::~TypeRegistry()
109 {
110   mRegistryLut.clear();
111 }
112
113 Dali::TypeInfo TypeRegistry::GetTypeInfo( const std::string &uniqueTypeName )
114 {
115   Dali::TypeInfo ret;
116
117   RegistryMap::iterator iter = mRegistryLut.find(uniqueTypeName);
118
119   if( iter != mRegistryLut.end() )
120   {
121     ret = iter->second;
122   }
123   else
124   {
125     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Cannot find requested type '%s'\n", uniqueTypeName.c_str());
126   }
127
128   return ret;
129 }
130
131 Dali::TypeInfo TypeRegistry::GetTypeInfo( const std::type_info& registerType )
132 {
133   Dali::TypeInfo ret;
134
135   std::string typeName = DemangleShortName(registerType.name());
136
137   RegistryMap::iterator iter = mRegistryLut.find(typeName);
138
139   if( iter != mRegistryLut.end() )
140   {
141     ret = iter->second;
142   }
143   else
144   {
145     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Cannot find requested type '%s'\n", registerType.name());
146   }
147
148   return ret;
149 }
150
151 Dali::TypeRegistry::NameContainer TypeRegistry::GetTypeNames() const
152 {
153   Dali::TypeRegistry::NameContainer ret;
154
155   for(RegistryMap::const_iterator iter = mRegistryLut.begin(); iter != mRegistryLut.end(); ++iter)
156   {
157     ret.push_back(iter->first);
158   }
159
160   return ret;
161 }
162
163 bool TypeRegistry::Register( const std::type_info& theTypeInfo, const std::type_info& baseTypeInfo,
164                                Dali::TypeInfo::CreateFunction createInstance, bool callCreateOnInit )
165 {
166   std::string uniqueTypeName  = DemangleShortName(theTypeInfo.name());
167
168   return Register( uniqueTypeName, baseTypeInfo, createInstance, callCreateOnInit );
169 }
170
171 bool TypeRegistry::Register( const std::string& uniqueTypeName, const std::type_info& baseTypeInfo,
172                              Dali::TypeInfo::CreateFunction createInstance, bool callCreateOnInit )
173 {
174   bool ret = false;
175
176   std::string baseTypeName    = DemangleShortName(baseTypeInfo.name());
177
178   RegistryMap::iterator iter = mRegistryLut.find(uniqueTypeName);
179
180   if( iter == mRegistryLut.end() )
181   {
182     mRegistryLut[uniqueTypeName] = Dali::TypeInfo(new Internal::TypeInfo(uniqueTypeName, baseTypeName, createInstance));
183     ret = true;
184     DALI_LOG_INFO( gLogFilter, Debug::Concise, "Type Registration %s(%s)\n", uniqueTypeName.c_str(), baseTypeName.c_str());
185   }
186   else
187   {
188     DALI_LOG_WARNING("Duplicate name for TypeRegistry for '%s'\n", + uniqueTypeName.c_str());
189     DALI_ASSERT_ALWAYS(!"Duplicate type name for Type Registation");
190   }
191
192   if( callCreateOnInit )
193   {
194     mInitFunctions.push_back(createInstance);
195   }
196
197   return ret;
198 }
199
200 void TypeRegistry::CallInitFunctions(void) const
201 {
202   for( InitFunctions::const_iterator iter = mInitFunctions.begin(); iter != mInitFunctions.end(); ++iter)
203   {
204     (*iter)();
205   }
206 }
207
208 std::string TypeRegistry::RegistrationName( const std::type_info& registerType )
209 {
210   return DemangleShortName( registerType.name() );
211 }
212
213 void TypeRegistry::RegisterSignal( TypeRegistration& typeRegistration, const std::string& name, Dali::TypeInfo::SignalConnectorFunctionV2 func )
214 {
215   RegistryMap::iterator iter = mRegistryLut.find( typeRegistration.RegisteredName() );
216
217   if( iter != mRegistryLut.end() )
218   {
219     DALI_ASSERT_DEBUG(iter->second);
220
221     GetImplementation(iter->second).AddConnectorFunction( name, func );
222   }
223 }
224
225 bool TypeRegistry::RegisterAction( TypeRegistration &registered, const std::string &name, Dali::TypeInfo::ActionFunction f)
226 {
227   RegistryMap::iterator iter = mRegistryLut.find( registered.RegisteredName() );
228
229   if( iter != mRegistryLut.end() )
230   {
231     DALI_ASSERT_DEBUG(iter->second);
232
233     GetImplementation(iter->second).AddActionFunction( name, f );
234
235     return true;
236   }
237   else
238   {
239     return false;
240   }
241 }
242
243 bool TypeRegistry::RegisterProperty( TypeRegistration& registered, const std::string& name, Property::Index index, Property::Type type, Dali::TypeInfo::SetPropertyFunction setFunc, Dali::TypeInfo::GetPropertyFunction getFunc )
244 {
245   RegistryMap::iterator iter = mRegistryLut.find( registered.RegisteredName() );
246
247   if( iter != mRegistryLut.end() )
248   {
249     DALI_ASSERT_DEBUG(iter->second);
250
251     GetImplementation(iter->second).AddProperty( name, index, type, setFunc, getFunc );
252
253     return true;
254   }
255
256   return false;
257 }
258
259 bool TypeRegistry::DoActionTo( BaseObject * const object, const std::string &actionName, const std::vector<Property::Value> &properties)
260 {
261   bool done = false;
262
263   Dali::TypeInfo type = GetTypeInfo( object );
264
265   while( type )
266   {
267     if(GetImplementation(type).DoActionTo(object, actionName, properties))
268     {
269       done = true;
270       break;
271     }
272     type = GetTypeInfo( type.GetBaseName() );
273   }
274
275   return done;
276 }
277
278 bool TypeRegistry::ConnectSignal( BaseObject* object, ConnectionTrackerInterface* connectionTracker, const std::string& signalName, FunctorDelegate* functor )
279 {
280   bool connected( false );
281
282   Dali::TypeInfo type = GetTypeInfo( object );
283
284   while( type )
285   {
286     connected = GetImplementation(type).ConnectSignal( object, connectionTracker, signalName, functor );
287     if( connected )
288     {
289       break;
290     }
291     type = GetTypeInfo( type.GetBaseName() );
292   }
293
294   if( !connected )
295   {
296     // Ownership of functor was not passed to Dali::CallbackBase, so clean-up now
297     delete functor;
298   }
299
300   return connected;
301 }
302
303 Dali::TypeInfo TypeRegistry::GetTypeInfo(const Dali::BaseObject * const pBaseObject)
304 {
305   Dali::TypeInfo type;
306
307   // test for custom actor which has another indirection to get to the type hiearchy we're after
308   const Dali::Internal::CustomActor * const pCustom = dynamic_cast<const Dali::Internal::CustomActor*>(pBaseObject);
309
310   if(pCustom)
311   {
312     type = GetTypeInfo( typeid( pCustom->GetImplementation() ) );
313   }
314   else
315   {
316     type = GetTypeInfo( typeid( *pBaseObject ) );
317   }
318
319   return type;
320 }
321
322 } // namespace Internal
323
324 } // namespace Dali