// $Id$
// Author: Sergey Linev   22/12/2013

#include "TRootSniffer.h"

#include "TH1.h"
#include "TGraph.h"
#include "TProfile.h"
#include "TCanvas.h"
#include "TFile.h"
#include "TKey.h"
#include "TList.h"
#include "TMemFile.h"
#include "TStreamerInfo.h"
#include "TBufferFile.h"
#include "TBufferJSON.h"
#include "TBufferXML.h"
#include "TROOT.h"
#include "TTimer.h"
#include "TFolder.h"
#include "TTree.h"
#include "TBranch.h"
#include "TLeaf.h"
#include "TClass.h"
#include "TMethod.h"
#include "TMethodArg.h"
#include "TMethodCall.h"
#include "TDataMember.h"
#include "TDataType.h"
#include "TBaseClass.h"
#include "TObjString.h"
#include "TUrl.h"
#include "TImage.h"
#include "RZip.h"
#include "TRootSnifferStore.h"
#include "THttpCallArg.h"

#include <stdlib.h>

const char *item_prop_kind = "_kind";
const char *item_prop_more = "_more";
const char *item_prop_title = "_title";
const char *item_prop_hidden = "_hidden";
const char *item_prop_typename = "_typename";
const char *item_prop_arraydim = "_arraydim";
const char *item_prop_realname = "_realname"; // real object name
const char *item_prop_user = "_username";

// ============================================================================

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TRootSnifferScanRec                                                  //
//                                                                      //
// Structure used to scan hierarchies of ROOT objects                   //
// Represents single level of hierarchy                                 //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

//______________________________________________________________________________
TRootSnifferScanRec::TRootSnifferScanRec() :
   fParent(0),
   fMask(0),
   fSearchPath(0),
   fLevel(0),
   fItemName(),
   fItemsNames(),
   fRestriction(0),
   fStore(0),
   fHasMore(kFALSE),
   fNodeStarted(kFALSE),
   fNumFields(0),
   fNumChilds(0)
{
   // constructor

   fItemsNames.SetOwner(kTRUE);
}

//______________________________________________________________________________
TRootSnifferScanRec::~TRootSnifferScanRec()
{
   // destructor

   CloseNode();
}

//______________________________________________________________________________
void TRootSnifferScanRec::SetField(const char *name, const char *value, Bool_t with_quotes)
{
   // record field for current element

   if (CanSetFields()) fStore->SetField(fLevel, name, value, with_quotes);
   fNumFields++;
}

//______________________________________________________________________________
void TRootSnifferScanRec::BeforeNextChild()
{
   // indicates that new child for current element will be started

   if (CanSetFields()) fStore->BeforeNextChild(fLevel, fNumChilds, fNumFields);
   fNumChilds++;
}

//______________________________________________________________________________
void TRootSnifferScanRec::MakeItemName(const char *objname, TString &itemname)
{
   // constructs item name from object name
   // if special symbols like '/', '#', ':', '&', '?'  are used in object name
   // they will be replaced with '_'.
   // To avoid item name duplication, additional id number can be appended

   std::string nnn = objname;

   size_t pos;

   // replace all special symbols which can make problem to navigate in hierarchy
   while ((pos = nnn.find_first_of("- []<>#:&?/\'\"\\")) != std::string::npos)
      nnn.replace(pos, 1, "_");

   itemname = nnn.c_str();
   Int_t cnt = 0;

   while (fItemsNames.FindObject(itemname.Data())) {
      itemname.Form("%s_%d", nnn.c_str(), cnt++);
   }

   fItemsNames.Add(new TObjString(itemname.Data()));
}

//______________________________________________________________________________
void TRootSnifferScanRec::BuildFullName(TString& buf, TRootSnifferScanRec* prnt)
{
   // Produce full name, including all parents

   if (!prnt) prnt = fParent;

   if (prnt) {
      prnt->BuildFullName(buf);

      buf.Append("/");
      buf.Append(fItemName);
   }
}


//______________________________________________________________________________
void TRootSnifferScanRec::CreateNode(const char *_node_name)
{
   // creates new node with specified name
   // if special symbols like "[]&<>" are used, node name
   // will be replaced by default name like "extra_item_N" and
   // original node name will be recorded as "_original_name" field
   // Optionally, object name can be recorded as "_realname" field

   if (!CanSetFields()) return;

   fNodeStarted = kTRUE;

   if (fParent) fParent->BeforeNextChild();

   if (fStore) fStore->CreateNode(fLevel, _node_name);
}

//______________________________________________________________________________
void TRootSnifferScanRec::CloseNode()
{
   // close started node

   if (fStore && fNodeStarted) {
      fStore->CloseNode(fLevel, fNumChilds);
      fNodeStarted = kFALSE;
   }
}

//______________________________________________________________________________
void TRootSnifferScanRec::SetRootClass(TClass *cl)
{
   // set root class name as node kind
   // in addition, path to master item (streamer info) specified
   // Such master item required to correctly unstream data on JavaScript

   if ((cl != 0) && CanSetFields())
      SetField(item_prop_kind, TString::Format("ROOT.%s", cl->GetName()));
}

//______________________________________________________________________________
Bool_t TRootSnifferScanRec::Done() const
{
   // returns true if scanning is done
   // Can happen when searched element is found

   if (fStore == 0)
      return kFALSE;

   if ((fMask & kSearch) && fStore->GetResPtr())
      return kTRUE;

   if ((fMask & kCheckChilds) && fStore->GetResPtr() &&
         (fStore->GetResNumChilds() >= 0))
      return kTRUE;

   return kFALSE;
}

