TSchemaRuleProcessor.h

Go to the documentation of this file.
00001 // @(#)root/core:$Id: TSchemaRuleProcessor.h 34641 2010-07-28 18:12:36Z pcanal $
00002 // author: Lukasz Janyst <ljanyst@cern.ch>
00003 
00004 #ifndef ROOT_TSchemaRuleProcessor
00005 #define ROOT_TSchemaRuleProcessor
00006 
00007 #if !defined(__CINT__)
00008 // Do no clutter the dictionary (in particular with STL containers)
00009 
00010 #include <stdlib.h>
00011 #include <string>
00012 #include <list>
00013 #include <utility>
00014 #include <cstdlib>
00015 #include <iostream>
00016 #include "Rtypes.h"
00017 
00018 #ifndef R__TSCHEMATYPE_H
00019 #include "TSchemaType.h"
00020 #endif
00021 
00022 namespace ROOT
00023 {
00024    class TSchemaRuleProcessor
00025    {
00026       public:
00027          //---------------------------------------------------------------------
00028          static void SplitList( const std::string& source,
00029                                 std::list<std::string>& result,
00030                                 char delimiter=',')
00031          {
00032             // Split the string producing a list of substrings
00033 
00034             std::string::size_type curr;
00035             std::string::size_type last = 0;
00036             std::string::size_type size;
00037             std::string            elem;
00038 
00039             result.clear();
00040 
00041             while( last != source.size() ) {
00042                curr = source.find( delimiter, last );
00043 
00044                if( curr == std::string::npos ) {
00045                   curr = source.size()-1;
00046                   size = curr-last+1;
00047                }
00048                else size = curr-last;
00049 
00050                elem = Trim( source.substr( last, size ) );
00051                if( !elem.empty() )
00052                   result.push_back( elem );
00053 
00054                last = curr+1;
00055             }
00056          }
00057 
00058          static void SplitDeclaration( const std::string& source,
00059                                        std::list<std::pair<ROOT::TSchemaType,std::string> >& result)
00060          {
00061             // Split a declaration string producing a list of substrings
00062             // Typically we have:
00063             //    int mem; SomeType mem2; SomeTmp<const key, const value> mem3; 
00064 
00065             std::string::size_type curr;
00066             std::string::size_type last = 0;
00067             std::string::size_type size;
00068             std::string            elem;
00069             std::string            type;
00070             std::string            dims;
00071 
00072             result.clear();
00073 
00074             while( last != source.size() ) {
00075                // Split on semi-colons.
00076                curr = source.find( ';', last );
00077 
00078                if( curr == std::string::npos ) {
00079                   curr = source.size()-1;
00080                   size = curr-last+1;
00081                }
00082                else size = curr-last;
00083                
00084                // Extra spaces.
00085                elem = Trim( source.substr( last, size ) );
00086                if( !elem.empty() ) {
00087                   unsigned int level = 0;
00088                  
00089                   // Split between the typename and the membername
00090                   // Take in consideration template names.
00091                   for(std::string::size_type i=0; i<elem.size(); ++i) {
00092                      if (elem[i]=='<') { ++level; }
00093                      else if (elem[i]=='>') { --level; }
00094                      else if (level == 0 && isspace(elem[i])) {
00095                         type = elem.substr( 0, i );
00096                         // At the first iteration we know we have a space.
00097                         while( elem[i]=='*' || elem[i]=='&' || isspace(elem[i]) ) {
00098                            ++i;
00099                            if (strcmp("const",elem.c_str()+i)==0 && (i+5)>elem.size()
00100                                && ( elem[i+5]=='*' || elem[i+5]=='&' || isspace(elem[i+5])) ) {
00101                               i += 5;
00102                               type += "const ";
00103                            } else if (elem[i]=='*' || elem[i]=='&') {
00104                               type += elem[i];
00105                            }
00106                         }
00107                         std::string::size_type endvar = i;
00108                         while( endvar!=elem.size() && elem[endvar] != '[' ) {
00109                            ++endvar;
00110                         }
00111                         if (endvar != elem.size() ) {
00112                            dims = Trim( elem.substr(endvar, elem.size()-endvar) );
00113                         }
00114                         elem = Trim( elem.substr(i, endvar-i) );
00115                         break;
00116                      }
00117                   }
00118                   result.push_back( make_pair(ROOT::TSchemaType(type,dims),elem) );
00119                }
00120                last = curr+1;
00121             }
00122          }
00123 
00124          //---------------------------------------------------------------------
00125          static std::string Trim( const std::string& source, char character = ' ' )
00126          {
00127             // Trim the whitespaces at the beginning and at the end of
00128             // given source string
00129 
00130             std::string::size_type start, end;
00131             for( start = 0; start < source.size() && isspace(source[start]); ++start) {}
00132             if( start == source.size() )
00133                return "";
00134             for( end = source.size()-1; end > start && source[end] == character; --end ) ;
00135             return source.substr( start, end-start+1 );
00136          }
00137 
00138          //---------------------------------------------------------------------
00139          static bool ProcessVersion( const std::string& source,
00140                                      std::pair<Int_t, Int_t>& result )
00141          {
00142             // Check if a version is specified correctly
00143             // The result is set the following way:
00144             //   x  :  first = x   second = x
00145             //  -x  :  first = -10 second = x
00146             // x-y  :  first = x   second = y
00147             // x-   :  first = x   second = 50000
00148             // if the given string is invalid (false is returned)
00149             // then the state of the result is undefined
00150 
00151             std::string::size_type hyphenI;
00152             std::string            first;
00153             std::string            second;
00154 
00155             std::string version = Trim( source );
00156 
00157             if( version.empty() )
00158                return false;
00159 
00160             //------------------------------------------------------------------
00161             // Do we have a star?
00162             //------------------------------------------------------------------
00163             if( version == "*" ) {
00164                result.first  = -10;
00165                result.second = 50000;
00166                return true;
00167             }
00168 
00169             //------------------------------------------------------------------
00170             // Check if we have a minus somewhere, if not then single version
00171             // number was specified
00172             //------------------------------------------------------------------
00173             hyphenI = version.find( '-' );
00174             if( hyphenI == std::string::npos && IsANumber( version ) ) {
00175                result.first = result.second = atoi( version.c_str() );
00176                return true;
00177             }
00178 
00179             //------------------------------------------------------------------
00180             // We start with the hyphen
00181             //------------------------------------------------------------------
00182             if( hyphenI == 0 ) {
00183                second = Trim( version.substr( 1 ) );
00184                if( IsANumber( second ) ) {
00185                   result.first  = -10;
00186                   result.second = atoi( second.c_str() );
00187                   return true;
00188                }
00189             }
00190 
00191             //------------------------------------------------------------------
00192             // We end with the hyphen
00193             //------------------------------------------------------------------
00194             if( hyphenI == version.size()-1 ) {
00195                first = Trim( version.substr( 0, version.size()-1 ) );
00196                if( IsANumber( first ) ) {
00197                   result.first  = atoi( first.c_str() );
00198                   result.second = 50000;
00199                   return true;
00200                }
00201             }
00202 
00203             //------------------------------------------------------------------
00204             // We have the hyphen somewhere in the middle
00205             //------------------------------------------------------------------
00206             first  = Trim( version.substr( 0, hyphenI ) );
00207             second = Trim( version.substr( hyphenI+1, version.size()-hyphenI-1 ) );
00208             if( IsANumber( first ) && IsANumber( second ) ) {
00209                result.first  = atoi( first.c_str() );
00210                result.second = atoi( second.c_str() );
00211                return true;
00212             }
00213 
00214             return false;
00215          }
00216 
00217          //---------------------------------------------------------------------
00218          static bool IsANumber( const std::string& source )
00219          {
00220             // check if given string si consisted of digits
00221 
00222             if( source.empty() )
00223                return false;
00224 
00225             std::string::size_type i;
00226             for( i = 0; i < source.size(); ++i )
00227                if( !isdigit( source[i] ) )
00228                   return false;
00229             return true;
00230          }
00231    };
00232 }
00233 #endif // defined(__CINT__)
00234 
00235 #endif // ROOT_TSchemaRuleProcessor

Generated on Tue Jul 5 14:11:56 2011 for ROOT_528-00b_version by  doxygen 1.5.1