// $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 "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 "TDataMember.h"
#include "TDataType.h"
#include "TBaseClass.h"
#include "TObjString.h"
#include "TUrl.h"
#include "TImage.h"

#include "TRootSnifferStore.h"

#include <stdlib.h>

#pragma pack(push, 4)


// binary header of data, delivered by the sniffer
struct BinDataHeader {
   UInt_t typ;              ///< type of the binary header (1 for the moment)
   UInt_t version;          ///< version of data in binary data
   UInt_t master_version;   ///< version of master object for that binary data
   UInt_t zipped;           ///< length of unzipped data
   UInt_t payload;          ///< length of payload (not including header)

   void reset()
   {
      typ = 1;
      version = 0;
      master_version = 0;
      zipped = 0;
      payload = 0;
   }

   /** \brief returns true if content of buffer is zipped */
   bool is_zipped() const
   {
      return (zipped > 0) && (payload > 0);
   }

   /** \brief returns pointer on raw data (just after header) */
   void *rawdata() const
   {
      return (char *) this + sizeof(BinDataHeader);
   }
};

#pragma pack(pop)



extern "C" void R__zipMultipleAlgorithm(int cxlevel, int *srcsize, char *src,
                                        int *tgtsize, char *tgt, int *irep,
                                        int compressionAlgorithm);

const char *dabc_prop_kind = "dabc:kind";
const char *dabc_prop_masteritem = "dabc:master";
const char *dabc_prop_more = "dabc:more";
const char *dabc_prop_realname = "dabc:realname"; // real object name
const char *dabc_prop_itemname = "dabc:itemname"; // item name in dabc hierarchy

Long_t gExcludeProperty = kIsStatic | kIsEnum | kIsUnion;

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

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

//______________________________________________________________________________
TRootSnifferScanRec::TRootSnifferScanRec() :
   parent(0),
   mask(0),
   searchpath(0),
   lvl(0),
   fItemsNames(),
   store(0),
   has_more(kFALSE),
   started_node(),
   num_fields(0),
   num_childs(0)
{
   // constructor

   fItemsNames.SetOwner(kTRUE);
}

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

   CloseNode();
}

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

   if (CanSetFields()) store->SetField(lvl, name, value, num_fields);
   num_fields++;
}

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

   if (CanSetFields()) store->BeforeNextChild(lvl, num_childs, num_fields);
   num_childs++;
}

//______________________________________________________________________________
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 = nnn.find_last_of("/");
   if (pos != std::string::npos) nnn = nnn.substr(pos + 1);
   if (nnn.empty()) nnn = "item";

   // replace all special symbols which can make problem in http (not in xml)
   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::CreateNode(const char *_node_name, const char *_obj_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 "dabc:itemname" field
   // Optionally, object name can be recorded as "dabc:realname" field

   if (!CanSetFields()) return;

   started_node = _node_name;
   TString real_item_name;

   // this is for XML
   if (started_node.First("[]&<>-\"\' ") != kNPOS) {
      real_item_name = started_node;
      MakeItemName("extra_item", started_node); // we generate abstract item just to be safe with syntax
   }

   if (parent) parent->BeforeNextChild();

   if (store) store->CreateNode(lvl, started_node.Data());

   if (real_item_name.Length() > 0)
      SetField(dabc_prop_itemname, real_item_name.Data());

   if (_obj_name && (started_node != _obj_name))
      SetField(dabc_prop_realname, _obj_name);
}

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

   if (store && !started_node.IsNull()) {
      store->CloseNode(lvl, started_node.Data(), num_childs);
      started_node = "";
   }
}