//______________________________________________________________________________
Bool_t TRootSnifferScanRec::IsReadyForResult() const
{
   // Checks if result will be accepted.
   // Used to verify if sniffer should read object from the file

   if (Done()) return kFALSE;

   // only when doing search, result will be propagated
   if ((fMask & (kSearch | kCheckChilds)) == 0) return kFALSE;

   // only when full search path is scanned
   if (fSearchPath != 0) return kFALSE;

   if (fStore == 0) return kFALSE;

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootSnifferScanRec::SetResult(void *obj, TClass *cl, TDataMember *member)
{
   // set results of scanning

   if (Done()) return kTRUE;

   if (!IsReadyForResult()) return kFALSE;

   fStore->SetResult(obj, cl, member, fNumChilds, fRestriction);

   return Done();
}

//______________________________________________________________________________
Int_t TRootSnifferScanRec::Depth() const
{
   // returns current depth of scanned hierarchy

   Int_t cnt = 0;
   const TRootSnifferScanRec *rec = this;
   while (rec->fParent) {
      rec = rec->fParent;
      cnt++;
   }

   return cnt;
}

//______________________________________________________________________________
Bool_t TRootSnifferScanRec::CanExpandItem()
{
   // returns true if current item can be expanded - means one could explore
   // objects members

   if (fMask & (kExpand | kSearch | kCheckChilds)) return kTRUE;

   if (!fHasMore) return kFALSE;

   // if parent has expand mask, allow to expand item
   if (fParent && (fParent->fMask & kExpand)) return kTRUE;

   return kFALSE;
}

//______________________________________________________________________________
Bool_t TRootSnifferScanRec::IsReadOnly(Bool_t dflt)
{
   // returns read-only flag for current item
   // Depends from default value and current restrictions

   if (fRestriction==0) return dflt;

   return fRestriction!=2;
}

//______________________________________________________________________________
Bool_t TRootSnifferScanRec::GoInside(TRootSnifferScanRec &super, TObject *obj,
                                     const char *obj_name, TRootSniffer* sniffer)
{
   // Method verifies if new level of hierarchy
   // should be started with provided object.
   // If required, all necessary nodes and fields will be created
   // Used when different collection kinds should be scanned

   if (super.Done()) return kFALSE;

   if ((obj != 0) && (obj_name == 0)) obj_name = obj->GetName();

   // exclude zero names
   if ((obj_name == 0) || (*obj_name == 0)) return kFALSE;

   const char *full_name = 0;

   // remove slashes from file names
   if (obj && obj->InheritsFrom(TDirectoryFile::Class())) {
      const char *slash = strrchr(obj_name, '/');
      if (slash != 0) {
         full_name = obj_name;
         obj_name = slash + 1;
         if (*obj_name == 0) obj_name = "file";
      }
   }

   super.MakeItemName(obj_name, fItemName);

   if (sniffer && sniffer->HasRestriction(fItemName.Data())) {
      // check restriction more precisely
      TString fullname;
      BuildFullName(fullname, &super);
      fRestriction = sniffer->CheckRestriction(fullname.Data());
      if (fRestriction<0) return kFALSE;
   }

   fParent = &super;
   fLevel = super.fLevel;
   fStore = super.fStore;
   fSearchPath = super.fSearchPath;
   fMask = super.fMask & kActions;
   if (fRestriction==0) fRestriction = super.fRestriction; // get restriction from parent

   if (fMask & kScan) {
      // if scanning only fields, ignore all childs
      if (super.ScanOnlyFields()) return kFALSE;
      // only when doing scan, increment level, used for text formatting
      fLevel++;
   } else {
      if (fSearchPath == 0) return kFALSE;

      if (strncmp(fSearchPath, fItemName.Data(), fItemName.Length()) != 0)
         return kFALSE;

      const char *separ = fSearchPath + fItemName.Length();

      Bool_t isslash = kFALSE;
      while (*separ == '/') {
         separ++;
         isslash = kTRUE;
      }

      if (*separ == 0) {
         fSearchPath = 0;
         if (fMask & kExpand) {
            fMask = (fMask & kOnlyFields) | kScan;
            fHasMore = (fMask & kOnlyFields) == 0;
         }
      } else {
         if (!isslash) return kFALSE;
         fSearchPath = separ;
      }
   }

   CreateNode(fItemName.Data());

   if ((obj_name != 0) && (fItemName != obj_name))
      SetField(item_prop_realname, obj_name);

   if (full_name != 0)
      SetField("_fullname", full_name);

   return kTRUE;
}


// ====================================================================

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TRootSniffer                                                         //
//                                                                      //
// Sniffer of ROOT objects, data provider for THttpServer               //
// Provides methods to scan different structures like folders,          //
// directories, files, trees, collections                               //
// Can locate objects (or its data member) per name                     //
// Can be extended to application-specific classes                      //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

//______________________________________________________________________________
TRootSniffer::TRootSniffer(const char *name, const char *objpath) :
   TNamed(name, "sniffer of root objects"),
   fObjectsPath(objpath),
   fMemFile(0),
   fSinfo(0),
   fReadOnly(kTRUE),
   fScanGlobalDir(kTRUE),
   fCurrentArg(0),
   fCurrentRestrict(0),
   fCurrentAllowedMethods(0),
   fRestrictions()
{
   // constructor

   fRestrictions.SetOwner(kTRUE);
}

//______________________________________________________________________________
TRootSniffer::~TRootSniffer()
{
   // destructor

   if (fSinfo) {
      delete fSinfo;
      fSinfo = 0;
   }

   if (fMemFile) {
      delete fMemFile;
      fMemFile = 0;
   }
}

//______________________________________________________________________________
void TRootSniffer::SetCurrentCallArg(THttpCallArg* arg)
{
   // set current http arguments, which then used in different process methods
   // For instance, if user authorized with some user name,
   // depending from restrictions some objects will be invisible
   // or user get full access to the element

   fCurrentArg = arg;
   fCurrentRestrict = 0;
   fCurrentAllowedMethods = "";
}

//______________________________________________________________________________
void TRootSniffer::Restrict(const char* path, const char* options)
{
   // Restrict access to the specified location
   //
   // Hides or provides read-only access to different parts of the hierarchy
   // Restriction done base on user-name specified with http requests
   // Options can be specified in URL style (separated with &)
   // Following parameters can be specified:
   //    visible = [all|user(s)] - make item visible for all users or only specified user
   //    hidden = [all|user(s)] - make item hidden from all users or only specified user
   //    readonly = [all|user(s)] - make item read-only for all users or only specified user
   //    allow = [all|user(s)] - make full access for all users or only specified user
   //    allow_method = method(s)  - allow method(s) execution even when readonly flag specified for the object
   // Like make command seen by all but can be executed only by admin
   //    sniff->Restrict("/CmdReset","allow=admin");
   // Or fully hide command from guest account
   //    sniff->Restrict("/CmdRebin","hidden=guest");

   const char* rslash = strrchr(path,'/');
   if (rslash) rslash++;
   if ((rslash==0) || (*rslash==0)) rslash = path;

   fRestrictions.Add(new TNamed(rslash, TString::Format("%s%s%s", path,"%%%",options).Data()));
}

//______________________________________________________________________________
Bool_t TRootSniffer::HasRestriction(const char* item_name)
{
   // Made fast check if item with specified name is in restriction list
   // If returns true, requires precise check with CheckRestriction() method

   if ((item_name==0) || (*item_name==0) || (fCurrentArg==0)) return kFALSE;

   return fRestrictions.FindObject(item_name)!=0;
}

//______________________________________________________________________________
Int_t TRootSniffer::WithCurrentUserName(const char* option)
{
   // return 2 when option match to current user name
   // return 1 when option==all
   // return 0 when option does not match user name

   const char* username = fCurrentArg ? fCurrentArg->GetUserName() : 0;

   if ((username==0) || (option == 0) || (*option==0)) return 0;

   if (strcmp(option,"all") == 0) return 1;

   if (strcmp(username, option) == 0) return 2;

   if (strstr(option, username) == 0) return -1;

   TObjArray* arr = TString(option).Tokenize(",");

   Bool_t find = arr->FindObject(username) != 0;

   delete arr;

   return find ? 2 : -1;
}

//______________________________________________________________________________
Int_t TRootSniffer::CheckRestriction(const char* full_item_name)
{
   // Checked if restriction is applied to the item
   // full_item_name should have full path to the item
   //
   // Returns -1 - object invisible, cannot be accessed or listed
   //          0 -  no explicit restrictions, use default
   //          1 - read-only access
   //          2 - full access

   if ((full_item_name==0) || (*full_item_name==0)) return 0;

   const char* item_name = strrchr(full_item_name,'/');
   if (item_name) item_name++;
   if ((item_name==0) || (*item_name==0)) item_name = full_item_name;

   TString pattern1 = TString("*/") + item_name + "%%%";
   TString pattern2 = TString(full_item_name) + "%%%";

   const char* options = 0;
   TIter iter(&fRestrictions);
   TObject* obj;

   while ((obj = iter()) != 0) {
      const char* title = obj->GetTitle();

      if (strstr(title,pattern1.Data())==title) { options = title + pattern1.Length(); break; }
      if (strstr(title,pattern2.Data())==title) { options = title + pattern2.Length(); break; }
   }

   if (options==0) return 0;

   TUrl url;
   url.SetOptions(options);
   url.ParseOptions();

   Int_t can_see = WithCurrentUserName(url.GetValueFromOptions("visible")) -
                   WithCurrentUserName(url.GetValueFromOptions("hidden"));

   Int_t can_access = WithCurrentUserName(url.GetValueFromOptions("allow")) -
                      WithCurrentUserName(url.GetValueFromOptions("readonly"));

   if (can_access > 0) return 2; // first of all, if access enabled, provide it
   if (can_see < 0) return -1; // if object to be hidden, do it

   const char* methods = url.GetValueFromOptions("allow_method");
   if (methods!=0) fCurrentAllowedMethods = methods;

   if (can_access < 0) return 1; // read-only access

   return 0; // default behavior
}

//______________________________________________________________________________
void TRootSniffer::ScanObjectMemebers(TRootSnifferScanRec &rec, TClass *cl,
                                      char *ptr, unsigned long int cloffset)
{
   // scan object data members
   // some members like enum or static members will be excluded

   if ((cl == 0) || (ptr == 0) || rec.Done()) return;

   // ensure that real class data (including parents) exists
   if (!(cl->Property() & kIsAbstract)) cl->BuildRealData();

   // first of all expand base classes
   TIter cliter(cl->GetListOfBases());
   TObject *obj = 0;
   while ((obj = cliter()) != 0) {
      TBaseClass *baseclass = dynamic_cast<TBaseClass *>(obj);
      if (baseclass == 0) continue;
      TClass *bclass = baseclass->GetClassPointer();
      if (bclass == 0) continue;

      // all parent classes scanned within same hierarchy level
      // this is how normal object streaming works
      ScanObjectMemebers(rec, bclass, ptr, cloffset + baseclass->GetDelta());
      if (rec.Done()) break;
   }

   // than expand data members
   TIter iter(cl->GetListOfDataMembers());
   while ((obj = iter()) != 0) {
      TDataMember *member = dynamic_cast<TDataMember *>(obj);
      // exclude enum or static variables
      if ((member == 0) || (member->Property() & (kIsStatic | kIsEnum | kIsUnion))) continue;
      char *member_ptr = ptr + cloffset + member->GetOffset();

      if (member->IsaPointer()) member_ptr = *((char **) member_ptr);

      TRootSnifferScanRec chld;

      if (chld.GoInside(rec, member, 0, this)) {

         TClass *mcl = (member->IsBasic() || member->IsSTLContainer()) ? 0 :
                       gROOT->GetClass(member->GetTypeName());

         Int_t coll_offset = mcl ? mcl->GetBaseClassOffset(TCollection::Class()) : -1;

         Bool_t iscollection = (coll_offset >= 0);
         if (iscollection) {
            chld.SetField(item_prop_more, "true", kFALSE);
            chld.fHasMore = kTRUE;
         }

         if (chld.SetResult(member_ptr, mcl, member)) break;

         const char *title = member->GetTitle();
         if ((title != 0) && (strlen(title) != 0))
            chld.SetField(item_prop_title, title);

         if (member->GetTypeName())
            chld.SetField(item_prop_typename, member->GetTypeName());

         if (member->GetArrayDim() > 0) {
            // store array dimensions in form [N1,N2,N3,...]
            TString dim("[");
            for (Int_t n = 0; n < member->GetArrayDim(); n++) {
               if (n > 0) dim.Append(",");
               dim.Append(TString::Format("%d", member->GetMaxIndex(n)));
            }
            dim.Append("]");
            chld.SetField(item_prop_arraydim, dim, kFALSE);
         }

         chld.SetRootClass(mcl);

         if (chld.CanExpandItem()) {
            if (iscollection) {
               // chld.SetField("#members", "true", kFALSE);
               ScanCollection(chld, (TCollection *)(member_ptr + coll_offset));
            }
         }

         if (chld.SetResult(member_ptr, mcl, member)) break;
      }
   }
}

//_____________________________________________________________________
void TRootSniffer::ScanObjectProperties(TRootSnifferScanRec & /*rec*/, TObject * /*obj*/)
{
   // scans object properties
   // here such fields as _autoload or _icon properties depending on class or object name could be assigned
}

//_____________________________________________________________________
void TRootSniffer::ScanObjectChilds(TRootSnifferScanRec &rec, TObject *obj)
{
   // scans object childs (if any)
   // here one scans collection, branches, trees and so on

   if (obj->InheritsFrom(TFolder::Class())) {
      ScanCollection(rec, ((TFolder *) obj)->GetListOfFolders());
   } else if (obj->InheritsFrom(TDirectory::Class())) {
      TDirectory *dir = (TDirectory *) obj;
      ScanCollection(rec, dir->GetList(), 0, dir->GetListOfKeys());
   } else if (obj->InheritsFrom(TTree::Class())) {
      if (!rec.IsReadOnly(fReadOnly)) {
         rec.SetField("_player", "JSROOT.drawTreePlayer");
         rec.SetField("_prereq", "jq2d");
      }
      ScanCollection(rec, ((TTree *) obj)->GetListOfLeaves());
   } else if (obj->InheritsFrom(TBranch::Class())) {
      ScanCollection(rec, ((TBranch *) obj)->GetListOfLeaves());
   } else if (rec.CanExpandItem()) {
      ScanObjectMemebers(rec, obj->IsA(), (char *) obj, 0);
   }
}

//______________________________________________________________________________
void TRootSniffer::ScanCollection(TRootSnifferScanRec &rec, TCollection *lst,
                                  const char *foldername, TCollection *keys_lst)
{
   // scan collection content

   if (((lst == 0) || (lst->GetSize() == 0)) && ((keys_lst == 0) || (keys_lst->GetSize() == 0))) return;

   TRootSnifferScanRec folderrec;
   if (foldername) {
      if (!folderrec.GoInside(rec, 0, foldername, this)) return;
   }

   TRootSnifferScanRec &master = foldername ? folderrec : rec;

   if (lst != 0) {
      TIter iter(lst);
      TObject *next = iter();
      Bool_t isany = kFALSE;

      while (next!=0) {
         if (IsItemField(next)) {
            // special case - in the beginning one could have items for master folder
            if (!isany && (next->GetName() != 0) && ((*(next->GetName()) == '_') || master.ScanOnlyFields()))
               master.SetField(next->GetName(), next->GetTitle());
            next = iter();
            continue;
         }

         isany = kTRUE;
         TObject* obj = next;

         TRootSnifferScanRec chld;
         if (!chld.GoInside(master, obj, 0, this)) { next = iter(); continue; }

         if (chld.SetResult(obj, obj->IsA())) return;

         Bool_t has_kind(kFALSE), has_title(kFALSE);

         ScanObjectProperties(chld, obj);
         // now properties, coded as TNamed objects, placed after object in the hierarchy
         while ((next = iter()) != 0) {
            if (!IsItemField(next)) break;
            if ((next->GetName() != 0) && ((*(next->GetName()) == '_') || chld.ScanOnlyFields())) {
               // only fields starting with _ are stored
               chld.SetField(next->GetName(), next->GetTitle());
               if (strcmp(next->GetName(), item_prop_kind)==0) has_kind = kTRUE;
               if (strcmp(next->GetName(), item_prop_title)==0) has_title = kTRUE;
            }
         }

         if (!has_kind) chld.SetRootClass(obj->IsA());
         if (!has_title && (obj->GetTitle()!=0)) chld.SetField(item_prop_title, obj->GetTitle());

         ScanObjectChilds(chld, obj);

         if (chld.SetResult(obj, obj->IsA())) return;
      }
   }

   if (keys_lst != 0) {
      TIter iter(keys_lst);
      TObject *kobj(0);

      while ((kobj = iter()) != 0) {
         TKey *key = dynamic_cast<TKey *>(kobj);
         if (key == 0) continue;
         TObject *obj = (lst == 0) ? 0 : lst->FindObject(key->GetName());

         // even object with the name exists, it should also match with class name
         if ((obj!=0) && (strcmp(obj->ClassName(),key->GetClassName())!=0)) obj = 0;

         // if object of that name and of that class already in the list, ignore appropriate key
         if ((obj != 0) && (master.fMask & TRootSnifferScanRec::kScan)) continue;

         Bool_t iskey = kFALSE;
         // if object not exists, provide key itself for the scan
         if (obj == 0) { obj = key; iskey = kTRUE; }

         TRootSnifferScanRec chld;
         TString fullname = TString::Format("%s;%d", key->GetName(), key->GetCycle());

         if (chld.GoInside(master, obj, fullname.Data(), this)) {

            if (!chld.IsReadOnly(fReadOnly) && iskey && chld.IsReadyForResult()) {
               TObject *keyobj = key->ReadObj();
               if (keyobj != 0)
                  if (chld.SetResult(keyobj, keyobj->IsA())) return;
            }

            if (chld.SetResult(obj, obj->IsA())) return;

            TClass *obj_class = obj->IsA();

            ScanObjectProperties(chld, obj);

            if (obj->GetTitle()!=0) chld.SetField(item_prop_title, obj->GetTitle());

            // special handling of TKey class - in non-readonly mode
            // sniffer allowed to fetch objects
            if (!chld.IsReadOnly(fReadOnly) && iskey) {
               if (strcmp(key->GetClassName(), "TDirectoryFile") == 0) {
                  if (chld.fLevel == 0) {
                     TDirectory *dir = dynamic_cast<TDirectory *>(key->ReadObj());
                     if (dir != 0) {
                        obj = dir;
                        obj_class = dir->IsA();
                     }
                  } else {
                     chld.SetField(item_prop_more, "true", kFALSE);
                     chld.fHasMore = kTRUE;
                  }
               } else {
                  obj_class = TClass::GetClass(key->GetClassName());
               }
            }

            rec.SetRootClass(obj_class);

            ScanObjectChilds(chld, obj);

            // here we should know how many childs are accumulated
            if (chld.SetResult(obj, obj_class)) return;
         }
      }
   }
}

//______________________________________________________________________________
void TRootSniffer::ScanRoot(TRootSnifferScanRec &rec)
{
   // scan complete ROOT objects hierarchy
   // For the moment it includes objects in gROOT directory
   // and list of canvases and files
   // Also all registered objects are included.
   // One could reimplement this method to provide alternative
   // scan methods or to extend some collection kinds

   rec.SetField(item_prop_kind, "ROOT.Session");
   if (fCurrentArg && fCurrentArg->GetUserName())
      rec.SetField(item_prop_user, fCurrentArg->GetUserName());

   // should be on the top while //root/http folder could have properties for itself
   TFolder *topf = dynamic_cast<TFolder *>(gROOT->FindObject("//root/http"));
   if (topf) {
      rec.SetField(item_prop_title, topf->GetTitle());
      ScanCollection(rec, topf->GetListOfFolders());
   }

   {
      TRootSnifferScanRec chld;
      if (chld.GoInside(rec, 0, "StreamerInfo", this)) {
         chld.SetField(item_prop_kind, "ROOT.TStreamerInfoList");
         chld.SetField(item_prop_title, "List of streamer infos for binary I/O");
         chld.SetField(item_prop_hidden, "true");
      }
   }

   if (IsScanGlobalDir()) {
      ScanCollection(rec, gROOT->GetList());

      ScanCollection(rec, gROOT->GetListOfCanvases(), "Canvases");

      ScanCollection(rec, gROOT->GetListOfFiles(), "Files");
   }
}

//______________________________________________________________________________
Bool_t TRootSniffer::IsDrawableClass(TClass *cl)
{
   // return true if object can be drawn

   if (cl == 0) return kFALSE;
   if (cl->InheritsFrom(TH1::Class())) return kTRUE;
   if (cl->InheritsFrom(TGraph::Class())) return kTRUE;
   if (cl->InheritsFrom(TCanvas::Class())) return kTRUE;
   if (cl->InheritsFrom(TProfile::Class())) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
void TRootSniffer::ScanHierarchy(const char *topname, const char *path,
                                 TRootSnifferStore *store, Bool_t only_fields)
{
   // scan ROOT hierarchy with provided store object

   TRootSnifferScanRec rec;
   rec.fSearchPath = path;
   if (rec.fSearchPath) {
      while(*rec.fSearchPath == '/') rec.fSearchPath++;
      if (*rec.fSearchPath == 0) rec.fSearchPath = 0;
   }

   // if path non-empty, we should find item first and than start scanning
   rec.fMask = (rec.fSearchPath == 0) ? TRootSnifferScanRec::kScan : TRootSnifferScanRec::kExpand;
   if (only_fields) rec.fMask |= TRootSnifferScanRec::kOnlyFields;

   rec.fStore = store;

   rec.CreateNode(topname);

   ScanRoot(rec);

   rec.CloseNode();
}

//______________________________________________________________________________
void *TRootSniffer::FindInHierarchy(const char *path, TClass **cl,
                                    TDataMember **member, Int_t *chld)
{
   // Search element with specified path
   // Returns pointer on element
   // Optionally one could obtain element class, member description
   // and number of childs. When chld!=0, not only element is searched,
   // but also number of childs are counted. When member!=0, any object
   // will be scanned for its data members (disregard of extra options)

   if (IsStreamerInfoItem(path)) {
      // special handling for streamer info
      CreateMemFile();
      if (cl && fSinfo) *cl = fSinfo->IsA();
      return fSinfo;
   }

   TRootSnifferStore store;

   TRootSnifferScanRec rec;
   rec.fSearchPath = path;
   rec.fMask = (chld != 0) ? TRootSnifferScanRec::kCheckChilds : TRootSnifferScanRec::kSearch;
   if (*rec.fSearchPath == '/') rec.fSearchPath++;
   rec.fStore = &store;

   ScanRoot(rec);

   if (cl) *cl = store.GetResClass();
   if (member) *member = store.GetResMember();
   if (chld) *chld = store.GetResNumChilds();

   // remember current restriction
   fCurrentRestrict = store.GetResRestrict();

   return store.GetResPtr();
}

//______________________________________________________________________________
TObject *TRootSniffer::FindTObjectInHierarchy(const char *path)
{
   // Search element in hierarchy, derived from TObject

   TClass *cl(0);

   void *obj = FindInHierarchy(path, &cl);

   return (cl != 0) && (cl->GetBaseClassOffset(TObject::Class()) == 0) ? (TObject *) obj : 0;
}

//______________________________________________________________________________
ULong_t TRootSniffer::GetStreamerInfoHash()
{
   // Returns hash value for streamer infos
   // At the moment - just number of items in streamer infos list.

   return fSinfo ? fSinfo->GetSize() : 0;
}

//______________________________________________________________________________
ULong_t TRootSniffer::GetItemHash(const char *itemname)
{
   // Get hash function for specified item
   // used to detect any changes in the specified object

   if (IsStreamerInfoItem(itemname)) return GetStreamerInfoHash();

   TObject *obj = FindTObjectInHierarchy(itemname);

   return obj == 0 ? 0 : TString::Hash(obj, obj->IsA()->Size());
}

//______________________________________________________________________________
Bool_t TRootSniffer::CanDrawItem(const char *path)
{
   // Method verifies if object can be drawn

   TClass *obj_cl(0);
   void *res = FindInHierarchy(path, &obj_cl);
   return (res != 0) && IsDrawableClass(obj_cl);
}

//______________________________________________________________________________
Bool_t TRootSniffer::CanExploreItem(const char *path)
{
   // Method returns true when object has childs or
   // one could try to expand item

   TClass *obj_cl(0);
   Int_t obj_chld(-1);
   void *res = FindInHierarchy(path, &obj_cl, 0, &obj_chld);
   return (res != 0) && (obj_chld > 0);
}

//______________________________________________________________________________
void TRootSniffer::CreateMemFile()
{
   // Creates TMemFile instance, which used for objects streaming
   // One could not use TBufferFile directly,
   // while one also require streamer infos list

   if (fMemFile != 0) return;

   TDirectory *olddir = gDirectory;
   gDirectory = 0;
   TFile *oldfile = gFile;
   gFile = 0;

   fMemFile = new TMemFile("dummy.file", "RECREATE");
   gROOT->GetListOfFiles()->Remove(fMemFile);

   TH1F *d = new TH1F("d", "d", 10, 0, 10);
   fMemFile->WriteObject(d, "h1");
   delete d;

   TGraph *gr = new TGraph(10);
   gr->SetName("abc");
   //      // gr->SetDrawOptions("AC*");
   fMemFile->WriteObject(gr, "gr1");
   delete gr;

   fMemFile->WriteStreamerInfo();

   // make primary list of streamer infos
   TList *l = new TList();

   l->Add(gROOT->GetListOfStreamerInfo()->FindObject("TGraph"));
   l->Add(gROOT->GetListOfStreamerInfo()->FindObject("TH1F"));
   l->Add(gROOT->GetListOfStreamerInfo()->FindObject("TH1"));
   l->Add(gROOT->GetListOfStreamerInfo()->FindObject("TNamed"));
   l->Add(gROOT->GetListOfStreamerInfo()->FindObject("TObject"));

   fMemFile->WriteObject(l, "ll");
   delete l;

   fMemFile->WriteStreamerInfo();

   fSinfo = fMemFile->GetStreamerInfoList();

   gDirectory = olddir;
   gFile = oldfile;
}

//______________________________________________________________________________
Bool_t TRootSniffer::ProduceJson(const char *path, const char *options,
                                 TString &res)
{
   // produce JSON data for specified item
   // For object conversion TBufferJSON is used

   if ((path == 0) || (*path == 0)) return kFALSE;

   if (*path == '/') path++;

   TUrl url;
   url.SetOptions(options);
   url.ParseOptions();
   Int_t compact = -1;
   if (url.GetValueFromOptions("compact"))
      compact = url.GetIntValueFromOptions("compact");

   TClass *obj_cl(0);
   TDataMember *member(0);
   void *obj_ptr = FindInHierarchy(path, &obj_cl, &member);
   if ((obj_ptr == 0) || ((obj_cl == 0) && (member == 0))) return kFALSE;

   if (member == 0)
      res = TBufferJSON::ConvertToJSON(obj_ptr, obj_cl, compact >= 0 ? compact : 0);
   else
      res = TBufferJSON::ConvertToJSON(obj_ptr, member, compact >= 0 ? compact : 1);

   return res.Length() > 0;
}

//______________________________________________________________________________
Bool_t TRootSniffer::ExecuteCmd(const char *path, const char *options,
                                TString &res)
{
   // execute command marked as _kind=='Command'

   TFolder *parent(0);
   TObject *obj = GetItem(path, parent, kFALSE, kFALSE);

   const char *kind = GetItemField(parent, obj, item_prop_kind);
   if ((kind == 0) || (strcmp(kind, "Command") != 0)) {
      if (gDebug > 0) Info("ExecuteCmd", "Entry %s is not a command", path);
      res = "false";
      return kTRUE;
   }

   const char *cmethod = GetItemField(parent, obj, "method");
   if ((cmethod==0) || (strlen(cmethod)==0)) {
      if (gDebug > 0) Info("ExecuteCmd", "Entry %s do not defines method for execution", path);
      res = "false";
      return kTRUE;
   }

   // if read-only specified for the command, it is not allowed for execution
   if (fRestrictions.GetLast()>=0) {
      FindInHierarchy(path); // one need to call method to check access rights
      if (fCurrentRestrict==1) {
         if (gDebug > 0) Info("ExecuteCmd", "Entry %s not allowed for specified user", path);
         res = "false";
         return kTRUE;
      }
   }

   TString method = cmethod;

   const char *cnumargs = GetItemField(parent, obj, "_numargs");
   Int_t numargs = cnumargs ? TString(cnumargs).Atoi() : 0;
   if (numargs > 0) {
      TUrl url;
      url.SetOptions(options);
      url.ParseOptions();

      for (Int_t n=0; n<numargs;n++) {
         TString argname = TString::Format("arg%d", n+1);
         const char* argvalue = url.GetValueFromOptions(argname);
         if (argvalue==0) {
            if (gDebug > 0) Info("ExecuteCmd", "For command %s argument %s not specified in options %s", path, argname.Data(), options);
            res = "false";
            return kTRUE;
         }

         TString svalue = DecodeUrlOptionValue(argvalue, kTRUE);
         argname = TString("%") + argname + TString("%");
         method.ReplaceAll(argname, svalue);
      }
   }

   if (gDebug > 0) Info("ExecuteCmd", "Executing command %s method:%s", path, method.Data());

   TObject *item_obj = 0;
   Ssiz_t separ = method.Index("/->");

   if (method.Index("this->") == 0) {
      // if command name started with this-> means method of sniffer will be executed
      item_obj = this;
      separ = 3;
   } else
   if (separ != kNPOS) {
      item_obj = FindTObjectInHierarchy(TString(method.Data(), separ).Data());
   }

   if (item_obj != 0) {
      method = TString::Format("((%s*)%lu)->%s", item_obj->ClassName(), (long unsigned) item_obj, method.Data() + separ + 3);
      if (gDebug > 2) Info("ExecuteCmd", "Executing %s", method.Data());
   }

   Long_t v = gROOT->ProcessLineSync(method.Data());

   res.Form("%ld", v);

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootSniffer::ProduceItem(const char *path, const char *options, TString &res, Bool_t asjson)
{
   // produce JSON/XML for specified item
   // contrary to h.json request, only fields for specified item are stored

   if (asjson) {
      TRootSnifferStoreJson store(res, strstr(options, "compact")!=0);
      ScanHierarchy("top", path, &store, kTRUE);
   } else {
      TRootSnifferStoreXml store(res, strstr(options, "compact")!=0);
      ScanHierarchy("top", path, &store, kTRUE);
   }
   return res.Length() > 0;
}


//______________________________________________________________________________
Bool_t TRootSniffer::ProduceXml(const char *path, const char * /*options*/,
                                TString &res)
{
   // produce XML data for specified item
   // For object conversion TBufferXML is used

   if ((path == 0) || (*path == 0)) return kFALSE;

   if (*path == '/') path++;

   TClass *obj_cl(0);
   void *obj_ptr = FindInHierarchy(path, &obj_cl);
   if ((obj_ptr == 0) || (obj_cl == 0)) return kFALSE;

   res = TBufferXML::ConvertToXML(obj_ptr, obj_cl);

   return res.Length() > 0;
}

//______________________________________________________________________________
TString TRootSniffer::DecodeUrlOptionValue(const char *value, Bool_t remove_quotes)
{
   // method replaces all kind of special symbols, which could appear in URL options

   if ((value == 0) || (strlen(value) == 0)) return TString();

   TString res = value;

   res.ReplaceAll("%27", "\'");
   res.ReplaceAll("%22", "\"");
   res.ReplaceAll("%3E", ">");
   res.ReplaceAll("%3C", "<");
   res.ReplaceAll("%20", " ");
   res.ReplaceAll("%5B", "[");
   res.ReplaceAll("%5D", "]");

   if (remove_quotes && (res.Length() > 1) &&
         ((res[0] == '\'') || (res[0] == '\"')) && (res[0] == res[res.Length() - 1])) {
      res.Remove(res.Length() - 1);
      res.Remove(0, 1);
   }

   return res;
}

//______________________________________________________________________________
Bool_t TRootSniffer::ProduceExe(const char *path, const char *options, Int_t reskind, TString *res_str, void **res_ptr, Long_t *res_length)
{
   // execute command for specified object
   // options include method and extra list of parameters
   // sniffer should be not-readonly to allow execution of the commands
   // reskind defines kind of result 0 - debug, 1 - json, 2 - binary

   TString *debug = (reskind == 0) ? res_str : 0;

   if ((path == 0) || (*path == 0)) {
      if (debug) debug->Append("Item name not specified\n");
      return debug != 0;
   }

   if (*path == '/') path++;

   TClass *obj_cl(0);
   void *obj_ptr = FindInHierarchy(path, &obj_cl);
   if (debug) debug->Append(TString::Format("Item:%s found:%s\n", path, obj_ptr ? "true" : "false"));
   if ((obj_ptr == 0) || (obj_cl == 0)) return debug != 0;

   TUrl url;
   url.SetOptions(options);

   const char *method_name = url.GetValueFromOptions("method");
   TString prototype = DecodeUrlOptionValue(url.GetValueFromOptions("prototype"), kTRUE);
   TMethod *method = 0;
   if (method_name != 0) {
      if (prototype.Length() == 0) {
         if (debug) debug->Append(TString::Format("Search for any method with name \'%s\'\n", method_name));
         method = obj_cl->GetMethodAllAny(method_name);
      } else {
         if (debug) debug->Append(TString::Format("Search for method \'%s\' with prototype \'%s\'\n", method_name, prototype.Data()));
         method = obj_cl->GetMethodWithPrototype(method_name, prototype);
      }
   }

   if (method == 0) {
      if (debug) debug->Append("Method not found\n");
      return debug != 0;
   }

   if (debug) debug->Append(TString::Format("Method: %s\n", method->GetPrototype()));

   if ((fReadOnly && (fCurrentRestrict == 0)) || (fCurrentRestrict == 1)) {
      if (fCurrentAllowedMethods.Index(method_name) == kNPOS) {
         if (debug) debug->Append("Server runs in read-only mode, method cannot be executed\n");
         return debug != 0;
      } else {
         if (debug) debug->Append("For that special method server allows access even read-only mode is specified\n");
      }
   }

   TList *args = method->GetListOfMethodArgs();

   TList garbage;
   garbage.SetOwner(kTRUE); // use as garbage collection
   TObject *post_obj = 0; // object reconstructed from post request
   TString call_args;

   TIter next(args);
   TMethodArg *arg = 0;
   while ((arg = (TMethodArg *) next()) != 0) {

      if ((strcmp(arg->GetName(), "rest_url_opt") == 0) &&
            (strcmp(arg->GetFullTypeName(), "const char*") == 0) && (args->GetSize() == 1)) {
         // very special case - function requires list of options after method=argument

         const char *pos = strstr(options, "method=");
         if ((pos == 0) || (strlen(pos) < strlen(method_name) + 8)) return debug != 0;
         call_args.Form("\"%s\"", pos + strlen(method_name) + 8);
         break;
      }

      TString sval;
      const char *val = url.GetValueFromOptions(arg->GetName());
      if (val) {
         sval = DecodeUrlOptionValue(val, kFALSE);
         val = sval.Data();
      }

      // process several arguments which are specific for post requests
      if ((val!=0) && (fCurrentArg!=0) && (fCurrentArg->GetPostData()!=0)) {
         if (strcmp(val,"_post_object_xml_")==0) {
            // post data has extra 0 at the end and can be used as null-terminated string
            post_obj = TBufferXML::ConvertFromXML((const char*) fCurrentArg->GetPostData());
            if (post_obj == 0) {
               sval = "0";
            } else {
               sval.Form("(%s*)0x%lx", post_obj->ClassName(), (long unsigned) post_obj);
               if (url.HasOption("_destroy_post_")) garbage.Add(post_obj);
            }
            val = sval.Data();
         } else
         if ((strcmp(val,"_post_object_")==0) && url.HasOption("_post_class_")) {
            TString clname = url.GetValueFromOptions("_post_class_");
            TClass* arg_cl = gROOT->GetClass(clname, kTRUE, kTRUE);
            if ((arg_cl!=0) && (arg_cl->GetBaseClassOffset(TObject::Class()) == 0) && (post_obj==0)) {
               post_obj = (TObject*) arg_cl->New();
               if (post_obj==0) {
                  if (debug) debug->Append(TString::Format("Fail to create object of class %s\n", clname.Data()));
               } else {
                  if (debug) debug->Append(TString::Format("Reconstruct object of class %s from POST data\n", clname.Data()));
                  TBufferFile buf(TBuffer::kRead, fCurrentArg->GetPostDataLength(), fCurrentArg->GetPostData(), kFALSE);
                  buf.MapObject(post_obj, arg_cl);
                  post_obj->Streamer(buf);
                  if (url.HasOption("_destroy_post_")) garbage.Add(post_obj);
               }
            }
            sval.Form("(%s*)0x%lx", clname.Data(), (long unsigned) post_obj);
            val = sval.Data();
         } else
         if (strcmp(val,"_post_data_")==0) {
            sval.Form("(void*)0x%lx", (long unsigned) *res_ptr);
            val = sval.Data();
         } else
         if (strcmp(val,"_post_length_")==0) {
            sval.Form("%ld", (long) *res_length);
            val = sval.Data();
         }
      }

      if (val == 0) val = arg->GetDefault();

      if (debug) debug->Append(TString::Format("  Argument:%s Type:%s Value:%s \n", arg->GetName(), arg->GetFullTypeName(), val ? val : "<missed>"));
      if (val == 0) return debug != 0;

      if (call_args.Length() > 0) call_args += ", ";

      if ((strcmp(arg->GetFullTypeName(), "const char*") == 0) || (strcmp(arg->GetFullTypeName(), "Option_t*") == 0)) {
         int len = strlen(val);
         if ((strlen(val) < 2) || (*val != '\"') || (val[len - 1] != '\"'))
            call_args.Append(TString::Format("\"%s\"", val));
         else
            call_args.Append(val);
      } else {
         call_args.Append(val);
      }
   }

   if (debug) debug->Append(TString::Format("Calling obj->%s(%s);\n", method_name, call_args.Data()));

   TMethodCall call(obj_cl, method_name, call_args.Data());

   if (!call.IsValid()) {
      if (debug) debug->Append("Fail: invalid TMethodCall\n");
      return debug != 0;
   }

   Int_t compact = 0;
   if (url.GetValueFromOptions("compact"))
      compact = url.GetIntValueFromOptions("compact");

   TString res = "null";
   void *ret_obj = 0;
   TClass *ret_cl = 0;
   TBufferFile *resbuf = 0;
   if (reskind==2) {
      resbuf = new TBufferFile(TBuffer::kWrite, 10000);
      garbage.Add(resbuf);
   }

   switch (call.ReturnType()) {
      case TMethodCall::kLong: {
            Long_t l(0);
            call.Execute(obj_ptr, l);
            if (resbuf) resbuf->WriteLong(l);
                   else res.Form("%ld", l);
            break;
         }
      case TMethodCall::kDouble : {
            Double_t d(0.);
            call.Execute(obj_ptr, d);
            if (resbuf) resbuf->WriteDouble(d);
                   else res.Form(TBufferJSON::GetFloatFormat(), d);
            break;
         }
      case TMethodCall::kString : {
            char *txt(0);
            call.Execute(obj_ptr, &txt);
            if (txt != 0) {
               if (resbuf) resbuf->WriteString(txt);
                      else res.Form("\"%s\"", txt);
            }
            break;
         }
      case TMethodCall::kOther : {
            std::string ret_kind = method->GetReturnTypeNormalizedName();
            if ((ret_kind.length() > 0) && (ret_kind[ret_kind.length() - 1] == '*')) {
               ret_kind.resize(ret_kind.length() - 1);
               ret_cl = gROOT->GetClass(ret_kind.c_str(), kTRUE, kTRUE);
            }

            if (ret_cl != 0) {
               Long_t l(0);
               call.Execute(obj_ptr, l);
               if (l != 0) ret_obj = (void *) l;
            } else {
               call.Execute(obj_ptr);
            }

            break;
         }
      case TMethodCall::kNone : {
            call.Execute(obj_ptr);
            break;
         }
   }

   const char *_ret_object_ = url.GetValueFromOptions("_ret_object_");
   if (_ret_object_ != 0) {
      TObject *obj = 0;
      if (gDirectory != 0) obj = gDirectory->Get(_ret_object_);
      if (debug) debug->Append(TString::Format("Return object %s found %s\n", _ret_object_, obj ? "true" : "false"));

      if (obj == 0) {
         res = "null";
      } else {
         ret_obj = obj;
         ret_cl = obj->IsA();
      }
   }

   if ((ret_obj != 0) && (ret_cl != 0)) {
      if ((resbuf != 0) && (ret_cl->GetBaseClassOffset(TObject::Class()) == 0)) {
         TObject *obj = (TObject *) ret_obj;
         resbuf->MapObject(obj);
         obj->Streamer(*resbuf);
         if (fCurrentArg) fCurrentArg->SetExtraHeader("RootClassName", ret_cl->GetName());
      } else {
         res = TBufferJSON::ConvertToJSON(ret_obj, ret_cl, compact);
      }
   }

   if ((resbuf != 0) && (resbuf->Length() > 0) && (res_ptr != 0) && (res_length != 0)) {
      *res_ptr = malloc(resbuf->Length());
      memcpy(*res_ptr, resbuf->Buffer(), resbuf->Length());
      *res_length = resbuf->Length();
   }

   if (debug) debug->Append(TString::Format("Result = %s\n", res.Data()));

   if ((reskind == 1) && res_str) *res_str = res;

   if (url.HasOption("_destroy_result_") && (ret_obj != 0) && (ret_cl != 0)) {
      ret_cl->Destructor(ret_obj);
      if (debug) debug->Append("Destroy result object at the end\n");
   }

   // delete all garbage objects, but should be also done with any return
   garbage.Delete();

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootSniffer::IsStreamerInfoItem(const char *itemname)
{
   // Return true if it is streamer info item name

   if ((itemname == 0) || (*itemname == 0)) return kFALSE;

   return (strcmp(itemname, "StreamerInfo") == 0) || (strcmp(itemname, "StreamerInfo/") == 0);
}

//______________________________________________________________________________
Bool_t TRootSniffer::ProduceBinary(const char *path, const char * /*query*/, void *&ptr,
                                   Long_t &length)
{
   // produce binary data for specified item
   // if "zipped" option specified in query, buffer will be compressed

   if ((path == 0) || (*path == 0)) return kFALSE;

   if (*path == '/') path++;

   TClass *obj_cl(0);
   void *obj_ptr = FindInHierarchy(path, &obj_cl);
   if ((obj_ptr == 0) || (obj_cl == 0)) return kFALSE;

   if (obj_cl->GetBaseClassOffset(TObject::Class()) != 0) {
      Info("ProduceBinary", "Non-TObject class not supported");
      return kFALSE;
   }

   // ensure that memfile exists
   CreateMemFile();

   TDirectory *olddir = gDirectory;
   gDirectory = 0;
   TFile *oldfile = gFile;
   gFile = 0;

   TObject *obj = (TObject *) obj_ptr;

   TBufferFile *sbuf = new TBufferFile(TBuffer::kWrite, 100000);
   sbuf->SetParent(fMemFile);
   sbuf->MapObject(obj);
   obj->Streamer(*sbuf);
   if (fCurrentArg) fCurrentArg->SetExtraHeader("RootClassName", obj_cl->GetName());

   // produce actual version of streamer info
   delete fSinfo;
   fMemFile->WriteStreamerInfo();
   fSinfo = fMemFile->GetStreamerInfoList();

   gDirectory = olddir;
   gFile = oldfile;

   ptr = malloc(sbuf->Length());
   memcpy(ptr, sbuf->Buffer(), sbuf->Length());
   length = sbuf->Length();

   delete sbuf;

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootSniffer::ProduceImage(Int_t kind, const char *path,
                                  const char *options, void *&ptr,
                                  Long_t &length)
{
   // Method to produce image from specified object
   //
   // Parameters:
   //    kind - image kind TImage::kPng, TImage::kJpeg, TImage::kGif
   //    path - path to object
   //    options - extra options
   //
   // By default, image 300x200 is produced
   // In options string one could provide following parameters:
   //    w - image width
   //    h - image height
   //    opt - draw options
   //  For instance:
   //     http://localhost:8080/Files/hsimple.root/hpx/get.png?w=500&h=500&opt=lego1
   //
   //  Return is memory with produced image
   //  Memory must be released by user with free(ptr) call

   ptr = 0;
   length = 0;

   if ((path == 0) || (*path == 0)) return kFALSE;
   if (*path == '/') path++;

   TClass *obj_cl(0);
   void *obj_ptr = FindInHierarchy(path, &obj_cl);
   if ((obj_ptr == 0) || (obj_cl == 0)) return kFALSE;

   if (obj_cl->GetBaseClassOffset(TObject::Class()) != 0) {
      Error("TRootSniffer", "Only derived from TObject classes can be drawn");
      return kFALSE;
   }

   TObject *obj = (TObject *) obj_ptr;

   TImage *img = TImage::Create();
   if (img == 0) return kFALSE;

   if (obj->InheritsFrom(TPad::Class())) {

      if (gDebug > 1)
         Info("TRootSniffer", "Crate IMAGE directly from pad");
      img->FromPad((TPad *) obj);
   } else if (IsDrawableClass(obj->IsA())) {

      if (gDebug > 1)
         Info("TRootSniffer", "Crate IMAGE from object %s", obj->GetName());

      Int_t width(300), height(200);
      TString drawopt = "";

      if ((options != 0) && (*options != 0)) {
         TUrl url;
         url.SetOptions(options);
         url.ParseOptions();
         Int_t w = url.GetIntValueFromOptions("w");
         if (w > 10) width = w;
         Int_t h = url.GetIntValueFromOptions("h");
         if (h > 10) height = h;
         const char *opt = url.GetValueFromOptions("opt");
         if (opt != 0) drawopt = opt;
      }

      Bool_t isbatch = gROOT->IsBatch();
      TVirtualPad *save_gPad = gPad;

      if (!isbatch) gROOT->SetBatch(kTRUE);

      TCanvas *c1 = new TCanvas("__online_draw_canvas__", "title", width, height);
      obj->Draw(drawopt.Data());
      img->FromPad(c1);
      delete c1;

      if (!isbatch) gROOT->SetBatch(kFALSE);
      gPad = save_gPad;

   } else {
      delete img;
      return kFALSE;
   }

   TImage *im = TImage::Create();
   im->Append(img);

   char *png_buffer(0);
   int size(0);

   im->GetImageBuffer(&png_buffer, &size, (TImage::EImageFileTypes) kind);

   if ((png_buffer != 0) && (size > 0)) {
      ptr = malloc(size);
      length = size;
      memcpy(ptr, png_buffer, length);
   }

   delete [] png_buffer;
   delete im;

   return ptr != 0;
}

//______________________________________________________________________________
Bool_t TRootSniffer::Produce(const char *path, const char *file,
                             const char *options, void *&ptr, Long_t &length, TString &str)
{
   // Method produce different kind of data out of object
   // Parameter 'path' specifies object or object member
   // Supported 'file' (case sensitive):
   //   "root.bin"  - binary data
   //   "root.png"  - png image
   //   "root.jpeg" - jpeg image
   //   "root.gif"  - gif image
   //   "root.xml"  - xml representation
   //   "root.json" - json representation
   //   "exe.json"  - method execution with json reply
   //   "exe.bin"   - method execution with binary reply
   //   "exe.txt"   - method execution with debug output
   //   "cmd.json"  - execution of registered commands
   // Result returned either as string or binary buffer,
   // which should be released with free() call

   if ((file == 0) || (*file == 0)) return kFALSE;

   if (strcmp(file, "root.bin") == 0)
      return ProduceBinary(path, options, ptr, length);

   if (strcmp(file, "root.png") == 0)
      return ProduceImage(TImage::kPng, path, options, ptr, length);

   if (strcmp(file, "root.jpeg") == 0)
      return ProduceImage(TImage::kJpeg, path, options, ptr, length);

   if (strcmp(file, "root.gif") == 0)
      return ProduceImage(TImage::kGif, path, options, ptr, length);

   if (strcmp(file, "exe.bin") == 0)
      return ProduceExe(path, options, 2, 0, &ptr, &length);

   if (strcmp(file, "root.xml") == 0)
      return ProduceXml(path, options, str);

   if (strcmp(file, "root.json") == 0)
      return ProduceJson(path, options, str);

   // used for debugging
   if (strcmp(file, "exe.txt") == 0)
      return ProduceExe(path, options, 0, &str);

   if (strcmp(file, "exe.json") == 0)
      return ProduceExe(path, options, 1, &str);

   if (strcmp(file, "cmd.json") == 0)
      return ExecuteCmd(path, options, str);

   if (strcmp(file, "item.json") == 0)
      return ProduceItem(path, options, str, kTRUE);

   if (strcmp(file, "item.xml") == 0)
      return ProduceItem(path, options, str, kFALSE);

   return kFALSE;
}

//______________________________________________________________________________
TObject *TRootSniffer::GetItem(const char *fullname, TFolder *&parent, Bool_t force, Bool_t within_objects)
{
   // return item from the subfolders structure

   TFolder *topf = gROOT->GetRootFolder();

   if (topf == 0) {
      Error("RegisterObject", "Not found top ROOT folder!!!");
      return 0;
   }

   TFolder *httpfold = dynamic_cast<TFolder *>(topf->FindObject("http"));
   if (httpfold == 0) {
      if (!force) return 0;
      httpfold = topf->AddFolder("http", "ROOT http server");
      httpfold->SetBit(kCanDelete);
      // register top folder in list of cleanups
      gROOT->GetListOfCleanups()->Add(httpfold);
   }

   parent = httpfold;
   TObject *obj = httpfold;

   if (fullname==0) return httpfold;

   // when full path started not with slash, "Objects" subfolder is appended
   TString path = fullname;
   if (within_objects && ((path.Length()==0) || (path[0]!='/')))
      path = fObjectsPath + "/" + path;

   TString tok;
   Ssiz_t from(0);

   while (path.Tokenize(tok,from,"/")) {
      if (tok.Length()==0) continue;

      TFolder *fold = dynamic_cast<TFolder *> (obj);
      if (fold == 0) return 0;

      TIter iter(fold->GetListOfFolders());
      while ((obj = iter()) != 0) {
         if (IsItemField(obj)) continue;
         if (tok.CompareTo(obj->GetName())==0) break;
      }

      if (obj == 0) {
         if (!force) return 0;
         obj = fold->AddFolder(tok, "sub-folder");
         obj->SetBit(kCanDelete);
      }

      parent = fold;
   }

   return obj;
}

//______________________________________________________________________________
TFolder *TRootSniffer::GetSubFolder(const char *subfolder, Bool_t force)
{
   // creates subfolder where objects can be registered

   TFolder *parent = 0;

   return dynamic_cast<TFolder *> (GetItem(subfolder, parent, force));
}

//______________________________________________________________________________
Bool_t TRootSniffer::RegisterObject(const char *subfolder, TObject *obj)
{
   // Register object in subfolder structure
   // subfolder parameter can have many levels like:
   //
   // TRootSniffer* sniff = new TRootSniffer("sniff");
   // sniff->RegisterObject("my/sub/subfolder", h1);
   //
   // Such objects can be later found in "Objects" folder of sniffer like
   //
   // h1 = sniff->FindTObjectInHierarchy("/Objects/my/sub/subfolder/h1");
   //
   // If subfolder name starts with '/', object will be registered starting from top folder.
   //
   // One could provide additional fields for registered objects
   // For instance, setting "_more" field to true let browser
   // explore objects members. For instance:
   //
   // TEvent* ev = new TEvent("ev");
   // sniff->RegisterObject("Events", ev);
   // sniff->SetItemField("Events/ev", "_more", "true");

   TFolder *f = GetSubFolder(subfolder, kTRUE);
   if (f == 0) return kFALSE;

   // If object will be destroyed, it will be removed from the folders automatically
   obj->SetBit(kMustCleanup);

   f->Add(obj);

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootSniffer::UnregisterObject(TObject *obj)
{
   // unregister (remove) object from folders structures
   // folder itself will remain even when it will be empty

   if (obj == 0) return kTRUE;

   TFolder *topf = dynamic_cast<TFolder *>(gROOT->FindObject("//root/http"));

   if (topf == 0) {
      Error("UnregisterObject", "Not found //root/http folder!!!");
      return kFALSE;
   }

   // TODO - probably we should remove all set properties as well
   if (topf) topf->RecursiveRemove(obj);

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootSniffer::CreateItem(const char *fullname, const char *title)
{
   // create item element

   TFolder *f = GetSubFolder(fullname, kTRUE);
   if (f == 0) return kFALSE;

   if (title) f->SetTitle(title);

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootSniffer::IsItemField(TObject* obj) const
{
   // return true when object is TNamed with kItemField bit set
   // such objects used to keep field values for item

   return (obj!=0) && (obj->IsA() == TNamed::Class()) && obj->TestBit(kItemField);
}

//______________________________________________________________________________
Bool_t TRootSniffer::AccessField(TFolder *parent, TObject *chld,
                                 const char *name, const char *value, TNamed **only_get)
{
   // set or get field for the child
   // each field coded as TNamed object, placed after chld in the parent hierarchy

   if (parent==0) return kFALSE;

   if (chld==0) {
      Info("SetField", "Should be special case for top folder, support later");
      return kFALSE;
   }

   TIter iter(parent->GetListOfFolders());

   TObject* obj = 0;
   Bool_t find(kFALSE), last_find(kFALSE);
   // this is special case of top folder - fields are on very top
   if (parent == chld) { last_find = find = kTRUE; }
   TNamed* curr = 0;
   while ((obj = iter()) != 0) {
      if (IsItemField(obj)) {
         if (last_find && (obj->GetName()!=0) && !strcmp(name, obj->GetName())) curr = (TNamed*) obj;
      } else {
         last_find = (obj == chld);
         if (last_find) find = kTRUE;
         if (find && !last_find) break; // no need to continue
      }
   }

   // object must be in childs list
   if (!find) return kFALSE;

   if (only_get!=0) {
      *only_get = curr;
      return curr!=0;
   }

   if (curr!=0) {
      if (value!=0) { curr->SetTitle(value); }
               else { parent->Remove(curr); delete curr; }
      return kTRUE;
   }

   curr = new TNamed(name, value);
   curr->SetBit(kItemField);

   if (last_find) {
      // object is on last place, therefore just add property
      parent->Add(curr);
      return kTRUE;
   }

   // only here we do dynamic cast to the TList to use AddAfter
   TList *lst = dynamic_cast<TList *> (parent->GetListOfFolders());
   if (lst==0) {
      Error("SetField", "Fail cast to TList");
      return kFALSE;
   }

   if (parent==chld)
      lst->AddFirst(curr);
   else
      lst->AddAfter(chld, curr);

   return kTRUE;
}

//_____________________________________________________________
Bool_t TRootSniffer::SetItemField(const char *fullname, const char *name, const char *value)
{
   // set field for specified item

   if ((fullname==0) || (name==0)) return kFALSE;

   TFolder *parent(0);
   TObject *obj = GetItem(fullname, parent);

   if ((parent==0) || (obj==0)) return kFALSE;

   if (strcmp(name, item_prop_title)==0) {
      TNamed* n = dynamic_cast<TNamed*> (obj);
      if (n!=0) { n->SetTitle(value); return kTRUE; }
   }

   return AccessField(parent, obj, name, value);
}

//______________________________________________________________________________
const char *TRootSniffer::GetItemField(TFolder *parent, TObject *obj, const char *name)
{
  // return field for specified item

   if ((parent==0) || (obj==0) || (name==0)) return 0;

   TNamed *field(0);

   if (!AccessField(parent, obj, name, 0, &field)) return 0;

   return field ? field->GetTitle() : 0;
}


//______________________________________________________________________________
const char *TRootSniffer::GetItemField(const char *fullname, const char *name)
{
   // return field for specified item

   if (fullname==0) return 0;

   TFolder *parent(0);
   TObject *obj = GetItem(fullname, parent);

   return GetItemField(parent, obj, name);
}


//______________________________________________________________________________
Bool_t TRootSniffer::RegisterCommand(const char *cmdname, const char *method, const char *icon)
{
   // Register command which can be executed from web interface
   //
   // As method one typically specifies string, which is executed with
   // gROOT->ProcessLine() method. For instance
   //    serv->RegisterCommand("Invoke","InvokeFunction()");
   //
   // Or one could specify any method of the object which is already registered
   // to the server. For instance:
   //     serv->Register("/", hpx);
   //     serv->RegisterCommand("/ResetHPX", "/hpx/->Reset()");
   // Here symbols '/->' separates item name from method to be executed
   //
   // One could specify additional arguments in the command with
   // syntax like %arg1%, %arg2% and so on. For example:
   //     serv->RegisterCommand("/ResetHPX", "/hpx/->SetTitle(\"%arg1%\")");
   //     serv->RegisterCommand("/RebinHPXPY", "/hpxpy/->Rebin2D(%arg1%,%arg2%)");
   // Such parameter(s) will be requested when command clicked in the browser.
   //
   // Once command is registered, one could specify icon which will appear in the browser:
   //     serv->SetIcon("/ResetHPX", "rootsys/icons/ed_execute.png");
   //
   // One also can set extra property '_fastcmd', that command appear as
   // tool button on the top of the browser tree:
   //     serv->SetItemField("/ResetHPX", "_fastcmd", "true");
   // Or it is equivalent to specifying extra argument when register command:
   //     serv->RegisterCommand("/ResetHPX", "/hpx/->Reset()", "button;rootsys/icons/ed_delete.png");

   CreateItem(cmdname, Form("command %s", method));
   SetItemField(cmdname, "_kind", "Command");
   if (icon != 0) {
      if (strncmp(icon, "button;", 7) == 0) {
         SetItemField(cmdname, "_fastcmd", "true");
         icon += 7;
      }
      if (*icon != 0) SetItemField(cmdname, "_icon", icon);
   }
   SetItemField(cmdname, "method", method);
   Int_t numargs = 0;
   do {
      TString nextname = TString::Format("%sarg%d%s","%",numargs+1,"%");
      if (strstr(method,nextname.Data())==0) break;
      numargs++;
   } while (numargs<100);
   if (numargs>0)
      SetItemField(cmdname, "_numargs", TString::Format("%d", numargs));

   return kTRUE;
}
 TRootSniffer.cxx:1
 TRootSniffer.cxx:2
 TRootSniffer.cxx:3
 TRootSniffer.cxx:4
 TRootSniffer.cxx:5
 TRootSniffer.cxx:6
 TRootSniffer.cxx:7
 TRootSniffer.cxx:8
 TRootSniffer.cxx:9
 TRootSniffer.cxx:10
 TRootSniffer.cxx:11
 TRootSniffer.cxx:12
 TRootSniffer.cxx:13
 TRootSniffer.cxx:14
 TRootSniffer.cxx:15
 TRootSniffer.cxx:16
 TRootSniffer.cxx:17
 TRootSniffer.cxx:18
 TRootSniffer.cxx:19
 TRootSniffer.cxx:20
 TRootSniffer.cxx:21
 TRootSniffer.cxx:22
 TRootSniffer.cxx:23
 TRootSniffer.cxx:24
 TRootSniffer.cxx:25
 TRootSniffer.cxx:26
 TRootSniffer.cxx:27
 TRootSniffer.cxx:28
 TRootSniffer.cxx:29
 TRootSniffer.cxx:30
 TRootSniffer.cxx:31
 TRootSniffer.cxx:32
 TRootSniffer.cxx:33
 TRootSniffer.cxx:34
 TRootSniffer.cxx:35
 TRootSniffer.cxx:36
 TRootSniffer.cxx:37
 TRootSniffer.cxx:38
 TRootSniffer.cxx:39
 TRootSniffer.cxx:40
 TRootSniffer.cxx:41
 TRootSniffer.cxx:42
 TRootSniffer.cxx:43
 TRootSniffer.cxx:44
 TRootSniffer.cxx:45
 TRootSniffer.cxx:46
 TRootSniffer.cxx:47
 TRootSniffer.cxx:48
 TRootSniffer.cxx:49
 TRootSniffer.cxx:50
 TRootSniffer.cxx:51
 TRootSniffer.cxx:52
 TRootSniffer.cxx:53
 TRootSniffer.cxx:54
 TRootSniffer.cxx:55
 TRootSniffer.cxx:56
 TRootSniffer.cxx:57
 TRootSniffer.cxx:58
 TRootSniffer.cxx:59
 TRootSniffer.cxx:60
 TRootSniffer.cxx:61
 TRootSniffer.cxx:62
 TRootSniffer.cxx:63
 TRootSniffer.cxx:64
 TRootSniffer.cxx:65
 TRootSniffer.cxx:66
 TRootSniffer.cxx:67
 TRootSniffer.cxx:68
 TRootSniffer.cxx:69
 TRootSniffer.cxx:70
 TRootSniffer.cxx:71
 TRootSniffer.cxx:72
 TRootSniffer.cxx:73
 TRootSniffer.cxx:74
 TRootSniffer.cxx:75
 TRootSniffer.cxx:76
 TRootSniffer.cxx:77
 TRootSniffer.cxx:78
 TRootSniffer.cxx:79
 TRootSniffer.cxx:80
 TRootSniffer.cxx:81
 TRootSniffer.cxx:82
 TRootSniffer.cxx:83
 TRootSniffer.cxx:84
 TRootSniffer.cxx:85
 TRootSniffer.cxx:86
 TRootSniffer.cxx:87
 TRootSniffer.cxx:88
 TRootSniffer.cxx:89
 TRootSniffer.cxx:90
 TRootSniffer.cxx:91
 TRootSniffer.cxx:92
 TRootSniffer.cxx:93
 TRootSniffer.cxx:94
 TRootSniffer.cxx:95
 TRootSniffer.cxx:96
 TRootSniffer.cxx:97
 TRootSniffer.cxx:98
 TRootSniffer.cxx:99
 TRootSniffer.cxx:100
 TRootSniffer.cxx:101
 TRootSniffer.cxx:102
 TRootSniffer.cxx:103
 TRootSniffer.cxx:104
 TRootSniffer.cxx:105
 TRootSniffer.cxx:106
 TRootSniffer.cxx:107
 TRootSniffer.cxx:108
 TRootSniffer.cxx:109
 TRootSniffer.cxx:110
 TRootSniffer.cxx:111
 TRootSniffer.cxx:112
 TRootSniffer.cxx:113
 TRootSniffer.cxx:114
 TRootSniffer.cxx:115
 TRootSniffer.cxx:116
 TRootSniffer.cxx:117
 TRootSniffer.cxx:118
 TRootSniffer.cxx:119
 TRootSniffer.cxx:120
 TRootSniffer.cxx:121
 TRootSniffer.cxx:122
 TRootSniffer.cxx:123
 TRootSniffer.cxx:124
 TRootSniffer.cxx:125
 TRootSniffer.cxx:126
 TRootSniffer.cxx:127
 TRootSniffer.cxx:128
 TRootSniffer.cxx:129
 TRootSniffer.cxx:130
 TRootSniffer.cxx:131
 TRootSniffer.cxx:132
 TRootSniffer.cxx:133
 TRootSniffer.cxx:134
 TRootSniffer.cxx:135
 TRootSniffer.cxx:136
 TRootSniffer.cxx:137
 TRootSniffer.cxx:138
 TRootSniffer.cxx:139
 TRootSniffer.cxx:140
 TRootSniffer.cxx:141
 TRootSniffer.cxx:142
 TRootSniffer.cxx:143
 TRootSniffer.cxx:144
 TRootSniffer.cxx:145
 TRootSniffer.cxx:146
 TRootSniffer.cxx:147
 TRootSniffer.cxx:148
 TRootSniffer.cxx:149
 TRootSniffer.cxx:150
 TRootSniffer.cxx:151
 TRootSniffer.cxx:152
 TRootSniffer.cxx:153
 TRootSniffer.cxx:154
 TRootSniffer.cxx:155
 TRootSniffer.cxx:156
 TRootSniffer.cxx:157
 TRootSniffer.cxx:158
 TRootSniffer.cxx:159
 TRootSniffer.cxx:160
 TRootSniffer.cxx:161
 TRootSniffer.cxx:162
 TRootSniffer.cxx:163
 TRootSniffer.cxx:164
 TRootSniffer.cxx:165
 TRootSniffer.cxx:166
 TRootSniffer.cxx:167
 TRootSniffer.cxx:168
 TRootSniffer.cxx:169
 TRootSniffer.cxx:170
 TRootSniffer.cxx:171
 TRootSniffer.cxx:172
 TRootSniffer.cxx:173
 TRootSniffer.cxx:174
 TRootSniffer.cxx:175
 TRootSniffer.cxx:176
 TRootSniffer.cxx:177
 TRootSniffer.cxx:178
 TRootSniffer.cxx:179
 TRootSniffer.cxx:180
 TRootSniffer.cxx:181
 TRootSniffer.cxx:182
 TRootSniffer.cxx:183
 TRootSniffer.cxx:184
 TRootSniffer.cxx:185
 TRootSniffer.cxx:186
 TRootSniffer.cxx:187
 TRootSniffer.cxx:188
 TRootSniffer.cxx:189
 TRootSniffer.cxx:190
 TRootSniffer.cxx:191
 TRootSniffer.cxx:192
 TRootSniffer.cxx:193
 TRootSniffer.cxx:194
 TRootSniffer.cxx:195
 TRootSniffer.cxx:196
 TRootSniffer.cxx:197
 TRootSniffer.cxx:198
 TRootSniffer.cxx:199
 TRootSniffer.cxx:200
 TRootSniffer.cxx:201
 TRootSniffer.cxx:202
 TRootSniffer.cxx:203
 TRootSniffer.cxx:204
 TRootSniffer.cxx:205
 TRootSniffer.cxx:206
 TRootSniffer.cxx:207
 TRootSniffer.cxx:208
 TRootSniffer.cxx:209
 TRootSniffer.cxx:210
 TRootSniffer.cxx:211
 TRootSniffer.cxx:212
 TRootSniffer.cxx:213
 TRootSniffer.cxx:214
 TRootSniffer.cxx:215
 TRootSniffer.cxx:216
 TRootSniffer.cxx:217
 TRootSniffer.cxx:218
 TRootSniffer.cxx:219
 TRootSniffer.cxx:220
 TRootSniffer.cxx:221
 TRootSniffer.cxx:222
 TRootSniffer.cxx:223
 TRootSniffer.cxx:224
 TRootSniffer.cxx:225
 TRootSniffer.cxx:226
 TRootSniffer.cxx:227
 TRootSniffer.cxx:228
 TRootSniffer.cxx:229
 TRootSniffer.cxx:230
 TRootSniffer.cxx:231
 TRootSniffer.cxx:232
 TRootSniffer.cxx:233
 TRootSniffer.cxx:234
 TRootSniffer.cxx:235
 TRootSniffer.cxx:236
 TRootSniffer.cxx:237
 TRootSniffer.cxx:238
 TRootSniffer.cxx:239
 TRootSniffer.cxx:240
 TRootSniffer.cxx:241
 TRootSniffer.cxx:242
 TRootSniffer.cxx:243
 TRootSniffer.cxx:244
 TRootSniffer.cxx:245
 TRootSniffer.cxx:246
 TRootSniffer.cxx:247
 TRootSniffer.cxx:248
 TRootSniffer.cxx:249
 TRootSniffer.cxx:250
 TRootSniffer.cxx:251
 TRootSniffer.cxx:252
 TRootSniffer.cxx:253
 TRootSniffer.cxx:254
 TRootSniffer.cxx:255
 TRootSniffer.cxx:256
 TRootSniffer.cxx:257
 TRootSniffer.cxx:258
 TRootSniffer.cxx:259
 TRootSniffer.cxx:260
 TRootSniffer.cxx:261
 TRootSniffer.cxx:262
 TRootSniffer.cxx:263
 TRootSniffer.cxx:264
 TRootSniffer.cxx:265
 TRootSniffer.cxx:266
 TRootSniffer.cxx:267
 TRootSniffer.cxx:268
 TRootSniffer.cxx:269
 TRootSniffer.cxx:270
 TRootSniffer.cxx:271
 TRootSniffer.cxx:272
 TRootSniffer.cxx:273
 TRootSniffer.cxx:274
 TRootSniffer.cxx:275
 TRootSniffer.cxx:276
 TRootSniffer.cxx:277
 TRootSniffer.cxx:278
 TRootSniffer.cxx:279
 TRootSniffer.cxx:280
 TRootSniffer.cxx:281
 TRootSniffer.cxx:282
 TRootSniffer.cxx:283
 TRootSniffer.cxx:284
 TRootSniffer.cxx:285
 TRootSniffer.cxx:286
 TRootSniffer.cxx:287
 TRootSniffer.cxx:288
 TRootSniffer.cxx:289
 TRootSniffer.cxx:290
 TRootSniffer.cxx:291
 TRootSniffer.cxx:292
 TRootSniffer.cxx:293
 TRootSniffer.cxx:294
 TRootSniffer.cxx:295
 TRootSniffer.cxx:296
 TRootSniffer.cxx:297
 TRootSniffer.cxx:298
 TRootSniffer.cxx:299
 TRootSniffer.cxx:300
 TRootSniffer.cxx:301
 TRootSniffer.cxx:302
 TRootSniffer.cxx:303
 TRootSniffer.cxx:304
 TRootSniffer.cxx:305
 TRootSniffer.cxx:306
 TRootSniffer.cxx:307
 TRootSniffer.cxx:308
 TRootSniffer.cxx:309
 TRootSniffer.cxx:310
 TRootSniffer.cxx:311
 TRootSniffer.cxx:312
 TRootSniffer.cxx:313
 TRootSniffer.cxx:314
 TRootSniffer.cxx:315
 TRootSniffer.cxx:316
 TRootSniffer.cxx:317
 TRootSniffer.cxx:318
 TRootSniffer.cxx:319
 TRootSniffer.cxx:320
 TRootSniffer.cxx:321
 TRootSniffer.cxx:322
 TRootSniffer.cxx:323
 TRootSniffer.cxx:324
 TRootSniffer.cxx:325
 TRootSniffer.cxx:326
 TRootSniffer.cxx:327
 TRootSniffer.cxx:328
 TRootSniffer.cxx:329
 TRootSniffer.cxx:330
 TRootSniffer.cxx:331
 TRootSniffer.cxx:332
 TRootSniffer.cxx:333
 TRootSniffer.cxx:334
 TRootSniffer.cxx:335
 TRootSniffer.cxx:336
 TRootSniffer.cxx:337
 TRootSniffer.cxx:338
 TRootSniffer.cxx:339
 TRootSniffer.cxx:340
 TRootSniffer.cxx:341
 TRootSniffer.cxx:342
 TRootSniffer.cxx:343
 TRootSniffer.cxx:344
 TRootSniffer.cxx:345
 TRootSniffer.cxx:346
 TRootSniffer.cxx:347
 TRootSniffer.cxx:348
 TRootSniffer.cxx:349
 TRootSniffer.cxx:350
 TRootSniffer.cxx:351
 TRootSniffer.cxx:352
 TRootSniffer.cxx:353
 TRootSniffer.cxx:354
 TRootSniffer.cxx:355
 TRootSniffer.cxx:356
 TRootSniffer.cxx:357
 TRootSniffer.cxx:358
 TRootSniffer.cxx:359
 TRootSniffer.cxx:360
 TRootSniffer.cxx:361
 TRootSniffer.cxx:362
 TRootSniffer.cxx:363
 TRootSniffer.cxx:364
 TRootSniffer.cxx:365
 TRootSniffer.cxx:366
 TRootSniffer.cxx:367
 TRootSniffer.cxx:368
 TRootSniffer.cxx:369
 TRootSniffer.cxx:370
 TRootSniffer.cxx:371
 TRootSniffer.cxx:372
 TRootSniffer.cxx:373
 TRootSniffer.cxx:374
 TRootSniffer.cxx:375
 TRootSniffer.cxx:376
 TRootSniffer.cxx:377
 TRootSniffer.cxx:378
 TRootSniffer.cxx:379
 TRootSniffer.cxx:380
 TRootSniffer.cxx:381
 TRootSniffer.cxx:382
 TRootSniffer.cxx:383
 TRootSniffer.cxx:384
 TRootSniffer.cxx:385
 TRootSniffer.cxx:386
 TRootSniffer.cxx:387
 TRootSniffer.cxx:388
 TRootSniffer.cxx:389
 TRootSniffer.cxx:390
 TRootSniffer.cxx:391
 TRootSniffer.cxx:392
 TRootSniffer.cxx:393
 TRootSniffer.cxx:394
 TRootSniffer.cxx:395
 TRootSniffer.cxx:396
 TRootSniffer.cxx:397
 TRootSniffer.cxx:398
 TRootSniffer.cxx:399
 TRootSniffer.cxx:400
 TRootSniffer.cxx:401
 TRootSniffer.cxx:402
 TRootSniffer.cxx:403
 TRootSniffer.cxx:404
 TRootSniffer.cxx:405
 TRootSniffer.cxx:406
 TRootSniffer.cxx:407
 TRootSniffer.cxx:408
 TRootSniffer.cxx:409
 TRootSniffer.cxx:410
 TRootSniffer.cxx:411
 TRootSniffer.cxx:412
 TRootSniffer.cxx:413
 TRootSniffer.cxx:414
 TRootSniffer.cxx:415
 TRootSniffer.cxx:416
 TRootSniffer.cxx:417
 TRootSniffer.cxx:418
 TRootSniffer.cxx:419
 TRootSniffer.cxx:420
 TRootSniffer.cxx:421
 TRootSniffer.cxx:422
 TRootSniffer.cxx:423
 TRootSniffer.cxx:424
 TRootSniffer.cxx:425
 TRootSniffer.cxx:426
 TRootSniffer.cxx:427
 TRootSniffer.cxx:428
 TRootSniffer.cxx:429
 TRootSniffer.cxx:430
 TRootSniffer.cxx:431
 TRootSniffer.cxx:432
 TRootSniffer.cxx:433
 TRootSniffer.cxx:434
 TRootSniffer.cxx:435
 TRootSniffer.cxx:436
 TRootSniffer.cxx:437
 TRootSniffer.cxx:438
 TRootSniffer.cxx:439
 TRootSniffer.cxx:440
 TRootSniffer.cxx:441
 TRootSniffer.cxx:442
 TRootSniffer.cxx:443
 TRootSniffer.cxx:444
 TRootSniffer.cxx:445
 TRootSniffer.cxx:446
 TRootSniffer.cxx:447
 TRootSniffer.cxx:448
 TRootSniffer.cxx:449
 TRootSniffer.cxx:450
 TRootSniffer.cxx:451
 TRootSniffer.cxx:452
 TRootSniffer.cxx:453
 TRootSniffer.cxx:454
 TRootSniffer.cxx:455
 TRootSniffer.cxx:456
 TRootSniffer.cxx:457
 TRootSniffer.cxx:458
 TRootSniffer.cxx:459
 TRootSniffer.cxx:460
 TRootSniffer.cxx:461
 TRootSniffer.cxx:462
 TRootSniffer.cxx:463
 TRootSniffer.cxx:464
 TRootSniffer.cxx:465
 TRootSniffer.cxx:466
 TRootSniffer.cxx:467
 TRootSniffer.cxx:468
 TRootSniffer.cxx:469
 TRootSniffer.cxx:470
 TRootSniffer.cxx:471
 TRootSniffer.cxx:472
 TRootSniffer.cxx:473
 TRootSniffer.cxx:474
 TRootSniffer.cxx:475
 TRootSniffer.cxx:476
 TRootSniffer.cxx:477
 TRootSniffer.cxx:478
 TRootSniffer.cxx:479
 TRootSniffer.cxx:480
 TRootSniffer.cxx:481
 TRootSniffer.cxx:482
 TRootSniffer.cxx:483
 TRootSniffer.cxx:484
 TRootSniffer.cxx:485
 TRootSniffer.cxx:486
 TRootSniffer.cxx:487
 TRootSniffer.cxx:488
 TRootSniffer.cxx:489
 TRootSniffer.cxx:490
 TRootSniffer.cxx:491
 TRootSniffer.cxx:492
 TRootSniffer.cxx:493
 TRootSniffer.cxx:494
 TRootSniffer.cxx:495
 TRootSniffer.cxx:496
 TRootSniffer.cxx:497
 TRootSniffer.cxx:498
 TRootSniffer.cxx:499
 TRootSniffer.cxx:500
 TRootSniffer.cxx:501
 TRootSniffer.cxx:502
 TRootSniffer.cxx:503
 TRootSniffer.cxx:504
 TRootSniffer.cxx:505
 TRootSniffer.cxx:506
 TRootSniffer.cxx:507
 TRootSniffer.cxx:508
 TRootSniffer.cxx:509
 TRootSniffer.cxx:510
 TRootSniffer.cxx:511
 TRootSniffer.cxx:512
 TRootSniffer.cxx:513
 TRootSniffer.cxx:514
 TRootSniffer.cxx:515
 TRootSniffer.cxx:516
 TRootSniffer.cxx:517
 TRootSniffer.cxx:518
 TRootSniffer.cxx:519
 TRootSniffer.cxx:520
 TRootSniffer.cxx:521
 TRootSniffer.cxx:522
 TRootSniffer.cxx:523
 TRootSniffer.cxx:524
 TRootSniffer.cxx:525
 TRootSniffer.cxx:526
 TRootSniffer.cxx:527
 TRootSniffer.cxx:528
 TRootSniffer.cxx:529
 TRootSniffer.cxx:530
 TRootSniffer.cxx:531
 TRootSniffer.cxx:532
 TRootSniffer.cxx:533
 TRootSniffer.cxx:534
 TRootSniffer.cxx:535
 TRootSniffer.cxx:536
 TRootSniffer.cxx:537
 TRootSniffer.cxx:538
 TRootSniffer.cxx:539
 TRootSniffer.cxx:540
 TRootSniffer.cxx:541
 TRootSniffer.cxx:542
 TRootSniffer.cxx:543
 TRootSniffer.cxx:544
 TRootSniffer.cxx:545
 TRootSniffer.cxx:546
 TRootSniffer.cxx:547
 TRootSniffer.cxx:548
 TRootSniffer.cxx:549
 TRootSniffer.cxx:550
 TRootSniffer.cxx:551
 TRootSniffer.cxx:552
 TRootSniffer.cxx:553
 TRootSniffer.cxx:554
 TRootSniffer.cxx:555
 TRootSniffer.cxx:556
 TRootSniffer.cxx:557
 TRootSniffer.cxx:558
 TRootSniffer.cxx:559
 TRootSniffer.cxx:560
 TRootSniffer.cxx:561
 TRootSniffer.cxx:562
 TRootSniffer.cxx:563
 TRootSniffer.cxx:564
 TRootSniffer.cxx:565
 TRootSniffer.cxx:566
 TRootSniffer.cxx:567
 TRootSniffer.cxx:568
 TRootSniffer.cxx:569
 TRootSniffer.cxx:570
 TRootSniffer.cxx:571
 TRootSniffer.cxx:572
 TRootSniffer.cxx:573
 TRootSniffer.cxx:574
 TRootSniffer.cxx:575
 TRootSniffer.cxx:576
 TRootSniffer.cxx:577
 TRootSniffer.cxx:578
 TRootSniffer.cxx:579
 TRootSniffer.cxx:580
 TRootSniffer.cxx:581
 TRootSniffer.cxx:582
 TRootSniffer.cxx:583
 TRootSniffer.cxx:584
 TRootSniffer.cxx:585
 TRootSniffer.cxx:586
 TRootSniffer.cxx:587
 TRootSniffer.cxx:588
 TRootSniffer.cxx:589
 TRootSniffer.cxx:590
 TRootSniffer.cxx:591
 TRootSniffer.cxx:592
 TRootSniffer.cxx:593
 TRootSniffer.cxx:594
 TRootSniffer.cxx:595
 TRootSniffer.cxx:596
 TRootSniffer.cxx:597
 TRootSniffer.cxx:598
 TRootSniffer.cxx:599
 TRootSniffer.cxx:600
 TRootSniffer.cxx:601
 TRootSniffer.cxx:602
 TRootSniffer.cxx:603
 TRootSniffer.cxx:604
 TRootSniffer.cxx:605
 TRootSniffer.cxx:606
 TRootSniffer.cxx:607
 TRootSniffer.cxx:608
 TRootSniffer.cxx:609
 TRootSniffer.cxx:610
 TRootSniffer.cxx:611
 TRootSniffer.cxx:612
 TRootSniffer.cxx:613
 TRootSniffer.cxx:614
 TRootSniffer.cxx:615
 TRootSniffer.cxx:616
 TRootSniffer.cxx:617
 TRootSniffer.cxx:618
 TRootSniffer.cxx:619
 TRootSniffer.cxx:620
 TRootSniffer.cxx:621
 TRootSniffer.cxx:622
 TRootSniffer.cxx:623
 TRootSniffer.cxx:624
 TRootSniffer.cxx:625
 TRootSniffer.cxx:626
 TRootSniffer.cxx:627
 TRootSniffer.cxx:628
 TRootSniffer.cxx:629
 TRootSniffer.cxx:630
 TRootSniffer.cxx:631
 TRootSniffer.cxx:632
 TRootSniffer.cxx:633
 TRootSniffer.cxx:634
 TRootSniffer.cxx:635
 TRootSniffer.cxx:636
 TRootSniffer.cxx:637
 TRootSniffer.cxx:638
 TRootSniffer.cxx:639
 TRootSniffer.cxx:640
 TRootSniffer.cxx:641
 TRootSniffer.cxx:642
 TRootSniffer.cxx:643
 TRootSniffer.cxx:644
 TRootSniffer.cxx:645
 TRootSniffer.cxx:646
 TRootSniffer.cxx:647
 TRootSniffer.cxx:648
 TRootSniffer.cxx:649
 TRootSniffer.cxx:650
 TRootSniffer.cxx:651
 TRootSniffer.cxx:652
 TRootSniffer.cxx:653
 TRootSniffer.cxx:654
 TRootSniffer.cxx:655
 TRootSniffer.cxx:656
 TRootSniffer.cxx:657
 TRootSniffer.cxx:658
 TRootSniffer.cxx:659
 TRootSniffer.cxx:660
 TRootSniffer.cxx:661
 TRootSniffer.cxx:662
 TRootSniffer.cxx:663
 TRootSniffer.cxx:664
 TRootSniffer.cxx:665
 TRootSniffer.cxx:666
 TRootSniffer.cxx:667
 TRootSniffer.cxx:668
 TRootSniffer.cxx:669
 TRootSniffer.cxx:670
 TRootSniffer.cxx:671
 TRootSniffer.cxx:672
 TRootSniffer.cxx:673
 TRootSniffer.cxx:674
 TRootSniffer.cxx:675
 TRootSniffer.cxx:676
 TRootSniffer.cxx:677
 TRootSniffer.cxx:678
 TRootSniffer.cxx:679
 TRootSniffer.cxx:680
 TRootSniffer.cxx:681
 TRootSniffer.cxx:682
 TRootSniffer.cxx:683
 TRootSniffer.cxx:684
 TRootSniffer.cxx:685
 TRootSniffer.cxx:686
 TRootSniffer.cxx:687
 TRootSniffer.cxx:688
 TRootSniffer.cxx:689
 TRootSniffer.cxx:690
 TRootSniffer.cxx:691
 TRootSniffer.cxx:692
 TRootSniffer.cxx:693
 TRootSniffer.cxx:694
 TRootSniffer.cxx:695
 TRootSniffer.cxx:696
 TRootSniffer.cxx:697
 TRootSniffer.cxx:698
 TRootSniffer.cxx:699
 TRootSniffer.cxx:700
 TRootSniffer.cxx:701
 TRootSniffer.cxx:702
 TRootSniffer.cxx:703
 TRootSniffer.cxx:704
 TRootSniffer.cxx:705
 TRootSniffer.cxx:706
 TRootSniffer.cxx:707
 TRootSniffer.cxx:708
 TRootSniffer.cxx:709
 TRootSniffer.cxx:710
 TRootSniffer.cxx:711
 TRootSniffer.cxx:712
 TRootSniffer.cxx:713
 TRootSniffer.cxx:714
 TRootSniffer.cxx:715
 TRootSniffer.cxx:716
 TRootSniffer.cxx:717
 TRootSniffer.cxx:718
 TRootSniffer.cxx:719
 TRootSniffer.cxx:720
 TRootSniffer.cxx:721
 TRootSniffer.cxx:722
 TRootSniffer.cxx:723
 TRootSniffer.cxx:724
 TRootSniffer.cxx:725
 TRootSniffer.cxx:726
 TRootSniffer.cxx:727
 TRootSniffer.cxx:728
 TRootSniffer.cxx:729
 TRootSniffer.cxx:730
 TRootSniffer.cxx:731
 TRootSniffer.cxx:732
 TRootSniffer.cxx:733
 TRootSniffer.cxx:734
 TRootSniffer.cxx:735
 TRootSniffer.cxx:736
 TRootSniffer.cxx:737
 TRootSniffer.cxx:738
 TRootSniffer.cxx:739
 TRootSniffer.cxx:740
 TRootSniffer.cxx:741
 TRootSniffer.cxx:742
 TRootSniffer.cxx:743
 TRootSniffer.cxx:744
 TRootSniffer.cxx:745
 TRootSniffer.cxx:746
 TRootSniffer.cxx:747
 TRootSniffer.cxx:748
 TRootSniffer.cxx:749
 TRootSniffer.cxx:750
 TRootSniffer.cxx:751
 TRootSniffer.cxx:752
 TRootSniffer.cxx:753
 TRootSniffer.cxx:754
 TRootSniffer.cxx:755
 TRootSniffer.cxx:756
 TRootSniffer.cxx:757
 TRootSniffer.cxx:758
 TRootSniffer.cxx:759
 TRootSniffer.cxx:760
 TRootSniffer.cxx:761
 TRootSniffer.cxx:762
 TRootSniffer.cxx:763
 TRootSniffer.cxx:764
 TRootSniffer.cxx:765
 TRootSniffer.cxx:766
 TRootSniffer.cxx:767
 TRootSniffer.cxx:768
 TRootSniffer.cxx:769
 TRootSniffer.cxx:770
 TRootSniffer.cxx:771
 TRootSniffer.cxx:772
 TRootSniffer.cxx:773
 TRootSniffer.cxx:774
 TRootSniffer.cxx:775
 TRootSniffer.cxx:776
 TRootSniffer.cxx:777
 TRootSniffer.cxx:778
 TRootSniffer.cxx:779
 TRootSniffer.cxx:780
 TRootSniffer.cxx:781
 TRootSniffer.cxx:782
 TRootSniffer.cxx:783
 TRootSniffer.cxx:784
 TRootSniffer.cxx:785
 TRootSniffer.cxx:786
 TRootSniffer.cxx:787
 TRootSniffer.cxx:788
 TRootSniffer.cxx:789
 TRootSniffer.cxx:790
 TRootSniffer.cxx:791
 TRootSniffer.cxx:792
 TRootSniffer.cxx:793
 TRootSniffer.cxx:794
 TRootSniffer.cxx:795
 TRootSniffer.cxx:796
 TRootSniffer.cxx:797
 TRootSniffer.cxx:798
 TRootSniffer.cxx:799
 TRootSniffer.cxx:800
 TRootSniffer.cxx:801
 TRootSniffer.cxx:802
 TRootSniffer.cxx:803
 TRootSniffer.cxx:804
 TRootSniffer.cxx:805
 TRootSniffer.cxx:806
 TRootSniffer.cxx:807
 TRootSniffer.cxx:808
 TRootSniffer.cxx:809
 TRootSniffer.cxx:810
 TRootSniffer.cxx:811
 TRootSniffer.cxx:812
 TRootSniffer.cxx:813
 TRootSniffer.cxx:814
 TRootSniffer.cxx:815
 TRootSniffer.cxx:816
 TRootSniffer.cxx:817
 TRootSniffer.cxx:818
 TRootSniffer.cxx:819
 TRootSniffer.cxx:820
 TRootSniffer.cxx:821
 TRootSniffer.cxx:822
 TRootSniffer.cxx:823
 TRootSniffer.cxx:824
 TRootSniffer.cxx:825
 TRootSniffer.cxx:826
 TRootSniffer.cxx:827
 TRootSniffer.cxx:828
 TRootSniffer.cxx:829
 TRootSniffer.cxx:830
 TRootSniffer.cxx:831
 TRootSniffer.cxx:832
 TRootSniffer.cxx:833
 TRootSniffer.cxx:834
 TRootSniffer.cxx:835
 TRootSniffer.cxx:836
 TRootSniffer.cxx:837
 TRootSniffer.cxx:838
 TRootSniffer.cxx:839
 TRootSniffer.cxx:840
 TRootSniffer.cxx:841
 TRootSniffer.cxx:842
 TRootSniffer.cxx:843
 TRootSniffer.cxx:844
 TRootSniffer.cxx:845
 TRootSniffer.cxx:846
 TRootSniffer.cxx:847
 TRootSniffer.cxx:848
 TRootSniffer.cxx:849
 TRootSniffer.cxx:850
 TRootSniffer.cxx:851
 TRootSniffer.cxx:852
 TRootSniffer.cxx:853
 TRootSniffer.cxx:854
 TRootSniffer.cxx:855
 TRootSniffer.cxx:856
 TRootSniffer.cxx:857
 TRootSniffer.cxx:858
 TRootSniffer.cxx:859
 TRootSniffer.cxx:860
 TRootSniffer.cxx:861
 TRootSniffer.cxx:862
 TRootSniffer.cxx:863
 TRootSniffer.cxx:864
 TRootSniffer.cxx:865
 TRootSniffer.cxx:866
 TRootSniffer.cxx:867
 TRootSniffer.cxx:868
 TRootSniffer.cxx:869
 TRootSniffer.cxx:870
 TRootSniffer.cxx:871
 TRootSniffer.cxx:872
 TRootSniffer.cxx:873
 TRootSniffer.cxx:874
 TRootSniffer.cxx:875
 TRootSniffer.cxx:876
 TRootSniffer.cxx:877
 TRootSniffer.cxx:878
 TRootSniffer.cxx:879
 TRootSniffer.cxx:880
 TRootSniffer.cxx:881
 TRootSniffer.cxx:882
 TRootSniffer.cxx:883
 TRootSniffer.cxx:884
 TRootSniffer.cxx:885
 TRootSniffer.cxx:886
 TRootSniffer.cxx:887
 TRootSniffer.cxx:888
 TRootSniffer.cxx:889
 TRootSniffer.cxx:890
 TRootSniffer.cxx:891
 TRootSniffer.cxx:892
 TRootSniffer.cxx:893
 TRootSniffer.cxx:894
 TRootSniffer.cxx:895
 TRootSniffer.cxx:896
 TRootSniffer.cxx:897
 TRootSniffer.cxx:898
 TRootSniffer.cxx:899
 TRootSniffer.cxx:900
 TRootSniffer.cxx:901
 TRootSniffer.cxx:902
 TRootSniffer.cxx:903
 TRootSniffer.cxx:904
 TRootSniffer.cxx:905
 TRootSniffer.cxx:906
 TRootSniffer.cxx:907
 TRootSniffer.cxx:908
 TRootSniffer.cxx:909
 TRootSniffer.cxx:910
 TRootSniffer.cxx:911
 TRootSniffer.cxx:912
 TRootSniffer.cxx:913
 TRootSniffer.cxx:914
 TRootSniffer.cxx:915
 TRootSniffer.cxx:916
 TRootSniffer.cxx:917
 TRootSniffer.cxx:918
 TRootSniffer.cxx:919
 TRootSniffer.cxx:920
 TRootSniffer.cxx:921
 TRootSniffer.cxx:922
 TRootSniffer.cxx:923
 TRootSniffer.cxx:924
 TRootSniffer.cxx:925
 TRootSniffer.cxx:926
 TRootSniffer.cxx:927
 TRootSniffer.cxx:928
 TRootSniffer.cxx:929
 TRootSniffer.cxx:930
 TRootSniffer.cxx:931
 TRootSniffer.cxx:932
 TRootSniffer.cxx:933
 TRootSniffer.cxx:934
 TRootSniffer.cxx:935
 TRootSniffer.cxx:936
 TRootSniffer.cxx:937
 TRootSniffer.cxx:938
 TRootSniffer.cxx:939
 TRootSniffer.cxx:940
 TRootSniffer.cxx:941
 TRootSniffer.cxx:942
 TRootSniffer.cxx:943
 TRootSniffer.cxx:944
 TRootSniffer.cxx:945
 TRootSniffer.cxx:946
 TRootSniffer.cxx:947
 TRootSniffer.cxx:948
 TRootSniffer.cxx:949
 TRootSniffer.cxx:950
 TRootSniffer.cxx:951
 TRootSniffer.cxx:952
 TRootSniffer.cxx:953
 TRootSniffer.cxx:954
 TRootSniffer.cxx:955
 TRootSniffer.cxx:956
 TRootSniffer.cxx:957
 TRootSniffer.cxx:958
 TRootSniffer.cxx:959
 TRootSniffer.cxx:960
 TRootSniffer.cxx:961
 TRootSniffer.cxx:962
 TRootSniffer.cxx:963
 TRootSniffer.cxx:964
 TRootSniffer.cxx:965
 TRootSniffer.cxx:966
 TRootSniffer.cxx:967
 TRootSniffer.cxx:968
 TRootSniffer.cxx:969
 TRootSniffer.cxx:970
 TRootSniffer.cxx:971
 TRootSniffer.cxx:972
 TRootSniffer.cxx:973
 TRootSniffer.cxx:974
 TRootSniffer.cxx:975
 TRootSniffer.cxx:976
 TRootSniffer.cxx:977
 TRootSniffer.cxx:978
 TRootSniffer.cxx:979
 TRootSniffer.cxx:980
 TRootSniffer.cxx:981
 TRootSniffer.cxx:982
 TRootSniffer.cxx:983
 TRootSniffer.cxx:984
 TRootSniffer.cxx:985
 TRootSniffer.cxx:986
 TRootSniffer.cxx:987
 TRootSniffer.cxx:988
 TRootSniffer.cxx:989
 TRootSniffer.cxx:990
 TRootSniffer.cxx:991
 TRootSniffer.cxx:992
 TRootSniffer.cxx:993
 TRootSniffer.cxx:994
 TRootSniffer.cxx:995
 TRootSniffer.cxx:996
 TRootSniffer.cxx:997
 TRootSniffer.cxx:998
 TRootSniffer.cxx:999
 TRootSniffer.cxx:1000
 TRootSniffer.cxx:1001
 TRootSniffer.cxx:1002
 TRootSniffer.cxx:1003
 TRootSniffer.cxx:1004
 TRootSniffer.cxx:1005
 TRootSniffer.cxx:1006
 TRootSniffer.cxx:1007
 TRootSniffer.cxx:1008
 TRootSniffer.cxx:1009
 TRootSniffer.cxx:1010
 TRootSniffer.cxx:1011
 TRootSniffer.cxx:1012
 TRootSniffer.cxx:1013
 TRootSniffer.cxx:1014
 TRootSniffer.cxx:1015
 TRootSniffer.cxx:1016
 TRootSniffer.cxx:1017
 TRootSniffer.cxx:1018
 TRootSniffer.cxx:1019
 TRootSniffer.cxx:1020
 TRootSniffer.cxx:1021
 TRootSniffer.cxx:1022
 TRootSniffer.cxx:1023
 TRootSniffer.cxx:1024
 TRootSniffer.cxx:1025
 TRootSniffer.cxx:1026
 TRootSniffer.cxx:1027
 TRootSniffer.cxx:1028
 TRootSniffer.cxx:1029
 TRootSniffer.cxx:1030
 TRootSniffer.cxx:1031
 TRootSniffer.cxx:1032
 TRootSniffer.cxx:1033
 TRootSniffer.cxx:1034
 TRootSniffer.cxx:1035
 TRootSniffer.cxx:1036
 TRootSniffer.cxx:1037
 TRootSniffer.cxx:1038
 TRootSniffer.cxx:1039
 TRootSniffer.cxx:1040
 TRootSniffer.cxx:1041
 TRootSniffer.cxx:1042
 TRootSniffer.cxx:1043
 TRootSniffer.cxx:1044
 TRootSniffer.cxx:1045
 TRootSniffer.cxx:1046
 TRootSniffer.cxx:1047
 TRootSniffer.cxx:1048
 TRootSniffer.cxx:1049
 TRootSniffer.cxx:1050
 TRootSniffer.cxx:1051
 TRootSniffer.cxx:1052
 TRootSniffer.cxx:1053
 TRootSniffer.cxx:1054
 TRootSniffer.cxx:1055
 TRootSniffer.cxx:1056
 TRootSniffer.cxx:1057
 TRootSniffer.cxx:1058
 TRootSniffer.cxx:1059
 TRootSniffer.cxx:1060
 TRootSniffer.cxx:1061
 TRootSniffer.cxx:1062
 TRootSniffer.cxx:1063
 TRootSniffer.cxx:1064
 TRootSniffer.cxx:1065
 TRootSniffer.cxx:1066
 TRootSniffer.cxx:1067
 TRootSniffer.cxx:1068
 TRootSniffer.cxx:1069
 TRootSniffer.cxx:1070
 TRootSniffer.cxx:1071
 TRootSniffer.cxx:1072
 TRootSniffer.cxx:1073
 TRootSniffer.cxx:1074
 TRootSniffer.cxx:1075
 TRootSniffer.cxx:1076
 TRootSniffer.cxx:1077
 TRootSniffer.cxx:1078
 TRootSniffer.cxx:1079
 TRootSniffer.cxx:1080
 TRootSniffer.cxx:1081
 TRootSniffer.cxx:1082
 TRootSniffer.cxx:1083
 TRootSniffer.cxx:1084
 TRootSniffer.cxx:1085
 TRootSniffer.cxx:1086
 TRootSniffer.cxx:1087
 TRootSniffer.cxx:1088
 TRootSniffer.cxx:1089
 TRootSniffer.cxx:1090
 TRootSniffer.cxx:1091
 TRootSniffer.cxx:1092
 TRootSniffer.cxx:1093
 TRootSniffer.cxx:1094
 TRootSniffer.cxx:1095
 TRootSniffer.cxx:1096
 TRootSniffer.cxx:1097
 TRootSniffer.cxx:1098
 TRootSniffer.cxx:1099
 TRootSniffer.cxx:1100
 TRootSniffer.cxx:1101
 TRootSniffer.cxx:1102
 TRootSniffer.cxx:1103
 TRootSniffer.cxx:1104
 TRootSniffer.cxx:1105
 TRootSniffer.cxx:1106
 TRootSniffer.cxx:1107
 TRootSniffer.cxx:1108
 TRootSniffer.cxx:1109
 TRootSniffer.cxx:1110
 TRootSniffer.cxx:1111
 TRootSniffer.cxx:1112
 TRootSniffer.cxx:1113
 TRootSniffer.cxx:1114
 TRootSniffer.cxx:1115
 TRootSniffer.cxx:1116
 TRootSniffer.cxx:1117
 TRootSniffer.cxx:1118
 TRootSniffer.cxx:1119
 TRootSniffer.cxx:1120
 TRootSniffer.cxx:1121
 TRootSniffer.cxx:1122
 TRootSniffer.cxx:1123
 TRootSniffer.cxx:1124
 TRootSniffer.cxx:1125
 TRootSniffer.cxx:1126
 TRootSniffer.cxx:1127
 TRootSniffer.cxx:1128
 TRootSniffer.cxx:1129
 TRootSniffer.cxx:1130
 TRootSniffer.cxx:1131
 TRootSniffer.cxx:1132
 TRootSniffer.cxx:1133
 TRootSniffer.cxx:1134
 TRootSniffer.cxx:1135
 TRootSniffer.cxx:1136
 TRootSniffer.cxx:1137
 TRootSniffer.cxx:1138
 TRootSniffer.cxx:1139
 TRootSniffer.cxx:1140
 TRootSniffer.cxx:1141
 TRootSniffer.cxx:1142
 TRootSniffer.cxx:1143
 TRootSniffer.cxx:1144
 TRootSniffer.cxx:1145
 TRootSniffer.cxx:1146
 TRootSniffer.cxx:1147
 TRootSniffer.cxx:1148
 TRootSniffer.cxx:1149
 TRootSniffer.cxx:1150
 TRootSniffer.cxx:1151
 TRootSniffer.cxx:1152
 TRootSniffer.cxx:1153
 TRootSniffer.cxx:1154
 TRootSniffer.cxx:1155
 TRootSniffer.cxx:1156
 TRootSniffer.cxx:1157
 TRootSniffer.cxx:1158
 TRootSniffer.cxx:1159
 TRootSniffer.cxx:1160
 TRootSniffer.cxx:1161
 TRootSniffer.cxx:1162
 TRootSniffer.cxx:1163
 TRootSniffer.cxx:1164
 TRootSniffer.cxx:1165
 TRootSniffer.cxx:1166
 TRootSniffer.cxx:1167
 TRootSniffer.cxx:1168
 TRootSniffer.cxx:1169
 TRootSniffer.cxx:1170
 TRootSniffer.cxx:1171
 TRootSniffer.cxx:1172
 TRootSniffer.cxx:1173
 TRootSniffer.cxx:1174
 TRootSniffer.cxx:1175
 TRootSniffer.cxx:1176
 TRootSniffer.cxx:1177
 TRootSniffer.cxx:1178
 TRootSniffer.cxx:1179
 TRootSniffer.cxx:1180
 TRootSniffer.cxx:1181
 TRootSniffer.cxx:1182
 TRootSniffer.cxx:1183
 TRootSniffer.cxx:1184
 TRootSniffer.cxx:1185
 TRootSniffer.cxx:1186
 TRootSniffer.cxx:1187
 TRootSniffer.cxx:1188
 TRootSniffer.cxx:1189
 TRootSniffer.cxx:1190
 TRootSniffer.cxx:1191
 TRootSniffer.cxx:1192
 TRootSniffer.cxx:1193
 TRootSniffer.cxx:1194
 TRootSniffer.cxx:1195
 TRootSniffer.cxx:1196
 TRootSniffer.cxx:1197
 TRootSniffer.cxx:1198
 TRootSniffer.cxx:1199
 TRootSniffer.cxx:1200
 TRootSniffer.cxx:1201
 TRootSniffer.cxx:1202
 TRootSniffer.cxx:1203
 TRootSniffer.cxx:1204
 TRootSniffer.cxx:1205
 TRootSniffer.cxx:1206
 TRootSniffer.cxx:1207
 TRootSniffer.cxx:1208
 TRootSniffer.cxx:1209
 TRootSniffer.cxx:1210
 TRootSniffer.cxx:1211
 TRootSniffer.cxx:1212
 TRootSniffer.cxx:1213
 TRootSniffer.cxx:1214
 TRootSniffer.cxx:1215
 TRootSniffer.cxx:1216
 TRootSniffer.cxx:1217
 TRootSniffer.cxx:1218
 TRootSniffer.cxx:1219
 TRootSniffer.cxx:1220
 TRootSniffer.cxx:1221
 TRootSniffer.cxx:1222
 TRootSniffer.cxx:1223
 TRootSniffer.cxx:1224
 TRootSniffer.cxx:1225
 TRootSniffer.cxx:1226
 TRootSniffer.cxx:1227
 TRootSniffer.cxx:1228
 TRootSniffer.cxx:1229
 TRootSniffer.cxx:1230
 TRootSniffer.cxx:1231
 TRootSniffer.cxx:1232
 TRootSniffer.cxx:1233
 TRootSniffer.cxx:1234
 TRootSniffer.cxx:1235
 TRootSniffer.cxx:1236
 TRootSniffer.cxx:1237
 TRootSniffer.cxx:1238
 TRootSniffer.cxx:1239
 TRootSniffer.cxx:1240
 TRootSniffer.cxx:1241
 TRootSniffer.cxx:1242
 TRootSniffer.cxx:1243
 TRootSniffer.cxx:1244
 TRootSniffer.cxx:1245
 TRootSniffer.cxx:1246
 TRootSniffer.cxx:1247
 TRootSniffer.cxx:1248
 TRootSniffer.cxx:1249
 TRootSniffer.cxx:1250
 TRootSniffer.cxx:1251
 TRootSniffer.cxx:1252
 TRootSniffer.cxx:1253
 TRootSniffer.cxx:1254
 TRootSniffer.cxx:1255
 TRootSniffer.cxx:1256
 TRootSniffer.cxx:1257
 TRootSniffer.cxx:1258
 TRootSniffer.cxx:1259
 TRootSniffer.cxx:1260
 TRootSniffer.cxx:1261
 TRootSniffer.cxx:1262
 TRootSniffer.cxx:1263
 TRootSniffer.cxx:1264
 TRootSniffer.cxx:1265
 TRootSniffer.cxx:1266
 TRootSniffer.cxx:1267
 TRootSniffer.cxx:1268
 TRootSniffer.cxx:1269
 TRootSniffer.cxx:1270
 TRootSniffer.cxx:1271
 TRootSniffer.cxx:1272
 TRootSniffer.cxx:1273
 TRootSniffer.cxx:1274
 TRootSniffer.cxx:1275
 TRootSniffer.cxx:1276
 TRootSniffer.cxx:1277
 TRootSniffer.cxx:1278
 TRootSniffer.cxx:1279
 TRootSniffer.cxx:1280
 TRootSniffer.cxx:1281
 TRootSniffer.cxx:1282
 TRootSniffer.cxx:1283
 TRootSniffer.cxx:1284
 TRootSniffer.cxx:1285
 TRootSniffer.cxx:1286
 TRootSniffer.cxx:1287
 TRootSniffer.cxx:1288
 TRootSniffer.cxx:1289
 TRootSniffer.cxx:1290
 TRootSniffer.cxx:1291
 TRootSniffer.cxx:1292
 TRootSniffer.cxx:1293
 TRootSniffer.cxx:1294
 TRootSniffer.cxx:1295
 TRootSniffer.cxx:1296
 TRootSniffer.cxx:1297
 TRootSniffer.cxx:1298
 TRootSniffer.cxx:1299
 TRootSniffer.cxx:1300
 TRootSniffer.cxx:1301
 TRootSniffer.cxx:1302
 TRootSniffer.cxx:1303
 TRootSniffer.cxx:1304
 TRootSniffer.cxx:1305
 TRootSniffer.cxx:1306
 TRootSniffer.cxx:1307
 TRootSniffer.cxx:1308
 TRootSniffer.cxx:1309
 TRootSniffer.cxx:1310
 TRootSniffer.cxx:1311
 TRootSniffer.cxx:1312
 TRootSniffer.cxx:1313
 TRootSniffer.cxx:1314
 TRootSniffer.cxx:1315
 TRootSniffer.cxx:1316
 TRootSniffer.cxx:1317
 TRootSniffer.cxx:1318
 TRootSniffer.cxx:1319
 TRootSniffer.cxx:1320
 TRootSniffer.cxx:1321
 TRootSniffer.cxx:1322
 TRootSniffer.cxx:1323
 TRootSniffer.cxx:1324
 TRootSniffer.cxx:1325
 TRootSniffer.cxx:1326
 TRootSniffer.cxx:1327
 TRootSniffer.cxx:1328
 TRootSniffer.cxx:1329
 TRootSniffer.cxx:1330
 TRootSniffer.cxx:1331
 TRootSniffer.cxx:1332
 TRootSniffer.cxx:1333
 TRootSniffer.cxx:1334
 TRootSniffer.cxx:1335
 TRootSniffer.cxx:1336
 TRootSniffer.cxx:1337
 TRootSniffer.cxx:1338
 TRootSniffer.cxx:1339
 TRootSniffer.cxx:1340
 TRootSniffer.cxx:1341
 TRootSniffer.cxx:1342
 TRootSniffer.cxx:1343
 TRootSniffer.cxx:1344
 TRootSniffer.cxx:1345
 TRootSniffer.cxx:1346
 TRootSniffer.cxx:1347
 TRootSniffer.cxx:1348
 TRootSniffer.cxx:1349
 TRootSniffer.cxx:1350
 TRootSniffer.cxx:1351
 TRootSniffer.cxx:1352
 TRootSniffer.cxx:1353
 TRootSniffer.cxx:1354
 TRootSniffer.cxx:1355
 TRootSniffer.cxx:1356
 TRootSniffer.cxx:1357
 TRootSniffer.cxx:1358
 TRootSniffer.cxx:1359
 TRootSniffer.cxx:1360
 TRootSniffer.cxx:1361
 TRootSniffer.cxx:1362
 TRootSniffer.cxx:1363
 TRootSniffer.cxx:1364
 TRootSniffer.cxx:1365
 TRootSniffer.cxx:1366
 TRootSniffer.cxx:1367
 TRootSniffer.cxx:1368
 TRootSniffer.cxx:1369
 TRootSniffer.cxx:1370
 TRootSniffer.cxx:1371
 TRootSniffer.cxx:1372
 TRootSniffer.cxx:1373
 TRootSniffer.cxx:1374
 TRootSniffer.cxx:1375
 TRootSniffer.cxx:1376
 TRootSniffer.cxx:1377
 TRootSniffer.cxx:1378
 TRootSniffer.cxx:1379
 TRootSniffer.cxx:1380
 TRootSniffer.cxx:1381
 TRootSniffer.cxx:1382
 TRootSniffer.cxx:1383
 TRootSniffer.cxx:1384
 TRootSniffer.cxx:1385
 TRootSniffer.cxx:1386
 TRootSniffer.cxx:1387
 TRootSniffer.cxx:1388
 TRootSniffer.cxx:1389
 TRootSniffer.cxx:1390
 TRootSniffer.cxx:1391
 TRootSniffer.cxx:1392
 TRootSniffer.cxx:1393
 TRootSniffer.cxx:1394
 TRootSniffer.cxx:1395
 TRootSniffer.cxx:1396
 TRootSniffer.cxx:1397
 TRootSniffer.cxx:1398
 TRootSniffer.cxx:1399
 TRootSniffer.cxx:1400
 TRootSniffer.cxx:1401
 TRootSniffer.cxx:1402
 TRootSniffer.cxx:1403
 TRootSniffer.cxx:1404
 TRootSniffer.cxx:1405
 TRootSniffer.cxx:1406
 TRootSniffer.cxx:1407
 TRootSniffer.cxx:1408
 TRootSniffer.cxx:1409
 TRootSniffer.cxx:1410
 TRootSniffer.cxx:1411
 TRootSniffer.cxx:1412
 TRootSniffer.cxx:1413
 TRootSniffer.cxx:1414
 TRootSniffer.cxx:1415
 TRootSniffer.cxx:1416
 TRootSniffer.cxx:1417
 TRootSniffer.cxx:1418
 TRootSniffer.cxx:1419
 TRootSniffer.cxx:1420
 TRootSniffer.cxx:1421
 TRootSniffer.cxx:1422
 TRootSniffer.cxx:1423
 TRootSniffer.cxx:1424
 TRootSniffer.cxx:1425
 TRootSniffer.cxx:1426
 TRootSniffer.cxx:1427
 TRootSniffer.cxx:1428
 TRootSniffer.cxx:1429
 TRootSniffer.cxx:1430
 TRootSniffer.cxx:1431
 TRootSniffer.cxx:1432
 TRootSniffer.cxx:1433
 TRootSniffer.cxx:1434
 TRootSniffer.cxx:1435
 TRootSniffer.cxx:1436
 TRootSniffer.cxx:1437
 TRootSniffer.cxx:1438
 TRootSniffer.cxx:1439
 TRootSniffer.cxx:1440
 TRootSniffer.cxx:1441
 TRootSniffer.cxx:1442
 TRootSniffer.cxx:1443
 TRootSniffer.cxx:1444
 TRootSniffer.cxx:1445
 TRootSniffer.cxx:1446
 TRootSniffer.cxx:1447
 TRootSniffer.cxx:1448
 TRootSniffer.cxx:1449
 TRootSniffer.cxx:1450
 TRootSniffer.cxx:1451
 TRootSniffer.cxx:1452
 TRootSniffer.cxx:1453
 TRootSniffer.cxx:1454
 TRootSniffer.cxx:1455
 TRootSniffer.cxx:1456
 TRootSniffer.cxx:1457
 TRootSniffer.cxx:1458
 TRootSniffer.cxx:1459
 TRootSniffer.cxx:1460
 TRootSniffer.cxx:1461
 TRootSniffer.cxx:1462
 TRootSniffer.cxx:1463
 TRootSniffer.cxx:1464
 TRootSniffer.cxx:1465
 TRootSniffer.cxx:1466
 TRootSniffer.cxx:1467
 TRootSniffer.cxx:1468
 TRootSniffer.cxx:1469
 TRootSniffer.cxx:1470
 TRootSniffer.cxx:1471
 TRootSniffer.cxx:1472
 TRootSniffer.cxx:1473
 TRootSniffer.cxx:1474
 TRootSniffer.cxx:1475
 TRootSniffer.cxx:1476
 TRootSniffer.cxx:1477
 TRootSniffer.cxx:1478
 TRootSniffer.cxx:1479
 TRootSniffer.cxx:1480
 TRootSniffer.cxx:1481
 TRootSniffer.cxx:1482
 TRootSniffer.cxx:1483
 TRootSniffer.cxx:1484
 TRootSniffer.cxx:1485
 TRootSniffer.cxx:1486
 TRootSniffer.cxx:1487
 TRootSniffer.cxx:1488
 TRootSniffer.cxx:1489
 TRootSniffer.cxx:1490
 TRootSniffer.cxx:1491
 TRootSniffer.cxx:1492
 TRootSniffer.cxx:1493
 TRootSniffer.cxx:1494
 TRootSniffer.cxx:1495
 TRootSniffer.cxx:1496
 TRootSniffer.cxx:1497
 TRootSniffer.cxx:1498
 TRootSniffer.cxx:1499
 TRootSniffer.cxx:1500
 TRootSniffer.cxx:1501
 TRootSniffer.cxx:1502
 TRootSniffer.cxx:1503
 TRootSniffer.cxx:1504
 TRootSniffer.cxx:1505
 TRootSniffer.cxx:1506
 TRootSniffer.cxx:1507
 TRootSniffer.cxx:1508
 TRootSniffer.cxx:1509
 TRootSniffer.cxx:1510
 TRootSniffer.cxx:1511
 TRootSniffer.cxx:1512
 TRootSniffer.cxx:1513
 TRootSniffer.cxx:1514
 TRootSniffer.cxx:1515
 TRootSniffer.cxx:1516
 TRootSniffer.cxx:1517
 TRootSniffer.cxx:1518
 TRootSniffer.cxx:1519
 TRootSniffer.cxx:1520
 TRootSniffer.cxx:1521
 TRootSniffer.cxx:1522
 TRootSniffer.cxx:1523
 TRootSniffer.cxx:1524
 TRootSniffer.cxx:1525
 TRootSniffer.cxx:1526
 TRootSniffer.cxx:1527
 TRootSniffer.cxx:1528
 TRootSniffer.cxx:1529
 TRootSniffer.cxx:1530
 TRootSniffer.cxx:1531
 TRootSniffer.cxx:1532
 TRootSniffer.cxx:1533
 TRootSniffer.cxx:1534
 TRootSniffer.cxx:1535
 TRootSniffer.cxx:1536
 TRootSniffer.cxx:1537
 TRootSniffer.cxx:1538
 TRootSniffer.cxx:1539
 TRootSniffer.cxx:1540
 TRootSniffer.cxx:1541
 TRootSniffer.cxx:1542
 TRootSniffer.cxx:1543
 TRootSniffer.cxx:1544
 TRootSniffer.cxx:1545
 TRootSniffer.cxx:1546
 TRootSniffer.cxx:1547
 TRootSniffer.cxx:1548
 TRootSniffer.cxx:1549
 TRootSniffer.cxx:1550
 TRootSniffer.cxx:1551
 TRootSniffer.cxx:1552
 TRootSniffer.cxx:1553
 TRootSniffer.cxx:1554
 TRootSniffer.cxx:1555
 TRootSniffer.cxx:1556
 TRootSniffer.cxx:1557
 TRootSniffer.cxx:1558
 TRootSniffer.cxx:1559
 TRootSniffer.cxx:1560
 TRootSniffer.cxx:1561
 TRootSniffer.cxx:1562
 TRootSniffer.cxx:1563
 TRootSniffer.cxx:1564
 TRootSniffer.cxx:1565
 TRootSniffer.cxx:1566
 TRootSniffer.cxx:1567
 TRootSniffer.cxx:1568
 TRootSniffer.cxx:1569
 TRootSniffer.cxx:1570
 TRootSniffer.cxx:1571
 TRootSniffer.cxx:1572
 TRootSniffer.cxx:1573
 TRootSniffer.cxx:1574
 TRootSniffer.cxx:1575
 TRootSniffer.cxx:1576
 TRootSniffer.cxx:1577
 TRootSniffer.cxx:1578
 TRootSniffer.cxx:1579
 TRootSniffer.cxx:1580
 TRootSniffer.cxx:1581
 TRootSniffer.cxx:1582
 TRootSniffer.cxx:1583
 TRootSniffer.cxx:1584
 TRootSniffer.cxx:1585
 TRootSniffer.cxx:1586
 TRootSniffer.cxx:1587
 TRootSniffer.cxx:1588
 TRootSniffer.cxx:1589
 TRootSniffer.cxx:1590
 TRootSniffer.cxx:1591
 TRootSniffer.cxx:1592
 TRootSniffer.cxx:1593
 TRootSniffer.cxx:1594
 TRootSniffer.cxx:1595
 TRootSniffer.cxx:1596
 TRootSniffer.cxx:1597
 TRootSniffer.cxx:1598
 TRootSniffer.cxx:1599
 TRootSniffer.cxx:1600
 TRootSniffer.cxx:1601
 TRootSniffer.cxx:1602
 TRootSniffer.cxx:1603
 TRootSniffer.cxx:1604
 TRootSniffer.cxx:1605
 TRootSniffer.cxx:1606
 TRootSniffer.cxx:1607
 TRootSniffer.cxx:1608
 TRootSniffer.cxx:1609
 TRootSniffer.cxx:1610
 TRootSniffer.cxx:1611
 TRootSniffer.cxx:1612
 TRootSniffer.cxx:1613
 TRootSniffer.cxx:1614
 TRootSniffer.cxx:1615
 TRootSniffer.cxx:1616
 TRootSniffer.cxx:1617
 TRootSniffer.cxx:1618
 TRootSniffer.cxx:1619
 TRootSniffer.cxx:1620
 TRootSniffer.cxx:1621
 TRootSniffer.cxx:1622
 TRootSniffer.cxx:1623
 TRootSniffer.cxx:1624
 TRootSniffer.cxx:1625
 TRootSniffer.cxx:1626
 TRootSniffer.cxx:1627
 TRootSniffer.cxx:1628
 TRootSniffer.cxx:1629
 TRootSniffer.cxx:1630
 TRootSniffer.cxx:1631
 TRootSniffer.cxx:1632
 TRootSniffer.cxx:1633
 TRootSniffer.cxx:1634
 TRootSniffer.cxx:1635
 TRootSniffer.cxx:1636
 TRootSniffer.cxx:1637
 TRootSniffer.cxx:1638
 TRootSniffer.cxx:1639
 TRootSniffer.cxx:1640
 TRootSniffer.cxx:1641
 TRootSniffer.cxx:1642
 TRootSniffer.cxx:1643
 TRootSniffer.cxx:1644
 TRootSniffer.cxx:1645
 TRootSniffer.cxx:1646
 TRootSniffer.cxx:1647
 TRootSniffer.cxx:1648
 TRootSniffer.cxx:1649
 TRootSniffer.cxx:1650
 TRootSniffer.cxx:1651
 TRootSniffer.cxx:1652
 TRootSniffer.cxx:1653
 TRootSniffer.cxx:1654
 TRootSniffer.cxx:1655
 TRootSniffer.cxx:1656
 TRootSniffer.cxx:1657
 TRootSniffer.cxx:1658
 TRootSniffer.cxx:1659
 TRootSniffer.cxx:1660
 TRootSniffer.cxx:1661
 TRootSniffer.cxx:1662
 TRootSniffer.cxx:1663
 TRootSniffer.cxx:1664
 TRootSniffer.cxx:1665
 TRootSniffer.cxx:1666
 TRootSniffer.cxx:1667
 TRootSniffer.cxx:1668
 TRootSniffer.cxx:1669
 TRootSniffer.cxx:1670
 TRootSniffer.cxx:1671
 TRootSniffer.cxx:1672
 TRootSniffer.cxx:1673
 TRootSniffer.cxx:1674
 TRootSniffer.cxx:1675
 TRootSniffer.cxx:1676
 TRootSniffer.cxx:1677
 TRootSniffer.cxx:1678
 TRootSniffer.cxx:1679
 TRootSniffer.cxx:1680
 TRootSniffer.cxx:1681
 TRootSniffer.cxx:1682
 TRootSniffer.cxx:1683
 TRootSniffer.cxx:1684
 TRootSniffer.cxx:1685
 TRootSniffer.cxx:1686
 TRootSniffer.cxx:1687
 TRootSniffer.cxx:1688
 TRootSniffer.cxx:1689
 TRootSniffer.cxx:1690
 TRootSniffer.cxx:1691
 TRootSniffer.cxx:1692
 TRootSniffer.cxx:1693
 TRootSniffer.cxx:1694
 TRootSniffer.cxx:1695
 TRootSniffer.cxx:1696
 TRootSniffer.cxx:1697
 TRootSniffer.cxx:1698
 TRootSniffer.cxx:1699
 TRootSniffer.cxx:1700
 TRootSniffer.cxx:1701
 TRootSniffer.cxx:1702
 TRootSniffer.cxx:1703
 TRootSniffer.cxx:1704
 TRootSniffer.cxx:1705
 TRootSniffer.cxx:1706
 TRootSniffer.cxx:1707
 TRootSniffer.cxx:1708
 TRootSniffer.cxx:1709
 TRootSniffer.cxx:1710
 TRootSniffer.cxx:1711
 TRootSniffer.cxx:1712
 TRootSniffer.cxx:1713
 TRootSniffer.cxx:1714
 TRootSniffer.cxx:1715
 TRootSniffer.cxx:1716
 TRootSniffer.cxx:1717
 TRootSniffer.cxx:1718
 TRootSniffer.cxx:1719
 TRootSniffer.cxx:1720
 TRootSniffer.cxx:1721
 TRootSniffer.cxx:1722
 TRootSniffer.cxx:1723
 TRootSniffer.cxx:1724
 TRootSniffer.cxx:1725
 TRootSniffer.cxx:1726
 TRootSniffer.cxx:1727
 TRootSniffer.cxx:1728
 TRootSniffer.cxx:1729
 TRootSniffer.cxx:1730
 TRootSniffer.cxx:1731
 TRootSniffer.cxx:1732
 TRootSniffer.cxx:1733
 TRootSniffer.cxx:1734
 TRootSniffer.cxx:1735
 TRootSniffer.cxx:1736
 TRootSniffer.cxx:1737
 TRootSniffer.cxx:1738
 TRootSniffer.cxx:1739
 TRootSniffer.cxx:1740
 TRootSniffer.cxx:1741
 TRootSniffer.cxx:1742
 TRootSniffer.cxx:1743
 TRootSniffer.cxx:1744
 TRootSniffer.cxx:1745
 TRootSniffer.cxx:1746
 TRootSniffer.cxx:1747
 TRootSniffer.cxx:1748
 TRootSniffer.cxx:1749
 TRootSniffer.cxx:1750
 TRootSniffer.cxx:1751
 TRootSniffer.cxx:1752
 TRootSniffer.cxx:1753
 TRootSniffer.cxx:1754
 TRootSniffer.cxx:1755
 TRootSniffer.cxx:1756
 TRootSniffer.cxx:1757
 TRootSniffer.cxx:1758
 TRootSniffer.cxx:1759
 TRootSniffer.cxx:1760
 TRootSniffer.cxx:1761
 TRootSniffer.cxx:1762
 TRootSniffer.cxx:1763
 TRootSniffer.cxx:1764
 TRootSniffer.cxx:1765
 TRootSniffer.cxx:1766
 TRootSniffer.cxx:1767
 TRootSniffer.cxx:1768
 TRootSniffer.cxx:1769
 TRootSniffer.cxx:1770
 TRootSniffer.cxx:1771
 TRootSniffer.cxx:1772
 TRootSniffer.cxx:1773
 TRootSniffer.cxx:1774
 TRootSniffer.cxx:1775
 TRootSniffer.cxx:1776
 TRootSniffer.cxx:1777
 TRootSniffer.cxx:1778
 TRootSniffer.cxx:1779
 TRootSniffer.cxx:1780
 TRootSniffer.cxx:1781
 TRootSniffer.cxx:1782
 TRootSniffer.cxx:1783
 TRootSniffer.cxx:1784
 TRootSniffer.cxx:1785
 TRootSniffer.cxx:1786
 TRootSniffer.cxx:1787
 TRootSniffer.cxx:1788
 TRootSniffer.cxx:1789
 TRootSniffer.cxx:1790
 TRootSniffer.cxx:1791
 TRootSniffer.cxx:1792
 TRootSniffer.cxx:1793
 TRootSniffer.cxx:1794
 TRootSniffer.cxx:1795
 TRootSniffer.cxx:1796
 TRootSniffer.cxx:1797
 TRootSniffer.cxx:1798
 TRootSniffer.cxx:1799
 TRootSniffer.cxx:1800
 TRootSniffer.cxx:1801
 TRootSniffer.cxx:1802
 TRootSniffer.cxx:1803
 TRootSniffer.cxx:1804
 TRootSniffer.cxx:1805
 TRootSniffer.cxx:1806
 TRootSniffer.cxx:1807
 TRootSniffer.cxx:1808
 TRootSniffer.cxx:1809
 TRootSniffer.cxx:1810
 TRootSniffer.cxx:1811
 TRootSniffer.cxx:1812
 TRootSniffer.cxx:1813
 TRootSniffer.cxx:1814
 TRootSniffer.cxx:1815
 TRootSniffer.cxx:1816
 TRootSniffer.cxx:1817
 TRootSniffer.cxx:1818
 TRootSniffer.cxx:1819
 TRootSniffer.cxx:1820
 TRootSniffer.cxx:1821
 TRootSniffer.cxx:1822
 TRootSniffer.cxx:1823
 TRootSniffer.cxx:1824
 TRootSniffer.cxx:1825
 TRootSniffer.cxx:1826
 TRootSniffer.cxx:1827
 TRootSniffer.cxx:1828
 TRootSniffer.cxx:1829
 TRootSniffer.cxx:1830
 TRootSniffer.cxx:1831
 TRootSniffer.cxx:1832
 TRootSniffer.cxx:1833
 TRootSniffer.cxx:1834
 TRootSniffer.cxx:1835
 TRootSniffer.cxx:1836
 TRootSniffer.cxx:1837
 TRootSniffer.cxx:1838
 TRootSniffer.cxx:1839
 TRootSniffer.cxx:1840
 TRootSniffer.cxx:1841
 TRootSniffer.cxx:1842
 TRootSniffer.cxx:1843
 TRootSniffer.cxx:1844
 TRootSniffer.cxx:1845
 TRootSniffer.cxx:1846
 TRootSniffer.cxx:1847
 TRootSniffer.cxx:1848
 TRootSniffer.cxx:1849
 TRootSniffer.cxx:1850
 TRootSniffer.cxx:1851
 TRootSniffer.cxx:1852
 TRootSniffer.cxx:1853
 TRootSniffer.cxx:1854
 TRootSniffer.cxx:1855
 TRootSniffer.cxx:1856
 TRootSniffer.cxx:1857
 TRootSniffer.cxx:1858
 TRootSniffer.cxx:1859
 TRootSniffer.cxx:1860
 TRootSniffer.cxx:1861
 TRootSniffer.cxx:1862
 TRootSniffer.cxx:1863
 TRootSniffer.cxx:1864
 TRootSniffer.cxx:1865
 TRootSniffer.cxx:1866
 TRootSniffer.cxx:1867
 TRootSniffer.cxx:1868
 TRootSniffer.cxx:1869
 TRootSniffer.cxx:1870
 TRootSniffer.cxx:1871
 TRootSniffer.cxx:1872
 TRootSniffer.cxx:1873
 TRootSniffer.cxx:1874
 TRootSniffer.cxx:1875
 TRootSniffer.cxx:1876
 TRootSniffer.cxx:1877
 TRootSniffer.cxx:1878
 TRootSniffer.cxx:1879
 TRootSniffer.cxx:1880
 TRootSniffer.cxx:1881
 TRootSniffer.cxx:1882
 TRootSniffer.cxx:1883
 TRootSniffer.cxx:1884
 TRootSniffer.cxx:1885
 TRootSniffer.cxx:1886
 TRootSniffer.cxx:1887
 TRootSniffer.cxx:1888
 TRootSniffer.cxx:1889
 TRootSniffer.cxx:1890
 TRootSniffer.cxx:1891
 TRootSniffer.cxx:1892
 TRootSniffer.cxx:1893
 TRootSniffer.cxx:1894
 TRootSniffer.cxx:1895
 TRootSniffer.cxx:1896
 TRootSniffer.cxx:1897
 TRootSniffer.cxx:1898
 TRootSniffer.cxx:1899
 TRootSniffer.cxx:1900
 TRootSniffer.cxx:1901
 TRootSniffer.cxx:1902
 TRootSniffer.cxx:1903
 TRootSniffer.cxx:1904
 TRootSniffer.cxx:1905
 TRootSniffer.cxx:1906
 TRootSniffer.cxx:1907
 TRootSniffer.cxx:1908
 TRootSniffer.cxx:1909
 TRootSniffer.cxx:1910
 TRootSniffer.cxx:1911
 TRootSniffer.cxx:1912
 TRootSniffer.cxx:1913
 TRootSniffer.cxx:1914
 TRootSniffer.cxx:1915
 TRootSniffer.cxx:1916
 TRootSniffer.cxx:1917
 TRootSniffer.cxx:1918
 TRootSniffer.cxx:1919
 TRootSniffer.cxx:1920
 TRootSniffer.cxx:1921
 TRootSniffer.cxx:1922
 TRootSniffer.cxx:1923
 TRootSniffer.cxx:1924
 TRootSniffer.cxx:1925
 TRootSniffer.cxx:1926
 TRootSniffer.cxx:1927
 TRootSniffer.cxx:1928
 TRootSniffer.cxx:1929
 TRootSniffer.cxx:1930
 TRootSniffer.cxx:1931
 TRootSniffer.cxx:1932
 TRootSniffer.cxx:1933
 TRootSniffer.cxx:1934
 TRootSniffer.cxx:1935
 TRootSniffer.cxx:1936
 TRootSniffer.cxx:1937
 TRootSniffer.cxx:1938
 TRootSniffer.cxx:1939
 TRootSniffer.cxx:1940
 TRootSniffer.cxx:1941
 TRootSniffer.cxx:1942
 TRootSniffer.cxx:1943
 TRootSniffer.cxx:1944
 TRootSniffer.cxx:1945
 TRootSniffer.cxx:1946
 TRootSniffer.cxx:1947
 TRootSniffer.cxx:1948
 TRootSniffer.cxx:1949
 TRootSniffer.cxx:1950
 TRootSniffer.cxx:1951
 TRootSniffer.cxx:1952
 TRootSniffer.cxx:1953
 TRootSniffer.cxx:1954
 TRootSniffer.cxx:1955
 TRootSniffer.cxx:1956
 TRootSniffer.cxx:1957
 TRootSniffer.cxx:1958
 TRootSniffer.cxx:1959
 TRootSniffer.cxx:1960
 TRootSniffer.cxx:1961
 TRootSniffer.cxx:1962
 TRootSniffer.cxx:1963
 TRootSniffer.cxx:1964
 TRootSniffer.cxx:1965
 TRootSniffer.cxx:1966
 TRootSniffer.cxx:1967
 TRootSniffer.cxx:1968
 TRootSniffer.cxx:1969
 TRootSniffer.cxx:1970
 TRootSniffer.cxx:1971
 TRootSniffer.cxx:1972
 TRootSniffer.cxx:1973
 TRootSniffer.cxx:1974
 TRootSniffer.cxx:1975
 TRootSniffer.cxx:1976
 TRootSniffer.cxx:1977
 TRootSniffer.cxx:1978
 TRootSniffer.cxx:1979
 TRootSniffer.cxx:1980
 TRootSniffer.cxx:1981
 TRootSniffer.cxx:1982
 TRootSniffer.cxx:1983
 TRootSniffer.cxx:1984
 TRootSniffer.cxx:1985
 TRootSniffer.cxx:1986
 TRootSniffer.cxx:1987
 TRootSniffer.cxx:1988
 TRootSniffer.cxx:1989
 TRootSniffer.cxx:1990
 TRootSniffer.cxx:1991