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