diff --git a/base/src/ManualBase4.cxx b/base/src/ManualBase4.cxx deleted file mode 100644 index a7f7585986c6c2423ecb3f12b48523ada4a692c6..0000000000000000000000000000000000000000 --- a/base/src/ManualBase4.cxx +++ /dev/null @@ -1,313 +0,0 @@ -// -// File generated by utils\src\rootcint_tmp.exe at Wed Jan 12 09:24:21 2005. -// Do NOT change. Changes will be lost next time file is generated -// - -#include "RConfig.h" -#if !defined(R__ACCESS_IN_SYMBOL) -//Break the privacy of classes -- Disabled for the moment -#define private public -#define protected public -#endif - -// Since CINT ignores the std namespace, we need to do so in this file. -namespace std {} using namespace std; - -#include "ManualBase4.h" -#include "TClass.h" -#include "TBuffer.h" -#include "TStreamerInfo.h" -#include "TMemberInspector.h" -#include "TError.h" - -#ifndef G__ROOT -#define G__ROOT -#endif - -#include "RtypesImp.h" - -namespace ROOT { - namespace Shadow { - } // Of namespace ROOT::Shadow -} // Of namespace ROOT - -/******************************************************** -* base/src/ManualBase4.cxx -* CAUTION: DON'T CHANGE THIS FILE. THIS FILE IS AUTOMATICALLY GENERATED -* FROM HEADER FILES LISTED IN G__setup_cpp_environmentXXX(). -* CHANGE THOSE HEADER FILES AND REGENERATE THIS FILE. -********************************************************/ - -#ifdef G__MEMTEST -#undef malloc -#undef free -#endif - -extern "C" void G__cpp_reset_tagtableManualBase4(); - -extern "C" void G__set_cpp_environmentManualBase4() { - G__add_compiledheader("base/inc/TROOT.h"); - G__add_compiledheader("base/inc/TMemberInspector.h"); - G__add_compiledheader("TDirectory.h"); - G__cpp_reset_tagtableManualBase4(); -} -class G__basedIsrcdIManualBase4dOcxx_tag {}; - -void* operator new(size_t size,G__basedIsrcdIManualBase4dOcxx_tag* p) { - if(p && G__PVOID!=G__getgvp()) return((void*)p); -#ifndef G__ROOT - return(malloc(size)); -#else - return(::operator new(size)); -#endif -} - -/* dummy, for exception */ -#ifdef G__EH_DUMMY_DELETE -void operator delete(void *p,G__basedIsrcdIManualBase4dOcxx_tag* x) { - if((long)p==G__getgvp() && G__PVOID!=G__getgvp()) return; -#ifndef G__ROOT - free(p); -#else - ::operator delete(p); -#endif -} -#endif - -static void G__operator_delete(void *p) { - if((long)p==G__getgvp() && G__PVOID!=G__getgvp()) return; -#ifndef G__ROOT - free(p); -#else - ::operator delete(p); -#endif -} - -void G__DELDMY_basedIsrcdIManualBase4dOcxx() { G__operator_delete(0); } - -extern "C" int G__cpp_dllrevManualBase4() { return(30051515); } - -/********************************************************* -* Member function Interface Method -*********************************************************/ - -/* TDirectory */ -#include "ManualBase4Body.h" - -/* Setting up global function */ - -/********************************************************* -* Member function Stub -*********************************************************/ - -/********************************************************* -* Global function Stub -*********************************************************/ - -/********************************************************* -* Get size of pointer to member function -*********************************************************/ -class G__Sizep2memfuncManualBase4 { - public: - G__Sizep2memfuncManualBase4() {p=&G__Sizep2memfuncManualBase4::sizep2memfunc;} - size_t sizep2memfunc() { return(sizeof(p)); } - private: - size_t (G__Sizep2memfuncManualBase4::*p)(); -}; - -size_t G__get_sizep2memfuncManualBase4() -{ - G__Sizep2memfuncManualBase4 a; - G__setsizep2memfunc((int)a.sizep2memfunc()); - return((size_t)a.sizep2memfunc()); -} - - -/********************************************************* -* virtual base class offset calculation interface -*********************************************************/ - - /* Setting up class inheritance */ - -/********************************************************* -* Inheritance information setup/ -*********************************************************/ -extern "C" void G__cpp_setup_inheritanceManualBase4() { - - /* Setting up class inheritance */ -} - -/********************************************************* -* typedef information setup/ -*********************************************************/ -extern "C" void G__cpp_setup_typetableManualBase4() { - - /* Setting up typedef entry */ - G__search_typename2("Int_t",105,-1,0, --1); - G__setnewtype(-1,"Signed integer 4 bytes (int)",0); - G__search_typename2("Option_t",99,-1,256, --1); - G__setnewtype(-1,"Option string (const char)",0); - G__search_typename2("vector<TStreamerInfo*>",117,G__get_linked_tagnum(&G__ManualBase4LN_vectorlETStreamerInfomUcOallocatorlETStreamerInfomUgRsPgR),0,-1); - G__setnewtype(-1,"// @(#)root/base:$Name: $:$Id: ManualBase4.cxx,v 1.4 2005/01/12 17:59:52 brun Exp $",0); - G__search_typename2("_Ranit<TStreamerInfo*,difference_type,const_pointer,const_reference>",117,G__get_linked_tagnum(&G__ManualBase4LN__RanitlETStreamerInfomUcOlongcOTStreamerInfomUmUcOTStreamerInfomUaNgR),0,G__get_linked_tagnum(&G__ManualBase4LN_vectorlETStreamerInfomUcOallocatorlETStreamerInfomUgRsPgR)); - G__setnewtype(-1,"// @(#)root/base:$Name: $:$Id: ManualBase4.cxx,v 1.4 2005/01/12 17:59:52 brun Exp $",0); - G__search_typename2("reverse_iterator<iterator>",117,G__get_linked_tagnum(&G__ManualBase4LN_reverse_iteratorlEvectorlETStreamerInfomUcOallocatorlETStreamerInfomUgRsPgRcLcLiteratorgR),0,G__get_linked_tagnum(&G__ManualBase4LN_vectorlETStreamerInfomUcOallocatorlETStreamerInfomUgRsPgR)); - G__setnewtype(-1,"// @(#)root/base:$Name: $:$Id: ManualBase4.cxx,v 1.4 2005/01/12 17:59:52 brun Exp $",0); - G__search_typename2("iterator<iterator_traits<vector<TStreamerInfo*,allocator<TStreamerInfo*> >::iterator>::iterator_category,iterator_traits<vector<TStreamerInfo*,allocator<TStreamerInfo*> >::iterator>::value_type,iterator_traits<vector<TStreamerInfo*,allocator<TStreamerInfo*> >::iterator>::difference_type,iterator_traits<vector<TStreamerInfo*,allocator<TStreamerInfo*> >::iterator>::pointer,iterator_traits<vector<TStreamerInfo*,allocator<TStreamerInfo*> >::iterator>::reference>",117,G__get_linked_tagnum(&G__ManualBase4LN_iteratorlErandom_access_iterator_tagcOTStreamerInfomUcOvectorlETStreamerInfomUcOallocatorlETStreamerInfomUgRsPgRcLcLiteratorcLcLdifference_typecOTStreamerInfomUmUcOTStreamerInfomUaNgR),0,-1); - G__setnewtype(-1,"// @(#)root/base:$Name: $:$Id: ManualBase4.cxx,v 1.4 2005/01/12 17:59:52 brun Exp $",0); - G__search_typename2("iterator<random_access_iterator_tag,TStreamerInfo*>",117,G__get_linked_tagnum(&G__ManualBase4LN_iteratorlErandom_access_iterator_tagcOTStreamerInfomUcOvectorlETStreamerInfomUcOallocatorlETStreamerInfomUgRsPgRcLcLiteratorcLcLdifference_typecOTStreamerInfomUmUcOTStreamerInfomUaNgR),0,-1); - G__setnewtype(-1,"// @(#)root/base:$Name: $:$Id: ManualBase4.cxx,v 1.4 2005/01/12 17:59:52 brun Exp $",0); - G__search_typename2("iterator<random_access_iterator_tag,TStreamerInfo*>vector<TStreamerInfo*,allocator<TStreamerInfo*> >::iterator::difference_type>",117,G__get_linked_tagnum(&G__ManualBase4LN_iteratorlErandom_access_iterator_tagcOTStreamerInfomUcOvectorlETStreamerInfomUcOallocatorlETStreamerInfomUgRsPgRcLcLiteratorcLcLdifference_typecOTStreamerInfomUmUcOTStreamerInfomUaNgR),0,-1); - G__setnewtype(-1,"// @(#)root/base:$Name: $:$Id: ManualBase4.cxx,v 1.4 2005/01/12 17:59:52 brun Exp $",0); - G__search_typename2("iterator<random_access_iterator_tag,TStreamerInfo*>vector<TStreamerInfo*,allocator<TStreamerInfo*> >::iterator::difference_type>TStreamerInfo**>",117,G__get_linked_tagnum(&G__ManualBase4LN_iteratorlErandom_access_iterator_tagcOTStreamerInfomUcOvectorlETStreamerInfomUcOallocatorlETStreamerInfomUgRsPgRcLcLiteratorcLcLdifference_typecOTStreamerInfomUmUcOTStreamerInfomUaNgR),0,-1); - G__setnewtype(-1,"// @(#)root/base:$Name: $:$Id: ManualBase4.cxx,v 1.4 2005/01/12 17:59:52 brun Exp $",0); - G__search_typename2("reverse_iterator<const_iterator>",117,G__get_linked_tagnum(&G__ManualBase4LN_reverse_iteratorlEvectorlETStreamerInfomUcOallocatorlETStreamerInfomUgRsPgRcLcLconst_iteratorgR),0,G__get_linked_tagnum(&G__ManualBase4LN_vectorlETStreamerInfomUcOallocatorlETStreamerInfomUgRsPgR)); - G__setnewtype(-1,"// @(#)root/base:$Name: $:$Id: ManualBase4.cxx,v 1.4 2005/01/12 17:59:52 brun Exp $",0); - G__search_typename2("iterator<iterator_traits<vector<TStreamerInfo*,allocator<TStreamerInfo*> >::const_iterator>::iterator_category,iterator_traits<vector<TStreamerInfo*,allocator<TStreamerInfo*> >::const_iterator>::value_type,iterator_traits<vector<TStreamerInfo*,allocator<TStreamerInfo*> >::const_iterator>::difference_type,iterator_traits<vector<TStreamerInfo*,allocator<TStreamerInfo*> >::const_iterator>::pointer,iterator_traits<vector<TStreamerInfo*,allocator<TStreamerInfo*> >::const_iterator>::reference>",117,G__get_linked_tagnum(&G__ManualBase4LN_iteratorlErandom_access_iterator_tagcOTStreamerInfomUcOlongcOTStreamerInfomUmUcOTStreamerInfomUaNgR),0,-1); - G__setnewtype(-1,"// @(#)root/base:$Name: $:$Id: ManualBase4.cxx,v 1.4 2005/01/12 17:59:52 brun Exp $",0); - G__search_typename2("iterator<random_access_iterator_tag,TStreamerInfo*>long>",117,G__get_linked_tagnum(&G__ManualBase4LN_iteratorlErandom_access_iterator_tagcOTStreamerInfomUcOlongcOTStreamerInfomUmUcOTStreamerInfomUaNgR),0,-1); - G__setnewtype(-1,"// @(#)root/base:$Name: $:$Id: ManualBase4.cxx,v 1.4 2005/01/12 17:59:52 brun Exp $",0); - G__search_typename2("iterator<random_access_iterator_tag,TStreamerInfo*>long>TStreamerInfo**>",117,G__get_linked_tagnum(&G__ManualBase4LN_iteratorlErandom_access_iterator_tagcOTStreamerInfomUcOlongcOTStreamerInfomUmUcOTStreamerInfomUaNgR),0,-1); - G__setnewtype(-1,"// @(#)root/base:$Name: $:$Id: ManualBase4.cxx,v 1.4 2005/01/12 17:59:52 brun Exp $",0); -} - -/********************************************************* -* Data Member information setup/ -*********************************************************/ - - /* Setting up class,struct,union tag member variable */ -extern "C" void G__cpp_setup_memvarManualBase4() { -} -/*********************************************************** -************************************************************ -************************************************************ -************************************************************ -************************************************************ -************************************************************ -************************************************************ -***********************************************************/ - -/********************************************************* -* Member function information setup for each class -*********************************************************/ -static void G__setup_memfuncTDirectory(void) { - /* TDirectory */ - G__tag_memfunc_setup(G__get_linked_tagnum(&G__ManualBase4LN_TDirectory)); - G__memfunc_setup("WriteObject",1122,G__ManualBase4_134_5_8,105,-1,G__defined_typename("Int_t"),0,3,1,1,0, -"Y - - 10 - obj C - - 10 - name " -"C - 'Option_t' 10 \"\" option",(char*)NULL,(void*)NULL,0); - G__memfunc_setup("GetObject",887,G__ManualBase4_134_6_8,121,-1,-1,0,2,1,1,0, -"C - - 10 - namecycle Y - - 1 - ptr",(char*)NULL,(void*)NULL,0); - G__tag_memfunc_reset(); -} - - -/********************************************************* -* Member function information setup -*********************************************************/ -extern "C" void G__cpp_setup_memfuncManualBase4() { -} - -/********************************************************* -* Global variable information setup for each class -*********************************************************/ -static void G__cpp_setup_global0() { - - /* Setting up global variables */ - G__resetplocal(); - -} - -static void G__cpp_setup_global1() { - - G__resetglobalenv(); -} -extern "C" void G__cpp_setup_globalManualBase4() { - G__cpp_setup_global0(); - G__cpp_setup_global1(); -} - -/********************************************************* -* Global function information setup for each class -*********************************************************/ -static void G__cpp_setup_func0() { - G__lastifuncposition(); - -} - -static void G__cpp_setup_func1() { -} - -static void G__cpp_setup_func2() { - - G__resetifuncposition(); -} - -extern "C" void G__cpp_setup_funcManualBase4() { - G__cpp_setup_func0(); - G__cpp_setup_func1(); - G__cpp_setup_func2(); -} - -/********************************************************* -* Class,struct,union,enum tag information setup -*********************************************************/ -/* Setup class/struct taginfo */ -G__linked_taginfo G__ManualBase4LN_vectorlETStreamerInfomUcOallocatorlETStreamerInfomUgRsPgR = { "vector<TStreamerInfo*,allocator<TStreamerInfo*> >" , 99 , -1 }; -G__linked_taginfo G__ManualBase4LN__RanitlETStreamerInfomUcOlongcOTStreamerInfomUmUcOTStreamerInfomUaNgR = { "_Ranit<TStreamerInfo*,long,TStreamerInfo**,TStreamerInfo*&>" , 115 , -1 }; -G__linked_taginfo G__ManualBase4LN_iteratorlErandom_access_iterator_tagcOTStreamerInfomUcOlongcOTStreamerInfomUmUcOTStreamerInfomUaNgR = { "iterator<random_access_iterator_tag,TStreamerInfo*,long,TStreamerInfo**,TStreamerInfo*&>" , 115 , -1 }; -G__linked_taginfo G__ManualBase4LN_reverse_iteratorlEvectorlETStreamerInfomUcOallocatorlETStreamerInfomUgRsPgRcLcLiteratorgR = { "reverse_iterator<vector<TStreamerInfo*,allocator<TStreamerInfo*> >::iterator>" , 99 , -1 }; -G__linked_taginfo G__ManualBase4LN_iteratorlErandom_access_iterator_tagcOTStreamerInfomUcOvectorlETStreamerInfomUcOallocatorlETStreamerInfomUgRsPgRcLcLiteratorcLcLdifference_typecOTStreamerInfomUmUcOTStreamerInfomUaNgR = { "iterator<random_access_iterator_tag,TStreamerInfo*,vector<TStreamerInfo*,allocator<TStreamerInfo*> >::iterator::difference_type,TStreamerInfo**,TStreamerInfo*&>" , 115 , -1 }; -G__linked_taginfo G__ManualBase4LN_reverse_iteratorlEvectorlETStreamerInfomUcOallocatorlETStreamerInfomUgRsPgRcLcLconst_iteratorgR = { "reverse_iterator<vector<TStreamerInfo*,allocator<TStreamerInfo*> >::const_iterator>" , 99 , -1 }; -G__linked_taginfo G__ManualBase4LN_TDirectory = { "TDirectory" , 99 , -1 }; - -/* Reset class/struct taginfo */ -extern "C" void G__cpp_reset_tagtableManualBase4() { - G__ManualBase4LN_vectorlETStreamerInfomUcOallocatorlETStreamerInfomUgRsPgR.tagnum = -1 ; - G__ManualBase4LN__RanitlETStreamerInfomUcOlongcOTStreamerInfomUmUcOTStreamerInfomUaNgR.tagnum = -1 ; - G__ManualBase4LN_iteratorlErandom_access_iterator_tagcOTStreamerInfomUcOlongcOTStreamerInfomUmUcOTStreamerInfomUaNgR.tagnum = -1 ; - G__ManualBase4LN_reverse_iteratorlEvectorlETStreamerInfomUcOallocatorlETStreamerInfomUgRsPgRcLcLiteratorgR.tagnum = -1 ; - G__ManualBase4LN_iteratorlErandom_access_iterator_tagcOTStreamerInfomUcOvectorlETStreamerInfomUcOallocatorlETStreamerInfomUgRsPgRcLcLiteratorcLcLdifference_typecOTStreamerInfomUmUcOTStreamerInfomUaNgR.tagnum = -1 ; - G__ManualBase4LN_reverse_iteratorlEvectorlETStreamerInfomUcOallocatorlETStreamerInfomUgRsPgRcLcLconst_iteratorgR.tagnum = -1 ; - G__ManualBase4LN_TDirectory.tagnum = -1 ; -} - - -extern "C" void G__cpp_setup_tagtableManualBase4() { - - /* Setting up class,struct,union tag entry */ - G__get_linked_tagnum(&G__ManualBase4LN_vectorlETStreamerInfomUcOallocatorlETStreamerInfomUgRsPgR); - G__get_linked_tagnum(&G__ManualBase4LN__RanitlETStreamerInfomUcOlongcOTStreamerInfomUmUcOTStreamerInfomUaNgR); - G__get_linked_tagnum(&G__ManualBase4LN_iteratorlErandom_access_iterator_tagcOTStreamerInfomUcOlongcOTStreamerInfomUmUcOTStreamerInfomUaNgR); - G__get_linked_tagnum(&G__ManualBase4LN_reverse_iteratorlEvectorlETStreamerInfomUcOallocatorlETStreamerInfomUgRsPgRcLcLiteratorgR); - G__get_linked_tagnum(&G__ManualBase4LN_iteratorlErandom_access_iterator_tagcOTStreamerInfomUcOvectorlETStreamerInfomUcOallocatorlETStreamerInfomUgRsPgRcLcLiteratorcLcLdifference_typecOTStreamerInfomUmUcOTStreamerInfomUaNgR); - G__get_linked_tagnum(&G__ManualBase4LN_reverse_iteratorlEvectorlETStreamerInfomUcOallocatorlETStreamerInfomUgRsPgRcLcLconst_iteratorgR); - G__tagtable_setup(G__get_linked_tagnum(&G__ManualBase4LN_TDirectory),sizeof(TDirectory),-1,65280,"Describe directory structure in memory",NULL,G__setup_memfuncTDirectory); -} -extern "C" void G__cpp_setupManualBase4(void) { - G__check_setup_version(30051515,"G__cpp_setupManualBase4()"); - G__set_cpp_environmentManualBase4(); - G__cpp_setup_tagtableManualBase4(); - - G__cpp_setup_inheritanceManualBase4(); - - G__cpp_setup_typetableManualBase4(); - - G__cpp_setup_memvarManualBase4(); - - G__cpp_setup_memfuncManualBase4(); - G__cpp_setup_globalManualBase4(); - G__cpp_setup_funcManualBase4(); - - if(0==G__getsizep2memfunc()) G__get_sizep2memfuncManualBase4(); - return; -} -class G__cpp_setup_initManualBase4 { - public: - G__cpp_setup_initManualBase4() { G__add_setup_func("ManualBase4",(G__incsetup)(&G__cpp_setupManualBase4)); G__call_setup_funcs(); } - ~G__cpp_setup_initManualBase4() { G__remove_setup_func("ManualBase4"); } -}; -G__cpp_setup_initManualBase4 G__cpp_setup_initializerManualBase4; - diff --git a/base/src/ManualBase4.h b/base/src/ManualBase4.h deleted file mode 100644 index df36c57056d7866816bebfceeef958ace454f126..0000000000000000000000000000000000000000 --- a/base/src/ManualBase4.h +++ /dev/null @@ -1,48 +0,0 @@ -/******************************************************************** -* base/src/ManualBase4.h -* CAUTION: DON'T CHANGE THIS FILE. THIS FILE IS AUTOMATICALLY GENERATED -* FROM HEADER FILES LISTED IN G__setup_cpp_environmentXXX(). -* CHANGE THOSE HEADER FILES AND REGENERATE THIS FILE. -********************************************************************/ -#ifdef __CINT__ -#error base/src/ManualBase4.h/C is only for compilation. Abort cint. -#endif -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <math.h> -#include <string.h> -#define G__ANSIHEADER -#define G__DICTIONARY -#include "G__ci.h" -extern "C" { -extern void G__cpp_setup_tagtableManualBase4(); -extern void G__cpp_setup_inheritanceManualBase4(); -extern void G__cpp_setup_typetableManualBase4(); -extern void G__cpp_setup_memvarManualBase4(); -extern void G__cpp_setup_globalManualBase4(); -extern void G__cpp_setup_memfuncManualBase4(); -extern void G__cpp_setup_funcManualBase4(); -extern void G__set_cpp_environmentManualBase4(); -} - - -#include "base/inc/TROOT.h" -#include "base/inc/TMemberInspector.h" -#include "TDirectory.h" -#include <algorithm> -namespace std { } -using namespace std; - -#ifndef G__MEMFUNCBODY -#endif - -extern G__linked_taginfo G__ManualBase4LN_vectorlETStreamerInfomUcOallocatorlETStreamerInfomUgRsPgR; -extern G__linked_taginfo G__ManualBase4LN__RanitlETStreamerInfomUcOlongcOTStreamerInfomUmUcOTStreamerInfomUaNgR; -extern G__linked_taginfo G__ManualBase4LN_iteratorlErandom_access_iterator_tagcOTStreamerInfomUcOlongcOTStreamerInfomUmUcOTStreamerInfomUaNgR; -extern G__linked_taginfo G__ManualBase4LN_reverse_iteratorlEvectorlETStreamerInfomUcOallocatorlETStreamerInfomUgRsPgRcLcLiteratorgR; -extern G__linked_taginfo G__ManualBase4LN_iteratorlErandom_access_iterator_tagcOTStreamerInfomUcOvectorlETStreamerInfomUcOallocatorlETStreamerInfomUgRsPgRcLcLiteratorcLcLdifference_typecOTStreamerInfomUmUcOTStreamerInfomUaNgR; -extern G__linked_taginfo G__ManualBase4LN_reverse_iteratorlEvectorlETStreamerInfomUcOallocatorlETStreamerInfomUgRsPgRcLcLconst_iteratorgR; -extern G__linked_taginfo G__ManualBase4LN_TDirectory; - -/* STUB derived class for protected member access */ diff --git a/base/src/ManualBase4Body.h b/base/src/ManualBase4Body.h deleted file mode 100644 index 61afd744aec473ad68f260a29dc4d25c9f4680ec..0000000000000000000000000000000000000000 --- a/base/src/ManualBase4Body.h +++ /dev/null @@ -1,40 +0,0 @@ -static int G__ManualBase4_134_5_8(G__value *result7,G__CONST char *funcname,struct G__param *libp,int hash) { - // We need to emulate: - // return WriteObjectAny(obj,TClass::GetClass(typeid(T)),name,option); - - // Here find the class name - G__ClassInfo ti( libp->para[0].tagnum ); - - switch(libp->paran) { - case 3: - G__letint(result7,105,(long)((TDirectory*)(G__getstructoffset()))->WriteObjectAny((const void*)G__int(libp->para[0]),ti.Fullname(),(const char*)G__int(libp->para[1]) -,(Option_t*)G__int(libp->para[2]))); - break; - case 2: - G__letint(result7,105,(long)((TDirectory*)(G__getstructoffset()))->WriteObjectAny((const void*)G__int(libp->para[0]),ti.Fullname(),(const char*)G__int(libp->para[1]))); - break; - } - return(1 || funcname || hash || result7 || libp) ; -} - -static int G__ManualBase4_134_6_8(G__value *result7,G__CONST char *funcname,struct G__param *libp,int hash) { - // We need to emulate: - // ptr = (T*)GetObjectChecked(namecycle,TClass::GetClass(typeid(T))); - - // Here find the class name - G__ClassInfo ti( libp->para[1].tagnum ); - - G__setnull(result7); - TDirectory *directory = ((TDirectory*)(G__getstructoffset())); - const char* namecycle = (const char*)G__int(libp->para[0]); - void *ptr = directory->GetObjectChecked( namecycle, ti.Fullname() ); - void **ptrarg; - if ( libp->para[1].ref ) { - ptrarg = (void**)libp->para[1].ref; - } else { - ptrarg = (void**)(&G__Mlong(libp->para[1])); - } - *ptrarg = ptr; - - return(1 || funcname || hash || result7 || libp) ; -} diff --git a/base/src/TArchiveFile.cxx b/base/src/TArchiveFile.cxx deleted file mode 100644 index 761ddc68d992585cb9224215f2972f8758ceef34..0000000000000000000000000000000000000000 --- a/base/src/TArchiveFile.cxx +++ /dev/null @@ -1,255 +0,0 @@ -// @(#)root/base:$Name: $:$Id: TArchiveFile.cxx,v 1.5 2006/10/05 14:53:48 rdm Exp $ -// Author: Fons Rademakers 30/6/04 - -/************************************************************************* - * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// // -// TArchiveFile // -// // -// This is an abstract class that describes an archive file containing // -// multiple sub-files, like a ZIP or TAR archive. // -// // -////////////////////////////////////////////////////////////////////////// - -#include "TArchiveFile.h" -#include "TPluginManager.h" -#include "TROOT.h" -#include "TObjArray.h" -#include "TObjString.h" -#include "TError.h" -#include "TUrl.h" - - -ClassImp(TArchiveFile) - -//______________________________________________________________________________ -TArchiveFile::TArchiveFile(const char *archive, const char *member, TFile *file) -{ - // Specify the archive name and member name. The member can be a decimal - // number which allows to access the n-th sub-file. This method is - // normally only called via TFile. - - if (!file) - Error("TArchiveFile", "must specify a valid TFile"); - - fFile = file; - fArchiveName = archive; - fMemberName = member; - fMemberIndex = -1; - if (fMemberName.IsDigit()) - fMemberIndex = atoi(fMemberName); - fMembers = new TObjArray; - fMembers->SetOwner(); - fCurMember = 0; -} - -//______________________________________________________________________________ -TArchiveFile::~TArchiveFile() -{ - // Dtor. - - delete fMembers; -} - -//______________________________________________________________________________ -Long64_t TArchiveFile::GetMemberFilePosition() const -{ - // Return position in archive of current member. - - return fCurMember ? fCurMember->GetFilePosition() : 0; -} - -//______________________________________________________________________________ -Int_t TArchiveFile::GetNumberOfMembers() const -{ - // Returns number of members in archive. - - return fMembers->GetEntriesFast(); -} - -//______________________________________________________________________________ -Int_t TArchiveFile::SetMember(const char *member) -{ - // Explicitely make the specified member the current member. - // Returns -1 in case of error, 0 otherwise. - - fMemberName = member; - fMemberIndex = -1; - - return SetCurrentMember(); -} - -//______________________________________________________________________________ -Int_t TArchiveFile::SetMember(Int_t idx) -{ - // Explicitely make the member with the specified index the current member. - // Returns -1 in case of error, 0 otherwise. - - fMemberName = ""; - fMemberIndex = idx; - - return SetCurrentMember(); -} - -//______________________________________________________________________________ -TArchiveFile *TArchiveFile::Open(const char *url, TFile *file) -{ - // Return proper archive file handler depending on passed url. - // The handler is loaded via the plugin manager and is triggered by - // the extension of the archive file. In case no handler is found 0 - // is returned. The file argument is used to access the archive. - // The archive should be specified as url with the member name as the - // anchor, e.g. "root://pcsalo.cern.ch/alice/event_1.zip#tpc.root", - // where tpc.root is the file in the archive to be opened. - // Alternatively the sub-file can be specified via its index number, - // e.g. "root://pcsalo.cern.ch/alice/event_1.zip#3". - // This function is normally only called via TFile::Open(). - - if (!file) { - ::Error("TArchiveFile::Open", "must specify a valid TFile to access %s", - url); - return 0; - } - - TString archive, member; - - if (!ParseUrl(url, archive, member)) - return 0; - - TArchiveFile *f = 0; - TPluginHandler *h; - if ((h = gROOT->GetPluginManager()->FindHandler("TArchiveFile", archive))) { - if (h->LoadPlugin() == -1) - return 0; - f = (TArchiveFile*) h->ExecPlugin(3, archive.Data(), member.Data(), file); - } - - return f; -} - -//______________________________________________________________________________ -Bool_t TArchiveFile::ParseUrl(const char *url, TString &archive, TString &member) -{ - // Try to determine if url contains an anchor specifying an archive member. - // Returns kFALSE in case of an error. - - TUrl u(url, kTRUE); - - archive = ""; - member = ""; - - // get the options and see, if the archive was specified by an option - TString urloptions = u.GetOptions(); - TObjArray *objOptions = urloptions.Tokenize("&"); - for (Int_t n = 0; n < objOptions->GetEntries(); n++) { - - TString loption = ((TObjString*)objOptions->At(n))->GetName(); - TObjArray *objTags = loption.Tokenize("="); - if (objTags->GetEntries() == 2) { - - TString key = ((TObjString*)objTags->At(0))->GetName(); - TString value = ((TObjString*)objTags->At(1))->GetName(); - - if (!key.CompareTo("zip", TString::kIgnoreCase)) { - archive = u.GetFile(); - archive += ".zip"; - member = value; - } - } - delete objTags; - } - delete objOptions; - - if (member != "") { - // member set by an option - return kTRUE; - } - - if (!strlen(u.GetAnchor())) { - archive = u.GetFile(); - return kTRUE; - } - - archive = u.GetFile(); - member = u.GetAnchor(); - - if (archive == "" || member == "") { - archive = ""; - member = ""; - return kFALSE; - } - return kTRUE; -} - - -ClassImp(TArchiveMember) - -//______________________________________________________________________________ -TArchiveMember::TArchiveMember() -{ - // Default ctor. - - fName = ""; - fComment = ""; - fPosition = 0; - fFilePosition = 0; - fCsize = 0; - fDsize = 0; - fDirectory = kFALSE; -} - -//______________________________________________________________________________ -TArchiveMember::TArchiveMember(const char *name) -{ - // Create an archive member file. - - fName = name; - fComment = ""; - fPosition = 0; - fFilePosition = 0; - fCsize = 0; - fDsize = 0; - fDirectory = kFALSE; -} - -//______________________________________________________________________________ -TArchiveMember::TArchiveMember(const TArchiveMember &member) - : TObject(member) -{ - // Copy ctor. - - fName = member.fName; - fComment = member.fComment; - fModTime = member.fModTime; - fPosition = member.fPosition; - fFilePosition = member.fFilePosition; - fCsize = member.fCsize; - fDsize = member.fDsize; - fDirectory = member.fDirectory; -} - -//______________________________________________________________________________ -TArchiveMember &TArchiveMember::operator=(const TArchiveMember &rhs) -{ - // Assignment operator. - - if (this != &rhs) { - TObject::operator=(rhs); - fName = rhs.fName; - fComment = rhs.fComment; - fModTime = rhs.fModTime; - fPosition = rhs.fPosition; - fFilePosition = rhs.fFilePosition; - fCsize = rhs.fCsize; - fDsize = rhs.fDsize; - fDirectory = rhs.fDirectory; - } - return *this; -} diff --git a/base/src/TBufferFile.cxx b/base/src/TBufferFile.cxx deleted file mode 100644 index 086692ebdd993137370bff1f42c21a3f6acb8491..0000000000000000000000000000000000000000 --- a/base/src/TBufferFile.cxx +++ /dev/null @@ -1,2970 +0,0 @@ -// @(#)root/base:$Name: $:$Id: TBufferFile.cxx,v 1.6 2007/02/05 18:08:45 brun Exp $ -// Author: Rene Brun 17/01/2007 - -/************************************************************************* - * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// // -// TBufferFile // -// // -// The concrete implementation of TBuffer for writing/reading to/from a // -// ROOT file or socket. // -// // -////////////////////////////////////////////////////////////////////////// - -#include <string.h> - -#include "TFile.h" -#include "TBufferFile.h" -#include "TExMap.h" -#include "TClass.h" -#include "TProcessID.h" -#include "TRefTable.h" -#include "TStorage.h" -#include "TError.h" -#include "TClonesArray.h" -#include "TStreamer.h" -#include "TStreamerInfo.h" -#include "TStreamerElement.h" - -#if (defined(__linux) || defined(__APPLE__)) && defined(__i386__) && \ - defined(__GNUC__) -#define USE_BSWAPCPY -#endif - -#ifdef USE_BSWAPCPY -#include "Bswapcpy.h" -#endif - - -const UInt_t kNullTag = 0; -const UInt_t kNewClassTag = 0xFFFFFFFF; -const UInt_t kClassMask = 0x80000000; // OR the class index with this -const UInt_t kByteCountMask = 0x40000000; // OR the byte count with this -const UInt_t kMaxMapCount = 0x3FFFFFFE; // last valid fMapCount and byte count -const Version_t kByteCountVMask = 0x4000; // OR the version byte count with this -const Version_t kMaxVersion = 0x3FFF; // highest possible version number -const Int_t kExtraSpace = 8; // extra space at end of buffer (used for free block count) -const Int_t kMapOffset = 2; // first 2 map entries are taken by null obj and self obj - -Int_t TBufferFile::fgMapSize = kMapSize; - - -ClassImp(TBufferFile) - -//______________________________________________________________________________ -static inline ULong_t Void_Hash(const void *ptr) -{ - // Return hash value for this object. - - return TString::Hash(&ptr, sizeof(void*)); -} - -//______________________________________________________________________________ -TBufferFile::TBufferFile(TBuffer::EMode mode) - :TBuffer(mode), - fDisplacement(0),fPidOffset(0), fMap(0), fClassMap(0), - fInfo(0), fInfoStack() -{ - // Create an I/O buffer object. Mode should be either TBuffer::kRead or - // TBuffer::kWrite. By default the I/O buffer has a size of - // TBuffer::kInitialSize (1024) bytes. - - fMapCount = 0; - fMapSize = fgMapSize; - fMap = 0; - fClassMap = 0; - fParent = 0; - fDisplacement = 0; -} - -//______________________________________________________________________________ -TBufferFile::TBufferFile(TBuffer::EMode mode, Int_t bufsiz) - :TBuffer(mode,bufsiz), - fDisplacement(0),fPidOffset(0), fMap(0), fClassMap(0), - fInfo(0), fInfoStack() -{ - // Create an I/O buffer object. Mode should be either TBuffer::kRead or - // TBuffer::kWrite. - - fMapCount = 0; - fMapSize = fgMapSize; - fMap = 0; - fClassMap = 0; - fDisplacement = 0; -} - -//______________________________________________________________________________ -TBufferFile::TBufferFile(TBuffer::EMode mode, Int_t bufsiz, void *buf, Bool_t adopt) : - TBuffer(mode,bufsiz,buf,adopt), - fDisplacement(0),fPidOffset(0), fMap(0), fClassMap(0), - fInfo(0), fInfoStack() -{ - // Create an I/O buffer object. Mode should be either TBuffer::kRead or - // TBuffer::kWrite. By default the I/O buffer has a size of - // TBuffer::kInitialSize (1024) bytes. An external buffer can be passed - // to TBuffer via the buf argument. By default this buffer will be adopted - // unless adopt is false. - - fMapCount = 0; - fMapSize = fgMapSize; - fMap = 0; - fClassMap = 0; - fDisplacement = 0; -} - -//______________________________________________________________________________ -TBufferFile::~TBufferFile() -{ - // Delete an I/O buffer object. - - delete fMap; - delete fClassMap; -} - -//______________________________________________________________________________ -Int_t TBufferFile::GetVersionOwner() const -{ - // Return the version number of the owner file. - - TFile *file = (TFile*)GetParent(); - if (file) return file->GetVersion(); - else return 0; -} - -//______________________________________________________________________________ -void TBufferFile::IncrementLevel(TStreamerInfo* info) -{ - // Increment level. - - fInfoStack.push_back(fInfo); - fInfo = info; -} - -//______________________________________________________________________________ -void TBufferFile::DecrementLevel(TStreamerInfo* /*info*/) -{ - // Decrement level. - - fInfo = fInfoStack.back(); - fInfoStack.pop_back(); -} -//______________________________________________________________________________ -static void frombufOld(char *&buf, Long_t *x) -{ - // Files written with versions older than 3.00/06 had a non-portable - // implementation of Long_t/ULong_t. These types should not have been - // used at all. However, because some users had already written many - // files with these types we provide this dirty patch for "backward - // compatibility" - -#ifdef R__BYTESWAP -#ifdef R__B64 - char *sw = (char *)x; - sw[0] = buf[7]; - sw[1] = buf[6]; - sw[2] = buf[5]; - sw[3] = buf[4]; - sw[4] = buf[3]; - sw[5] = buf[2]; - sw[6] = buf[1]; - sw[7] = buf[0]; -#else - char *sw = (char *)x; - sw[0] = buf[3]; - sw[1] = buf[2]; - sw[2] = buf[1]; - sw[3] = buf[0]; -#endif -#else - memcpy(x, buf, sizeof(Long_t)); -#endif - buf += sizeof(Long_t); -} - -//______________________________________________________________________________ -void TBufferFile::ReadLong(Long_t &l) -{ - // Read Long from TBuffer. - - TFile *file = (TFile*)fParent; - if (file && file->GetVersion() < 30006) { - frombufOld(fBufCur, &l); - } else { - frombuf(fBufCur, &l); - } -} - -//_______________________________________________________________________ -void TBufferFile::ReadTString(TString &s) -{ - // Read string from TBuffer. - - s.Streamer(*this); -} - -//_______________________________________________________________________ -void TBufferFile::WriteTString(const TString &s) -{ - // Write string to TBuffer. - - ((TString&)s).Streamer(*this); -} - -//______________________________________________________________________________ -void TBufferFile::SetByteCount(UInt_t cntpos, Bool_t packInVersion) -{ - // Set byte count at position cntpos in the buffer. Generate warning if - // count larger than kMaxMapCount. The count is excluded its own size. - - UInt_t cnt = UInt_t(fBufCur - fBuffer) - cntpos - sizeof(UInt_t); - char *buf = (char *)(fBuffer + cntpos); - - // if true, pack byte count in two consecutive shorts, so it can - // be read by ReadVersion() - if (packInVersion) { - union { - UInt_t cnt; - Version_t vers[2]; - } v; - v.cnt = cnt; -#ifdef R__BYTESWAP - tobuf(buf, Version_t(v.vers[1] | kByteCountVMask)); - tobuf(buf, v.vers[0]); -#else - tobuf(buf, Version_t(v.vers[0] | kByteCountVMask)); - tobuf(buf, v.vers[1]); -#endif - } else - tobuf(buf, cnt | kByteCountMask); - - if (cnt >= kMaxMapCount) { - Error("WriteByteCount", "bytecount too large (more than %d)", kMaxMapCount); - // exception - } -} - -//______________________________________________________________________________ -Int_t TBufferFile::CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss, const char *classname) -{ - // Check byte count with current buffer position. They should - // match. If not print warning and position buffer in correct - // place determined by the byte count. Startpos is position of - // first byte where the byte count is written in buffer. - // Returns 0 if everything is ok, otherwise the bytecount offset - // (< 0 when read too little, >0 when read too much). - - if (!bcnt) return 0; - - Int_t offset = 0; - - Long_t endpos = Long_t(fBuffer) + startpos + bcnt + sizeof(UInt_t); - - if (Long_t(fBufCur) != endpos) { - offset = Int_t(Long_t(fBufCur) - endpos); - - const char *name = clss ? clss->GetName() : classname ? classname : 0; - - if (name) { - if (offset < 0) { - Error("CheckByteCount", "object of class %s read too few bytes: %d instead of %d", - name,bcnt+offset,bcnt); - } - if (offset > 0) { - Error("CheckByteCount", "object of class %s read too many bytes: %d instead of %d", - name,bcnt+offset,bcnt); - if (fParent) - Warning("CheckByteCount","%s::Streamer() not in sync with data on file %s, fix Streamer()", - name, fParent->GetName()); - else - Warning("CheckByteCount","%s::Streamer() not in sync with data, fix Streamer()", - name); - } - } - if ( ((char *)endpos) > fBufMax ) { - offset = fBufMax-fBufCur; - Error("CheckByteCount", - "Byte count probably corrupted around buffer position %d:\n\t%d for a possible maximum of %d", - startpos, bcnt, offset); - fBufCur = fBufMax; - - } else { - - fBufCur = (char *) endpos; - - } - } - return offset; -} - -//______________________________________________________________________________ -Int_t TBufferFile::CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss) -{ - // Check byte count with current buffer position. They should - // match. If not print warning and position buffer in correct - // place determined by the byte count. Startpos is position of - // first byte where the byte count is written in buffer. - // Returns 0 if everything is ok, otherwise the bytecount offset - // (< 0 when read too little, >0 when read too much). - - if (!bcnt) return 0; - return CheckByteCount( startpos, bcnt, clss, 0); -} - -//______________________________________________________________________________ -Int_t TBufferFile::CheckByteCount(UInt_t startpos, UInt_t bcnt, const char *classname) -{ - // Check byte count with current buffer position. They should - // match. If not print warning and position buffer in correct - // place determined by the byte count. Startpos is position of - // first byte where the byte count is written in buffer. - // Returns 0 if everything is ok, otherwise the bytecount offset - // (< 0 when read too little, >0 when read too much). - - if (!bcnt) return 0; - return CheckByteCount( startpos, bcnt, 0, classname); -} - - -//______________________________________________________________________________ -void TBufferFile::ReadDouble32 (Double_t *d, TStreamerElement *ele) -{ - // Read a Double32_t from the buffer, - // see comments about Double32_t encoding at TBufferFile::WriteDouble32(). - - if (ele && ele->GetFactor() != 0) { - UInt_t aint; *this >> aint; d[0] = (Double_t)(aint/ele->GetFactor() + ele->GetXmin()); - } else { - Float_t afloat; *this >> afloat; d[0] = (Double_t)afloat; - } -} - -//______________________________________________________________________________ -void TBufferFile::WriteDouble32 (Double_t *d, TStreamerElement *ele) -{ - // write a Double32_t to the buffer. - // The following cases are supported for streaming a Double32_t type - // depending on the range declaration in the comment field of the data member: - // A- Double32_t fNormal; - // B- Double32_t fTemperature; //[0,100] - // C- Double32_t fCharge; //[-1,1,2] - // D- Double32_t fVertex[3]; //[-30,30,10] - // E Int_t fNsp; - // Double32_t* fPointValue; //[fNsp][0,3] - // - // In case A fNormal is converted from a Double_t to a Float_t - // In case B fTemperature is converted to a 32 bit unsigned integer - // In case C fCharge is converted to a 2 bits unsigned integer - // In case D the array elements of fVertex are converted to an unsigned 10 bits integer - // In case E the fNsp elements of array fPointvalue are converted to an unsigned 32 bit integer - // Note that the range specifier must follow the dimension specifier. - // the case B has more precision (9 to 10 significative digits than case A (6 to 7 digits). - // - // The range specifier has the general format: [xmin,xmax] or [xmin,xmax,nbits] - // [0,1] - // [-10,100]; - // [-pi,pi], [-pi/2,pi/4],[-2pi,2*pi] - // [-10,100,16] - // if nbits is not specified, or nbits <2 or nbits>32 it is set to 32 - // - // see example of use of the Double32_t data type in tutorial double32.C - // - //Begin_Html - /* - <img src="gif/double32.gif"> - */ - //End_Html - - if (ele && ele->GetFactor() != 0) { - Double_t x = d[0]; - Double_t xmin = ele->GetXmin(); - Double_t xmax = ele->GetXmax(); - if (x < xmin) x = xmin; - if (x > xmax) x = xmax; - UInt_t aint = UInt_t(0.5+ele->GetFactor()*(x-xmin)); *this << aint; - } else { - Float_t afloat = (Float_t)d[0]; *this << afloat; - } -} - -//______________________________________________________________________________ -Int_t TBufferFile::ReadArray(Bool_t *&b) -{ - // Read array of bools from the I/O buffer. Returns the number of - // bools read. If argument is a 0 pointer then space will be - // allocated for the array. - - R__ASSERT(IsReading()); - - Int_t n; - *this >> n; - - if (n <= 0 || n > fBufSize) return 0; - - if (!b) b = new Bool_t[n]; - - if (sizeof(Bool_t) > 1) { - for (int i = 0; i < n; i++) - frombuf(fBufCur, &b[i]); - } else { - Int_t l = sizeof(Bool_t)*n; - memcpy(b, fBufCur, l); - fBufCur += l; - } - - return n; -} - -//______________________________________________________________________________ -Int_t TBufferFile::ReadArray(Char_t *&c) -{ - // Read array of characters from the I/O buffer. Returns the number of - // characters read. If argument is a 0 pointer then space will be - // allocated for the array. - - R__ASSERT(IsReading()); - - Int_t n; - *this >> n; - Int_t l = sizeof(Char_t)*n; - - if (l <= 0 || l > fBufSize) return 0; - - if (!c) c = new Char_t[n]; - - memcpy(c, fBufCur, l); - fBufCur += l; - - return n; -} - -//______________________________________________________________________________ -Int_t TBufferFile::ReadArray(Short_t *&h) -{ - // Read array of shorts from the I/O buffer. Returns the number of shorts - // read. If argument is a 0 pointer then space will be allocated for the - // array. - - R__ASSERT(IsReading()); - - Int_t n; - *this >> n; - Int_t l = sizeof(Short_t)*n; - - if (l <= 0 || l > fBufSize) return 0; - - if (!h) h = new Short_t[n]; - -#ifdef R__BYTESWAP -# ifdef USE_BSWAPCPY - bswapcpy16(h, fBufCur, n); - fBufCur += l; -# else - for (int i = 0; i < n; i++) - frombuf(fBufCur, &h[i]); -# endif -#else - memcpy(h, fBufCur, l); - fBufCur += l; -#endif - - return n; -} - -//______________________________________________________________________________ -Int_t TBufferFile::ReadArray(Int_t *&ii) -{ - // Read array of ints from the I/O buffer. Returns the number of ints - // read. If argument is a 0 pointer then space will be allocated for the - // array. - - R__ASSERT(IsReading()); - - Int_t n; - *this >> n; - Int_t l = sizeof(Int_t)*n; - - if (l <= 0 || l > fBufSize) return 0; - - if (!ii) ii = new Int_t[n]; - -#ifdef R__BYTESWAP -# ifdef USE_BSWAPCPY - bswapcpy32(ii, fBufCur, n); - fBufCur += l; -# else - for (int i = 0; i < n; i++) - frombuf(fBufCur, &ii[i]); -# endif -#else - memcpy(ii, fBufCur, l); - fBufCur += l; -#endif - - return n; -} - -//______________________________________________________________________________ -Int_t TBufferFile::ReadArray(Long_t *&ll) -{ - // Read array of longs from the I/O buffer. Returns the number of longs - // read. If argument is a 0 pointer then space will be allocated for the - // array. - - R__ASSERT(IsReading()); - - Int_t n; - *this >> n; - Int_t l = sizeof(Long_t)*n; - - if (l <= 0 || l > fBufSize) return 0; - - if (!ll) ll = new Long_t[n]; - - TFile *file = (TFile*)fParent; - if (file && file->GetVersion() < 30006) { - for (int i = 0; i < n; i++) frombufOld(fBufCur, &ll[i]); - } else { - for (int i = 0; i < n; i++) frombuf(fBufCur, &ll[i]); - } - return n; -} - -//______________________________________________________________________________ -Int_t TBufferFile::ReadArray(Long64_t *&ll) -{ - // Read array of long longs from the I/O buffer. Returns the number of - // long longs read. If argument is a 0 pointer then space will be - // allocated for the array. - - R__ASSERT(IsReading()); - - Int_t n; - *this >> n; - Int_t l = sizeof(Long64_t)*n; - - if (l <= 0 || l > fBufSize) return 0; - - if (!ll) ll = new Long64_t[n]; - -#ifdef R__BYTESWAP - for (int i = 0; i < n; i++) - frombuf(fBufCur, &ll[i]); -#else - memcpy(ll, fBufCur, l); - fBufCur += l; -#endif - - return n; -} - -//______________________________________________________________________________ -Int_t TBufferFile::ReadArray(Float_t *&f) -{ - // Read array of floats from the I/O buffer. Returns the number of floats - // read. If argument is a 0 pointer then space will be allocated for the - // array. - - R__ASSERT(IsReading()); - - Int_t n; - *this >> n; - Int_t l = sizeof(Float_t)*n; - - if (l <= 0 || l > fBufSize) return 0; - - if (!f) f = new Float_t[n]; - -#ifdef R__BYTESWAP -# ifdef USE_BSWAPCPY - bswapcpy32(f, fBufCur, n); - fBufCur += l; -# else - for (int i = 0; i < n; i++) - frombuf(fBufCur, &f[i]); -# endif -#else - memcpy(f, fBufCur, l); - fBufCur += l; -#endif - - return n; -} - -//______________________________________________________________________________ -Int_t TBufferFile::ReadArray(Double_t *&d) -{ - // Read array of doubles from the I/O buffer. Returns the number of doubles - // read. If argument is a 0 pointer then space will be allocated for the - // array. - - R__ASSERT(IsReading()); - - Int_t n; - *this >> n; - Int_t l = sizeof(Double_t)*n; - - if (l <= 0 || l > fBufSize) return 0; - - if (!d) d = new Double_t[n]; - -#ifdef R__BYTESWAP - for (int i = 0; i < n; i++) - frombuf(fBufCur, &d[i]); -#else - memcpy(d, fBufCur, l); - fBufCur += l; -#endif - - return n; -} - -//______________________________________________________________________________ -Int_t TBufferFile::ReadArrayDouble32(Double_t *&d, TStreamerElement *ele) -{ - // Read array of doubles (written as float) from the I/O buffer. - // Returns the number of doubles read. - // If argument is a 0 pointer then space will be allocated for the array. - // see comments about Double32_t encoding at TBufferFile::WriteDouble32 - - R__ASSERT(IsReading()); - - Int_t n; - *this >> n; - - if (n <= 0 || 4*n > fBufSize) return 0; - - if (!d) d = new Double_t[n]; - - ReadFastArrayDouble32(d,n,ele); - - return n; -} - -//______________________________________________________________________________ -Int_t TBufferFile::ReadStaticArray(Bool_t *b) -{ - // Read array of bools from the I/O buffer. Returns the number of bools - // read. - - R__ASSERT(IsReading()); - - Int_t n; - *this >> n; - - if (n <= 0 || n > fBufSize) return 0; - - if (!b) return 0; - - if (sizeof(Bool_t) > 1) { - for (int i = 0; i < n; i++) - frombuf(fBufCur, &b[i]); - } else { - Int_t l = sizeof(Bool_t)*n; - memcpy(b, fBufCur, l); - fBufCur += l; - } - - return n; -} - -//______________________________________________________________________________ -Int_t TBufferFile::ReadStaticArray(Char_t *c) -{ - // Read array of characters from the I/O buffer. Returns the number of - // characters read. - - R__ASSERT(IsReading()); - - Int_t n; - *this >> n; - Int_t l = sizeof(Char_t)*n; - - if (l <= 0 || l > fBufSize) return 0; - - if (!c) return 0; - - memcpy(c, fBufCur, l); - fBufCur += l; - - return n; -} - -//______________________________________________________________________________ -Int_t TBufferFile::ReadStaticArray(Short_t *h) -{ - // Read array of shorts from the I/O buffer. Returns the number of shorts - // read. - - R__ASSERT(IsReading()); - - Int_t n; - *this >> n; - Int_t l = sizeof(Short_t)*n; - - if (l <= 0 || l > fBufSize) return 0; - - if (!h) return 0; - -#ifdef R__BYTESWAP -# ifdef USE_BSWAPCPY - bswapcpy16(h, fBufCur, n); - fBufCur += l; -# else - for (int i = 0; i < n; i++) - frombuf(fBufCur, &h[i]); -# endif -#else - memcpy(h, fBufCur, l); - fBufCur += l; -#endif - - return n; -} - -//______________________________________________________________________________ -Int_t TBufferFile::ReadStaticArray(Int_t *ii) -{ - // Read array of ints from the I/O buffer. Returns the number of ints - // read. - - R__ASSERT(IsReading()); - - Int_t n; - *this >> n; - Int_t l = sizeof(Int_t)*n; - - if (l <= 0 || l > fBufSize) return 0; - - if (!ii) return 0; - -#ifdef R__BYTESWAP -# ifdef USE_BSWAPCPY - bswapcpy32(ii, fBufCur, n); - fBufCur += sizeof(Int_t)*n; -# else - for (int i = 0; i < n; i++) - frombuf(fBufCur, &ii[i]); -# endif -#else - memcpy(ii, fBufCur, l); - fBufCur += l; -#endif - - return n; -} - -//______________________________________________________________________________ -Int_t TBufferFile::ReadStaticArray(Long_t *ll) -{ - // Read array of longs from the I/O buffer. Returns the number of longs - // read. - - R__ASSERT(IsReading()); - - Int_t n; - *this >> n; - Int_t l = sizeof(Long_t)*n; - - if (l <= 0 || l > fBufSize) return 0; - - if (!ll) return 0; - - TFile *file = (TFile*)fParent; - if (file && file->GetVersion() < 30006) { - for (int i = 0; i < n; i++) frombufOld(fBufCur, &ll[i]); - } else { - for (int i = 0; i < n; i++) frombuf(fBufCur, &ll[i]); - } - return n; -} - -//______________________________________________________________________________ -Int_t TBufferFile::ReadStaticArray(Long64_t *ll) -{ - // Read array of long longs from the I/O buffer. Returns the number of - // long longs read. - - R__ASSERT(IsReading()); - - Int_t n; - *this >> n; - Int_t l = sizeof(Long64_t)*n; - - if (l <= 0 || l > fBufSize) return 0; - - if (!ll) return 0; - -#ifdef R__BYTESWAP - for (int i = 0; i < n; i++) - frombuf(fBufCur, &ll[i]); -#else - memcpy(ll, fBufCur, l); - fBufCur += l; -#endif - - return n; -} - -//______________________________________________________________________________ -Int_t TBufferFile::ReadStaticArray(Float_t *f) -{ - // Read array of floats from the I/O buffer. Returns the number of floats - // read. - - R__ASSERT(IsReading()); - - Int_t n; - *this >> n; - Int_t l = sizeof(Float_t)*n; - - if (n <= 0 || l > fBufSize) return 0; - - if (!f) return 0; - -#ifdef R__BYTESWAP -# ifdef USE_BSWAPCPY - bswapcpy32(f, fBufCur, n); - fBufCur += sizeof(Float_t)*n; -# else - for (int i = 0; i < n; i++) - frombuf(fBufCur, &f[i]); -# endif -#else - memcpy(f, fBufCur, l); - fBufCur += l; -#endif - - return n; -} - -//______________________________________________________________________________ -Int_t TBufferFile::ReadStaticArray(Double_t *d) -{ - // Read array of doubles from the I/O buffer. Returns the number of doubles - // read. - - R__ASSERT(IsReading()); - - Int_t n; - *this >> n; - Int_t l = sizeof(Double_t)*n; - - if (n <= 0 || l > fBufSize) return 0; - - if (!d) return 0; - -#ifdef R__BYTESWAP - for (int i = 0; i < n; i++) - frombuf(fBufCur, &d[i]); -#else - memcpy(d, fBufCur, l); - fBufCur += l; -#endif - - return n; -} - -//______________________________________________________________________________ -Int_t TBufferFile::ReadStaticArrayDouble32(Double_t *d, TStreamerElement *ele) -{ - // Read array of doubles (written as float) from the I/O buffer. - // Returns the number of doubles read. - // see comments about Double32_t encoding at TBufferFile::WriteDouble32 - - R__ASSERT(IsReading()); - - Int_t n; - *this >> n; - - if (n <= 0 || 4*n > fBufSize) return 0; - - if (!d) return 0; - - ReadFastArrayDouble32(d,n,ele); - - return n; -} - -//______________________________________________________________________________ -void TBufferFile::ReadFastArray(Bool_t *b, Int_t n) -{ - // Read array of n bools from the I/O buffer. - - if (n <= 0 || n > fBufSize) return; - - if (sizeof(Bool_t) > 1) { - for (int i = 0; i < n; i++) - frombuf(fBufCur, &b[i]); - } else { - Int_t l = sizeof(Bool_t)*n; - memcpy(b, fBufCur, l); - fBufCur += l; - } -} - -//______________________________________________________________________________ -void TBufferFile::ReadFastArray(Char_t *c, Int_t n) -{ - // Read array of n characters from the I/O buffer. - - if (n <= 0 || n > fBufSize) return; - - Int_t l = sizeof(Char_t)*n; - memcpy(c, fBufCur, l); - fBufCur += l; -} - -//______________________________________________________________________________ -void TBufferFile::ReadFastArrayString(Char_t *c, Int_t n) -{ - // Read array of n characters from the I/O buffer. - - Int_t len; - UChar_t lenchar; - *this >> lenchar; - if (lenchar < 255) { - len = lenchar; - } else { - *this >> len; - } - if (len) { - if (len <= 0 || len > fBufSize) return; - Int_t blen = len; - if (len >= n) len = n-1; - - Int_t l = sizeof(Char_t)*len; - memcpy(c, fBufCur, l); - fBufCur += blen; - - c[len] = 0; - } else { - c[0] = 0; - } -} - -//______________________________________________________________________________ -void TBufferFile::ReadFastArray(Short_t *h, Int_t n) -{ - // Read array of n shorts from the I/O buffer. - - Int_t l = sizeof(Short_t)*n; - if (n <= 0 || l > fBufSize) return; - -#ifdef R__BYTESWAP -# ifdef USE_BSWAPCPY - bswapcpy16(h, fBufCur, n); - fBufCur += sizeof(Short_t)*n; -# else - for (int i = 0; i < n; i++) - frombuf(fBufCur, &h[i]); -# endif -#else - memcpy(h, fBufCur, l); - fBufCur += l; -#endif -} - -//______________________________________________________________________________ -void TBufferFile::ReadFastArray(Int_t *ii, Int_t n) -{ - // Read array of n ints from the I/O buffer. - - Int_t l = sizeof(Int_t)*n; - if (l <= 0 || l > fBufSize) return; - -#ifdef R__BYTESWAP -# ifdef USE_BSWAPCPY - bswapcpy32(ii, fBufCur, n); - fBufCur += sizeof(Int_t)*n; -# else - for (int i = 0; i < n; i++) - frombuf(fBufCur, &ii[i]); -# endif -#else - memcpy(ii, fBufCur, l); - fBufCur += l; -#endif -} - -//______________________________________________________________________________ -void TBufferFile::ReadFastArray(Long_t *ll, Int_t n) -{ - // Read array of n longs from the I/O buffer. - - Int_t l = sizeof(Long_t)*n; - if (l <= 0 || l > fBufSize) return; - - TFile *file = (TFile*)fParent; - if (file && file->GetVersion() < 30006) { - for (int i = 0; i < n; i++) frombufOld(fBufCur, &ll[i]); - } else { - for (int i = 0; i < n; i++) frombuf(fBufCur, &ll[i]); - } -} - -//______________________________________________________________________________ -void TBufferFile::ReadFastArray(Long64_t *ll, Int_t n) -{ - // Read array of n long longs from the I/O buffer. - - Int_t l = sizeof(Long64_t)*n; - if (l <= 0 || l > fBufSize) return; - -#ifdef R__BYTESWAP - for (int i = 0; i < n; i++) - frombuf(fBufCur, &ll[i]); -#else - memcpy(ll, fBufCur, l); - fBufCur += l; -#endif -} - -//______________________________________________________________________________ -void TBufferFile::ReadFastArray(Float_t *f, Int_t n) -{ - // Read array of n floats from the I/O buffer. - - Int_t l = sizeof(Float_t)*n; - if (l <= 0 || l > fBufSize) return; - -#ifdef R__BYTESWAP -# ifdef USE_BSWAPCPY - bswapcpy32(f, fBufCur, n); - fBufCur += sizeof(Float_t)*n; -# else - for (int i = 0; i < n; i++) - frombuf(fBufCur, &f[i]); -# endif -#else - memcpy(f, fBufCur, l); - fBufCur += l; -#endif -} - -//______________________________________________________________________________ -void TBufferFile::ReadFastArray(Double_t *d, Int_t n) -{ - // Read array of n doubles from the I/O buffer. - - Int_t l = sizeof(Double_t)*n; - if (l <= 0 || l > fBufSize) return; - -#ifdef R__BYTESWAP - for (int i = 0; i < n; i++) - frombuf(fBufCur, &d[i]); -#else - memcpy(d, fBufCur, l); - fBufCur += l; -#endif -} - -//______________________________________________________________________________ -void TBufferFile::ReadFastArrayDouble32(Double_t *d, Int_t n, TStreamerElement *ele) -{ - // Read array of n doubles (written as float) from the I/O buffer. - // see comments about Double32_t encoding at TBufferFile::WriteDouble32 - - if (n <= 0 || 4*n > fBufSize) return; - - if (ele && ele->GetFactor() != 0) { - Double_t xmin = ele->GetXmin(); - Double_t factor = ele->GetFactor(); - for (int j=0;j < n; j++) { - UInt_t aint; *this >> aint; d[j] = (Double_t)(aint/factor + xmin); - } - } else { - Float_t afloat; - for (int i = 0; i < n; i++) { - frombuf(fBufCur, &afloat); - d[i]=afloat; - } - } -} - -//______________________________________________________________________________ -void TBufferFile::ReadFastArray(void *start, const TClass *cl, Int_t n, - TMemberStreamer *streamer) -{ - // Read an array of 'n' objects from the I/O buffer. - // Stores the objects read starting at the address 'start'. - // The objects in the array are assume to be of class 'cl'. - - if (streamer) { - (*streamer)(*this,start,0); - return; - } - - int objectSize = cl->Size(); - char *obj = (char*)start; - char *end = obj + n*objectSize; - - for(; obj<end; obj+=objectSize) ((TClass*)cl)->Streamer(obj,*this); -} - -//______________________________________________________________________________ -void TBufferFile::ReadFastArray(void **start, const TClass *cl, Int_t n, - Bool_t isPreAlloc, TMemberStreamer *streamer) -{ - // Read an array of 'n' objects from the I/O buffer. - // The objects read are stored starting at the address '*start' - // The objects in the array are assumed to be of class 'cl' or a derived class. - // 'mode' indicates whether the data member is marked with '->' - - // if isPreAlloc is true (data member has a ->) we can assume that the pointer (*start) - // is never 0. - - if (streamer) { - if (isPreAlloc) { - for (Int_t j=0;j<n;j++) { - if (!start[j]) start[j] = ((TClass*)cl)->New(); - } - } - (*streamer)(*this,(void*)start,0); - return; - } - - if (!isPreAlloc) { - - for (Int_t j=0; j<n; j++){ - //delete the object or collection - if (start[j] && TStreamerInfo::CanDelete() - // There are some cases where the user may set up a pointer in the (default) - // constructor but not mark this pointer as transient. Sometime the value - // of this pointer is the address of one of the object with just created - // and the following delete would result in the deletion (possibly of the - // top level object we are goint to return!). - // Eventhough this is a user error, we could prevent the crash by simply - // adding: - // && !CheckObject(start[j],cl) - // However this can increase the read time significantly (10% in the case - // of one TLine pointer in the test/Track and run ./Event 200 0 0 20 30000 - ) ((TClass*)cl)->Destructor(start[j],kFALSE); // call delete and desctructor - start[j] = ReadObjectAny(cl); - } - - } else { //case //-> in comment - - for (Int_t j=0; j<n; j++){ - if (!start[j]) start[j] = ((TClass*)cl)->New(); - ((TClass*)cl)->Streamer(start[j],*this); - } - - } -} - -//______________________________________________________________________________ -void TBufferFile::WriteArray(const Bool_t *b, Int_t n) -{ - // Write array of n bools into the I/O buffer. - - R__ASSERT(IsWriting()); - - *this << n; - - if (n <= 0) return; - - R__ASSERT(b); - - Int_t l = sizeof(UChar_t)*n; - if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l)); - - if (sizeof(Bool_t) > 1) { - for (int i = 0; i < n; i++) - tobuf(fBufCur, b[i]); - } else { - memcpy(fBufCur, b, l); - fBufCur += l; - } -} - -//______________________________________________________________________________ -void TBufferFile::WriteArray(const Char_t *c, Int_t n) -{ - // Write array of n characters into the I/O buffer. - - R__ASSERT(IsWriting()); - - *this << n; - - if (n <= 0) return; - - R__ASSERT(c); - - Int_t l = sizeof(Char_t)*n; - if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l)); - - memcpy(fBufCur, c, l); - fBufCur += l; -} - -//______________________________________________________________________________ -void TBufferFile::WriteArray(const Short_t *h, Int_t n) -{ - // Write array of n shorts into the I/O buffer. - - R__ASSERT(IsWriting()); - - *this << n; - - if (n <= 0) return; - - R__ASSERT(h); - - Int_t l = sizeof(Short_t)*n; - if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l)); - -#ifdef R__BYTESWAP -# ifdef USE_BSWAPCPY - bswapcpy16(fBufCur, h, n); - fBufCur += l; -# else - for (int i = 0; i < n; i++) - tobuf(fBufCur, h[i]); -# endif -#else - memcpy(fBufCur, h, l); - fBufCur += l; -#endif -} - -//______________________________________________________________________________ -void TBufferFile::WriteArray(const Int_t *ii, Int_t n) -{ - // Write array of n ints into the I/O buffer. - - R__ASSERT(IsWriting()); - - *this << n; - - if (n <= 0) return; - - R__ASSERT(ii); - - Int_t l = sizeof(Int_t)*n; - if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l)); - -#ifdef R__BYTESWAP -# ifdef USE_BSWAPCPY - bswapcpy32(fBufCur, ii, n); - fBufCur += l; -# else - for (int i = 0; i < n; i++) - tobuf(fBufCur, ii[i]); -# endif -#else - memcpy(fBufCur, ii, l); - fBufCur += l; -#endif -} - -//______________________________________________________________________________ -void TBufferFile::WriteArray(const Long_t *ll, Int_t n) -{ - // Write array of n longs into the I/O buffer. - - R__ASSERT(IsWriting()); - - *this << n; - - if (n <= 0) return; - - R__ASSERT(ll); - - Int_t l = 8*n; - if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l)); - for (int i = 0; i < n; i++) tobuf(fBufCur, ll[i]); -} - -//______________________________________________________________________________ -void TBufferFile::WriteArray(const ULong_t *ll, Int_t n) -{ - // Write array of n unsigned longs into the I/O buffer. - // This is an explicit case for unsigned longs since signed longs - // have a special tobuf(). - - R__ASSERT(IsWriting()); - - *this << n; - - if (n <= 0) return; - - R__ASSERT(ll); - - Int_t l = 8*n; - if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l)); - for (int i = 0; i < n; i++) tobuf(fBufCur, ll[i]); -} - -//______________________________________________________________________________ -void TBufferFile::WriteArray(const Long64_t *ll, Int_t n) -{ - // Write array of n long longs into the I/O buffer. - - R__ASSERT(IsWriting()); - - *this << n; - - if (n <= 0) return; - - R__ASSERT(ll); - - Int_t l = sizeof(Long64_t)*n; - if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l)); - -#ifdef R__BYTESWAP - for (int i = 0; i < n; i++) - tobuf(fBufCur, ll[i]); -#else - memcpy(fBufCur, ll, l); - fBufCur += l; -#endif -} - -//______________________________________________________________________________ -void TBufferFile::WriteArray(const Float_t *f, Int_t n) -{ - // Write array of n floats into the I/O buffer. - - R__ASSERT(IsWriting()); - - *this << n; - - if (n <= 0) return; - - R__ASSERT(f); - - Int_t l = sizeof(Float_t)*n; - if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l)); - -#ifdef R__BYTESWAP -# ifdef USE_BSWAPCPY - bswapcpy32(fBufCur, f, n); - fBufCur += l; -# else - for (int i = 0; i < n; i++) - tobuf(fBufCur, f[i]); -# endif -#else - memcpy(fBufCur, f, l); - fBufCur += l; -#endif -} - -//______________________________________________________________________________ -void TBufferFile::WriteArray(const Double_t *d, Int_t n) -{ - // Write array of n doubles into the I/O buffer. - - R__ASSERT(IsWriting()); - - *this << n; - - if (n <= 0) return; - - R__ASSERT(d); - - Int_t l = sizeof(Double_t)*n; - if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l)); - -#ifdef R__BYTESWAP - for (int i = 0; i < n; i++) - tobuf(fBufCur, d[i]); -#else - memcpy(fBufCur, d, l); - fBufCur += l; -#endif -} - -//______________________________________________________________________________ -void TBufferFile::WriteArrayDouble32(const Double_t *d, Int_t n, TStreamerElement *ele) -{ - // Write array of n doubles (as float) into the I/O buffer. - // see comments about Double32_t encoding at TBufferFile::WriteDouble32 - - R__ASSERT(IsWriting()); - - *this << n; - - if (n <= 0) return; - - R__ASSERT(d); - - Int_t l = sizeof(Float_t)*n; - if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l)); - - WriteFastArrayDouble32(d,n,ele); -} - -//______________________________________________________________________________ -void TBufferFile::WriteFastArray(const Bool_t *b, Int_t n) -{ - // Write array of n bools into the I/O buffer. - - if (n <= 0) return; - - Int_t l = sizeof(UChar_t)*n; - if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l)); - - if (sizeof(Bool_t) > 1) { - for (int i = 0; i < n; i++) - tobuf(fBufCur, b[i]); - } else { - memcpy(fBufCur, b, l); - fBufCur += l; - } -} - -//______________________________________________________________________________ -void TBufferFile::WriteFastArray(const Char_t *c, Int_t n) -{ - // Write array of n characters into the I/O buffer. - - if (n <= 0) return; - - Int_t l = sizeof(Char_t)*n; - if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l)); - - memcpy(fBufCur, c, l); - fBufCur += l; -} - -//______________________________________________________________________________ -void TBufferFile::WriteFastArrayString(const Char_t *c, Int_t n) -{ - // Write array of n characters into the I/O buffer. - - if (n < 255) { - *this << (UChar_t)n; - } else { - *this << (UChar_t)255; - *this << n; - } - - if (n <= 0) return; - - Int_t l = sizeof(Char_t)*n; - if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l)); - - memcpy(fBufCur, c, l); - fBufCur += l; -} - -//______________________________________________________________________________ -void TBufferFile::WriteFastArray(const Short_t *h, Int_t n) -{ - // Write array of n shorts into the I/O buffer. - - if (n <= 0) return; - - Int_t l = sizeof(Short_t)*n; - if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l)); - -#ifdef R__BYTESWAP -# ifdef USE_BSWAPCPY - bswapcpy16(fBufCur, h, n); - fBufCur += l; -# else - for (int i = 0; i < n; i++) - tobuf(fBufCur, h[i]); -# endif -#else - memcpy(fBufCur, h, l); - fBufCur += l; -#endif -} - -//______________________________________________________________________________ -void TBufferFile::WriteFastArray(const Int_t *ii, Int_t n) -{ - // Write array of n ints into the I/O buffer. - - if (n <= 0) return; - - Int_t l = sizeof(Int_t)*n; - if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l)); - -#ifdef R__BYTESWAP -# ifdef USE_BSWAPCPY - bswapcpy32(fBufCur, ii, n); - fBufCur += l; -# else - for (int i = 0; i < n; i++) - tobuf(fBufCur, ii[i]); -# endif -#else - memcpy(fBufCur, ii, l); - fBufCur += l; -#endif -} - -//______________________________________________________________________________ -void TBufferFile::WriteFastArray(const Long_t *ll, Int_t n) -{ - // Write array of n longs into the I/O buffer. - - if (n <= 0) return; - - Int_t l = 8*n; - if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l)); - - for (int i = 0; i < n; i++) tobuf(fBufCur, ll[i]); -} - -//______________________________________________________________________________ -void TBufferFile::WriteFastArray(const ULong_t *ll, Int_t n) -{ - // Write array of n unsigned longs into the I/O buffer. - // This is an explicit case for unsigned longs since signed longs - // have a special tobuf(). - - if (n <= 0) return; - - Int_t l = 8*n; - if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l)); - - for (int i = 0; i < n; i++) tobuf(fBufCur, ll[i]); -} - -//______________________________________________________________________________ -void TBufferFile::WriteFastArray(const Long64_t *ll, Int_t n) -{ - // Write array of n long longs into the I/O buffer. - - if (n <= 0) return; - - Int_t l = sizeof(Long64_t)*n; - if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l)); - -#ifdef R__BYTESWAP - for (int i = 0; i < n; i++) - tobuf(fBufCur, ll[i]); -#else - memcpy(fBufCur, ll, l); - fBufCur += l; -#endif -} - -//______________________________________________________________________________ -void TBufferFile::WriteFastArray(const Float_t *f, Int_t n) -{ - // Write array of n floats into the I/O buffer. - - if (n <= 0) return; - - Int_t l = sizeof(Float_t)*n; - if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l)); - -#ifdef R__BYTESWAP -# ifdef USE_BSWAPCPY - bswapcpy32(fBufCur, f, n); - fBufCur += l; -# else - for (int i = 0; i < n; i++) - tobuf(fBufCur, f[i]); -# endif -#else - memcpy(fBufCur, f, l); - fBufCur += l; -#endif -} - -//______________________________________________________________________________ -void TBufferFile::WriteFastArray(const Double_t *d, Int_t n) -{ - // Write array of n doubles into the I/O buffer. - - if (n <= 0) return; - - Int_t l = sizeof(Double_t)*n; - if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l)); - -#ifdef R__BYTESWAP - for (int i = 0; i < n; i++) - tobuf(fBufCur, d[i]); -#else - memcpy(fBufCur, d, l); - fBufCur += l; -#endif -} - -//______________________________________________________________________________ -void TBufferFile::WriteFastArrayDouble32(const Double_t *d, Int_t n, TStreamerElement *ele) -{ - // Write array of n doubles (as float) into the I/O buffer. - // see comments about Double32_t encoding at TBufferFile::WriteDouble32 - - if (n <= 0) return; - - Int_t l = sizeof(Float_t)*n; - if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l)); - - if (ele && ele->GetFactor()) { - Double_t factor = ele->GetFactor(); - Double_t xmin = ele->GetXmin(); - Double_t xmax = ele->GetXmax(); - for (int j = 0; j < n; j++) { - Double_t x = d[j]; - if (x < xmin) x = xmin; - if (x > xmax) x = xmax; - UInt_t aint = UInt_t(0.5+factor*(x-xmin)); *this << aint; - } - } else { - for (int i = 0; i < n; i++) - tobuf(fBufCur, Float_t(d[i])); - } -} - -//______________________________________________________________________________ -void TBufferFile::WriteFastArray(void *start, const TClass *cl, Int_t n, - TMemberStreamer *streamer) -{ - // Write an array of object starting at the address 'start' and of length 'n' - // the objects in the array are assumed to be of class 'cl' - - if (streamer) { - (*streamer)(*this, start, 0); - return; - } - - char *obj = (char*)start; - if (!n) n=1; - int size = cl->Size(); - - for(Int_t j=0; j<n; j++,obj+=size) { - ((TClass*)cl)->Streamer(obj,*this); - } -} - -//______________________________________________________________________________ -Int_t TBufferFile::WriteFastArray(void **start, const TClass *cl, Int_t n, - Bool_t isPreAlloc, TMemberStreamer *streamer) -{ - // Write an array of object starting at the address '*start' and of length 'n' - // the objects in the array are of class 'cl' - // 'isPreAlloc' indicates whether the data member is marked with '->' - // Return: - // 0: success - // 2: truncated success (i.e actual class is missing. Only ptrClass saved.) - - // if isPreAlloc is true (data member has a ->) we can assume that the pointer - // is never 0. - - if (streamer) { - (*streamer)(*this,(void*)start,0); - return 0; - } - - int strInfo = 0; - - Int_t res = 0; - - if (!isPreAlloc) { - - for (Int_t j=0;j<n;j++) { - //must write StreamerInfo if pointer is null - if (!strInfo && !start[j] ) { - TStreamerInfo *info = (TStreamerInfo*)((TClass*)cl)->GetStreamerInfo(); - info->ForceWriteInfo((TFile *)GetParent()); - } - strInfo = 2003; - res |= WriteObjectAny(start[j],cl); - } - - } else { //case //-> in comment - - for (Int_t j=0;j<n;j++) { - if (!start[j]) start[j] = ((TClass*)cl)->New(); - ((TClass*)cl)->Streamer(start[j],*this); - } - - } - return res; -} - -//______________________________________________________________________________ -TObject *TBufferFile::ReadObject(const TClass * /*clReq*/) -{ - // Read object from I/O buffer. clReq is NOT used. - // The value returned is the address of the actual start in memory of - // the object. Note that if the actual class of the object does not - // inherit first from TObject, the type of the pointer is NOT 'TObject*'. - // [More accurately, the class needs to start with the TObject part, for - // the pointer to be a real TOject*]. - // We recommend using ReadObjectAny instead of ReadObject - - return (TObject*) ReadObjectAny(0); -} - -//______________________________________________________________________________ -void TBufferFile::SkipObjectAny() -{ - // Skip any kind of object from buffer - - UInt_t start, count; - ReadVersion(&start, &count); - SetBufferOffset(start+count+sizeof(UInt_t)); -} - -//______________________________________________________________________________ -void *TBufferFile::ReadObjectAny(const TClass *clCast) -{ - // Read object from I/O buffer. - // A typical use for this function is: - // MyClass *ptr = (MyClass*)b.ReadObjectAny(MyClass::Class()); - // I.e. clCast should point to a TClass object describing the class pointed - // to by your pointer. - // In case of multiple inheritance, the return value might not be the - // real beginning of the object in memory. You will need to use a - // dynamic_cast later if you need to retrieve it. - - R__ASSERT(IsReading()); - - // make sure fMap is initialized - InitMap(); - - // before reading object save start position - UInt_t startpos = UInt_t(fBufCur-fBuffer); - - // attempt to load next object as TClass clCast - UInt_t tag; // either tag or byte count - TClass *clRef = ReadClass(clCast, &tag); - Int_t baseOffset = 0; - if (clRef && (clRef!=(TClass*)(-1)) && clCast) { - //baseOffset will be -1 if clRef does not inherit from clCast. - baseOffset = clRef->GetBaseClassOffset(clCast); - if (baseOffset == -1) { - Error("ReadObject", "got object of wrong class! requested %s but got %s", - clCast->GetName(), clRef->GetName()); - - CheckByteCount(startpos, tag, (TClass*)0); // avoid mis-leading byte count error message - return 0; // We better return at this point - } - if (clCast->GetClassInfo() && !clRef->GetClassInfo()) { - //we cannot mix a compiled class with an emulated class in the inheritance - Error("ReadObject", "trying to read an emulated class (%s) to store in a compiled pointer (%s)", - clRef->GetName(),clCast->GetName()); - CheckByteCount(startpos, tag, (TClass*)0); // avoid mis-leading byte count error message - return 0; - } - } - - // check if object has not already been read - // (this can only happen when called via CheckObject()) - char *obj; - if (fVersion > 0) { - obj = (char *) fMap->GetValue(startpos+kMapOffset); - if (obj == (void*) -1) obj = 0; - if (obj) { - CheckByteCount(startpos, tag, (TClass*)0); - return (obj+baseOffset); - } - } - - // unknown class, skip to next object and return 0 obj - if (clRef == (TClass*) -1) { - if (fBufCur >= fBufMax) return 0; - if (fVersion > 0) - MapObject((TObject*) -1, startpos+kMapOffset); - else - MapObject((void*)0, 0, fMapCount); - CheckByteCount(startpos, tag, (TClass*)0); - return 0; - } - - if (!clRef) { - - // got a reference to an already read object - if (fVersion > 0) { - tag += fDisplacement; - tag = CheckObject(tag, clCast); - } else { - if (tag > (UInt_t)fMap->GetSize()) { - Error("ReadObject", "object tag too large, I/O buffer corrupted"); - return 0; - // exception - } - } - obj = (char *) fMap->GetValue(tag); - clRef = (TClass*) fClassMap->GetValue(tag); - - if (clRef && (clRef!=(TClass*)(-1)) && clCast) { - //baseOffset will be -1 if clRef does not inherit from clCast. - baseOffset = clRef->GetBaseClassOffset(clCast); - if (baseOffset == -1) { - Error("ReadObject", "Got object of wrong class (Got %s while expecting %s)", - clRef->GetName(),clCast->GetName()); - // exception - baseOffset = 0; - } - } - - // There used to be a warning printed here when: - // obj && isTObject && !((TObject*)obj)->IsA()->InheritsFrom(clReq) - // however isTObject was based on clReq (now clCast). - // If the test was to fail, then it is as likely that the object is not a TObject - // and then we have a potential core dump. - // At this point (missing clRef), we do NOT have enough information to really - // answer the question: is the object read of the type I requested. - - } else { - - // allocate a new object based on the class found - obj = (char *)clRef->New(); - if (!obj) { - Error("ReadObject", "could not create object of class %s", - clRef->GetName()); - // exception - return 0; - } - - // add to fMap before reading rest of object - if (fVersion > 0) - MapObject(obj, clRef, startpos+kMapOffset); - else - MapObject(obj, clRef, fMapCount); - - // let the object read itself - clRef->Streamer(obj, *this); - - CheckByteCount(startpos, tag, clRef); - } - - return obj+baseOffset; -} - -//______________________________________________________________________________ -void TBufferFile::WriteObject(const TObject *obj) -{ - // Write object to I/O buffer. - - WriteObjectAny(obj, TObject::Class()); -} - -//______________________________________________________________________________ -void TBufferFile::WriteObject(const void *actualObjectStart, const TClass *actualClass) -{ - // Write object to I/O buffer. - // This function assumes that the value of 'actualObjectStart' is the actual start of - // the object of class 'actualClass' - - R__ASSERT(IsWriting()); - - if (!actualObjectStart) { - - // save kNullTag to represent NULL pointer - *this << kNullTag; - - } else { - - // make sure fMap is initialized - InitMap(); - - ULong_t idx; - UInt_t slot; - ULong_t hash = Void_Hash(actualObjectStart); - - if ((idx = (ULong_t)fMap->GetValue(hash, (Long_t)actualObjectStart, slot)) != 0) { - - // truncation is OK the value we did put in the map is an 30-bit offset - // and not a pointer - UInt_t objIdx = UInt_t(idx); - - // save index of already stored object - *this << objIdx; - - } else { - - // A warning to let the user know it will need to change the class code - // to be able to read this back. - if (actualClass->HasDefaultConstructor() == 0) { - Warning("WriteObjectAny", "since %s has no public constructor\n" - "\twhich can be called without argument, objects of this class\n" - "\tcan not be read with the current library. You will need to\n" - "\tadd a default constructor before attempting to read it.", - actualClass->GetName()); - } - - // reserve space for leading byte count - UInt_t cntpos = UInt_t(fBufCur-fBuffer); - fBufCur += sizeof(UInt_t); - - // write class of object first - WriteClass(actualClass); - - // add to map before writing rest of object (to handle self reference) - // (+kMapOffset so it's != kNullTag) - //MapObject(actualObjectStart, actualClass, cntpos+kMapOffset); - UInt_t offset = cntpos+kMapOffset; - fMap->AddAt(slot, hash, (Long_t)actualObjectStart, offset); - // No need to keep track of the class in write mode - // fClassMap->Add(hash, (Long_t)obj, (Long_t)((TObject*)obj)->IsA()); - fMapCount++; - - ((TClass*)actualClass)->Streamer((void*)actualObjectStart,*this); - - // write byte count - SetByteCount(cntpos); - } - } -} - -namespace { - struct DynamicType { - // Helper class to enable typeid on any address - // Used in code similar to: - // typeid( * (DynamicType*) void_ptr ); - virtual ~DynamicType() {} - }; -} - -//______________________________________________________________________________ -Int_t TBufferFile::WriteObjectAny(const void *obj, const TClass *ptrClass) -{ - // Write object to I/O buffer. - // This function assumes that the value in 'obj' is the value stored in - // a pointer to a "ptrClass". The actual type of the object pointed to - // can be any class derived from "ptrClass". - // Return: - // 0: failure - // 1: success - // 2: truncated success (i.e actual class is missing. Only ptrClass saved.) - - if (!obj) { - WriteObject(0, 0); - return 1; - } - - if (!ptrClass) { - Error("WriteObjectAny", "ptrClass argument may not be 0"); - return 0; - } - - TClass *clActual = ptrClass->GetActualClass(obj); - - if (clActual==0) { - // The ptrClass is a class with a virtual table and we have no - // TClass with the actual type_info in memory. - - DynamicType* d_ptr = (DynamicType*)obj; - Warning("WriteObjectAny", - "An object of type %s (from type_info) passed through a %s pointer was truncated (due a missing dictionary)!!!", - typeid(*d_ptr).name(),ptrClass->GetName()); - WriteObject(obj, ptrClass); - return 2; - } else if (clActual && (clActual != ptrClass)) { - const char *temp = (const char*) obj; - temp -= clActual->GetBaseClassOffset(ptrClass); - WriteObject(temp, clActual); - return 1; - } else { - WriteObject(obj, ptrClass); - return 1; - } -} - -//______________________________________________________________________________ -TClass *TBufferFile::ReadClass(const TClass *clReq, UInt_t *objTag) -{ - // Read class definition from I/O buffer. clReq can be used to cross check - // if the actually read object is of the requested class. objTag is - // set in case the object is a reference to an already read object. - - R__ASSERT(IsReading()); - - // read byte count and/or tag (older files don't have byte count) - TClass *cl; - if (fBufCur < fBuffer || fBufCur > fBufMax) { - fBufCur = fBufMax; - cl = (TClass*)-1; - return cl; - } - UInt_t bcnt, tag, startpos = 0; - *this >> bcnt; - if (!(bcnt & kByteCountMask) || bcnt == kNewClassTag) { - tag = bcnt; - bcnt = 0; - } else { - fVersion = 1; - startpos = UInt_t(fBufCur-fBuffer); - *this >> tag; - } - - // in case tag is object tag return tag - if (!(tag & kClassMask)) { - if (objTag) *objTag = tag; - return 0; - } - - if (tag == kNewClassTag) { - - // got a new class description followed by a new object - // (class can be 0 if class dictionary is not found, in that - // case object of this class must be skipped) - cl = TClass::Load(*this); - - // add class to fMap for later reference - if (fVersion > 0) { - // check if class was already read - TClass *cl1 = (TClass *)fMap->GetValue(startpos+kMapOffset); - if (cl1 != cl) - MapObject(cl ? cl : (TObject*) -1, startpos+kMapOffset); - } else - MapObject(cl, fMapCount); - - } else { - - // got a tag to an already seen class - UInt_t clTag = (tag & ~kClassMask); - - if (fVersion > 0) { - clTag += fDisplacement; - clTag = CheckObject(clTag, clReq, kTRUE); - } else { - if (clTag == 0 || clTag > (UInt_t)fMap->GetSize()) { - Error("ReadClass", "illegal class tag=%d (0<tag<=%d), I/O buffer corrupted", - clTag, fMap->GetSize()); - // exception - } - } - - // class can be 0 if dictionary was not found - cl = (TClass *)fMap->GetValue(clTag); - } - - if (cl && clReq && !cl->InheritsFrom(clReq)) { - Error("ReadClass", "got wrong class: %s", cl->GetName()); - // exception - } - - // return bytecount in objTag - if (objTag) *objTag = (bcnt & ~kByteCountMask); - - // case of unknown class - if (!cl) cl = (TClass*)-1; - - return cl; -} - -//______________________________________________________________________________ -void TBufferFile::WriteClass(const TClass *cl) -{ - // Write class description to I/O buffer. - - R__ASSERT(IsWriting()); - - ULong_t idx; - ULong_t hash = Void_Hash(cl); - UInt_t slot; - - if ((idx = (ULong_t)fMap->GetValue(hash, (Long_t)cl,slot)) != 0) { - - // truncation is OK the value we did put in the map is an 30-bit offset - // and not a pointer - UInt_t clIdx = UInt_t(idx); - - // save index of already stored class - *this << (clIdx | kClassMask); - - } else { - - // offset in buffer where class info is written - UInt_t offset = UInt_t(fBufCur-fBuffer); - - // save new class tag - *this << kNewClassTag; - - // write class name - cl->Store(*this); - - // store new class reference in fMap (+kMapOffset so it's != kNullTag) - CheckCount(offset+kMapOffset); - fMap->AddAt(slot, hash, (Long_t)cl, offset+kMapOffset); - fMapCount++; - } -} - -//______________________________________________________________________________ -Version_t TBufferFile::ReadVersion(UInt_t *startpos, UInt_t *bcnt, const TClass *cl) -{ - // Read class version from I/O buffer. - - Version_t version; - - if (startpos && bcnt) { - // before reading object save start position - *startpos = UInt_t(fBufCur-fBuffer); - - // read byte count (older files don't have byte count) - // byte count is packed in two individual shorts, this to be - // backward compatible with old files that have at this location - // only a single short (i.e. the version) - union { - UInt_t cnt; - Version_t vers[2]; - } v; -#ifdef R__BYTESWAP - *this >> v.vers[1]; - *this >> v.vers[0]; -#else - *this >> v.vers[0]; - *this >> v.vers[1]; -#endif - - // no bytecount, backup and read version - if (!(v.cnt & kByteCountMask)) { - fBufCur -= sizeof(UInt_t); - v.cnt = 0; - } - *bcnt = (v.cnt & ~kByteCountMask); - *this >> version; - - } else { - - // not interested in byte count - *this >> version; - - // if this is a byte count, then skip next short and read version - if (version & kByteCountVMask) { - *this >> version; - *this >> version; - } - } - if (cl && cl->GetClassVersion() != 0) { - if (version <= 0) { - UInt_t checksum = 0; - *this >> checksum; - TStreamerInfo *vinfo = (TStreamerInfo*)cl->FindStreamerInfo(checksum); - if (vinfo) { - version = vinfo->GetClassVersion(); - } else { - // There are some cases (for example when the buffer was stored outside of - // a ROOT file) where we do not have a TStreamerInfo. If the checksum is - // the one from the current class, we can still assume that we can read - // the data so let use it. - if (checksum==cl->GetCheckSum() || checksum==cl->GetCheckSum(1)) { - version = cl->GetClassVersion(); - } else { - Error("ReadVersion", "Could not find the StreamerInfo with a checksum of %d for the class \"%s\" in %s.", - checksum, cl->GetName(), ((TFile*)fParent)->GetName()); - return 0; - } - } - } else if (version == 1 && fParent && ((TFile*)fParent)->GetVersion()<40000 ) { - // We could have a file created using a Foreign class before - // the introduction of the CheckSum. We need to check - if ((!cl->IsLoaded() || cl->IsForeign()) && - cl->GetStreamerInfos()->GetLast()>1 ) { - - const TList *list = ((TFile*)fParent)->GetStreamerInfoCache(); - const TStreamerInfo *local = (TStreamerInfo*)list->FindObject(cl->GetName()); - if ( local ) { - UInt_t checksum = local->GetCheckSum(); - TStreamerInfo *vinfo = (TStreamerInfo*)cl->FindStreamerInfo(checksum); - if (vinfo) { - version = vinfo->GetClassVersion(); - } else { - Error("ReadVersion", "Could not find the StreamerInfo with a checksum of %d for the class \"%s\" in %s.", - checksum, cl->GetName(), ((TFile*)fParent)->GetName()); - return 0; - } - } - else { - Error("ReadVersion", "Class %s not known to file %s.", - cl->GetName(), ((TFile*)fParent)->GetName()); - version = 0; - } - } - } - } - return version; -} - -//______________________________________________________________________________ -UInt_t TBufferFile::WriteVersion(const TClass *cl, Bool_t useBcnt) -{ - // Write class version to I/O buffer. - - UInt_t cntpos = 0; - if (useBcnt) { - // reserve space for leading byte count - cntpos = UInt_t(fBufCur-fBuffer); - fBufCur += sizeof(UInt_t); - } - - Version_t version = cl->GetClassVersion(); - if (version<=1 && cl->IsForeign()) { - *this << Version_t(0); - *this << cl->GetCheckSum(); - } else { - if (version > kMaxVersion) { - Error("WriteVersion", "version number cannot be larger than %hd)", - kMaxVersion); - version = kMaxVersion; - } - *this <<version; - } - - // return position where to store possible byte count - return cntpos; -} - -//______________________________________________________________________________ -UInt_t TBufferFile::WriteVersionMemberWise(const TClass *cl, Bool_t useBcnt) -{ - // Write class version to I/O buffer after setting the kStreamedMemberWise - // bit in the version number. - - UInt_t cntpos = 0; - if (useBcnt) { - // reserve space for leading byte count - cntpos = UInt_t(fBufCur-fBuffer); - fBufCur += sizeof(UInt_t); - } - - Version_t version = cl->GetClassVersion(); - if (version<=1 && cl->IsForeign()) { - Error("WriteVersionMemberWise", "Member-wise streaming of foreign collection not yet implemented!"); - *this << Version_t(0); - *this << cl->GetCheckSum(); - } else { - if (version > kMaxVersion) { - Error("WriteVersionMemberWise", "version number cannot be larger than %hd)", - kMaxVersion); - version = kMaxVersion; - } - version |= kStreamedMemberWise; - *this <<version; - } - - // return position where to store possible byte count - return cntpos; -} - -//______________________________________________________________________________ -void TBufferFile::StreamObject(void *obj, const type_info &typeinfo) -{ - // Stream an object given its C++ typeinfo information. - - TClass *cl = TClass::GetClass(typeinfo); - cl->Streamer(obj, *this); -} - -//______________________________________________________________________________ -void TBufferFile::StreamObject(void *obj, const char *className) -{ - // Stream an object given the name of its actual class. - - TClass *cl = TClass::GetClass(className); - cl->Streamer(obj, *this); -} - -//______________________________________________________________________________ -void TBufferFile::StreamObject(void *obj, const TClass *cl) -{ - // Stream an object given a pointer to its actual class. - - ((TClass*)cl)->Streamer(obj, *this); -} - -//______________________________________________________________________________ -void TBufferFile::StreamObject(TObject *obj) -{ - // Stream an object inheriting from TObject using its streamer. - - obj->Streamer(*this); -} - -//______________________________________________________________________________ -void TBufferFile::CheckCount(UInt_t offset) -{ - // Check if offset is not too large (< kMaxMapCount) when writing. - - if (IsWriting()) { - if (offset >= kMaxMapCount) { - Error("CheckCount", "buffer offset too large (larger than %d)", kMaxMapCount); - // exception - } - } -} - -//______________________________________________________________________________ -UInt_t TBufferFile::CheckObject(UInt_t offset, const TClass *cl, Bool_t readClass) -{ - // Check for object in the read map. If the object is 0 it still has to be - // read. Try to read it from the buffer starting at location offset. If the - // object is -1 then it really does not exist and we return 0. If the object - // exists just return the offset. - - // in position 0 we always have the reference to the null object - if (!offset) return offset; - - Long_t cli; - - if (readClass) { - if ((cli = fMap->GetValue(offset)) == 0) { - // No class found at this location in map. It might have been skipped - // as part of a skipped object. Try to explicitely read the class. - - // save fBufCur and set to place specified by offset (-kMapOffset-sizeof(bytecount)) - char *bufsav = fBufCur; - fBufCur = (char *)(fBuffer + offset-kMapOffset-sizeof(UInt_t)); - - TClass *c = ReadClass(cl); - if (c == (TClass*) -1) { - // mark class as really not available - fMap->Remove(offset); - fMap->Add(offset, -1); - offset = 0; - if (cl) - Warning("CheckObject", "reference to unavailable class %s," - " pointers of this type will be 0", cl->GetName()); - else - Warning("CheckObject", "reference to an unavailable class," - " pointers of that type will be 0"); - } - - fBufCur = bufsav; - - } else if (cli == -1) { - - // class really does not exist - return 0; - } - - } else { - - if ((cli = fMap->GetValue(offset)) == 0) { - // No object found at this location in map. It might have been skipped - // as part of a skipped object. Try to explicitely read the object. - - // save fBufCur and set to place specified by offset (-kMapOffset) - char *bufsav = fBufCur; - fBufCur = (char *)(fBuffer + offset-kMapOffset); - - TObject *obj = ReadObject(cl); - if (!obj) { - // mark object as really not available - fMap->Remove(offset); - fMap->Add(offset, -1); - Warning("CheckObject", "reference to object of unavailable class %s, offset=%d" - " pointer will be 0", cl ? cl->GetName() : "TObject",offset); - offset = 0; - } - - fBufCur = bufsav; - - } else if (cli == -1) { - - // object really does not exist - return 0; - } - - } - - return offset; -} - -//______________________________________________________________________________ -void TBufferFile::SetBuffer(void *buf, UInt_t newsiz, Bool_t adopt) -{ - // Sets a new buffer in an existing TBuffer object. If newsiz=0 then the - // new buffer is expected to have the same size as the previous buffer. - // The current buffer position is reset to the start of the buffer. - // If the TBuffer owned the previous buffer, it will be deleted prior - // to accepting the new buffer. By default the new buffer will be - // adopted unless adopt is false. - - if (fBuffer && TestBit(kIsOwner)) - delete [] fBuffer; - - if (adopt) - SetBit(kIsOwner); - else - ResetBit(kIsOwner); - - fBuffer = (char *)buf; - fBufCur = fBuffer; - if (newsiz > 0) fBufSize = newsiz; - fBufMax = fBuffer + fBufSize; -} - -//______________________________________________________________________________ -Bool_t TBufferFile::CheckObject(const TObject *obj) -{ - // Check if the specified object is already in the buffer. - // Returns kTRUE if object already in the buffer, kFALSE otherwise - // (also if obj is 0 or TBuffer not in writing mode). - - return CheckObject(obj, TObject::Class()); -} - -//______________________________________________________________________________ -Bool_t TBufferFile::CheckObject(const void *obj, const TClass *ptrClass) -{ - // Check if the specified object of the specified class is already in - // the buffer. Returns kTRUE if object already in the buffer, - // kFALSE otherwise (also if obj is 0 ). - - if (!obj || !fMap || !ptrClass) return kFALSE; - - TClass *clActual = ptrClass->GetActualClass(obj); - - ULong_t idx; - - if (clActual && (ptrClass != clActual)) { - const char *temp = (const char*) obj; - temp -= clActual->GetBaseClassOffset(ptrClass); - idx = (ULong_t)fMap->GetValue(Void_Hash(temp), (Long_t)temp); - } else { - idx = (ULong_t)fMap->GetValue(Void_Hash(obj), (Long_t)obj); - } - - return idx ? kTRUE : kFALSE; -} - -//______________________________________________________________________________ -void TBufferFile::SetPidOffset(UShort_t offset) -{ - // This offset is used when a key (or basket) is transfered from one - // file to the other. In this case the TRef and TObject might have stored a - // pid index (to retrieve TProcessIDs) which refered to their order on the original - // file, the fPidOffset is to be added to those values to correctly find the - // TProcessID. This fPidOffset needs to be increment if the key/basket is copied - // and need to be zero for new key/basket. - - fPidOffset = offset; -} - -//______________________________________________________________________________ -void TBufferFile::GetMappedObject(UInt_t tag, void* &ptr, TClass* &ClassPtr) const -{ - // Retrieve the object stored in the buffer's object map at 'tag' - // Set ptr and ClassPtr respectively to the address of the object and - // a pointer to its TClass. - - if (tag > (UInt_t)fMap->GetSize()) { - ptr = 0; - ClassPtr = 0; - } else { - ptr = (void*)fMap->GetValue(tag); - ClassPtr = (TClass*) fClassMap->GetValue(tag); - } -} - -//______________________________________________________________________________ -void TBufferFile::MapObject(const TObject *obj, UInt_t offset) -{ - // Add object to the fMap container. - // If obj is not 0 add object to the map (in read mode also add 0 objects to - // the map). This method may only be called outside this class just before - // calling obj->Streamer() to prevent self reference of obj, in case obj - // contains (via via) a pointer to itself. In that case offset must be 1 - // (default value for offset). - - if (IsWriting()) { - if (!fMap) InitMap(); - - if (obj) { - CheckCount(offset); - ULong_t hash = Void_Hash(obj); - fMap->Add(hash, (Long_t)obj, offset); - // No need to keep track of the class in write mode - // fClassMap->Add(hash, (Long_t)obj, (Long_t)((TObject*)obj)->IsA()); - fMapCount++; - } - } else { - if (!fMap || !fClassMap) InitMap(); - - fMap->Add(offset, (Long_t)obj); - fClassMap->Add(offset, - (obj && obj != (TObject*)-1) ? (Long_t)((TObject*)obj)->IsA() : 0); - fMapCount++; - } -} - -//______________________________________________________________________________ -void TBufferFile::MapObject(const void *obj, const TClass* cl, UInt_t offset) -{ - // Add object to the fMap container. - // If obj is not 0 add object to the map (in read mode also add 0 objects to - // the map). This method may only be called outside this class just before - // calling obj->Streamer() to prevent self reference of obj, in case obj - // contains (via via) a pointer to itself. In that case offset must be 1 - // (default value for offset). - - if (IsWriting()) { - if (!fMap) InitMap(); - - if (obj) { - CheckCount(offset); - ULong_t hash = Void_Hash(obj); - fMap->Add(hash, (Long_t)obj, offset); - // No need to keep track of the class in write mode - // fClassMap->Add(hash, (Long_t)obj, (Long_t)cl); - fMapCount++; - } - } else { - if (!fMap || !fClassMap) InitMap(); - - fMap->Add(offset, (Long_t)obj); - fClassMap->Add(offset, (Long_t)cl); - fMapCount++; - } -} - -//______________________________________________________________________________ -void TBufferFile::SetReadParam(Int_t mapsize) -{ - // Set the initial size of the map used to store object and class - // references during reading. The default size is kMapSize=503. - // Increasing the default has the benefit that when reading many - // small objects the map does not need to be resized too often - // (the system is always dynamic, even with the default everything - // will work, only the initial resizing will cost some time). - // This method can only be called directly after the creation of - // the TBuffer, before any reading is done. Globally this option - // can be changed using SetGlobalReadParam(). - - R__ASSERT(IsReading()); - R__ASSERT(fMap == 0); - - fMapSize = mapsize; -} - -//______________________________________________________________________________ -void TBufferFile::SetWriteParam(Int_t mapsize) -{ - // Set the initial size of the hashtable used to store object and class - // references during writing. The default size is kMapSize=503. - // Increasing the default has the benefit that when writing many - // small objects the hashtable does not get too many collisions - // (the system is always dynamic, even with the default everything - // will work, only a large number of collisions will cost performance). - // For optimal performance hashsize should always be a prime. - // This method can only be called directly after the creation of - // the TBuffer, before any writing is done. Globally this option - // can be changed using SetGlobalWriteParam(). - - R__ASSERT(IsWriting()); - R__ASSERT(fMap == 0); - - fMapSize = mapsize; -} - -//______________________________________________________________________________ -void TBufferFile::InitMap() -{ - // Create the fMap container and initialize them - // with the null object. - - if (IsWriting()) { - if (!fMap) { - fMap = new TExMap(fMapSize); - // No need to keep track of the class in write mode - // fClassMap = new TExMap(fMapSize); - fMapCount = 0; - } - } else { - if (!fMap) { - fMap = new TExMap(fMapSize); - fMap->Add(0, kNullTag); // put kNullTag in slot 0 - fMapCount = 1; - } else if (fMapCount==0) { - fMap->Add(0, kNullTag); // put kNullTag in slot 0 - fMapCount = 1; - } - if (!fClassMap) { - fClassMap = new TExMap(fMapSize); - fClassMap->Add(0, kNullTag); // put kNullTag in slot 0 - } - } -} - -//______________________________________________________________________________ -void TBufferFile::ResetMap() -{ - // Delete existing fMap and reset map counter. - - if (fMap) fMap->Delete(); - if (fClassMap) fClassMap->Delete(); - fMapCount = 0; - fDisplacement = 0; - - // reset user bits - ResetBit(kUser1); - ResetBit(kUser2); - ResetBit(kUser3); -} - -//______________________________________________________________________________ -Int_t TBufferFile::ReadBuf(void *buf, Int_t max) -{ - // Read max bytes from the I/O buffer into buf. The function returns - // the actual number of bytes read. - - R__ASSERT(IsReading()); - - if (max == 0) return 0; - - Int_t n = TMath::Min(max, (Int_t)(fBufMax - fBufCur)); - - memcpy(buf, fBufCur, n); - fBufCur += n; - - return n; -} - -//______________________________________________________________________________ -void TBufferFile::WriteBuf(const void *buf, Int_t max) -{ - // Write max bytes from buf into the I/O buffer. - - R__ASSERT(IsWriting()); - - if (max == 0) return; - - if (fBufCur + max > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+max)); - - memcpy(fBufCur, buf, max); - fBufCur += max; -} - -//______________________________________________________________________________ -Text_t *TBufferFile::ReadString(Text_t *s, Int_t max) -{ - // Read string from I/O buffer. String is read till 0 character is - // found or till max-1 characters are read (i.e. string s has max - // bytes allocated). If max = -1 no check on number of character is - // made, reading continues till 0 character is found. - - R__ASSERT(IsReading()); - - char ch; - Int_t nr = 0; - - if (max == -1) max = kMaxInt; - - while (nr < max-1) { - - *this >> ch; - - // stop when 0 read - if (ch == 0) break; - - s[nr++] = ch; - } - - s[nr] = 0; - return s; -} - -//______________________________________________________________________________ -void TBufferFile::WriteString(const Text_t *s) -{ - // Write string to I/O buffer. Writes string upto and including the - // terminating 0. - - WriteBuf(s, (strlen(s)+1)*sizeof(Text_t)); -} - -//______________________________________________________________________________ -TProcessID *TBufferFile::GetLastProcessID(TRefTable *reftable) const -{ - // Return the last TProcessID in the file. - - TFile *file = (TFile*)GetParent(); - // warn if the file contains > 1 PID (i.e. if we might have ambiguity) - if (file && !reftable->TestBit(TRefTable::kHaveWarnedReadingOld) && file->GetNProcessIDs()>1) { - Warning("ReadBuffer", "The file was written during several processes with an " - "older ROOT version; the TRefTable entries might be inconsistent."); - reftable->SetBit(TRefTable::kHaveWarnedReadingOld); - } - - // the file's last PID is the relevant one, all others might have their tables overwritten - TProcessID *fileProcessID = TProcessID::GetProcessID(0); - if (file && file->GetNProcessIDs() > 0) { - // take the last loaded PID - fileProcessID = (TProcessID *) file->GetListOfProcessIDs()->Last(); - } - return fileProcessID; -} - -//______________________________________________________________________________ -TProcessID *TBufferFile::ReadProcessID(UShort_t pidf) -{ - // The TProcessID with number pidf is read from file. - // If the object is not already entered in the gROOT list, it is added. - - TFile *file = (TFile*)GetParent(); - if (!file) { - if (!pidf) return TProcessID::GetPID(); //may happen when cloning an object - return 0; - } - return file->ReadProcessID(pidf); -} - -//______________________________________________________________________________ -UInt_t TBufferFile::GetTRefExecId() -{ - // Return the exec id stored in the current TStreamerInfo element. - // The execid has been saved in the unique id of the TStreamerElement - // being read by TStreamerElement::Streamer. - // The current element (fgElement) is set as a static global - // by TStreamerInfo::ReadBuffer (Clones) when reading this TRef. - - return TStreamerInfo::GetCurrentElement()->GetUniqueID(); -} - -//______________________________________________________________________________ -UShort_t TBufferFile::WriteProcessID(TProcessID *pid) -{ - // Check if the ProcessID pid is already in the file. - // If not, add it and return the index number in the local file list. - - TFile *file = (TFile*)GetParent(); - return file->WriteProcessID(pid); -} - -//---- Utilities for TClonesArray ---------------------------------------------- - -//______________________________________________________________________________ -void TBufferFile::ForceWriteInfo(TClonesArray *a) -{ - // Make sure TStreamerInfo is not optimized, otherwise it will not be - // possible to support schema evolution in read mode. - // In case the StreamerInfo has already been computed and optimized, - // one must disable the option BypassStreamer. - - Bool_t optim = TStreamerInfo::CanOptimize(); - if (optim) TStreamerInfo::Optimize(kFALSE); - TStreamerInfo *sinfo = (TStreamerInfo*)a->GetClass()->GetStreamerInfo(); - sinfo->ForceWriteInfo((TFile *)GetParent()); - if (optim) TStreamerInfo::Optimize(kTRUE); - if (sinfo->IsOptimized()) a->BypassStreamer(kFALSE); -} - -//______________________________________________________________________________ -Int_t TBufferFile::ReadClones(TClonesArray *a, Int_t nobjects) -{ - // Interface to TStreamerInfo::ReadBufferClones. - - char **arr = (char **)a->GetObjectRef(0); - //a->GetClass()->GetStreamerInfo()->ReadBufferClones(*this,a,nobjects,-1,0); - TStreamerInfo *info = (TStreamerInfo*)a->GetClass()->GetStreamerInfo(); - return info->ReadBuffer(*this,arr,-1,nobjects,0,1); -} - -//______________________________________________________________________________ -Int_t TBufferFile::WriteClones(TClonesArray *a, Int_t nobjects) -{ - // Interface to TStreamerInfo::WriteBufferClones. - - char **arr = reinterpret_cast<char**>(a->GetObjectRef(0)); - //a->GetClass()->GetStreamerInfo()->WriteBufferClones(*this,(TClonesArray*)a,nobjects,-1,0); - TStreamerInfo *info = (TStreamerInfo*)a->GetClass()->GetStreamerInfo(); - return info->WriteBufferAux(*this,arr,-1,nobjects,0,1); -} - -//______________________________________________________________________________ -Int_t TBufferFile::ReadClassEmulated(TClass *cl, void *object) -{ - // Read emulated class. - - UInt_t start,count; - //We assume that the class was written with a standard streamer - //We attempt to recover if a version count was not written - Version_t v = ReadVersion(&start,&count); - if (count) { - TStreamerInfo *sinfo = (TStreamerInfo*)cl->GetStreamerInfo(v); - sinfo->ReadBuffer(*this,(char**)&object,-1); - if (sinfo->IsRecovered()) count=0; - CheckByteCount(start,count,cl); - } else { - SetBufferOffset(start); - ((TStreamerInfo*)cl->GetStreamerInfo())->ReadBuffer(*this,(char**)&object,-1); - } - return 0; -} - -//______________________________________________________________________________ -Int_t TBufferFile::ReadClassBuffer(TClass *cl, void *pointer, Int_t version, UInt_t start, UInt_t count) -{ - // Function called by the Streamer functions to deserialize information - // from buffer b into object at p. - // This function assumes that the class version and the byte count information - // have been read. - // version is the version number of the class - // start is the starting position in the buffer b - // count is the number of bytes for this object in the buffer - - //the StreamerInfo should exist at this point - TObjArray *infos = cl->GetStreamerInfos(); - Int_t ninfos = infos->GetSize(); - if (version < 0 || version >= ninfos) { - Error("ReadBuffer1","class: %s, attempting to access a wrong version: %d",cl->GetName(),version); - CheckByteCount(start,count,cl); - return 0; - } - TStreamerInfo *sinfo = (TStreamerInfo*)infos->At(version); - if (sinfo == 0) { - cl->BuildRealData(pointer); - sinfo = new TStreamerInfo(cl,""); - infos->AddAtAndExpand(sinfo,version); - if (gDebug > 0) printf("Creating StreamerInfo for class: %s, version: %d\n",cl->GetName(),version); - sinfo->Build(); - //} else if (!fRealData) { - } else if (!sinfo->GetOffsets()) { - cl->BuildRealData(pointer); - sinfo->BuildOld(); - } - - //deserialize the object - sinfo->ReadBuffer(*this, (char**)&pointer,-1); - if (sinfo->IsRecovered()) count=0; - - //check that the buffer position corresponds to the byte count - CheckByteCount(start,count,cl); - return 0; -} - -//______________________________________________________________________________ -Int_t TBufferFile::ReadClassBuffer(TClass *cl, void *pointer) -{ - // Function called by the Streamer functions to deserialize information - // from buffer b into object at p. - - // read the class version from the buffer - UInt_t R__s, R__c; - Version_t version = ReadVersion(&R__s, &R__c, cl); - TFile *file = (TFile*)GetParent(); - if (file && file->GetVersion() < 30000) version = -1; //This is old file - - //the StreamerInfo should exist at this point - TObjArray *infos = cl->GetStreamerInfos(); - Int_t ninfos = infos->GetSize(); - if (version < -1 || version >= ninfos) { - Error("ReadBuffer2","class: %s, attempting to access a wrong version: %d, object skipped at offset %d", - cl->GetName(),version,Length()); - CheckByteCount(R__s, R__c,cl); - return 0; - } - TStreamerInfo *sinfo = (TStreamerInfo*)infos->At(version); - if (sinfo == 0) { - cl->BuildRealData(pointer); - sinfo = new TStreamerInfo(cl,""); - infos->AddAtAndExpand(sinfo,version); - if (gDebug > 0) printf("Creating StreamerInfo for class: %s, version: %d\n",cl->GetName(),version); - sinfo->Build(); - - if (version == -1) sinfo->BuildEmulated((TFile *)GetParent()); - - } else if (!sinfo->GetOffsets()) { - cl->BuildRealData(pointer); - sinfo->BuildOld(); - } - - //deserialize the object - sinfo->ReadBuffer(*this, (char**)&pointer,-1); - if (sinfo->IsRecovered()) R__c=0; - - //check that the buffer position corresponds to the byte count - CheckByteCount(R__s, R__c,cl); - - if (gDebug > 2) printf(" ReadBuffer for class: %s has read %d bytes\n",cl->GetName(),R__c); - - return 0; -} - -//______________________________________________________________________________ -Int_t TBufferFile::WriteClassBuffer(TClass *cl, void *pointer) -{ - // Function called by the Streamer functions to serialize object at p - // to buffer b. The optional argument info may be specified to give an - // alternative StreamerInfo instead of using the default StreamerInfo - // automatically built from the class definition. - // For more information, see class TStreamerInfo. - - //build the StreamerInfo if first time for the class - TStreamerInfo *sinfo = (TStreamerInfo*)cl->GetCurrentStreamerInfo(); - if (sinfo == 0) { - cl->BuildRealData(pointer); - sinfo = new TStreamerInfo(cl,""); - cl->SetCurrentStreamerInfo(sinfo); - cl->GetStreamerInfos()->AddAtAndExpand(sinfo,cl->GetClassVersion()); - if (gDebug > 0) printf("Creating StreamerInfo for class: %s, version: %d\n",cl->GetName(),cl->GetClassVersion()); - sinfo->Build(); - } else if (!sinfo->GetOffsets()) { - cl->BuildRealData(pointer); - sinfo->BuildOld(); - } - // This is necessary because it might be induced later anyway if an object - // of the same type is either a base class or a pointer data member of this - // class of any contained objects. - if (sinfo->IsOptimized() && !TVirtualStreamerInfo::CanOptimize()) sinfo->Compile(); - - //write the class version number and reserve space for the byte count - UInt_t R__c = WriteVersion(cl, kTRUE); - - //serialize the object - sinfo->WriteBufferAux(*this,(char**)&pointer,-1,1,0,0); // NOTE: expanded - - //write the byte count at the start of the buffer - SetByteCount(R__c, kTRUE); - - if (gDebug > 2) printf(" WriteBuffer for class: %s version %d has written %d bytes\n",cl->GetName(),cl->GetClassVersion(),R__c); - return 0; -} - -//---- Static functions -------------------------------------------------------- - -//______________________________________________________________________________ -void TBufferFile::SetGlobalReadParam(Int_t mapsize) -{ - // Set the initial size of the map used to store object and class - // references during reading. The default size is kMapSize=503. - // Increasing the default has the benefit that when reading many - // small objects the array does not need to be resized too often - // (the system is always dynamic, even with the default everything - // will work, only the initial resizing will cost some time). - // Per TBuffer object this option can be changed using SetReadParam(). - - fgMapSize = mapsize; -} - -//______________________________________________________________________________ -void TBufferFile::SetGlobalWriteParam(Int_t mapsize) -{ - // Set the initial size of the hashtable used to store object and class - // references during writing. The default size is kMapSize=503. - // Increasing the default has the benefit that when writing many - // small objects the hashtable does not get too many collisions - // (the system is always dynamic, even with the default everything - // will work, only a large number of collisions will cost performance). - // For optimal performance hashsize should always be a prime. - // Per TBuffer object this option can be changed using SetWriteParam(). - - fgMapSize = mapsize; -} - -//______________________________________________________________________________ -Int_t TBufferFile::GetGlobalReadParam() -{ - // Get default read map size. - - return fgMapSize; -} - -//______________________________________________________________________________ -Int_t TBufferFile::GetGlobalWriteParam() -{ - // Get default write map size. - - return fgMapSize; -} diff --git a/base/src/TDirectoryFile.cxx b/base/src/TDirectoryFile.cxx deleted file mode 100644 index d19ea00cc174c6bfbb11813bd70cc50ebb18ff3d..0000000000000000000000000000000000000000 --- a/base/src/TDirectoryFile.cxx +++ /dev/null @@ -1,1876 +0,0 @@ -// @(#)root/base:$Name: $:$Id: TDirectoryFile.cxx,v 1.6 2007/01/31 13:31:49 brun Exp $ -// Author: Rene Brun 22/01/2007 - -/************************************************************************* - * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -#include "Riostream.h" -#include "Strlen.h" -#include "TDirectoryFile.h" -#include "TFile.h" -#include "TBufferFile.h" -#include "TMapFile.h" -#include "TClassTable.h" -#include "TInterpreter.h" -#include "THashList.h" -#include "TBrowser.h" -#include "TFree.h" -#include "TKey.h" -#include "TStreamerInfo.h" -#include "TROOT.h" -#include "TError.h" -#include "Bytes.h" -#include "TClass.h" -#include "TRegexp.h" -#include "TSystem.h" -#include "TStreamerElement.h" -#include "TProcessUUID.h" -#include "TVirtualMutex.h" - -const UInt_t kIsBigFile = BIT(16); -const Int_t kMaxLen = 2048; - -//______________________________________________________________________________ -//Begin_Html -/* -<img src="gif/tdirectory_classtree.gif"> -*/ -//End_Html - -ClassImp(TDirectoryFile) - -//______________________________________________________________________________ -// -// A ROOT file is structured in Directories (like a file system). -// Each Directory has a list of Keys (see TKeys) and a list of objects -// in memory. A Key is a small object that describes the type and location -// of a persistent object in a file. The persistent object may be a directory. -//Begin_Html -/* -<img src="gif/fildir.gif"> -*/ -//End_Html -// -// The structure of a file is shown in TFile::TFile -// - -//______________________________________________________________________________ -TDirectoryFile::TDirectoryFile() : TDirectory() - , fModified(kFALSE), fWritable(kFALSE), fNbytesKeys(0), fNbytesName(0) - , fBufferSize(0), fSeekDir(0), fSeekParent(0), fSeekKeys(0) - , fFile(0), fKeys(0) -{ -//*-*-*-*-*-*-*-*-*-*-*-*Directory default constructor-*-*-*-*-*-*-*-*-*-*-*-* -//*-* ============================= -} - -//______________________________________________________________________________ -TDirectoryFile::TDirectoryFile(const char *name, const char *title, Option_t *classname, TDirectory* initMotherDir) - : TDirectory(name, title,classname,initMotherDir) -{ -//*-*-*-*-*-*-*-*-*-*-*-* Create a new DirectoryFile *-*-*-*-*-*-*-*-*-*-*-*-*-* -//*-* ========================== -// A new directory with name,title is created in the current directory -// The directory header information is immediatly saved on the file -// A new key is added in the parent directory -// -// When this constructor is called from a class directly derived -// from TDirectoryFile, the third argument classname MUST be specified. -// In this case, classname must be the name of the derived class. -// -// Note that the directory name cannot contain slashes. -// - if (initMotherDir==0) initMotherDir = gDirectory; - - if (strchr(name,'/')) { - ::Error("TDirectoryFile","directory name (%s) cannot contain a slash", name); - gDirectory = 0; - return; - } - if (strlen(GetName()) == 0) { - ::Error("TDirectoryFile","directory name cannot be \"\""); - gDirectory = 0; - return; - } - - Build(initMotherDir ? initMotherDir->GetFile() : 0, initMotherDir); - - TDirectory* motherdir = GetMotherDir(); - TFile* f = GetFile(); - - if ((motherdir==0) || (f==0)) return; - if (!f->IsWritable()) return; //*-* in case of a directory in memory - if (motherdir->GetKey(name)) { - Error("TDirectoryFile","An object with name %s exists already", name); - return; - } - TClass *cl = IsA(); - if (strlen(classname) != 0) cl = TClass::GetClass(classname); - - if (!cl) { - Error("TDirectoryFile","Invalid class name: %s",classname); - return; - } - fBufferSize = 0; - fWritable = kTRUE; - - if (f->IsBinary()) { - fSeekParent = f->GetSeekDir(); - Int_t nbytes = TDirectoryFile::Sizeof(); - TKey *key = new TKey(fName,fTitle,cl,nbytes,motherdir); - fNbytesName = key->GetKeylen(); - fSeekDir = key->GetSeekKey(); - if (fSeekDir == 0) return; - char *buffer = key->GetBuffer(); - TDirectoryFile::FillBuffer(buffer); - Int_t cycle = motherdir->AppendKey(key); - key->WriteFile(cycle); - } else { - fSeekParent = 0; - fNbytesName = 0; - fSeekDir = f->DirCreateEntry(this); - if (fSeekDir == 0) return; - } - - fModified = kFALSE; - R__LOCKGUARD2(gROOTMutex); - gROOT->GetUUIDs()->AddUUID(fUUID,this); -} - -//______________________________________________________________________________ -TDirectoryFile::TDirectoryFile(const TDirectoryFile & directory) : TDirectory(directory) -{ - // Copy constructor. - ((TDirectoryFile&)directory).Copy(*this); -} - -//______________________________________________________________________________ -TDirectoryFile::~TDirectoryFile() -{ - // -- Destructor. - - if (fKeys) { - fKeys->Delete("slow"); - SafeDelete(fKeys); - } - - if (gDirectory == this) { - if (gFile != this) { - gFile->cd(); - } else { - gDirectory = gROOT; - gFile = 0; - } - } - - TDirectory* mom = GetMotherDir(); - - if (mom) { - mom->GetList()->Remove(this); - } - - if (gDebug) { - Info("~TDirectoryFile", "dtor called for %s", GetName()); - } -} - -//______________________________________________________________________________ -void TDirectoryFile::Append(TObject *obj) -{ - // Append object to this directory. - - if (obj == 0 || fList == 0) return; - fList->Add(obj); - obj->SetBit(kMustCleanup); - if (!fMother) return; - if (fMother->IsA() == TMapFile::Class()) { - TMapFile *mfile = (TMapFile*)fMother; - mfile->Add(obj); - } -} - -//______________________________________________________________________________ -Int_t TDirectoryFile::AppendKey(TKey *key) -{ -//*-*-*-*-*-*-*Insert key in the linked list of keys of this directory*-*-*-* -//*-* ======================================================= - - fModified = kTRUE; - - key->SetMotherDir(this); - - // This is a fast hash lookup in case the key does not already exist - TKey *oldkey = (TKey*)fKeys->FindObject(key->GetName()); - if (!oldkey) { - fKeys->Add(key); - return 1; - } - - // If the key name already exists we have to make a scan for it - // and insert the new key ahead of the current one - TObjLink *lnk = fKeys->FirstLink(); - while (lnk) { - oldkey = (TKey*)lnk->GetObject(); - if (!strcmp(oldkey->GetName(), key->GetName())) - break; - lnk = lnk->Next(); - } - - fKeys->AddBefore(lnk, key); - return oldkey->GetCycle() + 1; -} - -//______________________________________________________________________________ -void TDirectoryFile::Browse(TBrowser *b) -{ - // Browse the content of the directory. - - Char_t name[kMaxLen]; - - if (b) { - TObject *obj = 0; - TIter nextin(fList); - TKey *key = 0, *keyo = 0; - TIter next(fKeys); - - cd(); - - //Add objects that are only in memory - while ((obj = nextin())) { - if (fKeys->FindObject(obj->GetName())) continue; - b->Add(obj, obj->GetName()); - } - - //Add keys - while ((key = (TKey *) next())) { - int skip = 0; - if (!keyo || (keyo && strcmp(keyo->GetName(), key->GetName()))) { - skip = 0; - obj = fList->FindObject(key->GetName()); - - if (obj) { - sprintf(name, "%s", obj->GetName()); - b->Add(obj, name); - if (obj->IsFolder()) skip = 1; - } - } - - if (!skip) { - sprintf(name, "%s;%d", key->GetName(), key->GetCycle()); - b->Add(key, name); - } - - keyo = key; - } - } -} - -//______________________________________________________________________________ -void TDirectoryFile::Build(TFile* motherFile, TDirectory* motherDir) -{ -//*-*-*-*-*-*-*-*-*-*-*-*Initialise directory to defaults*-*-*-*-*-*-*-*-*-* -//*-* ================================ - - // If directory is created via default ctor (when dir is read from file) - // don't add it here to the directory since its name is not yet known. - // It will be added to the directory in TKey::ReadObj(). - - if (motherDir && strlen(GetName()) != 0) motherDir->Append(this); - - fModified = kTRUE; - fWritable = kFALSE; - fDatimeC.Set(); - fDatimeM.Set(); - fNbytesKeys = 0; - fSeekDir = 0; - fSeekParent = 0; - fSeekKeys = 0; - fList = new THashList(100,50); - fKeys = new THashList(100,50); - fMother = motherDir; - fFile = motherFile ? motherFile : gFile; - SetBit(kCanDelete); -} - -//______________________________________________________________________________ -Bool_t TDirectoryFile::cd(const char *path) -{ - // Change current directory to "this" directory . Using path one can - // change the current directory to "path". The absolute path syntax is: - // file.root:/dir1/dir2 - // where file.root is the file and /dir1/dir2 the desired subdirectory - // in the file. Relative syntax is relative to "this" directory. E.g: - // ../aa. Returns kTRUE in case of success. - - Bool_t ok = TDirectory::cd(path); - if (ok) gFile = fFile; - return ok; -} - -//______________________________________________________________________________ -TObject *TDirectoryFile::CloneObject(const TObject *obj) -{ - // Make a clone of an object using the Streamer facility. - // If the object derives from TNamed, this function is called - // by TNamed::Clone. TNamed::Clone uses the optional argument newname to set - // a new name to the newly created object. - - // if no default ctor return immediately (error issued by New()) - TObject *newobj = (TObject *)obj->IsA()->New(); - if (!newobj) return 0; - - //create a buffer where the object will be streamed - TFile *filsav = gFile; - gFile = 0; - const Int_t bufsize = 10000; - TBuffer *buffer = new TBufferFile(TBuffer::kWrite,bufsize); - buffer->MapObject(obj); //register obj in map to handle self reference - ((TObject*)obj)->Streamer(*buffer); - - // read new object from buffer - buffer->SetReadMode(); - buffer->ResetMap(); - buffer->SetBufferOffset(0); - buffer->MapObject(newobj); //register obj in map to handle self reference - newobj->Streamer(*buffer); - newobj->ResetBit(kIsReferenced); - newobj->ResetBit(kCanDelete); - gFile = filsav; - - delete buffer; - return newobj; -} - -//______________________________________________________________________________ -TObject *TDirectoryFile::FindObjectAnyFile(const char *name) const -{ - // Scan the memory lists of all files for an object with name - - TFile *f; - TIter next(gROOT->GetListOfFiles()); - while ((f = (TFile*)next())) { - TObject *obj = f->GetList()->FindObject(name); - if (obj) return obj; - } - return 0; -} - - - -//______________________________________________________________________________ -TDirectory *TDirectoryFile::GetDirectory(const char *apath, - Bool_t printError, const char *funcname) -{ - // Find a directory using apath. - // It apath is null or empty, returns "this" directory. - // Otherwie use apath to find a directory. - // The absolute path syntax is: - // file.root:/dir1/dir2 - // where file.root is the file and /dir1/dir2 the desired subdirectory - // in the file. Relative syntax is relative to "this" directory. E.g: - // ../aa. - // Returns 0 in case path does not exist. - // If printError is true, use Error with 'funcname' to issue an error message. - - Int_t nch = 0; - if (apath) nch = strlen(apath); - if (!nch) { - return this; - } - - if (funcname==0 || strlen(funcname)==0) funcname = "GetDirectory"; - - TDirectory *result = this; - - char *path = new char[nch+1]; path[0] = 0; - if (nch) strcpy(path,apath); - char *s = (char*)strchr(path, ':'); - if (s) { - *s = '\0'; - R__LOCKGUARD2(gROOTMutex); - TDirectory *f = (TDirectory *)gROOT->GetListOfFiles()->FindObject(path); - if (!f && !strcmp(gROOT->GetName(), path)) f = gROOT; - if (s) *s = ':'; - if (f) { - result = f; - if (s && *(s+1)) result = f->GetDirectory(s+1,printError,funcname); - delete [] path; return result; - } else { - if (printError) Error(funcname, "No such file %s", path); - delete [] path; return 0; - } - } - - // path starts with a slash (assumes current file) - if (path[0] == '/') { - TDirectory *td = fFile; - if (!fFile) td = gROOT; - result = td->GetDirectory(path+1,printError,funcname); - delete [] path; return result; - } - - TObject *obj; - char *slash = (char*)strchr(path,'/'); - if (!slash) { // we are at the lowest level - if (!strcmp(path, "..")) { - result = GetMotherDir(); - delete [] path; return result; - } - obj = Get(path); - if (!obj) { - if (printError) Error(funcname,"Unknown directory %s", path); - delete [] path; return 0; - } - - //Check return object is a directory - if (!obj->InheritsFrom(TDirectory::Class())) { - if (printError) Error(funcname,"Object %s is not a directory", path); - delete [] path; return 0; - } - delete [] path; return (TDirectory*)obj; - } - - char subdir[kMaxLen]; - strcpy(subdir,path); - slash = (char*)strchr(subdir,'/'); - *slash = 0; - //Get object with path from current directory/file - if (!strcmp(subdir, "..")) { - TDirectory* mom = GetMotherDir(); - if (mom) - result = mom->GetDirectory(slash+1,printError,funcname); - delete [] path; return result; - } - obj = Get(subdir); - if (!obj) { - if (printError) Error(funcname,"Unknown directory %s", subdir); - delete [] path; return 0; - } - - //Check return object is a directory - if (!obj->InheritsFrom(TDirectory::Class())) { - if (printError) Error(funcname,"Object %s is not a directory", subdir); - delete [] path; return 0; - } - result = ((TDirectory*)obj)->GetDirectory(slash+1,printError,funcname); - delete [] path; return result; -} - -//______________________________________________________________________________ -void TDirectoryFile::Close(Option_t *) -{ - // -- Delete all objects from memory and directory structure itself. - - if (!fList) { - return; - } - - // Save the directory key list and header - Save(); - - Bool_t fast = kTRUE; - TObjLink *lnk = fList->FirstLink(); - while (lnk) { - if (lnk->GetObject()->IsA() == TDirectoryFile::Class()) {fast = kFALSE;break;} - lnk = lnk->Next(); - } - // Delete objects from directory list, this in turn, recursively closes all - // sub-directories (that were allocated on the heap) - // if this dir contains subdirs, we must use the slow option for Delete! - // we must avoid "slow" as much as possible, in particular Delete("slow") - // with a large number of objects (eg >10^5) would take for ever. - if (fast) fList->Delete(); - else fList->Delete("slow"); - - // Delete keys from key list (but don't delete the list header) - if (fKeys) { - fKeys->Delete("slow"); - } - - if (gDirectory == this) { - TDirectory *cursav = GetMotherDir(); - if (cursav && cursav != this) { - cursav->cd(); - } else { - gFile = 0; - gDirectory = gROOT; - } - } -} - -//______________________________________________________________________________ -void TDirectoryFile::Delete(const char *namecycle) -{ -//*-*-*-*-*-*-*-* Delete Objects or/and keys in a directory *-*-*-*-*-*-*-* -//*-* ========================================= -// namecycle has the format name;cycle -// namecycle = "" same as namecycle ="T*" -// name = * means all -// cycle = * means all cycles (memory and keys) -// cycle = "" or cycle = 9999 ==> apply to a memory object -// When name=* use T* to delete subdirectories also -// -// To delete one directory, you must specify the directory cycle, -// eg. file.Delete("dir1;1"); -// -// examples: -// foo : delete object named foo in memory -// foo* : delete all objects with a name starting with foo -// foo;1 : delete cycle 1 of foo on file -// foo;* : delete all cycles of foo on file and also from memory -// *;2 : delete all objects on file having the cycle 2 -// *;* : delete all objects from memory and file -// T*;* : delete all objects from memory and file and all subdirectories -// - - if (gDebug) - Info("Delete","Call for this = %s namecycle = %s", - GetName(), (namecycle ? namecycle : "null")); - - TDirectory::TContext ctxt(gDirectory, this); - Short_t cycle; - char name[kMaxLen]; - DecodeNameCycle(namecycle, name, cycle); - - Int_t deleteall = 0; - Int_t deletetree = 0; - if(strcmp(name,"*") == 0) deleteall = 1; - if(strcmp(name,"*T") == 0){ deleteall = 1; deletetree = 1;} - if(strcmp(name,"T*") == 0){ deleteall = 1; deletetree = 1;} - if(strlen(namecycle) == 0){ deleteall = 1; deletetree = 1;} - TRegexp re(name,kTRUE); - TString s; - Int_t deleteOK = 0; - -//*-*---------------------Case of Object in memory--------------------- -// ======================== - if (cycle >= 9999 ) { - TNamed *idcur; - TIter next(fList); - while ((idcur = (TNamed *) next())) { - deleteOK = 0; - s = idcur->GetName(); - if (deleteall || s.Index(re) != kNPOS) { - deleteOK = 1; - if (idcur->IsA() == TDirectoryFile::Class()) { - deleteOK = 2; - if (!deletetree && deleteall) deleteOK = 0; - } - } - if (deleteOK != 0) { - fList->Remove(idcur); - if (deleteOK==2) { - // read subdirectories to correctly delete them - if (deletetree) - ((TDirectory*) idcur)->ReadAll("dirs"); - idcur->Delete(deletetree ? "T*;*" : "*"); - delete idcur; - } else - idcur->Delete(name); - } - } -// if (deleteOK == 2) { -// Info("Delete","Dir:%x %s", fList->FindObject(name), name); -// delete fList->FindObject(name); //deleting a TDirectory -// } - } -//*-*---------------------Case of Key--------------------- -// =========== - if (cycle != 9999 ) { - if (IsWritable()) { - TKey *key; - TIter nextkey(GetListOfKeys()); - while ((key = (TKey *) nextkey())) { - deleteOK = 0; - s = key->GetName(); - if (deleteall || s.Index(re) != kNPOS) { - if (cycle == key->GetCycle()) deleteOK = 1; - if (cycle > 9999) deleteOK = 1; - //if (!strcmp(key->GetClassName(),"TDirectory")) { - if (strstr(key->GetClassName(),"TDirectory")) { - deleteOK = 2; - if (!deletetree && deleteall) deleteOK = 0; - if (cycle == key->GetCycle()) deleteOK = 2; - } - } - if (deleteOK) { - if (deleteOK==2) { - // read directory with subdirectories to correctly delete and free key structure - TDirectory* dir = GetDirectory(key->GetName(), kTRUE, "Delete"); - if (dir!=0) { - dir->Delete("T*;*"); - fList->Remove(dir); - delete dir; - } - } - - key->Delete(); - fKeys->Remove(key); - fModified = kTRUE; - delete key; - } - } - TFile* f = GetFile(); - if (fModified && (f!=0)) { - WriteKeys(); //*-* Write new keys structure - WriteDirHeader(); //*-* Write new directory header - f->WriteFree(); //*-* Write new free segments list - f->WriteHeader(); //*-* Write new file header - } - } - } -} - -//______________________________________________________________________________ -void TDirectoryFile::FillBuffer(char *&buffer) -{ -//*-*-*-*-*-*-*-*-*-*-*-*Encode directory header into output buffer*-*-*-*-*-* -//*-* ========================================= - Version_t version = TDirectoryFile::Class_Version(); - if (fSeekKeys > TFile::kStartBigFile) version += 1000; - tobuf(buffer, version); - fDatimeC.FillBuffer(buffer); - fDatimeM.FillBuffer(buffer); - tobuf(buffer, fNbytesKeys); - tobuf(buffer, fNbytesName); - if (version > 1000) { - tobuf(buffer, fSeekDir); - tobuf(buffer, fSeekParent); - tobuf(buffer, fSeekKeys); - } else { - tobuf(buffer, (Int_t)fSeekDir); - tobuf(buffer, (Int_t)fSeekParent); - tobuf(buffer, (Int_t)fSeekKeys); - } - fUUID.FillBuffer(buffer); - if (fFile && fFile->GetVersion() < 40000) return; - if (version <=1000) for (Int_t i=0;i<3;i++) tobuf(buffer,Int_t(0)); -} - -//______________________________________________________________________________ -TKey *TDirectoryFile::FindKey(const char *keyname) const -{ - // Find key with name keyname in the current directory - - Short_t cycle; - char name[kMaxLen]; - - DecodeNameCycle(keyname, name, cycle); - return GetKey(name,cycle); -} - -//______________________________________________________________________________ -TKey *TDirectoryFile::FindKeyAny(const char *keyname) const -{ - // Find key with name keyname in the current directory or - // its subdirectories. - // NOTE that If a key is found, the directory containing the key becomes - // the current directory - - TDirectory *dirsav = gDirectory; - Short_t cycle; - char name[kMaxLen]; - - DecodeNameCycle(keyname, name, cycle); - - TIter next(GetListOfKeys()); - TKey *key; - while ((key = (TKey *) next())) { - if (!strcmp(name, key->GetName())) - if ((cycle == 9999) || (cycle >= key->GetCycle())) { - ((TDirectory*)this)->cd(); // may be we should not make cd ??? - return key; - } - } - //try with subdirectories - next.Reset(); - while ((key = (TKey *) next())) { - //if (!strcmp(key->GetClassName(),"TDirectory")) { - if (strstr(key->GetClassName(),"TDirectory")) { - TDirectory* subdir = - ((TDirectory*)this)->GetDirectory(key->GetName(), kTRUE, "FindKeyAny"); - TKey *k = (subdir!=0) ? subdir->FindKeyAny(keyname) : 0; - if (k) return k; - } - } - if (dirsav) dirsav->cd(); - return 0; -} - -//______________________________________________________________________________ -TObject *TDirectoryFile::FindObjectAny(const char *aname) const -{ - // Find object by name in the list of memory objects of the current - // directory or its sub-directories. - // After this call the current directory is not changed. - // To automatically set the current directory where the object is found, - // use FindKeyAny(aname)->ReadObj(). - - //object may be already in the list of objects in memory - TObject *obj = fList->FindObject(aname); - if (obj) return obj; - - TDirectory *dirsav = gDirectory; - Short_t cycle; - char name[kMaxLen]; - - DecodeNameCycle(aname, name, cycle); - - TIter next(GetListOfKeys()); - TKey *key; - //may be a key in the current directory - while ((key = (TKey *) next())) { - if (!strcmp(name, key->GetName())) { - if (cycle == 9999) return key->ReadObj(); - if (cycle >= key->GetCycle()) return key->ReadObj(); - } - } - //try with subdirectories - next.Reset(); - while ((key = (TKey *) next())) { - //if (!strcmp(key->GetClassName(),"TDirectory")) { - if (strstr(key->GetClassName(),"TDirectory")) { - TDirectory* subdir = - ((TDirectory*)this)->GetDirectory(key->GetName(), kTRUE, "FindKeyAny"); - TKey *k = subdir==0 ? 0 : subdir->FindKeyAny(aname); - if (k) { if (dirsav) dirsav->cd(); return k->ReadObj();} - } - } - if (dirsav) dirsav->cd(); - return 0; -} - -//______________________________________________________________________________ -TObject *TDirectoryFile::Get(const char *namecycle) -{ -// return pointer to object identified by namecycle -// -// namecycle has the format name;cycle -// name = * is illegal, cycle = * is illegal -// cycle = "" or cycle = 9999 ==> apply to a memory object -// -// examples: -// foo : get object named foo in memory -// if object is not in memory, try with highest cycle from file -// foo;1 : get cycle 1 of foo on file -// -// The retrieved object should in principle derive from TObject. -// If not, the function TDirectoryFile::GetObject should be called. -// However, this function will still work for a non-TObject, providing that -// the calling application cast the return type to the correct type (which -// is the actual type of the object). -// -// NOTE: -// The method GetObject offer better protection and avoid the need -// for any cast: -// MyClass *obj; -// directory->GetObject("some object",obj); -// if (obj) { ... the object exist and inherits from MyClass ... } -// -// VERY IMPORTANT NOTE: -// In case the class of this object derives from TObject but not -// as a first inheritance, one must use dynamic_cast<>(). -// Example 1: Normal case: -// class MyClass : public TObject, public AnotherClass -// then on return, one can do: -// MyClass *obj = (MyClass*)directory->Get("some object of MyClass"); -// -// Example 2: Special case: -// class MyClass : public AnotherClass, public TObject -// then on return, one must do: -// MyClass *obj = dynamic_cast<MyClass*>(directory->Get("some object of MyClass")); -// -// Of course, dynamic_cast<> can also be used in the example 1. -// - - Short_t cycle; - char name[kMaxLen]; - - DecodeNameCycle(namecycle, name, cycle); - char *namobj = name; - Int_t nch = strlen(name); - for (Int_t i = nch-1; i > 0; i--) { - if (name[i] == '/') { - name[i] = 0; - TDirectory* dirToSearch=GetDirectory(name); - namobj = name + i + 1; - name[i] = '/'; - return dirToSearch?dirToSearch->Get(namobj):0; - } - } - -//*-*---------------------Case of Object in memory--------------------- -// ======================== - TObject *idcur = fList->FindObject(namobj); - if (idcur) { - if (idcur==this && strlen(namobj)!=0) { - // The object has the same name has the directory and - // that's what we picked-up! We just need to ignore - // it ... - idcur = 0; - } else if (cycle == 9999) { - return idcur; - } else { - if (idcur->InheritsFrom(TCollection::Class())) - idcur->Delete(); // delete also list elements - delete idcur; - idcur = 0; - } - } - -//*-*---------------------Case of Key--------------------- -// =========== - TKey *key; - TIter nextkey(GetListOfKeys()); - while ((key = (TKey *) nextkey())) { - if (strcmp(namobj,key->GetName()) == 0) { - if ((cycle == 9999) || (cycle == key->GetCycle())) { - TDirectory::TContext ctxt(this); - idcur = key->ReadObj(); - break; - } - } - } - - return idcur; -} - -//______________________________________________________________________________ -void *TDirectoryFile::GetObjectUnchecked(const char *namecycle) -{ -// return pointer to object identified by namecycle. -// The returned object may or may not derive from TObject. -// -// namecycle has the format name;cycle -// name = * is illegal, cycle = * is illegal -// cycle = "" or cycle = 9999 ==> apply to a memory object -// -// VERY IMPORTANT NOTE: -// The calling application must cast the returned object to -// the final type, eg -// MyClass *obj = (MyClass*)directory->GetObject("some object of MyClass"); - - return GetObjectChecked(namecycle,(TClass*)0); -} - -//_________________________________________________________________________________ -void *TDirectoryFile::GetObjectChecked(const char *namecycle, const char* classname) -{ -// See documentation of TDirectoryFile::GetObjectCheck(const char *namecycle, const TClass *cl) - - return GetObjectChecked(namecycle,TClass::GetClass(classname)); -} - - -//____________________________________________________________________________ -void *TDirectoryFile::GetObjectChecked(const char *namecycle, const TClass* expectedClass) -{ -// return pointer to object identified by namecycle if and only if the actual -// object is a type suitable to be stored as a pointer to a "expectedClass" -// If expectedClass is null, no check is performed. -// -// namecycle has the format name;cycle -// name = * is illegal, cycle = * is illegal -// cycle = "" or cycle = 9999 ==> apply to a memory object -// -// VERY IMPORTANT NOTE: -// The calling application must cast the returned pointer to -// the type described by the 2 arguments (i.e. cl): -// MyClass *obj = (MyClass*)directory->GetObjectChecked("some object of MyClass","MyClass")); -// -// Note: We recommend using the method TDirectoryFile::GetObject: -// MyClass *obj = 0; -// directory->GetObject("some object inheriting from MyClass",obj); -// if (obj) { ... we found what we are looking for ... } - - Short_t cycle; - char name[kMaxLen]; - - DecodeNameCycle(namecycle, name, cycle); - char *namobj = name; - Int_t nch = strlen(name); - for (Int_t i = nch-1; i > 0; i--) { - if (name[i] == '/') { - name[i] = 0; - TDirectory* dirToSearch=GetDirectory(name); - namobj = name + i + 1; - name[i] = '/'; - if (dirToSearch) { - return dirToSearch->GetObjectChecked(namobj, expectedClass); - } else { - return 0; - } - } - } - -//*-*---------------------Case of Object in memory--------------------- -// ======================== - if (expectedClass==0 || expectedClass->InheritsFrom(TObject::Class())) { - TObject *objcur = fList->FindObject(namobj); - if (objcur) { - if (objcur==this && strlen(namobj)!=0) { - // The object has the same name has the directory and - // that's what we picked-up! We just need to ignore - // it ... - objcur = 0; - } else if (cycle == 9999) { - // Check type - if (expectedClass && objcur->IsA()->GetBaseClassOffset(expectedClass) == -1) return 0; - else return objcur; - } else { - if (objcur->InheritsFrom(TCollection::Class())) - objcur->Delete(); // delete also list elements - delete objcur; - objcur = 0; - } - } - } - -//*-*---------------------Case of Key--------------------- -// =========== - void *idcur = 0; - TKey *key; - TIter nextkey(GetListOfKeys()); - while ((key = (TKey *) nextkey())) { - if (strcmp(namobj,key->GetName()) == 0) { - if ((cycle == 9999) || (cycle == key->GetCycle())) { - TDirectory::TContext ctxt(this); - idcur = key->ReadObjectAny(expectedClass); - break; - } - } - } - - return idcur; -} - -//______________________________________________________________________________ -Int_t TDirectoryFile::GetBufferSize() const -{ - // Return the buffer size to create new TKeys. - // If the stored fBufferSize is null, the value returned is the average - // buffer size of objects in the file so far. - - if (fBufferSize <= 0) return fFile->GetBestBuffer(); - else return fBufferSize; -} - - -//______________________________________________________________________________ -TKey *TDirectoryFile::GetKey(const char *name, Short_t cycle) const -{ -//*-*-*-*-*-*-*-*-*-*-*Return pointer to key with name,cycle*-*-*-*-*-*-*-* -//*-* ===================================== -// if cycle = 9999 returns highest cycle -// - TKey *key; - TIter next(GetListOfKeys()); - while ((key = (TKey *) next())) - if (!strcmp(name, key->GetName())) { - if (cycle == 9999) return key; - if (cycle >= key->GetCycle()) return key; - } - return 0; -} - -//______________________________________________________________________________ -void TDirectoryFile::ls(Option_t *option) const -{ -//*-*-*-*-*-*-*-*-*-*-*-*List Directory contents*-*-*-*-*-*-*-*-*-*-*-*-*-* -//*-* ======================= -// Indentation is used to identify the directory tree -// Subdirectories are listed first, then objects in memory, then objects on the file -// -// The option can has the following format: -// [-d |-m][<regexp>] -// Option -d means: only list objects in the file -// -m means: only list objects in memory -// The <regexp> will be used to match the name of the objects. -// By default memory and disk objects are listed. -// - TROOT::IndentLevel(); - cout <<ClassName()<<"*\t\t"<<GetName()<<"\t"<<GetTitle()<<endl; - TROOT::IncreaseDirLevel(); - - TString opta = option; - TString opt = opta.Strip(TString::kBoth); - Bool_t memobj = kTRUE; - Bool_t diskobj = kTRUE; - TString reg = "*"; - if (opt.BeginsWith("-m")) { - diskobj = kFALSE; - if (opt.Length() > 2) - reg = opt(2,opt.Length()); - } else if (opt.BeginsWith("-d")) { - memobj = kFALSE; - if (opt.Length() > 2) - reg = opt(2,opt.Length()); - } else if (!opt.IsNull()) - reg = opt; - - TRegexp re(reg, kTRUE); - - if (memobj) { - TObject *obj; - TIter nextobj(fList); - while ((obj = (TObject *) nextobj())) { - TString s = obj->GetName(); - if (s.Index(re) == kNPOS) continue; - obj->ls(option); //*-* Loop on all the objects in memory - } - } - - if (diskobj) { - TKey *key; - TIter next(GetListOfKeys()); - while ((key = (TKey *) next())) { - TString s = key->GetName(); - if (s.Index(re) == kNPOS) continue; - key->ls(); //*-* Loop on all the keys - } - } - TROOT::DecreaseDirLevel(); -} - -//______________________________________________________________________________ -TFile *TDirectoryFile::OpenFile(const char *name, Option_t *option,const char *ftitle, Int_t compress, Int_t netopt) -{ - // Interface to TFile::Open - - return TFile::Open(name,option,ftitle,compress,netopt); - -} - - -//______________________________________________________________________________ -TDirectory *TDirectoryFile::mkdir(const char *name, const char *title) -{ - // Create a sub-directory and return a pointer to the created directory. - // Returns 0 in case of error. - // Returns 0 if a directory with the same name already exists. - // Note that the directory name cannot contain slashes. - - if (!name || !title || !strlen(name)) return 0; - if (!strlen(title)) title = name; - if (strchr(name,'/')) { - ::Error("TDirectoryFile::mkdir","directory name (%s) cannot contain a slash", name); - return 0; - } - if (GetKey(name)) { - Error("mkdir","An object with name %s exists already",name); - return 0; - } - - TDirectory::TContext ctxt(this); - - TDirectoryFile *newdir = new TDirectoryFile(name, title, "", this); - - return newdir; -} - -//______________________________________________________________________________ -void TDirectoryFile::Purge(Short_t) -{ - // Purge lowest key cycles in a directory. - // By default, only the highest cycle of a key is kept. Keys for which - // the "KEEP" flag has been set are not removed. See TKey::Keep(). - - if (!IsWritable()) return; - - TDirectory::TContext ctxt(this); - - TKey *key; - TIter prev(GetListOfKeys(), kIterBackward); - - while ((key = (TKey*)prev())) { // reverse loop on keys - TKey *keyprev = (TKey*)GetListOfKeys()->Before(key); - if (!keyprev) break; - if (key->GetKeep() == 0) { - if (strcmp(key->GetName(), keyprev->GetName()) == 0) key->Delete(); - } - } - TFile* f = GetFile(); - if (fModified && (f!=0)) { - WriteKeys(); // Write new keys structure - WriteDirHeader(); // Write new directory header - f->WriteFree(); // Write new free segments list - f->WriteHeader(); // Write new file header - } -} - -//______________________________________________________________________________ -void TDirectoryFile::ReadAll(Option_t* opt) -{ - // Read objects from a ROOT db file directory into memory. - // If an object is already in memory, the memory copy is deleted - // and the object is again read from the file. - // If opt=="dirs", only subdirectories will be read - // If opt=="dirs*" complete directory tree will be read - - TDirectory::TContext ctxt(this); - - TKey *key; - TIter next(GetListOfKeys()); - - Bool_t readdirs = ((opt!=0) && ((strcmp(opt,"dirs")==0) || (strcmp(opt,"dirs*")==0))); - - if (readdirs) - while ((key = (TKey *) next())) { - - //if (strcmp(key->GetClassName(),"TDirectory")!=0) continue; - if (strstr(key->GetClassName(),"TDirectory")==0) continue; - - TDirectory *dir = GetDirectory(key->GetName(), kTRUE, "ReadAll"); - - if ((dir!=0) && (strcmp(opt,"dirs*")==0)) dir->ReadAll("dirs*"); - } - else - while ((key = (TKey *) next())) { - TObject *thing = GetList()->FindObject(key->GetName()); - if (thing) { delete thing; } - thing = key->ReadObj(); - } -} - -//______________________________________________________________________________ -Int_t TDirectoryFile::ReadKeys() -{ -//*-*-*-*-*-*-*-*-*-*-*-*-*Read the KEYS linked list*-*-*-*-*-*-*-*-*-*-*-*-* -//*-* ========================= -// Every directory has a linked list (fKeys). This linked list has been -// written on the file via WriteKeys as a single data record. -// -// It is interesting to call this function in the following situation. -// Assume another process1 is connecting this directory in Update mode -// -Process1 is adding/updating objects in this directory -// -You want to see the latest status from process1. -// Example Process1: -// obj1.Write(); -// obj2.Write(); -// gDirectory->SaveSelf(); -// -// Example Process2 -// gDirectory->ReadKeys(); -// obj1->Draw(); -// -// This is an efficient way (without opening/closing files) to view -// the latest updates of a file being modified by another process -// as it is typically the case in a data acquisition system. - - if (fFile==0) return 0; - - if (!fFile->IsBinary()) - return fFile->DirReadKeys(this); - - TDirectory::TContext ctxt(this); - - fKeys->Delete(); - //In case directory was updated by another process, read new - //position for the keys - Int_t nbytes = fNbytesName + TDirectoryFile::Sizeof(); - char *header = new char[nbytes]; - char *buffer = header; - fFile->Seek(fSeekDir); - fFile->ReadBuffer(buffer,nbytes); - buffer += fNbytesName; - Version_t versiondir; - frombuf(buffer,&versiondir); - fDatimeC.ReadBuffer(buffer); - fDatimeM.ReadBuffer(buffer); - frombuf(buffer, &fNbytesKeys); - frombuf(buffer, &fNbytesName); - if (versiondir > 1000) { - frombuf(buffer, &fSeekDir); - frombuf(buffer, &fSeekParent); - frombuf(buffer, &fSeekKeys); - } else { - Int_t sdir,sparent,skeys; - frombuf(buffer, &sdir); fSeekDir = (Long64_t)sdir; - frombuf(buffer, &sparent); fSeekParent = (Long64_t)sparent; - frombuf(buffer, &skeys); fSeekKeys = (Long64_t)skeys; - } - delete [] header; - - Int_t nkeys = 0; - Long64_t fsize = fFile->GetSize(); - if ( fSeekKeys > 0) { - TKey *headerkey = new TKey(fSeekKeys, fNbytesKeys, this); - headerkey->ReadFile(); - buffer = headerkey->GetBuffer(); - headerkey->ReadKeyBuffer(buffer); - - TKey *key; - frombuf(buffer, &nkeys); - for (Int_t i = 0; i < nkeys; i++) { - key = new TKey(this); - key->ReadKeyBuffer(buffer); - if (key->GetSeekKey() < 64 || key->GetSeekKey() > fsize) { - Error("ReadKeys","reading illegal key, exiting after %d keys",i); - fKeys->Remove(key); - nkeys = i; - break; - } - if (key->GetSeekPdir() < 64 || key->GetSeekPdir() > fsize) { - Error("ReadKeys","reading illegal key, exiting after %d keys",i); - fKeys->Remove(key); - nkeys = i; - break; - } - fKeys->Add(key); - } - delete headerkey; - } - - return nkeys; -} - - -//______________________________________________________________________________ -Int_t TDirectoryFile::ReadTObject(TObject *obj, const char *keyname) -{ - // Read object with keyname from the current directory - // Read contents of object with specified name from the current directory. - // First the key with keyname is searched in the current directory, - // next the key buffer is deserialized into the object. - // The object must have been created before via the default constructor. - // See TObject::Write(). - - if (!fFile) { Error("Read","No file open"); return 0; } - TKey *key = (TKey*)fKeys->FindObject(keyname); - if (!key) { Error("Read","Key not found"); return 0; } - return key->Read(obj); -} - -//______________________________________________________________________________ -void TDirectoryFile::rmdir(const char *name) -{ - // Removes subdirectory from the directory - // When diredctory is deleted, all keys in all subdirectories will be - // read first and deleted from file (if exists) - // Equivalent call is Delete("name;*"); - - if ((name==0) || (*name==0)) return; - - TString mask(name); - mask+=";*"; - Delete(mask); -} - -//______________________________________________________________________________ -void TDirectoryFile::Save() -{ -//*-*-*-*-*-*-*-*-*-*Save recursively all directory keys and headers-*-*-*-*-* -//*-* =============================================== - - TDirectory::TContext ctxt(this); - - SaveSelf(); - - // recursively save all sub-directories - if (fList) { - TObject *idcur; - TIter next(fList); - while ((idcur = next())) { - if (idcur->InheritsFrom(TDirectoryFile::Class())) { - TDirectoryFile *dir = (TDirectoryFile*)idcur; - dir->Save(); - } - } - } -} - -//______________________________________________________________________________ -Int_t TDirectoryFile::SaveObjectAs(const TObject *obj, const char *filename, Option_t *option) -{ - // Save object in filename (static function) - // if filename is null or "", a file with "objectname.root" is created. - // The name of the key is the object name. - // If the operation is successful, it returns the number of bytes written to the file - // otherwise it returns 0. - // By default a message is printed. Use option "q" to not print the message. - - if (!obj) return 0; - TDirectory *dirsav = gDirectory; - TString fname = filename; - if (!filename || strlen(filename) == 0) { - fname = Form("%s.root",obj->GetName()); - } - TFile *local = TFile::Open(fname.Data(),"recreate"); - if (!local) return 0; - Int_t nbytes = obj->Write(); - delete local; - if (dirsav) dirsav->cd(); - TString opt = option; - opt.ToLower(); - if (!opt.Contains("q")) { - if (!gSystem->AccessPathName(fname.Data())) obj->Info("SaveAs", "ROOT file %s has been created", fname.Data()); - } - return nbytes; -} - -//______________________________________________________________________________ -void TDirectoryFile::SaveSelf(Bool_t force) -{ -//*-*-*-*-*-*-*-*-*-*Save Directory keys and header*-*-*-*-*-*-*-*-*-*-*-* -//*-* ============================== -// If the directory has been modified (fModified set), write the keys -// and the directory header. This function assumes the cd is correctly set. -// -// It is recommended to use this function in the following situation: -// Assume a process1 using a directory in Update mode -// -New objects or modified objects have been written to the directory -// -You do not want to close the file -// -You want your changes be visible from another process2 already connected -// to this directory in read mode -// -Call this function -// -In process2, use TDirectoryFile::ReadKeys to refresh the directory - - if (IsWritable() && (fModified || force) && fFile) { - Bool_t dowrite = kTRUE; - if (fFile->GetListOfFree()) - dowrite = fFile->GetListOfFree()->First() != 0; - if (dowrite) { - TDirectory *dirsav = gDirectory; - if (dirsav != this) cd(); - WriteKeys(); //*-*- Write keys record - WriteDirHeader(); //*-*- Update directory record - if (dirsav && dirsav != this) dirsav->cd(); - } - } -} - -//______________________________________________________________________________ -void TDirectoryFile::SetBufferSize(Int_t bufsize) -{ - // set the default buffer size when creating new TKeys - // see also TDirectoryFile::GetBufferSize - - fBufferSize = bufsize; -} - -//______________________________________________________________________________ -void TDirectoryFile::SetTRefAction(TObject *ref, TObject *parent) -{ - // Find the action to be executed in the dictionary of the parent class - // and store the corresponding exec number into fBits. - // This function searches a data member in the class of parent with an - // offset corresponding to this. - // If a comment "TEXEC:" is found in the comment field of the data member, - // the function stores the exec identifier of the exec statement - // following this keyword. - - Int_t offset = (char*)ref - (char*)parent; - TClass *cl = parent->IsA(); - cl->BuildRealData(parent); - TStreamerInfo *info = (TStreamerInfo*)cl->GetStreamerInfo(); - TIter next(info->GetElements()); - TStreamerElement *element; - while((element = (TStreamerElement*)next())) { - if (element->GetOffset() != offset) continue; - Int_t execid = element->GetExecID(); - if (execid > 0) ref->SetBit(execid << 8); - return; - } -} - -//______________________________________________________________________________ -void TDirectoryFile::SetWritable(Bool_t writable) -{ -// Set the new value of fWritable recursively - - TDirectory::TContext ctxt(this); - - fWritable = writable; - - // recursively set all sub-directories - if (fList) { - TObject *idcur; - TIter next(fList); - while ((idcur = next())) { - if (idcur->InheritsFrom(TDirectory::Class())) { - TDirectoryFile *dir = (TDirectoryFile*)idcur; - dir->SetWritable(writable); - } - } - } -} - - -//______________________________________________________________________________ -Int_t TDirectoryFile::Sizeof() const -{ -//*-*-*-*-*-*-*Return the size in bytes of the directory header*-*-*-*-*-*-* -//*-* ================================================ - //Int_t nbytes = sizeof(Version_t); 2 - //nbytes += fDatimeC.Sizeof(); - //nbytes += fDatimeM.Sizeof(); - //nbytes += sizeof fNbytesKeys; 4 - //nbytes += sizeof fNbytesName; 4 - //nbytes += sizeof fSeekDir; 4 or 8 - //nbytes += sizeof fSeekParent; 4 or 8 - //nbytes += sizeof fSeekKeys; 4 or 8 - //nbytes += fUUID.Sizeof(); - Int_t nbytes = 22; - - nbytes += fDatimeC.Sizeof(); - nbytes += fDatimeM.Sizeof(); - nbytes += fUUID.Sizeof(); - //assume that the file may be above 2 Gbytes if file version is > 4 - if (fFile && fFile->GetVersion() >= 40000) nbytes += 12; - return nbytes; -} - - -//_______________________________________________________________________ -void TDirectoryFile::Streamer(TBuffer &b) -{ -//*-*-*-*-*-*-*-*-*Stream a class object*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* -//*-* ========================================= - - Version_t v,version; - if (b.IsReading()) { - Build((TFile*)b.GetParent(), 0); - if (fFile && fFile->IsWritable()) fWritable = kTRUE; - - if (fFile && !fFile->IsBinary()) { - Version_t R__v = b.ReadVersion(0, 0); - b.ClassBegin(TDirectoryFile::Class(), R__v); - - TString sbuf; - - b.ClassMember("CreateTime","TString"); - sbuf.Streamer(b); - TDatime timeC(sbuf.Data()); - fDatimeC = timeC; - - b.ClassMember("ModifyTime","TString"); - sbuf.Streamer(b); - TDatime timeM(sbuf.Data()); - fDatimeM = timeM; - - b.ClassMember("UUID","TString"); - sbuf.Streamer(b); - TUUID id(sbuf.Data()); - fUUID = id; - - b.ClassEnd(TDirectoryFile::Class()); - - fSeekKeys = 0; // read keys later in the TKeySQL class - } else { - b >> version; - fDatimeC.Streamer(b); - fDatimeM.Streamer(b); - b >> fNbytesKeys; - b >> fNbytesName; - if (version > 1000) { - SetBit(kIsBigFile); - b >> fSeekDir; - b >> fSeekParent; - b >> fSeekKeys; - } else { - Int_t sdir,sparent,skeys; - b >> sdir; fSeekDir = (Long64_t)sdir; - b >> sparent; fSeekParent = (Long64_t)sparent; - b >> skeys; fSeekKeys = (Long64_t)skeys; - } - v = version%1000; - if (v == 2) { - fUUID.StreamerV1(b); - } else if (v > 2) { - fUUID.Streamer(b); - } - } - R__LOCKGUARD2(gROOTMutex); - gROOT->GetUUIDs()->AddUUID(fUUID,this); - if (fSeekKeys) ReadKeys(); - } else { - if (fFile && !fFile->IsBinary()) { - b.WriteVersion(TDirectoryFile::Class()); - - TString sbuf; - - b.ClassBegin(TDirectoryFile::Class()); - - b.ClassMember("CreateTime","TString"); - sbuf = fDatimeC.AsSQLString(); - sbuf.Streamer(b); - - b.ClassMember("ModifyTime","TString"); - fDatimeM.Set(); - sbuf = fDatimeM.AsSQLString(); - sbuf.Streamer(b); - - b.ClassMember("UUID","TString"); - sbuf = fUUID.AsString(); - sbuf.Streamer(b); - - b.ClassEnd(TDirectoryFile::Class()); - } else { - version = TDirectoryFile::Class_Version(); - if (fFile && fFile->GetEND() > TFile::kStartBigFile) version += 1000; - b << version; - fDatimeC.Streamer(b); - fDatimeM.Streamer(b); - b << fNbytesKeys; - b << fNbytesName; - if (version > 1000) { - b << fSeekDir; - b << fSeekParent; - b << fSeekKeys; - } else { - b << (Int_t)fSeekDir; - b << (Int_t)fSeekParent; - b << (Int_t)fSeekKeys; - } - fUUID.Streamer(b); - if (version <=1000) for (Int_t i=0;i<3;i++) b << Int_t(0); - } - } -} - -//______________________________________________________________________________ -Int_t TDirectoryFile::Write(const char *, Int_t opt, Int_t bufsize) -{ - // Write all objects in memory to disk. - // Loop on all objects in memory (including subdirectories). - // A new key is created in the KEYS linked list for each object. - // For allowed options see TObject::Write(). - // The directory header info is rewritten on the directory header record. - - if (!IsWritable()) return 0; - TDirectory::TContext ctxt(this); - - // Loop on all objects (including subdirs) - TIter next(fList); - TObject *obj; - Int_t nbytes = 0; - while ((obj=next())) { - nbytes += obj->Write(0,opt,bufsize); - } - SaveSelf(kTRUE); // force save itself - - return nbytes; -} - -//______________________________________________________________________________ -Int_t TDirectoryFile::Write(const char *n, Int_t opt, Int_t bufsize) const -{ - // One can not save a const TDirectory object. - - Error("Write const","A const TDirectory object should not be saved. We try to proceed anyway."); - return const_cast<TDirectoryFile*>(this)->Write(n, opt, bufsize); -} - -//____________________________________________________________________________________ -Int_t TDirectoryFile::WriteTObject(const TObject *obj, const char *name, Option_t *option, Int_t bufsize) -{ - // Write object obj to this directory - // The data structure corresponding to this object is serialized. - // The corresponding buffer is written to this directory - // with an associated key with name "name". - // - // Writing an object to a file involves the following steps: - // - // -Creation of a support TKey object in the directory. - // The TKey object creates a TBuffer object. - // - // -The TBuffer object is filled via the class::Streamer function. - // - // -If the file is compressed (default) a second buffer is created to - // hold the compressed buffer. - // - // -Reservation of the corresponding space in the file by looking - // in the TFree list of free blocks of the file. - // - // -The buffer is written to the file. - // - // By default, the buffersize will be taken from the average buffer size - // of all objects written to the current file so far. - // Use TDirectoryFile::SetBufferSize to force a given buffer size. - // - // If a name is specified, it will be the name of the key. - // If name is not given, the name of the key will be the name as returned - // by obj->GetName(). - // - // The option can be a combination of: - // "SingleKey", "Overwrite" or "WriteDelete" - // Using the "Overwrite" option a previous key with the same name is - // overwritten. The previous key is deleted before writing the new object. - // Using the "WriteDelete" option a previous key with the same name is - // deleted only after the new object has been written. This option - // is safer than kOverwrite but it is slower. - // The "SingleKey" option is only used by TCollection::Write() to write - // a container with a single key instead of each object in the container - // with its own key. - // - // An object is read from this directory via TDirectoryFile::Get. - // - // The function returns the total number of bytes written to the directory. - // It returns 0 if the object cannot be written. - - TDirectory::TContext ctxt(this); - - if (fFile==0) return 0; - - if (!fFile->IsWritable()) { - if (!fFile->TestBit(TFile::kWriteError)) { - // Do not print the error if the file already had a SysError. - Error("WriteTObject","Directory %s is not writable", fFile->GetName()); - } - return 0; - } - - if (!obj) return 0; - - TString opt = option; - opt.ToLower(); - - TKey *key=0, *oldkey=0; - Int_t bsize = GetBufferSize(); - if (bufsize > 0) bsize = bufsize; - - const char *oname; - if (name && *name) - oname = name; - else - oname = obj->GetName(); - - // Remove trailing blanks in object name - Int_t nch = strlen(oname); - char *newName = 0; - if (oname[nch-1] == ' ') { - newName = new char[nch+1]; - strcpy(newName,oname); - for (Int_t i=0;i<nch;i++) { - if (newName[nch-i-1] != ' ') break; - newName[nch-i-1] = 0; - } - oname = newName; - } - - if (opt.Contains("overwrite")) { - //One must use GetKey. FindObject would return the lowest cycle of the key! - //key = (TKey*)gDirectory->GetListOfKeys()->FindObject(oname); - key = GetKey(oname); - if (key) { - key->Delete(); - delete key; - } - } - if (opt.Contains("writedelete")) { - oldkey = GetKey(oname); - } - key = fFile->CreateKey(this, obj, oname, bsize); - if (newName) delete [] newName; - - if (!key->GetSeekKey()) { - fKeys->Remove(key); - delete key; - if (bufsize) fFile->SetBufferSize(bufsize); - return 0; - } - fFile->SumBuffer(key->GetObjlen()); - Int_t nbytes = key->WriteFile(0); - if (fFile->TestBit(TFile::kWriteError)) { - if (bufsize) fFile->SetBufferSize(bufsize); - return 0; - } - if (oldkey) { - oldkey->Delete(); - delete oldkey; - } - if (bufsize) fFile->SetBufferSize(bufsize); - - return nbytes; -} - -//______________________________________________________________________________ -Int_t TDirectoryFile::WriteObjectAny(const void *obj, const char *classname, const char *name, Option_t *option, Int_t bufsize) -{ - // Write object from pointer of class classname in this directory - // obj may not derive from TObject - // see TDirectoryFile::WriteObject for comments - // - // VERY IMPORTANT NOTE: - // The value passed as 'obj' needs to be from a pointer to the type described by classname - // For example with: - // TopClass *top; - // BottomClass *bottom; - // top = bottom; - // you can do: - // directory->WriteObjectAny(top,"top","name of object"); - // directory->WriteObjectAny(bottom,"bottom","name of object"); - // BUT YOU CAN NOT DO (it will fail in particular with multiple inheritance): - // directory->WriteObjectAny(top,"bottom","name of object"); - // - // We STRONGLY recommend to use - // TopClass *top = ....; - // directory->WriteObject(top,"name of object") - - TClass *cl = TClass::GetClass(classname); - if (!cl) { - Error("WriteObjectAny","Unknown class: %s",classname); - return 0; - } - return WriteObjectAny(obj,cl,name,option,bufsize); -} - -//______________________________________________________________________________ -Int_t TDirectoryFile::WriteObjectAny(const void *obj, const TClass *cl, const char *name, Option_t *option, Int_t bufsize) -{ - // Write object of class with dictionary cl in this directory - // obj may not derive from TObject - // To get the TClass* cl pointer, one can use - // TClass *cl = TClass::GetClass("classname"); - // An alternative is to call the function WriteObjectAny above. - // see TDirectoryFile::WriteObject for comments - - TDirectory::TContext ctxt(this); - - if (fFile==0) return 0; - - if (!fFile->IsWritable()) { - if (!fFile->TestBit(TFile::kWriteError)) { - // Do not print the error if the file already had a SysError. - Error("WriteObject","File %s is not writable", fFile->GetName()); - } - return 0; - } - - if (!obj || !cl) return 0; - TKey *key, *oldkey=0; - Int_t bsize = GetBufferSize(); - if (bufsize > 0) bsize = bufsize; - - TString opt = option; - opt.ToLower(); - - const char *oname; - if (name && *name) - oname = name; - else - oname = cl->GetName(); - - // Remove trailing blanks in object name - Int_t nch = strlen(oname); - char *newName = 0; - if (oname[nch-1] == ' ') { - newName = new char[nch+1]; - strcpy(newName,oname); - for (Int_t i=0;i<nch;i++) { - if (newName[nch-i-1] != ' ') break; - newName[nch-i-1] = 0; - } - oname = newName; - } - - if (opt.Contains("overwrite")) { - //One must use GetKey. FindObject would return the lowest cycle of the key! - //key = (TKey*)gDirectory->GetListOfKeys()->FindObject(oname); - key = GetKey(oname); - if (key) { - key->Delete(); - delete key; - } - } - if (opt.Contains("writedelete")) { - oldkey = GetKey(oname); - } - key = fFile->CreateKey(this, obj, cl, oname, bsize); - if (newName) delete [] newName; - - if (!key->GetSeekKey()) { - fKeys->Remove(key); - delete key; - return 0; - } - fFile->SumBuffer(key->GetObjlen()); - Int_t nbytes = key->WriteFile(0); - if (fFile->TestBit(TFile::kWriteError)) return 0; - - if (oldkey) { - oldkey->Delete(); - delete oldkey; - } - - return nbytes; -} - -//______________________________________________________________________________ -void TDirectoryFile::WriteDirHeader() -{ -//*-*-*-*-*-*-*-*-*-*-*Overwrite the Directory header record*-*-*-*-*-*-*-*-* -//*-* ===================================== - TFile* f = GetFile(); - if (f==0) return; - - if (!f->IsBinary()) { - fDatimeM.Set(); - f->DirWriteHeader(this); - return; - } - - Int_t nbytes = TDirectoryFile::Sizeof(); //Warning ! TFile has a Sizeof() - char * header = new char[nbytes]; - char * buffer = header; - fDatimeM.Set(); - TDirectoryFile::FillBuffer(buffer); - Long64_t pointer = fSeekDir + fNbytesName; // do not overwrite the name/title part - fModified = kFALSE; - f->Seek(pointer); - f->WriteBuffer(header, nbytes); - if (f->MustFlush()) f->Flush(); - delete [] header; -} - -//______________________________________________________________________________ -void TDirectoryFile::WriteKeys() -{ -//*-*-*-*-*-*-*-*-*-*-*-*Write KEYS linked list on the file *-*-*-*-*-*-*-* -//*-* ================================== -// The linked list of keys (fKeys) is written as a single data record -// - - TFile* f = GetFile(); - if (f==0) return; - - if (!f->IsBinary()) { - f->DirWriteKeys(this); - return; - } - -//*-* Delete the old keys structure if it exists - if (fSeekKeys != 0) { - f->MakeFree(fSeekKeys, fSeekKeys + fNbytesKeys -1); - } -//*-* Write new keys record - TIter next(fKeys); - TKey *key; - Int_t nkeys = fKeys->GetSize(); - Int_t nbytes = sizeof nkeys; //*-* Compute size of all keys - if (f->GetEND() > TFile::kStartBigFile) nbytes += 8; - while ((key = (TKey*)next())) { - nbytes += key->Sizeof(); - } - TKey *headerkey = new TKey(fName,fTitle,IsA(),nbytes,this); - if (headerkey->GetSeekKey() == 0) { - delete headerkey; - return; - } - char *buffer = headerkey->GetBuffer(); - next.Reset(); - tobuf(buffer, nkeys); - while ((key = (TKey*)next())) { - key->FillBuffer(buffer); - } - - fSeekKeys = headerkey->GetSeekKey(); - fNbytesKeys = headerkey->GetNbytes(); - headerkey->WriteFile(); - delete headerkey; -} diff --git a/base/src/TFile.cxx b/base/src/TFile.cxx deleted file mode 100644 index d21e5f2cfddb7636621bc1fadd16dc9f4e3a576a..0000000000000000000000000000000000000000 --- a/base/src/TFile.cxx +++ /dev/null @@ -1,2856 +0,0 @@ -// @(#)root/base:$Name: $:$Id: TFile.cxx,v 1.203 2007/01/28 18:28:33 brun Exp $ -// Author: Rene Brun 28/11/94 - -/************************************************************************* - * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -#include "RConfig.h" - -#include <fcntl.h> -#include <errno.h> -#include <sys/stat.h> -#ifndef WIN32 -# include <unistd.h> -#else -# define ssize_t int -# include <io.h> -# include <sys/types.h> -#endif - -#include "Bytes.h" -#include "Riostream.h" -#include "Strlen.h" -#include "TArrayC.h" -#include "TClass.h" -#include "TClassTable.h" -#include "TDatime.h" -#include "TError.h" -#include "TFile.h" -#include "TFileCacheRead.h" -#include "TFileCacheWrite.h" -#include "TFree.h" -#include "TInterpreter.h" -#include "TKey.h" -#include "TNetFile.h" -#include "TPluginManager.h" -#include "TProcessUUID.h" -#include "TRegexp.h" -#include "TROOT.h" -#include "TStreamerInfo.h" -#include "TSystem.h" -#include "TTimeStamp.h" -#include "TVirtualPerfStats.h" -#include "TWebFile.h" -#include "TArchiveFile.h" -#include "TEnv.h" -#include "TVirtualMonitoring.h" -#include "TVirtualMutex.h" -#include "TMathBase.h" -#include <cmath> - -TFile *gFile; //Pointer to current file - - -Long64_t TFile::fgBytesRead = 0; -Long64_t TFile::fgBytesWrite = 0; -Long64_t TFile::fgFileCounter = 0; -Int_t TFile::fgReadCalls = 0; -Bool_t TFile::fgReadInfo = kTRUE; -TList *TFile::fgAsyncOpenRequests = 0; - -const Int_t kBEGIN = 100; - -ClassImp(TFile) - -//*-*x17 macros/layout_file - -//______________________________________________________________________________ -TFile::TFile() : TDirectoryFile(), fInfoCache(0) -{ - // File default Constructor. - - fD = -1; - fFree = 0; - fWritten = 0; - fSumBuffer = 0; - fSum2Buffer = 0; - fClassIndex = 0; - fProcessIDs = 0; - fNProcessIDs = 0; - fOffset = 0; - fArchive = 0; - fCacheRead = 0; - fCacheWrite = 0; - fArchiveOffset = 0; - fReadCalls = 0; - fNoAnchorInName = kFALSE; - fIsRootFile = kTRUE; - fIsArchive = kFALSE; - fInitDone = kFALSE; - fMustFlush = kTRUE; - fAsyncHandle = 0; - fAsyncOpenStatus = kAOSNotAsync; - SetBit(kBinaryFile, kTRUE); - - if (gDebug) - Info("TFile", "default ctor"); -} - -//_____________________________________________________________________________ -TFile::TFile(const char *fname1, Option_t *option, const char *ftitle, Int_t compress) - : TDirectoryFile(), fUrl(fname1,kTRUE), fInfoCache(0) -{ - // Opens or creates a local ROOT file whose name is fname1. It is - // recommended to specify fname1 as "<file>.root". The suffix ".root" - // will be used by object browsers to automatically identify the file as - // a ROOT file. If the constructor fails in any way IsZombie() will - // return true. Use IsOpen() to check if the file is (still) open. - // - // To open non-local files use the static TFile::Open() method, that - // will take care of opening the files using the correct remote file - // access plugin. - // - // If option = NEW or CREATE create a new file and open it for writing, - // if the file already exists the file is - // not opened. - // = RECREATE create a new file, if the file already - // exists it will be overwritten. - // = UPDATE open an existing file for writing. - // if no file exists, it is created. - // = READ open an existing file for reading. - // = NET used by derived remote file access - // classes, not a user callable option - // = WEB used by derived remote http access - // class, not a user callable option - // - // The file can be specified as a URL of the form: - // file:///user/rdm/bla.root or file:/user/rdm/bla.root - // - // The file can also be a member of an archive, in which case it is - // specified as: - // multi.zip#file.root or multi.zip#0 - // which will open file.root which is a member of the file multi.zip - // archive or member 1 from the archive. For more on archive file - // support see the TArchiveFile class. - // - // TFile and its remote access plugins can also be used to open any - // file, i.e. also non ROOT files, using: - // file.tar?filetype=raw - // This is convenient because the many remote file access plugins allow - // easy access to/from the many different mass storage systems. - // - // The title of the file (ftitle) will be shown by the ROOT browsers. - // - // A ROOT file (like a Unix file system) may contain objects and - // directories. There are no restrictions for the number of levels - // of directories. - // - // A ROOT file is designed such that one can write in the file in pure - // sequential mode (case of BATCH jobs). In this case, the file may be - // read sequentially again without using the file index written - // at the end of the file. In case of a job crash, all the information - // on the file is therefore protected. - // - // A ROOT file can be used interactively. In this case, one has the - // possibility to delete existing objects and add new ones. - // When an object is deleted from the file, the freed space is added - // into the FREE linked list (fFree). The FREE list consists of a chain - // of consecutive free segments on the file. At the same time, the first - // 4 bytes of the freed record on the file are overwritten by GAPSIZE - // where GAPSIZE = -(Number of bytes occupied by the record). - // - // Option compress is used to specify the compression level: - // compress = 0 objects written to this file will not be compressed. - // compress = 1 minimal compression level but fast. - // .... - // compress = 9 maximal compression level but slow. - // - // Note that the compression level may be changed at any time. - // The new compression level will only apply to newly written objects. - // The function TFile::Map() shows the compression factor - // for each object written to this file. - // The function TFile::GetCompressionFactor returns the global - // compression factor for this file. - // - // In case the file does not exist or is not a valid ROOT file, - // it is made a Zombie. One can detect this situation with a code like: - // TFile f("file.root"); - // if (f.IsZombie()) { - // cout << "Error opening file" << endl; - // exit(-1); - // } - // - // A ROOT file is a suite of consecutive data records (TKey's) with - // the following format (see also the TKey class). If the key is - // located past the 32 bit file limit (> 2 GB) then some fields will - // be 8 instead of 4 bytes: - // 1->4 Nbytes = Length of compressed object (in bytes) - // 5->6 Version = TKey version identifier - // 7->10 ObjLen = Length of uncompressed object - // 11->14 Datime = Date and time when object was written to file - // 15->16 KeyLen = Length of the key structure (in bytes) - // 17->18 Cycle = Cycle of key - // 19->22 [19->26] SeekKey = Pointer to record itself (consistency check) - // 23->26 [27->34] SeekPdir = Pointer to directory header - // 27->27 [35->35] lname = Number of bytes in the class name - // 28->.. [36->..] ClassName = Object Class Name - // ..->.. lname = Number of bytes in the object name - // ..->.. Name = lName bytes with the name of the object - // ..->.. lTitle = Number of bytes in the object title - // ..->.. Title = Title of the object - // -----> DATA = Data bytes associated to the object - // - // The first data record starts at byte fBEGIN (currently set to kBEGIN). - // Bytes 1->kBEGIN contain the file description, when fVersion >= 1000000 - // it is a large file (> 2 GB) and the offsets will be 8 bytes long and - // fUnits will be set to 8: - // 1->4 "root" = Root file identifier - // 5->8 fVersion = File format version - // 9->12 fBEGIN = Pointer to first data record - // 13->16 [13->20] fEND = Pointer to first free word at the EOF - // 17->20 [21->28] fSeekFree = Pointer to FREE data record - // 21->24 [29->32] fNbytesFree = Number of bytes in FREE data record - // 25->28 [33->36] nfree = Number of free data records - // 29->32 [37->40] fNbytesName = Number of bytes in TNamed at creation time - // 33->33 [41->41] fUnits = Number of bytes for file pointers - // 34->37 [42->45] fCompress = Zip compression level - // 38->41 [46->53] fSeekInfo = Pointer to TStreamerInfo record - // 42->45 [54->57] fNbytesInfo = Number of bytes in TStreamerInfo record - // 46->63 [58->75] fUUID = Universal Unique ID -//Begin_Html -/* -<img src="gif/file_layout.gif"> -*/ -//End_Html - // - // The structure of a directory is shown in TDirectoryFile::TDirectoryFile - - if (!gROOT) - ::Fatal("TFile::TFile", "ROOT system not initialized"); - - // store name without the options as name and title - TString sfname1 = fname1; - fNoAnchorInName = kFALSE; - if (sfname1.Index("?") != kNPOS) { - TString s = sfname1(0, sfname1.Index("?")); - SetName(s); - fNoAnchorInName = kTRUE; - } else - SetName(fname1); - - SetTitle(ftitle); - - // accept also URL like "file:..." syntax - fname1 = fUrl.GetFile(); - - // if option contains filetype=raw then go into raw file mode - fIsRootFile = kTRUE; - if (strstr(fUrl.GetOptions(), "filetype=raw")) - fIsRootFile = kFALSE; - - // Init initialization control flag - fInitDone = kFALSE; - fMustFlush = kTRUE; - - // We are opening synchronously - fAsyncHandle = 0; - fAsyncOpenStatus = kAOSNotAsync; - - TDirectoryFile::Build(this, 0); - - fD = -1; - fFree = 0; - fVersion = gROOT->GetVersionInt(); //ROOT version in integer format - fUnits = 4; - fOption = option; - fCompress = compress; - fWritten = 0; - fSumBuffer = 0; - fSum2Buffer = 0; - fBytesRead = 0; - fBytesWrite = 0; - fClassIndex = 0; - fSeekInfo = 0; - fNbytesInfo = 0; - fProcessIDs = 0; - fNProcessIDs = 0; - fOffset = 0; - fCacheRead = 0; - fCacheWrite = 0; - fReadCalls = 0; - SetBit(kBinaryFile, kTRUE); - - fOption.ToUpper(); - - fArchiveOffset = 0; - fIsArchive = kFALSE; - fArchive = TArchiveFile::Open(fUrl.GetUrl(), this); - if (fArchive) { - fname1 = fArchive->GetArchiveName(); - // if no archive member is specified then this TFile is just used - // to read the archive contents - if (!strlen(fArchive->GetMemberName())) - fIsArchive = kTRUE; - } - - if (fOption == "NET") - return; - - if (fOption == "WEB") { - fOption = "READ"; - fWritable = kFALSE; - return; - } - - if (fOption == "NEW") - fOption = "CREATE"; - - Bool_t create = (fOption == "CREATE") ? kTRUE : kFALSE; - Bool_t recreate = (fOption == "RECREATE") ? kTRUE : kFALSE; - Bool_t update = (fOption == "UPDATE") ? kTRUE : kFALSE; - Bool_t read = (fOption == "READ") ? kTRUE : kFALSE; - if (!create && !recreate && !update && !read) { - read = kTRUE; - fOption = "READ"; - } - - Bool_t devnull = kFALSE; - - if (!fname1 || !strlen(fname1)) { - Error("TFile", "file name is not specified"); - goto zombie; - } - - // support dumping to /dev/null on UNIX - if (!strcmp(fname1, "/dev/null") && - !gSystem->AccessPathName(fname1, kWritePermission)) { - devnull = kTRUE; - create = kTRUE; - recreate = kFALSE; - update = kFALSE; - read = kFALSE; - fOption = "CREATE"; - SetBit(kDevNull); - } - - const char *fname; - if ((fname = gSystem->ExpandPathName(fname1))) { - SetName(fname); - delete [] (char*)fname; - fRealName = GetName(); - fname = fRealName.Data(); - } else { - Error("TFile", "error expanding path %s", fname1); - goto zombie; - } - - if (recreate) { - if (!gSystem->AccessPathName(fname, kFileExists)) - gSystem->Unlink(fname); - recreate = kFALSE; - create = kTRUE; - fOption = "CREATE"; - } - if (create && !devnull && !gSystem->AccessPathName(fname, kFileExists)) { - Error("TFile", "file %s already exists", fname); - goto zombie; - } - if (update) { - if (gSystem->AccessPathName(fname, kFileExists)) { - update = kFALSE; - create = kTRUE; - } - if (update && gSystem->AccessPathName(fname, kWritePermission)) { - Error("TFile", "no write permission, could not open file %s", fname); - goto zombie; - } - } - if (read) { - if (gSystem->AccessPathName(fname, kFileExists)) { - Error("TFile", "file %s does not exist", fname); - goto zombie; - } - if (gSystem->AccessPathName(fname, kReadPermission)) { - Error("TFile", "no read permission, could not open file %s", fname); - goto zombie; - } - } - - // Connect to file system stream - if (create || update) { -#ifndef WIN32 - fD = SysOpen(fname, O_RDWR | O_CREAT, 0644); -#else - fD = SysOpen(fname, O_RDWR | O_CREAT | O_BINARY, S_IREAD | S_IWRITE); -#endif - if (fD == -1) { - SysError("TFile", "file %s can not be opened", fname); - goto zombie; - } - fWritable = kTRUE; - } else { -#ifndef WIN32 - fD = SysOpen(fname, O_RDONLY, 0644); -#else - fD = SysOpen(fname, O_RDONLY | O_BINARY, S_IREAD | S_IWRITE); -#endif - if (fD == -1) { - SysError("TFile", "file %s can not be opened for reading", fname); - goto zombie; - } - fWritable = kFALSE; - } - - Init(create); - - return; - -zombie: - // error in file opening occured, make this object a zombie - MakeZombie(); - gDirectory = gROOT; -} - -//______________________________________________________________________________ -TFile::TFile(const TFile &file) : TDirectoryFile(), fInfoCache(0) -{ - // Copy constructor. - - ((TFile&)file).Copy(*this); -} - -//______________________________________________________________________________ -TFile::~TFile() -{ - // File destructor. - - Close(); - - SafeDelete(fProcessIDs); - SafeDelete(fFree); - SafeDelete(fArchive); - SafeDelete(fInfoCache); - SafeDelete(fAsyncHandle); - SafeDelete(fCacheRead); - SafeDelete(fCacheWrite); - - R__LOCKGUARD2(gROOTMutex); - gROOT->GetListOfFiles()->Remove(this); - gROOT->GetUUIDs()->RemoveUUID(GetUniqueID()); - - if (gDebug) - Info("~TFile", "dtor called for %s [%d]", GetName(),this); -} - -//______________________________________________________________________________ -void TFile::Init(Bool_t create) -{ - // Initialize a TFile object. - // TFile implementations providing asynchronous open functionality need to - // override this method to run the appropriate checks before calling this - // standard initialization part. See TXNetFile::Init for an example. - - if (fInitDone) - // Already called once - return; - fInitDone = kTRUE; - - if (fArchive) { - if (fOption != "READ") { - Error("Init", "archive %s can only be opened in read mode", GetName()); - delete fArchive; - fArchive = 0; - fIsArchive = kFALSE; - goto zombie; - } - - fArchive->OpenArchive(); - - if (fIsArchive) return; - - // Make sure the anchor is in the name - if (!fNoAnchorInName) - if (!strchr(GetName(),'#')) - SetName(Form("%s#%s", GetName(), fArchive->GetMemberName())); - - if (fArchive->SetCurrentMember() != -1) - fArchiveOffset = fArchive->GetMemberFilePosition(); - else { - Error("Init", "member %s not found in archive %s", - fArchive->GetMemberName(), fArchive->GetArchiveName()); - delete fArchive; - fArchive = 0; - fIsArchive = kFALSE; - goto zombie; - } - } - - if (!fIsRootFile) { - gDirectory = gROOT; - return; - } - - Int_t nfree; - fBEGIN = (Long64_t)kBEGIN; //First used word in file following the file header - - // make newly opened file the current file and directory - cd(); - - if (create) { - //*-*---------------NEW file - fFree = new TList; - fEND = fBEGIN; //Pointer to end of file - new TFree(fFree, fBEGIN, Long64_t(kStartBigFile)); //Create new free list - - //*-* Write Directory info - Int_t namelen= TNamed::Sizeof(); - Int_t nbytes = namelen + TDirectoryFile::Sizeof(); - TKey *key = new TKey(fName, fTitle, IsA(), nbytes, this); - fNbytesName = key->GetKeylen() + namelen; - fSeekDir = key->GetSeekKey(); - fSeekFree = 0; - fNbytesFree = 0; - WriteHeader(); - char *buffer = key->GetBuffer(); - TNamed::FillBuffer(buffer); - TDirectoryFile::FillBuffer(buffer); - key->WriteFile(); - delete key; - } else { - //*-*----------------UPDATE - char *header = new char[kBEGIN]; - Seek(0); - ReadBuffer(header, kBEGIN); - - // make sure this is a ROOT file - if (strncmp(header, "root", 4)) { - Error("Init", "%s not a ROOT file", GetName()); - delete [] header; - goto zombie; - } - - char *buffer = header + 4; // skip the "root" file identifier - frombuf(buffer, &fVersion); - Int_t headerLength; - frombuf(buffer, &headerLength); - fBEGIN = (Long64_t)headerLength; - if (fVersion < 1000000) { //small file - Int_t send,sfree,sinfo; - frombuf(buffer, &send); fEND = (Long64_t)send; - frombuf(buffer, &sfree); fSeekFree= (Long64_t)sfree; - frombuf(buffer, &fNbytesFree); - frombuf(buffer, &nfree); - frombuf(buffer, &fNbytesName); - frombuf(buffer, &fUnits ); - frombuf(buffer, &fCompress); - frombuf(buffer, &sinfo); fSeekInfo = (Long64_t)sinfo; - frombuf(buffer, &fNbytesInfo); - } else { // new format to support large files - frombuf(buffer, &fEND); - frombuf(buffer, &fSeekFree); - frombuf(buffer, &fNbytesFree); - frombuf(buffer, &nfree); - frombuf(buffer, &fNbytesName); - frombuf(buffer, &fUnits ); - frombuf(buffer, &fCompress); - frombuf(buffer, &fSeekInfo); - frombuf(buffer, &fNbytesInfo); - } - fSeekDir = fBEGIN; - delete [] header; - //*-*-------------Read Free segments structure if file is writable - if (fWritable) { - fFree = new TList; - if (fSeekFree > fBEGIN) { - ReadFree(); - } else { - Warning("Init","file %s probably not closed, cannot read free segments",GetName()); - } - } - //*-*-------------Read directory info - Int_t nbytes = fNbytesName + TDirectoryFile::Sizeof(); - header = new char[nbytes]; - buffer = header; - Seek(fBEGIN); - ReadBuffer(buffer,nbytes); - buffer = header+fNbytesName; - Version_t version,versiondir; - frombuf(buffer,&version); versiondir = version%1000; - fDatimeC.ReadBuffer(buffer); - fDatimeM.ReadBuffer(buffer); - frombuf(buffer, &fNbytesKeys); - frombuf(buffer, &fNbytesName); - Int_t nk = sizeof(Int_t) +sizeof(Version_t) +2*sizeof(Int_t)+2*sizeof(Short_t) - +2*sizeof(Int_t); - if (version > 1000) { - frombuf(buffer, &fSeekDir); - frombuf(buffer, &fSeekParent); - frombuf(buffer, &fSeekKeys); - } else { - Int_t sdir,sparent,skeys; - frombuf(buffer, &sdir); fSeekDir = (Long64_t)sdir; - frombuf(buffer, &sparent); fSeekParent = (Long64_t)sparent; - frombuf(buffer, &skeys); fSeekKeys = (Long64_t)skeys; - } - if (versiondir > 1) fUUID.ReadBuffer(buffer); - - //*-*---------read TKey::FillBuffer info - buffer = header+nk; - TString cname; - cname.ReadBuffer(buffer); - cname.ReadBuffer(buffer); // fName.ReadBuffer(buffer); file may have been renamed - fTitle.ReadBuffer(buffer); - delete [] header; - if (fNbytesName < 10 || fNbytesName > 10000) { - Error("Init","cannot read directory info of file %s", GetName()); - goto zombie; - } - - //*-* -------------Check if file is truncated - Long64_t size; - if ((size = GetSize()) == -1) { - Error("Init", "cannot stat the file %s", GetName()); - goto zombie; - } - - //*-* -------------Read keys of the top directory - if (fSeekKeys > fBEGIN && fEND <= size) { - //normal case. Recover only if file has no keys - TDirectoryFile::ReadKeys(); - gDirectory = this; - if (!GetNkeys()) Recover(); - } else if ((fBEGIN+nbytes == fEND) && (fEND == size)) { - //the file might be open by another process and nothing written to the file yet - Warning("Init","file %s has no keys", GetName()); - gDirectory = this; - } else { - //something had been written to the file. Trailer is missing, must recover - if (fEND > size) { - Error("Init","file %s is truncated at %lld bytes: should be %lld, trying to recover", - GetName(), size, fEND); - } else { - Warning("Init","file %s probably not closed, trying to recover", - GetName()); - } - Int_t nrecov = Recover(); - if (nrecov) { - Warning("Init", "successfully recovered %d keys", nrecov); - } else { - Warning("Init", "no keys recovered, file has been made a Zombie"); - goto zombie; - } - } - } - - { - R__LOCKGUARD2(gROOTMutex); - gROOT->GetListOfFiles()->Add(this); - gROOT->GetUUIDs()->AddUUID(fUUID,this); - - // Create StreamerInfo index - Int_t lenIndex = gROOT->GetListOfStreamerInfo()->GetSize()+1; - if (lenIndex < 5000) lenIndex = 5000; - fClassIndex = new TArrayC(lenIndex); - if (fgReadInfo && fSeekInfo > fBEGIN) ReadStreamerInfo(); - } - - // Count number of TProcessIDs in this file - { - TIter next(fKeys); - TKey *key; - while ((key = (TKey*)next())) { - if (!strcmp(key->GetClassName(),"TProcessID")) fNProcessIDs++; - } - fProcessIDs = new TObjArray(fNProcessIDs+1); - return; - } - -zombie: - // error in file opening occured, make this object a zombie - MakeZombie(); - gDirectory = gROOT; -} - -//______________________________________________________________________________ -void TFile::Close(Option_t *option) -{ - // Close a file. - // If option == "R", all TProcessIDs referenced by this file are deleted. - // Calling TFile::Close("R") might be necessary in case one reads a long list - // of files having TRef, writing some of the referenced objects or TRef - // to a new file. If the TRef or referenced objects of the file being closed - // will not be referenced again, it is possible to minimize the size - // of the TProcessID data structures in memory by forcing a delete of - // the unused TProcessID. - - TString opt = option; - - opt.ToLower(); - - if (!IsOpen()) return; - - - if (gMonitoringWriter && (!fWritable)) - gMonitoringWriter->SendFileReadProgress(this,true); - - if (fIsArchive || !fIsRootFile) { - FlushWriteCache(); - SysClose(fD); - fD = -1; - return; - } - - if (IsWritable()) { - WriteStreamerInfo(); - } - - delete fClassIndex; - fClassIndex = 0; - - // Delete all supported directories structures from memory - // If gDirectory points to this object or any of the nested - // TDirectoryFile, TDirectoryFile::Close will induce the proper cd. - TDirectoryFile::Close(); - - if (IsWritable()) { - TFree *f1 = (TFree*)fFree->First(); - if (f1) { - WriteFree(); //*-*- Write free segments linked list - WriteHeader(); //*-*- Now write file header - } - } - - FlushWriteCache(); - - // Delete free segments from free list (but don't delete list header) - if (fFree) { - fFree->Delete(); - } - - if (IsOpen()) { - SysClose(fD); - fD = -1; - } - - fWritable = kFALSE; - - // delete the TProcessIDs - TList pidDeleted; - TIter next(fProcessIDs); - TProcessID *pid; - while ((pid = (TProcessID*)next())) { - if (!pid->DecrementCount()) { - if (pid != TProcessID::GetSessionProcessID()) pidDeleted.Add(pid); - } else if(opt.Contains("r")) { - pid->Clear(); - } - } - pidDeleted.Delete(); - - R__LOCKGUARD2(gROOTMutex); - gROOT->GetListOfFiles()->Remove(this); - gROOT->GetListOfBrowsers()->RecursiveRemove(this); - -} - -//____________________________________________________________________________________ -TKey* TFile::CreateKey(TDirectory* mother, const TObject* obj, const char* name, Int_t bufsize) -{ - // Creates key for object and converts data to buffer. - - return new TKey(obj, name, bufsize, mother); -} - -//____________________________________________________________________________________ -TKey* TFile::CreateKey(TDirectory* mother, const void* obj, const TClass* cl, const char* name, Int_t bufsize) -{ - // Creates key for object and converts data to buffer. - - return new TKey(obj, cl, name, bufsize, mother); -} - -//______________________________________________________________________________ -void TFile::Delete(const char *namecycle) -{ - // Delete object namecycle. - // Namecycle identifies an object in the top directory of the file - // namecycle has the format name;cycle - // name = * means all - // cycle = * means all cycles (memory and keys) - // cycle = "" or cycle = 9999 ==> apply to a memory object - // When name=* use T* to delete subdirectories also - // - // Examples: - // foo : delete object named foo in memory - // foo;1 : delete cycle 1 of foo on file - // foo;* : delete all cycles of foo on disk and also from memory - // *;2 : delete all objects on file having the cycle 2 - // *;* : delete all objects from memory and file - // T*;* : delete all objects from memory and file and all subdirectories - - if (gDebug) - Info("Delete", "deleting name = %s", namecycle); - - TDirectoryFile::Delete(namecycle); -} - -//______________________________________________________________________________ -void TFile::Draw(Option_t *option) -{ - // Fill Graphics Structure and Paint. - // Loop on all objects (memory or file) and all subdirectories. - - GetList()->R__FOR_EACH(TObject,Draw)(option); -} - -//______________________________________________________________________________ -void TFile::DrawMap(const char *keys, Option_t *option) -{ - // Draw map of objects in this file. - - TPluginHandler *h; - if ((h = gROOT->GetPluginManager()->FindHandler("TFileDrawMap"))) { - if (h->LoadPlugin() == -1) - return; - h->ExecPlugin(3, this, keys, option); - } -} - -//______________________________________________________________________________ -void TFile::Flush() -{ - // Synchronize a file's in-core and on-disk states. - if (IsOpen() && fWritable) { - FlushWriteCache(); - if (SysSync(fD) < 0) { - // Write the system error only once for this file - SetBit(kWriteError); SetWritable(kFALSE); - SysError("Flush", "error flushing file %s", GetName()); - } - } -} - -//______________________________________________________________________________ -Bool_t TFile::FlushWriteCache() -{ - // Flush the write cache if active. - // Return kTRUE in case of error - - if (fCacheWrite && IsOpen() && fWritable) - return fCacheWrite->Flush(); - return kFALSE; -} - -//______________________________________________________________________________ -void TFile::FillBuffer(char *&buffer) -{ - // Encode file output buffer. - // The file output buffer contains only the FREE data record. - - Version_t version = TFile::Class_Version(); - tobuf(buffer, version); -} - -//______________________________________________________________________________ -Int_t TFile::GetBestBuffer() const -{ - // Return the best buffer size of objects on this file. - // The best buffer size is estimated based on the current mean value - // and standard deviation of all objects written so far to this file. - // Returns mean value + one standard deviation. - - if (!fWritten) return TBuffer::kInitialSize; - Double_t mean = fSumBuffer/fWritten; - Double_t rms2 = TMath::Abs(fSum2Buffer/fSumBuffer -mean*mean); - return (Int_t)(mean + sqrt(rms2)); -} - -//______________________________________________________________________________ -Float_t TFile::GetCompressionFactor() -{ - // Return the file compression factor. - // Add total number of compressed/uncompressed bytes for each key. - // return ratio of the two. - - Short_t keylen; - UInt_t datime; - Int_t nbytes, objlen, nwh = 64; - char *header = new char[fBEGIN]; - char *buffer; - Long64_t idcur = fBEGIN; - Float_t comp,uncomp; - comp = uncomp = fBEGIN; - - while (idcur < fEND-100) { - Seek(idcur); - ReadBuffer(header, nwh); - buffer=header; - frombuf(buffer, &nbytes); - if (nbytes < 0) { - idcur -= nbytes; - Seek(idcur); - continue; - } - if (nbytes == 0) break; //this may happen when the file is corrupted - Version_t versionkey; - frombuf(buffer, &versionkey); - frombuf(buffer, &objlen); - frombuf(buffer, &datime); - frombuf(buffer, &keylen); - if (!objlen) objlen = nbytes-keylen; - comp += nbytes; - uncomp += keylen + objlen; - idcur += nbytes; - } - delete [] header; - return uncomp/comp; -} - -//______________________________________________________________________________ -Int_t TFile::GetErrno() const -{ - // Method returning errno. Is overriden in TRFIOFile. - - return TSystem::GetErrno(); -} - -//______________________________________________________________________________ -void TFile::ResetErrno() const -{ - // Method resetting the errno. Is overridden in TRFIOFile. - - TSystem::ResetErrno(); -} - -//______________________________________________________________________________ -TFileCacheRead *TFile::GetCacheRead() const -{ - // Return a pointer to the current read cache. - - return fCacheRead; -} - -//______________________________________________________________________________ -TFileCacheWrite *TFile::GetCacheWrite() const -{ - // Return a pointer to the current write cache. - - return fCacheWrite; -} - -//______________________________________________________________________________ -Int_t TFile::GetRecordHeader(char *buf, Long64_t first, Int_t maxbytes, Int_t &nbytes, Int_t &objlen, Int_t &keylen) -{ - // Read the logical record header starting at position first. - // Maxbytes bytes are read into buf the function reads nread bytes - // where nread is the minimum of maxbytes and the number of bytes - // before the end of file. The function returns nread. - // In output arguments: - // nbytes : number of bytes in record - // if negative, this is a deleted record - // if 0, cannot read record, wrong value of argument first - // objlen : uncompressed object size - // keylen : length of logical record header - // Note that the arguments objlen and keylen are returned only - // if maxbytes >=16 - - if (first < fBEGIN) return 0; - if (first > fEND) return 0; - Seek(first); - Int_t nread = maxbytes; - if (first+maxbytes > fEND) nread = fEND-maxbytes; - if (nread < 4) { - Warning("GetRecordHeader","%s: parameter maxbytes = %d must be >= 4", - GetName(), nread); - return nread; - } - ReadBuffer(buf,nread); - Version_t versionkey; - Short_t klen; - UInt_t datime; - Int_t nb,olen; - char *buffer = buf; - frombuf(buffer,&nb); - nbytes = nb; - if (nb < 0) return nread; - // const Int_t headerSize = Int_t(sizeof(nb) +sizeof(versionkey) +sizeof(olen) +sizeof(datime) +sizeof(klen)); - const Int_t headerSize = 16; - if (nread < headerSize) return nread; - frombuf(buffer, &versionkey); - frombuf(buffer, &olen); - frombuf(buffer, &datime); - frombuf(buffer, &klen); - if (!olen) olen = nbytes-klen; - objlen = olen; - keylen = klen; - return nread; -} - -//______________________________________________________________________________ -Long64_t TFile::GetSize() const -{ - // Returns the current file size. Returns -1 in case the file could not - // be stat'ed. - - Long64_t size; - - if (fArchive && fArchive->GetMember()) { - size = fArchive->GetMember()->GetDecompressedSize(); - } else { - Long_t id, flags, modtime; - if (const_cast<TFile*>(this)->SysStat(fD, &id, &size, &flags, &modtime)) { - Error("GetSize", "cannot stat the file %s", GetName()); - return -1; - } - } - return size; -} - -//______________________________________________________________________________ -const TList *TFile::GetStreamerInfoCache() -{ - // Returns the cached list of StreamerInfos used in this file. - - return fInfoCache ? fInfoCache : (fInfoCache=GetStreamerInfoList()); -} - -//______________________________________________________________________________ -TList *TFile::GetStreamerInfoList() -{ - // Read the list of TStreamerInfo objects written to this file. - // The function returns a TList. It is the user'responsability - // to delete the list created by this function. - // - // Using the list, one can access additional information,eg: - // TFile f("myfile.root"); - // TList *list = f.GetStreamerInfoList(); - // TStreamerInfo *info = (TStreamerInfo*)list->FindObject("MyClass"); - // Int_t classversionid = info->GetClassVersion(); - // delete list; - - TList *list = 0; - if (fSeekInfo) { - TDirectory::TContext ctx(gDirectory,this); // gFile and gDirectory used in ReadObj - - TKey *key = new TKey(this); - char *buffer = new char[fNbytesInfo+1]; - char *buf = buffer; - Seek(fSeekInfo); - ReadBuffer(buf,fNbytesInfo); - key->ReadKeyBuffer(buf); - list = (TList*)key->ReadObj(); - if (list) list->SetOwner(); - delete [] buffer; - delete key; - } else { - list = (TList*)Get("StreamerInfo"); //for versions 2.26 (never released) - } - - if (list == 0) { - Info("GetStreamerInfoList", "cannot find the StreamerInfo record in file %s", - GetName()); - return 0; - } - - return list; -} - -//______________________________________________________________________________ -void TFile::ls(Option_t *option) const -{ - // List File contents. - // Indentation is used to identify the file tree. - // Subdirectories are listed first, then objects in memory, - // then objects on the file. - - TROOT::IndentLevel(); - cout <<ClassName()<<"**\t\t"<<GetName()<<"\t"<<GetTitle()<<endl; - TROOT::IncreaseDirLevel(); - TDirectoryFile::ls(option); - TROOT::DecreaseDirLevel(); -} - -//______________________________________________________________________________ -Bool_t TFile::IsOpen() const -{ - // Returns kTRUE in case file is open and kFALSE if file is not open. - - return fD == -1 ? kFALSE : kTRUE; -} - -//______________________________________________________________________________ -void TFile::MakeFree(Long64_t first, Long64_t last) -{ - // Mark unused bytes on the file. - // The list of free segments is in the fFree linked list. - // When an object is deleted from the file, the freed space is added - // into the FREE linked list (fFree). The FREE list consists of a chain - // of consecutive free segments on the file. At the same time, the first - // 4 bytes of the freed record on the file are overwritten by GAPSIZE - // where GAPSIZE = -(Number of bytes occupied by the record). - - TFree *f1 = (TFree*)fFree->First(); - if (!f1) return; - TFree *newfree = f1->AddFree(fFree,first,last); - if(!newfree) return; - Long64_t nfirst = newfree->GetFirst(); - Long64_t nlast = newfree->GetLast(); - Long64_t nbytesl= nlast-nfirst+1; - if (nbytesl > 2000000000) nbytesl = 2000000000; - Int_t nbytes = -Int_t (nbytesl); - Int_t nb = sizeof(Int_t); - char * buffer = new char[nb]; - char * psave = buffer; - tobuf(buffer, nbytes); - if (last == fEND-1) fEND = nfirst; - Seek(nfirst); - WriteBuffer(psave, nb); - Flush(); - delete [] psave; -} - -//______________________________________________________________________________ -void TFile::Map() -{ - // List the contents of a file sequentially. - // For each logical record found, it prints: - // Date/Time Record_Adress Logical_Record_Length ClassName CompressionFactor - // - // Example of output - // 20010404/150437 At:64 N=150 TFile - // 20010404/150440 At:214 N=28326 TBasket CX = 1.13 - // 20010404/150440 At:28540 N=29616 TBasket CX = 1.08 - // 20010404/150440 At:58156 N=29640 TBasket CX = 1.08 - // 20010404/150440 At:87796 N=29076 TBasket CX = 1.10 - // 20010404/150440 At:116872 N=10151 TBasket CX = 3.15 - // 20010404/150441 At:127023 N=28341 TBasket CX = 1.13 - // 20010404/150441 At:155364 N=29594 TBasket CX = 1.08 - // 20010404/150441 At:184958 N=29616 TBasket CX = 1.08 - // 20010404/150441 At:214574 N=29075 TBasket CX = 1.10 - // 20010404/150441 At:243649 N=9583 TBasket CX = 3.34 - // 20010404/150442 At:253232 N=28324 TBasket CX = 1.13 - // 20010404/150442 At:281556 N=29641 TBasket CX = 1.08 - // 20010404/150442 At:311197 N=29633 TBasket CX = 1.08 - // 20010404/150442 At:340830 N=29091 TBasket CX = 1.10 - // 20010404/150442 At:369921 N=10341 TBasket CX = 3.09 - // 20010404/150442 At:380262 N=509 TH1F CX = 1.93 - // 20010404/150442 At:380771 N=1769 TH2F CX = 4.32 - // 20010404/150442 At:382540 N=1849 TProfile CX = 1.65 - // 20010404/150442 At:384389 N=18434 TNtuple CX = 4.51 - // 20010404/150442 At:402823 N=307 KeysList - // 20010404/150443 At:403130 N=4548 StreamerInfo CX = 3.65 - // 20010404/150443 At:407678 N=86 FreeSegments - // 20010404/150443 At:407764 N=1 END - - Short_t keylen,cycle; - UInt_t datime; - Int_t nbytes,date,time,objlen,nwheader; - Long64_t seekkey,seekpdir; - char *buffer; - char nwhc; - Long64_t idcur = fBEGIN; - - nwheader = 64; - Int_t nread = nwheader; - - char header[kBEGIN]; - char classname[512]; - - while (idcur < fEND) { - Seek(idcur); - if (idcur+nread >= fEND) nread = fEND-idcur-1; - ReadBuffer(header, nread); - buffer=header; - frombuf(buffer, &nbytes); - if (!nbytes) { - Printf("Address = %lld\tNbytes = %d\t=====E R R O R=======", idcur, nbytes); - break; - } - if (nbytes < 0) { - Printf("Address = %lld\tNbytes = %d\t=====G A P===========", idcur, nbytes); - idcur -= nbytes; - Seek(idcur); - continue; - } - Version_t versionkey; - frombuf(buffer, &versionkey); - frombuf(buffer, &objlen); - frombuf(buffer, &datime); - frombuf(buffer, &keylen); - frombuf(buffer, &cycle); - if (versionkey > 1000) { - frombuf(buffer, &seekkey); - frombuf(buffer, &seekpdir); - } else { - Int_t skey,sdir; - frombuf(buffer, &skey); seekkey = (Long64_t)skey; - frombuf(buffer, &sdir); seekpdir = (Long64_t)sdir; - } - frombuf(buffer, &nwhc); - int i; - for (i = 0;i < nwhc; i++) frombuf(buffer, &classname[i]); - classname[(int)nwhc] = '\0'; //cast to avoid warning with gcc3.4 - if (idcur == fSeekFree) strcpy(classname,"FreeSegments"); - if (idcur == fSeekInfo) strcpy(classname,"StreamerInfo"); - if (idcur == fSeekKeys) strcpy(classname,"KeysList"); - TDatime::GetDateTime(datime, date, time); - if (objlen != nbytes-keylen) { - Float_t cx = Float_t(objlen+keylen)/Float_t(nbytes); - //Printf("%d/%06d At:%-8d N=%-8d %-14s CX = %5.2f",date,time,idcur,nbytes,classname,cx); - Printf("%d/%06d At:%lld N=%-8d %-14s CX = %5.2f",date,time,idcur,nbytes,classname,cx); - } else { - //Printf("%d/%06d At:%-8d N=%-8d %-14s",date,time,idcur,nbytes,classname); - Printf("%d/%06d At:%lld N=%-8d %-14s",date,time,idcur,nbytes,classname); - } - idcur += nbytes; - } - //Printf("%d/%06d At:%-8d N=%-8d %-14s",date,time,idcur,1,"END"); - Printf("%d/%06d At:%lld N=%-8d %-14s",date,time,idcur,1,"END"); -} - -//______________________________________________________________________________ -void TFile::Paint(Option_t *option) -{ - // Paint all objects in the file. - - GetList()->R__FOR_EACH(TObject,Paint)(option); -} - -//______________________________________________________________________________ -void TFile::Print(Option_t *option) const -{ - // Print all objects in the file. - - Printf("TFile: name=%s, title=%s, option=%s", GetName(), GetTitle(), GetOption()); - GetList()->R__FOR_EACH(TObject,Print)(option); -} - -//______________________________________________________________________________ -Bool_t TFile::ReadBuffer(char *buf, Int_t len) -{ - // Read a buffer from the file. This is the basic low level read operation. - // Returns kTRUE in case of failure. - - if (IsOpen()) { - - Int_t st; - if ((st = ReadBufferViaCache(buf, len))) { - if (st == 2) - return kTRUE; - return kFALSE; - } - - ssize_t siz; - - Double_t start = 0; - if (gPerfStats != 0) start = TTimeStamp(); - - if (gMonitoringWriter) - gMonitoringWriter->SendFileReadProgress(this); - - while ((siz = SysRead(fD, buf, len)) < 0 && GetErrno() == EINTR) - ResetErrno(); - - if (siz < 0) { - SysError("ReadBuffer", "error reading from file %s", GetName()); - return kTRUE; - } - if (siz != len) { - Error("ReadBuffer", "error reading all requested bytes from file %s, got %d of %d", - GetName(), siz, len); - return kTRUE; - } - fBytesRead += siz; - fgBytesRead += siz; - fReadCalls++; - fgReadCalls++; - - if (gPerfStats != 0) { - gPerfStats->FileReadEvent(this, len, double(TTimeStamp())-start); - } - return kFALSE; - } - return kTRUE; -} - -//______________________________________________________________________________ -Bool_t TFile::ReadBuffers(char *buf, Long64_t *pos, Int_t *len, Int_t nbuf) -{ - // Read the nbuf blocks described in arrays pos and len, - // where pos[i] is the seek position of block i of length len[i]. - // Note that for nbuf=1, this call is equivalent to TFile::ReafBuffer. - // This function is overloaded by TNetFile, TWebFile, etc. - // Returns kTRUE in case of failure. - - Int_t k = 0; - Bool_t result = kTRUE; - TFileCacheRead *old = fCacheRead; - fCacheRead = 0; - for (Int_t i = 0; i < nbuf; i++) { - Seek(pos[i]); - result = ReadBuffer(&buf[k], len[i]); - if (result) break; - k += len[i]; - } - fCacheRead = old; - return result; -} - -//______________________________________________________________________________ -Int_t TFile::ReadBufferViaCache(char *buf, Int_t len) -{ - // Read buffer via cache. Returns 0 if the requested block is - // not in the cache, 1 in case read via cache was successful, - // 2 in case read via cache failed. - - Long64_t off = GetRelOffset(); - if (fCacheRead) { - Int_t st = fCacheRead->ReadBuffer(buf, off, len); - if (st < 0) - return 2; // failure reading - else if (st == 1) { - // fOffset might have been changed via TFileCacheRead::ReadBuffer(), reset it - Seek(off + len); - return 1; - } - // fOffset might have been changed via TFileCacheRead::ReadBuffer(), reset it - Seek(off); - } else { - // if write cache is active check if data still in write cache - if (fWritable && fCacheWrite) { - if (fCacheWrite->ReadBuffer(buf, off, len) == 0) { - Seek(off + len); - return 1; - } - // fOffset might have been changed via TFileCacheWrite::ReadBuffer(), reset it - Seek(off); - } - } - - return 0; -} - -//______________________________________________________________________________ -void TFile::ReadFree() -{ - // Read the FREE linked list. - // Every file has a linked list (fFree) of free segments. - // This linked list has been written on the file via WriteFree - // as a single data record. - - TKey *headerfree = new TKey(fSeekFree, fNbytesFree, this); - headerfree->ReadFile(); - char *buffer = headerfree->GetBuffer(); - headerfree->ReadKeyBuffer(buffer); - buffer = headerfree->GetBuffer(); - while (1) { - TFree *afree = new TFree(); - afree->ReadBuffer(buffer); - fFree->Add(afree); - if (afree->GetLast() > fEND) break; - } - delete headerfree; -} - -//______________________________________________________________________________ -TProcessID *TFile::ReadProcessID(UShort_t pidf) -{ - //The TProcessID with number pidf is read from this file. - //If the object is not already entered in the gROOT list, it is added. - - TProcessID *pid = 0; - TObjArray *pids = GetListOfProcessIDs(); - if (pidf < pids->GetSize()) pid = (TProcessID *)pids->UncheckedAt(pidf); - if (pid) { - pid->CheckInit(); - return pid; - } - - //check if fProcessIDs[uid] is set in file - //if not set, read the process uid from file - char pidname[32]; - sprintf(pidname,"ProcessID%d",pidf); - TDirectory *dirsav = gDirectory; - this->cd(); - pid = (TProcessID *)Get(pidname); - if (dirsav) dirsav->cd(); - if (gDebug > 0) { - printf("ReadProcessID, name=%s, file=%s, pid=%lx\n",pidname,GetName(),(Long_t)pid); - } - if (!pid) { - //file->Error("ReadProcessID","Cannot find %s in file %s",pidname,file->GetName()); - return pid; - } - //check that a similar pid is not already registered in fgPIDs - TObjArray *pidslist = TProcessID::GetPIDs(); - TIter next(pidslist); - TProcessID *p; - while ((p = (TProcessID*)next())) { - if (!strcmp(p->GetTitle(),pid->GetTitle())) { - delete pid; - pids->AddAtAndExpand(p,pidf); - p->IncrementCount(); - return p; - } - } - pids->AddAtAndExpand(pid,pidf); - pid->IncrementCount(); - pidslist->Add(pid); - Int_t ind = pidslist->IndexOf(pid); - pid->SetUniqueID((UInt_t)ind); - return pid; -} - - -//______________________________________________________________________________ -Int_t TFile::Recover() -{ - // Attempt to recover file if not correctly closed. - // The function returns the number of keys that have been recovered. - // If no keys can be recovered, the file will be declared Zombie by - // the calling function. This function is automatically called when - // opening a file. - // - // If the file is open in read only mode, the file is not modified. - // If open in update mode and the function finds something to recover, - // a new directory header is written to the file. When opening the file gain - // no message from Recover will be reported. - // If keys have been recovered, the file is usable and you can safely - // read the corresponding objects. - // If the file is not usable (a zombie), you can test for this case - // with code like: - // TFile f("myfile.root"); - // if (f.IsZombie()) {file is unusable) - // If the file has been recovered, the bit kRecovered is set in the TFile object in memory. - // You can test if the file has been recovered with - // if (f.TestBit(TFile::kRecovered)) {.. the file has been recovered} - // - // When writing TTrees to a file, it is important to save the Tree header - // at regular intervals (see TTree::AutoSave). If a file containing a Tree - // is recovered, the last Tree header written to the file will be used. - // In this case all the entries in all the branches written before writing - // the header are valid entries. - - Short_t keylen,cycle; - UInt_t datime; - Int_t nbytes,date,time,objlen,nwheader; - Long64_t seekkey,seekpdir; - char header[1024]; - char *buffer, *bufread; - char nwhc; - Long64_t idcur = fBEGIN; - - Long64_t size; - if ((size = GetSize()) == -1) { - Error("Recover", "cannot stat the file %s", GetName()); - return 0; - } - - fEND = Long64_t(size); - - if (fWritable && !fFree) fFree = new TList; - - TKey *key; - Int_t nrecov = 0; - nwheader = 1024; - Int_t nread = nwheader; - - while (idcur < fEND) { - Seek(idcur); - if (idcur+nread >= fEND) nread = fEND-idcur-1; - ReadBuffer(header, nread); - buffer = header; - bufread = header; - frombuf(buffer, &nbytes); - if (!nbytes) { - Printf("Address = %lld\tNbytes = %d\t=====E R R O R=======", idcur, nbytes); - break; - } - if (nbytes < 0) { - idcur -= nbytes; - if (fWritable) new TFree(fFree,idcur,idcur-nbytes-1); - Seek(idcur); - continue; - } - Version_t versionkey; - frombuf(buffer, &versionkey); - frombuf(buffer, &objlen); - frombuf(buffer, &datime); - frombuf(buffer, &keylen); - frombuf(buffer, &cycle); - if (versionkey > 1000) { - frombuf(buffer, &seekkey); - frombuf(buffer, &seekpdir); - } else { - Int_t skey,sdir; - frombuf(buffer, &skey); seekkey = (Long64_t)skey; - frombuf(buffer, &sdir); seekpdir = (Long64_t)sdir; - } - frombuf(buffer, &nwhc); - char *classname = 0; - if (nwhc <= 0 || nwhc > 100) break; - classname = new char[nwhc+1]; - int i; - for (i = 0;i < nwhc; i++) frombuf(buffer, &classname[i]); - classname[nwhc] = '\0'; - TDatime::GetDateTime(datime, date, time); - if (seekpdir == fSeekDir && strcmp(classname,"TFile") && strcmp(classname,"TBasket")) { - key = new TKey(this); - key->ReadKeyBuffer(bufread); - if (!strcmp(key->GetName(),"StreamerInfo")) { - fSeekInfo = seekkey; - SafeDelete(fInfoCache); - fNbytesInfo = nbytes; - } else { - AppendKey(key); - nrecov++; - SetBit(kRecovered); - Info("Recover", "%s, recovered key %s:%s at address %lld",GetName(),key->GetClassName(),key->GetName(),idcur); - } - } - delete [] classname; - idcur += nbytes; - } - if (fWritable) { - Long64_t max_file_size = Long64_t(kStartBigFile); - if (max_file_size < fEND) max_file_size = fEND+1000000000; - new TFree(fFree,fEND,max_file_size); - if (nrecov) Write(); - } - return nrecov; -} - -//______________________________________________________________________________ -Int_t TFile::ReOpen(Option_t *mode) -{ - // Reopen a file with a different access mode, like from READ to - // UPDATE or from NEW, CREATE, RECREATE, UPDATE to READ. Thus the - // mode argument can be either "READ" or "UPDATE". The method returns - // 0 in case the mode was successfully modified, 1 in case the mode - // did not change (was already as requested or wrong input arguments) - // and -1 in case of failure, in which case the file cannot be used - // anymore. The current directory (gFile) is changed to this file. - - cd(); - - TString opt = mode; - opt.ToUpper(); - - if (opt != "READ" && opt != "UPDATE") { - Error("ReOpen", "mode must be either READ or UPDATE, not %s", opt.Data()); - return 1; - } - - if (opt == fOption || (opt == "UPDATE" && fOption == "CREATE")) - return 1; - - if (opt == "READ") { - // switch to READ mode - - // flush data still in the pipeline and close the file - if (IsOpen() && IsWritable()) { - WriteStreamerInfo(); - - // save directory key list and header - Save(); - - TFree *f1 = (TFree*)fFree->First(); - if (f1) { - WriteFree(); // write free segments linked list - WriteHeader(); // now write file header - } - - FlushWriteCache(); - - // delete free segments from free list - if (fFree) { - fFree->Delete(); - SafeDelete(fFree); - } - - SysClose(fD); - fD = -1; - - SetWritable(kFALSE); - } - - // open in READ mode - fOption = opt; // set fOption before SysOpen() for TNetFile -#ifndef WIN32 - fD = SysOpen(fRealName, O_RDONLY, 0644); -#else - fD = SysOpen(fRealName, O_RDONLY | O_BINARY, S_IREAD | S_IWRITE); -#endif - if (fD == -1) { - SysError("ReOpen", "file %s can not be opened in read mode", GetName()); - return -1; - } - SetWritable(kFALSE); - - } else { - // switch to UPDATE mode - - // close readonly file - if (IsOpen()) { - SysClose(fD); - fD = -1; - } - - // open in UPDATE mode - fOption = opt; // set fOption before SysOpen() for TNetFile -#ifndef WIN32 - fD = SysOpen(fRealName, O_RDWR | O_CREAT, 0644); -#else - fD = SysOpen(fRealName, O_RDWR | O_CREAT | O_BINARY, S_IREAD | S_IWRITE); -#endif - if (fD == -1) { - SysError("ReOpen", "file %s can not be opened in update mode", GetName()); - return -1; - } - SetWritable(kTRUE); - - fFree = new TList; - if (fSeekFree > fBEGIN) - ReadFree(); - else - Warning("ReOpen","file %s probably not closed, cannot read free segments", GetName()); - } - - return 0; -} - -//______________________________________________________________________________ -void TFile::Seek(Long64_t offset, ERelativeTo pos) -{ - // Seek to a specific position in the file. Pos it either kBeg, kCur or kEnd. - - int whence = 0; - switch (pos) { - case kBeg: - whence = SEEK_SET; - offset += fArchiveOffset; - break; - case kCur: - whence = SEEK_CUR; - break; - case kEnd: - whence = SEEK_END; - // this option is not used currently in the ROOT code - if (fArchiveOffset) - Error("Seek", "seeking from end in archive is not (yet) supported"); - break; - } - Long64_t retpos; - if ((retpos = SysSeek(fD, offset, whence)) < 0) - SysError("Seek", "cannot seek to position %lld in file %s, retpos=%lld", - offset, GetName(), retpos); - - // used by TFileCacheRead::ReadBuffer() - fOffset = retpos; -} - -//______________________________________________________________________________ -void TFile::SetCompressionLevel(Int_t level) -{ - // Set level of compression for this file: - // level = 0 objects written to this file will not be compressed. - // level = 1 minimal compression level but fast. - // .... - // level = 9 maximal compression level but slow. - // - // Note that the compression level may be changed at any time. - // The new compression level will only apply to newly written objects. - // The function TFile::Map shows the compression factor - // for each object written to this file. - // The function TFile::GetCompressionFactor returns the global - // compression factor for this file. - - if (level < 0) level = 0; - if (level > 9) level = 9; - fCompress = level; -} - -//______________________________________________________________________________ -void TFile::SetCacheRead(TFileCacheRead *cache) -{ - // Set a pointer to the read cache. - - fCacheRead = cache; -} - -//______________________________________________________________________________ -void TFile::SetCacheWrite(TFileCacheWrite *cache) -{ - // Set a pointer to the write cache. - // If file is null the existing write cache is deleted. - - if (!cache && fCacheWrite) delete fCacheWrite; - fCacheWrite = cache; -} - -//______________________________________________________________________________ -Int_t TFile::Sizeof() const -{ - // Return the size in bytes of the file header. - - return 0; -} - -//_______________________________________________________________________ -void TFile::Streamer(TBuffer &b) -{ - // Stream a TFile object. - - if (b.IsReading()) { - b.ReadVersion(); //Version_t v = b.ReadVersion(); - } else { - b.WriteVersion(TFile::IsA()); - } -} - -//_______________________________________________________________________ -void TFile::SumBuffer(Int_t bufsize) -{ - // Increment statistics for buffer sizes of objects in this file. - - fWritten++; - fSumBuffer += bufsize; - fSum2Buffer += bufsize*bufsize; -} - -//_______________________________________________________________________ -void TFile::UseCache(Int_t /*maxCacheSize*/, Int_t /*pageSize*/) -{ - // Dummy function kept for backward compatibility. - // The read cache is now managed by TFileCacheRead - // The write cache is now managed by TFileCacheWrite - // Both caches are created automatically by the system. - -} - -//______________________________________________________________________________ -Int_t TFile::Write(const char *, Int_t opt, Int_t bufsiz) -{ - // Write memory objects to this file. - // Loop on all objects in memory (including subdirectories). - // A new key is created in the KEYS linked list for each object. - // The list of keys is then saved on the file (via WriteKeys) - // as a single data record. - // For values of opt see TObject::Write(). - // The directory header info is rewritten on the directory header record. - // The linked list of FREE segments is written. - // The file header is written (bytes 1->fBEGIN). - - if (!IsWritable()) { - if (!TestBit(kWriteError)) { - // Do not print the warning if we already had a SysError. - Warning("Write", "file %s not opened in write mode", GetName()); - } - return 0; - } - - TDirectory *cursav = gDirectory; - cd(); - - if (gDebug) { - if (!GetTitle() || strlen(GetTitle()) == 0) - Info("Write", "writing name = %s", GetName()); - else - Info("Write", "writing name = s title = %s", GetName(), GetTitle()); - } - - fMustFlush = kFALSE; - Int_t nbytes = TDirectoryFile::Write(0, opt, bufsiz); // Write directory tree - WriteStreamerInfo(); - WriteFree(); // Write free segments linked list - WriteHeader(); // Now write file header - fMustFlush = kTRUE; - - cursav->cd(); - return nbytes; -} - -//______________________________________________________________________________ -Int_t TFile::Write(const char *n, Int_t opt, Int_t bufsize) const -{ - // One can not save a const TDirectory object. - - Error("Write const","A const TFile object should not be saved. We try to proceed anyway."); - return const_cast<TFile*>(this)->Write(n, opt, bufsize); -} - -//______________________________________________________________________________ -Bool_t TFile::WriteBuffer(const char *buf, Int_t len) -{ - // Write a buffer to the file. This is the basic low level write operation. - // Returns kTRUE in case of failure. - - if (IsOpen() && fWritable) { - - Int_t st; - if ((st = WriteBufferViaCache(buf, len))) { - if (st == 2) - return kTRUE; - return kFALSE; - } - - ssize_t siz; - gSystem->IgnoreInterrupt(); - while ((siz = SysWrite(fD, buf, len)) < 0 && GetErrno() == EINTR) - ResetErrno(); - gSystem->IgnoreInterrupt(kFALSE); - if (siz < 0) { - // Write the system error only once for this file - SetBit(kWriteError); SetWritable(kFALSE); - SysError("WriteBuffer", "error writing to file %s (%d)", GetName(), siz); - return kTRUE; - } - if (siz != len) { - SetBit(kWriteError); - Error("WriteBuffer", "error writing all requested bytes to file %s, wrote %d of %d", - GetName(), siz, len); - return kTRUE; - } - fBytesWrite += siz; - fgBytesWrite += siz; - - return kFALSE; - } - return kTRUE; -} - -//______________________________________________________________________________ -Int_t TFile::WriteBufferViaCache(const char *buf, Int_t len) -{ - // Write buffer via cache. Returns 0 if cache is not active, 1 in case - // write via cache was successful, 2 in case write via cache failed. - - if (!fCacheWrite) return 0; - - Int_t st; - Long64_t off = GetRelOffset(); - if ((st = fCacheWrite->WriteBuffer(buf, off, len)) < 0) { - SetBit(kWriteError); - Error("WriteBuffer", "error writing to cache"); - return 2; - } - if (st > 0) { - // fOffset might have been changed via TFileCacheWrite::WriteBuffer(), reset it - Seek(off + len); - return 1; - } - return 0; -} - -//______________________________________________________________________________ -void TFile::WriteFree() -{ - // Write FREE linked list on the file. - // The linked list of FREE segments (fFree) is written as a single data - // record. - - //*-* Delete old record if it exists - if (fSeekFree != 0){ - MakeFree(fSeekFree, fSeekFree + fNbytesFree -1); - } - - Int_t nbytes = 0; - TFree *afree; - TIter next (fFree); - while ((afree = (TFree*) next())) { - nbytes += afree->Sizeof(); - } - if (!nbytes) return; - TKey *key = new TKey(fName,fTitle,IsA(),nbytes,this); - if (key->GetSeekKey() == 0) { - delete key; - return; - } - char *buffer = key->GetBuffer(); - - next.Reset(); - while ((afree = (TFree*) next())) { - afree->FillBuffer(buffer); - } - fNbytesFree = key->GetNbytes(); - fSeekFree = key->GetSeekKey(); - key->WriteFile(); - delete key; -} - -//______________________________________________________________________________ -void TFile::WriteHeader() -{ - // Write File Header. - - SafeDelete(fInfoCache); - TFree *lastfree = (TFree*)fFree->Last(); - if (lastfree) fEND = lastfree->GetFirst(); - const char *root = "root"; - char *psave = new char[fBEGIN]; - char *buffer = psave; - Int_t nfree = fFree->GetSize(); - memcpy(buffer, root, 4); buffer += 4; - Int_t version = fVersion; - if (fEND > kStartBigFile) {version += 1000000; fUnits = 8;} - tobuf(buffer, version); - tobuf(buffer, (Int_t)fBEGIN); - if (version < 1000000) { - tobuf(buffer, (Int_t)fEND); - tobuf(buffer, (Int_t)fSeekFree); - tobuf(buffer, fNbytesFree); - tobuf(buffer, nfree); - tobuf(buffer, fNbytesName); - tobuf(buffer, fUnits); - tobuf(buffer, fCompress); - tobuf(buffer, (Int_t)fSeekInfo); - tobuf(buffer, fNbytesInfo); - } else { - tobuf(buffer, fEND); - tobuf(buffer, fSeekFree); - tobuf(buffer, fNbytesFree); - tobuf(buffer, nfree); - tobuf(buffer, fNbytesName); - tobuf(buffer, fUnits); - tobuf(buffer, fCompress); - tobuf(buffer, fSeekInfo); - tobuf(buffer, fNbytesInfo); - } - fUUID.FillBuffer(buffer); - Int_t nbytes = buffer - psave; - Seek(0); - WriteBuffer(psave, nbytes); - Flush(); - delete [] psave; -} - -//______________________________________________________________________________ -void TFile::MakeProject(const char *dirname, const char * /*classes*/, - Option_t *option) -{ - // Generate code in directory dirname for all classes specified in argument classes - // If classes = "*" (default), the function generates an include file for each - // class in the StreamerInfo list for which a TClass object does not exist. - // One can restrict the list of classes to be generated by using expressions like: - // classes = "Ali*" generate code only for classes starting with Ali - // classes = "myClass" generate code for class MyClass only. - // - // If option = "new" (default) a new directory dirname is created. - // If dirname already exist, an error message is printed - // and the function returns. - // If option = "recreate", then; - // if dirname does not exist, it is created (like in "new") - // if dirname already exist, all existing files in dirname - // are deleted before creating the new files. - // If option = "update", then new classes are added to the existing directory. - // Existing classes with the same name are replaced by the - // new definition. If the directory dirname doest not exist, - // same effect as "new". - // If, in addition to one of the 3 above options, the option "+" is specified, - // the function will generate: - // - a script called MAKE to build the shared lib - // - a LinkDef.h file - // - rootcint will be run to generate a dirnameProjectDict.cxx file - // - dirnameProjectDict.cxx will be compiled with the current options in compiledata.h - // - a shared lib dirname.so will be created. - // If the option "++" is specified, the generated shared lib is dynamically - // linked with the current executable module. - // Example: - // file.MakeProject("demo","*","recreate++"); - // - creates a new directory demo unless it already exist - // - clear the previous directory content - // - generate the xxx.h files for all classes xxx found in this file - // and not yet known to the CINT dictionary. - // - creates the build script MAKE - // - creates a LinkDef.h file - // - runs rootcint generating demoProjectDict.cxx - // - compiles demoProjectDict.cxx into demoProjectDict.o - // - generates a shared lib demo.so - // - dynamically links the shared lib demo.so to the executable - // If only the option "+" had been specified, one can still link the - // shared lib to the current executable module with: - // gSystem->load("demo/demo.so"); - - TString opt = option; - opt.ToLower(); - void *dir = gSystem->OpenDirectory(dirname); - char *path = new char[4000]; - - if (opt.Contains("update")) { - // check that directory exist, if not create it - if (dir == 0) { - gSystem->mkdir(dirname); - } - - } else if (opt.Contains("recreate")) { - // check that directory exist, if not create it - if (dir == 0) { - gSystem->mkdir(dirname); - } - // clear directory - while (dir) { - const char *afile = gSystem->GetDirEntry(dir); - if (afile == 0) break; - if (strcmp(afile,".") == 0) continue; - if (strcmp(afile,"..") == 0) continue; - sprintf(path,"%s/%s",dirname,afile); - gSystem->Unlink(path); - } - - } else { - // new is assumed - // if directory already exist, print error message and return - if (dir) { - Error("MakeProject","cannot create directory %s, already existing",dirname); - delete [] path; - return; - } - gSystem->mkdir(dirname); - } - - // we are now ready to generate the classes - // loop on all TStreamerInfo - TList *list = 0; - if (fSeekInfo) { - TKey *key = new TKey(this); - char *buffer = new char[fNbytesInfo+1]; - char *buf = buffer; - Seek(fSeekInfo); - ReadBuffer(buf,fNbytesInfo); - key->ReadKeyBuffer(buf); - list = (TList*)key->ReadObj(); - delete [] buffer; - delete key; - } else { - list = (TList*)Get("StreamerInfo"); //for versions 2.26 (never released) - } - if (list == 0) { - Error("MakeProject","file %s has no StreamerInfo", GetName()); - delete [] path; - return; - } - - // loop on all TStreamerInfo classes - TStreamerInfo *info; - TIter next(list); - Int_t ngener = 0; - while ((info = (TStreamerInfo*)next())) { - ngener += info->GenerateHeaderFile(dirname); - } - list->Delete(); - delete list; - printf("MakeProject has generated %d classes in %s\n",ngener,dirname); - - // generate the shared lib - if (!opt.Contains("+")) { delete [] path; return;} - - // create the MAKE file by looping on all *.h files - // delete MAKE if it already exists -#ifdef WIN32 - sprintf(path,"%s/make.cmd",dirname); -#else - sprintf(path,"%s/MAKE",dirname); -#endif -#ifdef R__WINGCC - FILE *fpMAKE = fopen(path,"wb"); -#else - FILE *fpMAKE = fopen(path,"w"); -#endif - if (!fpMAKE) { - Error("MakeProject", "cannot open file %s", path); - delete [] path; - return; - } - - // add rootcint statement generating ProjectDict.cxx - fprintf(fpMAKE,"rootcint -f %sProjectDict.cxx -c %s ",dirname,gSystem->GetIncludePath()); - - // create the LinkDef.h file by looping on all *.h files - // delete LinkDef.h if it already exists - sprintf(path,"%s/LinkDef.h",dirname); -#ifdef R__WINGCC - FILE *fp = fopen(path,"wb"); -#else - FILE *fp = fopen(path,"w"); -#endif - if (!fp) { - Error("MakeProject", "cannot open path file %s", path); - delete [] path; - return; - } - fprintf(fp,"#ifdef __CINT__\n"); - fprintf(fp,"#pragma link off all globals;\n"); - fprintf(fp,"#pragma link off all classes;\n"); - fprintf(fp,"#pragma link off all functions;\n"); - fprintf(fp,"\n"); - dir = gSystem->OpenDirectory(dirname); - while (dir) { - const char *afile = gSystem->GetDirEntry(dir); - if (afile == 0) break; - if(strcmp(afile,"LinkDef.h") == 0) continue; - if(strstr(afile,"ProjectDict.h") != 0) continue; - strcpy(path,afile); - char *h = strstr(path,".h"); - if (!h) continue; - *h = 0; - fprintf(fp,"#pragma link C++ class %s+;\n",path); - if (strstr(afile,"<")) continue; //do not write the vector<T>, pair<T>, etc - fprintf(fpMAKE,"%s ",afile); - } - fprintf(fp,"#endif\n"); - fclose(fp); - fprintf(fpMAKE,"LinkDef.h \n"); - - // add compilation line - TString sdirname(dirname); - - TString cmd = gSystem->GetMakeSharedLib(); - cmd.ReplaceAll("$SourceFiles",sdirname+"ProjectDict.cxx"); - cmd.ReplaceAll("$ObjectFiles",sdirname+"ProjectDict."+gSystem->GetObjExt()); - cmd.ReplaceAll("$IncludePath",TString(gSystem->GetIncludePath()) + " -I" + dirname); - cmd.ReplaceAll("$SharedLib",sdirname+"."+gSystem->GetSoExt()); - cmd.ReplaceAll("$LinkedLibs",gSystem->GetLibraries("","SDL")); - cmd.ReplaceAll("$LibName",sdirname); - cmd.ReplaceAll("$BuildDir","."); - - fprintf(fpMAKE,"%s\n",cmd.Data()); - - fclose(fpMAKE); - printf("%s/MAKE file has been generated\n",dirname); - - // now execute the generated script compiling and generating the shared lib - strcpy(path,gSystem->WorkingDirectory()); - gSystem->ChangeDirectory(dirname); -#ifndef WIN32 - gSystem->Exec("chmod +x MAKE"); -#else - // not really needed for Windows but it would work both both Unix and NT - chmod("make.cmd",00700); -#endif - int res = !gSystem->Exec("MAKE"); - gSystem->ChangeDirectory(path); - sprintf(path,"%s/%s.%s",dirname,dirname,gSystem->GetSoExt()); - if (res) printf("Shared lib %s has been generated\n",path); - - //dynamically link the generated shared lib - if (opt.Contains("++")) { - res = !gSystem->Load(path); - if (res) printf("Shared lib %s has been dynamically linked\n",path); - } - delete [] path; -} - -//______________________________________________________________________________ -void TFile::ReadStreamerInfo() -{ - // Read the list of StreamerInfo from this file. - // The key with name holding the list of TStreamerInfo objects is read. - // The corresponding TClass objects are updated. - // Note that this function is not called if the static member fgReadInfo is falsse. - // (see TFile::SetReadStreamerInfo) - - TList *list = GetStreamerInfoList(); - if (!list) { - MakeZombie(); - return; - } - - list->SetOwner(kFALSE); - - if (gDebug > 0) Info("ReadStreamerInfo", "called for file %s",GetName()); - - // loop on all TStreamerInfo classes - TStreamerInfo *info; - TIter next(list); - while ((info = (TStreamerInfo*)next())) { - if (info->IsA() != TStreamerInfo::Class()) { - Warning("ReadStreamerInfo","%s: not a TStreamerInfo object", GetName()); - continue; - } - info->BuildCheck(); - Int_t uid = info->GetNumber(); - Int_t asize = fClassIndex->GetSize(); - if (uid >= asize && uid <100000) fClassIndex->Set(2*asize); - if (uid >= 0 && uid < fClassIndex->GetSize()) fClassIndex->fArray[uid] = 1; - else { - printf("ReadStreamerInfo, class:%s, illegal uid=%d\n",info->GetName(),uid); - } - if (gDebug > 0) printf(" -class: %s version: %d info read at slot %d\n",info->GetName(), info->GetClassVersion(),uid); - } - fClassIndex->fArray[0] = 0; - list->Clear(); //this will delete all TStreamerInfo objects with kCanDelete bit set - delete list; -} - -//______________________________________________________________________________ -void TFile::SetReadStreamerInfo(Bool_t readinfo) -{ - // static function to set fgReadInfo. - // If fgReadInfo is true (default) TFile::ReadStreamerInfo is called - // when opening the file. - // It may be interesting to set fgReadInfo to false to speedup the file - // opening time or in case libraries containing classes referenced - // by the file have not yet been loaded. - // if fgReadInfo is false, one can still read the StreamerInfo with - // myfile.ReadStreamerInfo(); - - fgReadInfo = readinfo; -} - -//______________________________________________________________________________ -void TFile::ShowStreamerInfo() -{ - // Show the StreamerInfo of all classes written to this file. - - TList *list = GetStreamerInfoList(); - - if (!list) return; - - list->ls(); - delete list; -} - - -//______________________________________________________________________________ -UShort_t TFile::WriteProcessID(TProcessID *pidd) -{ - // Check if the ProcessID pidd is already in the file. - // if not, add it and return the index number in the local file list - - TProcessID *pid = pidd; - if (!pid) pid = TProcessID::GetPID(); - TObjArray *pids = GetListOfProcessIDs(); - Int_t npids = GetNProcessIDs(); - for (Int_t i=0;i<npids;i++) { - if (pids->At(i) == pid) return (UShort_t)i; - } - - TDirectory *dirsav = gDirectory; - this->cd(); - this->SetBit(TFile::kHasReferences); - pids->AddAtAndExpand(pid,npids); - pid->IncrementCount(); - char name[32]; - sprintf(name,"ProcessID%d",npids); - pid->Write(name); - this->IncrementProcessIDs(); - if (gDebug > 0) { - printf("WriteProcessID, name=%s, file=%s\n",name,GetName()); - } - if (dirsav) dirsav->cd(); - return (UShort_t)npids; -} - - -//______________________________________________________________________________ -void TFile::WriteStreamerInfo() -{ - // Write the list of TStreamerInfo as a single object in this file - // The class Streamer description for all classes written to this file - // is saved. See class TStreamerInfo. - - //if (!gFile) return; - if (!fWritable) return; - if (!fClassIndex) return; - //no need to update the index if no new classes added to the file - if (fClassIndex->fArray[0] == 0) return; - if (gDebug > 0) Info("WriteStreamerInfo", "called for file %s",GetName()); - - SafeDelete(fInfoCache); - - // build a temporary list with the marked files - TIter next(gROOT->GetListOfStreamerInfo()); - TStreamerInfo *info; - TList list; - - while ((info = (TStreamerInfo*)next())) { - Int_t uid = info->GetNumber(); - if (fClassIndex->fArray[uid]) list.Add(info); - if (gDebug > 0) printf(" -class: %s info number %d saved\n",info->GetName(),uid); - } - if (list.GetSize() == 0) return; - fClassIndex->fArray[0] = 2; //to prevent adding classes in TStreamerInfo::TagFile - - // always write with compression on - Int_t compress = fCompress; - fCompress = 1; - TFile * fileSave = gFile; - TDirectory *dirSave = gDirectory; - gFile = this; - gDirectory = this; - - //free previous StreamerInfo record - if (fSeekInfo) MakeFree(fSeekInfo,fSeekInfo+fNbytesInfo-1); - //Create new key - TKey key(&list,"StreamerInfo",GetBestBuffer(), this); - fKeys->Remove(&key); - fSeekInfo = key.GetSeekKey(); - fNbytesInfo = key.GetNbytes(); - SumBuffer(key.GetObjlen()); - key.WriteFile(0); - - fClassIndex->fArray[0] = 0; - gFile = fileSave; - gDirectory = dirSave; - fCompress = compress; -} - -//______________________________________________________________________________ -TFile *TFile::Open(const char *name, Option_t *option, const char *ftitle, - Int_t compress, Int_t netopt) -{ - // Static member function allowing the creation/opening of either a - // TFile, TNetFile, TWebFile or any TFile derived class for which an - // plugin library handler has been registered with the plugin manager - // (for the plugin manager see the TPluginManager class). The returned - // type of TFile depends on the file name. If the file starts with - // "root:", "roots:" or "rootk:" a TNetFile object will be returned, - // with "http:" a TWebFile, with "file:" a local TFile, etc. (see the - // list of TFile plugin handlers in $ROOTSYS/etc/system.rootrc for regular - // expressions that will be checked) and as last a local file will be tried. - // Before opening a file via TNetFile a check is made to see if the URL - // specifies a local file. If that is the case the file will be opened - // via a normal TFile. To force the opening of a local file via a - // TNetFile use either TNetFile directly or specify as host "localhost". - // The netopt argument is only used by TNetFile. For the meaning of the - // options and other arguments see the constructors of the individual - // file classes. In case of error returns 0. - - TPluginHandler *h; - TFile *f = 0; - - IncrementFileCounter(); - - // change names from e.g. /castor/cern.ch/alice/file.root to - // castor:/castor/cern.ch/alice/file.root as recognized by the plugin manager - TUrl urlname(name, kTRUE); - name = urlname.GetUrl(); - // Check first if a pending async open request matches this one - if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) { - TIter nxr(fgAsyncOpenRequests); - TFileOpenHandle *fh = 0; - while ((fh = (TFileOpenHandle *)nxr())) - if (fh->Matches(name)) - return TFile::Open(fh); - } - - // Resolve the file type; this also adjusts names - EFileType type = GetType(name, option); - - if (type == kLocal) { - - // Local files - urlname.SetHost(""); - urlname.SetProtocol("file"); - f = new TFile(urlname.GetUrl(), option, ftitle, compress); - - } else if (type == kNet) { - - // Network files - if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) && - h->LoadPlugin() == 0) - f = (TFile*) h->ExecPlugin(5, name, option, ftitle, compress, netopt); - else - f = new TNetFile(name, option, ftitle, compress, netopt); - - } else if (type == kWeb) { - - // Web files - if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) && - h->LoadPlugin() == 0) - f = (TFile*) h->ExecPlugin(1, name); - else - f = new TWebFile(name); - - } else if (type == kFile) { - - // 'file:' protocol - if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) && - h->LoadPlugin() == 0) - f = (TFile*) h->ExecPlugin(4, name+5, option, ftitle, compress); - else - f = new TFile(name, option, ftitle, compress); - - } else { - - // no recognized specification: try the plugin manager - if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name))) { - if (h->LoadPlugin() == -1) - return 0; - TClass *cl = TClass::GetClass(h->GetClass()); - if (cl && cl->InheritsFrom("TNetFile")) - f = (TFile*) h->ExecPlugin(5, name, option, ftitle, compress, netopt); - else - f = (TFile*) h->ExecPlugin(4, name, option, ftitle, compress); - } else - // just try to open it locally - f = new TFile(name, option, ftitle, compress); - } - - if (f && f->IsZombie()) { - delete f; - f = 0; - } - - // if the file is writable, non local, and not opened in raw mode - // we create a default write cache of 512 KBytes - if (type != kLocal && type != kFile && - f && f->IsWritable() && !f->IsRaw()) { - new TFileCacheWrite(f, 1); - } - - if (gMonitoringWriter && (!f->IsWritable())) - gMonitoringWriter->SendFileReadProgress(f,true); - - return f; -} - -//______________________________________________________________________________ -TFileOpenHandle *TFile::AsyncOpen(const char *name, Option_t *option, - const char *ftitle, Int_t compress, - Int_t netopt) -{ - // Static member function to submit an open request. The request will be - // processed asynchronously. See TFile::Open(const char *, ...) for an - // explanation of the arguments. A handler is returned which is to be passed - // to TFile::Open(TFileOpenHandle *) to get the real TFile instance once - // the file is open. - // This call never blocks and it is provided to allow parallel submission - // of file opening operations expected to take a long time. - // TFile::Open(TFileOpenHandle *) may block if the file is not yet ready. - // The sequence - // TFile::Open(TFile::AsyncOpen(const char *, ...)) - // is equivalent to - // TFile::Open(const char *, ...) . - // To be effective, the underlying TFile implementation must be able to - // support asynchronous open functionality. Currently, only TXNetFile - // supports it. If the functionality is not implemented, this call acts - // transparently by returning an handle with the arguments for the - // standard synchronous open run by TFile::Open(TFileOpenHandle *). - // The retuned handle will be adopted by TFile after opening completion - // in TFile::Open(TFileOpenHandle *); if opening is not finalized the - // handle must be deleted by the caller. - - TFileOpenHandle *fh = 0; - TPluginHandler *h; - TFile *f = 0; - Bool_t notfound = kTRUE; - - // change names from e.g. /castor/cern.ch/alice/file.root to - // castor:/castor/cern.ch/alice/file.root as recognized by the plugin manager - TUrl urlname(name, kTRUE); - name = urlname.GetUrl(); - - // Resolve the file type; this also adjusts names - EFileType type = GetType(name, option); - - // Here we send the asynchronous request if the functionality is implemented - if (type == kNet) { - // Network files - if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) && - !strcmp(h->GetClass(),"TXNetFile") && h->LoadPlugin() == 0) { - f = (TFile*) h->ExecPlugin(6, name, option, ftitle, compress, netopt, kTRUE); - notfound = kFALSE; - } - } - if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) && - !strcmp(h->GetClass(),"TAlienFile") && h->LoadPlugin() == 0) { - f = (TFile*) h->ExecPlugin(5, name, option, ftitle, compress, kTRUE); - notfound = kFALSE; - } - - // Make sure that no error occured - if (notfound) { - SafeDelete(f); - // Save the arguments in the handler, so that a standard open can be - // attempted later on - fh = new TFileOpenHandle(name, option, ftitle, compress, netopt); - } else if (f) { - // Fill the opaque handler to be use to attach the file later on - fh = new TFileOpenHandle(f); - } - - // Record this request - if (fh) { - // Create the lst, if not done already - if (!fgAsyncOpenRequests) - fgAsyncOpenRequests = new TList; - fgAsyncOpenRequests->Add(fh); - } - - // We are done - return fh; -} - -//______________________________________________________________________________ -TFile *TFile::Open(TFileOpenHandle *fh) -{ - // Waits for the completion of an asynchronous open request. - // Returns the associated TFile, transferring ownership of the - // handle to the TFile instance. - - TFile *f = 0; - - // Note that the request may have failed - if (fh && fgAsyncOpenRequests) { - // Was asynchronous open functionality implemented? - if ((f = fh->GetFile()) && !(f->IsZombie())) { - // Yes: wait for the completion of the open phase, if needed - Bool_t cr = (!strcmp(f->GetOption(),"CREATE") || - !strcmp(f->GetOption(),"RECREATE") || - !strcmp(f->GetOption(),"NEW")) ? kTRUE : kFALSE; - f->Init(cr); - } else { - // No: process a standard open - f = TFile::Open(fh->GetName(), fh->GetOpt(), fh->GetTitle(), - fh->GetCompress(), fh->GetNetOpt()); - } - - // Adopt the handle instance in the TFile instance so that it gets - // automatically cleaned up - f->fAsyncHandle = fh; - - // Remove it from the pending list - fgAsyncOpenRequests->Remove(fh); - } - - // We are done - return f; -} - -//______________________________________________________________________________ -Int_t TFile::SysOpen(const char *pathname, Int_t flags, UInt_t mode) -{ - // Interface to system open. All arguments like in POSIX open(). - -#if defined(R__WINGCC) - // ALWAYS use binary mode - even cygwin text should be in unix format - // although this is posix default it has to be set explicitly - return ::open(pathname, flags | O_BINARY, mode); -#elif defined(R__SEEK64) - return ::open64(pathname, flags, mode); -#else - return ::open(pathname, flags, mode); -#endif -} - -//______________________________________________________________________________ -Int_t TFile::SysClose(Int_t fd) -{ - // Interface to system close. All arguments like in POSIX close(). - - return ::close(fd); -} - -//______________________________________________________________________________ -Int_t TFile::SysRead(Int_t fd, void *buf, Int_t len) -{ - // Interface to system read. All arguments like in POSIX read(). - - return ::read(fd, buf, len); -} - -//______________________________________________________________________________ -Int_t TFile::SysWrite(Int_t fd, const void *buf, Int_t len) -{ - // Interface to system write. All arguments like in POSIX write(). - - return ::write(fd, buf, len); -} -//______________________________________________________________________________ -Long64_t TFile::SysSeek(Int_t fd, Long64_t offset, Int_t whence) -{ - // Interface to system lseek. All arguments like in POSIX lseek() - // except that the offset and return value are of a type which are - // able to handle 64 bit file systems. - -#if defined (R__SEEK64) - return ::lseek64(fd, offset, whence); -#elif defined(WIN32) - return ::_lseeki64(fd, offset, whence); -#else - return ::lseek(fd, offset, whence); -#endif -} - -//______________________________________________________________________________ -Int_t TFile::SysStat(Int_t, Long_t *id, Long64_t *size, Long_t *flags, - Long_t *modtime) -{ - // Return file stat information. The interface and return value is - // identical to TSystem::GetPathInfo(). The function returns 0 in - // case of success and 1 if the file could not be stat'ed. - - return gSystem->GetPathInfo(fRealName, id, size, flags, modtime); -} - -//______________________________________________________________________________ -Int_t TFile::SysSync(Int_t fd) -{ - // Interface to system fsync. All arguments like in POSIX fsync(). - - if (TestBit(kDevNull)) return 0; - -#ifndef WIN32 - return ::fsync(fd); -#else - return ::_commit(fd); -#endif -} - -//______________________________________________________________________________ -Long64_t TFile::GetBytesWritten() const -{ - // Return the total number of bytes written so far to the file. - - return fCacheWrite ? fCacheWrite->GetBytesInCache() + fBytesWrite : fBytesWrite; -} - -//______________________________________________________________________________ -Long64_t TFile::GetFileBytesRead() -{ - // Static function returning the total number of bytes read from all files. - - return fgBytesRead; -} - -//______________________________________________________________________________ -Long64_t TFile::GetFileBytesWritten() -{ - // Static function returning the total number of bytes written to all files. - // Does not take into account what might still be in the write caches. - - return fgBytesWrite; -} - -//______________________________________________________________________________ -Int_t TFile::GetFileReadCalls() -{ - // Static function returning the total number of read calls from all files. - - return fgReadCalls; -} - -//______________________________________________________________________________ -void TFile::SetFileBytesRead(Long64_t bytes) { fgBytesRead = bytes; } - -//______________________________________________________________________________ -void TFile::SetFileBytesWritten(Long64_t bytes) { fgBytesWrite = bytes; } - -//______________________________________________________________________________ -void TFile::SetFileReadCalls(Int_t readcalls) { fgReadCalls = readcalls; } - -//______________________________________________________________________________ -Long64_t TFile::GetFileCounter() { return fgFileCounter; } - -//______________________________________________________________________________ -void TFile::IncrementFileCounter() { fgFileCounter++; } - -//______________________________________________________________________________ -Bool_t TFile::Matches(const char *url) -{ - // Return kTRUE if 'url' matches the coordinates of this file. - // The check is implementation dependent and may need to be overload - // by each TFile implememtation relying on this check. - // The default implementation checks teh file name only. - - // Check the full URL, including port and FQDN. - TUrl u(url); - - // Check - if (!strcmp(u.GetFile(), fUrl.GetFile())) { - // Check ports - if (u.GetPort() == fUrl.GetPort()) { - if (!strcmp(u.GetHostFQDN(), fUrl.GetHostFQDN())) { - // Ok, coordinates match - return kTRUE; - } - } - } - - // Default is not matching - return kFALSE; -} - -//______________________________________________________________________________ -Bool_t TFileOpenHandle::Matches(const char *url) -{ - // Return kTRUE if this async request matches the open request - // specified by 'url' - - if (fFile) { - return fFile->Matches(url); - } else if (fName.Length() > 0){ - // Deep check of URLs - TUrl u(url); - TUrl uref(fName); - if (!strcmp(u.GetFile(), uref.GetFile())) { - // Check ports - if (u.GetPort() == uref.GetPort()) { - // Check also the host name - if (!strcmp(u.GetHostFQDN(), uref.GetHostFQDN())) { - // Ok, coordinates match - return kTRUE; - } - } - } - } - - // Default is not matching - return kFALSE; -} - -//______________________________________________________________________________ -TFile::EFileType TFile::GetType(const char *name, Option_t *option) -{ - // Resolve the file type as a function of the protocol field in 'name' - - EFileType type = kDefault; - - TRegexp re("^root.*:"); - TString sname = name; - if (sname.Index(re) != kNPOS) { - // - // Should be a network file ... - type = kNet; - // ... but make sure that is not local or that a remote-like connection - // is forced. Treat it as local if: - // i) the url points to the localhost, the file will be opened in - // readonly mode and the current user has read access; - // ii) the specified user is equal to the current user then open local - // TFile. - const char *lfname = 0; - Bool_t localFile = kFALSE; - TUrl url(name); - // - // Check whether we should try to optimize for local files - Bool_t forceRemote = gEnv->GetValue("TFile.ForceRemote", 0); - TString opts = url.GetOptions(); - if (opts.Contains("remote=1")) - forceRemote = kTRUE; - else if (opts.Contains("remote=0")) - forceRemote = kFALSE; - if (!forceRemote) { - TInetAddress a(gSystem->GetHostByName(url.GetHost())); - TInetAddress b(gSystem->GetHostByName(gSystem->HostName())); - if (!strcmp(a.GetHostName(), b.GetHostName())) { - Bool_t read = kFALSE; - TString opt = option; - opt.ToUpper(); - if (opt == "" || opt == "READ") read = kTRUE; - const char *fname = url.GetFile(); - if (fname[0] == '/' || fname[0] == '~' || fname[0] == '$') - lfname = fname; - else - lfname = Form("%s/%s", gSystem->HomeDirectory(), fname); - if (read) { - char *fn; - if ((fn = gSystem->ExpandPathName(lfname))) { - if (gSystem->AccessPathName(fn, kReadPermission)) - read = kFALSE; - delete [] fn; - } - } - Bool_t sameUser = kFALSE; - UserGroup_t *u = gSystem->GetUserInfo(); - if (u && !strcmp(u->fUser, url.GetUser())) - sameUser = kTRUE; - delete u; - if (read || sameUser) - localFile = kTRUE; - } - } - // - // Adjust the type according to findings - type = (localFile) ? kLocal : type; - } else if (!strncmp(name, "http:", 5)) { - // - // Web file - type = kWeb; - } else if (!strncmp(name, "file:", 5)) { - // - // 'file' protocol - type = kFile; - } - - // We are done - return type; -} - -//______________________________________________________________________________ -TFile::EAsyncOpenStatus TFile::GetAsyncOpenStatus(const char* name) -{ - // Get status of the async open request related to 'name'. - - // Check the list of pending async opem requests - if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) { - TIter nxr(fgAsyncOpenRequests); - TFileOpenHandle *fh = 0; - while ((fh = (TFileOpenHandle *)nxr())) - if (fh->Matches(name)) - return TFile::GetAsyncOpenStatus(fh); - } - - // Check also the list of files open - TSeqCollection *of = gROOT->GetListOfFiles(); - if (of && (of->GetSize() > 0)) { - TIter nxf(of); - TFile *f = 0; - while ((f = (TFile *)nxf())) - if (f->Matches(name)) - return f->GetAsyncOpenStatus(); - } - - // Default is synchronous mode - return kAOSNotAsync; -} - -//______________________________________________________________________________ -TFile::EAsyncOpenStatus TFile::GetAsyncOpenStatus(TFileOpenHandle *handle) -{ - // Get status of the async open request related to 'handle'. - - if (handle && handle->fFile) - if (!handle->fFile->IsZombie()) - return handle->fFile->GetAsyncOpenStatus(); - else - return TFile::kAOSFailure; - - // Default is synchronous mode - return TFile::kAOSNotAsync; -} - -//______________________________________________________________________________ -const TUrl *TFile::GetEndpointUrl(const char* name) -{ - // Get final URL for file being opened asynchronously. - // Returns 0 is the information is not yet available. - - // Check the list of pending async opem requests - if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) { - TIter nxr(fgAsyncOpenRequests); - TFileOpenHandle *fh = 0; - while ((fh = (TFileOpenHandle *)nxr())) - if (fh->Matches(name)) - if (fh->fFile) - return fh->fFile->GetEndpointUrl(); - } - - // Check also the list of files open - TSeqCollection *of = gROOT->GetListOfFiles(); - if (of && (of->GetSize() > 0)) { - TIter nxf(of); - TFile *f = 0; - while ((f = (TFile *)nxf())) - if (f->Matches(name)) - return f->GetEndpointUrl(); - } - - // Information not yet available - return (const TUrl *)0; -} diff --git a/base/src/TFileCacheRead.cxx b/base/src/TFileCacheRead.cxx deleted file mode 100644 index b0c14bf4ecd98a61fff0524b94a40d2ec5526914..0000000000000000000000000000000000000000 --- a/base/src/TFileCacheRead.cxx +++ /dev/null @@ -1,264 +0,0 @@ -// @(#)root/base:$Name: $:$Id: TFileCacheRead.cxx,v 1.6 2006/10/25 14:38:38 brun Exp $ -// Author: Rene Brun 18/05/2006 - -/************************************************************************* - * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// // -// TFileCacheRead : a cache when reading files over the network // -// // -// A caching system to speed up network I/O, i.e. when there is // -// no operating system caching support (like the buffer cache for // -// local disk I/O). The cache makes sure that every I/O is done with // -// a (large) fixed length buffer thereby avoiding many small I/O's. // -// Currently the read cache system is used by the classes TNetFile, // -// TXNetFile and TWebFile (via TFile::ReadBuffers()). // -// // -// When processing TTree, TChain, a specialized class TTreeCache that // -// derives from this class is automatically created. // -// // -////////////////////////////////////////////////////////////////////////// - -#include "TFile.h" -#include "TFileCacheRead.h" -#include "TFileCacheWrite.h" -#include "TMath.h" - -ClassImp(TFileCacheRead) - -//______________________________________________________________________________ -TFileCacheRead::TFileCacheRead() : TObject() -{ - // Default Constructor. - - fBufferSizeMin = 0; - fBufferSize = 0; - fBufferLen = 0; - fNseek = 0; - fNtot = 0; - fNb = 0; - fSeekSize = 0; - fSeek = 0; - fSeekIndex = 0; - fSeekSort = 0; - fPos = 0; - fSeekLen = 0; - fSeekSortLen = 0; - fSeekPos = 0; - fLen = 0; - fFile = 0; - fBuffer = 0; - fIsSorted = kFALSE; -} - -//_____________________________________________________________________________ -TFileCacheRead::TFileCacheRead(TFile *file, Int_t buffersize) - : TObject() -{ - // Creates a TFileCacheRead data structure. - - if (buffersize <=10000) fBufferSize = 100000; - fBufferSizeMin = buffersize; - fBufferSize = buffersize; - fBufferLen = 0; - fNseek = 0; - fNtot = 0; - fNb = 0; - fSeekSize = 10000; - fSeek = new Long64_t[fSeekSize]; - fSeekIndex = new Long64_t[fSeekSize]; - fSeekSort = new Long64_t[fSeekSize]; - fPos = new Long64_t[fSeekSize]; - fSeekLen = new Int_t[fSeekSize]; - fSeekSortLen = new Int_t[fSeekSize]; - fSeekPos = new Int_t[fSeekSize]; - fLen = new Int_t[fSeekSize]; - fFile = file; - fBuffer = new char[fBufferSize]; - fIsSorted = kFALSE; - if (file) file->SetCacheRead(this); -} - -//_____________________________________________________________________________ -TFileCacheRead::~TFileCacheRead() -{ - // Destructor. - - delete [] fSeek; - delete [] fSeekIndex; - delete [] fSeekSort; - delete [] fPos; - delete [] fSeekLen; - delete [] fSeekSortLen; - delete [] fSeekPos; - delete [] fLen; - delete [] fBuffer; -} - -//_____________________________________________________________________________ -void TFileCacheRead::Prefetch(Long64_t pos, Int_t len) -{ - // Add block of length len at position pos in the list of blocks to - // be prefetched. If pos <= 0 the current blocks (if any) are reset. - - fIsSorted = kFALSE; - if (pos <= 0) { - fNseek = 0; - fNtot = 0; - return; - } - if (fNseek >= fSeekSize) { - //reallocate buffers - fSeekSize *= 2; - Long64_t *aSeek = new Long64_t[fSeekSize]; - Long64_t *aSeekIndex = new Long64_t[fSeekSize]; - Long64_t *aSeekSort = new Long64_t[fSeekSize]; - Long64_t *aPos = new Long64_t[fSeekSize]; - Int_t *aSeekLen = new Int_t[fSeekSize]; - Int_t *aSeekSortLen = new Int_t[fSeekSize]; - Int_t *aSeekPos = new Int_t[fSeekSize]; - Int_t *aLen = new Int_t[fSeekSize]; - for (Int_t i=0;i<fNseek;i++) { - aSeek[i] = fSeek[i]; - aSeekIndex[i] = fSeekIndex[i]; - aSeekSort[i] = fSeekSort[i]; - aPos[i] = fPos[i]; - aSeekLen[i] = fSeekLen[i]; - aSeekSortLen[i] = fSeekSortLen[i]; - aSeekPos[i] = fSeekPos[i]; - aLen[i] = fLen[i]; - } - delete [] fSeek; - delete [] fSeekIndex; - delete [] fSeekSort; - delete [] fPos; - delete [] fSeekLen; - delete [] fSeekSortLen; - delete [] fSeekPos; - delete [] fLen; - fSeek = aSeek; - fSeekIndex = aSeekIndex; - fSeekSort = aSeekSort; - fPos = aPos; - fSeekLen = aSeekLen; - fSeekSortLen = aSeekSortLen; - fSeekPos = aSeekPos; - fLen = aLen; - } - - fSeek[fNseek] = pos; - fSeekLen[fNseek] = len; - fNseek++; - fNtot += len; -} - -//_____________________________________________________________________________ -void TFileCacheRead::Print(Option_t *option) const -{ - // Print class internal structure. - - TString opt = option; - opt.ToLower(); - printf("Number of blocks: %d, total size : %d\n",fNseek,fNtot); - if (!opt.Contains("a")) return; - for (Int_t i=0;i<fNseek;i++) { - if (fIsSorted && !opt.Contains("s")) { - printf("block: %5d, from: %lld to %lld, len=%d bytes\n",i,fSeekSort[i],fSeekSort[i]+fSeekSortLen[i],fSeekSortLen[i]); - } else { - printf("block: %5d, from: %lld to %lld, len=%d bytes\n",i,fSeek[i],fSeek[i]+fSeekLen[i],fSeekLen[i]); - } - } - printf ("Number of long buffers = %d\n",fNb); - for (Int_t j=0;j<fNb;j++) { - printf("fPos[%d]=%lld, fLen=%d\n",j,fPos[j],fLen[j]); - } -} - -//_____________________________________________________________________________ -Int_t TFileCacheRead::ReadBuffer(char *buf, Long64_t pos, Int_t len) -{ - // Read buffer at position pos. - // If pos is in the list of prefetched blocks read from fBuffer, - // otherwise need to make a normal read from file. Returns -1 in case of - // read error, 0 in case not in cache, 1 in case read from cache. - - if (fNseek > 0 && !fIsSorted) { - Sort(); - if (fFile->ReadBuffers(fBuffer,fPos,fLen,fNb)) { - return -1; - } - } - - // in case we are writing and reading to/from this file, we much check - // if this buffer is in the write cache (not yet written to the file) - if (TFileCacheWrite *cachew = fFile->GetCacheWrite()) { - if (cachew->ReadBuffer(buf,pos,len) == 0) { - fFile->Seek(pos+len); - return 1; - } - } - - Int_t loc = (Int_t)TMath::BinarySearch(fNseek,fSeekSort,pos); - if (loc >= 0 && loc <fNseek && pos == fSeekSort[loc]) { - memcpy(buf,&fBuffer[fSeekPos[loc]],len); - fFile->Seek(pos+len); - //printf("TFileCacheRead::ReadBuffer, pos=%lld, len=%d, slen=%d, loc=%d\n",pos,len,fSeekSortLen[loc],loc); - return 1; - } - - return 0; -} - -//_____________________________________________________________________________ -void TFileCacheRead::SetFile(TFile *file) -{ - // Set the file using this cache and reset the current blocks (if any). - - - fFile = file; - Prefetch(0,0); -} - -//_____________________________________________________________________________ -void TFileCacheRead::Sort() -{ - // Sort buffers to be prefetched in increasing order of positions. - // Merge consecutive blocks if necessary. - - if (!fNseek) return; - TMath::Sort(fNseek,fSeek,fSeekIndex,kFALSE); - Int_t i; - Int_t nb = 0; - for (i=0;i<fNseek;i++) { - Long64_t ind = fSeekIndex[i]; - fSeekSort[i] = fSeek[ind]; - fSeekSortLen[i] = fSeekLen[ind]; - } - if (fNtot > fBufferSizeMin) { - fBufferSize = fNtot + 100; - delete [] fBuffer; - fBuffer = new char[fBufferSize]; - // printf("CHANGING fBufferSize=%d, fNseek=%d, fNtot=%d\n",fBufferSize, fNseek,fNtot); - } - fPos[0] = fSeekSort[0]; - fLen[0] = fSeekSortLen[0]; - fSeekPos[0] = 0; - for (i=1;i<fNseek;i++) { - fSeekPos[i] = fSeekPos[i-1] + fSeekSortLen[i-1]; - if (fSeekSort[i] != fSeekSort[i-1]+fSeekSortLen[i-1]) { - nb++; - fPos[nb] = fSeekSort[i]; - fLen[nb] = fSeekSortLen[i]; - } else { - fLen[nb] += fSeekSortLen[i]; - } - } - fNb = nb+1; - fIsSorted = kTRUE; -} diff --git a/base/src/TFileCacheWrite.cxx b/base/src/TFileCacheWrite.cxx deleted file mode 100644 index eee6a6409d4bd307e5bb07dbdc1f98470242ea05..0000000000000000000000000000000000000000 --- a/base/src/TFileCacheWrite.cxx +++ /dev/null @@ -1,155 +0,0 @@ -// @(#)root/base:$Name: $:$Id: TFileCacheWrite.cxx,v 1.7 2006/08/26 16:28:32 rdm Exp $ -// Author: Rene Brun 18/05/2006 - -/************************************************************************* - * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// // -// TFileCacheWrite : a cache when writing files over the network // -// // -// A caching system to speed up network I/O, i.e. when there is // -// no operating system caching support (like the buffer cache for // -// local disk I/O). The cache makes sure that every I/O is done with // -// a (large) fixed length buffer thereby avoiding many small I/O's. // -// Currently the write cache system is used by the classes TNetFile, // -// TXNetFile and TWebFile (via TFile::WriteBuffers()). // -// // -// The write cache is automatically created when writing a remote file // -// (created in TFile::Open()). // -// // -////////////////////////////////////////////////////////////////////////// - - -#include "TFile.h" -#include "TFileCacheWrite.h" - -ClassImp(TFileCacheWrite) - -//______________________________________________________________________________ -TFileCacheWrite::TFileCacheWrite() : TObject() -{ - // Default Constructor. - - fBufferSize = 0; - fNtot = 0; - fSeekStart = 0; - fFile = 0; - fBuffer = 0; - fRecursive = kFALSE; -} - -//_____________________________________________________________________________ -TFileCacheWrite::TFileCacheWrite(TFile *file, Int_t buffersize) - : TObject() -{ - // Creates a TFileCacheWrite data structure. - // The write cache will be connected to file. - // The size of the cache will be buffersize, - // if buffersize < 10000 a default size of 512 Kbytes is used - - if (buffersize < 10000) buffersize = 512000; - fBufferSize = buffersize; - fSeekStart = 0; - fNtot = 0; - fFile = file; - fRecursive = kFALSE; - fBuffer = new char[fBufferSize]; - if (file) file->SetCacheWrite(this); - if (gDebug > 0) Info("TFileCacheWrite","Creating a write cache with buffersize=%d bytes",buffersize); -} - -//_____________________________________________________________________________ -TFileCacheWrite::~TFileCacheWrite() -{ - // Destructor. - - delete [] fBuffer; -} - -//_____________________________________________________________________________ -Bool_t TFileCacheWrite::Flush() -{ - // Flush the current write buffer to the file. - // Returns kTRUE in case of error. - - if (!fNtot) return kFALSE; - fFile->Seek(fSeekStart); - //printf("Flushing buffer at fSeekStart=%lld, fNtot=%d\n",fSeekStart,fNtot); - fRecursive = kTRUE; - Bool_t status = fFile->WriteBuffer(fBuffer, fNtot); - fRecursive = kFALSE; - fNtot = 0; - return status; -} - -//_____________________________________________________________________________ -void TFileCacheWrite::Print(Option_t *option) const -{ - // Print class internal structure. - - TString opt = option; - printf("Write cache for file %s\n",fFile->GetName()); - printf("Size of write cache: %d bytes to be written at %lld\n",fNtot,fSeekStart); - opt.ToLower(); -} - -//_____________________________________________________________________________ -Int_t TFileCacheWrite::ReadBuffer(char *buf, Long64_t pos, Int_t len) -{ - // Called by the read cache to check if the requested data is not - // in the write cache buffer. - // Returns -1 if data not in write cache, - // 0 otherwise. - - if (pos < fSeekStart || pos+len > fSeekStart+fNtot) return -1; - memcpy(buf,fBuffer+pos-fSeekStart,len); - return 0; -} - -//_____________________________________________________________________________ -Int_t TFileCacheWrite::WriteBuffer(const char *buf, Long64_t pos, Int_t len) -{ - // Write buffer at position pos in the write buffer. - // The function returns 1 if the buffer has been successfully entered into the write buffer. - // The function returns 0 in case WriteBuffer() was recusively called via Flush(). - // The function returns -1 in case of error. - - if (fRecursive) return 0; - - //printf("TFileCacheWrite::WriteBuffer, pos=%lld, len=%d, fSeekStart=%lld, fNtot=%d\n",pos,len,fSeekStart,fNtot); - - if (fSeekStart + fNtot != pos) { - //we must flush the current cache - if (Flush()) return -1; //failure - } - if (fNtot + len >= fBufferSize) { - if (Flush()) return -1; //failure - if (len >= fBufferSize) { - //buffer larger than the cache itself: direct write to file - fRecursive = kTRUE; - if (fFile->WriteBuffer(buf,len)) return -1; // failure - fRecursive = kFALSE; - return 1; - } - } - if (!fNtot) fSeekStart = pos; - memcpy(fBuffer+fNtot,buf,len); - fNtot += len; - - return 1; -} - -//_____________________________________________________________________________ -void TFileCacheWrite::SetFile(TFile *file) -{ - // Set the file using this cache. - // Any write not yet flushed will be lost. - - fFile = file; -} diff --git a/base/src/TKey.cxx b/base/src/TKey.cxx deleted file mode 100644 index e37d7ba1a69a21582216121b9116a1ee15e9b786..0000000000000000000000000000000000000000 --- a/base/src/TKey.cxx +++ /dev/null @@ -1,1184 +0,0 @@ -// @(#)root/base:$Name: $:$Id: TKey.cxx,v 1.67 2007/01/29 15:53:35 brun Exp $ -// Author: Rene Brun 28/12/94 - -/************************************************************************* - * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// // -// The TKey class includes functions to book space on a file, // -// to create I/O buffers, to fill these buffers, // -// to compress/uncompress data buffers. // -// // -// Before saving (making persistent) an object on a file, a key must // -// be created. The key structure contains all the information to // -// uniquely identify a persistent object on a file. // -// fNbytes = number of bytes for the compressed object+key // -// fObjlen = Length of uncompressed object // -// fDatime = Date/Time when the object was written // -// fKeylen = number of bytes for the key structure // -// fCycle = cycle number of the object // -// fSeekKey = Address of the object on file (points to fNbytes) // -// This is a redundant information used to cross-check // -// the data base integrity. // -// fSeekPdir = Pointer to the directory supporting this object // -// fClassName = Object class name // -// fName = name of the object // -// fTitle = title of the object // -// // -// In the 16 highest bit of fSeekPdir is encoded a pid offset. This // -// offset is to be added to the pid index stored in the TRef object // -// and the referenced TObject. // -// // -// The TKey class is used by ROOT to: // -// - to write an object in the Current Directory // -// - to write a new ntuple buffer // -// // -// The structure of a file is shown in TFile::TFile. // -// The structure of a directory is shown in TDirectoryFile ctor. // -// The TKey class is used by the TBasket class. // -// See also TTree. // -// // -////////////////////////////////////////////////////////////////////////// - -#include "Riostream.h" -#include "TROOT.h" -#include "TClass.h" -#include "TDirectoryFile.h" -#include "TFile.h" -#include "TKey.h" -#include "TBufferFile.h" -#include "TFree.h" -#include "TBrowser.h" -#include "Bytes.h" -#include "TInterpreter.h" -#include "TError.h" -#include "Api.h" - -extern "C" void R__zip (Int_t cxlevel, Int_t *nin, char *bufin, Int_t *lout, char *bufout, Int_t *nout); -extern "C" void R__unzip(Int_t *nin, UChar_t *bufin, Int_t *lout, char *bufout, Int_t *nout); -const Int_t kMAXBUF = 0xffffff; -const Int_t kTitleMax = 32000; -#if 0 -const Int_t kMAXFILEBUFFER = 262144; -#endif - -#if !defined(_MSC_VER) || (_MSC_VER>1300) -const ULong64_t kPidOffsetMask = 0xffffffffffffULL; -#else -const ULong64_t kPidOffsetMask = 0xffffffffffffUL; -#endif -const UChar_t kPidOffsetShift = 48; - -UInt_t keyAbsNumber = 0; - -ClassImp(TKey) - -//______________________________________________________________________________ -TKey::TKey() : TNamed(), fDatime((UInt_t)0) -{ - // TKey default constructor. - - Build(0, "", 0); - - fKeylen = Sizeof(); - - keyAbsNumber++; SetUniqueID(keyAbsNumber); -} - -//______________________________________________________________________________ -TKey::TKey(const TKey& tk) : - TNamed(tk), fVersion(tk.fVersion), fNbytes(tk.fNbytes), fObjlen(tk.fObjlen), - fDatime(tk.fDatime), fKeylen(tk.fKeylen), fCycle(tk.fCycle), fSeekKey(tk.fSeekKey), - fSeekPdir(tk.fSeekPdir), fClassName(tk.fClassName), fLeft(tk.fLeft), fBuffer(tk.fBuffer), - fBufferRef(tk.fBufferRef), fPidOffset(tk.fPidOffset), fMotherDir(tk.fMotherDir) -{ - // copy constructor -} - -//______________________________________________________________________________ -TKey& TKey::operator=(const TKey& tk) -{ - // assignment operator - - if(this!=&tk) { - TNamed::operator=(tk); - fVersion=tk.fVersion; - fNbytes=tk.fNbytes; - fObjlen=tk.fObjlen; - fDatime=tk.fDatime; - fKeylen=tk.fKeylen; - fCycle=tk.fCycle; - fSeekKey=tk.fSeekKey; - fSeekPdir=tk.fSeekPdir; - fClassName=tk.fClassName; - fLeft=tk.fLeft; - fBuffer=tk.fBuffer; - fBufferRef=tk.fBufferRef; - fPidOffset=tk.fPidOffset; - fMotherDir=tk.fMotherDir; - } - return *this; -} - -//______________________________________________________________________________ -TKey::TKey(TDirectory* motherDir) : TNamed(), fDatime((UInt_t)0) -{ - // TKey default constructor. - - Build(motherDir, "", 0); - - fKeylen = Sizeof(); - - keyAbsNumber++; SetUniqueID(keyAbsNumber); -} - -//______________________________________________________________________________ -TKey::TKey(Long64_t pointer, Int_t nbytes, TDirectory* motherDir) : TNamed() -{ - // Create a TKey object to read keys. - // Constructor called by TDirectoryFile::ReadKeys and by TFile::TFile. - // A TKey object is created to read the keys structure itself. - - Build(motherDir, "", pointer); - - fSeekKey = pointer; - fNbytes = nbytes; - fBuffer = new char[nbytes]; - keyAbsNumber++; SetUniqueID(keyAbsNumber); -} - -//______________________________________________________________________________ -TKey::TKey(const char *name, const char *title, const TClass *cl, Int_t nbytes, TDirectory* motherDir) - : TNamed(name,title) -{ - // Create a TKey object with the specified name, title for the given class. - - Build(motherDir, cl->GetName(), -1); - - fKeylen = Sizeof(); - fObjlen = nbytes; - Create(nbytes); -} - -//______________________________________________________________________________ -TKey::TKey(const TString &name, const TString &title, const TClass *cl, Int_t nbytes, TDirectory* motherDir) - : TNamed(name,title) -{ - // Create a TKey object with the specified name, title for the given class. - - Build(motherDir, cl->GetName(), -1); - - fKeylen = Sizeof(); - fObjlen = nbytes; - Create(nbytes); -} - -//______________________________________________________________________________ -TKey::TKey(const TObject *obj, const char *name, Int_t bufsize, TDirectory* motherDir) - : TNamed(name, obj->GetTitle()) -{ - // Create a TKey object for a TObject* and fill output buffer - - R__ASSERT(obj); - - if (!obj->IsA()->HasDefaultConstructor()) { - Warning("TKey", "since %s has no public constructor\n" - "\twhich can be called without argument, objects of this class\n" - "\tcan not be read with the current library. You will need to\n" - "\tadd a default constructor before attempting to read it.", - obj->ClassName()); - } - - Build(motherDir, obj->ClassName(), -1); - - Int_t lbuf, nout, noutot, bufmax, nzip; - fBufferRef = new TBufferFile(TBuffer::kWrite, bufsize); - fBufferRef->SetParent(GetFile()); - fCycle = fMotherDir->AppendKey(this); - - Streamer(*fBufferRef); //write key itself - fKeylen = fBufferRef->Length(); - fBufferRef->MapObject(obj); //register obj in map in case of self reference - ((TObject*)obj)->Streamer(*fBufferRef); //write object - lbuf = fBufferRef->Length(); - fObjlen = lbuf - fKeylen; - - Int_t cxlevel = GetFile() ? GetFile()->GetCompressionLevel() : 0; - if (cxlevel && fObjlen > 256) { - if (cxlevel == 2) cxlevel--; - Int_t nbuffers = fObjlen/kMAXBUF; - Int_t buflen = TMath::Max(512,fKeylen + fObjlen + 9*nbuffers + 28); //add 28 bytes in case object is placed in a deleted gap - fBuffer = new char[buflen]; - char *objbuf = fBufferRef->Buffer() + fKeylen; - char *bufcur = &fBuffer[fKeylen]; - noutot = 0; - nzip = 0; - for (Int_t i=0;i<=nbuffers;i++) { - if (i == nbuffers) bufmax = fObjlen -nzip; - else bufmax = kMAXBUF; - R__zip(cxlevel, &bufmax, objbuf, &bufmax, bufcur, &nout); - if (nout == 0 || nout >= fObjlen) { //this happens when the buffer cannot be compressed - fBuffer = fBufferRef->Buffer(); - Create(fObjlen); - fBufferRef->SetBufferOffset(0); - Streamer(*fBufferRef); //write key itself again - return; - } - bufcur += nout; - noutot += nout; - objbuf += kMAXBUF; - nzip += kMAXBUF; - } - Create(noutot); - fBufferRef->SetBufferOffset(0); - Streamer(*fBufferRef); //write key itself again - memcpy(fBuffer,fBufferRef->Buffer(),fKeylen); - delete fBufferRef; fBufferRef = 0; - } else { - fBuffer = fBufferRef->Buffer(); - Create(fObjlen); - fBufferRef->SetBufferOffset(0); - Streamer(*fBufferRef); //write key itself again - } -} - -//______________________________________________________________________________ -TKey::TKey(const void *obj, const TClass *cl, const char *name, Int_t bufsize, TDirectory* motherDir) - : TNamed(name, "object title") -{ - // Create a TKey object for any object obj of class cl d and fill - // output buffer. - - R__ASSERT(obj && cl); - - if (!cl->HasDefaultConstructor()) { - Warning("TKey", "since %s has no public constructor\n" - "\twhich can be called without argument, objects of this class\n" - "\tcan not be read with the current library. You will need to\n" - "\tadd a default constructor before attempting to read it.", - cl->GetName()); - } - - TClass *clActual = cl->GetActualClass(obj); - const void* actualStart; - if (clActual) { - const char *temp = (const char*) obj; - // clActual->GetStreamerInfo(); - Int_t offset = (cl != clActual) ? - clActual->GetBaseClassOffset(cl) : 0; - temp -= offset; - actualStart = temp; - } else { - actualStart = obj; - } - - Build(motherDir, clActual->GetName(), -1); - - fBufferRef = new TBufferFile(TBuffer::kWrite, bufsize); - fBufferRef->SetParent(GetFile()); - fCycle = fMotherDir->AppendKey(this); - - Streamer(*fBufferRef); //write key itself - fKeylen = fBufferRef->Length(); - - Int_t lbuf, nout, noutot, bufmax, nzip; - - fBufferRef->MapObject(actualStart,clActual); //register obj in map in case of self reference - clActual->Streamer((void*)actualStart, *fBufferRef); //write object - lbuf = fBufferRef->Length(); - fObjlen = lbuf - fKeylen; - - Int_t cxlevel = GetFile() ? GetFile()->GetCompressionLevel() : 0; - if (cxlevel && fObjlen > 256) { - if (cxlevel == 2) cxlevel--; - Int_t nbuffers = fObjlen/kMAXBUF; - Int_t buflen = TMath::Max(512,fKeylen + fObjlen + 9*nbuffers + 28); //add 28 bytes in case object is placed in a deleted gap - fBuffer = new char[buflen]; - char *objbuf = fBufferRef->Buffer() + fKeylen; - char *bufcur = &fBuffer[fKeylen]; - noutot = 0; - nzip = 0; - for (Int_t i=0;i<=nbuffers;i++) { - if (i == nbuffers) bufmax = fObjlen -nzip; - else bufmax = kMAXBUF; - R__zip(cxlevel, &bufmax, objbuf, &bufmax, bufcur, &nout); - if (nout == 0 || nout >= fObjlen) { //this happens when the buffer cannot be compressed - fBuffer = fBufferRef->Buffer(); - Create(fObjlen); - fBufferRef->SetBufferOffset(0); - Streamer(*fBufferRef); //write key itself again - return; - } - bufcur += nout; - noutot += nout; - objbuf += kMAXBUF; - nzip += kMAXBUF; - } - Create(noutot); - fBufferRef->SetBufferOffset(0); - Streamer(*fBufferRef); //write key itself again - memcpy(fBuffer,fBufferRef->Buffer(),fKeylen); - delete fBufferRef; fBufferRef = 0; - } else { - fBuffer = fBufferRef->Buffer(); - Create(fObjlen); - fBufferRef->SetBufferOffset(0); - Streamer(*fBufferRef); //write key itself again - } -} - -//______________________________________________________________________________ -void TKey::Build(TDirectory* motherDir, const char* classname, Long64_t filepos) -{ - // method used in all TKey constructor to initialize basic data fields - // filepos is used to calculate correct version number of key - // if filepos==-1, end of file position is used - - fMotherDir = motherDir; - - fPidOffset = 0; - fNbytes = 0; - fBuffer = 0; - fKeylen = 0; - fObjlen = 0; - fBufferRef = 0; - fCycle = 0; - fSeekPdir = 0; - fSeekKey = 0; - - fClassName = classname; - //the following test required for forward and backward compatibility - if (fClassName == "TDirectoryFile") fClassName = "TDirectory"; - - fVersion = TKey::Class_Version(); - - if ((filepos==-1) && GetFile()) filepos = GetFile()->GetEND(); - if (filepos > TFile::kStartBigFile) fVersion += 1000; - - if (fTitle.Length() > kTitleMax) fTitle.Resize(kTitleMax); -} - -//______________________________________________________________________________ -void TKey::Browse(TBrowser *b) -{ - // Read object from disk and call its Browse() method. - // If object with same name already exist in memory delete it (like - // TDirectoryFile::Get() is doing), except when the key references a - // folder in which case we don't want to re-read the folder object - // since it might contain new objects not yet saved. - - if (fMotherDir==0) return; - - TObject *obj = fMotherDir->GetList()->FindObject(GetName()); - if (obj && !obj->IsFolder()) { - if (obj->InheritsFrom(TCollection::Class())) - obj->Delete(); // delete also collection elements - delete obj; - obj = 0; - } - - if (!obj) - obj = ReadObj(); - - if (b && obj) { - obj->Browse(b); - b->SetRefreshFlag(kTRUE); - } -} - -//______________________________________________________________________________ -void TKey::Create(Int_t nbytes, TFile* externFile) -{ - // Create a TKey object of specified size - // if externFile!=0, key will be allocated in specified file, - // otherwise file of mother directory will be used - - keyAbsNumber++; SetUniqueID(keyAbsNumber); - - TFile *f = externFile; - if (!f) f = GetFile(); - if (!f) { - Error("Create","Cannot create key without file"); - return; - } - - Int_t nsize = nbytes + fKeylen; - TList *lfree = f->GetListOfFree(); - TFree *f1 = (TFree*)lfree->First(); -//*-*-------------------find free segment -//*-* ================= - TFree *bestfree = f1->GetBestFree(lfree,nsize); - if (bestfree == 0) { - Error("Create","Cannot allocate %d bytes for ID = %s Title = %s", - nsize,GetName(),GetTitle()); - return; - } - fDatime.Set(); - fSeekKey = bestfree->GetFirst(); -//*-*----------------- Case Add at the end of the file - if (fSeekKey == f->GetEND()) { - f->SetEND(fSeekKey+nsize); - bestfree->SetFirst(fSeekKey+nsize); - fLeft = -1; - if (!fBuffer) fBuffer = new char[nsize]; - } else { - fLeft = Int_t(bestfree->GetLast() - fSeekKey - nsize + 1); - } -//*-*----------------- Case where new object fills exactly a deleted gap - fNbytes = nsize; - if (fLeft == 0) { - if (!fBuffer) { - fBuffer = new char[nsize]; - } - lfree->Remove(bestfree); - delete bestfree; - } -//*-*----------------- Case where new object is placed in a deleted gap larger than itself - if (fLeft > 0) { // found a bigger segment - if (!fBuffer) { - fBuffer = new char[nsize+sizeof(Int_t)]; - } - char *buffer = fBuffer+nsize; - Int_t nbytesleft = -fLeft; // set header of remaining record - tobuf(buffer, nbytesleft); - bestfree->SetFirst(fSeekKey+nsize); - } - - fSeekPdir = externFile ? externFile->GetSeekDir() : fMotherDir->GetSeekDir(); -} - -//______________________________________________________________________________ -TKey::~TKey() -{ - // TKey default destructor. - - // delete [] fBuffer; fBuffer = 0; - // delete fBufferRef; fBufferRef = 0; - - DeleteBuffer(); -} - -//______________________________________________________________________________ -void TKey::Delete(Option_t *option) -{ - // Delete an object from the file. - // Note: the key is not deleted. You still have to call "delete key". - // This is different from the behaviour of TObject::Delete()! - - if (option && option[0] == 'v') printf("Deleting key: %s at address %lld, nbytes = %d\n",GetName(),fSeekKey,fNbytes); - Long64_t first = fSeekKey; - Long64_t last = fSeekKey + fNbytes -1; - if (GetFile()) GetFile()->MakeFree(first, last); // release space used by this key - fMotherDir->GetListOfKeys()->Remove(this); -} - -//______________________________________________________________________________ -void TKey::DeleteBuffer() -{ - // Delete key buffer(s). - - if (fBufferRef) { - delete fBufferRef; - fBufferRef = 0; - } else { - if (fBuffer) delete [] fBuffer; - } - fBuffer = 0; -} - -//______________________________________________________________________________ -Short_t TKey::GetCycle() const -{ - // Return cycle number associated to this key. - - return ((fCycle >0) ? fCycle : -fCycle); -} - -//______________________________________________________________________________ -TFile *TKey::GetFile() const -{ - // Returns file to which key belong - - return fMotherDir!=0 ? fMotherDir->GetFile() : gFile; -} - -//______________________________________________________________________________ -Short_t TKey::GetKeep() const -{ - // Returns the "KEEP" status. - - return ((fCycle >0) ? 0 : 1); -} - -//______________________________________________________________________________ -void TKey::FillBuffer(char *&buffer) -{ - // Encode key header into output buffer. - - tobuf(buffer, fNbytes); - Version_t version = fVersion; - tobuf(buffer, version); - - tobuf(buffer, fObjlen); - fDatime.FillBuffer(buffer); - tobuf(buffer, fKeylen); - tobuf(buffer, fCycle); - if (fVersion > 1000) { - tobuf(buffer, fSeekKey); - - // We currently store in the 16 highest bit of fSeekPdir the value of - // fPidOffset. This offset is used when a key (or basket) is transfered from one - // file to the other. In this case the TRef and TObject might have stored a - // pid index (to retrieve TProcessIDs) which refered to their order on the original - // file, the fPidOffset is to be added to those values to correctly find the - // TProcessID. This fPidOffset needs to be increment if the key/basket is copied - // and need to be zero for new key/basket. - Long64_t pdir = (((Long64_t)fPidOffset)<<kPidOffsetShift) | (kPidOffsetMask & fSeekPdir); - tobuf(buffer, pdir); - } else { - tobuf(buffer, (Int_t)fSeekKey); - tobuf(buffer, (Int_t)fSeekPdir); - } - fClassName.FillBuffer(buffer); - fName.FillBuffer(buffer); - fTitle.FillBuffer(buffer); -} - -//______________________________________________________________________________ -ULong_t TKey::Hash() const -{ - // This Hash function should redefine the default from TNamed. - - return TNamed::Hash(); -} - -//______________________________________________________________________________ -void TKey::IncrementPidOffset(UShort_t offset) -{ - // Increment fPidOffset by 'offset'. - // This offset is used when a key (or basket) is transfered from one file to - // the other. In this case the TRef and TObject might have stored a pid - // index (to retrieve TProcessIDs) which refered to their order on the - // original file, the fPidOffset is to be added to those values to correctly - // find the TProcessID. This fPidOffset needs to be increment if the - // key/basket is copied and need to be zero for new key/basket. - - fPidOffset += offset; - if (fPidOffset) { - // We currently store fPidOffset in the 16 highest bit of fSeekPdir, which - // need to be store as a 64 bit integer. So we require this key to be - // a 'large file' key. - if (fVersion<1000) fVersion += 1000; - } -} - -//______________________________________________________________________________ -Bool_t TKey::IsFolder() const -{ - // Check if object referenced by the key is a folder. - - Bool_t ret = kFALSE; - - TClass *classPtr = TClass::GetClass((const char *) fClassName); - if (classPtr && classPtr->GetClassInfo()) { - TObject *obj = (TObject *) classPtr->New(TClass::kDummyNew); - if (obj) { - ret = obj->IsFolder(); - delete obj; - } - } - - return ret; -} - -//______________________________________________________________________________ -void TKey::Keep() -{ - // Set the "KEEP" status. - // When the KEEP flag is set to 1 the object cannot be purged. - - if (fCycle >0) fCycle = -fCycle; -} - -//______________________________________________________________________________ -void TKey::ls(Option_t *) const -{ - // List Key contents. - - TROOT::IndentLevel(); - cout <<"KEY: "<<fClassName<<"\t"<<GetName()<<";"<<GetCycle()<<"\t"<<GetTitle()<<endl; -} - -//______________________________________________________________________________ -void TKey::Print(Option_t *) const -{ - // Print key contents. - - printf("TKey Name = %s, Title = %s, Cycle = %d\n",GetName(),GetTitle(),GetCycle()); -} - -//______________________________________________________________________________ -TObject *TKey::ReadObj() -{ - // To read a TObject* from the file. - // - // The object associated to this key is read from the file into memory - // Once the key structure is read (via Streamer) the class identifier - // of the object is known. - // Using the class identifier we find the TClass object for this class. - // A TClass object contains a full description (i.e. dictionary) of the - // associated class. In particular the TClass object can create a new - // object of the class type it describes. This new object now calls its - // Streamer function to rebuilt itself. - // - // see TKey::ReadObjectAny to read any object non-derived from TObject - // - // NOTE: - // In case the class of this object derives from TObject but not - // as a first inheritance, one must cast the return value twice. - // Example1: Normal case: - // class MyClass : public TObject, public AnotherClass - // then on return, one can do: - // MyClass *obj = (MyClass*)key->ReadObj(); - // - // Example2: Special case: - // class MyClass : public AnotherClass, public TObject - // then on return, one must do: - // MyClass *obj = dynamic_cast<MyClass*>(key->ReadObj()); - // - // Of course, dynamic_cast<> can also be used in the example 1. - -//printf("in TKey::ReadObj, fClassname=%s\n",fClassName.Data()); - TClass *cl = TClass::GetClass(fClassName.Data()); - if (!cl) { - Error("ReadObj", "Unknown class %s", fClassName.Data()); - return 0; - } - if (!cl->InheritsFrom(TObject::Class())) { - // in principle user should call TKey::ReadObjectAny! - return (TObject*)ReadObjectAny(0); - } - - fBufferRef = new TBufferFile(TBuffer::kRead, fObjlen+fKeylen); - if (!fBufferRef) { - Error("ReadObj", "Cannot allocate buffer: fObjlen = %d", fObjlen); - return 0; - } - if (GetFile()==0) return 0; - fBufferRef->SetParent(GetFile()); - fBufferRef->SetPidOffset(fPidOffset); - - if (fObjlen > fNbytes-fKeylen) { - fBuffer = new char[fNbytes]; - ReadFile(); //Read object structure from file - memcpy(fBufferRef->Buffer(),fBuffer,fKeylen); - } else { - fBuffer = fBufferRef->Buffer(); - ReadFile(); //Read object structure from file - } - - // get version of key - fBufferRef->SetBufferOffset(sizeof(fNbytes)); - Version_t kvers = fBufferRef->ReadVersion(); - - fBufferRef->SetBufferOffset(fKeylen); - TObject *tobj = 0; - TDirectory *cursav = gDirectory; - // Create an instance of this class - - char *pobj = (char*)cl->New(); - Int_t baseOffset = cl->GetBaseClassOffset(TObject::Class()); - if (baseOffset==-1) { - // cl does not inherit from TObject. - // Since this is not possible yet, the only reason we could reach this code - // is because something is screw up in the ROOT code. - Fatal("ReadObj","Incorrect detection of the inheritance from TObject for class %s.\n", - fClassName.Data()); - } - tobj = (TObject*)(pobj+baseOffset); - if (!pobj) { - Error("ReadObj", "Cannot create new object of class %s", fClassName.Data()); - return 0; - } - if (kvers > 1) - fBufferRef->MapObject(pobj,cl); //register obj in map to handle self reference - - if (fObjlen > fNbytes-fKeylen) { - char *objbuf = fBufferRef->Buffer() + fKeylen; - UChar_t *bufcur = (UChar_t *)&fBuffer[fKeylen]; - Int_t nin, nout, nbuf; - Int_t noutot = 0; - while (1) { - nin = 9 + ((Int_t)bufcur[3] | ((Int_t)bufcur[4] << 8) | ((Int_t)bufcur[5] << 16)); - nbuf = (Int_t)bufcur[6] | ((Int_t)bufcur[7] << 8) | ((Int_t)bufcur[8] << 16); - R__unzip(&nin, bufcur, &nbuf, objbuf, &nout); - if (!nout) break; - noutot += nout; - if (noutot >= fObjlen) break; - bufcur += nin; - objbuf += nout; - } - if (nout) { - tobj->Streamer(*fBufferRef); //does not work with example 2 above - delete [] fBuffer; - } else { - delete [] fBuffer; - delete pobj; - pobj = 0; - tobj = 0; - goto CLEAR; - } - } else { - tobj->Streamer(*fBufferRef); - } - - if (gROOT->GetForceStyle()) tobj->UseCurrentStyle(); - - if (cl == TDirectoryFile::Class()) { - TDirectory *dir = dynamic_cast<TDirectoryFile*>(tobj); - dir->SetName(GetName()); - dir->SetTitle(GetTitle()); - dir->SetMother(fMotherDir); - fMotherDir->Append(dir); - } -CLEAR: - delete fBufferRef; - fBufferRef = 0; - fBuffer = 0; - gDirectory = cursav; - - return tobj; -} - -//______________________________________________________________________________ -void *TKey::ReadObjectAny(const TClass* expectedClass) -{ - // To read an object (non deriving from TObject) from the file. - // - // If expectedClass is not null, we checked that that actual class of - // the object stored is suitable to be stored in a pointer pointing - // to an object of class 'expectedClass'. We also adjust the value - // of the returned address so that it is suitable to be cast (C-Style) - // a a pointer pointing to an object of class 'expectedClass'. - // - // So for example if the class Bottom inherits from Top and the object - // stored is of type Bottom you can safely do: - // - // TClass *TopClass = TClass::GetClass("Top"); - // Top *ptr = (Top*) key->ReadObjectAny( TopClass ); - // if (ptr==0) printError("the object stored in the key is not of the expected type\n"); - // - // The object associated to this key is read from the file into memory - // Once the key structure is read (via Streamer) the class identifier - // of the object is known. - // Using the class identifier we find the TClass object for this class. - // A TClass object contains a full description (i.e. dictionary) of the - // associated class. In particular the TClass object can create a new - // object of the class type it describes. This new object now calls its - // Streamer function to rebuilt itself. - - fBufferRef = new TBufferFile(TBuffer::kRead, fObjlen+fKeylen); - if (!fBufferRef) { - Error("ReadObj", "Cannot allocate buffer: fObjlen = %d", fObjlen); - return 0; - } - if (GetFile()==0) return 0; - fBufferRef->SetParent(GetFile()); - fBufferRef->SetPidOffset(fPidOffset); - - if (fObjlen > fNbytes-fKeylen) { - fBuffer = new char[fNbytes]; - ReadFile(); //Read object structure from file - memcpy(fBufferRef->Buffer(),fBuffer,fKeylen); - } else { - fBuffer = fBufferRef->Buffer(); - ReadFile(); //Read object structure from file - } - - // get version of key - fBufferRef->SetBufferOffset(sizeof(fNbytes)); - Version_t kvers = fBufferRef->ReadVersion(); - - fBufferRef->SetBufferOffset(fKeylen); - TDirectory *cursav = gDirectory; - TClass *cl = TClass::GetClass(fClassName.Data()); - if (!cl) { - Error("ReadObjectAny", "Unknown class %s", fClassName.Data()); - return 0; - } - Int_t baseOffset = 0; - if (expectedClass) { - // baseOffset will be -1 if cl does not inherit from expectedClass - baseOffset = cl->GetBaseClassOffset(expectedClass); - if (baseOffset == -1) { - return 0; - } - if (cl->GetClassInfo() && !expectedClass->GetClassInfo()) { - //we cannot mix a compiled class with an emulated class in the inheritance - Warning("ReadObjectAny", - "Trying to read an emulated class (%s) to store in a compiled pointer (%s)", - cl->GetName(),expectedClass->GetName()); - } - } - // Create an instance of this class - - void *pobj = cl->New(); - if (!pobj) { - Error("ReadObjectAny", "Cannot create new object of class %s", fClassName.Data()); - return 0; - } - - if (kvers > 1) - fBufferRef->MapObject(pobj,cl); //register obj in map to handle self reference - - if (fObjlen > fNbytes-fKeylen) { - char *objbuf = fBufferRef->Buffer() + fKeylen; - UChar_t *bufcur = (UChar_t *)&fBuffer[fKeylen]; - Int_t nin, nout, nbuf; - Int_t noutot = 0; - while (1) { - nin = 9 + ((Int_t)bufcur[3] | ((Int_t)bufcur[4] << 8) | ((Int_t)bufcur[5] << 16)); - nbuf = (Int_t)bufcur[6] | ((Int_t)bufcur[7] << 8) | ((Int_t)bufcur[8] << 16); - R__unzip(&nin, bufcur, &nbuf, objbuf, &nout); - if (!nout) break; - noutot += nout; - if (noutot >= fObjlen) break; - bufcur += nin; - objbuf += nout; - } - if (nout) { - cl->Streamer((void*)pobj, *fBufferRef); //read object - delete [] fBuffer; - } else { - delete [] fBuffer; - cl->Destructor(pobj); - pobj = 0; - goto CLEAR; - } - } else { - cl->Streamer((void*)pobj, *fBufferRef); //read object - } - - if (cl->InheritsFrom(TObject::Class())) { - Int_t baseOffset = cl->GetBaseClassOffset(TObject::Class()); - if (baseOffset==-1) { - Fatal("ReadObj","Incorrect detection of the inheritance from TObject for class %s.\n", - fClassName.Data()); - } - TObject *tobj = (TObject*)( ((char*)pobj) +baseOffset); - - // See similar adjustments in ReadObj - if (gROOT->GetForceStyle()) tobj->UseCurrentStyle(); - - if (cl == TDirectoryFile::Class()) { - TDirectory *dir = dynamic_cast<TDirectoryFile*>(tobj); - dir->SetName(GetName()); - dir->SetTitle(GetTitle()); - gDirectory->Append(dir); - } - } - - CLEAR: - delete fBufferRef; - fBufferRef = 0; - fBuffer = 0; - gDirectory = cursav; - - return ( ((char*)pobj) + baseOffset ); -} - -//______________________________________________________________________________ -Int_t TKey::Read(TObject *obj) -{ - // To read an object from the file. - // The object associated to this key is read from the file into memory. - // Before invoking this function, obj has been created via the - // default constructor. - - if (!obj || (GetFile()==0)) return 0; - - fBufferRef = new TBufferFile(TBuffer::kRead, fObjlen+fKeylen); - fBufferRef->SetParent(GetFile()); - fBufferRef->SetPidOffset(fPidOffset); - - if (fVersion > 1) - fBufferRef->MapObject(obj); //register obj in map to handle self reference - - if (fObjlen > fNbytes-fKeylen) { - fBuffer = new char[fNbytes]; - ReadFile(); //Read object structure from file - memcpy(fBufferRef->Buffer(),fBuffer,fKeylen); - } else { - fBuffer = fBufferRef->Buffer(); - ReadFile(); //Read object structure from file - } - fBufferRef->SetBufferOffset(fKeylen); - TDirectory *cursav = gDirectory; - if (fObjlen > fNbytes-fKeylen) { - char *objbuf = fBufferRef->Buffer() + fKeylen; - UChar_t *bufcur = (UChar_t *)&fBuffer[fKeylen]; - Int_t nin, nout, nbuf; - Int_t noutot = 0; - while (1) { - nin = 9 + ((Int_t)bufcur[3] | ((Int_t)bufcur[4] << 8) | ((Int_t)bufcur[5] << 16)); - nbuf = (Int_t)bufcur[6] | ((Int_t)bufcur[7] << 8) | ((Int_t)bufcur[8] << 16); - R__unzip(&nin, bufcur, &nbuf, objbuf, &nout); - if (!nout) break; - noutot += nout; - if (noutot >= fObjlen) break; - bufcur += nin; - objbuf += nout; - } - if (nout) obj->Streamer(*fBufferRef); - delete [] fBuffer; - } else { - obj->Streamer(*fBufferRef); - } - delete fBufferRef; - fBufferRef = 0; - fBuffer = 0; - gDirectory = cursav; - return fNbytes; -} - -//______________________________________________________________________________ -void TKey::ReadBuffer(char *&buffer) -{ - // Decode input buffer. - // In some situation will add key to gDirectory ??? - - ReadKeyBuffer(buffer); - - if (!gROOT->ReadingObject() && gDirectory) { - if (fSeekPdir != gDirectory->GetSeekDir()) gDirectory->AppendKey(this); - } -} - -//______________________________________________________________________________ -void TKey::ReadKeyBuffer(char *&buffer) -{ - // Decode input buffer. - - frombuf(buffer, &fNbytes); - Version_t version; - frombuf(buffer,&version); - fVersion = (Int_t)version; - frombuf(buffer, &fObjlen); - fDatime.ReadBuffer(buffer); - frombuf(buffer, &fKeylen); - frombuf(buffer, &fCycle); - if (fVersion > 1000) { - frombuf(buffer, &fSeekKey); - - // We currently store in the 16 highest bit of fSeekPdir the value of - // fPidOffset. This offset is used when a key (or basket) is transfered from one - // file to the other. In this case the TRef and TObject might have stored a - // pid index (to retrieve TProcessIDs) which refered to their order on the original - // file, the fPidOffset is to be added to those values to correctly find the - // TProcessID. This fPidOffset needs to be increment if the key/basket is copied - // and need to be zero for new key/basket. - Long64_t pdir; - frombuf(buffer, &pdir); - fPidOffset = pdir >> kPidOffsetShift; - fSeekPdir = pdir & kPidOffsetMask; - } else { - Int_t seekkey,seekdir; - frombuf(buffer, &seekkey); fSeekKey = (Long64_t)seekkey; - frombuf(buffer, &seekdir); fSeekPdir= (Long64_t)seekdir; - } - fClassName.ReadBuffer(buffer); - //the following test required for forward and backward compatibility - if (fClassName == "TDirectory") fClassName = "TDirectoryFile"; - - fName.ReadBuffer(buffer); - fTitle.ReadBuffer(buffer); -} - -//______________________________________________________________________________ -void TKey::ReadFile() -{ - // Read the key structure from the file - - TFile* f = GetFile(); - if (f==0) return; - - Int_t nsize = fNbytes; - f->Seek(fSeekKey); -#if 0 - for (Int_t i = 0; i < nsize; i += kMAXFILEBUFFER) { - int nb = kMAXFILEBUFFER; - if (i+nb > nsize) nb = nsize - i; - f->ReadBuffer(fBuffer+i,nb); - } -#else - f->ReadBuffer(fBuffer,nsize); -#endif - if (gDebug) { - cout << "TKey Reading "<<nsize<< " bytes at address "<<fSeekKey<<endl; - } -} - -//______________________________________________________________________________ -void TKey::SetParent(const TObject *parent) -{ - // Set parent in key buffer. - - if (fBufferRef) fBufferRef->SetParent((TObject*)parent); -} - -//______________________________________________________________________________ -Int_t TKey::Sizeof() const -{ - // Return the size in bytes of the key header structure. - // Int_t nbytes = sizeof fNbytes; 4 - // += sizeof(Version_t); 2 - // += sizeof fObjlen; 4 - // += sizeof fKeylen; 2 - // += sizeof fCycle; 2 - // += sizeof fSeekKey; 4 or 8 - // += sizeof fSeekPdir; 4 or 8 - // = 22 - - Int_t nbytes = 22; if (fVersion > 1000) nbytes += 8; - nbytes += fDatime.Sizeof(); - nbytes += fClassName.Sizeof(); - nbytes += fName.Sizeof(); - nbytes += fTitle.Sizeof(); - return nbytes; -} - -//_______________________________________________________________________ -void TKey::Streamer(TBuffer &b) -{ - // Stream a class object. - - Version_t version; - if (b.IsReading()) { - b >> fNbytes; - b >> version; fVersion = (Int_t)version; - b >> fObjlen; - fDatime.Streamer(b); - b >> fKeylen; - b >> fCycle; - if (fVersion > 1000) { - b >> fSeekKey; - - // We currently store in the 16 highest bit of fSeekPdir the value of - // fPidOffset. This offset is used when a key (or basket) is transfered from one - // file to the other. In this case the TRef and TObject might have stored a - // pid index (to retrieve TProcessIDs) which refered to their order on the original - // file, the fPidOffset is to be added to those values to correctly find the - // TProcessID. This fPidOffset needs to be increment if the key/basket is copied - // and need to be zero for new key/basket. - Long64_t pdir; - b >> pdir; - fPidOffset = pdir >> kPidOffsetShift; - fSeekPdir = pdir & kPidOffsetMask; - } else { - Int_t seekkey, seekdir; - b >> seekkey; fSeekKey = (Long64_t)seekkey; - b >> seekdir; fSeekPdir= (Long64_t)seekdir; - } - fClassName.Streamer(b); - fName.Streamer(b); - fTitle.Streamer(b); - } else { - b << fNbytes; - version = (Version_t)fVersion; - b << version; - b << fObjlen; - if (fDatime.Get() == 0) fDatime.Set(); - fDatime.Streamer(b); - b << fKeylen; - b << fCycle; - if (fVersion > 1000) { - b << fSeekKey; - - // We currently store in the 16 highest bit of fSeekPdir the value of - // fPidOffset. This offset is used when a key (or basket) is transfered from one - // file to the other. In this case the TRef and TObject might have stored a - // pid index (to retrieve TProcessIDs) which refered to their order on the original - // file, the fPidOffset is to be added to those values to correctly find the - // TProcessID. This fPidOffset needs to be increment if the key/basket is copied - // and need to be zero for new key/basket. - Long64_t pdir = (((Long64_t)fPidOffset)<<kPidOffsetShift) | (kPidOffsetMask & fSeekPdir); - b << pdir; - } else { - b << (Int_t)fSeekKey; - b << (Int_t)fSeekPdir; - } - fClassName.Streamer(b); - fName.Streamer(b); - fTitle.Streamer(b); - } -} - -//______________________________________________________________________________ -Int_t TKey::WriteFile(Int_t cycle, TFile* f) -{ - // Write the encoded object supported by this key. - // The function returns the number of bytes committed to the file. - // If a write error occurs, the number of bytes returned is -1. - - if (!f) f = GetFile(); - if (!f) return -1; - - Int_t nsize = fNbytes; - char *buffer = fBuffer; - if (cycle) { - fCycle = cycle; - FillBuffer(buffer); - buffer = fBuffer; - } - - if (fLeft > 0) nsize += sizeof(Int_t); - f->Seek(fSeekKey); -#if 0 - for (Int_t i=0;i<nsize;i+=kMAXFILEBUFFER) { - Int_t nb = kMAXFILEBUFFER; - if (i+nb > nsize) nb = nsize - i; - f->WriteBuffer(buffer,nb); - buffer += nb; - } -#else - Bool_t result = f->WriteBuffer(buffer,nsize); -#endif - //f->Flush(); Flushing takes too much time. - // Let user flush the file when he wants. - if (gDebug) { - cout <<" TKey Writing "<<nsize<< " bytes at address "<<fSeekKey - <<" for ID= " <<GetName()<<" Title= "<<GetTitle()<<endl; - } - - DeleteBuffer(); - return result==kTRUE ? -1 : nsize; -} - -//______________________________________________________________________________ -const char *TKey::GetIconName() const -{ - // Title can keep 32x32 xpm thumbnail/icon of the parent object. - - return (!fTitle.IsNull() && fTitle.BeginsWith("/* ") ? fTitle.Data() : 0); -} - -//______________________________________________________________________________ -const char *TKey::GetTitle() const -{ - // Returns title (title can contain 32x32 xpm thumbnail/icon). - - if (!fTitle.IsNull() && fTitle.BeginsWith("/* ")) { // title contains xpm thumbnail - static TString ret; - int start = fTitle.Index("/*") + 3; - int stop = fTitle.Index("*/") - 1; - ret = fTitle(start, stop - start); - return ret.Data(); - } - return fTitle.Data(); -} diff --git a/base/src/TMapFile.cxx b/base/src/TMapFile.cxx deleted file mode 100644 index f98f37cfebf758eddc0f1775b23b8b5bad3a8781..0000000000000000000000000000000000000000 --- a/base/src/TMapFile.cxx +++ /dev/null @@ -1,1151 +0,0 @@ -// @(#)root/base:$Name: $:$Id: TMapFile.cxx,v 1.26 2007/01/29 15:53:35 brun Exp $ -// Author: Fons Rademakers 08/07/97 - -/************************************************************************* - * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ -#ifdef WIN32 -#pragma optimize("",off) -#endif - -////////////////////////////////////////////////////////////////////////// -// // -// TMapFile // -// // -// This class implements a shared memory region mapped to a file. // -// Objects can be placed into this shared memory area using the Add() // -// member function. To actually place a copy of the object is shared // -// memory call Update() also whenever the mapped object(s) change(s) // -// call Update() to put a fresh copy in the shared memory. This extra // -// step is necessary since it is not possible to share objects with // -// virtual pointers between processes (the vtbl ptr points to the // -// originators unique address space and can not be used by the // -// consumer process(es)). Consumer processes can map the memory region // -// from this file and access the objects stored in it via the Get() // -// method (which returns a copy of the object stored in the shared // -// memory with correct vtbl ptr set). Only objects of classes with a // -// Streamer() member function defined can be shared. // -// // -// I know the current implementation is not ideal (you need to copy to // -// and from the shared memory file) but the main problem is with the // -// class' virtual_table pointer. This pointer points to a table unique // -// for every process. Therefore, different options are: // -// 1) One could allocate an object directly in shared memory in the // -// producer, but the consumer still has to copy the object from // -// shared memory into a local object which has the correct vtbl // -// pointer for that process (copy ctor's can be used for creating // -// the local copy). // -// 2) Another possibility is to only allow objects without virtual // -// functions in shared memory (like simple C structs), or to // -// forbid (how?) the consumer from calling any virtual functions // -// of the objects in shared memory. // -// 3) A last option is to copy the object internals to shared memory // -// and copy them again from there. This is what is done in the // -// TMapFile (using the object Streamer() to make a deep copy). // -// Option 1) saves one copy, but requires solid copy ctor's (along the // -// full inheritance chain) to rebuild the object in the consumer. Most // -// classes don't provide these copy ctor's, especially not when objects // -// contain collections, etc. 2) is too limiting or dangerous (calling // -// accidentally a virtual function will segv). So since we have a // -// robust Streamer mechanism I opted for 3). // -// // -////////////////////////////////////////////////////////////////////////// - - -#ifdef WIN32 -# include <windows.h> -# include <process.h> -# ifdef GetObject -# undef GetObject -# endif -# define HAVE_SEMOP - -# ifdef CreateSemaphore -# undef CreateSemaphore -# endif - -# ifdef AcquireSemaphore -# undef AcquireSemaphore; -# endif - -# ifdef ReleaseSemaphore -# undef ReleaseSemaphore -# endif - -# ifdef DeleteSemaphore -# undef DeleteSemaphore -# endif - -#else -# define INVALID_HANDLE_VALUE -1 -#endif - -#include <fcntl.h> -#include <errno.h> - -#include "TMapFile.h" -#include "TKeyMapFile.h" -#include "TDirectoryFile.h" -#include "TBrowser.h" -#include "TString.h" -#include "TSystem.h" -#include "TClass.h" -#include "TBufferFile.h" -#include "TVirtualMutex.h" -#include <cmath> - -#if defined(R__UNIX) && !defined(R__MACOSX) && !defined(R__WINGCC) -#define HAVE_SEMOP -#include <sys/types.h> -#include <sys/ipc.h> -#include <sys/sem.h> -#if defined(R__HPUX) || (defined (R__ALPHA) && !defined(R__FBSD)) || \ - defined (R__SOLARIS) || defined(R__AIX) || defined(R__HIUX) || \ - __GLIBC_MINOR__ > 0 -union semun { - int val; // value for SETVAL - struct semid_ds *buf; // buffer for IPC_STAT & IPC_SET - ushort *array; // array for GETALL & SETALL -}; -#endif -#if defined(R__LINUX) || defined(R__LYNXOS) || defined(R__HURD) -# define SEM_A 0200 // alter permission -# define SEM_R 0400 // read permission -#endif -#endif - - -Long_t TMapFile::fgMapAddress = 0; -void *TMapFile::fgMmallocDesc = 0; - -//void *gMmallocDesc = 0; //is initialized in TClass.cxx - - - -//______________________________________________________________________________ -TMapRec::TMapRec(const char *name, const TObject *obj, Int_t size, void *buf) -{ - /// Constructor. - fName = StrDup(name); - fClassName = 0; - fObject = (TObject*)obj; - fBuffer = buf; - fBufSize = size; - fNext = 0; -} - -//______________________________________________________________________________ -TMapRec::~TMapRec() -{ - // Destructor. - delete [] fName; - delete [] fClassName; -} - -//______________________________________________________________________________ -TObject *TMapRec::GetObject() const -{ - // This method returns a pointer to the original object. NOTE: this pointer - // is only valid in the process that produces the shared memory file. In a - // consumer process this pointer is illegal! Be careful. - - return fObject; -} - - - - -ClassImp(TMapFile) - -//______________________________________________________________________________ -TMapFile::TMapFile() -{ - // Default ctor. Does not much except setting some basic values. - - fFd = -1; - fMmallocDesc = 0; - fFirst = 0; -} - -//______________________________________________________________________________ -TMapFile::TMapFile(const char *name, const char *title, Option_t *option, - Int_t size, TMapFile *&newMapFile) -{ - // Create a memory mapped file. This opens a file (to which the - // memory will be mapped) and attaches a memory region to it. - // Option can be either: "NEW", "CREATE", "RECREATE", "UPDATE" or - // "READ" (see TFile). The default open mode is "READ". The size - // argument specifies the maximum size of shared memory file in bytes. - // This protected ctor is called via the static Create() method. - -#ifndef WIN32 - fFd = -1; - fSemaphore = -1; -#else - fFd = (Int_t) INVALID_HANDLE_VALUE; - fSemaphore = (Int_t) INVALID_HANDLE_VALUE; -#endif - fMmallocDesc = 0; - fSize = size; - fFirst = 0; - fOffset = 0; - fVersion = gROOT->GetVersionInt(); - fTitle = StrDup(title); - fOption = StrDup(option); - fDirectory = 0; - fBrowseList = 0; - fGetting = 0; - fWritten = 0; - fSumBuffer = 0; - fSum2Buffer = 0; - - char *cleanup = 0; - Bool_t create = kFALSE; - Bool_t recreate, update, read; - - { - TString opt = option; - - if (!opt.CompareTo("NEW", TString::kIgnoreCase) || - !opt.CompareTo("CREATE", TString::kIgnoreCase)) - create = kTRUE; - recreate = opt.CompareTo("RECREATE", TString::kIgnoreCase) - ? kFALSE : kTRUE; - update = opt.CompareTo("UPDATE", TString::kIgnoreCase) - ? kFALSE : kTRUE; - read = opt.CompareTo("READ", TString::kIgnoreCase) - ? kFALSE : kTRUE; - if (!create && !recreate && !update && !read) { - read = kTRUE; - delete [] fOption; - fOption = StrDup("READ"); - } - } - - const char *fname; - if ((fname = gSystem->ExpandPathName(name))) { - fName = StrDup(fname); - delete [] (char*)fname; - fname = fName; - } else { - Error("TMapFile", "error expanding path %s", fname); - goto zombie; - } - - if (recreate) { - if (!gSystem->AccessPathName(fname, kFileExists)) - gSystem->Unlink(fname); - recreate = kFALSE; - create = kTRUE; - delete [] fOption; - fOption = StrDup("CREATE"); - } - if (create && !gSystem->AccessPathName(fname, kFileExists)) { - Error("TMapFile", "file %s already exists", fname); - goto zombie; - } - if (update) { - if (gSystem->AccessPathName(fname, kFileExists)) { - update = kFALSE; - create = kTRUE; - } - if (update && gSystem->AccessPathName(fname, kWritePermission)) { - Error("TMapFile", "no write permission, could not open file %s", fname); - goto zombie; - } - } - if (read) { - if (gSystem->AccessPathName(fname, kFileExists)) { - Error("TMapFile", "file %s does not exist", fname); - goto zombie; - } - if (gSystem->AccessPathName(fname, kReadPermission)) { - Error("TMapFile", "no read permission, could not open file %s", fname); - goto zombie; - } - } - - // Open file to which memory will be mapped - if (create || update) { -#ifndef WIN32 - fFd = open(fname, O_RDWR | O_CREAT, 0644); -#else - fFd = (Int_t) CreateFile(fname, // pointer to name of the file - GENERIC_WRITE | GENERIC_READ, // access (read-write) mode - FILE_SHARE_WRITE | FILE_SHARE_READ, // share mode - NULL, // pointer to security attributes - OPEN_ALWAYS, // how to create - FILE_ATTRIBUTE_TEMPORARY, // file attributes - (HANDLE) NULL); // handle to file with attributes to copy -#endif - if (fFd == (Int_t)INVALID_HANDLE_VALUE) { - SysError("TMapFile", "file %s can not be opened", fname); - goto zombie; - } - fWritable = kTRUE; - } else { -#ifndef WIN32 - fFd = open(fname, O_RDONLY); -#else - fFd = (Int_t) CreateFile(fname, // pointer to name of the file - GENERIC_READ, // access (read-write) mode - FILE_SHARE_WRITE | FILE_SHARE_READ, // share mode - NULL, // pointer to security attributes - OPEN_EXISTING, // how to create - FILE_ATTRIBUTE_TEMPORARY, // file attributes - (HANDLE) NULL); // handle to file with attributes to copy -#endif - if (fFd == (Int_t)INVALID_HANDLE_VALUE) { - SysError("TMapFile", "file %s can not be opened for reading", fname); - goto zombie; - } - fWritable = kFALSE; - } - - // Attach memory region to file. - void *mapto; - TMapFile *mapfil; - - if (((mapto = MapToAddress()) == (void *)-1) || -#ifndef WIN32 - ((fMmallocDesc = mmalloc_attach(fFd, mapto, fSize)) == 0)) { -#else - ((fMmallocDesc = mmalloc_attach((HANDLE) fFd, mapto, fSize)) == 0)) { -#endif - - if (mapto == (void *)-1) { - Error("TMapFile", "no memory mapped file capability available\n" - "Use rootn.exe or link application against \"-lNew\""); - } else { - if (fMmallocDesc == 0 && fWritable) - Error("TMapFile", "mapped file not in mmalloc format or\n" - "already open in RW mode by another process"); - if (fMmallocDesc == 0 && !fWritable) - Error("TMapFile", "mapped file not in mmalloc format"); - } -#ifndef WIN32 - close(fFd); -#else - CloseHandle((HANDLE) fFd); -#endif - fFd = -1; - if (create) - gSystem->Unlink(fname); - goto zombie; - - } else if ((mapfil = (TMapFile *) mmalloc_getkey(fMmallocDesc, 0)) != 0) { - - // File contains mmalloc heap. If we are in write mode and mapped - // file already connected in write mode switch to read-only mode. - // Check if ROOT versions are compatible. - // If so update mapped version of TMapFile to reflect current - // situation (only if not opened in READ mode). - if (mapfil->fVersion != fVersion) { - Error("TMapFile", "map file %s (%d) incompatible with current ROOT version (%d)", - fname, mapfil->fVersion, fVersion); - mmalloc_detach(fMmallocDesc); -#ifndef WIN32 - close(fFd); -#else - CloseHandle((HANDLE) fFd); -#endif - fFd = -1; - fMmallocDesc = 0; - goto zombie; - } - - if (mapfil->fWritable && fWritable) { - Warning("TMapFile", "map file already open in write mode, opening in read-only mode"); - fWritable = kFALSE; - } - - fBaseAddr = mapfil->fBaseAddr; - fSize = mapfil->fSize; - - if (fWritable) { - // create new TMapFile object in mapped heap to get correct vtbl ptr - CreateSemaphore(); - gMmallocDesc = fMmallocDesc; - TMapFile *mf = new TMapFile(*mapfil); - mf->fFd = fFd; - mf->fWritable = kTRUE; - cleanup = mf->fOption; - mf->fOption = StrDup(fOption); - mf->fSemaphore = fSemaphore; -#ifdef WIN32 - mf->CreateSemaphore(fSemaphore); -#endif - mmalloc_setkey(fMmallocDesc, 0, mf); - gMmallocDesc = 0; - mapfil = mf; - } else { - gMmallocDesc = 0; // make sure we are in sbrk heap - fOffset = ((struct mdesc *) fMmallocDesc)->offset; - TMapFile *mf = new TMapFile(*mapfil, fOffset); - delete [] mf->fOption; - mf->fFd = fFd; - mf->fOption = StrDup("READ"); - mf->fMmallocDesc = fMmallocDesc; - mf->fWritable = kFALSE; - mapfil = mf; - } - - // store shadow mapfile (it contains the real fFd in case map - // is not writable) - fVersion = -1; // make this the shadow map file - R__LOCKGUARD2(gROOTMutex); - gROOT->GetListOfMappedFiles()->AddLast(this); - - } else { - - // New file. If the file is writable create a new copy of the - // TMapFile which will now be allocated on the memory mapped heap. - if (!fWritable) { - Error("TMapFile", "map file is not writable"); - mmalloc_detach(fMmallocDesc); -#ifndef WIN32 - close(fFd); -#else - CloseHandle((HANDLE) fFd); -#endif - fFd = -1; - fMmallocDesc = 0; - goto zombie; - } - - fBaseAddr = (ULong_t)((struct mdesc *) fMmallocDesc)->base; - - CreateSemaphore(); - - gMmallocDesc = fMmallocDesc; - - mapfil = new TMapFile(*this); - mmalloc_setkey(fMmallocDesc, 0, mapfil); - - gMmallocDesc = 0; - - // store shadow mapfile - fVersion = -1; // make this the shadow map file - R__LOCKGUARD2(gROOTMutex); - gROOT->GetListOfMappedFiles()->AddLast(this); - - } - - mapfil->InitDirectory(); - { - R__LOCKGUARD2(gROOTMutex); - gROOT->GetListOfMappedFiles()->AddFirst(mapfil); - } - - if (cleanup) delete [] cleanup; - - newMapFile = mapfil; - - return; - -zombie: - // error in file opening occured, make this object a zombie - MakeZombie(); - newMapFile = this; - gMmallocDesc = 0; -} - -//______________________________________________________________________________ -TMapFile::TMapFile(const TMapFile &f, Long_t offset) : TObject(f) -{ - // Private copy ctor. Used by the the ctor to create a new version - // of TMapFile in the memory mapped heap. It's main purpose is to - // correctly create the string data members. - - fFd = f.fFd; - fVersion = f.fVersion; - fName = StrDup((char *)((long)f.fName + offset)); - fTitle = StrDup((char *)((long)f.fTitle + offset)); - fOption = StrDup((char *)((long)f.fOption + offset)); - fMmallocDesc = f.fMmallocDesc; - fBaseAddr = f.fBaseAddr; - fSize = f.fSize; - fFirst = f.fFirst; - fLast = f.fLast; - fWritable = f.fWritable; - fSemaphore = f.fSemaphore; - fOffset = offset; - fDirectory = 0; - fBrowseList = 0; - fGetting = 0; - fWritten = f.fWritten; - fSumBuffer = f.fSumBuffer; - fSum2Buffer = f.fSum2Buffer; -#ifdef WIN32 - CreateSemaphore(fSemaphore); -#endif -} - -//______________________________________________________________________________ -TMapFile::~TMapFile() -{ - // TMapFiles may not be deleted, since we want to keep the complete - // TMapFile object in the mapped file for later re-use. To enforce this - // the delete operator has been made private. Use Close() to properly - // terminate a TMapFile (also done via the TROOT dtor). - - if (fDirectory == gDirectory) gDirectory = gROOT; - delete fDirectory; fDirectory = 0; - if (fBrowseList) fBrowseList->Delete(); - delete fBrowseList; fBrowseList = 0; - - // if shadow map file we are done here - if (fVersion == -1) - return; - - // Writable mapfile is allocated in mapped memory. This object should - // not be deleted by ::operator delete(), because it is needed if we - // want to connect later to the file again. - if (fWritable) - TObject::SetDtorOnly(this); - - Close("dtor"); - - fgMmallocDesc = fMmallocDesc; -} - -//______________________________________________________________________________ -void TMapFile::InitDirectory() -{ - // Create the directory associated to this mapfile - - gDirectory = 0; - fDirectory = new TDirectoryFile(); - fDirectory->SetName(GetName()); - fDirectory->SetTitle(GetTitle()); - fDirectory->Build(); - fDirectory->SetMother(this); - gDirectory = fDirectory; -} - -//______________________________________________________________________________ -void TMapFile::Add(const TObject *obj, const char *name) -{ - // Add an object to the list of objects to be stored in shared memory. - // To place the object actually into shared memory call Update(). - - if (!fWritable || !fMmallocDesc) return; - - Bool_t lock = fGetting != obj ? kTRUE : kFALSE; - - if (lock) - AcquireSemaphore(); - - gMmallocDesc = fMmallocDesc; - - const char *n; - if (name && *name) - n = name; - else - n = obj->GetName(); - - if (Remove(n, kFALSE)) - ; //Warning("Add", "replaced object with same name %s", n); - - TMapRec *mr = new TMapRec(n, obj, 0, 0); - if (!fFirst) { - fFirst = mr; - fLast = mr; - } else { - fLast->fNext = mr; - fLast = mr; - } - - gMmallocDesc = 0; - - if (lock) - ReleaseSemaphore(); -} - -//______________________________________________________________________________ -void TMapFile::Update(TObject *obj) -{ - // Update an object (or all objects, if obj == 0) in shared memory. - - if (!fWritable || !fMmallocDesc) return; - - AcquireSemaphore(); - - gMmallocDesc = fMmallocDesc; - - Bool_t all = (obj == 0) ? kTRUE : kFALSE; - - TMapRec *mr = fFirst; - while (mr) { - if (all || mr->fObject == obj) { - TBufferFile *b; - if (!mr->fBufSize) { - b = new TBufferFile(TBuffer::kWrite, GetBestBuffer()); - mr->fClassName = StrDup(mr->fObject->ClassName()); - } else - b = new TBufferFile(TBuffer::kWrite, mr->fBufSize, mr->fBuffer); - b->MapObject(mr->fObject); //register obj in map to handle self reference - mr->fObject->Streamer(*b); - mr->fBufSize = b->BufferSize(); - mr->fBuffer = b->Buffer(); - SumBuffer(b->Length()); - b->DetachBuffer(); - delete b; - } - mr = mr->fNext; - } - - gMmallocDesc = 0; - - ReleaseSemaphore(); -} - -//______________________________________________________________________________ -TObject *TMapFile::Remove(TObject *obj, Bool_t lock) -{ - // Remove object from shared memory. Returns pointer to removed - // object if successful, 0 otherwise. - - if (!fWritable || !fMmallocDesc) return 0; - - if (lock) - AcquireSemaphore(); - - TObject *retObj = 0; - TMapRec *prev = 0, *mr = fFirst; - while (mr) { - if (mr->fObject == obj) { - if (mr == fFirst) { - fFirst = mr->fNext; - if (mr == fLast) - fLast = 0; - } else { - prev->fNext = mr->fNext; - if (mr == fLast) - fLast = prev; - } - retObj = obj; - delete mr; - break; - } - prev = mr; - mr = mr->fNext; - } - - if (lock) - ReleaseSemaphore(); - - return retObj; -} - -//______________________________________________________________________________ -TObject *TMapFile::Remove(const char *name, Bool_t lock) -{ - // Remove object by name from shared memory. Returns pointer to removed - // object if successful, 0 otherwise. - - if (!fWritable || !fMmallocDesc) return 0; - - if (lock) - AcquireSemaphore(); - - TObject *retObj = 0; - TMapRec *prev = 0, *mr = fFirst; - while (mr) { - if (!strcmp(mr->fName, name)) { - if (mr == fFirst) { - fFirst = mr->fNext; - if (mr == fLast) - fLast = 0; - } else { - prev->fNext = mr->fNext; - if (mr == fLast) - fLast = prev; - } - retObj = mr->fObject; - delete mr; - break; - } - prev = mr; - mr = mr->fNext; - } - - if (lock) - ReleaseSemaphore(); - - return retObj; -} - -//______________________________________________________________________________ -void TMapFile::RemoveAll() -{ - // Remove all objects from shared memory. - - if (!fWritable || !fMmallocDesc) return; - - AcquireSemaphore(); - - TMapRec *mr = fFirst; - while (mr) { - TMapRec *t = mr; - mr = mr->fNext; - delete t; - } - fFirst = fLast = 0; - - ReleaseSemaphore(); -} - -//______________________________________________________________________________ -TObject *TMapFile::Get(const char *name, TObject *delObj) -{ - // Return pointer to object retrieved from shared memory. The object must - // be deleted after use. If delObj is a pointer to a previously allocated - // object it will be deleted. Returns 0 in case object with the given - // name does not exist. - - if (!fMmallocDesc) return 0; - - AcquireSemaphore(); - - delete delObj; - - TObject *obj = 0; - TMapRec *mr = GetFirst(); - while (OrgAddress(mr)) { - if (!strcmp(mr->GetName(fOffset), name)) { - if (!mr->fBufSize) goto release; - TClass *cl = TClass::GetClass(mr->GetClassName(fOffset)); - if (!cl) { - Error("Get", "unknown class %s", mr->GetClassName(fOffset)); - goto release; - } - - obj = (TObject *)cl->New(); - if (!obj) { - Error("Get", "cannot create new object of class %s", mr->GetClassName(fOffset)); - goto release; - } - - fGetting = obj; - TBufferFile *b = new TBufferFile(TBuffer::kRead, mr->fBufSize, mr->GetBuffer(fOffset)); - b->MapObject(obj); //register obj in map to handle self reference - obj->Streamer(*b); - b->DetachBuffer(); - delete b; - fGetting = 0; - goto release; - } - mr = mr->GetNext(fOffset); - } - -release: - ReleaseSemaphore(); - - return obj; -} - -//______________________________________________________________________________ -#ifndef WIN32 -void TMapFile::CreateSemaphore(int) -#else -void TMapFile::CreateSemaphore(int pid) -#endif -{ - // Create semaphore used for synchronizing access to shared memory. - -#ifdef HAVE_SEMOP -#ifndef WIN32 - // create semaphore to synchronize access (should use read/write lock) - fSemaphore = semget(IPC_PRIVATE, 1, SEM_R|SEM_A|(SEM_R>>3)|(SEM_A>>3)| - (SEM_R>>6)|(SEM_A>>6)); - - // set semaphore to 1 - if (fSemaphore != -1) { - union semun set; - set.val = 1; - semctl(fSemaphore, 0, SETVAL, set); - } -#else - char buffer[] ="ROOT_Semaphore_xxxxxxxx"; - int lbuf = strlen(buffer); - if (!pid) fSemaphore = getpid(); - fhSemaphore = (ULong_t)CreateMutex(NULL,FALSE,itoa(fSemaphore,&buffer[lbuf-8],16)); - if (fhSemaphore == 0) fSemaphore = (Int_t)INVALID_HANDLE_VALUE; -#endif -#endif -} - -//______________________________________________________________________________ -void TMapFile::DeleteSemaphore() -{ - // Delete the semaphore. - -#ifdef HAVE_SEMOP - // remove semaphore -#ifndef WIN32 - if (fSemaphore != -1) { - int semid = fSemaphore; - fSemaphore = -1; - union semun set; - set.val = 0; - semctl(semid, 0, IPC_RMID, set); - } -#else - if (fSemaphore != (Int_t)INVALID_HANDLE_VALUE) { - CloseHandle((HANDLE)fhSemaphore); - fhSemaphore = 0; - fSemaphore = (Int_t)INVALID_HANDLE_VALUE; - } -#endif -#endif -} - -//______________________________________________________________________________ -Int_t TMapFile::AcquireSemaphore() -{ - // Acquire semaphore. Returns 0 if OK, -1 on error. - -#ifdef HAVE_SEMOP -#ifndef WIN32 - if (fSemaphore != -1) { - struct sembuf buf = { 0, -1, SEM_UNDO }; - int intr = 0; -again: - if (semop(fSemaphore, &buf, 1) == -1) { -#if defined(R__FBSD) || defined(R__OBSD) - if (TSystem::GetErrno() == EINVAL) -#else - if (TSystem::GetErrno() == EIDRM) -#endif - fSemaphore = -1; -#if !defined(R__FBSD) - if (TSystem::GetErrno() == EINTR) { - if (intr > 2) - return -1; - TSystem::ResetErrno(); - intr++; - goto again; - } -#endif - } - } -#else - // Enter Critical section to "write" lock - if (fSemaphore != (Int_t)INVALID_HANDLE_VALUE) - WaitForSingleObject((HANDLE)fhSemaphore,INFINITE); -#endif -#endif - - // file might have grown, update mapping on reader to new size - if (!fWritable && fMmallocDesc) { - if (mmalloc_update_mapping(fMmallocDesc) == -1) - Error("AcquireSemaphore", "cannot update mapping"); - } - - return 0; -} - -//______________________________________________________________________________ -Int_t TMapFile::ReleaseSemaphore() -{ - // Release semaphore. Returns 0 if OK, -1 on error. - -#ifdef HAVE_SEMOP -#ifndef WIN32 - if (fSemaphore != -1) { - struct sembuf buf = { 0, 1, SEM_UNDO }; - if (semop(fSemaphore, &buf, 1) == -1) { -#if defined(R__FBSD) || defined(R__OBSD) - if (TSystem::GetErrno() == EINVAL) -#else - if (TSystem::GetErrno() == EIDRM) -#endif - fSemaphore = -1; - } - } -#else - if (fSemaphore != (Int_t)INVALID_HANDLE_VALUE) - ReleaseMutex((HANDLE)fhSemaphore); -#endif -#endif - return 0; -} - -//______________________________________________________________________________ -void TMapFile::Close(Option_t *option) -{ - // Close a mapped file. First detach mapped memory then close file. - // No member functions of a TMapFile that was opened in write mode - // may be called after Close() (this includes, of course, "delete" which - // would call the dtors). The option="dtor" is only used when called - // via the ~TMapFile. - - if (!fMmallocDesc) return; - - TMapFile *shadow = FindShadowMapFile(); - if (!shadow) { - Error("Close", "shadow map == 0, should never happen!"); - return; - } - - { - R__LOCKGUARD2(gROOTMutex); - gROOT->GetListOfMappedFiles()->Remove(shadow); - gROOT->GetListOfMappedFiles()->Remove(this); - } - - if (shadow->fWritable) { - fWritable = kFALSE; - DeleteSemaphore(); - } - - if (fMmallocDesc) { - if (strcmp(option, "dtor")) - mmalloc_detach(fMmallocDesc); - - // If writable cannot access fMmallocDesc anymore since - // it points to the just unmapped memory region. Any further - // access to this TMapFile will cause a crash. - if (!shadow->fWritable) - fMmallocDesc = 0; - } - - if (shadow->fFd != -1) -#ifndef WIN32 - close(shadow->fFd); -#else - CloseHandle((HANDLE)shadow->fFd); -#endif - - delete shadow; -} - -//______________________________________________________________________________ -TMapFile *TMapFile::FindShadowMapFile() -{ - // Returns shadow map file. - - R__LOCKGUARD2(gROOTMutex); - TObjLink *lnk = ((TList *)gROOT->GetListOfMappedFiles())->LastLink(); - while (lnk) { - TMapFile *mf = (TMapFile*)lnk->GetObject(); - if (mf->fVersion == -1 && fBaseAddr == mf->fBaseAddr && fSize == mf->fSize) - return mf; - lnk = lnk->Prev(); - } - return 0; -} - -//______________________________________________________________________________ -void TMapFile::Print(Option_t *) const -{ - // Print some info about the mapped file. - - Printf("Memory mapped file: %s", fName); - Printf("Title: %s", fTitle); - if (fMmallocDesc) { - Printf("Option: %s", fOption); - ULong_t size = (ULong_t)((struct mdesc *)fMmallocDesc)->top - fBaseAddr; - Printf("Mapped Memory region: 0x%lx - 0x%lx (%.2f MB)", fBaseAddr, fBaseAddr + size, - (float)size/1048576); - Printf("Current breakval: 0x%lx", (ULong_t)GetBreakval()); - } else - Printf("Option: file closed"); -} - -//______________________________________________________________________________ -Bool_t TMapFile::IsFolder() const -{ - // Returns kTRUE in case object is a folder (i.e. contains browsable lists). - - if (fMmallocDesc && fVersion > 0) return kTRUE; - return kFALSE; -} - -//______________________________________________________________________________ -void TMapFile::Browse(TBrowser *b) -{ - // Browse contents of TMapFile. - - if (b && fMmallocDesc) { - - AcquireSemaphore(); - - TMapRec *mr = GetFirst(); - TKeyMapFile *keymap; - if (!fBrowseList) fBrowseList = new TList(); - while (OrgAddress(mr)) { - keymap = (TKeyMapFile*)fBrowseList->FindObject(mr->GetName(fOffset)); - if (!keymap) { - keymap = new TKeyMapFile(mr->GetName(fOffset),mr->GetClassName(fOffset),this); - fBrowseList->Add(keymap); - } - b->Add(keymap, keymap->GetName()); - mr = mr->GetNext(fOffset); - } - - ReleaseSemaphore(); - - } -} - -//______________________________________________________________________________ -Bool_t TMapFile::cd(const char *path) -{ - // Cd to associated directory, - - if (fDirectory) - return fDirectory->cd(path); - return kFALSE; -} - -//______________________________________________________________________________ -void TMapFile::ls(Option_t *) const -{ - // List contents of TMapFile. - - if (fMmallocDesc) { - - ((TMapFile*)this)->AcquireSemaphore(); - - Printf("%-20s %-20s %-10s", "Object", "Class", "Size"); - if (!fFirst) - Printf("*** no objects stored in memory mapped file ***"); - - TMapRec *mr = GetFirst(); - while (OrgAddress(mr)) { - Printf("%-20s %-20s %-10d", mr->GetName(fOffset), - mr->GetClassName(fOffset), mr->fBufSize); - mr = mr->GetNext(fOffset); - } - - ((TMapFile*)this)->ReleaseSemaphore(); - - } -} - -//_______________________________________________________________________ -void TMapFile::SumBuffer(Int_t bufsize) -{ - // Increment statistics for buffer sizes of objects in this file. - - fWritten++; - fSumBuffer += bufsize; - fSum2Buffer += bufsize*bufsize; -} - -//______________________________________________________________________________ -Int_t TMapFile::GetBestBuffer() -{ - // Return the best buffer size for objects in this file. - // - // The best buffer size is estimated based on the current mean value - // and standard deviation of all objects written so far to this file. - // Returns mean value + one standard deviation. - - if (!fWritten) return TBuffer::kMinimalSize; - Double_t mean = fSumBuffer/fWritten; - Double_t rms2 = TMath::Abs(fSum2Buffer/fSumBuffer - mean*mean); - return (Int_t)(mean + sqrt(rms2)); -} - - -//______________________________________________________________________________ -TMapFile *TMapFile::Create(const char *name, Option_t *option, Int_t size, - const char *title) -{ - // Create a memory mapped file. This opens a file (to which the - // memory will be mapped) and attaches a memory region to it. - // Option can be either: "NEW", "CREATE", "RECREATE", "UPDATE" - // or "READ" (see TFile). The default open mode is "READ". The size - // argument specifies the maximum size of shared memory file in bytes. - // TMapFile's can only be created via this method. Create() enforces that - // a TMapFile is always on the memory mapped heap (when "NEW", "CREATE" - // or "RECREATE" are used). - - TMapFile *newMapFile; - new TMapFile(name, title, option, size, newMapFile); - - return newMapFile; -} - -//______________________________________________________________________________ -void TMapFile::SetMapAddress(Long_t addr) -{ - // Set preferred map address. Find out preferred map address as follows: - // 1) Run consumer program to find the preferred map address: - // $ root - // root [0] m = TMapFile::Create("dummy.map", "recreate", 10000000); - // root [1] m.Print() - // Memory mapped file: dummy.map - // Title: - // Option: CREATE - // Mapped Memory region: 0x40b4c000 - 0x40d95f00 (2.29 MB) - // Current breakval: 0x40b53000 - // root [2] .q - // $ rm dummy.map - // Remember begin of mapped region, i.e. 0x40b4c000 - // - // 2) Add to producer program, just before creating the TMapFile: - // TMapFile::SetMapAddress(0x40b4c000); - // - // Repeat this if more than one map file is being used. - // - // The above procedure allow programs using, e.g., different number of - // shared libraries (that cause the default mapping address to be - // different) to create shared memory regions in the same location - // without overwriting a shared library. The above assumes the consumer - // program is larger (i.e. has more shared memory occupied) than the - // producer. If this is not true inverse the procedure. - - fgMapAddress = addr; -} - -//______________________________________________________________________________ -void *TMapFile::MapToAddress() -{ - // Return the base address at which we would like the next TMapFile's - // mapped data to start. - // - // For now, we let the system decide (start address 0). There are - // a lot of issues to deal with here to make this work reasonably, - // including: - // - // - Avoid memory collisions with existing mapped address spaces - // - // - Reclaim address spaces when their mmalloc heaps are unmapped - // - // - When mmalloc heaps are shared between processes they have to be - // mapped at the same addresses in each - // - // Once created, a mmalloc heap that is to be mapped back in must be - // mapped at the original address. I.E. each TMapFile will expect - // to be remapped at it's original address. This becomes a problem if - // the desired address is already in use. - -#ifdef R__HAVE_MMAP - if (TStorage::HasCustomNewDelete()) - return (void *)fgMapAddress; - else - return (void *)-1; -#else - return (void *)-1; -#endif -} - -//______________________________________________________________________________ -void TMapFile::operator delete(void *ptr) -{ - // Need special "operator delete" in which we close the shared memory. - // This has to be done after the dtor chain has been finished. - - mmalloc_detach(fgMmallocDesc); - fgMmallocDesc = 0; - - TObject::operator delete(ptr); -} diff --git a/base/src/TZIPFile.cxx b/base/src/TZIPFile.cxx deleted file mode 100644 index 9cb8e0ef494c352ca23b3f9dd08d205a2d4421d1..0000000000000000000000000000000000000000 --- a/base/src/TZIPFile.cxx +++ /dev/null @@ -1,515 +0,0 @@ -// @(#)root/base:$Name: $:$Id: TZIPFile.cxx,v 1.6 2007/01/12 10:20:08 brun Exp $ -// Author: Fons Rademakers and Lassi Tuura 30/6/04 - -/************************************************************************* - * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// // -// TZIPFile // -// // -// This class describes a ZIP archive file containing multiple // -// sub-files. Typically the sub-files are ROOT files. Notice that // -// the ROOT files should not be compressed when being added to the // -// ZIP file, since ROOT files are normally already compressed. // -// Such a ZIP file should be created like: // -// // -// zip -n root multi file1.root file2.root // -// // -// which creates a ZIP file multi.zip. // -// // -// A ZIP archive consists of files compressed with the popular ZLIB // -// compression algorithm. The archive format is used among others by // -// PKZip and Info-ZIP. The compression algorithm is also used by // -// GZIP and the PNG graphics standard. The format of the archives is // -// explained briefly below. This class provides an interface to read // -// such archives. // -// // -// A ZIP archive contains a prefix, series of archive members // -// (sub-files), and a central directory. In theory the archive could // -// span multiple disks (or files) with the central directory of the // -// whole archive on the last disk, but this class does not support // -// such multi-part archives. The prefix is only used in self-extracting // -// executable archive files. // -// // -// The members are stored in the archive sequentially, each with a // -// local header followed by the (optionally) compressed data; the local // -// header describes the member, including its file name and compressed // -// and real sizes. The central directory includes the member details // -// again, plus allows an extra member comment to be added. The last // -// member in the central directory is an end marker that can contain // -// a comment for the whole archive. Both the local header and the // -// central directory can also carry extra member-specific data; the // -// data in the local and global parts can be different. // -// The fact that the archive has a global directory makes it efficient // -// and allows for only the reading of the desired data, one does not // -// have to scan through the whole file to find the desired sub-file. // -// // -// Once the archive has been opened, the client can query the members // -// and read their contents by asking the archive for an offset where // -// the sub-file starts. The members can be accessed in any order. // -// // -////////////////////////////////////////////////////////////////////////// - -#include "TZIPFile.h" -#include "TFile.h" -#include "TObjArray.h" - - -ClassImp(TZIPFile) - -//______________________________________________________________________________ -TZIPFile::TZIPFile() : TArchiveFile() -{ - // Default ctor. - - fDirPos = 0; - fDirSize = 0; - fDirOffset = 0; -} - -//______________________________________________________________________________ -TZIPFile::TZIPFile(const char *archive, const char *member, TFile *file) - : TArchiveFile(archive, member, file) -{ - // Specify the archive name and member name. The member can be a decimal - // number which allows to access the n-th member. - - fDirPos = 0; - fDirSize = 0; - fDirOffset = 0; -} - -//______________________________________________________________________________ -Int_t TZIPFile::OpenArchive() -{ - // Open archive and read end-header and directory. Returns -1 in case - // of error, 0 otherwise. - - if (ReadEndHeader(FindEndHeader()) == -1) - return -1; - return ReadDirectory(); -} - -//______________________________________________________________________________ -Long64_t TZIPFile::FindEndHeader() -{ - // Find the end header of the ZIP archive. Returns 0 in case of error. - - const Int_t kBUFSIZE = 1024; - Long64_t size = fFile->GetSize(); - Long64_t limit = TMath::Min(size, Long64_t(kMAX_VAR_LEN)); - char buf[kBUFSIZE+4]; - - // Note, this works correctly even if the signature straddles read - // boundaries since we always read an overlapped area of four - // bytes on the next read - for (Long64_t offset = 4; offset < limit; ) { - offset = TMath::Min(offset + kBUFSIZE, limit); - - Long64_t pos = size - offset; - Int_t n = TMath::Min(kBUFSIZE+4, Int_t(offset)); - - fFile->Seek(pos); - if (fFile->ReadBuffer(buf, n)) { - Error("FindEndHeader", "error reading %d bytes at %ldd", n, pos); - return 0; - } - - for (Int_t i = n - 4; i > 0; i--) - if (buf[i] == 0x50 && buf[i+1] == 0x4b && - buf[i+2] == 0x05 && buf[i+3] == 0x06) { - return pos + i; - } - } - - Error("FindEndHeader", "did not find end header in %s", fArchiveName.Data()); - - return 0; -} - -//______________________________________________________________________________ -Int_t TZIPFile::ReadEndHeader(Long64_t pos) -{ - // Read the end header of the ZIP archive including the archive comment - // at the current file position. Check that it really was a single-disk - // archive with all the entries as expected. Most importantly, figure - // out where the central directory begins. Returns -1 in case of error, - // 0 otherwise. - - char buf[kEND_HEADER_SIZE]; - - // read and validate first the end header magic - fFile->Seek(pos); - if (fFile->ReadBuffer(buf, kZIP_MAGIC_LEN) || - Get(buf, kZIP_MAGIC_LEN) != kEND_HEADER_MAGIC) { - Error("ReadEndHeader", "wrong end header magic in %s", fArchiveName.Data()); - return -1; - } - - // read rest of the header - if (fFile->ReadBuffer(buf + kZIP_MAGIC_LEN, kEND_HEADER_SIZE - kZIP_MAGIC_LEN)) { - Error("ReadEndHeader", "error reading %d end header bytes from %s", - kEND_HEADER_SIZE - kZIP_MAGIC_LEN, fArchiveName.Data()); - return -1; - } - - UInt_t disk = Get(buf + kEND_DISK_OFF, kEND_DISK_LEN); - UInt_t dirdisk = Get(buf + kEND_DIR_DISK_OFF, kEND_DIR_DISK_LEN); - UInt_t dhdrs = Get(buf + kEND_DISK_HDRS_OFF, kEND_DISK_HDRS_LEN); - UInt_t thdrs = Get(buf + kEND_TOTAL_HDRS_OFF, kEND_TOTAL_HDRS_LEN); - Long64_t diroff = Get(buf + kEND_DIR_OFFSET_OFF, kEND_DIR_OFFSET_LEN); - Long64_t dirsz = Get(buf + kEND_DIR_SIZE_OFF, kEND_DIR_SIZE_LEN); - Int_t commlen = Get(buf + kEND_COMMENTLEN_OFF, kEND_COMMENTLEN_LEN); - - if (disk != 0 || dirdisk != 0 || dhdrs != thdrs || diroff + dirsz != pos) { - Error("ReadEndHeader", "inconsistency in end header data in %s", - fArchiveName.Data()); - return -1; - } - - char *comment = new char[commlen+1]; - if (fFile->ReadBuffer(comment, commlen)) { - Error("ReadEndHeader", "error reading %d end header comment bytes from %s", - commlen, fArchiveName.Data()); - return -1; - } - comment[commlen] = '\0'; - - fComment = comment; - fDirOffset = fDirPos = diroff; - fDirSize = dirsz; - - delete [] comment; - - return 0; -} - -//______________________________________________________________________________ -Int_t TZIPFile::ReadDirectory() -{ - // Read the directory of the ZIP archive. Returns -1 in case of error, - // 0 otherwise. - - char buf[kDIR_HEADER_SIZE]; - UInt_t n, i; - - // read and validate first the header magic - fFile->Seek(fDirPos); - if (fFile->ReadBuffer(buf, kZIP_MAGIC_LEN) || - (n = Get(buf, kZIP_MAGIC_LEN)) != kDIR_HEADER_MAGIC) { - Error("ReadDirectory", "wrong directory header magic in %s", - fArchiveName.Data()); - return -1; - } - - // now read the full directory - for (i = 0; n == kDIR_HEADER_MAGIC; i++) { - // read the rest of the header - if (fFile->ReadBuffer(buf + kZIP_MAGIC_LEN, kDIR_HEADER_SIZE - kZIP_MAGIC_LEN)) { - Error("ReadDirectory", "error reading %d directory bytes from %s", - kDIR_HEADER_SIZE - kZIP_MAGIC_LEN, fArchiveName.Data()); - return -1; - } - - UInt_t version = Get(buf + kDIR_VREQD_OFF, kDIR_VREQD_LEN); - UInt_t flags = Get(buf + kDIR_FLAG_OFF, kDIR_FLAG_LEN); - UInt_t method = Get(buf + kDIR_METHOD_OFF, kDIR_METHOD_LEN); - UInt_t time = Get(buf + kDIR_DATE_OFF, kDIR_DATE_LEN); - UInt_t crc32 = Get(buf + kDIR_CRC32_OFF, kDIR_CRC32_LEN); - Long64_t csize = Get(buf + kDIR_CSIZE_OFF, kDIR_CSIZE_LEN); - Long64_t usize = Get(buf + kDIR_USIZE_OFF, kDIR_USIZE_LEN); - Int_t namelen = Get(buf + kDIR_NAMELEN_OFF, kDIR_NAMELEN_LEN); - Int_t extlen = Get(buf + kDIR_EXTRALEN_OFF, kDIR_EXTRALEN_LEN); - Int_t commlen = Get(buf + kDIR_COMMENTLEN_OFF, kDIR_COMMENTLEN_LEN); - UInt_t disk = Get(buf + kDIR_DISK_START_OFF, kDIR_DISK_START_LEN); - UInt_t iattr = Get(buf + kDIR_INT_ATTR_OFF, kDIR_INT_ATTR_LEN); - UInt_t xattr = Get(buf + kDIR_EXT_ATTR_OFF, kDIR_EXT_ATTR_LEN); - Long64_t offset = Get(buf + kDIR_ENTRY_POS_OFF, kDIR_ENTRY_POS_LEN); - - // check value sanity and the variable-length fields - if (Get(buf + kDIR_MAGIC_OFF, kZIP_MAGIC_LEN) != kDIR_HEADER_MAGIC || - version > kARCHIVE_VERSION || - flags & 8 || - (method != kSTORED && method != kDEFLATED) || - disk != 0 || - csize < 0 || - usize < 0 || - csize > kMaxInt || - usize > kMaxInt) { - Error("ReadDirectory", "inconsistency in directory data in %s", - fArchiveName.Data()); - return -1; - } - - char *name = new char[namelen+1]; - char *extra = new char[extlen+1]; - char *comment = new char[commlen+1]; - if (fFile->ReadBuffer(name, namelen) || - fFile->ReadBuffer(extra, extlen) || - fFile->ReadBuffer(comment, commlen)) { - Error("ReadDirectory", "error reading additional directory data from %s", - fArchiveName.Data()); - return -1; - } - name[namelen] = '\0'; - extra[extlen] = '\0'; - comment[commlen] = '\0'; - - // create a new archive member and store the fields - TZIPMember *m = new TZIPMember(name); - fMembers->Add(m); - - m->fMethod = method; - m->fLevel = method == kSTORED ? 0 - : (flags & 6)/2 == 0 ? 3 // default (:N) - : (flags & 6)/2 == 1 ? 9 // best (:X) - : (flags & 6)/2 == 2 ? 2 // fast (:F) - : (flags & 6)/2 == 3 ? 1 // fastest (:F) - : 3; // unreached - m->fCsize = csize; - m->fDsize = usize; - m->fCRC32 = crc32; - m->fModTime.Set(time, kTRUE); // DOS date/time format - m->fGlobalLen = extlen; - m->fGlobal = extra; - m->fComment = comment; - m->fAttrInt = iattr; - m->fAttrExt = xattr; - m->fPosition = offset; - - delete [] name; - delete [] comment; - // extra is adopted be the TZIPMember - - if (gDebug) - Info("ReadDirectory", "%lld %lld %s %s", - m->GetDecompressedSize(), m->GetCompressedSize(), - m->GetModTime().AsSQLString(), m->GetName()); - - // done, read the next magic - if (fFile->ReadBuffer(buf, kZIP_MAGIC_LEN)) { - Error("ReadDirectory", "error reading %d directory bytes from %s", - kZIP_MAGIC_LEN, fArchiveName.Data()); - return -1; - } - n = Get(buf, kZIP_MAGIC_LEN); - } - - // should now see end of archive - if (n != kEND_HEADER_MAGIC) { - Error("ReadDirectory", "wrong end header magic in %s", fArchiveName.Data()); - return -1; - } - - return 0; -} - -//______________________________________________________________________________ -Int_t TZIPFile::ReadMemberHeader(TZIPMember *member) -{ - // Read the member header of the ZIP archive. Sets the position where - // the data starts in the member object. Returns -1 in case of error, - // 0 otherwise. - - // read file header to find start of data, since extra len might be - // different we cannot take it from the directory data - char buf[kENTRY_HEADER_SIZE]; - - // read and validate first the entry header magic - fFile->Seek(member->fPosition); - if (fFile->ReadBuffer(buf, kZIP_MAGIC_LEN) || - Get(buf, kZIP_MAGIC_LEN) != kENTRY_HEADER_MAGIC) { - Error("ReadMemberHeader", "wrong entry header magic in %s", - fArchiveName.Data()); - return -1; - } - - // read rest of the header - if (fFile->ReadBuffer(buf + kZIP_MAGIC_LEN, kENTRY_HEADER_SIZE - kZIP_MAGIC_LEN)) { - Error("ReadMemberHeader", "error reading %d member header bytes from %s", - kENTRY_HEADER_SIZE - kZIP_MAGIC_LEN, fArchiveName.Data()); - return -1; - } - Int_t namelen = Get(buf + kENTRY_NAMELEN_OFF, kENTRY_NAMELEN_LEN); - Int_t extlen = Get(buf + kENTRY_EXTRALEN_OFF, kENTRY_EXTRALEN_LEN); - - member->fFilePosition = member->fPosition + kENTRY_HEADER_SIZE + - namelen + extlen; - - return 0; -} - -//______________________________________________________________________________ -Int_t TZIPFile::SetCurrentMember() -{ - // Find the desired member in the member array and make it the - // current member. Returns -1 in case member is not found, 0 otherwise. - - fCurMember = 0; - - if (fMemberIndex > -1) { - fCurMember = (TZIPMember *) fMembers->At(fMemberIndex); - if (!fCurMember) - return -1; - fMemberName = fCurMember->GetName(); - } else { - for (int i = 0; i < fMembers->GetEntriesFast(); i++) { - TZIPMember *m = (TZIPMember *) fMembers->At(i); - if (fMemberName == m->fName) { - fCurMember = m; - fMemberIndex = i; - break; - } - } - if (!fCurMember) - return -1; - } - - return ReadMemberHeader((TZIPMember *)fCurMember); -} - -//______________________________________________________________________________ -UInt_t TZIPFile::Get(const void *buffer, Int_t bytes) -{ - // Read a "bytes" long little-endian integer value from "buffer". - - UInt_t value = 0; -#ifdef R__BYTESWAP - memcpy(&value, buffer, bytes); -#else - const UChar_t *buf = static_cast<const unsigned char *>(buffer); - for (UInt_t shift = 0; bytes; shift += 8, --bytes, ++buf) - value += *buf << shift; -#endif - return value; -} - -//______________________________________________________________________________ -void TZIPFile::Print(Option_t *) const -{ - // Pretty print ZIP archive members. - - if (fMembers) - fMembers->Print(); -} - - -ClassImp(TZIPMember) - -//______________________________________________________________________________ -TZIPMember::TZIPMember() -{ - // Default ctor. - - fLocal = 0; - fLocalLen = 0; - fGlobal = 0; - fGlobalLen = 0; - fCRC32 = 0; - fAttrInt = 0; - fAttrExt = 0; - fMethod = 0; - fLevel = 0; -} - -//______________________________________________________________________________ -TZIPMember::TZIPMember(const char *name) - : TArchiveMember(name) -{ - // Create ZIP member file. - - fLocal = 0; - fLocalLen = 0; - fGlobal = 0; - fGlobalLen = 0; - fCRC32 = 0; - fAttrInt = 0; - fAttrExt = 0; - fMethod = 0; - fLevel = 0; -} - -//______________________________________________________________________________ -TZIPMember::TZIPMember(const TZIPMember &member) - : TArchiveMember(member) -{ - // Copy ctor. - - fLocal = 0; - fLocalLen = member.fLocalLen; - fGlobal = 0; - fGlobalLen = member.fGlobalLen; - fCRC32 = member.fCRC32; - fAttrInt = member.fAttrInt; - fAttrExt = member.fAttrExt; - fMethod = member.fMethod; - fLevel = member.fLevel; - - if (member.fLocal) { - fLocal = new char [fLocalLen]; - memcpy(fLocal, member.fLocal, fLocalLen); - } - if (member.fGlobal) { - fGlobal = new char [fGlobalLen]; - memcpy(fGlobal, member.fGlobal, fGlobalLen); - } -} - -//______________________________________________________________________________ -TZIPMember &TZIPMember::operator=(const TZIPMember &rhs) -{ - // Assignment operator. - - if (this != &rhs) { - TArchiveMember::operator=(rhs); - - delete [] (char*) fLocal; - delete [] (char*) fGlobal; - - fLocal = 0; - fLocalLen = rhs.fLocalLen; - fGlobal = 0; - fGlobalLen = rhs.fGlobalLen; - fCRC32 = rhs.fCRC32; - fAttrInt = rhs.fAttrInt; - fAttrExt = rhs.fAttrExt; - fMethod = rhs.fMethod; - fLevel = rhs.fLevel; - - if (rhs.fLocal) { - fLocal = new char [fLocalLen]; - memcpy(fLocal, rhs.fLocal, fLocalLen); - } - if (rhs.fGlobal) { - fGlobal = new char [fGlobalLen]; - memcpy(fGlobal, rhs.fGlobal, fGlobalLen); - } - } - return *this; -} - -//______________________________________________________________________________ -TZIPMember::~TZIPMember() -{ - // Cleanup. - - delete [] (char*) fLocal; - delete [] (char*) fGlobal; -} - -//______________________________________________________________________________ -void TZIPMember::Print(Option_t *) const -{ - // Pretty print basic ZIP member info. - - //printf("%-20lld %s %s\n", fDsize, fModTime.AsSQLString(), fName.Data()); - // above statement does not work with VC++7.1, spurious (null) - printf("%-20lld", fDsize); - printf(" %s %s\n", fModTime.AsSQLString(), fName.Data()); -} diff --git a/cont/src/TCollectionProxyFactory.cxx b/cont/src/TCollectionProxyFactory.cxx deleted file mode 100644 index 58946df820b06ac3e3351b2a93378052d3ee4d7d..0000000000000000000000000000000000000000 --- a/cont/src/TCollectionProxyFactory.cxx +++ /dev/null @@ -1,182 +0,0 @@ -// @(#)root/cont:$Name: $:$Id: TCollectionProxyFactory.cxx,v 1.1 2007/02/07 08:52:24 brun Exp $ -// Author: Markus Frank 28/10/04 - -/************************************************************************* - * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// // -// TGenCollectionProxy -// -// Proxy around an arbitrary container, which implements basic -// functionality and iteration. The purpose of this implementation -// is to shield any generated dictionary implementation from the -// underlying streamer/proxy implementation and only expose -// the creation fucntions. -// -// In particular this is used to implement splitting and abstract -// element access of any container. Access to compiled code is necessary -// to implement the abstract iteration sequence and functionality like -// size(), clear(), resize(). resize() may be a void operation. -// -////////////////////////////////////////////////////////////////////////// - -#include "TError.h" -#include "TClassEdit.h" -#include "TCollectionProxyFactory.h" -#include "TGenCollectionProxy.h" -#include "TGenCollectionStreamer.h" - -#include "TEmulatedMapProxy.h" -#include "TEmulatedCollectionProxy.h" - -// Do not clutter global namespace with shit.... -namespace { - static TClassEdit::ESTLType stl_type(const std::string& class_name) { - // return the STL type. - int nested = 0; - std::vector<std::string> inside; - int num = TClassEdit::GetSplit(class_name.c_str(),inside,nested); - if ( num > 1 ) { - return (TClassEdit::ESTLType)TClassEdit::STLKind(inside[0].c_str()); - } - return TClassEdit::kNotSTL; - } - - static TEmulatedCollectionProxy* GenEmulation(const char* class_name) { - // Generate an emulated collection proxy. - - if ( class_name ) { - std::string cl = class_name; - if ( cl.find("stdext::hash_") != std::string::npos ) - cl.replace(3,10,"::"); - if ( cl.find("__gnu_cxx::hash_") != std::string::npos ) - cl.replace(0,16,"std::"); - switch ( stl_type(cl) ) { - case TClassEdit::kNotSTL: - return 0; - case TClassEdit::kMap: - case TClassEdit::kMultiMap: - return new TEmulatedMapProxy(class_name); - default: - return new TEmulatedCollectionProxy(class_name); - } - } - return 0; - } -} - -TVirtualCollectionProxy* -TCollectionProxyFactory::GenEmulatedProxy(const char* class_name) -{ - // Generate emulated collection proxy for a given class. - - return GenEmulation(class_name); -} - -TClassStreamer* -TCollectionProxyFactory::GenEmulatedClassStreamer(const char* class_name) -{ - // Generate emulated class streamer for a given collection class. - - TCollectionClassStreamer* s = new TCollectionClassStreamer(); - s->AdoptStreamer(GenEmulation(class_name)); - return s; -} - -TMemberStreamer* -TCollectionProxyFactory::GenEmulatedMemberStreamer(const char* class_name) -{ - // Generate emulated member streamer for a given collection class. - - TCollectionMemberStreamer* s = new TCollectionMemberStreamer(); - s->AdoptStreamer(GenEmulation(class_name)); - return s; -} - -TCollectionProxyFactory::Proxy_t* -TCollectionProxyFactory::GenExplicitProxy( const ::ROOT::TCollectionProxyInfo &info, TClass *cl) -{ - // Generate proxy from static functions. - return new TGenCollectionProxy(info,cl); -} - -TGenCollectionStreamer* -TCollectionProxyFactory::GenExplicitStreamer( const ::ROOT::TCollectionProxyInfo &info, TClass *cl ) -{ - // Generate streamer from static functions. - TGenCollectionStreamer* ptr = new TGenCollectionStreamer(info,cl); - return ptr; -} - -TClassStreamer* -TCollectionProxyFactory::GenExplicitClassStreamer( const ::ROOT::TCollectionProxyInfo &info, TClass *cl ) -{ - // Generate class streamer from static functions. - TCollectionClassStreamer* s = new TCollectionClassStreamer(); - s->AdoptStreamer(GenExplicitStreamer(info,cl)); - return s; -} - -TMemberStreamer* -TCollectionProxyFactory::GenExplicitMemberStreamer( const ::ROOT::TCollectionProxyInfo &info, TClass *cl) -{ - // Generate member streamer from static functions. - TCollectionMemberStreamer* s = new TCollectionMemberStreamer(); - s->AdoptStreamer(GenExplicitStreamer(info,cl)); - return s; -} - -void TCollectionStreamer::InvalidProxyError() { - // Issue Error about invalid proxy. - Fatal("TCollectionStreamer>","No proxy available. Data streaming impossible."); -} - -TCollectionStreamer::TCollectionStreamer() : fStreamer(0) -{ - // Initializing constructor. -} - -TCollectionStreamer::TCollectionStreamer(const TCollectionStreamer& c) -{ - // Copy constructor. - if ( c.fStreamer ) { - fStreamer = dynamic_cast<TGenCollectionProxy*>(c.fStreamer->Generate()); - R__ASSERT(fStreamer != 0); - return; - } - InvalidProxyError(); -} - -TCollectionStreamer::~TCollectionStreamer() -{ - // Standard destructor. - if ( fStreamer ) { - delete fStreamer; - } -} - -void TCollectionStreamer::AdoptStreamer(TGenCollectionProxy* streamer) -{ - // Attach worker proxy. - if ( fStreamer ) { - delete fStreamer; - } - fStreamer = streamer; -} - -void TCollectionStreamer::Streamer(TBuffer &buff, void *pObj, int /* siz */ ) -{ - // Streamer for I/O handling. - if ( fStreamer ) { - TVirtualCollectionProxy::TPushPop env(fStreamer, pObj); - fStreamer->Streamer(buff); - return; - } - InvalidProxyError(); -} diff --git a/cont/src/TContainerConverters.cxx b/cont/src/TContainerConverters.cxx deleted file mode 100644 index f32b7382623fbd27cf4eefa2beddc9e442be9c14..0000000000000000000000000000000000000000 --- a/cont/src/TContainerConverters.cxx +++ /dev/null @@ -1,207 +0,0 @@ -// @(#)root/cony:$Name: $:$Id: TContainerConverters.cxx,v 1.8 2007/01/29 15:53:35 brun Exp $ -// Author: Philippe Canal 11/11/2004 - -/************************************************************************* - * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// // -// Helper classes to convert collection from ROOT collection to STL // -// collections // -// // -////////////////////////////////////////////////////////////////////////// - -#include "TContainerConverters.h" -#include "TClonesArray.h" -#include "TStreamerInfo.h" -#include "TVirtualCollectionProxy.h" -#include "TError.h" - -namespace { - const Int_t kMapOffset = 2; -} - -//________________________________________________________________________ -TConvertClonesArrayToProxy::TConvertClonesArrayToProxy( - TVirtualCollectionProxy *proxy, - Bool_t isPointer, Bool_t isPrealloc) : - fIsPointer(isPointer), - fIsPrealloc(isPrealloc), - fProxy(proxy?proxy->Generate():0) -{ - // Constructor. - - if (isPointer) fOffset = sizeof(TClonesArray*); - else fOffset = sizeof(TClonesArray*); -} - -void TConvertClonesArrayToProxy::operator()(TBuffer &b, void *pmember, Int_t size) -{ - // Read a TClonesArray in the TBuffer b and load it into a (stl) collection - - TStreamerInfo *subinfo = (TStreamerInfo*)fProxy->GetValueClass()->GetStreamerInfo(); - R__ASSERT(subinfo); - - Int_t nobjects, dummy; - char nch; - TString s; - char classv[256]; - void *env; - UInt_t start, bytecount; - - R__ASSERT(b.IsReading()); - - Bool_t needAlloc = fIsPointer && !fIsPrealloc; - - if (needAlloc) { - char *addr = (char*)pmember; - for(Int_t k=0; k<size; ++k, addr += fOffset ) { - if (*(void**)addr && TStreamerInfo::CanDelete()) { - fProxy->GetValueClass()->Destructor(*(void**)addr,kFALSE); // call delete and desctructor - } - //*(void**)addr = fProxy->New(); - //TClonesArray *clones = (TClonesArray*)ReadObjectAny(TClonesArray::Class()); - } - } - - char *addr = (char*)pmember; - if (size==0) size=1; - for(Int_t k=0; k<size; ++k, addr += fOffset ) { - - if (needAlloc) { - // Read the class name. - - // make sure fMap is initialized - b.InitMap(); - - // before reading object save start position - UInt_t startpos = b.Length(); - - // attempt to load next object as TClass clCast - UInt_t tag; // either tag or byte count - TClass *clRef = b.ReadClass(TClonesArray::Class(), &tag); - - if (clRef==0) { - // got a reference to an already read object - // got a reference to an already read object - if (b.GetBufferVersion() > 0) { - tag += b.GetBufferDisplacement(); - } else { - if (tag > (UInt_t)b.GetMapCount()) { - Error("TConvertClonesArrayToProxy", "object tag too large, I/O buffer corrupted"); - return; - } - } - void *objptr; - b.GetMappedObject( tag, objptr, clRef); - if ( objptr == (void*)-1 ) { - Error("TConvertClonesArrayToProxy", - "Object can not be found in the buffer's map (at %d)",tag); - continue; - } - if ( objptr == 0 ) { - if (b.GetBufferVersion()==0) continue; - - // No object found at this location in map. It might have been skipped - // as part of a skipped object. Try to explicitely read the object. - b.MapObject(*(void**)addr, fProxy->GetCollectionClass(), 0); - Int_t currentpos = b.Length(); - b.SetBufferOffset( tag - kMapOffset ); - - (*this)(b,&objptr,1); - b.SetBufferOffset( currentpos); - - if (objptr==0) continue; - - clRef = fProxy->GetCollectionClass(); - - } - R__ASSERT(clRef); - if (clRef==TClonesArray::Class()) { - Error("TConvertClonesArrayToProxy", - "Object refered to has not been converted from TClonesArray to %s", - fProxy->GetCollectionClass()->GetName()); - continue; - } else if (clRef!=fProxy->GetCollectionClass()) { - Error("TConvertClonesArrayToProxy", - "Object refered to is of type %s instead of %s", - clRef->GetName(),fProxy->GetCollectionClass()->GetName()); - continue; - } - *(void**)addr = objptr; - continue; - - } else if (clRef != TClonesArray::Class()) { - Warning("TConvertClonesArrayToProxy", - "Only the TClonesArray part of %s will be read into %s!\n", - (clRef!=((TClass*)-1)&&clRef) ? clRef->GetName() : "N/A", - fProxy->GetCollectionClass()->GetName()); - } else { - *(void**)addr = fProxy->New(); - if (b.GetBufferVersion()>0) { - b.MapObject(*(void**)addr, fProxy->GetCollectionClass(), startpos+kMapOffset); - } else { - b.MapObject(*(void**)addr, fProxy->GetCollectionClass(), b.GetMapCount() ); - } - } - } - void *obj; - if (fIsPointer) obj = *(void**)addr; - else obj = addr; - - TObject objdummy; - Version_t v = b.ReadVersion(&start, &bytecount); - - //if (v == 3) { - // const int_t koldbypassstreamer = bit(14); - // if (testbit(koldbypassstreamer)) bypassstreamer(); - //} - if (v > 2) objdummy.Streamer(b); - TString fName; - if (v > 1) fName.Streamer(b); - s.Streamer(b); - strncpy(classv,s.Data(),255); - Int_t clv = 0; - char *semicolon = strchr(classv,';'); - if (semicolon) { - *semicolon = 0; - clv = atoi(semicolon+1); - } - TClass *cl = TClass::GetClass(classv); - if (!cl) { - printf("TClonesArray::Streamer expecting class %s\n", classv); - b.CheckByteCount(start, bytecount, TClonesArray::Class()); - return; - } - - b >> nobjects; - if (nobjects < 0) nobjects = -nobjects; // still there for backward compatibility - b >> dummy; // fLowerBound is ignored - if (cl != subinfo->GetClass()) { - Error("TClonesArray::Conversion to vector","Bad class"); - } - TVirtualCollectionProxy::TPushPop helper( fProxy, obj ); - env = fProxy->Allocate(nobjects,true); - - if (objdummy.TestBit(TClonesArray::kBypassStreamer)) { - - subinfo->ReadBufferSTL(b,fProxy,nobjects,-1,0); - - } else { - for (Int_t i = 0; i < nobjects; i++) { - b >> nch; - if (nch) { - void* elem = fProxy->At(i); - b.StreamObject(elem,subinfo->GetClass()); - } - } - } - fProxy->Commit(env); - b.CheckByteCount(start, bytecount,TClonesArray::Class()); - } -} diff --git a/cont/src/TEmulatedCollectionProxy.cxx b/cont/src/TEmulatedCollectionProxy.cxx deleted file mode 100644 index ad37b7eca6aadfb8352dd292d1230963a6ef5f7f..0000000000000000000000000000000000000000 --- a/cont/src/TEmulatedCollectionProxy.cxx +++ /dev/null @@ -1,624 +0,0 @@ -// @(#)root/cont:$Name: $:$Id: TEmulatedCollectionProxy.cxx,v 1.25 2007/01/29 15:53:35 brun Exp $ -// Author: Markus Frank 28/10/04 - -/************************************************************************* - * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// // -// TEmulatedCollectionProxy -// -// Streamer around an arbitrary container, which implements basic -// functionality and iteration. -// -// In particular this is used to implement splitting and abstract -// element access of any container. Access to compiled code is necessary -// to implement the abstract iteration sequence and functionality like -// size(), clear(), resize(). resize() may be a void operation. -// -////////////////////////////////////////////////////////////////////////// - -#include "TEmulatedCollectionProxy.h" -#include "TStreamerElement.h" -#include "TStreamerInfo.h" -#include "TClassEdit.h" -#include "TError.h" -#include "TROOT.h" -#include "Riostream.h" - -#include "TVirtualMutex.h" // For R__LOCKGUARD - -// -// Utility function to allow the creation of a TClass for a std::pair without -// a dictionary (See end of file for implementation -// - -static TStreamerElement* R__CreateEmulatedElement(const char *dmName, const char *dmFull, Int_t offset); -static TStreamerInfo *R__GenerateTClassForPair(const string &f, const string &s); - -TEmulatedCollectionProxy::TEmulatedCollectionProxy(const TEmulatedCollectionProxy& copy) - : TGenCollectionProxy(copy) -{ - // Build a Streamer for an emulated vector whose type is 'name'. -} - -TEmulatedCollectionProxy::TEmulatedCollectionProxy(const char* cl_name) - : TGenCollectionProxy(typeid(std::vector<char>), sizeof(std::vector<char>::iterator)) -{ - // Build a Streamer for a collection whose type is described by 'collectionClass'. - - fName = cl_name; - this->TEmulatedCollectionProxy::InitializeEx(); -} - -TEmulatedCollectionProxy::~TEmulatedCollectionProxy() -{ - // Standard destructor - if ( fEnv && fEnv->object ) { - Clear(); - } -} - -TVirtualCollectionProxy* TEmulatedCollectionProxy::Generate() const -{ - // Virtual copy constructor - - if ( !fClass ) Initialize(); - return new TEmulatedCollectionProxy(*this); -} - -void TEmulatedCollectionProxy::Destructor(void* p, Bool_t dtorOnly) -{ - // Virtual destructor - - if (!p) return; - TVirtualCollectionProxy::TPushPop env(this, p); - Clear(); - if (!dtorOnly) { - delete (Cont_t*) p; - } -} - -void TEmulatedCollectionProxy::DeleteArray(void* p, Bool_t dtorOnly) -{ - // Virtual array destructor - - // Cannot implement this properly, we do not know - // how many elements are in the array. - Warning("DeleteArray", "Cannot properly delete emulated array of %s at %p, I don't know how many elements it has!", fClass->GetName(), p); - if (!dtorOnly) { - delete[] (Cont_t*) p; - } -} - -TGenCollectionProxy *TEmulatedCollectionProxy::InitializeEx() -{ - // Proxy initializer - R__LOCKGUARD2(gCollectionMutex); - if (fClass) return this; - - - TClass *cl = TClass::GetClass(fName.c_str()); - fEnv = 0; - fKey = 0; - if ( cl ) { - int nested = 0; - std::vector<std::string> inside; - fPointers = false; - int num = TClassEdit::GetSplit(fName.c_str(),inside,nested); - if ( num > 1 ) { - std::string nam; - if ( inside[0].find("stdext::hash_") != std::string::npos ) { - inside[0].replace(3,10,"::"); - } - if ( inside[0].find("__gnu_cxx::hash_") != std::string::npos ) { - inside[0].replace(0,16,"std::"); - } - fSTL_type = TClassEdit::STLKind(inside[0].c_str()); - // std::cout << "Initialized " << typeid(*this).name() << ":" << fName << std::endl; - int slong = sizeof(void*); - switch ( fSTL_type ) { - case TClassEdit::kMap: - case TClassEdit::kMultiMap: - nam = "pair<"+inside[1]+","+inside[2]; - nam += (nam[nam.length()-1]=='>') ? " >" : ">"; - if (0==TClass::GetClass(nam.c_str())) { - // We need to emulate the pair - R__GenerateTClassForPair(inside[1],inside[2]); - } - fValue = new Value(nam); - fKey = new Value(inside[1]); - fVal = new Value(inside[2]); - fPointers |= 0 != (fKey->fCase&G__BIT_ISPOINTER); - if ( 0 == fValDiff ) { - fValDiff = fKey->fSize + fVal->fSize; - fValDiff += (slong - fKey->fSize%slong)%slong; - fValDiff += (slong - fValDiff%slong)%slong; - } - if ( 0 == fValOffset ) { - fValOffset = fKey->fSize; - fValOffset += (slong - fKey->fSize%slong)%slong; - } - break; - default: - fValue = new Value(inside[1]); - fVal = new Value(*fValue); - if ( 0 == fValDiff ) { - fValDiff = fVal->fSize; - fValDiff += (slong - fValDiff%slong)%slong; - } - break; - } - fPointers |= 0 != (fVal->fCase&G__BIT_ISPOINTER); - fClass = cl; - return this; - } - Fatal("TEmulatedCollectionProxy","Components of %s not analysed!",cl->GetName()); - } - Fatal("TEmulatedCollectionProxy","Collection class %s not found!",fTypeinfo.name()); - return 0; -} - -UInt_t TEmulatedCollectionProxy::Size() const -{ - // Return the current size of the container - - if ( fEnv && fEnv->object ) { - return fEnv->size = PCont_t(fEnv->object)->size()/fValDiff; - } - Fatal("TEmulatedCollectionProxy","Size> Logic error - no proxy object set."); - return 0; -} - -void TEmulatedCollectionProxy::Clear(const char* opt) -{ - // Clear the emulated collection. - Resize(0, opt && *opt=='f'); -} - -void TEmulatedCollectionProxy::Shrink(UInt_t nCurr, UInt_t left, Bool_t /* force */ ) -{ - // Shrink the container - - typedef std::string String_t; - PCont_t c = PCont_t(fEnv->object); - char* addr = ((char*)fEnv->start) + fValDiff*left; - size_t i; - - switch ( fSTL_type ) { - case TClassEdit::kMap: - case TClassEdit::kMultiMap: - addr = ((char*)fEnv->start) + fValDiff*left; - switch(fKey->fCase) { - case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way - case G__BIT_ISENUM: - break; - case G__BIT_ISCLASS: - for( i= fKey->fType ? left : nCurr; i<nCurr; ++i, addr += fValDiff ) { - // Call emulation in case non-compiled content - fKey->fType->Destructor(addr, kTRUE); - } - break; - case kBIT_ISSTRING: - for( i=left; i<nCurr; ++i, addr += fValDiff ) { - ((std::string*)addr)->~String_t(); - } - break; - case G__BIT_ISPOINTER|G__BIT_ISCLASS: - for( i=left; i<nCurr; ++i, addr += fValDiff ) { - StreamHelper* h = (StreamHelper*)addr; - //Eventually we'll need to delete this - //(but only when needed). - //void* ptr = h->ptr(); - //fKey->fType->Destructor(ptr); - h->set(0); - } - case G__BIT_ISPOINTER|kBIT_ISSTRING: - for( i=nCurr; i<left; ++i, addr += fValDiff ) { - StreamHelper* h = (StreamHelper*)addr; - //Eventually we'll need to delete this - //(but only when needed). - //delete (std::string*)h->ptr(); - h->set(0); - } - break; - case G__BIT_ISPOINTER|kBIT_ISTSTRING|G__BIT_ISCLASS: - for( i=nCurr; i<left; ++i, addr += fValDiff ) { - StreamHelper* h = (StreamHelper*)addr; - //delete (TString*)h->ptr(); - h->set(0); - } - break; - } - addr = ((char*)fEnv->start)+fValOffset+fValDiff*left; - // DO NOT break; just continue - - // General case for all values - default: - switch( fVal->fCase ) { - case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way - case G__BIT_ISENUM: - break; - case G__BIT_ISCLASS: - for( i=left; i<nCurr; ++i, addr += fValDiff ) { - // Call emulation in case non-compiled content - fVal->fType->Destructor(addr,kTRUE); - } - break; - case kBIT_ISSTRING: - for( i=left; i<nCurr; ++i, addr += fValDiff ) - ((std::string*)addr)->~String_t(); - break; - case G__BIT_ISPOINTER|G__BIT_ISCLASS: - for( i=left; i<nCurr; ++i, addr += fValDiff ) { - StreamHelper* h = (StreamHelper*)addr; - void* p = h->ptr(); - if ( p ) { - //fVal->fType->Destructor(p); - } - h->set(0); - } - case G__BIT_ISPOINTER|kBIT_ISSTRING: - for( i=nCurr; i<left; ++i, addr += fValDiff ) { - StreamHelper* h = (StreamHelper*)addr; - //delete (std::string*)h->ptr(); - h->set(0); - } - break; - case G__BIT_ISPOINTER|kBIT_ISTSTRING|G__BIT_ISCLASS: - for( i=nCurr; i<left; ++i, addr += fValDiff ) { - StreamHelper* h = (StreamHelper*)addr; - //delete (TString*)h->ptr(); - h->set(0); - } - break; - } - } - c->resize(left*fValDiff,0); - fEnv->start = left>0 ? &(*c->begin()) : 0; - return; -} - -void TEmulatedCollectionProxy::Expand(UInt_t nCurr, UInt_t left) -{ - // Expand the container - size_t i; - PCont_t c = PCont_t(fEnv->object); - c->resize(left*fValDiff,0); - void *oldstart = fEnv->start; - fEnv->start = left>0 ? &(*c->begin()) : 0; - - char* addr = ((char*)fEnv->start) + fValDiff*nCurr; - switch ( fSTL_type ) { - case TClassEdit::kMap: - case TClassEdit::kMultiMap: - switch(fKey->fCase) { - case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way - case G__BIT_ISENUM: - break; - case G__BIT_ISCLASS: - if (oldstart && oldstart != fEnv->start) { - Long_t offset = 0; - for( i=0; i<=nCurr; ++i, offset += fValDiff ) { - // For now 'Move' only register the change of location - // so per se this is wrong since the object are copied via memcpy - // rather than a copy (or move) constructor. - fVal->fType->Move(((char*)oldstart)+offset,((char*)fEnv->start)+offset); - } - } - for( i=nCurr; i<left; ++i, addr += fValDiff ) - fKey->fType->New(addr); - break; - case kBIT_ISSTRING: - for( i=nCurr; i<left; ++i, addr += fValDiff ) - ::new(addr) std::string(); - break; - case G__BIT_ISPOINTER|G__BIT_ISCLASS: - case G__BIT_ISPOINTER|kBIT_ISSTRING: - case G__BIT_ISPOINTER|kBIT_ISTSTRING|G__BIT_ISCLASS: - for( i=nCurr; i<left; ++i, addr += fValDiff ) - *(void**)addr = 0; - break; - } - addr = ((char*)fEnv->start)+fValOffset+fValDiff*nCurr; - // DO NOT break; just continue - - // General case for all values - default: - switch(fVal->fCase) { - case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way - case G__BIT_ISENUM: - break; - case G__BIT_ISCLASS: - if (oldstart && oldstart != fEnv->start) { - Long_t offset = 0; - for( i=0; i<=nCurr; ++i, offset += fValDiff ) { - // For now 'Move' only register the change of location - // so per se this is wrong since the object are copied via memcpy - // rather than a copy (or move) constructor. - fVal->fType->Move(((char*)oldstart)+offset,((char*)fEnv->start)+offset); - } - } - for( i=nCurr; i<left; ++i, addr += fValDiff ) { - fVal->fType->New(addr); - } - break; - case kBIT_ISSTRING: - for( i=nCurr; i<left; ++i, addr += fValDiff ) - ::new(addr) std::string(); - break; - case G__BIT_ISPOINTER|G__BIT_ISCLASS: - case G__BIT_ISPOINTER|kBIT_ISSTRING: - case G__BIT_ISPOINTER|kBIT_ISTSTRING|G__BIT_ISCLASS: - for( i=nCurr; i<left; ++i, addr += fValDiff ) - *(void**)addr = 0; - break; - } - break; - } -} - -void TEmulatedCollectionProxy::Resize(UInt_t left, Bool_t force) -{ - // Resize the container - - if ( fEnv && fEnv->object ) { - size_t nCurr = Size(); - PCont_t c = PCont_t(fEnv->object); - fEnv->start = nCurr>0 ? &(*c->begin()) : 0; - if ( left == nCurr ) { - return; - } - else if ( left < nCurr ) { - Shrink(nCurr, left, force); - return; - } - Expand(nCurr, left); - return; - } - Fatal("TEmulatedCollectionProxy","Resize> Logic error - no proxy object set."); -} - -void* TEmulatedCollectionProxy::At(UInt_t idx) -{ - // Return the address of the value at index 'idx' - if ( fEnv && fEnv->object ) { - PCont_t c = PCont_t(fEnv->object); - size_t s = c->size(); - if ( idx >= (s/fValDiff) ) { - return 0; - } - return idx<(s/fValDiff) ? ((char*)&(*c->begin()))+idx*fValDiff : 0; - } - Fatal("TEmulatedCollectionProxy","At> Logic error - no proxy object set."); - return 0; -} - -void* TEmulatedCollectionProxy::Allocate(UInt_t n, Bool_t forceDelete) -{ - // Allocate the necessary space. - - Resize(n, forceDelete); - return fEnv; -} - -void TEmulatedCollectionProxy::Commit(void* /* env */ ) -{ -} - -void TEmulatedCollectionProxy::ReadItems(int nElements, TBuffer &b) -{ - // Object input streamer - Bool_t vsn3 = b.GetInfo() && b.GetInfo()->GetOldVersion()<=3; - StreamHelper* itm = (StreamHelper*)At(0); - switch (fVal->fCase) { - case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way - case G__BIT_ISENUM: - switch( int(fVal->fKind) ) { - case kBool_t: b.ReadFastArray(&itm->boolean , nElements); break; - case kChar_t: b.ReadFastArray(&itm->s_char , nElements); break; - case kShort_t: b.ReadFastArray(&itm->s_short , nElements); break; - case kInt_t: b.ReadFastArray(&itm->s_int , nElements); break; - case kLong_t: b.ReadFastArray(&itm->s_long , nElements); break; - case kLong64_t: b.ReadFastArray(&itm->s_longlong, nElements); break; - case kFloat_t: b.ReadFastArray(&itm->flt , nElements); break; - case kDouble_t: b.ReadFastArray(&itm->dbl , nElements); break; - case kBOOL_t: b.ReadFastArray(&itm->boolean , nElements); break; - case kUChar_t: b.ReadFastArray(&itm->u_char , nElements); break; - case kUShort_t: b.ReadFastArray(&itm->u_short , nElements); break; - case kUInt_t: b.ReadFastArray(&itm->u_int , nElements); break; - case kULong_t: b.ReadFastArray(&itm->u_long , nElements); break; - case kULong64_t: b.ReadFastArray(&itm->u_longlong, nElements); break; - case kDouble32_t:b.ReadFastArrayDouble32(&itm->dbl,nElements); break; - case kchar: - case kNoType_t: - case kOther_t: - Error("TEmulatedCollectionProxy","fType %d is not supported yet!\n",fVal->fKind); - } - break; - -#define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)(((char*)itm) + fValDiff*idx); { x ;} ++idx;} break;} - - case G__BIT_ISCLASS: - DOLOOP( b.StreamObject(i,fVal->fType) ); - case kBIT_ISSTRING: - DOLOOP( i->read_std_string(b) ); - case G__BIT_ISPOINTER|G__BIT_ISCLASS: - DOLOOP( i->read_any_object(fVal,b) ); - case G__BIT_ISPOINTER|kBIT_ISSTRING: - DOLOOP( i->read_std_string_pointer(b) ); - case G__BIT_ISPOINTER|kBIT_ISTSTRING|G__BIT_ISCLASS: - DOLOOP( i->read_tstring_pointer(vsn3,b) ); - } - -#undef DOLOOP - -} - -void TEmulatedCollectionProxy::WriteItems(int nElements, TBuffer &b) -{ - // Object output streamer - StreamHelper* itm = (StreamHelper*)At(0); - switch (fVal->fCase) { - case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way - case G__BIT_ISENUM: - itm = (StreamHelper*)At(0); - switch( int(fVal->fKind) ) { - case kBool_t: b.WriteFastArray(&itm->boolean , nElements); break; - case kChar_t: b.WriteFastArray(&itm->s_char , nElements); break; - case kShort_t: b.WriteFastArray(&itm->s_short , nElements); break; - case kInt_t: b.WriteFastArray(&itm->s_int , nElements); break; - case kLong_t: b.WriteFastArray(&itm->s_long , nElements); break; - case kLong64_t: b.WriteFastArray(&itm->s_longlong, nElements); break; - case kFloat_t: b.WriteFastArray(&itm->flt , nElements); break; - case kDouble_t: b.WriteFastArray(&itm->dbl , nElements); break; - case kBOOL_t: b.WriteFastArray(&itm->boolean , nElements); break; - case kUChar_t: b.WriteFastArray(&itm->u_char , nElements); break; - case kUShort_t: b.WriteFastArray(&itm->u_short , nElements); break; - case kUInt_t: b.WriteFastArray(&itm->u_int , nElements); break; - case kULong_t: b.WriteFastArray(&itm->u_long , nElements); break; - case kULong64_t: b.WriteFastArray(&itm->u_longlong, nElements); break; - case kDouble32_t:b.WriteFastArrayDouble32(&itm->dbl,nElements); break; - case kchar: - case kNoType_t: - case kOther_t: - Error("TEmulatedCollectionProxy","fType %d is not supported yet!\n",fVal->fKind); - } - break; -#define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)(((char*)itm) + fValDiff*idx); { x ;} ++idx;} break;} - case G__BIT_ISCLASS: - DOLOOP( b.StreamObject(i,fVal->fType) ); - case kBIT_ISSTRING: - DOLOOP( TString(i->c_str()).Streamer(b) ); - case G__BIT_ISPOINTER|G__BIT_ISCLASS: - DOLOOP( b.WriteObjectAny(i->ptr(),fVal->fType) ); - case kBIT_ISSTRING|G__BIT_ISPOINTER: - DOLOOP( i->write_std_string_pointer(b) ); - case kBIT_ISTSTRING|G__BIT_ISCLASS|G__BIT_ISPOINTER: - DOLOOP( i->write_tstring_pointer(b) ); - } -#undef DOLOOP -} - -void TEmulatedCollectionProxy::Streamer(TBuffer &b) -{ - // TClassStreamer IO overload - if ( b.IsReading() ) { //Read mode - int nElements = 0; - b >> nElements; - if ( fEnv->object ) { - Resize(nElements,true); - } - if ( nElements > 0 ) { - ReadItems(nElements, b); - } - } - else { // Write case - int nElements = fEnv->object ? Size() : 0; - b << nElements; - if ( nElements > 0 ) { - WriteItems(nElements, b); - } - } -} - -// -// Utility functions -// -static TStreamerElement* R__CreateEmulatedElement(const char *dmName, const char *dmFull, Int_t offset) -{ - // Create a TStreamerElement for the type 'dmFull' and whose data member name is 'dmName'. - - TString s1( TClassEdit::ShortType(dmFull,0) ); - TString dmType( TClassEdit::ShortType(dmFull,1) ); - bool dmIsPtr = (s1 != dmType); - const char *dmTitle = "Emulation"; - - TDataType *dt = gROOT->GetType(dmType); - if (dt && dt->GetType() > 0 ) { // found a basic type - Int_t dsize,dtype; - dtype = dt->GetType(); - dsize = dt->Size(); - if (dmIsPtr && dtype != kCharStar) { - Error("Pair Emulation Building","%s is not yet supported in pair emulation", - dmFull); - return 0; - } else { - TStreamerElement *el = new TStreamerBasicType(dmName,dmTitle,offset,dtype,dmFull); - el->SetSize(dsize); - return el; - } - } else { - - static const char *full_string_name = "basic_string<char,char_traits<char>,allocator<char> >"; - if (strcmp(dmType,"string") == 0 || strcmp(dmType,full_string_name)==0 ) { - return new TStreamerSTLstring(dmName,dmTitle,offset,dmFull,dmIsPtr); - } - if (TClassEdit::IsSTLCont(dmType)) { - return new TStreamerSTL(dmName,dmTitle,offset,dmFull,dmFull,dmIsPtr); - } - TClass *clm = TClass::GetClass(dmType); - if (!clm) { - // either we have an Emulated enum or a really unknown class! - // let's just claim its an enum :( - Int_t dtype = kInt_t; - return new TStreamerBasicType(dmName,dmTitle,offset,dtype,dmFull); - } - // a pointer to a class - if ( dmIsPtr ) { - if (clm->InheritsFrom(TObject::Class())) { - return new TStreamerObjectPointer(dmName,dmTitle,offset,dmFull); - } else { - return new TStreamerObjectAnyPointer(dmName,dmTitle,offset,dmFull); - } - } - // a class - if (clm->InheritsFrom(TObject::Class())) { - return new TStreamerObject(dmName,dmTitle,offset,dmFull); - } else if(clm == TString::Class() && !dmIsPtr) { - return new TStreamerString(dmName,dmTitle,offset); - } else { - return new TStreamerObjectAny(dmName,dmTitle,offset,dmFull); - } - } -} - - -static TStreamerInfo *R__GenerateTClassForPair(const string &fname, const string &sname) -{ - // Generate a TStreamerInfo for a pair<fname,sname> - // This TStreamerInfo is then used as if it was read from a file to generate - // and emulated TClass. - - TStreamerInfo *i = (TStreamerInfo*)TClass::GetClass("pair<const int,int>")->GetStreamerInfo()->Clone(); - std::string pname = "pair<"+fname+","+sname; - pname += (pname[pname.length()-1]=='>') ? " >" : ">"; - i->SetName(pname.c_str()); - i->SetClass(0); - i->GetElements()->Clear(); - TStreamerElement *fel = R__CreateEmulatedElement("first", fname.c_str(), 0); - i->GetElements()->Add( fel ); - Int_t size = 0; - if (fel) { - size = fel->GetSize(); - Int_t sp = sizeof(void *); -#if defined(R__SGI64) - sp = 8; -#endif - //align the non-basic data types (required on alpha and IRIX!!) - if (size%sp != 0) size = size - size%sp + sp; - } - i->GetElements()->Add( R__CreateEmulatedElement("second", sname.c_str(), size) ); - Int_t oldlevel = gErrorIgnoreLevel; - // Hide the warning about the missing pair dictionary. - gErrorIgnoreLevel = kError; - i->BuildCheck(); - gErrorIgnoreLevel = oldlevel; - i->BuildOld(); - return i; -} diff --git a/cont/src/TEmulatedMapProxy.cxx b/cont/src/TEmulatedMapProxy.cxx deleted file mode 100644 index 0fd0e8b253185134796108df6ed2025cae9a284b..0000000000000000000000000000000000000000 --- a/cont/src/TEmulatedMapProxy.cxx +++ /dev/null @@ -1,224 +0,0 @@ -// @(#)root/cont:$Name: $:$Id: TEmulatedMapProxy.cxx,v 1.10 2007/01/25 11:53:26 brun Exp $ -// Author: Markus Frank 28/10/04 - -/************************************************************************* - * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// // -// TEmulatedMapProxy -// -// Streamer around an arbitrary container, which implements basic -// functionality and iteration. -// -// In particular this is used to implement splitting and abstract -// element access of any container. Access to compiled code is necessary -// to implement the abstract iteration sequence and functionality like -// size(), clear(), resize(). resize() may be a void operation. -// -////////////////////////////////////////////////////////////////////////// - -#include "TEmulatedMapProxy.h" -#include "TClassEdit.h" -#include "TStreamerInfo.h" -#include "TError.h" - -TEmulatedMapProxy::TEmulatedMapProxy(const TEmulatedMapProxy& copy) - : TEmulatedCollectionProxy(copy) -{ - // copy constructor - if ( !(fSTL_type == TClassEdit::kMap || fSTL_type == TClassEdit::kMultiMap) ) { - Fatal("TEmulatedMapProxy","Class %s is not a map-type!",fName.c_str()); - } -} - -TEmulatedMapProxy::TEmulatedMapProxy(const char* cl_name) - : TEmulatedCollectionProxy(cl_name) -{ - // Build a Streamer for an emulated vector whose type is 'name'. - if ( !(fSTL_type == TClassEdit::kMap || fSTL_type == TClassEdit::kMultiMap) ) { - Fatal("TEmulatedMapProxy","Class %s is not a map-type!",fName.c_str()); - } -} - -TEmulatedMapProxy::~TEmulatedMapProxy() -{ - // Standard destructor. -} - -TVirtualCollectionProxy* TEmulatedMapProxy::Generate() const -{ - // Virtual copy constructor. - if ( !fClass ) Initialize(); - return new TEmulatedMapProxy(*this); -} - -void* TEmulatedMapProxy::At(UInt_t idx) -{ - // Return the address of the value at index 'idx'. - if ( fEnv && fEnv->object ) { - PCont_t c = PCont_t(fEnv->object); - return idx<(c->size()/fValDiff) ? ((char*)&(*c->begin())) + idx*fValDiff : 0; - } - Fatal("TEmulatedMapProxy","At> Logic error - no proxy object set."); - return 0; -} - -UInt_t TEmulatedMapProxy::Size() const -{ - // Return the current size of the container. - if ( fEnv && fEnv->object ) { - PCont_t c = PCont_t(fEnv->object); - return fEnv->size = (c->size()/fValDiff); - } - Fatal("TEmulatedMapProxy","Size> Logic error - no proxy object set."); - return 0; -} - -void TEmulatedMapProxy::ReadMap(int nElements, TBuffer &b) -{ - // Map input streamer. - Bool_t vsn3 = b.GetInfo() && b.GetInfo()->GetOldVersion()<=3; - int idx, loop, off[2] = {0, fValOffset }; - Value *v, *val[2] = { fKey, fVal }; - StreamHelper* helper; - float f; - char* addr = 0; - char* temp = (char*)At(0); - for ( idx = 0; idx < nElements; ++idx ) { - addr = temp + idx*fValDiff; - for ( loop=0; loop<2; loop++) { - addr += off[loop]; - helper = (StreamHelper*)addr; - v = val[loop]; - switch (v->fCase) { - case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way - case G__BIT_ISENUM: - switch( int(v->fKind) ) { - case kBool_t: b >> helper->boolean; break; - case kChar_t: b >> helper->s_char; break; - case kShort_t: b >> helper->s_short; break; - case kInt_t: b >> helper->s_int; break; - case kLong_t: b >> helper->s_long; break; - case kLong64_t: b >> helper->s_longlong; break; - case kFloat_t: b >> helper->flt; break; - case kDouble_t: b >> helper->dbl; break; - case kBOOL_t: b >> helper->boolean; break; - case kUChar_t: b >> helper->u_char; break; - case kUShort_t: b >> helper->u_short; break; - case kUInt_t: b >> helper->u_int; break; - case kULong_t: b >> helper->u_long; break; - case kULong64_t: b >> helper->u_longlong; break; - case kDouble32_t:b >> f; - helper->dbl = double(f); break; - case kchar: - case kNoType_t: - case kOther_t: - Error("TEmulatedMapProxy","fType %d is not supported yet!\n",v->fKind); - } - break; - case G__BIT_ISCLASS: - b.StreamObject(helper,v->fType); - break; - case kBIT_ISSTRING: - helper->read_std_string(b); - break; - case G__BIT_ISPOINTER|G__BIT_ISCLASS: - helper->set(b.ReadObjectAny(v->fType)); - break; - case G__BIT_ISPOINTER|kBIT_ISSTRING: - helper->read_std_string_pointer(b); - break; - case G__BIT_ISPOINTER|kBIT_ISTSTRING|G__BIT_ISCLASS: - helper->read_tstring_pointer(vsn3,b); - break; - } - } - } -} - -void TEmulatedMapProxy::WriteMap(int nElements, TBuffer &b) -{ - // Map output streamer. - Value *v, *val[2] = { fKey, fVal }; - int off[2] = { 0, fValOffset }; - StreamHelper* i; - char* addr = 0; - char* temp = (char*)At(0); - for (int loop, idx = 0; idx < nElements; ++idx ) { - addr = temp + idx*fValDiff; - for ( loop = 0; loop<2; ++loop ) { - addr += off[loop]; - i = (StreamHelper*)addr; - v = val[loop]; - switch (v->fCase) { - case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way - case G__BIT_ISENUM: - switch( int(v->fKind) ) { - case kBool_t: b << i->boolean; break; - case kChar_t: b << i->s_char; break; - case kShort_t: b << i->s_short; break; - case kInt_t: b << i->s_int; break; - case kLong_t: b << i->s_long; break; - case kLong64_t: b << i->s_longlong; break; - case kFloat_t: b << i->flt; break; - case kDouble_t: b << i->dbl; break; - case kBOOL_t: b << i->boolean; break; - case kUChar_t: b << i->u_char; break; - case kUShort_t: b << i->u_short; break; - case kUInt_t: b << i->u_int; break; - case kULong_t: b << i->u_long; break; - case kULong64_t: b << i->u_longlong; break; - case kDouble32_t:b << float(i->dbl); break; - case kchar: - case kNoType_t: - case kOther_t: - Error("TEmulatedMapProxy","fType %d is not supported yet!\n",v->fKind); - } - break; - case G__BIT_ISCLASS: - b.StreamObject(i,v->fType); - break; - case kBIT_ISSTRING: - TString(i->c_str()).Streamer(b); - break; - case G__BIT_ISPOINTER|G__BIT_ISCLASS: - b.WriteObjectAny(i->ptr(),v->fType); - break; - case kBIT_ISSTRING|G__BIT_ISPOINTER: - i->write_std_string_pointer(b); - break; - case kBIT_ISTSTRING|G__BIT_ISCLASS|G__BIT_ISPOINTER: - i->write_tstring_pointer(b); - break; - } - } - } -} - -void TEmulatedMapProxy::Streamer(TBuffer &b) -{ - // TClassStreamer IO overload. - if ( b.IsReading() ) { //Read mode - int nElements = 0; - b >> nElements; - if ( fEnv->object ) { - Resize(nElements,true); - } - if ( nElements > 0 ) { - ReadMap(nElements, b); - } - } - else { // Write case - int nElements = fEnv->object ? Size() : 0; - b << nElements; - if ( nElements > 0 ) { - WriteMap(nElements, b); - } - } -} diff --git a/cont/src/TGenCollectionProxy.cxx b/cont/src/TGenCollectionProxy.cxx deleted file mode 100644 index 9210ca6534e48ffd2632ea8578a0fe55174f0b77..0000000000000000000000000000000000000000 --- a/cont/src/TGenCollectionProxy.cxx +++ /dev/null @@ -1,914 +0,0 @@ -// @(#)root/cont:$Name: $:$Id: TGenCollectionProxy.cxx,v 1.30 2007/02/01 22:02:48 pcanal Exp $ -// Author: Markus Frank 28/10/04 - -/************************************************************************* - * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// // -// TGenCollectionProxy -// -// Proxy around an arbitrary container, which implements basic -// functionality and iteration. -// -// In particular this is used to implement splitting and abstract -// element access of any container. Access to compiled code is necessary -// to implement the abstract iteration sequence and functionality like -// size(), clear(), resize(). resize() may be a void operation. -// -////////////////////////////////////////////////////////////////////////// - -#include "TGenCollectionProxy.h" -#include "TStreamerElement.h" -#include "TClassEdit.h" -#include "Property.h" -#include "TClass.h" -#include "TError.h" -#include "TROOT.h" -#include "Api.h" -#include "Riostream.h" -#include "TVirtualMutex.h" - -#define MESSAGE(which,text) - -////////////////////////////////////////////////////////////////////////// -// // -// class TGenVectorProxy -// -// Local optimization class. -// -// Collection proxies get copied. On copy we switch the type of the -// proxy to the concrete STL type. The concrete types are optimized -// for element access. -// -////////////////////////////////////////////////////////////////////////// -class TGenVectorProxy : public TGenCollectionProxy { -public: - // Standard Destructor - TGenVectorProxy(const TGenCollectionProxy& c) : TGenCollectionProxy(c) -{ - } - // Standard Destructor - virtual ~TGenVectorProxy() -{ - } - // Return the address of the value at index 'idx' - virtual void* At(UInt_t idx) -{ - if ( fEnv && fEnv->object ) { - fEnv->idx = idx; - switch( idx ) { - case 0: - return fEnv->start = fFirst.invoke(fEnv); - default: - if (! fEnv->start ) fEnv->start = fFirst.invoke(fEnv); - return ((char*)fEnv->start) + fValDiff*idx; - } - } - Fatal("TGenVectorProxy","At> Logic error - no proxy object set."); - return 0; - } - // Call to delete/destruct individual item - virtual void DeleteItem(bool force, void* ptr) const - { - if ( force && ptr ) { - fVal->DeleteItem(ptr); - } - } -}; - -////////////////////////////////////////////////////////////////////////// -// // -// class TGenListProxy -// -// Localoptimization class. -// -// Collection proxies get copied. On copy we switch the type of the -// proxy to the concrete STL type. The concrete types are optimized -// for element access. -// -////////////////////////////////////////////////////////////////////////// -class TGenListProxy : public TGenVectorProxy { -public: - // Standard Destructor - TGenListProxy(const TGenCollectionProxy& c) : TGenVectorProxy(c) -{ - } - // Standard Destructor - virtual ~TGenListProxy() -{ - } - // Return the address of the value at index 'idx' - void* At(UInt_t idx) -{ - if ( fEnv && fEnv->object ) { - switch( idx ) { - case 0: - fEnv->idx = idx; - return fEnv->start = fFirst.invoke(fEnv); - default: { - fEnv->idx = idx - fEnv->idx; - if (! fEnv->start ) fEnv->start = fFirst.invoke(fEnv); - void* result = fNext.invoke(fEnv); - fEnv->idx = idx; - return result; - } - } - } - Fatal("TGenListProxy","At> Logic error - no proxy object set."); - return 0; - } -}; - -////////////////////////////////////////////////////////////////////////// -// // -// class TGenSetProxy -// -// Localoptimization class. -// -// Collection proxies get copied. On copy we switch the type of the -// proxy to the concrete STL type. The concrete types are optimized -// for element access. -// -////////////////////////////////////////////////////////////////////////// -class TGenSetProxy : public TGenVectorProxy { -public: - // Standard Destructor - TGenSetProxy(const TGenCollectionProxy& c) : TGenVectorProxy(c) -{ - } - // Standard Destructor - virtual ~TGenSetProxy() -{ - } - // Return the address of the value at index 'idx' - void* At(UInt_t idx) -{ - if ( fEnv && fEnv->object ) { - if ( fEnv->temp ) { - return (((char*)fEnv->temp)+idx*fValDiff); - } - switch( idx ) { - case 0: - fEnv->idx = idx; - return fEnv->start = fFirst.invoke(fEnv); - default: { - fEnv->idx = idx - fEnv->idx; - if (! fEnv->start ) fEnv->start = fFirst.invoke(fEnv); - void* result = fNext.invoke(fEnv); - fEnv->idx = idx; - return result; - } - } - } - Fatal("TGenSetProxy","At> Logic error - no proxy object set."); - return 0; - } -}; - -////////////////////////////////////////////////////////////////////////// -// // -// class TGenMapProxy -// -// Localoptimization class. -// -// Collection proxies get copied. On copy we switch the type of the -// proxy to the concrete STL type. The concrete types are optimized -// for element access. -// -////////////////////////////////////////////////////////////////////////// -class TGenMapProxy : public TGenSetProxy { -public: - // Standard Destructor - TGenMapProxy(const TGenCollectionProxy& c) : TGenSetProxy(c) -{ - } - // Standard Destructor - virtual ~TGenMapProxy() -{ - } - // Call to delete/destruct individual item - virtual void DeleteItem(Bool_t /* force */, void* ptr) const - { - if ( fKey->fCase&G__BIT_ISPOINTER ) { - fKey->DeleteItem(*(void**)ptr); - } - if ( fVal->fCase&G__BIT_ISPOINTER ) { - char *addr = ((char*)ptr)+fValOffset; - fVal->DeleteItem(*(void**)addr); - } - } -}; - - -//______________________________________________________________________________ -TGenCollectionProxy::Value::Value(const Value& copy) -{ - // Constructor. - - fType = copy.fType; - fCase = copy.fCase; - fKind = copy.fKind; - fSize = copy.fSize; - fCtor = copy.fCtor; - fDtor = copy.fDtor; - fDelete = copy.fDelete; -} - -//______________________________________________________________________________ -TGenCollectionProxy::Value::Value(const std::string& inside_type) -{ - // Constructor. - - std::string inside = (inside_type.find("const ")==0) ? inside_type.substr(6) : inside_type; - fCase = 0; - fCtor = 0; - fDtor = 0; - fDelete = 0; - fSize = std::string::npos; - fKind = kNoType_t; - std::string intype = TClassEdit::ShortType(inside.c_str(),TClassEdit::kDropTrailStar ); - if ( inside.substr(0,6) == "string" || inside.substr(0,11) == "std::string" ) { - fCase = kBIT_ISSTRING; - fType = TClass::GetClass("string"); - fCtor = fType->GetNew(); - fDtor = fType->GetDestructor(); - fDelete = fType->GetDelete(); - switch(inside[inside.length()-1]) { - case '*': - fCase |= G__BIT_ISPOINTER; - fSize = sizeof(void*); - break; - default: - fSize = sizeof(std::string); - break; - } - } - else { - // In the case where we have an emulated class, - // if the class is nested (in a class or a namespace), - // calling G__TypeInfo ti(inside.c_str()); - // might fail because CINT does not known the nesting - // scope, so let's first look for an emulated class: - fType = TClass::GetClass(intype.c_str()); - if (fType && !fType->IsLoaded()) { - if (intype != inside) { - fCase |= G__BIT_ISPOINTER; - fSize = sizeof(void*); - } - fCase |= G__BIT_ISCLASS; - fCtor = fType->GetNew(); - fDtor = fType->GetDestructor(); - fDelete = fType->GetDelete(); - } else { -#if defined(NOT_YET) - // Because the TStreamerInfo of the contained classes - // is stored only when tbere at least one element in - // the collection, we might not even have an emulated - // class. So go the long route to avoid errors - // issued by CINT .... - G__value gval = G__string2type_body(inside.c_str(),2); - G__TypeInfo ti(gval); -#else - G__TypeInfo ti(inside.c_str()); -#endif - if ( !ti.IsValid() ) { - if (intype != inside) { - fCase |= G__BIT_ISPOINTER; - fSize = sizeof(void*); - } - fType = TClass::GetClass(intype.c_str()); - if (fType) { - fCase |= G__BIT_ISCLASS; - fCtor = fType->GetNew(); - fDtor = fType->GetDestructor(); - fDelete = fType->GetDelete(); - } - else { - // either we have an Emulated enum or a really unknown class! - // let's just claim its an enum :( - fCase = G__BIT_ISENUM; - fSize = sizeof(Int_t); - fKind = kInt_t; - } - } - else { - Long_t prop = ti.Property(); - if ( prop&G__BIT_ISPOINTER ) { - fSize = sizeof(void*); - } - if ( prop&G__BIT_ISSTRUCT ) { - prop |= G__BIT_ISCLASS; - } - if ( prop&G__BIT_ISCLASS ) { - fType = TClass::GetClass(intype.c_str()); - R__ASSERT(fType); - fCtor = fType->GetNew(); - fDtor = fType->GetDestructor(); - fDelete = fType->GetDelete(); - } - else if ( prop&G__BIT_ISFUNDAMENTAL ) { - TDataType *fundType = gROOT->GetType( intype.c_str() ); - fKind = (EDataType)fundType->GetType(); - if ( 0 == strcmp("bool",fundType->GetFullTypeName()) ) { - fKind = (EDataType)kBOOL_t; - } - fSize = ti.Size(); - R__ASSERT(fKind>0 && fKind<0x16 || (fKind==-1&&(prop&G__BIT_ISPOINTER)) ); - } - else if ( prop&G__BIT_ISENUM ) { - fSize = sizeof(int); - fKind = kInt_t; - } - fCase = prop & (G__BIT_ISPOINTER|G__BIT_ISFUNDAMENTAL|G__BIT_ISENUM|G__BIT_ISCLASS); - if (fType == TString::Class() && (fCase&G__BIT_ISPOINTER)) { - fCase |= kBIT_ISTSTRING; - } - } - } - } - if ( fSize == std::string::npos ) { - if ( fType == 0 ) { - Fatal("TGenCollectionProxy","Could not find %s!",inside.c_str()); - } - fSize = fType->Size(); - } -} - -void TGenCollectionProxy::Value::DeleteItem(void* ptr) -{ - // Delete an item. - - if ( ptr && fCase&G__BIT_ISPOINTER ) { - if ( fDelete ) { - (*fDelete)(ptr); - } - else if ( fType ) { - fType->Destructor(ptr); - } - else { - ::operator delete(ptr); - } - } -} - -//______________________________________________________________________________ -TGenCollectionProxy::TGenCollectionProxy(const TGenCollectionProxy& copy) - : TVirtualCollectionProxy(copy.fClass), - fTypeinfo(copy.fTypeinfo) -{ - // Build a proxy for an emulated container. - fEnv = 0; - fName = copy.fName; - fPointers = copy.fPointers; - fSTL_type = copy.fSTL_type; - fSize.call = copy.fSize.call; - fNext.call = copy.fNext.call; - fFirst.call = copy.fFirst.call; - fClear.call = copy.fClear.call; - fResize.call = copy.fResize.call; - fDestruct.call = copy.fDestruct.call; - fConstruct.call = copy.fConstruct.call; - fFeed.call = copy.fFeed.call; - fCollect.call = copy.fCollect.call; - fValOffset = copy.fValOffset; - fValDiff = copy.fValDiff; - fValue = copy.fValue ? new Value(*copy.fValue) : 0; - fVal = copy.fVal ? new Value(*copy.fVal) : 0; - fKey = copy.fKey ? new Value(*copy.fKey) : 0; -} - -//______________________________________________________________________________ -TGenCollectionProxy::TGenCollectionProxy(Info_t info, size_t iter_size) - : TVirtualCollectionProxy(0), - fTypeinfo(info) -{ - // Build a proxy for a collection whose type is described by 'collectionClass'. - fEnv = 0; - fSize.call = 0; - fFirst.call = 0; - fNext.call = 0; - fClear.call = 0; - fResize.call = 0; - fDestruct.call = 0; - fConstruct.call = 0; - fCollect.call = 0; - fFeed.call = 0; - fValue = 0; - fKey = 0; - fVal = 0; - fValOffset = 0; - fValDiff = 0; - fPointers = false; - Env_t e; - if ( iter_size > sizeof(e.buff) ) { - Fatal("TGenCollectionProxy", - "%s %s are too large:%d bytes. Maximum is:%d bytes", - "Iterators for collection", - fClass->GetName(), - iter_size, - sizeof(e.buff)); - } -} - -//______________________________________________________________________________ -TGenCollectionProxy::TGenCollectionProxy(const ROOT::TCollectionProxyInfo &info, TClass *cl) - : TVirtualCollectionProxy(cl), - fTypeinfo(info.fInfo) -{ - // Build a proxy for a collection whose type is described by 'collectionClass'. - fEnv = 0; - fValDiff = info.fValueDiff; - fValOffset = info.fValueOffset; - fSize.call = info.fSizeFunc; - fResize.call = info.fResizeFunc; - fNext.call = info.fNextFunc; - fFirst.call = info.fFirstFunc; - fClear.call = info.fClearFunc; - fConstruct.call = info.fConstructFunc; - fDestruct.call = info.fDestructFunc; - fFeed.call = info.fFeedFunc; - fCollect.call = info.fCollectFunc; - CheckFunctions(); - - fValue = 0; - fKey = 0; - fVal = 0; - fPointers = false; - - Env_t e; - if ( info.fIterSize > sizeof(e.buff) ) { - Fatal("TGenCollectionProxy", - "%s %s are too large:%d bytes. Maximum is:%d bytes", - "Iterators for collection", - fClass->GetName(), - info.fIterSize, - sizeof(e.buff)); - } -} - -namespace { - typedef std::vector<ROOT::TCollectionProxyInfo::Environ<char[64]>* > Proxies_t; - void clearProxies(Proxies_t& v) - { - // Clear out the proxies. - - for(Proxies_t::iterator i=v.begin(); i != v.end(); ++i) { - ROOT::TCollectionProxyInfo::Environ<char[64]> *e = *i; - if ( e ) { - if ( e->temp ) ::free(e->temp); - delete e; - } - } - v.clear(); - } -} -//______________________________________________________________________________ -TGenCollectionProxy::~TGenCollectionProxy() -{ - // Standard destructor - clearProxies(fProxyList); - clearProxies(fProxyKept); - - if ( fValue ) delete fValue; - if ( fVal ) delete fVal; - if ( fKey ) delete fKey; -} - -//______________________________________________________________________________ -TVirtualCollectionProxy* TGenCollectionProxy::Generate() const -{ - // Virtual copy constructor - if ( !fValue ) Initialize(); - switch(fSTL_type) { - case TClassEdit::kVector: - return new TGenVectorProxy(*this); - case TClassEdit::kList: - return new TGenListProxy(*this); - case TClassEdit::kMap: - case TClassEdit::kMultiMap: - return new TGenMapProxy(*this); - case TClassEdit::kSet: - case TClassEdit::kMultiSet: - return new TGenSetProxy(*this); - default: - return new TGenCollectionProxy(*this); - } -} - -//______________________________________________________________________________ -TGenCollectionProxy *TGenCollectionProxy::Initialize() const -{ - // Proxy initializer - TGenCollectionProxy* p = const_cast<TGenCollectionProxy*>(this); - if ( fValue ) return p; - return p->InitializeEx(); -} - -//______________________________________________________________________________ -void TGenCollectionProxy::CheckFunctions() const -{ - // Check existence of function pointers - if ( 0 == fSize.call ) { - Fatal("TGenCollectionProxy","No 'size' function pointer for class %s present.",fName.c_str()); - } - if ( 0 == fResize.call ) { - Fatal("TGenCollectionProxy","No 'resize' function for class %s present.",fName.c_str()); - } - if ( 0 == fNext.call ) { - Fatal("TGenCollectionProxy","No 'next' function for class %s present.",fName.c_str()); - } - if ( 0 == fFirst.call ) { - Fatal("TGenCollectionProxy","No 'begin' function for class %s present.",fName.c_str()); - } - if ( 0 == fClear.call ) { - Fatal("TGenCollectionProxy","No 'clear' function for class %s present.",fName.c_str()); - } - if ( 0 == fConstruct.call ) { - Fatal("TGenCollectionProxy","No 'block constructor' function for class %s present.",fName.c_str()); - } - if ( 0 == fDestruct.call ) { - Fatal("TGenCollectionProxy","No 'block destructor' function for class %s present.",fName.c_str()); - } - if ( 0 == fFeed.call ) { - Fatal("TGenCollectionProxy","No 'data feed' function for class %s present.",fName.c_str()); - } - if ( 0 == fCollect.call ) { - Fatal("TGenCollectionProxy","No 'data collect' function for class %s present.",fName.c_str()); - } -} - -//______________________________________________________________________________ -TGenCollectionProxy *TGenCollectionProxy::InitializeEx() -{ - // Proxy initializer - R__LOCKGUARD2(gCollectionMutex); - if (fValue) return this; - - TClass *cl = fClass ? fClass.GetClass() : TClass::GetClass(fTypeinfo); - if ( cl ) { - fEnv = 0; - fName = cl->GetName(); - fPointers = false; - int nested = 0; - std::vector<std::string> inside; - int num = TClassEdit::GetSplit(cl->GetName(),inside,nested); - if ( num > 1 ) { - std::string nam; - if ( inside[0].find("stdext::hash_") != std::string::npos ) - inside[0].replace(3,10,"::"); - if ( inside[0].find("__gnu_cxx::hash_") != std::string::npos ) - inside[0].replace(0,16,"std::"); - fSTL_type = TClassEdit::STLKind(inside[0].c_str()); - int slong = sizeof(void*); - switch ( fSTL_type ) { - case TClassEdit::kMap: - case TClassEdit::kMultiMap: - nam = "pair<"+inside[1]+","+inside[2]; - nam += (nam[nam.length()-1]=='>') ? " >" : ">"; - fValue = new Value(nam); - fVal = new Value(inside[2]); - fKey = new Value(inside[1]); - fPointers = fPointers || (0 != (fKey->fCase&G__BIT_ISPOINTER)); - if ( 0 == fValDiff ) { - fValDiff = fKey->fSize + fVal->fSize; - fValDiff += (slong - fKey->fSize%slong)%slong; - fValDiff += (slong - fValDiff%slong)%slong; - } - if ( 0 == fValOffset ) { - fValOffset = fKey->fSize; - fValOffset += (slong - fKey->fSize%slong)%slong; - } - break; - default: - fValue = new Value(inside[1]); - fVal = new Value(*fValue); - if ( 0 == fValDiff ) { - fValDiff = fVal->fSize; - fValDiff += (slong - fValDiff%slong)%slong; - } - break; - } - fPointers = fPointers || (0 != (fVal->fCase&G__BIT_ISPOINTER)); - fClass = cl; - return this; - } - Fatal("TGenCollectionProxy","Components of %s not analysed!",cl->GetName()); - } - Fatal("TGenCollectionProxy","Collection class %s not found!",fTypeinfo.name()); - return 0; -} - -//______________________________________________________________________________ -TClass *TGenCollectionProxy::GetCollectionClass() -{ - // Return a pointer to the TClass representing the container - return fClass ? fClass : Initialize()->fClass; -} - -//______________________________________________________________________________ -UInt_t TGenCollectionProxy::Sizeof() const -{ - // Return the sizeof the collection object. - return fClass->Size(); -} - -//______________________________________________________________________________ -Bool_t TGenCollectionProxy::HasPointers() const -{ - // Return true if the content is of type 'pointer to' - - // The content of a map and multimap is always a 'pair' and hence - // fPointers means "Flag to indicate if containee has pointers (key or value)" - // so we need to ignore its value for map and multimap; - return fPointers && !(fSTL_type == TClassEdit::kMap || fSTL_type == TClassEdit::kMultiMap); -} - -//______________________________________________________________________________ -TClass *TGenCollectionProxy::GetValueClass() -{ - // Return a pointer to the TClass representing the content. - - if (!fValue) Initialize(); - return fValue ? fValue->fType.GetClass() : 0; -} - -//______________________________________________________________________________ -void TGenCollectionProxy::SetValueClass(TClass *new_Value_type) -{ - // Set pointer to the TClass representing the content. - - if (!fValue) Initialize(); - fValue->fType = new_Value_type; -} - -//______________________________________________________________________________ -EDataType TGenCollectionProxy::GetType() -{ - // If the content is a simple numerical value, return its type (see TDataType) - - if ( !fValue ) Initialize(); - return fValue->fKind; -} - -//______________________________________________________________________________ -void* TGenCollectionProxy::At(UInt_t idx) -{ - // Return the address of the value at index 'idx' - if ( fEnv && fEnv->object ) { - switch (fSTL_type) { - case TClassEdit::kVector: - fEnv->idx = idx; - switch( idx ) { - case 0: - return fEnv->start = fFirst.invoke(fEnv); - default: - if (! fEnv->start ) fEnv->start = fFirst.invoke(fEnv); - return ((char*)fEnv->start) + fValDiff*idx; - } - case TClassEdit::kSet: - case TClassEdit::kMultiSet: - case TClassEdit::kMap: - case TClassEdit::kMultiMap: - if ( fEnv->temp ) { - return (((char*)fEnv->temp)+idx*fValDiff); - } - default: - switch( idx ) { - case 0: - fEnv->idx = idx; - return fEnv->start = fFirst.invoke(fEnv); - default: { - fEnv->idx = idx - fEnv->idx; - if (! fEnv->start ) fEnv->start = fFirst.invoke(fEnv); - void* result = fNext.invoke(fEnv); - fEnv->idx = idx; - return result; - } - } - } - } - Fatal("TGenCollectionProxy","At> Logic error - no proxy object set."); - return 0; -} - -//______________________________________________________________________________ -void TGenCollectionProxy::Clear(const char* opt) -{ - // Clear the emulated collection. - if ( fEnv && fEnv->object ) { - if ( fPointers && opt && *opt=='f' ) { - size_t i, n = *(size_t*)fSize.invoke(fEnv); - if ( n > 0 ) { - for (i=0; i<n; ++i) - DeleteItem(true, TGenCollectionProxy::At(i)); - } - } - fClear.invoke(fEnv); - } -} - -//______________________________________________________________________________ -UInt_t TGenCollectionProxy::Size() const -{ - // Return the current size of the container - if ( fEnv && fEnv->object ) { - return *(size_t*)fSize.invoke(fEnv); - } - Fatal("TGenCollectionProxy","Size> Logic error - no proxy object set."); - return 0; -} - -//______________________________________________________________________________ -void TGenCollectionProxy::Resize(UInt_t n, Bool_t force) -{ - // Resize the container - if ( fEnv && fEnv->object ) { - if ( force && fPointers ) { - size_t i, nold = *(size_t*)fSize.invoke(fEnv); - if ( n != nold ) { - for (i=n; i<nold; ++i) - DeleteItem(true, *(void**)TGenCollectionProxy::At(i)); - } - } - MESSAGE(3, "Resize(n)" ); - fEnv->size = n; - fResize.invoke(fEnv); - return; - } - Fatal("TGenCollectionProxy","Resize> Logic error - no proxy object set."); -} - -//______________________________________________________________________________ -void* TGenCollectionProxy::Allocate(UInt_t n, Bool_t /* forceDelete */ ) -{ - // Allocate the needed space. - - if ( fEnv && fEnv->object ) { - switch ( fSTL_type ) { - case TClassEdit::kSet: - case TClassEdit::kMultiSet: - case TClassEdit::kMap: - case TClassEdit::kMultiMap: - if ( fPointers ) - Clear("force"); - else - fClear.invoke(fEnv); - ++fEnv->refCount; - fEnv->size = n; - if ( fEnv->space < fValDiff*n ) { - fEnv->temp = fEnv->temp ? ::realloc(fEnv->temp,fValDiff*n) : ::malloc(fValDiff*n); - fEnv->space = fValDiff*n; - } - fEnv->start = fEnv->temp; - fConstruct.invoke(fEnv); - return fEnv; - case TClassEdit::kVector: - case TClassEdit::kList: - case TClassEdit::kDeque: - if( fPointers ) { - Clear("force"); - } - fEnv->size = n; - fResize.invoke(fEnv); - return fEnv; - } - } - return 0; -} - -//______________________________________________________________________________ -void TGenCollectionProxy::Commit(void* env) -{ - // Commit the change. - - switch (fSTL_type) { - case TClassEdit::kVector: - case TClassEdit::kList: - case TClassEdit::kDeque: - return; - case TClassEdit::kMap: - case TClassEdit::kMultiMap: - case TClassEdit::kSet: - case TClassEdit::kMultiSet: - if ( env ) { - Env_t* e = (Env_t*)env; - if ( e->object ) { - e->start = e->temp; - fFeed.invoke(e); - } - fDestruct.invoke(e); - e->start = 0; - --e->refCount; - } - return; - default: - return; - } -} - -//______________________________________________________________________________ -void TGenCollectionProxy::PushProxy(void *objstart) -{ - // Add an object. - - if ( !fValue ) Initialize(); - if ( !fProxyList.empty() ) { - Env_t* back = fProxyList.back(); - if ( back->object == objstart ) { - back->refCount++; - fProxyList.push_back(back); - fEnv = back; - return; - } - } - Env_t* e = 0; - if ( fProxyKept.empty() ) { - e = new Env_t(); - e->space = 0; - e->temp = 0; - } - else { - e = fProxyKept.back(); - fProxyKept.pop_back(); - } - e->size = 0; - e->refCount = 1; - e->object = objstart; - e->start = 0; - ::memset(e->buff,0,sizeof(e->buff)); - fProxyList.push_back(e); - fEnv = e; -} - -//______________________________________________________________________________ -void TGenCollectionProxy::PopProxy() -{ - // Remove the last object. - - if ( !fProxyList.empty() ) { - Env_t* e = fProxyList.back(); - if ( --e->refCount <= 0 ) { - fProxyKept.push_back(e); - } - fProxyList.pop_back(); - } - fEnv = fProxyList.empty() ? 0 : fProxyList.back(); -} - -//______________________________________________________________________________ -void TGenCollectionProxy::DeleteItem(Bool_t force, void* ptr) const -{ - // Call to delete/destruct individual item. - if ( force && ptr ) { - switch (fSTL_type) { - case TClassEdit::kMap: - case TClassEdit::kMultiMap: - if ( fKey->fCase&G__BIT_ISPOINTER ) { - fKey->DeleteItem(*(void**)ptr); - } - if ( fVal->fCase&G__BIT_ISPOINTER ) { - char *addr = ((char*)ptr)+fValOffset; - fVal->DeleteItem(*(void**)addr); - } - break; - default: - if ( fVal->fCase&G__BIT_ISPOINTER ) { - fVal->DeleteItem(*(void**)ptr); - } - break; - } - } -} - -//______________________________________________________________________________ -void TGenCollectionProxy::Streamer(TBuffer &buff) -{ - // Streamer Function. - if ( fEnv ) { - GetCollectionClass()->Streamer( fEnv->object, buff ); - return; - } - Fatal("TGenCollectionProxy","Streamer> Logic error - no proxy object set."); -} - -//______________________________________________________________________________ -void TGenCollectionProxy::Streamer(TBuffer &buff, void *objp, int /* siz */ ) -{ - // Streamer I/O overload - TPushPop env(this, objp); - Streamer(buff); -} - -//______________________________________________________________________________ -void TGenCollectionProxy::operator()(TBuffer &b, void *objp) -{ - // TClassStreamer IO overload - Streamer(b, objp, 0); -} - diff --git a/cont/src/TGenCollectionStreamer.cxx b/cont/src/TGenCollectionStreamer.cxx deleted file mode 100644 index 359a0292c5cd1b85afa7b3457e7ee1861d4433be..0000000000000000000000000000000000000000 --- a/cont/src/TGenCollectionStreamer.cxx +++ /dev/null @@ -1,494 +0,0 @@ -// @(#)root/cont:$Name: $:$Id: TGenCollectionStreamer.cxx,v 1.13 2007/02/01 22:02:48 pcanal Exp $ -// Author: Markus Frank 28/10/04 - -/************************************************************************* - * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// // -// TGenCollectionStreamer -// -// Streamer around an arbitrary container, which implements basic -// functionality and iteration. -// -// In particular this is used to implement splitting and abstract -// element access of any container. Access to compiled code is necessary -// to implement the abstract iteration sequence and functionality like -// size(), clear(), resize(). resize() may be a void operation. -// -////////////////////////////////////////////////////////////////////////// - -#include "TGenCollectionStreamer.h" -#include "TClassEdit.h" -#include "TError.h" -#include "TROOT.h" -#include "TStreamerInfo.h" -#include "Riostream.h" - -TGenCollectionStreamer::TGenCollectionStreamer(const TGenCollectionStreamer& copy) - : TGenCollectionProxy(copy) -{ - // Build a Streamer for an emulated vector whose type is 'name'. -} - -TGenCollectionStreamer::TGenCollectionStreamer(Info_t info, size_t iter_size) - : TGenCollectionProxy(info, iter_size) -{ - // Build a Streamer for a collection whose type is described by 'collectionClass'. -} - -TGenCollectionStreamer::TGenCollectionStreamer(const ::ROOT::TCollectionProxyInfo &info, TClass *cl) - : TGenCollectionProxy(info,cl) -{ - // Build a Streamer for a collection whose type is described by 'collectionClass'. -} - -TGenCollectionStreamer::~TGenCollectionStreamer() -{ - // Standard destructor. -} - -TVirtualCollectionProxy* TGenCollectionStreamer::Generate() const -{ - // Virtual copy constructor. - if ( !fClass ) Initialize(); - return new TGenCollectionStreamer(*this); -} - -void TGenCollectionStreamer::ReadPrimitives(int nElements, TBuffer &b) -{ - // Primitive input streamer. - size_t len = fValDiff*nElements; - char buffer[8096]; - Bool_t feed = false; - void* memory = 0; - StreamHelper* itm = 0; - fEnv->size = nElements; - switch ( fSTL_type ) { - case TClassEdit::kVector: - if ( fVal->fKind != EDataType(kBOOL_t) ) { - itm = (StreamHelper*)fResize.invoke(fEnv); - break; - } - default: - feed = true; - itm = (StreamHelper*)(len<sizeof(buffer) ? buffer : memory=::operator new(len)); - break; - } - fEnv->start = itm; - switch( int(fVal->fKind) ) { - case kBool_t: b.ReadFastArray(&itm->boolean , nElements); break; - case kChar_t: b.ReadFastArray(&itm->s_char , nElements); break; - case kShort_t: b.ReadFastArray(&itm->s_short , nElements); break; - case kInt_t: b.ReadFastArray(&itm->s_int , nElements); break; - case kLong_t: b.ReadFastArray(&itm->s_long , nElements); break; - case kLong64_t: b.ReadFastArray(&itm->s_longlong, nElements); break; - case kFloat_t: b.ReadFastArray(&itm->flt , nElements); break; - case kDouble_t: b.ReadFastArray(&itm->dbl , nElements); break; - case kBOOL_t: b.ReadFastArray(&itm->boolean , nElements); break; - case kUChar_t: b.ReadFastArray(&itm->u_char , nElements); break; - case kUShort_t: b.ReadFastArray(&itm->u_short , nElements); break; - case kUInt_t: b.ReadFastArray(&itm->u_int , nElements); break; - case kULong_t: b.ReadFastArray(&itm->u_long , nElements); break; - case kULong64_t: b.ReadFastArray(&itm->u_longlong, nElements); break; - case kDouble32_t:b.ReadFastArrayDouble32(&itm->dbl,nElements); break; - case kchar: - case kNoType_t: - case kOther_t: - Error("TGenCollectionStreamer","fType %d is not supported yet!\n",fVal->fKind); - } - if ( feed ) { // need to feed in data... - fEnv->start = fFeed.invoke(fEnv); - if ( memory ) { - ::operator delete(memory); - } - } -} - -void TGenCollectionStreamer::ReadObjects(int nElements, TBuffer &b) -{ - // Object input streamer. - Bool_t vsn3 = b.GetInfo() && b.GetInfo()->GetOldVersion()<=3; - size_t len = fValDiff*nElements; - StreamHelper* itm = 0; - char buffer[8096]; - void* memory = 0; - - fEnv->size = nElements; - switch ( fSTL_type ) { - // Simple case: contiguous memory. get address of first, then jump. - case TClassEdit::kVector: -#define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)(((char*)itm) + fValDiff*idx); { x ;} ++idx;} break;} - itm = (StreamHelper*)fResize.invoke(fEnv); - switch (fVal->fCase) { - case G__BIT_ISCLASS: - DOLOOP( b.StreamObject(i,fVal->fType) ); - case kBIT_ISSTRING: - DOLOOP( i->read_std_string(b) ); - case G__BIT_ISPOINTER|G__BIT_ISCLASS: - DOLOOP( i->set(b.ReadObjectAny(fVal->fType)) ); - case G__BIT_ISPOINTER|kBIT_ISSTRING: - DOLOOP( i->read_std_string_pointer(b) ); - case G__BIT_ISPOINTER|kBIT_ISTSTRING|G__BIT_ISCLASS: - DOLOOP( i->read_tstring_pointer(vsn3,b) ); - } -#undef DOLOOP - break; - - // No contiguous memory, but resize is possible - // Hence accessing objects using At(i) should be not too much an overhead - case TClassEdit::kList: - case TClassEdit::kDeque: -#define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)TGenCollectionProxy::At(idx); { x ;} ++idx;} break;} - fResize.invoke(fEnv); - switch (fVal->fCase) { - case G__BIT_ISCLASS: - DOLOOP( b.StreamObject(i,fVal->fType) ); - case kBIT_ISSTRING: - DOLOOP( i->read_std_string(b) ); - case G__BIT_ISPOINTER|G__BIT_ISCLASS: - DOLOOP( i->set( b.ReadObjectAny(fVal->fType) ) ); - case G__BIT_ISPOINTER|kBIT_ISSTRING: - DOLOOP( i->read_std_string_pointer(b) ); - case G__BIT_ISPOINTER|kBIT_ISTSTRING|G__BIT_ISCLASS: - DOLOOP( i->read_tstring_pointer(vsn3,b) ); - } -#undef DOLOOP - break; - - // Rather troublesome case: Objects can only be fed into the container - // Once they are created. Need to take memory from stack or heap. - case TClassEdit::kMultiSet: - case TClassEdit::kSet: -#define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)(((char*)itm) + fValDiff*idx); { x ;} ++idx;}} - fEnv->start = itm = (StreamHelper*)(len<sizeof(buffer) ? buffer : memory=::operator new(len)); - fConstruct.invoke(fEnv); - switch ( fVal->fCase ) { - case G__BIT_ISCLASS: - DOLOOP( b.StreamObject(i,fVal->fType) ) - fFeed.invoke(fEnv); - fDestruct.invoke(fEnv); - break; - case kBIT_ISSTRING: - DOLOOP( i->read_std_string(b) ) - fFeed.invoke(fEnv); - fDestruct.invoke(fEnv); - break; - case G__BIT_ISPOINTER|G__BIT_ISCLASS: - DOLOOP( i->set(b.ReadObjectAny(fVal->fType)) ); - fFeed.invoke(fEnv); - break; - case G__BIT_ISPOINTER|kBIT_ISSTRING: - DOLOOP( i->read_std_string_pointer(b) ) - fFeed.invoke(fEnv); - break; - case G__BIT_ISPOINTER|kBIT_ISTSTRING|G__BIT_ISCLASS: - DOLOOP( i->read_tstring_pointer(vsn3,b) ) - fFeed.invoke(fEnv); - break; - } -#undef DOLOOP - break; - default: - break; - } - if ( memory ) { - ::operator delete(memory); - } -} - -void TGenCollectionStreamer::ReadMap(int nElements, TBuffer &b) -{ - // Map input streamer. - Bool_t vsn3 = b.GetInfo() && b.GetInfo()->GetOldVersion()<=3; - size_t len = fValDiff*nElements; - Value *v; - char buffer[8096], *addr, *temp; - void* memory = 0; - StreamHelper* i; - float f; - fEnv->size = nElements; - fEnv->start = (len<sizeof(buffer) ? buffer : memory=::operator new(len)); - addr = temp = (char*)fEnv->start; - fConstruct.invoke(fEnv); - for ( int loop, idx = 0; idx < nElements; ++idx ) { - addr = temp + fValDiff*idx; - v = fKey; - for ( loop=0; loop<2; loop++ ) { - i = (StreamHelper*)addr; - switch (v->fCase) { - case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way - case G__BIT_ISENUM: - switch( int(v->fKind) ) { - case kBool_t: b >> i->boolean; break; - case kChar_t: b >> i->s_char; break; - case kShort_t: b >> i->s_short; break; - case kInt_t: b >> i->s_int; break; - case kLong_t: b >> i->s_long; break; - case kLong64_t: b >> i->s_longlong; break; - case kFloat_t: b >> i->flt; break; - case kDouble_t: b >> i->dbl; break; - case kBOOL_t: b >> i->boolean; break; - case kUChar_t: b >> i->u_char; break; - case kUShort_t: b >> i->u_short; break; - case kUInt_t: b >> i->u_int; break; - case kULong_t: b >> i->u_long; break; - case kULong64_t: b >> i->u_longlong; break; - case kDouble32_t:b >> f; - i->dbl = double(f); break; - case kchar: - case kNoType_t: - case kOther_t: - Error("TGenCollectionStreamer","fType %d is not supported yet!\n",v->fKind); - } - break; - case G__BIT_ISCLASS: - b.StreamObject(i,v->fType); - break; - case kBIT_ISSTRING: - i->read_std_string(b); - break; - case G__BIT_ISPOINTER|G__BIT_ISCLASS: - i->set(b.ReadObjectAny(v->fType)); - break; - case G__BIT_ISPOINTER|kBIT_ISSTRING: - i->read_std_string_pointer(b); - break; - case G__BIT_ISPOINTER|kBIT_ISTSTRING|G__BIT_ISCLASS: - i->read_tstring_pointer(vsn3,b); - break; - } - v = fVal; - addr += fValOffset; - } - } - fFeed.invoke(fEnv); - fDestruct.invoke(fEnv); - if ( memory ) { - ::operator delete(memory); - } -} - -void TGenCollectionStreamer::WritePrimitives(int nElements, TBuffer &b) -{ - // Primitive output streamer. - size_t len = fValDiff*nElements; - char buffer[8192]; - void* memory = 0; - StreamHelper* itm = 0; - switch ( fSTL_type ) { - case TClassEdit::kVector: - if ( fVal->fKind != EDataType(kBOOL_t) ) { - itm = (StreamHelper*)(fEnv->start = fFirst.invoke(fEnv)); - break; - } - default: - fEnv->start = itm = (StreamHelper*) (len<sizeof(buffer) ? buffer : memory=::operator new(len)); - fCollect.invoke(fEnv); - break; - } - switch( int(fVal->fKind) ) { - case kBool_t: b.WriteFastArray(&itm->boolean , nElements); break; - case kChar_t: b.WriteFastArray(&itm->s_char , nElements); break; - case kShort_t: b.WriteFastArray(&itm->s_short , nElements); break; - case kInt_t: b.WriteFastArray(&itm->s_int , nElements); break; - case kLong_t: b.WriteFastArray(&itm->s_long , nElements); break; - case kLong64_t: b.WriteFastArray(&itm->s_longlong, nElements); break; - case kFloat_t: b.WriteFastArray(&itm->flt , nElements); break; - case kDouble_t: b.WriteFastArray(&itm->dbl , nElements); break; - case kBOOL_t: b.WriteFastArray(&itm->boolean , nElements); break; - case kUChar_t: b.WriteFastArray(&itm->u_char , nElements); break; - case kUShort_t: b.WriteFastArray(&itm->u_short , nElements); break; - case kUInt_t: b.WriteFastArray(&itm->u_int , nElements); break; - case kULong_t: b.WriteFastArray(&itm->u_long , nElements); break; - case kULong64_t: b.WriteFastArray(&itm->u_longlong, nElements); break; - case kDouble32_t:b.WriteFastArrayDouble32(&itm->dbl,nElements); break; - case kchar: - case kNoType_t: - case kOther_t: - Error("TGenCollectionStreamer","fType %d is not supported yet!\n",fVal->fKind); - } - if ( memory ) { - ::operator delete(memory); - } -} - -void TGenCollectionStreamer::WriteObjects(int nElements, TBuffer &b) -{ - // Object output streamer. - StreamHelper* itm = 0; - switch(fSTL_type) { - // Simple case: contiguous memory. get address of first, then jump. - case TClassEdit::kVector: -#define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)(((char*)itm) + fValDiff*idx); { x ;} ++idx;} break;} - itm = (StreamHelper*)fFirst.invoke(fEnv); - switch (fVal->fCase) { - case G__BIT_ISCLASS: - DOLOOP( b.StreamObject(i,fVal->fType)); - break; - case kBIT_ISSTRING: - DOLOOP( TString(i->c_str()).Streamer(b)); - break; - case G__BIT_ISPOINTER|G__BIT_ISCLASS: - DOLOOP( b.WriteObjectAny(i->ptr(),fVal->fType) ); - break; - case kBIT_ISSTRING|G__BIT_ISPOINTER: - DOLOOP( i->write_std_string_pointer(b)); - break; - case kBIT_ISTSTRING|G__BIT_ISCLASS|G__BIT_ISPOINTER: - DOLOOP( i->write_tstring_pointer(b)); - break; - } -#undef DOLOOP - break; - - // No contiguous memory, but resize is possible - // Hence accessing objects using At(i) should be not too much an overhead - case TClassEdit::kList: - case TClassEdit::kDeque: - case TClassEdit::kMultiSet: - case TClassEdit::kSet: -#define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)TGenCollectionProxy::At(idx); { x ;} ++idx;} break;} - switch (fVal->fCase) { - case G__BIT_ISCLASS: - DOLOOP( b.StreamObject(i,fVal->fType)); - case kBIT_ISSTRING: - DOLOOP( TString(i->c_str()).Streamer(b)); - case G__BIT_ISPOINTER|G__BIT_ISCLASS: - DOLOOP( b.WriteObjectAny(i->ptr(),fVal->fType) ); - case kBIT_ISSTRING|G__BIT_ISPOINTER: - DOLOOP( i->write_std_string_pointer(b)); - case kBIT_ISTSTRING|G__BIT_ISCLASS|G__BIT_ISPOINTER: - DOLOOP( i->write_tstring_pointer(b)); - } -#undef DOLOOP - break; - default: - break; - } -} - -void TGenCollectionStreamer::WriteMap(int nElements, TBuffer &b) -{ - // Map output streamer - StreamHelper* i; - Value *v; - - for (int loop, idx = 0; idx < nElements; ++idx ) { - char* addr = (char*)TGenCollectionProxy::At(idx); - v = fKey; - for ( loop = 0; loop<2; ++loop ) { - i = (StreamHelper*)addr; - switch (v->fCase) { - case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way - case G__BIT_ISENUM: - switch( int(v->fKind) ) { - case kBool_t: b << i->boolean; break; - case kChar_t: b << i->s_char; break; - case kShort_t: b << i->s_short; break; - case kInt_t: b << i->s_int; break; - case kLong_t: b << i->s_long; break; - case kLong64_t: b << i->s_longlong; break; - case kFloat_t: b << i->flt; break; - case kDouble_t: b << i->dbl; break; - case kBOOL_t: b << i->boolean; break; - case kUChar_t: b << i->u_char; break; - case kUShort_t: b << i->u_short; break; - case kUInt_t: b << i->u_int; break; - case kULong_t: b << i->u_long; break; - case kULong64_t: b << i->u_longlong; break; - case kDouble32_t:b << float(i->dbl); break; - case kchar: - case kNoType_t: - case kOther_t: - Error("TGenCollectionStreamer","fType %d is not supported yet!\n",v->fKind); - } - break; - case G__BIT_ISCLASS: - b.StreamObject(i,v->fType); - break; - case kBIT_ISSTRING: - TString(i->c_str()).Streamer(b); - break; - case G__BIT_ISPOINTER|G__BIT_ISCLASS: - b.WriteObjectAny(i->ptr(),v->fType); - break; - case kBIT_ISSTRING|G__BIT_ISPOINTER: - i->write_std_string_pointer(b); - break; - case kBIT_ISTSTRING|G__BIT_ISCLASS|G__BIT_ISPOINTER: - i->write_tstring_pointer(b); - break; - } - addr += fValOffset; - v = fVal; - } - } -} - -void TGenCollectionStreamer::Streamer(TBuffer &b) -{ - // TClassStreamer IO overload. - if ( b.IsReading() ) { //Read mode - int nElements = 0; - b >> nElements; - if ( fEnv->object ) { - TGenCollectionProxy::Clear("force"); - } - if ( nElements > 0 ) { - switch(fSTL_type) { - case TClassEdit::kVector: - case TClassEdit::kList: - case TClassEdit::kDeque: - case TClassEdit::kMultiSet: - case TClassEdit::kSet: - switch (fVal->fCase) { - case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way - case G__BIT_ISENUM: - ReadPrimitives(nElements, b); - return; - default: - ReadObjects(nElements, b); - return; - } - break; - case TClassEdit::kMap: - case TClassEdit::kMultiMap: - ReadMap(nElements, b); - break; - } - } - } - else { // Write case - int nElements = fEnv->object ? *(size_t*)fSize.invoke(fEnv) : 0; - b << nElements; - if ( nElements > 0 ) { - switch(fSTL_type) { - case TClassEdit::kVector: - case TClassEdit::kList: - case TClassEdit::kDeque: - case TClassEdit::kMultiSet: - case TClassEdit::kSet: - switch (fVal->fCase) { - case G__BIT_ISFUNDAMENTAL: // Only handle primitives this way - case G__BIT_ISENUM: - WritePrimitives(nElements, b); - return; - default: - WriteObjects(nElements, b); - return; - } - break; - case TClassEdit::kMap: - case TClassEdit::kMultiMap: - WriteMap(nElements, b); - break; - } - } - } -}