Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TXMLPlayer.cxx
Go to the documentation of this file.
1 // @(#)root/xml:$Id$
2 // Author: Sergey Linev, Rene Brun 10.05.2004
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 //________________________________________________________________________
13 //
14 // Class for xml code generation
15 // It should be used for generation of xml streamers, which could be used outside root
16 // environment. This means, that with help of such streamers user can read and write
17 // objects from/to xml file, which later can be accepted by ROOT.
18 //
19 // At the moment supported only classes, which are not inherited from TObject
20 // and which not contains any TObject members.
21 //
22 // To generate xml code:
23 //
24 // 1. ROOT library with required classes should be created.
25 // In general, without such library non of user objects can be stored and
26 // retrieved from any ROOT file
27 //
28 // 2. Generate xml streamers by root script like:
29 //
30 // void generate() {
31 // gSystem->Load("libRXML.so"); // load ROOT xml library
32 // gSystem->Load("libuser.so"); // load user ROOT library
33 //
34 // TList lst;
35 // lst.Add(TClass::GetClass("TUserClass1"));
36 // lst.Add(TClass::GetClass("TUserClass2"));
37 // ...
38 // TXMLPlayer player;
39 // player.ProduceCode(&lst, "streamers"); // create xml streamers
40 // }
41 //
42 // 3. Copy "streamers.h", "streamers.cxx", "TXmlFile.h", "TXmlFile.cxx" files
43 // to user project and compile them. TXmlFile class implementation can be taken
44 // from http://web-docs.gsi.de/~linev/xmlfile.tar.gz
45 //
46 // TXMLPlayer class generates one function per class, which called class streamer.
47 // Name of such function for class TExample will be TExample_streamer.
48 //
49 // Following data members for streamed classes are supported:
50 // - simple data types (int, double, float)
51 // - array of simple types (int[5], double[5][6])
52 // - dynamic array of simple types (int* with comment field // [fSize])
53 // - const char*
54 // - object of any nonROOT class
55 // - pointer on object
56 // - array of objects
57 // - array of pointers on objects
58 // - stl string
59 // - stl vector, list, deque, set, multiset, map, multimap
60 // - allowed arguments for stl containers are: simple data types, string, object, pointer on object
61 // Any other data member can not be (yet) read from xml file and write to xml file.
62 //
63 // If data member of class is private or protected, it can not be accessed via
64 // member name. Two alternative way is supported. First, if for class member fValue
65 // exists function GetValue(), it will be used to get value from the class, and if
66 // exists SetValue(), it will be used to set appropriate data member. Names of setter
67 // and getter methods can be specified in comments filed like:
68 //
69 // int fValue; // *OPTION={GetMethod="GetV";SetMethod="SetV"}
70 //
71 // If getter or setter methods does not available, address to data member will be
72 // calculated as predefined offset to object start address. In that case generated code
73 // should be used only on the same platform (OS + compiler), where it was generated.
74 //
75 // Generated streamers resolve inheritance tree for given class. This allows to have
76 // array (or vector) of object pointers on some basic class, while objects of derived
77 // class(es) are used.
78 //
79 // To access data from xml files, user should use TXmlFile class, which is different from
80 // ROOT TXMLFile, but provides very similar functionality. For example, to read
81 // object from xml file:
82 //
83 // TXmlFile file("test.xml"); // open xml file
84 // file.ls(); // show list of keys in file
85 // TExample* ex1 = (TExample*) file.Get("ex1", TExample_streamer); // get object
86 // file.Close();
87 //
88 // To write object to file:
89 //
90 // TXmlFile outfile("test2.xml", "recreate"); // create xml file
91 // TExample* ex1 = new TExample;
92 // outfile.Write(ex1, "ex1", TExample_streamer); // write object to file
93 // outfile.Close();
94 //
95 // Complete example for generating and using of external xml streamers can be taken from
96 // http://www-docs.gsi.de/~linev/xmlreader.tar.gz
97 //
98 // Any bug reports and requests for additional functionality are welcome.
99 //
100 // Sergey Linev, S.Linev@gsi.de
101 //
102 //________________________________________________________________________
103 
104 #include "TXMLPlayer.h"
105 
106 #include "Riostream.h"
107 #include "TROOT.h"
108 #include "TClass.h"
109 #include "TVirtualStreamerInfo.h"
110 #include "TStreamerElement.h"
111 #include "TObjArray.h"
112 #include "TObjString.h"
113 #include "TDataMember.h"
114 #include "TMethod.h"
115 #include "TDataType.h"
116 #include "TMethodCall.h"
117 #include "TVirtualCollectionProxy.h"
118 #include "TClassEdit.h"
119 #include <string>
120 #include <vector>
121 
122 const char *tab1 = " ";
123 const char *tab2 = " ";
124 const char *tab3 = " ";
125 const char *tab4 = " ";
126 
127 const char *names_xmlfileclass = "TXmlFile";
128 
129 ClassImp(TXMLPlayer);
130 
131 ////////////////////////////////////////////////////////////////////////////////
132 /// default constructor
133 
134 TXMLPlayer::TXMLPlayer() : TObject()
135 {
136 }
137 
138 ////////////////////////////////////////////////////////////////////////////////
139 /// destructor of TXMLPlayer object
140 
141 TXMLPlayer::~TXMLPlayer()
142 {
143 }
144 
145 ////////////////////////////////////////////////////////////////////////////////
146 /// returns streamer function name for given class
147 
148 TString TXMLPlayer::GetStreamerName(TClass *cl)
149 {
150  if (cl == 0)
151  return "";
152  TString res = cl->GetName();
153  res += "_streamer";
154  return res;
155 }
156 
157 ////////////////////////////////////////////////////////////////////////////////
158 /// Produce streamers for provide class list
159 /// TList should include list of classes, for which code should be generated.
160 /// filename specify name of file (without extension), where streamers should be
161 /// created. Function produces two files: header file and source file.
162 /// For instance, if filename is "streamers", files "streamers.h" and "streamers.cxx"
163 /// will be created.
164 
165 Bool_t TXMLPlayer::ProduceCode(TList *cllist, const char *filename)
166 {
167  if ((cllist == 0) || (filename == 0))
168  return kFALSE;
169 
170  std::ofstream fh(TString(filename) + ".h");
171  std::ofstream fs(TString(filename) + ".cxx");
172 
173  fh << "// generated header file" << std::endl << std::endl;
174  fh << "#ifndef " << filename << "_h" << std::endl;
175  fh << "#define " << filename << "_h" << std::endl << std::endl;
176 
177  fh << "#include \"" << names_xmlfileclass << ".h\"" << std::endl << std::endl;
178 
179  fs << "// generated source file" << std::endl << std::endl;
180  fs << "#include \"" << filename << ".h\"" << std::endl << std::endl;
181 
182  // produce appropriate include for all classes
183 
184  TObjArray inclfiles;
185  TIter iter(cllist);
186  TClass *cl = 0;
187  while ((cl = (TClass *)iter()) != 0) {
188  if (inclfiles.FindObject(cl->GetDeclFileName()) == 0) {
189  fs << "#include \"" << cl->GetDeclFileName() << "\"" << std::endl;
190  inclfiles.Add(new TNamed(cl->GetDeclFileName(), ""));
191  }
192  }
193  inclfiles.Delete();
194 
195  fh << std::endl;
196  fs << std::endl;
197 
198  // produce streamers declarations and implementations
199 
200  iter.Reset();
201 
202  while ((cl = (TClass *)iter()) != 0) {
203 
204  fh << "extern void* " << GetStreamerName(cl) << "(" << names_xmlfileclass
205  << " &buf, void* ptr = 0, bool checktypes = true);" << std::endl
206  << std::endl;
207 
208  ProduceStreamerSource(fs, cl, cllist);
209  }
210 
211  fh << "#endif" << std::endl << std::endl;
212  fs << std::endl << std::endl;
213 
214  return kTRUE;
215 }
216 
217 ////////////////////////////////////////////////////////////////////////////////
218 /// returns name of simple data type for given data member
219 
220 TString TXMLPlayer::GetMemberTypeName(TDataMember *member)
221 {
222  if (member == 0)
223  return "int";
224 
225  if (member->IsBasic())
226  switch (member->GetDataType()->GetType()) {
227  case kChar_t: return "char";
228  case kShort_t: return "short";
229  case kInt_t: return "int";
230  case kLong_t: return "long";
231  case kLong64_t: return "long long";
232  case kFloat16_t:
233  case kFloat_t: return "float";
234  case kDouble32_t:
235  case kDouble_t: return "double";
236  case kUChar_t: {
237  char first = member->GetDataType()->GetTypeName()[0];
238  if ((first == 'B') || (first == 'b'))
239  return "bool";
240  return "unsigned char";
241  }
242  case kBool_t: return "bool";
243  case kUShort_t: return "unsigned short";
244  case kUInt_t: return "unsigned int";
245  case kULong_t: return "unsigned long";
246  case kULong64_t: return "unsigned long long";
247  }
248 
249  if (member->IsEnum())
250  return "int";
251 
252  return member->GetTypeName();
253 }
254 
255 ////////////////////////////////////////////////////////////////////////////////
256 /// return simple data types for given TStreamerElement object
257 
258 TString TXMLPlayer::GetBasicTypeName(TStreamerElement *el)
259 {
260  if (el->GetType() == TVirtualStreamerInfo::kCounter)
261  return "int";
262 
263  switch (el->GetType() % 20) {
264  case TVirtualStreamerInfo::kChar: return "char";
265  case TVirtualStreamerInfo::kShort: return "short";
266  case TVirtualStreamerInfo::kInt: return "int";
267  case TVirtualStreamerInfo::kLong: return "long";
268  case TVirtualStreamerInfo::kLong64: return "long long";
269  case TVirtualStreamerInfo::kFloat16:
270  case TVirtualStreamerInfo::kFloat: return "float";
271  case TVirtualStreamerInfo::kDouble32:
272  case TVirtualStreamerInfo::kDouble: return "double";
273  case TVirtualStreamerInfo::kUChar: {
274  char first = el->GetTypeNameBasic()[0];
275  if ((first == 'B') || (first == 'b'))
276  return "bool";
277  return "unsigned char";
278  }
279  case TVirtualStreamerInfo::kBool: return "bool";
280  case TVirtualStreamerInfo::kUShort: return "unsigned short";
281  case TVirtualStreamerInfo::kUInt: return "unsigned int";
282  case TVirtualStreamerInfo::kULong: return "unsigned long";
283  case TVirtualStreamerInfo::kULong64: return "unsigned long long";
284  }
285  return "int";
286 }
287 
288 ////////////////////////////////////////////////////////////////////////////////
289 /// return functions name to read simple data type from xml file
290 
291 TString TXMLPlayer::GetBasicTypeReaderMethodName(Int_t type, const char *realname)
292 {
293  if (type == TVirtualStreamerInfo::kCounter)
294  return "ReadInt";
295 
296  switch (type % 20) {
297  case TVirtualStreamerInfo::kChar: return "ReadChar";
298  case TVirtualStreamerInfo::kShort: return "ReadShort";
299  case TVirtualStreamerInfo::kInt: return "ReadInt";
300  case TVirtualStreamerInfo::kLong: return "ReadLong";
301  case TVirtualStreamerInfo::kLong64: return "ReadLong64";
302  case TVirtualStreamerInfo::kFloat16:
303  case TVirtualStreamerInfo::kFloat: return "ReadFloat";
304  case TVirtualStreamerInfo::kDouble32:
305  case TVirtualStreamerInfo::kDouble: return "ReadDouble";
306  case TVirtualStreamerInfo::kUChar: {
307  Bool_t isbool = false;
308  if (realname != 0)
309  isbool = (TString(realname).Index("bool", 0, TString::kIgnoreCase) >= 0);
310  if (isbool)
311  return "ReadBool";
312  return "ReadUChar";
313  }
314  case TVirtualStreamerInfo::kBool: return "ReadBool";
315  case TVirtualStreamerInfo::kUShort: return "ReadUShort";
316  case TVirtualStreamerInfo::kUInt: return "ReadUInt";
317  case TVirtualStreamerInfo::kULong: return "ReadULong";
318  case TVirtualStreamerInfo::kULong64: return "ReadULong64";
319  }
320  return "ReadValue";
321 }
322 
323 ////////////////////////////////////////////////////////////////////////////////
324 /// produce code to access member of given class.
325 /// Parameter specials has following meaning:
326 /// 0 - nothing special
327 /// 1 - cast to data type
328 /// 2 - produce pointer on given member
329 /// 3 - skip casting when produce pointer by buf.P() function
330 
331 const char *TXMLPlayer::ElementGetter(TClass *cl, const char *membername, int specials)
332 {
333  TClass *membercl = cl ? cl->GetBaseDataMember(membername) : 0;
334  TDataMember *member = membercl ? membercl->GetDataMember(membername) : 0;
335  TMethodCall *mgetter = member ? member->GetterMethod(0) : 0;
336 
337  if ((mgetter != 0) && (mgetter->GetMethod()->Property() & kIsPublic)) {
338  fGetterName = "obj->";
339  fGetterName += mgetter->GetMethodName();
340  fGetterName += "()";
341  } else if ((member == 0) || ((member->Property() & kIsPublic) != 0)) {
342  fGetterName = "obj->";
343  fGetterName += membername;
344  } else {
345  fGetterName = "";
346  Bool_t deref = (member->GetArrayDim() == 0) && (specials != 2);
347  if (deref)
348  fGetterName += "*(";
349  if (specials != 3) {
350  fGetterName += "(";
351  if (member->Property() & kIsConstant)
352  fGetterName += "const ";
353  fGetterName += GetMemberTypeName(member);
354  if (member->IsaPointer())
355  fGetterName += "*";
356  fGetterName += "*) ";
357  }
358  fGetterName += "buf.P(obj,";
359  fGetterName += member->GetOffset();
360  fGetterName += ")";
361  if (deref)
362  fGetterName += ")";
363  specials = 0;
364  }
365 
366  if ((specials == 1) && (member != 0)) {
367  TString cast = "(";
368  cast += GetMemberTypeName(member);
369  if (member->IsaPointer() || (member->GetArrayDim() > 0))
370  cast += "*";
371  cast += ") ";
372  cast += fGetterName;
373  fGetterName = cast;
374  }
375 
376  if ((specials == 2) && (member != 0)) {
377  TString buf = "&(";
378  buf += fGetterName;
379  buf += ")";
380  fGetterName = buf;
381  }
382 
383  return fGetterName.Data();
384 }
385 
386 ////////////////////////////////////////////////////////////////////////////////
387 /// Produce code to set value to given data member.
388 /// endch should be output after value is specified.
389 
390 const char *TXMLPlayer::ElementSetter(TClass *cl, const char *membername, char *endch)
391 {
392  strcpy(endch, "");
393 
394  TClass *membercl = cl ? cl->GetBaseDataMember(membername) : 0;
395  TDataMember *member = membercl ? membercl->GetDataMember(membername) : 0;
396  TMethodCall *msetter = member ? member->SetterMethod(cl) : 0;
397 
398  if ((msetter != 0) && (msetter->GetMethod()->Property() & kIsPublic)) {
399  fSetterName = "obj->";
400  fSetterName += msetter->GetMethodName();
401  fSetterName += "(";
402  strcpy(endch, ")");
403  } else if ((member == 0) || (member->Property() & kIsPublic) != 0) {
404  fSetterName = "obj->";
405  fSetterName += membername;
406  fSetterName += " = ";
407  } else {
408  fSetterName = "";
409  if (member->GetArrayDim() == 0)
410  fSetterName += "*";
411  fSetterName += "((";
412  if (member->Property() & kIsConstant)
413  fSetterName += "const ";
414  fSetterName += GetMemberTypeName(member);
415  if (member->IsaPointer())
416  fSetterName += "*";
417  fSetterName += "*) buf.P(obj,";
418  fSetterName += member->GetOffset();
419  fSetterName += ")) = ";
420  }
421  return fSetterName.Data();
422 }
423 
424 ////////////////////////////////////////////////////////////////////////////////
425 /// Produce source code of streamer function for specified class
426 
427 void TXMLPlayer::ProduceStreamerSource(std::ostream &fs, TClass *cl, TList *cllist)
428 {
429  if (cl == 0)
430  return;
431  TVirtualStreamerInfo *info = cl->GetStreamerInfo();
432  TObjArray *elements = info->GetElements();
433  if (elements == 0)
434  return;
435 
436  fs << "//__________________________________________________________________________" << std::endl;
437  fs << "void* " << GetStreamerName(cl) << "(" << names_xmlfileclass << " &buf, void* ptr, bool checktypes)"
438  << std::endl;
439  fs << "{" << std::endl;
440  fs << tab1 << cl->GetName() << " *obj = (" << cl->GetName() << "*) ptr;" << std::endl;
441 
442  fs << tab1 << "if (buf.IsReading()) { " << std::endl;
443 
444  TIter iter(cllist);
445  TClass *c1 = 0;
446  Bool_t firstchild = true;
447 
448  while ((c1 = (TClass *)iter()) != 0) {
449  if (c1 == cl)
450  continue;
451  if (c1->GetListOfBases()->FindObject(cl->GetName()) == 0)
452  continue;
453  if (firstchild) {
454  fs << tab2 << "if (checktypes) {" << std::endl;
455  fs << tab3 << "void* ";
456  firstchild = false;
457  } else
458  fs << tab3;
459  fs << "res = " << GetStreamerName(c1) << "(buf, dynamic_cast<" << c1->GetName() << "*>(obj));" << std::endl;
460  fs << tab3 << "if (res) return dynamic_cast<" << cl->GetName() << "*>((" << c1->GetName() << " *) res);"
461  << std::endl;
462  }
463  if (!firstchild)
464  fs << tab2 << "}" << std::endl;
465 
466  fs << tab2 << "if (!buf.CheckClassNode(\"" << cl->GetName() << "\", " << info->GetClassVersion() << ")) return 0;"
467  << std::endl;
468 
469  fs << tab2 << "if (obj==0) obj = new " << cl->GetName() << ";" << std::endl;
470 
471  int n;
472  for (n = 0; n <= elements->GetLast(); n++) {
473 
474  TStreamerElement *el = dynamic_cast<TStreamerElement *>(elements->At(n));
475  if (el == 0)
476  continue;
477 
478  Int_t typ = el->GetType();
479 
480  switch (typ) {
481  // basic types
482  case TVirtualStreamerInfo::kBool:
483  case TVirtualStreamerInfo::kChar:
484  case TVirtualStreamerInfo::kShort:
485  case TVirtualStreamerInfo::kInt:
486  case TVirtualStreamerInfo::kLong:
487  case TVirtualStreamerInfo::kLong64:
488  case TVirtualStreamerInfo::kFloat:
489  case TVirtualStreamerInfo::kFloat16:
490  case TVirtualStreamerInfo::kDouble:
491  case TVirtualStreamerInfo::kUChar:
492  case TVirtualStreamerInfo::kUShort:
493  case TVirtualStreamerInfo::kUInt:
494  case TVirtualStreamerInfo::kULong:
495  case TVirtualStreamerInfo::kULong64:
496  case TVirtualStreamerInfo::kDouble32:
497  case TVirtualStreamerInfo::kCounter: {
498  char endch[5];
499  fs << tab2 << ElementSetter(cl, el->GetName(), endch);
500  fs << "buf." << GetBasicTypeReaderMethodName(el->GetType(), 0) << "(\"" << el->GetName() << "\")" << endch
501  << ";" << std::endl;
502  continue;
503  }
504 
505  // array of basic types like bool[10]
506  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kBool:
507  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kChar:
508  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kShort:
509  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kInt:
510  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kLong:
511  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kLong64:
512  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kFloat:
513  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kFloat16:
514  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kDouble:
515  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUChar:
516  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUShort:
517  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUInt:
518  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kULong:
519  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kULong64:
520  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kDouble32: {
521  fs << tab2 << "buf.ReadArray(" << ElementGetter(cl, el->GetName(), (el->GetArrayDim() > 1) ? 1 : 0);
522  fs << ", " << el->GetArrayLength() << ", \"" << el->GetName() << "\");" << std::endl;
523  continue;
524  }
525 
526  // array of basic types like bool[n]
527  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kBool:
528  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kChar:
529  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kShort:
530  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kInt:
531  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kLong:
532  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kLong64:
533  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kFloat:
534  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kFloat16:
535  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kDouble:
536  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUChar:
537  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUShort:
538  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUInt:
539  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kULong:
540  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kULong64:
541  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kDouble32: {
542  TStreamerBasicPointer *elp = dynamic_cast<TStreamerBasicPointer *>(el);
543  if (elp == 0) {
544  std::cout << "fatal error with TStreamerBasicPointer" << std::endl;
545  continue;
546  }
547  char endch[5];
548 
549  fs << tab2 << ElementSetter(cl, el->GetName(), endch);
550  fs << "buf.ReadArray(" << ElementGetter(cl, el->GetName());
551  fs << ", " << ElementGetter(cl, elp->GetCountName());
552  fs << ", \"" << el->GetName() << "\", true)" << endch << ";" << std::endl;
553  continue;
554  }
555 
556  case TVirtualStreamerInfo::kCharStar: {
557  char endch[5];
558  fs << tab2 << ElementSetter(cl, el->GetName(), endch);
559  fs << "buf.ReadCharStar(" << ElementGetter(cl, el->GetName());
560  fs << ", \"" << el->GetName() << "\")" << endch << ";" << std::endl;
561  continue;
562  }
563 
564  case TVirtualStreamerInfo::kBase: {
565  fs << tab2 << GetStreamerName(el->GetClassPointer()) << "(buf, dynamic_cast<"
566  << el->GetClassPointer()->GetName() << "*>(obj), false);" << std::endl;
567  continue;
568  }
569 
570  // Class* Class not derived from TObject and with comment field //->
571  case TVirtualStreamerInfo::kAnyp:
572  case TVirtualStreamerInfo::kAnyp + TVirtualStreamerInfo::kOffsetL: {
573  if (el->GetArrayLength() > 0) {
574  fs << tab2 << "buf.ReadObjectArr(" << ElementGetter(cl, el->GetName());
575  fs << ", " << el->GetArrayLength() << ", -1"
576  << ", \"" << el->GetName() << "\", " << GetStreamerName(el->GetClassPointer()) << ");" << std::endl;
577  } else {
578  fs << tab2 << "buf.ReadObject(" << ElementGetter(cl, el->GetName());
579  fs << ", \"" << el->GetName() << "\", " << GetStreamerName(el->GetClassPointer()) << ");" << std::endl;
580  }
581  continue;
582  }
583 
584  // Class* Class not derived from TObject and no comment
585  case TVirtualStreamerInfo::kAnyP:
586  case TVirtualStreamerInfo::kAnyP + TVirtualStreamerInfo::kOffsetL: {
587  if (el->GetArrayLength() > 0) {
588  fs << tab2 << "for (int n=0;n<" << el->GetArrayLength() << ";n++) "
589  << "delete (" << ElementGetter(cl, el->GetName()) << ")[n];" << std::endl;
590  fs << tab2 << "buf.ReadObjectPtrArr((void**) " << ElementGetter(cl, el->GetName(), 3);
591  fs << ", " << el->GetArrayLength() << ", \"" << el->GetName() << "\", "
592  << GetStreamerName(el->GetClassPointer()) << ");" << std::endl;
593  } else {
594  char endch[5];
595 
596  fs << tab2 << "delete " << ElementGetter(cl, el->GetName()) << ";" << std::endl;
597  fs << tab2 << ElementSetter(cl, el->GetName(), endch);
598  fs << "(" << el->GetClassPointer()->GetName() << "*) buf.ReadObjectPtr(\"" << el->GetName() << "\", "
599  << GetStreamerName(el->GetClassPointer()) << ")" << endch << ";" << std::endl;
600  }
601  continue;
602  }
603 
604  // Class NOT derived from TObject
605  case TVirtualStreamerInfo::kAny: {
606  fs << tab2 << "buf.ReadObject(" << ElementGetter(cl, el->GetName(), 2);
607  fs << ", \"" << el->GetName() << "\", " << GetStreamerName(el->GetClassPointer()) << ");" << std::endl;
608  continue;
609  }
610 
611  // Class NOT derived from TObject, array
612  case TVirtualStreamerInfo::kAny + TVirtualStreamerInfo::kOffsetL: {
613  fs << tab2 << "buf.ReadObjectArr(" << ElementGetter(cl, el->GetName());
614  fs << ", " << el->GetArrayLength() << ", sizeof(" << el->GetClassPointer()->GetName() << "), \""
615  << el->GetName() << "\", " << GetStreamerName(el->GetClassPointer()) << ");" << std::endl;
616  continue;
617  }
618 
619  // container with no virtual table (stl) and no comment
620  case TVirtualStreamerInfo::kSTLp:
621  case TVirtualStreamerInfo::kSTL:
622  case TVirtualStreamerInfo::kSTLp + TVirtualStreamerInfo::kOffsetL:
623  case TVirtualStreamerInfo::kSTL + TVirtualStreamerInfo::kOffsetL: {
624  TStreamerSTL *elstl = dynamic_cast<TStreamerSTL *>(el);
625  if (elstl == 0)
626  break; // to make skip
627 
628  if (ProduceSTLstreamer(fs, cl, elstl, false))
629  continue;
630 
631  fs << tab2 << "// STL type = " << elstl->GetSTLtype() << std::endl;
632  break;
633  }
634  }
635  fs << tab2 << "buf.SkipMember(\"" << el->GetName() << "\"); // sinfo type " << el->GetType() << " of class "
636  << el->GetClassPointer()->GetName() << " not supported" << std::endl;
637  }
638 
639  fs << tab2 << "buf.EndClassNode();" << std::endl;
640 
641  fs << tab1 << "} else {" << std::endl;
642 
643  // generation of writing part of class streamer
644 
645  fs << tab2 << "if (obj==0) return 0;" << std::endl;
646 
647  firstchild = true;
648  iter.Reset();
649  while ((c1 = (TClass *)iter()) != 0) {
650  if (c1 == cl)
651  continue;
652  if (c1->GetListOfBases()->FindObject(cl->GetName()) == 0)
653  continue;
654  if (firstchild) {
655  firstchild = false;
656  fs << tab2 << "if (checktypes) {" << std::endl;
657  }
658  fs << tab3 << "if (dynamic_cast<" << c1->GetName() << "*>(obj))" << std::endl;
659  fs << tab4 << "return " << GetStreamerName(c1) << "(buf, dynamic_cast<" << c1->GetName() << "*>(obj));"
660  << std::endl;
661  }
662  if (!firstchild)
663  fs << tab2 << "}" << std::endl;
664 
665  fs << tab2 << "buf.StartClassNode(\"" << cl->GetName() << "\", " << info->GetClassVersion() << ");" << std::endl;
666 
667  for (n = 0; n <= elements->GetLast(); n++) {
668 
669  TStreamerElement *el = dynamic_cast<TStreamerElement *>(elements->At(n));
670  if (el == 0)
671  continue;
672 
673  Int_t typ = el->GetType();
674 
675  switch (typ) {
676  // write basic types
677  case TVirtualStreamerInfo::kBool:
678  case TVirtualStreamerInfo::kChar:
679  case TVirtualStreamerInfo::kShort:
680  case TVirtualStreamerInfo::kInt:
681  case TVirtualStreamerInfo::kLong:
682  case TVirtualStreamerInfo::kLong64:
683  case TVirtualStreamerInfo::kFloat:
684  case TVirtualStreamerInfo::kFloat16:
685  case TVirtualStreamerInfo::kDouble:
686  case TVirtualStreamerInfo::kUChar:
687  case TVirtualStreamerInfo::kUShort:
688  case TVirtualStreamerInfo::kUInt:
689  case TVirtualStreamerInfo::kULong:
690  case TVirtualStreamerInfo::kULong64:
691  case TVirtualStreamerInfo::kDouble32:
692  case TVirtualStreamerInfo::kCounter: {
693  fs << tab2 << "buf.WriteValue(";
694  if (typ == TVirtualStreamerInfo::kUChar)
695  fs << "(unsigned char) " << ElementGetter(cl, el->GetName());
696  else
697  fs << ElementGetter(cl, el->GetName());
698  fs << ", \"" << el->GetName() << "\");" << std::endl;
699  continue;
700  }
701 
702  // array of basic types
703  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kBool:
704  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kChar:
705  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kShort:
706  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kInt:
707  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kLong:
708  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kLong64:
709  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kFloat:
710  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kFloat16:
711  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kDouble:
712  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUChar:
713  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUShort:
714  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUInt:
715  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kULong:
716  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kULong64:
717  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kDouble32: {
718  fs << tab2 << "buf.WriteArray(" << ElementGetter(cl, el->GetName(), (el->GetArrayDim() > 1) ? 1 : 0);
719  fs << ", " << el->GetArrayLength() << ", \"" << el->GetName() << "\");" << std::endl;
720  continue;
721  }
722 
723  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kBool:
724  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kChar:
725  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kShort:
726  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kInt:
727  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kLong:
728  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kLong64:
729  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kFloat:
730  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kFloat16:
731  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kDouble:
732  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUChar:
733  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUShort:
734  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUInt:
735  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kULong:
736  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kULong64:
737  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kDouble32: {
738  TStreamerBasicPointer *elp = dynamic_cast<TStreamerBasicPointer *>(el);
739  if (elp == 0) {
740  std::cout << "fatal error with TStreamerBasicPointer" << std::endl;
741  continue;
742  }
743  fs << tab2 << "buf.WriteArray(" << ElementGetter(cl, el->GetName());
744  fs << ", " << ElementGetter(cl, elp->GetCountName()) << ", \"" << el->GetName() << "\", true);" << std::endl;
745  continue;
746  }
747 
748  case TVirtualStreamerInfo::kCharStar: {
749  fs << tab2 << "buf.WriteCharStar(" << ElementGetter(cl, el->GetName()) << ", \"" << el->GetName() << "\");"
750  << std::endl;
751  continue;
752  }
753 
754  case TVirtualStreamerInfo::kBase: {
755  fs << tab2 << GetStreamerName(el->GetClassPointer()) << "(buf, dynamic_cast<"
756  << el->GetClassPointer()->GetName() << "*>(obj), false);" << std::endl;
757  continue;
758  }
759 
760  // Class* Class not derived from TObject and with comment field //->
761  case TVirtualStreamerInfo::kAnyp:
762  case TVirtualStreamerInfo::kAnyp + TVirtualStreamerInfo::kOffsetL: {
763  if (el->GetArrayLength() > 0) {
764  fs << tab2 << "buf.WriteObjectArr(" << ElementGetter(cl, el->GetName());
765  fs << ", " << el->GetArrayLength() << ", -1"
766  << ", \"" << el->GetName() << "\", " << GetStreamerName(el->GetClassPointer()) << ");" << std::endl;
767  } else {
768  fs << tab2 << "buf.WriteObject(" << ElementGetter(cl, el->GetName());
769  fs << ", \"" << el->GetName() << "\", " << GetStreamerName(el->GetClassPointer()) << ");" << std::endl;
770  }
771  continue;
772  }
773 
774  // Class* Class not derived from TObject and no comment
775  case TVirtualStreamerInfo::kAnyP:
776  case TVirtualStreamerInfo::kAnyP + TVirtualStreamerInfo::kOffsetL: {
777  if (el->GetArrayLength() > 0) {
778  fs << tab2 << "buf.WriteObjectPtrArr((void**) " << ElementGetter(cl, el->GetName(), 3);
779  fs << ", " << el->GetArrayLength() << ", \"" << el->GetName() << "\", "
780  << GetStreamerName(el->GetClassPointer()) << ");" << std::endl;
781  } else {
782  fs << tab2 << "buf.WriteObjectPtr(" << ElementGetter(cl, el->GetName());
783  fs << ", \"" << el->GetName() << "\", " << GetStreamerName(el->GetClassPointer()) << ");" << std::endl;
784  }
785  continue;
786  }
787 
788  case TVirtualStreamerInfo::kAny: { // Class NOT derived from TObject
789  fs << tab2 << "buf.WriteObject(" << ElementGetter(cl, el->GetName(), 2);
790  fs << ", \"" << el->GetName() << "\", " << GetStreamerName(el->GetClassPointer()) << ");" << std::endl;
791  continue;
792  }
793 
794  case TVirtualStreamerInfo::kAny + TVirtualStreamerInfo::kOffsetL: {
795  fs << tab2 << "buf.WriteObjectArr(" << ElementGetter(cl, el->GetName());
796  fs << ", " << el->GetArrayLength() << ", sizeof(" << el->GetClassPointer()->GetName() << "), \""
797  << el->GetName() << "\", " << GetStreamerName(el->GetClassPointer()) << ");" << std::endl;
798  continue;
799  }
800 
801  // container with no virtual table (stl) and no comment
802  case TVirtualStreamerInfo::kSTLp + TVirtualStreamerInfo::kOffsetL:
803  case TVirtualStreamerInfo::kSTL + TVirtualStreamerInfo::kOffsetL:
804  case TVirtualStreamerInfo::kSTLp:
805  case TVirtualStreamerInfo::kSTL: {
806  TStreamerSTL *elstl = dynamic_cast<TStreamerSTL *>(el);
807  if (elstl == 0)
808  break; // to make skip
809 
810  if (ProduceSTLstreamer(fs, cl, elstl, true))
811  continue;
812  fs << tab2 << "// STL type = " << elstl->GetSTLtype() << std::endl;
813  break;
814  }
815  }
816  fs << tab2 << "buf.MakeEmptyMember(\"" << el->GetName() << "\"); // sinfo type " << el->GetType()
817  << " of class " << el->GetClassPointer()->GetName() << " not supported" << std::endl;
818  }
819 
820  fs << tab2 << "buf.EndClassNode();" << std::endl;
821 
822  fs << tab1 << "}" << std::endl;
823  fs << tab1 << "return obj;" << std::endl;
824  fs << "}" << std::endl << std::endl;
825 }
826 
827 ////////////////////////////////////////////////////////////////////////////////
828 /// Produce code to read argument of stl container from xml file
829 
830 void TXMLPlayer::ReadSTLarg(std::ostream &fs, TString &argname, int argtyp, Bool_t isargptr, TClass *argcl,
831  TString &tname, TString &ifcond)
832 {
833  switch (argtyp) {
834  case TVirtualStreamerInfo::kBool:
835  case TVirtualStreamerInfo::kChar:
836  case TVirtualStreamerInfo::kShort:
837  case TVirtualStreamerInfo::kInt:
838  case TVirtualStreamerInfo::kLong:
839  case TVirtualStreamerInfo::kLong64:
840  case TVirtualStreamerInfo::kFloat:
841  case TVirtualStreamerInfo::kFloat16:
842  case TVirtualStreamerInfo::kDouble:
843  case TVirtualStreamerInfo::kUChar:
844  case TVirtualStreamerInfo::kUShort:
845  case TVirtualStreamerInfo::kUInt:
846  case TVirtualStreamerInfo::kULong:
847  case TVirtualStreamerInfo::kULong64:
848  case TVirtualStreamerInfo::kDouble32:
849  case TVirtualStreamerInfo::kCounter: {
850  fs << tname << " " << argname << " = buf." << GetBasicTypeReaderMethodName(argtyp, tname.Data()) << "(0);"
851  << std::endl;
852  break;
853  }
854 
855  case TVirtualStreamerInfo::kObject: {
856  fs << tname << (isargptr ? " " : " *") << argname << " = "
857  << "(" << argcl->GetName() << "*)"
858  << "buf.ReadObjectPtr(0, " << GetStreamerName(argcl) << ");" << std::endl;
859  if (!isargptr) {
860  if (ifcond.Length() > 0)
861  ifcond += " && ";
862  ifcond += argname;
863  TString buf = "*";
864  buf += argname;
865  argname = buf;
866  }
867  break;
868  }
869 
870  case TVirtualStreamerInfo::kSTLstring: {
871  fs << "string *" << argname << " = "
872  << "buf.ReadSTLstring();" << std::endl;
873  if (!isargptr) {
874  if (ifcond.Length() > 0)
875  ifcond += " && ";
876  ifcond += argname;
877  TString buf = "*";
878  buf += argname;
879  argname = buf;
880  }
881  break;
882  }
883 
884  default: fs << "/* argument " << argname << " not supported */";
885  }
886 }
887 
888 ////////////////////////////////////////////////////////////////////////////////
889 /// Produce code to write argument of stl container to xml file
890 
891 void TXMLPlayer::WriteSTLarg(std::ostream &fs, const char *accname, int argtyp, Bool_t isargptr, TClass *argcl)
892 {
893  switch (argtyp) {
894  case TVirtualStreamerInfo::kBool:
895  case TVirtualStreamerInfo::kChar:
896  case TVirtualStreamerInfo::kShort:
897  case TVirtualStreamerInfo::kInt:
898  case TVirtualStreamerInfo::kLong:
899  case TVirtualStreamerInfo::kLong64:
900  case TVirtualStreamerInfo::kFloat:
901  case TVirtualStreamerInfo::kFloat16:
902  case TVirtualStreamerInfo::kDouble:
903  case TVirtualStreamerInfo::kUChar:
904  case TVirtualStreamerInfo::kUShort:
905  case TVirtualStreamerInfo::kUInt:
906  case TVirtualStreamerInfo::kULong:
907  case TVirtualStreamerInfo::kULong64:
908  case TVirtualStreamerInfo::kDouble32:
909  case TVirtualStreamerInfo::kCounter: {
910  fs << "buf.WriteValue(" << accname << ", 0);" << std::endl;
911  break;
912  }
913 
914  case TVirtualStreamerInfo::kObject: {
915  fs << "buf.WriteObjectPtr(";
916  if (isargptr)
917  fs << accname;
918  else
919  fs << "&(" << accname << ")";
920  fs << ", 0, " << GetStreamerName(argcl) << ");" << std::endl;
921  break;
922  }
923 
924  case TVirtualStreamerInfo::kSTLstring: {
925  fs << "buf.WriteSTLstring(";
926  if (isargptr)
927  fs << accname;
928  else
929  fs << "&(" << accname << ")";
930  fs << ");" << std::endl;
931  break;
932  }
933 
934  default: fs << "/* argument not supported */" << std::endl;
935  }
936 }
937 
938 ////////////////////////////////////////////////////////////////////////////////
939 /// Produce code of xml streamer for data member of stl type
940 
941 Bool_t TXMLPlayer::ProduceSTLstreamer(std::ostream &fs, TClass *cl, TStreamerSTL *el, Bool_t isWriting)
942 {
943  if ((cl == 0) || (el == 0))
944  return false;
945 
946  TClass *contcl = el->GetClassPointer();
947 
948  Bool_t isstr = (el->GetSTLtype() == ROOT::kSTLstring);
949  Bool_t isptr = el->IsaPointer();
950  Bool_t isarr = (el->GetArrayLength() > 0);
951  Bool_t isparent = (strcmp(el->GetName(), contcl->GetName()) == 0);
952 
953  int stltyp = -1;
954  int narg = 0;
955  int argtype[2];
956  Bool_t isargptr[2];
957  TClass *argcl[2];
958  TString argtname[2];
959 
960  if (!isstr && contcl->GetCollectionType() != ROOT::kNotSTL) {
961  int nestedLoc = 0;
962  std::vector<std::string> splitName;
963  TClassEdit::GetSplit(contcl->GetName(), splitName, nestedLoc);
964 
965  stltyp = contcl->GetCollectionType();
966  switch (stltyp) {
967  case ROOT::kSTLvector: narg = 1; break;
968  case ROOT::kSTLlist: narg = 1; break;
969  case ROOT::kSTLforwardlist: narg = 1; break;
970  case ROOT::kSTLdeque: narg = 1; break;
971  case ROOT::kSTLmap: narg = 2; break;
972  case ROOT::kSTLmultimap: narg = 2; break;
973  case ROOT::kSTLset: narg = 1; break;
974  case ROOT::kSTLmultiset: narg = 1; break;
975  case ROOT::kSTLunorderedset: narg = 1; break;
976  case ROOT::kSTLunorderedmultiset: narg = 1; break;
977  case ROOT::kSTLunorderedmap: narg = 2; break;
978  case ROOT::kSTLunorderedmultimap: narg = 2; break;
979 
980  default: return false;
981  }
982 
983  for (int n = 0; n < narg; n++) {
984  argtype[n] = -1;
985  isargptr[n] = false;
986  argcl[n] = 0;
987  argtname[n] = "";
988 
989  TString buf = splitName[n + 1];
990 
991  argtname[n] = buf;
992 
993  // nested STL containers not yet supported
994  if (TClassEdit::IsSTLCont(buf.Data()))
995  return false;
996 
997  int pstar = buf.Index("*");
998 
999  if (pstar > 0) {
1000  isargptr[n] = true;
1001  pstar--;
1002  while ((pstar > 0) && (buf[pstar] == ' '))
1003  pstar--;
1004  buf.Remove(pstar + 1);
1005  } else
1006  isargptr[n] = false;
1007 
1008  if (buf.Index("const ") == 0) {
1009  buf.Remove(0, 6);
1010  while ((buf.Length() > 0) && (buf[0] == ' '))
1011  buf.Remove(0, 1);
1012  }
1013 
1014  TDataType *dt = (TDataType *)gROOT->GetListOfTypes()->FindObject(buf);
1015  if (dt)
1016  argtype[n] = dt->GetType();
1017  else if (buf == "string")
1018  argtype[n] = TVirtualStreamerInfo::kSTLstring;
1019  else {
1020  argcl[n] = TClass::GetClass(buf);
1021  if (argcl[n] != 0)
1022  argtype[n] = TVirtualStreamerInfo::kObject;
1023  }
1024  if (argtype[n] < 0)
1025  stltyp = -1;
1026  } // for narg
1027 
1028  if (stltyp < 0)
1029  return false;
1030  }
1031 
1032  Bool_t akaarrayaccess = (narg == 1) && (argtype[0] < 20);
1033 
1034  char tabs[30], tabs2[30];
1035 
1036  if (isWriting) {
1037 
1038  fs << tab2 << "if (buf.StartSTLnode(\"" << fXmlSetup.XmlGetElementName(el) << "\")) {" << std::endl;
1039 
1040  fs << tab3 << contcl->GetName() << " ";
1041 
1042  TString accname;
1043  if (isptr) {
1044  if (isarr) {
1045  fs << "**cont";
1046  accname = "(*cont)->";
1047  } else {
1048  fs << "*cont";
1049  accname = "cont->";
1050  }
1051  } else if (isarr) {
1052  fs << "*cont";
1053  accname = "cont->";
1054  } else {
1055  fs << "&cont";
1056  accname = "cont.";
1057  }
1058 
1059  fs << " = ";
1060 
1061  if (isparent)
1062  fs << "*dynamic_cast<" << contcl->GetName() << "*>(obj);" << std::endl;
1063  else
1064  fs << ElementGetter(cl, el->GetName()) << ";" << std::endl;
1065 
1066  if (isarr && el->GetArrayLength()) {
1067  strlcpy(tabs, tab4, sizeof(tabs));
1068  fs << tab3 << "for(int n=0;n<" << el->GetArrayLength() << ";n++) {" << std::endl;
1069  } else
1070  strlcpy(tabs, tab3, sizeof(tabs));
1071 
1072  strlcpy(tabs2, tabs, sizeof(tabs2));
1073 
1074  if (isptr) {
1075  strlcat(tabs2, tab1, sizeof(tabs2));
1076  fs << tabs << "if (" << (isarr ? "*cont" : "cont") << "==0) {" << std::endl;
1077  fs << tabs2 << "buf.WriteSTLsize(0" << (isstr ? ",true);" : ");") << std::endl;
1078  fs << tabs << "} else {" << std::endl;
1079  }
1080 
1081  fs << tabs2 << "buf.WriteSTLsize(" << accname << (isstr ? "length(), true);" : "size());") << std::endl;
1082 
1083  if (isstr) {
1084  fs << tabs2 << "buf.WriteSTLstringData(" << accname << "c_str());" << std::endl;
1085  } else {
1086  if (akaarrayaccess) {
1087  fs << tabs2 << argtname[0] << "* arr = new " << argtname[0] << "[" << accname << "size()];" << std::endl;
1088  fs << tabs2 << "int k = 0;" << std::endl;
1089  }
1090 
1091  fs << tabs2 << contcl->GetName() << "::const_iterator iter;" << std::endl;
1092  fs << tabs2 << "for (iter = " << accname << "begin(); iter != " << accname << "end(); iter++)";
1093  if (akaarrayaccess) {
1094  fs << std::endl << tabs2 << tab1 << "arr[k++] = *iter;" << std::endl;
1095  fs << tabs2 << "buf.WriteArray(arr, " << accname << "size(), 0, false);" << std::endl;
1096  fs << tabs2 << "delete[] arr;" << std::endl;
1097  } else if (narg == 1) {
1098  fs << std::endl << tabs2 << tab1;
1099  WriteSTLarg(fs, "*iter", argtype[0], isargptr[0], argcl[0]);
1100  } else if (narg == 2) {
1101  fs << " {" << std::endl;
1102  fs << tabs2 << tab1;
1103  WriteSTLarg(fs, "iter->first", argtype[0], isargptr[0], argcl[0]);
1104  fs << tabs2 << tab1;
1105  WriteSTLarg(fs, "iter->second", argtype[1], isargptr[1], argcl[1]);
1106  fs << tabs2 << "}" << std::endl;
1107  }
1108  } // if (isstr)
1109 
1110  if (isptr)
1111  fs << tabs << "}" << std::endl;
1112 
1113  if (isarr && el->GetArrayLength()) {
1114  if (isptr)
1115  fs << tabs << "cont++;" << std::endl;
1116  else
1117  fs << tabs << "(void*) cont = (char*) cont + sizeof(" << contcl->GetName() << ");" << std::endl;
1118  fs << tab3 << "}" << std::endl;
1119  }
1120 
1121  fs << tab3 << "buf.EndSTLnode();" << std::endl;
1122  fs << tab2 << "}" << std::endl;
1123 
1124  } else {
1125 
1126  fs << tab2 << "if (buf.VerifySTLnode(\"" << fXmlSetup.XmlGetElementName(el) << "\")) {" << std::endl;
1127 
1128  fs << tab3 << contcl->GetName() << " ";
1129  TString accname, accptr;
1130  if (isptr) {
1131  if (isarr) {
1132  fs << "**cont";
1133  accname = "(*cont)->";
1134  accptr = "*cont";
1135  } else {
1136  fs << "*cont";
1137  accname = "cont->";
1138  accptr = "cont";
1139  }
1140  } else if (isarr) {
1141  fs << "*cont";
1142  accname = "cont->";
1143  } else {
1144  fs << "&cont";
1145  accname = "cont.";
1146  }
1147 
1148  fs << " = ";
1149 
1150  if (isparent)
1151  fs << "*dynamic_cast<" << contcl->GetName() << "*>(obj);" << std::endl;
1152  else
1153  fs << ElementGetter(cl, el->GetName()) << ";" << std::endl;
1154 
1155  if (isarr && el->GetArrayLength()) {
1156  strlcpy(tabs, tab4, sizeof(tabs));
1157  fs << tab3 << "for(int n=0;n<" << el->GetArrayLength() << ";n++) {" << std::endl;
1158  } else
1159  strlcpy(tabs, tab3, sizeof(tabs));
1160 
1161  fs << tabs << "int size = buf.ReadSTLsize(" << (isstr ? "true);" : ");") << std::endl;
1162 
1163  if (isptr) {
1164  fs << tabs << "delete " << accptr << ";" << std::endl;
1165  fs << tabs << "if (size==0) " << accptr << " = 0;" << std::endl;
1166  fs << tabs << " else " << accptr << " = new " << contcl->GetName() << ";" << std::endl;
1167  if (!isarr) {
1168  char endch[5];
1169  fs << tabs << ElementSetter(cl, el->GetName(), endch);
1170  fs << "cont" << endch << ";" << std::endl;
1171  }
1172  } else {
1173  fs << tabs << accname << (isstr ? "erase();" : "clear();") << std::endl;
1174  }
1175 
1176  if (isstr) {
1177  fs << tabs << "if (size>0) " << accname << "assign(buf.ReadSTLstringData(size));" << std::endl;
1178  } else {
1179  if (akaarrayaccess) {
1180  fs << tabs << argtname[0] << "* arr = new " << argtname[0] << "[size];" << std::endl;
1181  fs << tabs << "buf.ReadArray(arr, size, 0, false);" << std::endl;
1182  }
1183 
1184  fs << tabs << "for(int k=0;k<size;k++)";
1185 
1186  if (akaarrayaccess) {
1187  fs << std::endl << tabs << tab1 << accname;
1188  if ((stltyp == ROOT::kSTLset) || (stltyp == ROOT::kSTLmultiset))
1189  fs << "insert";
1190  else
1191  fs << "push_back";
1192  fs << "(arr[k]);" << std::endl;
1193  fs << tabs << "delete[] arr;" << std::endl;
1194  } else if (narg == 1) {
1195  TString arg1("arg"), ifcond;
1196  fs << " {" << std::endl << tabs << tab1;
1197  ReadSTLarg(fs, arg1, argtype[0], isargptr[0], argcl[0], argtname[0], ifcond);
1198  fs << tabs << tab1;
1199  if (ifcond.Length() > 0)
1200  fs << "if (" << ifcond << ") ";
1201  fs << accname;
1202  if ((stltyp == ROOT::kSTLset) || (stltyp == ROOT::kSTLmultiset))
1203  fs << "insert";
1204  else
1205  fs << "push_back";
1206  fs << "(" << arg1 << ");" << std::endl;
1207  fs << tabs << "}" << std::endl;
1208  } else if (narg == 2) {
1209  TString arg1("arg1"), arg2("arg2"), ifcond;
1210  fs << " {" << std::endl << tabs << tab1;
1211  ReadSTLarg(fs, arg1, argtype[0], isargptr[0], argcl[0], argtname[0], ifcond);
1212  fs << tabs << tab1;
1213  ReadSTLarg(fs, arg2, argtype[1], isargptr[1], argcl[1], argtname[1], ifcond);
1214  fs << tabs << tab1;
1215  if (ifcond.Length() > 0)
1216  fs << "if (" << ifcond << ") ";
1217  fs << accname << "insert(make_pair(" << arg1 << ", " << arg2 << "));" << std::endl;
1218  fs << tabs << "}" << std::endl;
1219  }
1220  }
1221 
1222  if (isarr && el->GetArrayLength()) {
1223  if (isptr)
1224  fs << tabs << "cont++;" << std::endl;
1225  else
1226  fs << tabs << "(void*) cont = (char*) cont + sizeof(" << contcl->GetName() << ");" << std::endl;
1227  fs << tab3 << "}" << std::endl;
1228  }
1229 
1230  fs << tab3 << "buf.EndSTLnode();" << std::endl;
1231  fs << tab2 << "}" << std::endl;
1232  }
1233  return true;
1234 }