Synopsis - Cross-Reference

File: src/Synopsis/PTree/Encoding.hh
  1//
  2// Copyright (C) 1997 Shigeru Chiba
  3// Copyright (C) 2004 Stefan Seefeld
  4// All rights reserved.
  5// Licensed to the public under the terms of the GNU LGPL (>= 2),
  6// see the file COPYING for details.
  7//
  8#ifndef Synopsis_PTree_Encoding_hh_
  9#define Synopsis_PTree_Encoding_hh_
 10
 11#include <string>
 12#include <iostream>
 13#include <cassert>
 14#include <cstring>
 15
 16namespace Synopsis
 17{
 18namespace PTree
 19{
 20
 21class Node;
 22class Atom;
 23
 24//. An Encoding represents a mangled (type) name. Here is a quick reference of the grammar:
 25//.
 26//. - `b`: boolean
 27//. - `c`: char
 28//. - `w`: wchar_t
 29//. - `i`: int (signed, unsigned)
 30//. - `s`: short (short int)
 31//. - `l`: long (long int)
 32//. - `j`: long long
 33//. - `f`: float
 34//. - `d`: double
 35//. - `r`: long double
 36//. - `v`: void
 37//. - `T`: template class (e.g. `Foo<int,char>` ==> `T[3]Foo[2]ic`.  `[2]` means
 38//.   the length of `ic`.  It doesn't mean the number of template arguments.
 39//.
 40//. - `e`: ...
 41//. - `?`: no return type.  the return type of constructors
 42//. - `*`: non-type template parameter
 43//.
 44//. - `S`: `signed`
 45//. - `U`: `unsigned`
 46//. - `C`: `const`
 47//. - `V`: `volatile`
 48//.
 49//. - `P`: pointer
 50//. - `R`: reference
 51//. - `A`: array (e.g. `char[16]` ==> `A16_c`)
 52//. - `F`: function (e.g. `char foo(int)` ==> `Fi_c`)
 53//. - `M`: pointer to member (e.g. `Type::*` ==> `M[4]Type`)
 54//.
 55//. - `Q`: qualified class (e.g. `X::YY` ==> `Q[2][1]X[2]YY`, `::YY` ==> `Q[2][0][2]YY`)
 56//.
 57//. - `[x]`: means `0x80 + x`
 58//. - `0`: means `::` (global scope)
 59//.
 60//. Special function names:
 61//.
 62//. - operator + ==> +
 63//. - operator new[] ==> new[]
 64//. - operator <type> ==> @<encoded type>		cast operator
 65//.
 66class Encoding 
 67{
 68public:
 69  struct char_traits
 70  {
 71    typedef unsigned char  char_type;
 72    typedef unsigned long  int_type;
 73    typedef std::streampos pos_type;
 74    typedef std::streamoff off_type;
 75    typedef std::mbstate_t state_type;
 76
 77    static void assign(char_type &c1, const char_type &c2) { c1 = c2;}
 78    static bool eq(const char_type &c1, const char_type &c2) { return c1 == c2;}
 79    static bool lt(const char_type &c1, const char_type &c2) { return c1 < c2;}
 80    static int compare(const char_type *s1, const char_type *s2, std::size_t n) { return memcmp(s1, s2, n);}
 81    static std::size_t length(const char_type *s) { return strlen((const char *)s);}
 82    static const char_type *find(const char_type *s, std::size_t n, const char_type &a)
 83    { return static_cast<const char_type *>(memchr(s, a, n));}
 84    static char_type *move(char_type *s1, const char_type *s2, std::size_t n)
 85    { return static_cast<char_type *>(memmove(s1, s2, n));}
 86    static char_type *copy(char_type *s1, const char_type *s2, std::size_t n)
 87    { return static_cast<char_type *>(memcpy(s1, s2, n));}
 88    static char_type *assign(char_type *s, std::size_t n, char_type a)
 89    { return static_cast<char_type *>(memset(s, a, n));}
 90    static char_type to_char_type(const int_type &c) { return static_cast<char_type>(c);}
 91    static int_type to_int_type(const char_type &c) { return static_cast<int_type>(c);}
 92    static bool eq_int_type(const int_type &c1, const int_type &c2) { return c1 == c2;}
 93    static int_type eof() { return static_cast<int_type>(EOF);}
 94    static int_type not_eof(const int_type &c) { return !eq_int_type(c, eof()) ? c : to_int_type(char_type());}
 95  };
 96
 97  typedef std::basic_string<unsigned char, char_traits> Code;
 98  typedef Code::const_iterator iterator;
 99
100  static void do_init_static();
101
102  Encoding() {}
103  Encoding(const Code &b) : my_buffer(b) {}
104  Encoding(const char *b) : my_buffer(b, b + strlen(b)) {}
105  Encoding(const char *b, size_t s) : my_buffer(b, b + s) {}
106  Encoding(iterator b, iterator e) : my_buffer(b, e) {}
107  static Encoding simple_name(PTree::Atom const *name);
108
109  void clear() { my_buffer.clear();}
110  bool empty() const { return my_buffer.empty();}
111  size_t size() const { return my_buffer.size();}
112  iterator begin() const { return my_buffer.begin();}
113  iterator end() const { return my_buffer.end();}
114  unsigned char front() const { return *begin();}
115  unsigned char at(size_t i) const { return my_buffer.at(i);}
116  //. return a copy of the underlaying buffer
117  //. FIXME: this is a temporary workaround while there are
118  //. still places that use raw strings
119  const char *copy() const;
120
121  bool operator == (const Encoding &e) const { return my_buffer == e.my_buffer;}
122  bool operator == (const std::string &s) const { return my_buffer == (const unsigned char *)s.c_str();}
123  bool operator == (const char *s) const { return my_buffer == (const unsigned char *)s;}
124
125  void prepend(unsigned char c) { my_buffer.insert(my_buffer.begin(), c);}
126  void prepend(const char *p, size_t s) { my_buffer.insert(0, (const unsigned char *)p, s);}
127  void prepend(const Encoding &e) { my_buffer.insert(0, e.my_buffer);}
128
129  void append(unsigned char c) { my_buffer.append(1, c);}
130  void append(const char *p, size_t s) { my_buffer.append((const unsigned char *)p, s);}
131  void append(const Encoding &e) { my_buffer.append(e.my_buffer);}
132  void append_with_length(const char *s, size_t n) { append(0x80 + n); append((const char *)s, n);}
133  void append_with_length(const Encoding &e) { append(0x80 + e.size()); append(e);}
134
135  unsigned char pop();
136  void pop(size_t n) { my_buffer.erase(my_buffer.begin(), my_buffer.begin() + n);}
137
138  void cv_qualify(const Node *, const Node * = 0);
139  void simple_const() { append("Ci", 2);}
140  void global_scope();
141  void simple_name(const Node *);
142  void anonymous();
143  void template_(const Node *, const Encoding &);
144  void qualified(int);
145  void destructor(const Node *);
146  void ptr_operator(int);
147  void ptr_to_member(const Encoding &, int);
148  void cast_operator(const Encoding &);
149  void array() { prepend("A_", 2);}
150  void array(unsigned long s);
151  void function(const Encoding &e) { prepend(e);}
152  void recursion(const Encoding &e) { prepend(e);}
153  void start_func_args() { append('F');}
154  void end_func_args() { append('_');}
155  void void_() { append('v');}
156  void ellipsis_arg() { append('e');}
157  void no_return_type() { append('?');}
158  void value_temp_param() { append('*');}
159
160  //. if this Encoding represents a qualified name,
161  //. return the name of the outer scope
162  Encoding get_scope() const;
163  //. if this Encoding represents a qualified name,
164  //. return the name of the symbol inside the outer scope,
165  //. else return the unmodified name
166  Encoding get_symbol() const;
167  Encoding get_template_arguments() const;
168  
169  std::string unmangled() const;
170
171  PTree::Node *make_name();
172  PTree::Node *make_qname();
173  PTree::Node *make_ptree(PTree::Node *);
174  bool is_simple_name() const { return front() >= 0x80;}
175  bool is_global_scope() const { return front() == 0x80 && size() == 1;}
176  bool is_qualified() const { return front() == 'Q';}
177  bool is_function() const;
178  bool is_template() const { return front() == 'T';}
179  PTree::Node *name_to_ptree();
180
181  friend bool operator < (const Encoding &, const Encoding &);
182  friend std::ostream &operator << (std::ostream &, const Encoding &);
183
184private:
185
186  iterator end_of_scope() const;
187
188  Code my_buffer;
189
190public:
191  static PTree::Node *bool_t, *char_t, *wchar_t_t, *int_t, *short_t, *long_t,
192		 *float_t, *double_t, *void_t;
193
194  static PTree::Node *signed_t, *unsigned_t, *const_t, *volatile_t;
195
196  static PTree::Node *operator_name, *new_operator, *anew_operator,
197		 *delete_operator, *adelete_operator;
198
199  static PTree::Node *star, *ampersand, *comma, *dots, *scope, *tilder,
200		 *left_paren, *right_paren, *left_bracket, *right_bracket,
201		 *left_angle, *right_angle;
202};
203
204inline bool operator < (const Encoding &e1, const Encoding &e2) 
205{
206  return e1.my_buffer < e2.my_buffer;
207}
208
209inline std::ostream &operator << (std::ostream &os, const Encoding &e)
210{
211  for (Encoding::iterator i = e.begin();
212       i != e.end();
213       ++i)
214    if(*i < 0x80) os.put(static_cast<char>(*i));
215    else os << '[' << static_cast<int>(*i - 0x80) << ']';
216  return os;
217}
218
219inline unsigned char Encoding::pop() 
220{
221  unsigned char code = my_buffer[0]; 
222  my_buffer.erase(0, 1); 
223  return code;
224}
225
226inline bool Encoding::is_function() const 
227{
228  if (front() == 'F') return true;
229  // const (member) function.
230  else if (front() == 'C' && *(begin() + 1) == 'F') return true;
231  else return false;
232}
233
234}
235}
236
237#endif