//______________________________________________________________________________
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())  return;

   SetField(dabc_prop_kind, TString::Format("ROOT.%s", cl->GetName()));

   if (TRootSniffer::IsDrawableClass(cl)) {
      // only drawable class can be fetched from the server
      TString master;
      Int_t depth = Depth();
      for (Int_t n = 1; n < depth; n++) master.Append("../");
      master.Append("StreamerInfo");
      SetField(dabc_prop_masteritem, master.Data());
   }
}

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

   if (store == 0)
      return kFALSE;

   if ((mask & mask_Search) && store->GetResPtr())
      return kTRUE;

   if ((mask & mask_CheckChld) && store->GetResPtr() &&
         (store->GetResNumChilds() >= 0))
      return kTRUE;

   return kFALSE;
}

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

   if (Done()) return kTRUE;

   // only when doing search, result will be propagated
   if ((mask & (mask_Search | mask_CheckChld)) == 0) return kFALSE;

   //DOUT0("Set RESULT obj = %p search path = %s", obj, searchpath ? searchpath : "-null-");

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

   if (store == 0) return kFALSE;

   store->SetResult(obj, cl, member, chlds);

   return Done();
}

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

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

   return cnt;
}

//______________________________________________________________________________
Int_t TRootSnifferScanRec::ExtraFolderLevel()
{
   // return level depth till folder, marked with extra flag
   // Objects in such folder can be 'expanded' -
   // one can get access to all class members
   // If no extra folder found, -1 is returned

   TRootSnifferScanRec *rec = this;
   Int_t cnt = 0;
   while (rec) {
      if (rec->mask & mask_ExtraFolder) return cnt;
      rec = rec->parent;
      cnt++;
   }

   return -1;
}

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

   if (mask & (mask_Expand | mask_Search | mask_CheckChld)) return kTRUE;

   if (!has_more) return kFALSE;

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

   return kFALSE;
}

//______________________________________________________________________________
Bool_t TRootSnifferScanRec::GoInside(TRootSnifferScanRec &super, TObject *obj,
                                     const char *obj_name)
{
   // 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;

   TString obj_item_name;

   super.MakeItemName(obj_name, obj_item_name);

   lvl = super.lvl;
   store = super.store;
   searchpath = super.searchpath;
   mask = super.mask & mask_Actions;
   parent = &super;

   if (mask & mask_Scan) {
      // only when doing scan, increment lvl, used for text formatting
      lvl++;
   } else {
      if (searchpath == 0) return kFALSE;

      if (strncmp(searchpath, obj_item_name.Data(), obj_item_name.Length()) != 0)
         return kFALSE;

      const char *separ = searchpath + obj_item_name.Length();

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

      if (*separ == 0) {
         searchpath = 0;
         if (mask & mask_Expand) mask = mask_Scan;
      } else {
         if (!isslash) return kFALSE;
         searchpath = separ;
      }
   }

   CreateNode(obj_item_name.Data(), obj ? obj->GetName() : 0);

   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),
   fSinfoSize(0),
   fCompression(5)
{
   // constructor
}

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

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

//______________________________________________________________________________
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;

   //DOUT0("SCAN CLASS %s mask %u", cl->GetName(), rec.mask);

   // 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;

//    this code was used when each base class creates its own sub level

//      TRootSnifferScanRec chld;
//      if (chld.GoInside(rec, baseclass)) {
//         ScanObjectMemebers(chld, bclass, ptr, cloffset + baseclass->GetDelta());
//         if (chld.Done()) break;
//      }
   }

   //DOUT0("SCAN MEMBERS %s %u mask %u done %s", cl->GetName(),
   //      cl->GetListOfDataMembers()->GetSize(), chld.mask, DBOOL(chld.Done()));

   // 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() & gExcludeProperty)) continue;

      char *member_ptr = ptr + cloffset + member->GetOffset();
      if (member->IsaPointer()) member_ptr = *((char **) member_ptr);

      TRootSnifferScanRec chld;

      if (chld.GoInside(rec, member)) {
         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(dabc_prop_more, "true");
            chld.has_more = kTRUE;
         }

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

         if (IsDrawableClass(mcl))
            chld.SetRootClass(mcl);

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

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

