// @(#)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;
}
