5a2caed09674686505d4f9697b280fbc4988f3b8
[platform/core/uifw/dali-core.git] / dali / internal / event / common / demangler.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0
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
18 //
19 // gcc and clang minimal demangling
20 // Both follow Itanium C++ ABI
21 //
22 // We only decode namespaces and class typeid names for simplicity as its all we need.
23 //
24 // From http://mentorembedded.github.io/cxx-abi/abi.html#mangling-structure
25 //
26 // <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
27 //     ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
28 //
29 // <prefix> ::= <prefix> <unqualified-name>
30 //     ::= <template-prefix> <template-args>
31 //          ::= <template-param>
32 //          ::= <decltype>
33 //     ::= # empty
34 //     ::= <substitution>
35 //          ::= <prefix> <data-member-prefix>
36 //
37 // <template-prefix> ::= <prefix> <template unqualified-name>
38 //                   ::= <template-param>
39 //                   ::= <substitution>
40 // <unqualified-name> ::= <operator-name>
41 //                    ::= <ctor-dtor-name>
42 //                    ::= <source-name>
43 //                    ::= <unnamed-type-name>
44 //
45 // <source-name> ::= <positive length number> <identifier>
46 // <number> ::= [n] <non-negative decimal integer>
47 // <identifier> ::= <unqualified source code identifier>
48 //
49 // So for example
50 //
51 // Dali::Internal::Actor would be
52 //
53 //   N4Dali8Internal5ActorE
54 //
55
56 // CLASS HEADER
57 #include <dali/internal/event/common/demangler.h>
58
59 namespace
60 {
61
62 // true if character represent a digit
63 inline bool IsDigit(char c)
64 {
65   return (c >= '0' && c <= '9');
66 }
67
68 // Gets the number of characters (number is in string)
69 //   start The start position to look for a number
70 //   result The number as an integer
71 //   returns the number of characters used to define the number ie '12' is 2
72 size_t GetNumberOfCharacters(const std::string& s, const size_t& start, int& result)
73 {
74   size_t size = s.size();
75
76   size_t i = start;
77
78   int number = 0;
79
80   for( ; i < size; ++i )
81   {
82     char c = s.at(i);
83     if( !IsDigit( c ) )
84     {
85       break;
86     }
87     else
88     {
89       number = 10 * number + (c - '0');
90     }
91   }
92
93   if( i - start )
94   {
95     result = number;
96   }
97
98   return i - start;
99 }
100
101 } // anon namespace
102
103
104 namespace Dali
105 {
106
107 namespace Internal
108 {
109
110 #if defined(__clang__) || defined(__GNUC__)
111
112 // Demangle class name mangled according to the Itanium C++ ABI
113 // Returns demangled names ie "N4Dali8Internal5ActorE" is ["Dali","Internal","Actor"]
114 std::vector<std::string> DemangleNestedNames(const char *typeIdName)
115 {
116   std::vector<std::string> ret;
117
118   const std::string mangledName(typeIdName);
119
120
121   size_t size = mangledName.size();
122
123   if( size >= 2 )
124   {
125     int number = 0;
126     size_t start = 0;
127
128     // If the class isnt nested in a namespace then it just starts with the
129     // number of characters
130     if(mangledName[0] == 'N' && mangledName[size-1]  == 'E')
131     {
132       start = 1;
133     }
134
135     while( size_t chars = GetNumberOfCharacters(mangledName, start, number) )
136     {
137       ret.push_back( mangledName.substr( start + chars, number ) );
138
139       start += chars + number;
140     }
141   }
142
143   return ret;
144 }
145
146 #else
147 # error Unsupported Compiler
148 #endif
149
150
151 const std::string DemangleClassName(const char *typeIdName)
152 {
153   std::string name;
154   std::vector<std::string> names = DemangleNestedNames(typeIdName);
155
156   if( names.size() )
157   {
158     name = names[ names.size() - 1 ];
159   }
160
161   return name;
162 }
163
164 } // namespace Internal
165
166 } // namespace Dali