//______________________________________________________________________________
void TRootSniffer::ScanObject(TRootSnifferScanRec &rec, TObject *obj)
{
   // scan object content
   // if object is known collection class (like TFolder),
   // collection content will be scanned as well

   if (obj == 0) return;

   //if (rec.mask & mask_Expand)
   //   printf("EXPAND OBJECT %s can expand %s mask %u\n", obj->GetName(),
   //          DBOOL(rec.CanExpandItem()), rec.mask);

   // mark object as expandable for direct child of extra folder
   // or when non drawable object is scanned

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

   int isextra = rec.ExtraFolderLevel();

   if ((isextra == 1) || ((isextra > 1) && !IsDrawableClass(obj->IsA()))) {
      rec.SetField(dabc_prop_more, "true");
      rec.has_more = kTRUE;
   }

   rec.SetRootClass(obj->IsA());

   if (obj->InheritsFrom(TFolder::Class())) {
      // starting from special folder, we automatically scan members

      TFolder *fold = (TFolder *) obj;
      if (fold->TestBit(BIT(19))) rec.mask = rec.mask | mask_ExtraFolder;

      ScanCollection(rec, fold->GetListOfFolders());
   } else if (obj->InheritsFrom(TDirectory::Class())) {
      ScanCollection(rec, ((TDirectory *) obj)->GetList());
   } else if (obj->InheritsFrom(TTree::Class())) {
      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);
   }

   // here we should know how many childs are accumulated
   rec.SetResult(obj, obj->IsA(), 0, rec.num_childs);
}

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

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

   TRootSnifferScanRec folderrec;
   if (foldername) {
      if (!folderrec.GoInside(rec, 0, foldername)) return;
      if (extra) folderrec.mask = folderrec.mask | mask_ExtraFolder;
   }

   {
      TRootSnifferScanRec &master = foldername ? folderrec : rec;

      TIter iter(lst);
      TObject *obj(0);

      while ((obj = iter()) != 0) {
         TRootSnifferScanRec chld;
         if (chld.GoInside(master, obj)) {
            ScanObject(chld, obj);
            if (chld.Done()) break;
         }
      }
   }
}

//______________________________________________________________________________
void TRootSniffer::ScanRoot(TRootSnifferScanRec &rec)
{
   // scan complete ROOT objects hierarchy
   // For the moment it includes objects in gROOT directory and lise 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(dabc_prop_kind, "ROOT.Session");

   {
      TRootSnifferScanRec chld;
      if (chld.GoInside(rec, 0, "StreamerInfo"))
         chld.SetField(dabc_prop_kind, "ROOT.TList");
   }

   TFolder *topf = dynamic_cast<TFolder *>(gROOT->FindObject(TString::Format("//root/%s", fObjectsPath.Data())));

   ScanCollection(rec, gROOT->GetList());

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

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

   ScanCollection(rec, topf ? topf->GetListOfFolders() : 0, "Objects");
}

//______________________________________________________________________________
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;
}

//______________________________________________________________________________
Bool_t TRootSniffer::IsBrowsableClass(TClass *cl)
{
   // return true if object can be browsed?

   if (cl == 0) return kFALSE;

   if (cl->InheritsFrom(TTree::Class())) return kTRUE;
   if (cl->InheritsFrom(TBranch::Class())) return kTRUE;
   if (cl->InheritsFrom(TLeaf::Class())) return kTRUE;
   if (cl->InheritsFrom(TFolder::Class())) return kTRUE;

   return kFALSE;
}

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

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

   // if path non-empty, we should find item first and than start scanning
   rec.mask = rec.searchpath == 0 ? mask_Scan : mask_Expand;

   rec.store = 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)

   TRootSnifferStore store;

   TRootSnifferScanRec rec;
   rec.searchpath = path;
   rec.mask = (chld != 0) ? mask_CheckChld : mask_Search;
   if (*rec.searchpath == '/') rec.searchpath++;
   rec.store = &store;

   ScanRoot(rec);

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

   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 fSinfoSize;
}

