    // @(#)root/star:$Name:  $:$Id: TDataSetIter.cxx,v 1.3 2003/01/27 20:41:36 brun Exp $
    // Author: Valery Fine(fine@mail.cern.ch)   03/07/98
    // Copyright (C) Valery Fine (Valeri Faine) 1998. All right reserved
    #include "Riosfwd.h"
    #include "Riostream.h"

    #include "TDataSetIter.h"
    #include "TBrowser.h"
    #include "TSystem.h"

    #ifndef WIN32
    # ifndef HASSTRCASE
    #  define HASSTRCASE
    # endif
    #endif

    #ifndef HASSTRCASE
    #  define strcasecmp(arg1,arg2) stricmp(arg1,arg2)
    #endif

    TDataSet *TDataSetIter::fNullDataSet = (TDataSet *)(-1);

    ClassImp(TDataSetIter)

    //////////////////////////////////////////////////////////////////////////
    //                                                                      //
    // TDataSetIter                                                         //
    //                                                                      //
    // TDataSetIter is a class iterator to navigate TDataSet objects        //
    // via 4 internal pointers :                                            //
    //                                                                      //
    //  1. fRootDataSet    - "root" dataset                                 //
    //  2. fWorkingDataSet - Working dataset                                //
    //  3. fDataSet        - the last selected TDataSet                     //
    //  4. fNext           - TIter for the the list of the "root" dataset   //
    //                                                                      //
    //////////////////////////////////////////////////////////////////////////

    //______________________________________________________________________________
     TDataSetIter::TDataSetIter(TDataSet *link, Bool_t dir)
    {
       fWorkingDataSet= fRootDataSet   =link;
       fMaxDepth      = fDepth         =1;
       fDataSet= fNullDataSet ;
       fNext = link ? new TIter(link->GetCollection() ,dir):0;
    }

    //______________________________________________________________________________
     TDataSetIter::TDataSetIter(TDataSet *link, Int_t depth, Bool_t dir)
    {
       fRootDataSet = fWorkingDataSet = link;
       fMaxDepth    = depth;
       fDepth       = 1;
       fDataSet     = fNullDataSet;
       fNext        = (link)? new TIter(link->GetCollection() ,dir):0;

       // Create a DataSet iterator to pass all nodes of the
       //     "depth"  levels
       //  of  TDataSet *link

       if (fMaxDepth != 1) {
          fNextSet[0] = fNext;
          if (fMaxDepth > 100) fMaxDepth = 100;
          fDepth = 0;
       }
    }

    //______________________________________________________________________________
     TDataSetIter::~TDataSetIter()
    {
       if (fMaxDepth != 1) {
          Int_t level = fDepth;
          if (level) level--;
          for (Int_t i = level;i>=0;i--) {
             TIter *s = fNextSet[i];
             if (s) delete s;
          }
       }
       else
          SafeDelete(fNext);
       fDepth = 0;
    }

    //______________________________________________________________________________
     TDataSet *TDataSetIter::Add(TDataSet *set, TDataSet *dataset)
    {
       ///////////////////////////////////////////////////////////////////////////////
       //                                                                           //
       // Add - adds the set to the dataset defined with the second parameters      //
       //                                                                           //
       // TDataSet dataset != 0 - Add the set to the TDataSet *dataset              //
       //                                                                           //
       //                     = 0 - (by default) to the current TDataSet defined    //
       //                          with fWorkingDataSet data member                 //
       //                                                                           //
       //  returns  the pointer to set is success or ZERO poiner                    //
       //  =======                                                                  //
       //                                                                           //
       //  Note: If this TDataSetIter is empty (i.e. Cwd() returns 0), the "set"    //
       //        becomes the "root" dataset of this iterator                        //                                                                         //
       ///////////////////////////////////////////////////////////////////////////////

       if (!set) return 0;
       TDataSet *s =  dataset;
       if (!s) s = Cwd();
       if (s) {
          s->Add(set);
          s = set;
       }
       else {
          //  make the coming dataset the current one for the iterator
          s = set;
          fRootDataSet    = s;
          fWorkingDataSet = s;
          if (fNext) {
             Error("Add","TDataSetIter.has been corrupted ;-!");
             delete fNext;
             fNext = 0;
          }
          fNext = new TIter(s->GetCollection() );
       }
       return s;
    }

    //______________________________________________________________________________
     TDataSet *TDataSetIter::Add(TDataSet *dataset, const Char_t *path)
    {
       ///////////////////////////////////////////////////////////////////////////////
       //                                                                           //
       // Add                                                                       //
       //                                                                           //
       // Char_t path != 0 - Add a TDataSet dataset to the TDataSet dataset         //
       //                    defined with "path"                                    //
       //              = 0 - (by default) to the current TDataSet defined           //
       //                     with fWorkingDataSet data member                      //
       //                                                                           //
       //  returns the dataset is success or ZERO pointer                           //
       //  =======                                                                  //
       //                                                                           //
       ///////////////////////////////////////////////////////////////////////////////
       if (!dataset) return 0;
       TDataSet *set = 0;
       if (path && strlen(path)) set = Find(path);
       return Add(dataset,set);
    }

    //______________________________________________________________________________
     TDataSet *TDataSetIter::Cd(const Char_t *dirname){
       /////////////////////////////////////////////////////////////////////
       //                                                                 //
       // TDataSet *TDataSetIter::Cd(const Char_t *dirname)               //
       //                                                                 //
       // Change the current working directory to dirname                 //
       //                                                                 //
       // Returns the pointer to the new "working" TDataSet               //
       // =======   0,  if the new directory doesn't exist.               //
       //                                                                 //
       // Remark:  The name = ".." has a special meaning.                 //
       // ------   TDataSetIter::Cd("..") returns the parent set          //
       //          But one still can not use ".." as a legal part         //
       //          of the full path                                       //
       /////////////////////////////////////////////////////////////////////
       TDataSet *set = 0;
       if (strcmp(dirname,".."))
          set =  Find(dirname);
       else
          set = fWorkingDataSet->GetParent();
       if (set) fWorkingDataSet = set;
       return set;
    }

    //______________________________________________________________________________
     TDataSet *TDataSetIter::Cd(TDataSet *ds)
    {
       /////////////////////////////////////////////////////////////////////
       //                                                                 //
       // TDataSet *TDataSetIter::Cd(const TDataSet *ds)                  //
       //                                                                 //
       // Make:  Cwd() = ds;                                              //
       // Look for the first occurence of the "ds" pointer for the current//
       // TDataSet in respect of the Cwd() if any                         //
       //                                                                 //
       // Change the current working directory to ds if present           //
       //                                                                 //
       // Returns the pointer to the new "working" TDataSet (i.e. ds)     //
       // =======   0,  if the new directory doesn't exist.               //
       //                                                                 //
       /////////////////////////////////////////////////////////////////////
       TDataSet *nextSet = 0;
       if (Cwd()) {
          TDataSetIter next(Cwd(),0);
          while ( (nextSet = next()) )
             if (ds == nextSet) {fWorkingDataSet = ds; break;}
       }
       return nextSet;
    }

    //______________________________________________________________________________
     TDataSet *TDataSetIter::Dir(Char_t *dirname)
    {
       //
       // Print the names of the TDataSet objects for the datatset named with "dirname"
       // apart of TDataSet::Ls()  this method prints one level only
       //
       TDataSet *set = (TDataSet *)fWorkingDataSet;
       if (dirname) set = Find(dirname);
       if (set) set->ls();
       return set;
    }

    //______________________________________________________________________________
     Int_t TDataSetIter::Du() const {
       // summarize dataset usage by Herb Ward proposal
       if (!fWorkingDataSet) return 0;
       TDataSetIter next(fWorkingDataSet,0);
       TDataSet *nextset = 0;
       Int_t count = 0;
       while((nextset = (count) ? next():fWorkingDataSet)) {
          count++;
          if (nextset->IsFolder()) cout << endl;
          TString path = nextset->Path();
          cout << setw(2) << next.GetDepth() << ". ";
          cout << path << setw(TMath::Max(Int_t(60-strlen(path.Data())),Int_t(0))) << "...";
          const Char_t *type = nextset->IsFolder() ? "directory" : "table" ;
          cout << setw(10) << type;
          cout  << " : " << setw(10) << nextset->GetTitle();
          cout << endl;
       }
       return count;
    }

    //______________________________________________________________________________
     TDataSet  *TDataSetIter::FindByName(const Char_t *name,const Char_t *path,Option_t *opt)
    { return FindDataSet(name,path,opt);}

    //______________________________________________________________________________
     TDataSet  *TDataSetIter::FindByTitle(const Char_t *title,const Char_t *path,Option_t *opt)
    {
       TString optt = "-t";
       optt += opt;
       return FindDataSet(title,path,optt.Data());
    }

    //______________________________________________________________________________
     TDataSet *TDataSetIter::FindDataSet(const Char_t *name,const Char_t *path,Option_t *opt)
    {
       //
       // FindDataSet looks for the object with the name supplied across dataset.
       //
       // name        - the "base" name title (with no path) of the TDataSet (see: opt = -t)
       // path        - path to start the search from (the current dataset "by default")
       // opt = "-i"  - case insensitive search
       //       "-t"  - first <name> parameter defines the object "title" rather the object "name"
       //
       // Note: If the name provided is not unique
       //       the first found is returned.
       //

       if (!name || strlen(name) == 0) return 0;
       if (strchr(name,'/')) {
          Error("FindDataSet","The name of the object <%s> can not contain any \"/\"",name);
          return 0;
       }

       Bool_t opti = opt ? strcasecmp(opt,"-i") == 0 : kFALSE;
       Bool_t optt = opt ? strcasecmp(opt,"-t") == 0 : kFALSE;

       TDataSet *startset = 0;
       if (path && strlen(path)) startset = Find(path);
       else                      startset = fWorkingDataSet;
       if (!startset) return 0;

       TDataSet *set = startset;
       if ( !((opti && strcasecmp( optt ? set->GetTitle() : set->GetName(),name) == 0 ) ||
          (strcmp(optt ? set->GetTitle() : set->GetName(),name) == 0)) )
       {
          TDataSetIter next(startset,0);
          while ((set = next()))
             if ( (opti && strcasecmp(optt ? set->GetTitle() : set->GetName(),name) == 0 ) ||
                (strcmp(optt ? set->GetTitle() : set->GetName(),name) == 0) )           break;
       }

       return set;
    }

    //______________________________________________________________________________
     TDataSet *TDataSetIter::FindDataSet(TDataSet *set,const Char_t *path,Option_t *opt)
    {
       //
       // Check whether the object does belong the TDataSet defined with "path"
       // opt = "-l"  - check the "reference" links only
       //       "-s"  - check the "structural" links only
       //             = "by default" - checks all links
       //
       if (!set) return 0;
       if (opt) {/* no used */}

       TDataSet *startset = 0;
       if (path) startset = Find(path);
       else      startset = fWorkingDataSet;
       if (!startset) return 0;

       TDataSetIter next(startset);
       TDataSet *nextSet = 0;
       while ( (nextSet = next()) )
          if (set == nextSet) break;

       return nextSet;
    }
    //______________________________________________________________________________
     TObject *TDataSetIter::FindObject(const Char_t *name) const
    {
       // This method is not recommended.
       // It is done to back TObject::FindObject method only.
       // One is recommnened to use FindByName method instead.
       return ((TDataSetIter *)this)->FindByName(name);
    }

    //______________________________________________________________________________
     TObject  *TDataSetIter::FindObject(const TObject *dataset) const
    {
       // This method is not recommended.
       // It is done to back TObject::FindObject method only.
       // One is recommended to use FindByName method instead.
       return ((TDataSetIter *)this)->FindByPointer((TDataSet *)dataset);
    }
    //______________________________________________________________________________
     TDataSet *TDataSetIter::FindByPointer(TDataSet *set,const Char_t *path,Option_t *)
    {
       //
       // Check whether the object does belong the TDataSet defined with "path"
       // opt = "-l"  - check the "reference" links only
       //       "-s"  - check the "structural" links only
       //             = "by default" - checks all links
       //
       if (!set) return 0;

       TDataSet *startset = 0;
       if (path && path[0]) startset = Find(path);
       else      startset = fWorkingDataSet;
       if (!startset) return 0;

       TDataSetIter next(startset);
       TDataSet *nextSet = 0;
       while ( (nextSet = next()) )
          if (set == nextSet) break;

       return nextSet;
    }

    //______________________________________________________________________________
     Int_t TDataSetIter::Flag(const Char_t *path,UInt_t flag,TDataSet::EBitOpt reset)
    {
       TDataSet *set = Find(path);
       if (set) set->SetBit(flag,reset);
       return 0;
    }
    //______________________________________________________________________________
     Int_t TDataSetIter::Flag(TDataSet *dataset,UInt_t flag,TDataSet::EBitOpt reset)
    {
       if (dataset) dataset->SetBit(flag,reset);
       return 0;
    }

    //______________________________________________________________________________
     TDataSet *TDataSetIter::Ls(const Char_t *dirname,Option_t *opt) const {
       //
       //   Ls(const Char_t *dirname,Option_t)
       //
       //   Prints the list of the TDataSet defined with dirname
       //
       //   dirname     = 0   - prints the current dataset
       //   dirname[0]  = '/' - print TDataSet defined with dirname
       //   dirname[0] != '/' - prints DataSet with respect of the current class
       //

       TDataSet *set= 0;
       if (dirname && strlen(dirname)) set = ((TDataSetIter*)this)->Find(dirname);
       if (!set && dirname==0) set=Cwd();
       if (set) set->ls(opt);
       return set;
    }

    //______________________________________________________________________________
     TDataSet *TDataSetIter::Ls(const Char_t *dirname,Int_t depth) const {
       //
       //   Ls(const Char_t *dirname,Int_t depth)
       //
       //   Prints the list of the TDataSet defined with dirname
       //   Returns the dataset defined by "path" or Cwd();
       //
       //   dirname     = 0   - prints the current dataset
       //   dirname[0]  = '/' - print TDataSet defined with dirname
       //   dirname[0] != '/' - prints DataSet with respect of the current class
       //
       //   depth       = 0   - print all level of the TDataSet defined with dirname
       //               > 0   - print depth levels at most of the dirname TDataSet
       //
       TDataSet *set= fWorkingDataSet;
       if (dirname && strlen(dirname)) set= ((TDataSetIter*)this)->Find(dirname);
       if (set) set->ls(depth);
       return set;
    }

    //______________________________________________________________________________
     TDataSet *TDataSetIter::Mkdir(const Char_t *dirname)
    {
       TDataSet *set = 0;
       set = Find(dirname,0,kTRUE);
       if (!fNext)  Reset();  // Create a new iterator
       // If this dataset is first one then make it the root and working
       if (!fRootDataSet ) fRootDataSet  = set;
       if (!fWorkingDataSet) fWorkingDataSet = fRootDataSet;
       return set;
    }

    //______________________________________________________________________________
     void TDataSetIter::Notify(TDataSet *)
    {
       //
       //  Notify(TDataSet *dataset)
       //
       //  This dummy method is called when TDataSetIter::Find dives in "dataset"
       //  to look for thew next level of the dataset's
       //  printf("void TDataSetIter::Notify(TDataSet *) level: %d %s\n",fDepth,ds->GetName());
       //
    }

    //______________________________________________________________________________
     TDataSet *TDataSetIter::Rmdir(TDataSet *dataset,Option_t *)
    {
       //
       //  Remove the TDataSet *dataset from the current dataset
       //  If the current dataset is the deleted dataset the its parent
       //  becomes the "current dataset" or 0 if this dataset has no parent.
       //
       //  returns: the "current dataset" pointer
       //
       //
       TDataSet *set = dataset;
       if (set) {
          if (set == fWorkingDataSet) {
             fWorkingDataSet = set->GetParent();
          }
          if (set == fRootDataSet) {
             fRootDataSet = 0;
          }
          delete set;
       }
       return Cwd();
    }

    //______________________________________________________________________________
     TDataSet *TDataSetIter::Next( TDataSet::EDataSetPass mode)
    {
       ////////////////////////////////////////////////////////////////////////////////
       //
       // returns the pointer the "next" TDataSet object
       //         = 0 if all objects have been returned.
       //
       //  mode = kContinue  - default normal mode
       //         kPrune     - stop passing of the current branch but continue with the next one if any
       //         kUp        - break passing, return to the previous level, then continue
       //         all other  - are treated as "kContinue"
       //
       ////////////////////////////////////////////////////////////////////////////////

       if (fMaxDepth==1) fDataSet = fNext ? NextDataSet(*fNext) :0;
       else {
          // Check the whether the next level does exist
          if (fDepth==0) fDepth = 1;
          if (fDataSet && fDataSet != fNullDataSet &&
             (fDepth < fMaxDepth || fMaxDepth ==0) && mode == TDataSet::kContinue )
          {
             // create the next level iterator, go deeper
             TSeqCollection *list  = fDataSet->GetCollection();
             // Look for the next level
             if (list && list->GetSize() ) {
                fDepth++;
                if (fDepth >= 100) {
                   Error("Next()"
                      ," too many (%d) nested levels of your TDataSet has been detected",fDepth);
                   return 0;
                }
                fNextSet[fDepth-1] = new TIter(list);
             }
          }

          // Pick the next object of the current level
          TIter *next = fNextSet[fDepth-1];
          if (next) {
             fDataSet = 0;
             if (mode != TDataSet::kUp) fDataSet = NextDataSet(*next);

             // Go upstair if the current one has been escaped
             if (!fDataSet) {
                // go backwards direction
                while (!fDataSet && fDepth > 1) {
                   fDepth--;
                   delete next;
                   next =  fNextSet[fDepth-1];
                   TDataSet *set = NextDataSet(*next);
                   if (set)
                      fDataSet = set;
                }
             }
          }
       }
       return (TDataSet *)fDataSet;
    }
    //______________________________________________________________________________
     TDataSet *TDataSetIter::NextDataSet(TIter &next){
       TDataSet *ds = (TDataSet *)next();
       if (ds) Notify(ds);
       return ds;
    }

    //______________________________________________________________________________
     TDataSet *TDataSetIter::NextDataSet(Int_t nDataSet)
    {
       // Pick the next object of the  level provided
       TIter *next = fNextSet[nDataSet];
       if (next) return NextDataSet(*next);
       return 0;
    }
    //______________________________________________________________________________
     TDataSet  *TDataSetIter::FindByPath(const Char_t *path, TDataSet *rootset,Bool_t mkdir)
    { return Find(path,rootset,mkdir);}

    //______________________________________________________________________________
     TDataSet *TDataSetIter::Find(const Char_t *path, TDataSet *rootset,
                                 Bool_t mkdirflag,Bool_t titleFlag)
    {
       ////////////////////////////////////////////////////////////////////////////////
       //                                                                            //
       //     titleFlag = kFALSE; use object name as key (by default)                //
       //                 kTRUE;  use object title as key  and ignore mkdirFlag      //
       //                                                                            //
       //           "path" ::= <relative path> | <absolute path> | <empty>           //
       //                                                                            //
       //  "relative path" ::= <dataset name> | <dataset name>/<dataset name>        //
       //                                                                            //
       //  "absolute path" ::= /<relative path>                                      //
       //  "empty"         ::= zero pointer | pointer to zero length string          //
       //                                                                            //
       // "relative path": the search is done against of fWorkingDataSet data mem    //
       // "absolute path": the search is done against of fRootDataSet    data mem    //
       // "empty path"   : no search is done just next TDataSet is returned if any   //
       //                                                                            //
       //  Remark: This version can not treat any "special name" like "..", ".", etc //
       //  ------                                                                    //
       ////////////////////////////////////////////////////////////////////////////////
       TDataSet *dataset=0,*dsnext=0,*ds=0;
       Int_t len=0,nextlen=0,yes=0,anywhere=0,rootdir=0;
       const Char_t *name=0,*nextname=0;
       TSeqCollection *tl=0;

       name = path;
       if (!name) return rootset;
       dataset = rootset;
       if (!dataset) {// Starting point
          rootdir = 1999;
          dataset = (path[0]=='/') ? fRootDataSet:fWorkingDataSet;}

       if (name[0] == '/') name++;

       if (!strncmp(name,".*/",3)) {anywhere=1998; name +=3;}

       len = strcspn(name," /");
       if (!len) return dataset;

       if (!dataset) goto NOTFOUND;

       //      Check name of root directory
       if (rootdir)
       {
          nextname = titleFlag ? dataset->GetTitle() : dataset->GetName();
          nextlen  = strlen(nextname);
          if (nextlen==len && !strncmp(name,nextname,len))
             return Find(name+len,dataset,mkdirflag,titleFlag);
       }

       tl = dataset->GetCollection();
       if (tl) {
          TIter next(tl);
          while ( (dsnext = NextDataSet(next)) )
          { //horisontal loop
             nextname = titleFlag ? dataset->GetTitle() : dsnext->GetName();
             if (!nextname)  continue;
             yes = name[0]=='*';     // wildcard test
             if (!yes) {             // real     test
                nextlen  = strlen(nextname);
                yes = (len == nextlen);
                if (yes)
                   yes = !strncmp(name,nextname,len);
             }

             if (yes)
             {//go down
                if (fDepth == 0) fDepth = 1;
                Notify(dsnext);
                fDepth++;
                ds = Find(name+len,dsnext,mkdirflag,titleFlag);
                fDepth--;
                if (ds)
                   return ds;
             }

             if (!anywhere) continue;        // next horizontal
             ds = Find(name,dsnext,mkdirflag,titleFlag);
             if (ds)
                return ds;
          }                                  // end of while
       }

    NOTFOUND:
       if (mkdirflag && !titleFlag)
       {
          // create dir the same type as the type of the fRootDataSet if present
          // Create TDataSet by default.
          char buf[512];buf[0]=0; strncat(buf,name,len);
          if (!fRootDataSet)
             ds = new TDataSet(buf);
          else {
             ds = fRootDataSet->Instance();
             ds->SetName(buf);
          }

          if (!fRootDataSet)         fRootDataSet    = ds;
          if (!fWorkingDataSet)      fWorkingDataSet = ds;
          if (dataset)
             dataset->Add(ds);
          else {
             dataset = ds;
             name +=len;
          }

          return Find(name,dataset,mkdirflag);
       }

       return 0;
    }
    //______________________________________________________________________________
     void TDataSetIter::Reset(TDataSet *l, int depth)
    {
       //
       // TDataSet *l != 0 means the new start pointer
       //    depth      != 0 means the new value for the depth
       //                    otherwise the privious one is used;
       //
       fDataSet = fNullDataSet;
       if (fMaxDepth != 1) {
          // clean all interators
          Int_t level = fDepth;
          if (level) level--;
          for (int i = level;i>=0;i--) {
             TIter *s = fNextSet[i];
             if (s) delete s;
          }
          fNext = 0; // this iterator has been deleted in the loop above
       }

       fDepth = 0;

       if (l) {
          fRootDataSet    = l;
          fWorkingDataSet = l;
          SafeDelete(fNext);
          if (fRootDataSet->GetCollection() )
             fNext = new TIter(fRootDataSet->GetCollection() );
       }
       else {
          fWorkingDataSet = fRootDataSet;
          if (fNext)
             fNext->Reset();
          else if (fRootDataSet && fRootDataSet->GetCollection() )
             fNext = new TIter(fRootDataSet->GetCollection() );
       }
       // set the new value of the maximum depth to bypass
       if (depth) fMaxDepth = depth;
    }
    //______________________________________________________________________________
     TDataSet *TDataSetIter::Shunt(TDataSet *set, TDataSet *dataset)
    {
       ///////////////////////////////////////////////////////////////////////////////
       //                                                                           //
       // Shunt - moves the set to the dataset defined with the second parameters   //
       //                                                                           //
       // TDataSet dataset != 0 - Add the set to the TDataSet *dataset              //
       //                                                                           //
       //                     = 0 - (by default) to the current TDataSet defined    //
       //                          with fWorkingDataSet data member                 //
       //                                                                           //
       //  returns  the pointer to set if successful or ZERO pointer                //
       //  =======                                                                  //
       //                                                                           //
       //  Note: If this TDataSetIter is empty (i.e. Cwd() returns 0), the "set"    //
       //        becomes the "root" dataset of this iterator                        //                                                                         //
       ///////////////////////////////////////////////////////////////////////////////

       if (!set) return 0;
       TDataSet *s =  dataset;
       if (!s) s = Cwd();
       if (s) {
          s->Shunt(set);
          s = set;
       }
       else {
          //  make the coming dataset the current one for the iterator
          s = set;
          fRootDataSet    = s;
          fWorkingDataSet = s;
          if (fNext) {
             Error("Shunt","TDataSetIter.has been corrupted ;-!");
             delete fNext;
             fNext = 0;
          }
          fNext = new TIter(s->GetCollection() );
       }
       return s;
    }

    //______________________________________________________________________________
     TDataSet *TDataSetIter::Shunt(TDataSet *dataset, const Char_t *path)
    {
       ///////////////////////////////////////////////////////////////////////////////
       //                                                                           //
       // Shunt                                                                     //
       //                                                                           //
       // Char_t path != 0 - Move a TDataSet dataset from its parent to             //
       //                    the TDataSet dataset                                   //
       //                    defined with "path"                                    //
       //              = 0 - (by default) to the current TDataSet defined           //
       //                    with fWorkingDataSet data member                       //
       //                                                                           //
       //  returns the dataset is success or ZERO pointer                           //
       //  =======                                                                  //
       //                                                                           //
       ///////////////////////////////////////////////////////////////////////////////
       if (!dataset) return 0;
       TDataSet *set = 0;
       if (path && strlen(path)) set = Find(path);
       return Shunt(dataset,set);
    }

    //______________________________________________________________________________
    TDataSet *TDataSetIter::operator[](const Char_t *path)
    {
       //
       // operator [] returns the pointer to the TDataSet if it does contain
       // any data (TTable for example)
       //
       //  Input:
       //     path  = The path to the dataset to find
       //
       //  Output:
       //     pointer to the dataset if it found and
       //     its TDataSet::HasData() method returns non-zero
       //     (see for example TTable::HasData() )
       TDataSet *dataSet = Find(path);
       if (dataSet && dataSet->HasData()) return dataSet;
       return 0;
    }