Logo ROOT   6.14/05
Reference Guide
TSchemaRuleProcessor.h
Go to the documentation of this file.
1 // @(#)root/core:$Id$
2 // author: Lukasz Janyst <ljanyst@cern.ch>
3 
4 #ifndef ROOT_TSchemaRuleProcessor
5 #define ROOT_TSchemaRuleProcessor
6 
7 // NOTE: #included by libCore and libCling. All symbols must be inline.
8 
9 #include <stdlib.h>
10 #include <cstring>
11 #include <string>
12 #include <list>
13 #include <utility>
14 #include <cstdlib>
15 #include <iostream>
16 #include "RtypesCore.h"
17 
18 #include "TSchemaType.h"
19 
20 namespace ROOT {
21 namespace Internal {
23  {
24  public:
25  //---------------------------------------------------------------------
26  static void SplitList( const std::string& source,
27  std::list<std::string>& result,
28  char delimiter=',')
29  {
30  // Split the string producing a list of substrings
31 
32  std::string::size_type curr;
33  std::string::size_type last = 0;
34  std::string::size_type size;
35  std::string elem;
36 
37  result.clear();
38 
39  while( last != source.size() ) {
40  curr = source.find( delimiter, last );
41 
42  if( curr == std::string::npos ) {
43  curr = source.size()-1;
44  size = curr-last+1;
45  }
46  else size = curr-last;
47 
48  elem = Trim( source.substr( last, size ) );
49  if( !elem.empty() )
50  result.push_back( elem );
51 
52  last = curr+1;
53  }
54  }
55 
56  static void SplitDeclaration( const std::string& source,
57  std::list<std::pair<ROOT::Internal::TSchemaType,std::string> >& result)
58  {
59  // Split a declaration string producing a list of substrings
60  // Typically we have:
61  // int mem; SomeType mem2; SomeTmp<const key, const value> mem3;
62 
63  std::string::size_type curr;
64  std::string::size_type last = 0;
65  std::string::size_type size;
66  std::string elem;
67  std::string type;
68  std::string dims;
69 
70  result.clear();
71 
72  while( last != source.size() ) {
73  // Split on semi-colons.
74  curr = source.find( ';', last );
75 
76  if( curr == std::string::npos ) {
77  curr = source.size()-1;
78  size = curr-last+1;
79  }
80  else size = curr-last;
81 
82  // Extra spaces.
83  elem = Trim( source.substr( last, size ) );
84  if( !elem.empty() ) {
85  unsigned int level = 0;
86 
87  // Split between the typename and the membername
88  // Take in consideration template names.
89  for(std::string::size_type j=elem.size(); j>0; --j) {
90  std::string::size_type i = j-1;
91  if (elem[i]=='<') { ++level; }
92  else if (elem[i]=='>') { if (level==0) { continue; } ; --level; }
93  else if (level == 0 && isspace(elem[i])) {
94  type = elem.substr( 0, i );
95  // At the first iteration we know we have a space.
96  while( elem[i]=='*' || elem[i]=='&' || isspace(elem[i]) ) {
97  ++i;
98  if (strcmp("const",elem.c_str()+i)==0 && (i+5)>elem.size()
99  && ( elem[i+5]=='*' || elem[i+5]=='&' || isspace(elem[i+5])) ) {
100  i += 5;
101  type += "const ";
102  } else if (elem[i]=='*' || elem[i]=='&') {
103  type += elem[i];
104  }
105  }
106  std::string::size_type endvar = i;
107  while( endvar!=elem.size() && elem[endvar] != '[' ) {
108  ++endvar;
109  }
110  if (endvar != elem.size() ) {
111  dims = Trim( elem.substr(endvar, elem.size()-endvar) );
112  }
113  elem = Trim( elem.substr(i, endvar-i) );
114  break;
115  }
116  }
117  result.push_back( make_pair(ROOT::Internal::TSchemaType(type,dims),elem) );
118  }
119  last = curr+1;
120  }
121  }
122 
123  //---------------------------------------------------------------------
124  static std::string Trim( const std::string& source )
125  {
126  // Trim the whitespaces at the beginning and at the end of
127  // given source string
128 
129  std::string::size_type start, end;
130  for( start = 0; start < source.size(); ++start) {
131  if ( isspace(source[start]) ) {
132  continue;
133  } else if ( source[start] == '\\' && (start+1)<source.size() && (source[start+1]=='\n' || source[start+1]=='\r') ) {
134  ++start;
135  continue;
136  } else {
137  // Not a white space.
138  break;
139  }
140  }
141  if( start == source.size() )
142  return "";
143  for( end = source.size()-1; end > start; --end ) {
144  if ( (source[end]=='\n' || source[end]=='\r') && end > (start+1) && source[end-1] == '\\' ) {
145  --end;
146  continue;
147  } else if ( isspace(source[end]) ) {
148  continue;
149  } else {
150  // Not a white space.
151  break;
152  }
153  }
154  return source.substr( start, end-start+1 );
155  }
156 
157  //---------------------------------------------------------------------
158  static bool ProcessVersion( const std::string& source,
159  std::pair<Int_t, Int_t>& result )
160  {
161  // Check if a version is specified correctly
162  // The result is set the following way:
163  // x : first = x second = x
164  // -x : first = -10 second = x
165  // x-y : first = x second = y
166  // x- : first = x second = 50000
167  // if the given string is invalid (false is returned)
168  // then the state of the result is undefined
169 
170  std::string::size_type hyphenI;
171  std::string first;
172  std::string second;
173 
174  std::string version = Trim( source );
175 
176  if( version.empty() )
177  return false;
178 
179  //------------------------------------------------------------------
180  // Do we have a star?
181  //------------------------------------------------------------------
182  if( version == "*" ) {
183  result.first = -10;
184  result.second = 50000;
185  return true;
186  }
187 
188  //------------------------------------------------------------------
189  // Check if we have a minus somewhere, if not then single version
190  // number was specified
191  //------------------------------------------------------------------
192  hyphenI = version.find( '-' );
193  if( hyphenI == std::string::npos && IsANumber( version ) ) {
194  result.first = result.second = atoi( version.c_str() );
195  return true;
196  }
197 
198  //------------------------------------------------------------------
199  // We start with the hyphen
200  //------------------------------------------------------------------
201  if( hyphenI == 0 ) {
202  second = Trim( version.substr( 1 ) );
203  if( IsANumber( second ) ) {
204  result.first = -10;
205  result.second = atoi( second.c_str() );
206  return true;
207  }
208  }
209 
210  //------------------------------------------------------------------
211  // We end with the hyphen
212  //------------------------------------------------------------------
213  if( hyphenI == version.size()-1 ) {
214  first = Trim( version.substr( 0, version.size()-1 ) );
215  if( IsANumber( first ) ) {
216  result.first = atoi( first.c_str() );
217  result.second = 50000;
218  return true;
219  }
220  }
221 
222  //------------------------------------------------------------------
223  // We have the hyphen somewhere in the middle
224  //------------------------------------------------------------------
225  first = Trim( version.substr( 0, hyphenI ) );
226  second = Trim( version.substr( hyphenI+1, version.size()-hyphenI-1 ) );
227  if( IsANumber( first ) && IsANumber( second ) ) {
228  result.first = atoi( first.c_str() );
229  result.second = atoi( second.c_str() );
230  return true;
231  }
232 
233  return false;
234  }
235 
236  //---------------------------------------------------------------------
237  static bool IsANumber( const std::string& source )
238  {
239  // check if given string si consisted of digits
240 
241  if( source.empty() )
242  return false;
243 
244  std::string::size_type i;
245  for( i = 0; i < source.size(); ++i )
246  if( !isdigit( source[i] ) )
247  return false;
248  return true;
249  }
250  };
251 } // namespace Internal
252 } // namespace ROOT
253 
254 #endif // ROOT_TSchemaRuleProcessor
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
static bool IsANumber(const std::string &source)
static void SplitDeclaration(const std::string &source, std::list< std::pair< ROOT::Internal::TSchemaType, std::string > > &result)
static constexpr double second
static void SplitList(const std::string &source, std::list< std::string > &result, char delimiter=',')
int type
Definition: TGX11.cxx:120
Definition: first.py:1
static std::string Trim(const std::string &source)
static bool ProcessVersion(const std::string &source, std::pair< Int_t, Int_t > &result)