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