source: trunk/Mars/mbase/MParEmulated.cc @ 19273

Last change on this file since 19273 was 9302, checked in by tbretz, 11 years ago
*** empty log message ***
File size: 8.8 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appear in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18!   Author(s): Thomas Bretz 07/2008 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20!   Copyright: MAGIC Software Development, 2000-2008
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26//
27// MParEmulated
28//
29// Storage Container for emulated branches
30//
31// Thanks to roots streaming mechanism simple branches can be recreated
32// from a file. To read these kind of foreign branches the root system
33// allocates memory. We can get a pointer to this memory and the
34// offsets to the data, thus allowing to use this data and ecapsulate
35// it into the MARS environment. This is done using MParEmulated.
36//
37/////////////////////////////////////////////////////////////////////////////
38#include "MParEmulated.h"
39
40#include <TClass.h>   // root >=5.20/00
41#include <TPRegexp.h>
42#include <TMethodCall.h>
43#include <TStreamerElement.h>
44#include <TVirtualCollectionProxy.h>
45#if ROOT_VERSION_CODE>ROOT_VERSION(5,12,00)
46#include <TVirtualStreamerInfo.h>
47#endif
48
49#include "MLog.h"
50#include "MLogManip.h"
51
52#include "MString.h"
53
54ClassImp(MParEmulated);
55
56using namespace std;
57
58// --------------------------------------------------------------------------
59//
60// Default constructor.
61//
62MParEmulated::MParEmulated(const char *name, const char *title)
63    : fPtr(0)
64{
65    fName  = name  ? name  : "MParEmulated";
66    fTitle = title ? title : "Parameter container emulating a class";
67}
68
69// --------------------------------------------------------------------------
70//
71// The default is to print all emulated data members. If an option is
72// given it is interpreted as TPRegexp (regular expression) and only
73// data members matching this regex are printed.
74//
75void MParEmulated::Print(Option_t *o) const
76{
77    TString opt(o);
78    if (opt.IsNull())
79        opt = ".*";
80
81    TPRegexp regex(opt);
82    Print(regex, fClassName, "", 0);
83}
84
85int MParEmulated::GetPInt(TVirtualCollectionProxy *proxy, Int_t offset) const
86{
87    const TVirtualCollectionProxy::TPushPop pp(proxy, fPtr);
88    return *reinterpret_cast<int*>((char*)proxy->At(0)+offset);
89}
90Int_t MParEmulated::GetPInt_t(TVirtualCollectionProxy *proxy, Int_t offset) const
91{
92    const TVirtualCollectionProxy::TPushPop pp(proxy, fPtr);
93    return *reinterpret_cast<Int_t*>((char*)proxy->At(0)+offset);
94}
95double MParEmulated::GetPDouble(TVirtualCollectionProxy *proxy, Int_t offset) const
96{
97    const TVirtualCollectionProxy::TPushPop pp(proxy, fPtr);
98    return *reinterpret_cast<double*>((char*)proxy->At(0)+offset);
99}
100unsigned long long MParEmulated::GetPULongLong(TVirtualCollectionProxy *proxy, Int_t offset) const
101{
102    const TVirtualCollectionProxy::TPushPop pp(proxy, fPtr);
103    return *reinterpret_cast<unsigned long long*>((char*)proxy->At(0)+offset);
104}
105
106// --------------------------------------------------------------------------
107//
108// Get the class with name clsname and its corresponding streamer info
109//
110#if ROOT_VERSION_CODE<ROOT_VERSION(5,18,00)
111TStreamerInfo *MParEmulated::GetStreamerInfo(const TString &clsname, TVirtualCollectionProxy * &proxy, Int_t &offset) const
112#else
113TVirtualStreamerInfo *MParEmulated::GetStreamerInfo(const TString &clsname, TVirtualCollectionProxy * &proxy, Int_t &offset) const
114#endif
115{
116    TClass *cls = gROOT->GetClass(clsname);
117    if (!cls)
118    {
119        *fLog << err << dbginf << "ERROR - Class " << clsname << " not in dictionary." << endl;
120        return 0;
121    }
122
123    proxy = cls->GetCollectionProxy();
124    if (proxy)
125    {
126        cls = proxy->GetValueClass();
127
128        proxy->PushProxy(fPtr);
129        // proxy->GetSize()  // Number of elements in array
130        if (proxy->At(0))
131            offset = (char*)proxy->At(0)-(char*)fPtr;
132        proxy->PopProxy();
133
134    }
135
136#if ROOT_VERSION_CODE<ROOT_VERSION(5,18,00)
137    TStreamerInfo *info = cls->GetStreamerInfo();
138#else
139    TVirtualStreamerInfo *info = cls->GetStreamerInfo();
140#endif
141    if (!info)
142    {
143        *fLog << err << dbginf << "ERROR - No TStreamerInfo for class " << clsname << "." << endl;
144        return 0;
145    }
146
147    return info;
148}
149
150// --------------------------------------------------------------------------
151//
152// Get the method call for the given method and offset, add method to
153// MParContainer::fgListmethodCall
154//
155TMethodCall *MParEmulated::GetMethodCall(const char *get, Int_t offset, TVirtualCollectionProxy *proxy) const
156{
157    TString name(get);
158    if (proxy)
159        name.Prepend("P");
160    name.Prepend("Get");
161
162    TMethodCall *call = new TMethodCall(MParEmulated::Class(), name, proxy?MString::Format("%p,%d", proxy, offset):MString::Format("%d", offset));
163    fgListMethodCall.Add(call);
164    return call;
165}
166
167// --------------------------------------------------------------------------
168//
169// Get the getter method for the given data member. Since we have no real
170// getter methods and no real data members we have to fake the TMethodCall.
171//
172TMethodCall *MParEmulated::GetterMethod(const char *name, TString clsname, Int_t offset) const
173{
174    TVirtualCollectionProxy *proxy = 0;
175
176    // Get the streamer info for the class and the offset to the
177    // first element of a possible array
178    Int_t arroff = 0;
179
180#if ROOT_VERSION_CODE<ROOT_VERSION(5,18,00)
181    TStreamerInfo *info = GetStreamerInfo(clsname, proxy, arroff);
182#else
183    TVirtualStreamerInfo *info = GetStreamerInfo(clsname, proxy, arroff);
184#endif
185    if (!info)
186        return 0;
187
188    const TString arg(name);
189
190    const Ssiz_t p = arg.Last('.');
191
192    const TString nam = p<0 ? arg : arg(0, p);
193
194    // Get the streamer element to the data member and
195    // and the offset from the base of the object
196    Int_t off;
197    TStreamerElement *el = info->GetStreamerElement(nam, off);
198    if (!el)
199    {
200        *fLog << err << dbginf << "ERROR - No TStreamerElement for " << nam << " [" << clsname << "]" << endl;
201        return 0;
202    }
203
204    const TString type = el->GetTypeNameBasic();
205
206    if (type=="int")
207        return GetMethodCall("Int", arroff+offset+off, proxy);
208    if (type=="Int_t")
209        return GetMethodCall("Int_t", arroff+offset+off, proxy);
210    if (type=="unisgned long long")
211        return GetMethodCall("ULongLong", arroff+offset+off, proxy);
212    if (type=="double")
213    {
214        cout << name << ": " << arroff << " " << offset << " " << off << " " << fPtr << endl;
215
216        return GetMethodCall("Double", arroff+offset+off, proxy);
217    }
218
219    if (p<0)
220    {
221        *fLog << err << dbginf << "ERROR - Variable name missing for " << nam << "." << type << " [" << clsname << "]" << endl;
222        return 0;
223    }
224
225    const TString var = arg(p+1, arg.Length());
226    return GetterMethod(var, type, arroff+offset+off);
227}
228
229// --------------------------------------------------------------------------
230//
231//  Print the requested data from our memory using the streamer info.
232//
233void MParEmulated::Print(TPRegexp &regex, TString clsname, TString prefix, Int_t offset) const
234{
235    Int_t arroff = 0;
236
237#if ROOT_VERSION_CODE<ROOT_VERSION(5,18,00)
238    TStreamerInfo *info = GetStreamerInfo(clsname, arroff);
239#else
240    TVirtualStreamerInfo *info = GetStreamerInfo(clsname, arroff);
241#endif
242    if (!info)
243        return;
244
245    TIter Next(info->GetElements());
246    TStreamerElement *el = 0;
247    while ((el=(TStreamerElement*)Next()))
248    {
249        const TString str = prefix+el->GetName();
250
251        if (str(regex).IsNull())
252            continue;
253
254        if (el->InheritsFrom(TStreamerBasicType::Class()))
255        {
256            const TString type(el->GetTypeNameBasic());
257
258            cout << fName << (arroff?"[0]":"") << "." << str << " [" << type << "]"  << " \t";
259            if (type=="int")
260                cout << GetInt(el->GetOffset()+arroff+offset);
261            if (type=="Int_t")
262                cout << GetInt_t(el->GetOffset()+arroff+offset);
263            if (type=="double")
264                cout << GetDouble(el->GetOffset()+arroff+offset);
265            if (type=="unsigned long long")
266                cout << GetULongLong(el->GetOffset()+arroff+offset);
267
268            cout << endl;
269            continue;
270        }
271
272        if (el->InheritsFrom(TStreamerObjectAny::Class()))
273        {
274            Print(regex, el->GetTypeNameBasic(), str+".",
275                  el->GetOffset()+arroff+offset);
276            continue;
277        }
278    }
279}
Note: See TracBrowser for help on using the repository browser.