//______________________________________________________________________________
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 TBuffer 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();

   l = fMemFile->GetStreamerInfoList();
   // l->Print("*");
   fSinfoSize = l->GetSize();
   delete l;

   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");

   if (IsStreamerInfoItem(path)) {

      CreateMemFile();

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

      fMemFile->WriteStreamerInfo();
      TList *l = fMemFile->GetStreamerInfoList();
      fSinfoSize = l->GetSize();

      res = TBufferJSON::ConvertToJSON(l, compact);

      delete l;
      gDirectory = olddir;
      gFile = oldfile;
   } else {

      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::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++;

   if (IsStreamerInfoItem(path)) {

      CreateMemFile();

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

      fMemFile->WriteStreamerInfo();
      TList *l = fMemFile->GetStreamerInfoList();
      fSinfoSize = l->GetSize();

      res = TBufferXML::ConvertToXML(l);

      delete l;
      gDirectory = olddir;
      gFile = oldfile;
   } else {

      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;
}

//______________________________________________________________________________
Bool_t TRootSniffer::IsStreamerInfoItem(const char *itemname)
{
   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 *, void *&ptr,
                                   Long_t &length)
{
   // produce binary data for specified item
   // It is 20 bytes for header plus compressed content of TBuffer

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

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

   TBufferFile *sbuf = 0;

//   Info("ProduceBinary","Request %s", path);

   Bool_t istreamerinfo = IsStreamerInfoItem(path);

   if (istreamerinfo) {

      CreateMemFile();

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

      fMemFile->WriteStreamerInfo();
      TList *l = fMemFile->GetStreamerInfoList();
      //l->Print("*");

      fSinfoSize = l->GetSize();

      // TODO: one could reuse memory from dabc::MemoryPool here
      //       now keep as it is and copy data at least once
      sbuf = new TBufferFile(TBuffer::kWrite, 100000);
      sbuf->SetParent(fMemFile);
      sbuf->MapObject(l);
      l->Streamer(*sbuf);
      delete l;

      gDirectory = olddir;
      gFile = oldfile;
   } else {

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

      CreateMemFile();

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

      TList *l1 = fMemFile->GetStreamerInfoList();

      if (obj_cl->GetBaseClassOffset(TObject::Class()) == 0) {
         TObject *obj = (TObject *) obj_ptr;

         sbuf = new TBufferFile(TBuffer::kWrite, 100000);
         sbuf->SetParent(fMemFile);
         sbuf->MapObject(obj);
         obj->Streamer(*sbuf);
      } else {
         Info("ProduceBinary", "Non TObject class not yet supported");
         delete sbuf;
         sbuf = 0;
      }

      Bool_t believe_not_changed = kFALSE;

      if ((fMemFile->GetClassIndex() == 0) ||
            (fMemFile->GetClassIndex()->fArray[0] == 0)) {
         believe_not_changed = true;
      }

      fMemFile->WriteStreamerInfo();
      TList *l2 = fMemFile->GetStreamerInfoList();

      if (believe_not_changed && (l1->GetSize() != l2->GetSize())) {
         Error("ProduceBinary",
               "StreamerInfo changed when we were expecting no changes!!!!!!!!!");
         delete sbuf;
         sbuf = 0;
      }

      fSinfoSize = l2->GetSize();

      delete l1;
      delete l2;

      gDirectory = olddir;
      gFile = oldfile;
   }

   if (!CreateBindData(sbuf, ptr, length)) return kFALSE;

   BinDataHeader *hdr = (BinDataHeader *) ptr;

   if (istreamerinfo) {
      hdr->version = fSinfoSize;
      hdr->master_version = 0;
   } else {
      hdr->version = 0;
      hdr->master_version = fSinfoSize;
   }

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootSniffer::CreateBindData(TBufferFile *sbuf, void *&ptr,
                                    Long_t &length)
{
   // create binary data from TBufferFile
   // If compression enabled, data also will be zipped

   if (sbuf == 0) return kFALSE;

   Bool_t with_zip = fCompression > 0;

   const Int_t kMAXBUF = 0xffffff;
   Int_t noutot = 0;
   Int_t fObjlen = sbuf->Length();
   Int_t nbuffers = 1 + (fObjlen - 1) / kMAXBUF;
   Int_t buflen = TMath::Max(512, fObjlen + 9 * nbuffers + 28);
   if (buflen < fObjlen) buflen = fObjlen;

   ptr = malloc(sizeof(BinDataHeader) + buflen);

   if (ptr == 0) {
      Error("CreateBinData", "Cannot create buffer of size %u",
            (unsigned)(sizeof(BinDataHeader) + buflen));
      delete sbuf;
      return kFALSE;
   }

   BinDataHeader *hdr = (BinDataHeader *) ptr;
   hdr->reset();

   char *fBuffer = ((char *) ptr) + sizeof(BinDataHeader);

   if (with_zip) {
      Int_t cxAlgorithm = 0;

      char *objbuf = sbuf->Buffer();
      char *bufcur = fBuffer; // start writing from beginning

      Int_t nzip   = 0;
      Int_t bufmax = 0;
      Int_t nout = 0;

      for (Int_t i = 0; i < nbuffers; ++i) {
         if (i == nbuffers - 1)
            bufmax = fObjlen - nzip;
         else
            bufmax = kMAXBUF;
         R__zipMultipleAlgorithm(fCompression, &bufmax, objbuf, &bufmax,
                                 bufcur, &nout, cxAlgorithm);
         if (nout == 0 || nout >= fObjlen) {
            // this happens when the buffer cannot be compressed
            Error("CreateBindData", "Fail to zip buffer");
            noutot = 0;
            with_zip = false;
            break;
         }
         bufcur += nout;
         noutot += nout;
         objbuf += kMAXBUF;
         nzip   += kMAXBUF;
      }
   }

   if (with_zip) {
      hdr->zipped = (UInt_t) fObjlen;
      hdr->payload = (UInt_t) noutot;
   } else {
      memcpy(fBuffer, sbuf->Buffer(), fObjlen);
      hdr->zipped = 0;
      hdr->payload = (UInt_t) fObjlen;
   }

   length = sizeof(BinDataHeader) + hdr->payload;

   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)
{
   // method to produce different kind of binary data
   // 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

   if ((file == 0) || (*file == 0) || (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, "root.xml") == 0) {
      TString res;
      if (!ProduceXml(path, options, res)) return kFALSE;
      length = res.Length();
      ptr = malloc(length);
      memcpy(ptr, res.Data(), length);
      return kTRUE;
   }

   if ((strcmp(file, "root.json") == 0) || (strcmp(file, "get.json") == 0)) {
      TString res;
      if (!ProduceJson(path, options, res)) return kFALSE;
      length = res.Length();
      ptr = malloc(length);
      memcpy(ptr, res.Data(), length);
      return kTRUE;
   }

   return kFALSE;
}

//______________________________________________________________________________
Bool_t TRootSniffer::RegisterObject(const char *subfolder, TObject *obj)
{
   // register object in subfolder structure
   // subfolder paramerer 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");
   //
   // Objects, registered in "extra" sub-folder, can be explored.
   // Typically one used "extra" sub-folder to register event structures to
   // be able expand it later in web-browser:
   //
   // TEvent* ev = new TEvent;
   // sniff->RegisterObject("extra", ev);


   if (obj == 0) return kFALSE;

   TFolder *topf = gROOT->GetRootFolder();

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

   TFolder *topdabcfold = dynamic_cast<TFolder *>(topf->FindObject(fObjectsPath.Data()));
   if (topdabcfold == 0) {
      topdabcfold = topf->AddFolder(fObjectsPath.Data(), "Top online folder");
      topdabcfold->SetOwner(kFALSE);
   }

   TFolder *dabcfold = topdabcfold;

   if ((subfolder != 0) && (strlen(subfolder) > 0)) {

      TObjArray *arr = TString(subfolder).Tokenize("/");
      for (Int_t i = 0; i <= (arr ? arr->GetLast() : -1); i++) {

         const char *subname = arr->At(i)->GetName();
         if (strlen(subname) == 0) continue;

         TFolder *fold = dynamic_cast<TFolder *>(dabcfold->FindObject(subname));
         if (fold == 0) {
            fold = dabcfold->AddFolder(subname, "sub-folder");
            fold->SetOwner(kFALSE);

            if ((dabcfold == topdabcfold) && (strcmp(subname, "extra") == 0))
               fold->SetBit(BIT(19), kTRUE);
         }
         dabcfold = fold;
      }

   }

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

   dabcfold->Add(obj);

   // register folder for cleanup
   if (!gROOT->GetListOfCleanups()->FindObject(dabcfold))
      gROOT->GetListOfCleanups()->Add(dabcfold);

   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 = gROOT->GetRootFolder();

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

   TFolder *dabcfold = dynamic_cast<TFolder *>(topf->FindObject(fObjectsPath.Data()));

   if (dabcfold) dabcfold->RecursiveRemove(obj);

   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