Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TBufferSQL2.cxx
Go to the documentation of this file.
1 // @(#)root/sql:$Id$
2 // Author: Sergey Linev 20/11/2005
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2005, 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 \class TBufferSQL2
14 \ingroup IO
15 
16 Converts data to SQL statements or read data from SQL tables.
17 
18 Class for serializing/deserializing object to/from SQL data base.
19 It redefines most of TBuffer class function to convert simple types,
20 array of simple types and objects to/from TSQLStructure objects.
21 TBufferSQL2 class uses streaming mechanism, provided by ROOT system,
22 therefore most of ROOT and user classes can be stored. There are
23 limitations for complex objects like TTree, TClonesArray, TDirectory and
24 few other, which can not be converted to SQL (yet).
25 */
26 
27 #include "TBufferSQL2.h"
28 
29 #include "TObjArray.h"
30 #include "TROOT.h"
31 #include "TDataType.h"
32 #include "TClass.h"
33 #include "TClassTable.h"
34 #include "TMap.h"
35 #include "TStreamerInfo.h"
36 #include "TStreamerElement.h"
37 #include "TFile.h"
38 #include "TMemberStreamer.h"
39 #include "TStreamer.h"
40 #include "Riostream.h"
41 #include <stdlib.h>
42 #include <string>
43 #include "TStreamerInfoActions.h"
44 
45 #include "TSQLServer.h"
46 #include "TSQLResult.h"
47 #include "TSQLRow.h"
48 #include "TSQLStructure.h"
49 #include "TSQLObjectData.h"
50 #include "TSQLFile.h"
51 #include "TSQLClassInfo.h"
52 
53 ClassImp(TBufferSQL2);
54 
55 ////////////////////////////////////////////////////////////////////////////////
56 /// Default constructor, should not be used
57 
58 TBufferSQL2::TBufferSQL2()
59  : TBufferText(), fSQL(nullptr), fIOVersion(1), fStructure(nullptr), fStk(0), fReadBuffer(), fErrorFlag(0),
60  fCompressLevel(ROOT::RCompressionSetting::EAlgorithm::kUseGlobal), fReadVersionBuffer(-1), fObjIdCounter(1), fIgnoreVerification(kFALSE),
61  fCurrentData(nullptr), fObjectsInfos(nullptr), fFirstObjId(0), fLastObjId(0), fPoolsMap(nullptr)
62 {
63 }
64 
65 ////////////////////////////////////////////////////////////////////////////////
66 /// Creates buffer object to serialize/deserialize data to/from sql.
67 /// This constructor should be used, if data from buffer supposed to be stored in file.
68 /// Mode should be either TBuffer::kRead or TBuffer::kWrite.
69 
70 TBufferSQL2::TBufferSQL2(TBuffer::EMode mode, TSQLFile *file)
71  : TBufferText(mode, file), fSQL(nullptr), fIOVersion(1), fStructure(nullptr), fStk(0), fReadBuffer(), fErrorFlag(0),
72  fCompressLevel(ROOT::RCompressionSetting::EAlgorithm::kUseGlobal), fReadVersionBuffer(-1), fObjIdCounter(1), fIgnoreVerification(kFALSE),
73  fCurrentData(nullptr), fObjectsInfos(nullptr), fFirstObjId(0), fLastObjId(0), fPoolsMap(nullptr)
74 {
75  fSQL = file;
76  if (file) {
77  SetCompressionLevel(file->GetCompressionLevel());
78  fIOVersion = file->GetIOVersion();
79  }
80 }
81 
82 ////////////////////////////////////////////////////////////////////////////////
83 /// Destroy sql buffer.
84 
85 TBufferSQL2::~TBufferSQL2()
86 {
87  if (fStructure)
88  delete fStructure;
89 
90  if (fObjectsInfos) {
91  fObjectsInfos->Delete();
92  delete fObjectsInfos;
93  }
94 
95  if (fPoolsMap) {
96  fPoolsMap->DeleteValues();
97  delete fPoolsMap;
98  }
99 }
100 
101 ////////////////////////////////////////////////////////////////////////////////
102 /// Convert object of any class to sql structures
103 /// Return pointer on created TSQLStructure
104 /// TSQLStructure object will be owned by TBufferSQL2
105 
106 TSQLStructure *TBufferSQL2::SqlWriteAny(const void *obj, const TClass *cl, Long64_t objid)
107 {
108  fErrorFlag = 0;
109 
110  fStructure = nullptr;
111 
112  fFirstObjId = objid;
113  fObjIdCounter = objid;
114 
115  SqlWriteObject(obj, cl, kTRUE);
116 
117  if (gDebug > 3)
118  if (fStructure) {
119  std::cout << "==== Printout of Sql structures ===== " << std::endl;
120  fStructure->Print("*");
121  std::cout << "=========== End printout ============ " << std::endl;
122  }
123 
124  return fStructure;
125 }
126 
127 ////////////////////////////////////////////////////////////////////////////////
128 /// Recreate object from sql structure.
129 /// Return pointer to read object.
130 /// if (cl!=0) returns pointer to class of object
131 
132 void *TBufferSQL2::SqlReadAny(Long64_t keyid, Long64_t objid, TClass **cl, void *obj)
133 {
134  if (cl)
135  *cl = nullptr;
136  if (!fSQL)
137  return nullptr;
138 
139  fCurrentData = 0;
140  fErrorFlag = 0;
141 
142  fReadVersionBuffer = -1;
143 
144  fObjectsInfos = fSQL->SQLObjectsInfo(keyid);
145  fFirstObjId = objid;
146  fLastObjId = objid;
147  if (fObjectsInfos) {
148  TSQLObjectInfo *objinfo = (TSQLObjectInfo *)fObjectsInfos->Last();
149  if (objinfo)
150  fLastObjId = objinfo->GetObjId();
151  }
152 
153  return SqlReadObjectDirect(obj, cl, objid);
154 }
155 
156 ////////////////////////////////////////////////////////////////////////////////
157 /// Returns object info like classname and version
158 /// Should be taken from buffer, which is produced in the beginning
159 
160 Bool_t TBufferSQL2::SqlObjectInfo(Long64_t objid, TString &clname, Version_t &version)
161 {
162  if ((objid < 0) || !fObjectsInfos)
163  return kFALSE;
164 
165  // suppose that objects info are sorted out
166 
167  Long64_t shift = objid - fFirstObjId;
168 
169  TSQLObjectInfo *info = nullptr;
170  if ((shift >= 0) && (shift <= fObjectsInfos->GetLast())) {
171  info = (TSQLObjectInfo *)fObjectsInfos->At(shift);
172  if (info->GetObjId() != objid)
173  info = nullptr;
174  }
175 
176  if (!info) {
177  // I hope, i will never get inside it
178  Info("SqlObjectInfo", "Standard not works %lld", objid);
179  for (Int_t n = 0; n <= fObjectsInfos->GetLast(); n++) {
180  info = (TSQLObjectInfo *)fObjectsInfos->At(n);
181  if (info->GetObjId() == objid)
182  break;
183  info = nullptr;
184  }
185  }
186 
187  if (!info)
188  return kFALSE;
189 
190  clname = info->GetObjClassName();
191  version = info->GetObjVersion();
192  return kTRUE;
193 }
194 
195 ////////////////////////////////////////////////////////////////////////////////
196 /// Creates TSQLObjectData for specified object id and specified class
197 ///
198 /// Object data for each class can be stored in two different tables.
199 /// First table contains data in column-wise form for simple types like integer,
200 /// strings and so on when second table contains any other data which cannot
201 /// be converted into column-wise representation.
202 /// TSQLObjectData will contain results of the requests to both such tables for
203 /// concrete object id.
204 
205 TSQLObjectData *TBufferSQL2::SqlObjectData(Long64_t objid, TSQLClassInfo *sqlinfo)
206 {
207  TSQLResult *classdata = nullptr;
208  TSQLRow *classrow = nullptr;
209 
210  if (sqlinfo->IsClassTableExist()) {
211 
212  TSQLObjectDataPool *pool = nullptr;
213 
214  if (fPoolsMap)
215  pool = (TSQLObjectDataPool *)fPoolsMap->GetValue(sqlinfo);
216 
217  if (pool && (fLastObjId >= fFirstObjId)) {
218  if (gDebug > 4)
219  Info("SqlObjectData", "Before request to %s", sqlinfo->GetClassTableName());
220  TSQLResult *alldata = fSQL->GetNormalClassDataAll(fFirstObjId, fLastObjId, sqlinfo);
221  if (gDebug > 4)
222  Info("SqlObjectData", "After request res = 0x%lx", (Long_t)alldata);
223  if (!alldata) {
224  Error("SqlObjectData", "Cannot get data from table %s", sqlinfo->GetClassTableName());
225  return nullptr;
226  }
227 
228  if (!fPoolsMap)
229  fPoolsMap = new TMap();
230  pool = new TSQLObjectDataPool(sqlinfo, alldata);
231  fPoolsMap->Add(sqlinfo, pool);
232  }
233 
234  if (!pool)
235  return nullptr;
236 
237  if (pool->GetSqlInfo() != sqlinfo) {
238  Error("SqlObjectData", "Missmatch in pools map !!! CANNOT BE !!!");
239  return nullptr;
240  }
241 
242  classdata = pool->GetClassData();
243 
244  classrow = pool->GetObjectRow(objid);
245  if (!classrow) {
246  Error("SqlObjectData", "Can not find row for objid = %lld in table %s", objid, sqlinfo->GetClassTableName());
247  return nullptr;
248  }
249  }
250 
251  TSQLResult *blobdata = nullptr;
252  TSQLStatement *blobstmt = fSQL->GetBlobClassDataStmt(objid, sqlinfo);
253 
254  if (!blobstmt)
255  blobdata = fSQL->GetBlobClassData(objid, sqlinfo);
256 
257  return new TSQLObjectData(sqlinfo, objid, classdata, classrow, blobdata, blobstmt);
258 }
259 
260 ////////////////////////////////////////////////////////////////////////////////
261 /// Write object to buffer.
262 /// If object was written before, only pointer will be stored
263 /// Return id of saved object
264 
265 Int_t TBufferSQL2::SqlWriteObject(const void *obj, const TClass *cl, Bool_t cacheReuse, TMemberStreamer *streamer,
266  Int_t streamer_index)
267 {
268  if (gDebug > 1)
269  Info("SqlWriteObject", "Object: %p Class: %s", obj, (cl ? cl->GetName() : "null"));
270 
271  PushStack();
272 
273  Long64_t objid = -1;
274 
275  if (!cl)
276  obj = nullptr;
277 
278  if (!obj) {
279  objid = 0;
280  } else {
281  Long64_t value = GetObjectTag(obj);
282  if (value > 0)
283  objid = fFirstObjId + value - 1;
284  }
285 
286  if (gDebug > 1)
287  Info("SqlWriteObject", "Find objectid %ld", (long)objid);
288 
289  if (objid >= 0) {
290  Stack()->SetObjectPointer(objid);
291  PopStack();
292  return objid;
293  }
294 
295  objid = fObjIdCounter++;
296 
297  Stack()->SetObjectRef(objid, cl);
298 
299  if (cacheReuse)
300  MapObject(obj, cl, objid - fFirstObjId + 1);
301 
302  if (streamer)
303  (*streamer)(*this, (void *)obj, streamer_index);
304  else
305  ((TClass *)cl)->Streamer((void *)obj, *this);
306 
307  if (gDebug > 1)
308  Info("SqlWriteObject", "Done write of %s", cl->GetName());
309 
310  PopStack();
311 
312  return objid;
313 }
314 
315 ////////////////////////////////////////////////////////////////////////////////
316 /// Read object from the buffer
317 
318 void *TBufferSQL2::SqlReadObject(void *obj, TClass **cl, TMemberStreamer *streamer, Int_t streamer_index,
319  const TClass *onFileClass)
320 {
321  if (cl)
322  *cl = nullptr;
323 
324  if (fErrorFlag > 0)
325  return obj;
326 
327  Bool_t findptr = kFALSE;
328 
329  const char *refid = fCurrentData->GetValue();
330  if ((refid == 0) || (strlen(refid) == 0)) {
331  Error("SqlReadObject", "Invalid object reference value");
332  fErrorFlag = 1;
333  return obj;
334  }
335 
336  Long64_t objid = (Long64_t)std::stoll(refid);
337 
338  if (gDebug > 2)
339  Info("SqlReadObject", "Starting objid: %ld column: %s", (long)objid, fCurrentData->GetLocatedField());
340 
341  if (!fCurrentData->IsBlobData() || fCurrentData->VerifyDataType(sqlio::ObjectPtr, kFALSE)) {
342  if (objid == 0) {
343  obj = nullptr;
344  findptr = kTRUE;
345  } else if (objid == -1) {
346  findptr = kTRUE;
347  } else if (objid >= fFirstObjId) {
348  void *obj1 = nullptr;
349  TClass *cl1 = nullptr;
350  GetMappedObject(objid - fFirstObjId + 1, obj1, cl1);
351  if (obj1 && cl1) {
352  obj = obj1;
353  if (cl)
354  *cl = cl1;
355  }
356  }
357  }
358 
359  if ((gDebug > 3) && findptr)
360  Info("SqlReadObject", "Found pointer %p cl %s", obj, ((cl && *cl) ? (*cl)->GetName() : "null"));
361 
362  if (findptr) {
363  fCurrentData->ShiftToNextValue();
364  return obj;
365  }
366 
367  if (fCurrentData->IsBlobData())
368  if (!fCurrentData->VerifyDataType(sqlio::ObjectRef)) {
369  Error("SqlReadObject", "Object reference or pointer is not found in blob data");
370  fErrorFlag = 1;
371  return obj;
372  }
373 
374  fCurrentData->ShiftToNextValue();
375 
376  if ((gDebug > 2) || (objid < 0))
377  Info("SqlReadObject", "Found object reference %ld", (long)objid);
378 
379  return SqlReadObjectDirect(obj, cl, objid, streamer, streamer_index, onFileClass);
380 }
381 
382 ////////////////////////////////////////////////////////////////////////////////
383 /// Read object data.
384 /// Class name and version are taken from special objects table.
385 
386 void *TBufferSQL2::SqlReadObjectDirect(void *obj, TClass **cl, Long64_t objid, TMemberStreamer *streamer,
387  Int_t streamer_index, const TClass *onFileClass)
388 {
389  TString clname;
390  Version_t version;
391 
392  if (!SqlObjectInfo(objid, clname, version))
393  return obj;
394 
395  if (gDebug > 2)
396  Info("SqlReadObjectDirect", "objid = %lld clname = %s ver = %d", objid, clname.Data(), version);
397 
398  TSQLClassInfo *sqlinfo = fSQL->FindSQLClassInfo(clname.Data(), version);
399 
400  TClass *objClass = TClass::GetClass(clname);
401  if (objClass == TDirectory::Class())
402  objClass = TDirectoryFile::Class();
403 
404  if (!objClass || !sqlinfo) {
405  Error("SqlReadObjectDirect", "Class %s is not known", clname.Data());
406  return obj;
407  }
408 
409  if (!obj)
410  obj = objClass->New();
411 
412  MapObject(obj, objClass, objid - fFirstObjId + 1);
413 
414  PushStack()->SetObjectRef(objid, objClass);
415 
416  TSQLObjectData *olddata = fCurrentData;
417 
418  if (sqlinfo->IsClassTableExist()) {
419  // TObject and TString classes treated differently
420  if ((objClass == TObject::Class()) || (objClass == TString::Class())) {
421 
422  TSQLObjectData *objdata = new TSQLObjectData;
423  if (objClass == TObject::Class())
424  TSQLStructure::UnpackTObject(fSQL, this, objdata, objid, version);
425  else if (objClass == TString::Class())
426  TSQLStructure::UnpackTString(fSQL, this, objdata, objid, version);
427 
428  Stack()->AddObjectData(objdata);
429  fCurrentData = objdata;
430  } else
431  // before normal streamer first version will be read and
432  // then streamer functions of TStreamerInfo class
433  fReadVersionBuffer = version;
434  } else {
435  TSQLObjectData *objdata = SqlObjectData(objid, sqlinfo);
436  if (!objdata || !objdata->PrepareForRawData()) {
437  Error("SqlReadObjectDirect", "No found raw data for obj %lld in class %s version %d table", objid,
438  clname.Data(), version);
439  fErrorFlag = 1;
440  return obj;
441  }
442 
443  Stack()->AddObjectData(objdata);
444 
445  fCurrentData = objdata;
446  }
447 
448  if (streamer) {
449  streamer->SetOnFileClass(onFileClass);
450  (*streamer)(*this, (void *)obj, streamer_index);
451  } else {
452  objClass->Streamer((void *)obj, *this, onFileClass);
453  }
454 
455  PopStack();
456 
457  if (gDebug > 1)
458  Info("SqlReadObjectDirect", "Read object of class %s done", objClass->GetName());
459 
460  if (cl)
461  *cl = objClass;
462 
463  fCurrentData = olddata;
464 
465  return obj;
466 }
467 
468 ////////////////////////////////////////////////////////////////////////////////
469 /// Function is called from TStreamerInfo WriteBuffer and Readbuffer functions
470 /// and indent new level in data structure.
471 /// This call indicates, that TStreamerInfo functions starts streaming
472 /// object data of correspondent class
473 
474 void TBufferSQL2::IncrementLevel(TVirtualStreamerInfo *info)
475 {
476  if (!info)
477  return;
478 
479  PushStack()->SetStreamerInfo((TStreamerInfo *)info);
480 
481  if (gDebug > 2)
482  Info("IncrementLevel", "Info: %s", info->GetName());
483 
484  WorkWithClass(info->GetName(), info->GetClassVersion());
485 }
486 
487 ////////////////////////////////////////////////////////////////////////////////
488 /// Function is called from TStreamerInfo WriteBuffer and Readbuffer functions
489 /// and decrease level in sql structure.
490 
491 void TBufferSQL2::DecrementLevel(TVirtualStreamerInfo *info)
492 {
493  if (Stack()->GetElement())
494  PopStack(); // for element
495  PopStack(); // for streamerinfo
496 
497  // restore value of object data
498  fCurrentData = Stack()->GetObjectData(kTRUE);
499 
500  if (gDebug > 2)
501  Info("DecrementLevel", "Info: %s", info->GetName());
502 }
503 
504 ////////////////////////////////////////////////////////////////////////////////
505 /// Function is called from TStreamerInfo WriteBuffer and Readbuffer functions
506 /// and add/verify next element in sql tables
507 /// This calls allows separate data, correspondent to one class member, from another
508 
509 void TBufferSQL2::SetStreamerElementNumber(TStreamerElement *elem, Int_t comp_type)
510 {
511  if (Stack()->GetElement())
512  PopStack(); // was with if (number > 0), i.e. not first element.
513  TSQLStructure *curr = Stack();
514 
515  TStreamerInfo *info = curr->GetStreamerInfo();
516  if (!info) {
517  Error("SetStreamerElementNumber", "Error in structures stack");
518  return;
519  }
520 
521  WorkWithElement(elem, comp_type);
522 }
523 
524 ////////////////////////////////////////////////////////////////////////////////
525 /// This method inform buffer data of which class now
526 /// will be streamed. When reading, classversion should be specified
527 /// as was read by TBuffer::ReadVersion().
528 ///
529 /// ClassBegin(), ClassEnd() & ClassMemeber() should be used in
530 /// custom class streamers to specify which kind of data are
531 /// now streamed to/from buffer. That information is used to correctly
532 /// convert class data to/from "normal" sql tables with meaningfull names
533 /// and correct datatypes. Without that functions data from custom streamer
534 /// will be saved as "raw" data in special _streamer_ table one value after another
535 /// Such MUST be used when object is written with standard ROOT streaming
536 /// procedure, but should be read back in custom streamer.
537 /// For example, custom streamer of TNamed class may look like:
538 
539 void TBufferSQL2::ClassBegin(const TClass *cl, Version_t classversion)
540 {
541  // void TNamed::Streamer(TBuffer &b)
542  // UInt_t R__s, R__c;
543  // if (b.IsReading()) {
544  // Version_t R__v = b.ReadVersion(&R__s, &R__c);
545  // b.ClassBegin(TNamed::Class(), R__v);
546  // b.ClassMember("TObject");
547  // TObject::Streamer(b);
548  // b.ClassMember("fName","TString");
549  // fName.Streamer(b);
550  // b.ClassMember("fTitle","TString");
551  // fTitle.Streamer(b);
552  // b.ClassEnd(TNamed::Class());
553  // b.SetBufferOffset(R__s+R__c+sizeof(UInt_t));
554  // } else {
555  // TNamed::Class()->WriteBuffer(b,this);
556  // }
557 
558  if (classversion < 0)
559  classversion = cl->GetClassVersion();
560 
561  PushStack()->SetCustomClass(cl, classversion);
562 
563  if (gDebug > 2)
564  Info("ClassBegin", "Class: %s", cl->GetName());
565 
566  WorkWithClass(cl->GetName(), classversion);
567 }
568 
569 ////////////////////////////////////////////////////////////////////////////////
570 /// Method indicates end of streaming of classdata in custom streamer.
571 /// See ClassBegin() method for more details.
572 
573 void TBufferSQL2::ClassEnd(const TClass *cl)
574 {
575  if (Stack()->GetType() == TSQLStructure::kSqlCustomElement)
576  PopStack(); // for element
577  PopStack(); // for streamerinfo
578 
579  // restore value of object data
580  fCurrentData = Stack()->GetObjectData(kTRUE);
581 
582  if (gDebug > 2)
583  Info("ClassEnd", "Class: %s", cl->GetName());
584 }
585 
586 ////////////////////////////////////////////////////////////////////////////////
587 /// Method indicates name and typename of class memeber,
588 /// which should be now streamed in custom streamer
589 /// Following combinations are supported:
590 /// see TBufferXML::ClassMember for the details.
591 
592 void TBufferSQL2::ClassMember(const char *name, const char *typeName, Int_t arrsize1, Int_t arrsize2)
593 {
594  if (!typeName)
595  typeName = name;
596 
597  if (!name || (strlen(name) == 0)) {
598  Error("ClassMember", "Invalid member name");
599  fErrorFlag = 1;
600  return;
601  }
602 
603  TString tname = typeName;
604 
605  Int_t typ_id = -1;
606 
607  if (strcmp(typeName, "raw:data") == 0)
608  typ_id = TStreamerInfo::kMissing;
609 
610  if (typ_id < 0) {
611  TDataType *dt = gROOT->GetType(typeName);
612  if (dt)
613  if ((dt->GetType() > 0) && (dt->GetType() < 20))
614  typ_id = dt->GetType();
615  }
616 
617  if (typ_id < 0)
618  if (strcmp(name, typeName) == 0) {
619  TClass *cl = TClass::GetClass(tname.Data());
620  if (cl)
621  typ_id = TStreamerInfo::kBase;
622  }
623 
624  if (typ_id < 0) {
625  Bool_t isptr = kFALSE;
626  if (tname[tname.Length() - 1] == '*') {
627  tname.Resize(tname.Length() - 1);
628  isptr = kTRUE;
629  }
630  TClass *cl = TClass::GetClass(tname.Data());
631  if (!cl) {
632  Error("ClassMember", "Invalid class specifier %s", typeName);
633  fErrorFlag = 1;
634  return;
635  }
636 
637  if (cl->IsTObject())
638  typ_id = isptr ? TStreamerInfo::kObjectp : TStreamerInfo::kObject;
639  else
640  typ_id = isptr ? TStreamerInfo::kAnyp : TStreamerInfo::kAny;
641 
642  if ((cl == TString::Class()) && !isptr)
643  typ_id = TStreamerInfo::kTString;
644  }
645 
646  TStreamerElement *elem = nullptr;
647 
648  if (typ_id == TStreamerInfo::kMissing) {
649  elem = new TStreamerElement(name, "title", 0, typ_id, "raw:data");
650  } else if (typ_id == TStreamerInfo::kBase) {
651  TClass *cl = TClass::GetClass(tname.Data());
652  if (cl) {
653  TStreamerBase *b = new TStreamerBase(tname.Data(), "title", 0);
654  b->SetBaseVersion(cl->GetClassVersion());
655  elem = b;
656  }
657  } else if ((typ_id > 0) && (typ_id < 20)) {
658  elem = new TStreamerBasicType(name, "title", 0, typ_id, typeName);
659  } else if ((typ_id == TStreamerInfo::kObject) || (typ_id == TStreamerInfo::kTObject) ||
660  (typ_id == TStreamerInfo::kTNamed)) {
661  elem = new TStreamerObject(name, "title", 0, tname.Data());
662  } else if (typ_id == TStreamerInfo::kObjectp) {
663  elem = new TStreamerObjectPointer(name, "title", 0, tname.Data());
664  } else if (typ_id == TStreamerInfo::kAny) {
665  elem = new TStreamerObjectAny(name, "title", 0, tname.Data());
666  } else if (typ_id == TStreamerInfo::kAnyp) {
667  elem = new TStreamerObjectAnyPointer(name, "title", 0, tname.Data());
668  } else if (typ_id == TStreamerInfo::kTString) {
669  elem = new TStreamerString(name, "title", 0);
670  }
671 
672  if (!elem) {
673  Error("ClassMember", "Invalid combination name = %s type = %s", name, typeName);
674  fErrorFlag = 1;
675  return;
676  }
677 
678  if (arrsize1 > 0) {
679  elem->SetArrayDim(arrsize2 > 0 ? 2 : 1);
680  elem->SetMaxIndex(0, arrsize1);
681  if (arrsize2 > 0)
682  elem->SetMaxIndex(1, arrsize2);
683  }
684 
685  // return stack to CustomClass node
686  if (Stack()->GetType() == TSQLStructure::kSqlCustomElement)
687  PopStack();
688 
689  // we indicate that there is no streamerinfo
690  WorkWithElement(elem, -1);
691 }
692 
693 ////////////////////////////////////////////////////////////////////////////////
694 /// This function is a part of IncrementLevel method.
695 /// Also used in StartClass method
696 
697 void TBufferSQL2::WorkWithClass(const char *classname, Version_t classversion)
698 {
699  if (IsReading()) {
700  Long64_t objid = 0;
701 
702  // if ((fCurrentData!=0) && fCurrentData->VerifyDataType(sqlio::ObjectInst, kFALSE))
703  // if (!fCurrentData->IsBlobData()) Info("WorkWithClass","Big problem %s", fCurrentData->GetValue());
704 
705  if (fCurrentData && fCurrentData->IsBlobData() && fCurrentData->VerifyDataType(sqlio::ObjectInst, kFALSE)) {
706  objid = atoi(fCurrentData->GetValue());
707  fCurrentData->ShiftToNextValue();
708  TString sobjid;
709  sobjid.Form("%lld", objid);
710  Stack()->ChangeValueOnly(sobjid.Data());
711  } else
712  objid = Stack()->DefineObjectId(kTRUE);
713  if (objid < 0) {
714  Error("WorkWithClass", "cannot define object id");
715  fErrorFlag = 1;
716  return;
717  }
718 
719  TSQLClassInfo *sqlinfo = fSQL->FindSQLClassInfo(classname, classversion);
720  if (!sqlinfo) {
721  Error("WorkWithClass", "Can not find table for class %s version %d", classname, classversion);
722  fErrorFlag = 1;
723  return;
724  }
725 
726  TSQLObjectData *objdata = SqlObjectData(objid, sqlinfo);
727  if (!objdata) {
728  Error("WorkWithClass", "Request error for data of object %lld for class %s version %d", objid, classname,
729  classversion);
730  fErrorFlag = 1;
731  return;
732  }
733 
734  Stack()->AddObjectData(objdata);
735 
736  fCurrentData = objdata;
737  }
738 }
739 
740 ////////////////////////////////////////////////////////////////////////////////
741 /// This function is a part of SetStreamerElementNumber method.
742 /// It is introduced for reading of data for specified data member of class.
743 /// Used also in ReadFastArray methods to resolve problem of compressed data,
744 /// when several data members of the same basic type streamed with single ...FastArray call
745 
746 void TBufferSQL2::WorkWithElement(TStreamerElement *elem, Int_t /* comp_type */)
747 {
748  if (gDebug > 2)
749  Info("WorkWithElement", "elem = %s", elem->GetName());
750 
751  TSQLStructure *stack = Stack(1);
752  TStreamerInfo *info = stack->GetStreamerInfo();
753  Int_t number = info ? info->GetElements()->IndexOf(elem) : -1;
754 
755  if (number >= 0)
756  PushStack()->SetStreamerElement(elem, number);
757  else
758  PushStack()->SetCustomElement(elem);
759 
760  if (IsReading()) {
761 
762  if (!fCurrentData) {
763  Error("WorkWithElement", "Object data is lost");
764  fErrorFlag = 1;
765  return;
766  }
767 
768  fCurrentData = Stack()->GetObjectData(kTRUE);
769 
770  Int_t located = Stack()->LocateElementColumn(fSQL, this, fCurrentData);
771 
772  if (located == TSQLStructure::kColUnknown) {
773  Error("WorkWithElement", "Cannot locate correct column in the table");
774  fErrorFlag = 1;
775  return;
776  } else if ((located == TSQLStructure::kColObject) || (located == TSQLStructure::kColObjectArray) ||
777  (located == TSQLStructure::kColParent)) {
778  // search again for object data while for BLOB it should be already assign
779  fCurrentData = Stack()->GetObjectData(kTRUE);
780  }
781  }
782 }
783 
784 ////////////////////////////////////////////////////////////////////////////////
785 /// Suppressed function of TBuffer
786 
787 TClass *TBufferSQL2::ReadClass(const TClass *, UInt_t *)
788 {
789  return nullptr;
790 }
791 
792 ////////////////////////////////////////////////////////////////////////////////
793 /// Suppressed function of TBuffer
794 
795 void TBufferSQL2::WriteClass(const TClass *)
796 {
797 }
798 
799 ////////////////////////////////////////////////////////////////////////////////
800 /// Read version value from buffer
801 /// actually version is normally defined by table name
802 /// and kept in intermediate variable fReadVersionBuffer
803 
804 Version_t TBufferSQL2::ReadVersion(UInt_t *start, UInt_t *bcnt, const TClass *)
805 {
806  Version_t res = 0;
807 
808  if (start)
809  *start = 0;
810  if (bcnt)
811  *bcnt = 0;
812 
813  if (fReadVersionBuffer >= 0) {
814  res = fReadVersionBuffer;
815  fReadVersionBuffer = -1;
816  if (gDebug > 3)
817  Info("ReadVersion", "from buffer = %d", (int)res);
818  } else if (fCurrentData && fCurrentData->IsBlobData() && fCurrentData->VerifyDataType(sqlio::Version)) {
819  TString value = fCurrentData->GetValue();
820  res = value.Atoi();
821  if (gDebug > 3)
822  Info("ReadVersion", "from blob %s = %d", fCurrentData->GetBlobPrefixName(), (int)res);
823  fCurrentData->ShiftToNextValue();
824  } else {
825  Error("ReadVersion", "No correspondent tags to read version");
826  fErrorFlag = 1;
827  }
828 
829  return res;
830 }
831 
832 ////////////////////////////////////////////////////////////////////////////////
833 /// Copies class version to buffer, but not writes it to sql immidiately
834 /// Version will be used to produce complete table
835 /// name, which will include class version
836 
837 UInt_t TBufferSQL2::WriteVersion(const TClass *cl, Bool_t /* useBcnt */)
838 {
839  if (gDebug > 2)
840  Info("WriteVersion", "cl:%s ver:%d", (cl ? cl->GetName() : "null"), (int)(cl ? cl->GetClassVersion() : 0));
841 
842  if (cl)
843  Stack()->AddVersion(cl);
844 
845  return 0;
846 }
847 
848 ////////////////////////////////////////////////////////////////////////////////
849 /// Read object from buffer. Only used from TBuffer.
850 
851 void *TBufferSQL2::ReadObjectAny(const TClass *)
852 {
853  return SqlReadObject(0);
854 }
855 
856 ////////////////////////////////////////////////////////////////////////////////
857 /// ?????? Skip any kind of object from buffer
858 /// !!!!!! fix me, not yet implemented
859 /// Should be just skip of current column later
860 
861 void TBufferSQL2::SkipObjectAny()
862 {
863 }
864 
865 ////////////////////////////////////////////////////////////////////////////////
866 /// Write object to buffer. Only used from TBuffer
867 
868 void TBufferSQL2::WriteObjectClass(const void *actualObjStart, const TClass *actualClass, Bool_t cacheReuse)
869 {
870  if (gDebug > 2)
871  Info("WriteObjectClass", "class %s", (actualClass ? actualClass->GetName() : " null"));
872  SqlWriteObject(actualObjStart, actualClass, cacheReuse);
873 }
874 
875 ////////////////////////////////////////////////////////////////////////////////
876 /// Template method to read array content
877 
878 template <typename T>
879 R__ALWAYS_INLINE void TBufferSQL2::SqlReadArrayContent(T *arr, Int_t arrsize, Bool_t withsize)
880 {
881  if (gDebug > 3)
882  Info("SqlReadArrayContent", "size %d", (int)(arrsize));
883  PushStack()->SetArray(withsize ? arrsize : -1);
884  Int_t indx(0), first, last;
885  if (fCurrentData->IsBlobData()) {
886  while (indx < arrsize) {
887  const char *name = fCurrentData->GetBlobPrefixName();
888  if (strstr(name, sqlio::IndexSepar) == 0) {
889  sscanf(name, "[%d", &first);
890  last = first;
891  } else {
892  sscanf(name, "[%d..%d", &first, &last);
893  }
894  if ((first != indx) || (last < first) || (last >= arrsize)) {
895  Error("SqlReadArrayContent", "Error reading array content %s", name);
896  fErrorFlag = 1;
897  break;
898  }
899  SqlReadBasic(arr[indx++]);
900  while (indx <= last)
901  arr[indx++] = arr[first];
902  }
903  } else {
904  while (indx < arrsize)
905  SqlReadBasic(arr[indx++]);
906  }
907  PopStack();
908  if (gDebug > 3)
909  Info("SqlReadArrayContent", "done");
910 }
911 
912 template <typename T>
913 R__ALWAYS_INLINE Int_t TBufferSQL2::SqlReadArray(T *&arr, Bool_t is_static)
914 {
915  Int_t n = SqlReadArraySize();
916  if (n <= 0)
917  return 0;
918  if (!arr) {
919  if (is_static)
920  return 0;
921  arr = new T[n];
922  }
923  SqlReadArrayContent(arr, n, kTRUE);
924  return n;
925 }
926 
927 ////////////////////////////////////////////////////////////////////////////////
928 /// Read array of Bool_t from buffer
929 
930 Int_t TBufferSQL2::ReadArray(Bool_t *&b)
931 {
932  return SqlReadArray(b);
933 }
934 
935 ////////////////////////////////////////////////////////////////////////////////
936 /// Read array of Char_t from buffer
937 
938 Int_t TBufferSQL2::ReadArray(Char_t *&c)
939 {
940  return SqlReadArray(c);
941 }
942 
943 ////////////////////////////////////////////////////////////////////////////////
944 /// Read array of UChar_t from buffer
945 
946 Int_t TBufferSQL2::ReadArray(UChar_t *&c)
947 {
948  return SqlReadArray(c);
949 }
950 
951 ////////////////////////////////////////////////////////////////////////////////
952 /// Read array of Short_t from buffer
953 
954 Int_t TBufferSQL2::ReadArray(Short_t *&h)
955 {
956  return SqlReadArray(h);
957 }
958 
959 ////////////////////////////////////////////////////////////////////////////////
960 /// Read array of UShort_t from buffer
961 
962 Int_t TBufferSQL2::ReadArray(UShort_t *&h)
963 {
964  return SqlReadArray(h);
965 }
966 
967 ////////////////////////////////////////////////////////////////////////////////
968 /// Read array of Int_t from buffer
969 
970 Int_t TBufferSQL2::ReadArray(Int_t *&i)
971 {
972  return SqlReadArray(i);
973 }
974 
975 ////////////////////////////////////////////////////////////////////////////////
976 /// Read array of UInt_t from buffer
977 
978 Int_t TBufferSQL2::ReadArray(UInt_t *&i)
979 {
980  return SqlReadArray(i);
981 }
982 
983 ////////////////////////////////////////////////////////////////////////////////
984 /// Read array of Long_t from buffer
985 
986 Int_t TBufferSQL2::ReadArray(Long_t *&l)
987 {
988  return SqlReadArray(l);
989 }
990 
991 ////////////////////////////////////////////////////////////////////////////////
992 /// Read array of ULong_t from buffer
993 
994 Int_t TBufferSQL2::ReadArray(ULong_t *&l)
995 {
996  return SqlReadArray(l);
997 }
998 
999 ////////////////////////////////////////////////////////////////////////////////
1000 /// Read array of Long64_t from buffer
1001 
1002 Int_t TBufferSQL2::ReadArray(Long64_t *&l)
1003 {
1004  return SqlReadArray(l);
1005 }
1006 
1007 ////////////////////////////////////////////////////////////////////////////////
1008 /// Read array of ULong64_t from buffer
1009 
1010 Int_t TBufferSQL2::ReadArray(ULong64_t *&l)
1011 {
1012  return SqlReadArray(l);
1013 }
1014 
1015 ////////////////////////////////////////////////////////////////////////////////
1016 /// Read array of Float_t from buffer
1017 
1018 Int_t TBufferSQL2::ReadArray(Float_t *&f)
1019 {
1020  return SqlReadArray(f);
1021 }
1022 
1023 ////////////////////////////////////////////////////////////////////////////////
1024 /// Read array of Double_t from buffer
1025 
1026 Int_t TBufferSQL2::ReadArray(Double_t *&d)
1027 {
1028  return SqlReadArray(d);
1029 }
1030 
1031 ////////////////////////////////////////////////////////////////////////////////
1032 /// Read array of Bool_t from buffer
1033 
1034 Int_t TBufferSQL2::ReadStaticArray(Bool_t *b)
1035 {
1036  return SqlReadArray(b, kTRUE);
1037 }
1038 
1039 ////////////////////////////////////////////////////////////////////////////////
1040 /// Read array of Char_t from buffer
1041 
1042 Int_t TBufferSQL2::ReadStaticArray(Char_t *c)
1043 {
1044  return SqlReadArray(c, kTRUE);
1045 }
1046 
1047 ////////////////////////////////////////////////////////////////////////////////
1048 /// Read array of UChar_t from buffer
1049 
1050 Int_t TBufferSQL2::ReadStaticArray(UChar_t *c)
1051 {
1052  return SqlReadArray(c, kTRUE);
1053 }
1054 
1055 ////////////////////////////////////////////////////////////////////////////////
1056 /// Read array of Short_t from buffer
1057 
1058 Int_t TBufferSQL2::ReadStaticArray(Short_t *h)
1059 {
1060  return SqlReadArray(h, kTRUE);
1061 }
1062 
1063 ////////////////////////////////////////////////////////////////////////////////
1064 /// Read array of UShort_t from buffer
1065 
1066 Int_t TBufferSQL2::ReadStaticArray(UShort_t *h)
1067 {
1068  return SqlReadArray(h, kTRUE);
1069 }
1070 
1071 ////////////////////////////////////////////////////////////////////////////////
1072 /// Read array of Int_t from buffer
1073 
1074 Int_t TBufferSQL2::ReadStaticArray(Int_t *i)
1075 {
1076  return SqlReadArray(i, kTRUE);
1077 }
1078 
1079 ////////////////////////////////////////////////////////////////////////////////
1080 /// Read array of UInt_t from buffer
1081 
1082 Int_t TBufferSQL2::ReadStaticArray(UInt_t *i)
1083 {
1084  return SqlReadArray(i, kTRUE);
1085 }
1086 
1087 ////////////////////////////////////////////////////////////////////////////////
1088 /// Read array of Long_t from buffer
1089 
1090 Int_t TBufferSQL2::ReadStaticArray(Long_t *l)
1091 {
1092  return SqlReadArray(l, kTRUE);
1093 }
1094 
1095 ////////////////////////////////////////////////////////////////////////////////
1096 /// Read array of ULong_t from buffer
1097 
1098 Int_t TBufferSQL2::ReadStaticArray(ULong_t *l)
1099 {
1100  return SqlReadArray(l, kTRUE);
1101 }
1102 
1103 ////////////////////////////////////////////////////////////////////////////////
1104 /// Read array of Long64_t from buffer
1105 
1106 Int_t TBufferSQL2::ReadStaticArray(Long64_t *l)
1107 {
1108  return SqlReadArray(l, kTRUE);
1109 }
1110 
1111 ////////////////////////////////////////////////////////////////////////////////
1112 /// Read array of ULong64_t from buffer
1113 
1114 Int_t TBufferSQL2::ReadStaticArray(ULong64_t *l)
1115 {
1116  return SqlReadArray(l, kTRUE);
1117 }
1118 
1119 ////////////////////////////////////////////////////////////////////////////////
1120 /// Read array of Float_t from buffer
1121 
1122 Int_t TBufferSQL2::ReadStaticArray(Float_t *f)
1123 {
1124  return SqlReadArray(f, kTRUE);
1125 }
1126 
1127 ////////////////////////////////////////////////////////////////////////////////
1128 /// Read array of Double_t from buffer
1129 
1130 Int_t TBufferSQL2::ReadStaticArray(Double_t *d)
1131 {
1132  return SqlReadArray(d, kTRUE);
1133 }
1134 
1135 ////////////////////////////////////////////////////////////////////////////////
1136 /// Template method to read content of array, which not include size of array
1137 
1138 template <typename T>
1139 R__ALWAYS_INLINE void TBufferSQL2::SqlReadFastArray(T *arr, Int_t arrsize)
1140 {
1141  if (arrsize > 0)
1142  SqlReadArrayContent(arr, arrsize, kFALSE);
1143 }
1144 
1145 ////////////////////////////////////////////////////////////////////////////////
1146 /// Read array of Bool_t from buffer
1147 
1148 void TBufferSQL2::ReadFastArray(Bool_t *b, Int_t n)
1149 {
1150  SqlReadFastArray(b, n);
1151 }
1152 
1153 ////////////////////////////////////////////////////////////////////////////////
1154 /// Read array of Char_t from buffer
1155 /// if nodename==CharStar, read all array as string
1156 
1157 void TBufferSQL2::ReadFastArray(Char_t *c, Int_t n)
1158 {
1159  if ((n > 0) && fCurrentData->IsBlobData() && fCurrentData->VerifyDataType(sqlio::CharStar, kFALSE)) {
1160  const char *buf = SqlReadCharStarValue();
1161  if (!buf || (n <= 0))
1162  return;
1163  Int_t size = strlen(buf);
1164  if (size < n)
1165  size = n;
1166  memcpy(c, buf, size);
1167  } else {
1168  SqlReadFastArray(c, n);
1169  }
1170 }
1171 
1172 ////////////////////////////////////////////////////////////////////////////////
1173 /// Read array of UChar_t from buffer
1174 
1175 void TBufferSQL2::ReadFastArray(UChar_t *c, Int_t n)
1176 {
1177  SqlReadFastArray(c, n);
1178 }
1179 
1180 ////////////////////////////////////////////////////////////////////////////////
1181 /// Read array of Short_t from buffer
1182 
1183 void TBufferSQL2::ReadFastArray(Short_t *h, Int_t n)
1184 {
1185  SqlReadFastArray(h, n);
1186 }
1187 
1188 ////////////////////////////////////////////////////////////////////////////////
1189 /// Read array of UShort_t from buffer
1190 
1191 void TBufferSQL2::ReadFastArray(UShort_t *h, Int_t n)
1192 {
1193  SqlReadFastArray(h, n);
1194 }
1195 
1196 ////////////////////////////////////////////////////////////////////////////////
1197 /// Read array of Int_t from buffer
1198 
1199 void TBufferSQL2::ReadFastArray(Int_t *i, Int_t n)
1200 {
1201  SqlReadFastArray(i, n);
1202 }
1203 
1204 ////////////////////////////////////////////////////////////////////////////////
1205 /// Read array of UInt_t from buffer
1206 
1207 void TBufferSQL2::ReadFastArray(UInt_t *i, Int_t n)
1208 {
1209  SqlReadFastArray(i, n);
1210 }
1211 
1212 ////////////////////////////////////////////////////////////////////////////////
1213 /// Read array of Long_t from buffer
1214 
1215 void TBufferSQL2::ReadFastArray(Long_t *l, Int_t n)
1216 {
1217  SqlReadFastArray(l, n);
1218 }
1219 
1220 ////////////////////////////////////////////////////////////////////////////////
1221 /// Read array of ULong_t from buffer
1222 
1223 void TBufferSQL2::ReadFastArray(ULong_t *l, Int_t n)
1224 {
1225  SqlReadFastArray(l, n);
1226 }
1227 
1228 ////////////////////////////////////////////////////////////////////////////////
1229 /// Read array of Long64_t from buffer
1230 
1231 void TBufferSQL2::ReadFastArray(Long64_t *l, Int_t n)
1232 {
1233  SqlReadFastArray(l, n);
1234 }
1235 
1236 ////////////////////////////////////////////////////////////////////////////////
1237 /// Read array of ULong64_t from buffer
1238 
1239 void TBufferSQL2::ReadFastArray(ULong64_t *l, Int_t n)
1240 {
1241  SqlReadFastArray(l, n);
1242 }
1243 
1244 ////////////////////////////////////////////////////////////////////////////////
1245 /// Read array of Float_t from buffer
1246 
1247 void TBufferSQL2::ReadFastArray(Float_t *f, Int_t n)
1248 {
1249  SqlReadFastArray(f, n);
1250 }
1251 
1252 ////////////////////////////////////////////////////////////////////////////////
1253 /// Read array of n characters from the I/O buffer.
1254 /// Used only from TLeafC, dummy implementation here
1255 
1256 void TBufferSQL2::ReadFastArrayString(Char_t *c, Int_t n)
1257 {
1258  SqlReadFastArray(c, n);
1259 }
1260 
1261 ////////////////////////////////////////////////////////////////////////////////
1262 /// Read array of Double_t from buffer
1263 
1264 void TBufferSQL2::ReadFastArray(Double_t *d, Int_t n)
1265 {
1266  SqlReadFastArray(d, n);
1267 }
1268 
1269 ////////////////////////////////////////////////////////////////////////////////
1270 /// Same functionality as TBuffer::ReadFastArray(...) but
1271 /// instead of calling cl->Streamer(obj,buf) call here
1272 /// buf.StreamObject(obj, cl). In that case it is easy to understand where
1273 /// object data is started and finished
1274 
1275 void TBufferSQL2::ReadFastArray(void *start, const TClass *cl, Int_t n, TMemberStreamer *streamer,
1276  const TClass *onFileClass)
1277 {
1278  if (gDebug > 2)
1279  Info("ReadFastArray", "(void *");
1280 
1281  if (streamer) {
1282  StreamObjectExtra(start, streamer, cl, 0, onFileClass);
1283  // (*streamer)(*this,start,0);
1284  return;
1285  }
1286 
1287  int objectSize = cl->Size();
1288  char *obj = (char *)start;
1289  char *end = obj + n * objectSize;
1290 
1291  for (; obj < end; obj += objectSize) {
1292  StreamObject(obj, cl, onFileClass);
1293  }
1294  // TBuffer::ReadFastArray(start, cl, n, s);
1295 }
1296 
1297 ////////////////////////////////////////////////////////////////////////////////
1298 /// Same functionality as TBuffer::ReadFastArray(...) but
1299 /// instead of calling cl->Streamer(obj,buf) call here
1300 /// buf.StreamObject(obj, cl). In that case it is easy to understand where
1301 /// object data is started and finished
1302 
1303 void TBufferSQL2::ReadFastArray(void **start, const TClass *cl, Int_t n, Bool_t isPreAlloc, TMemberStreamer *streamer,
1304  const TClass *onFileClass)
1305 {
1306  if (gDebug > 2)
1307  Info("ReadFastArray", "(void ** pre = %d n = %d", isPreAlloc, n);
1308 
1309  Bool_t oldStyle = kFALSE; // flag used to reproduce old-style I/O actions for kSTLp
1310 
1311  if ((fIOVersion < 2) && !isPreAlloc) {
1312  TStreamerElement *elem = Stack(0)->GetElement();
1313  if (elem && ((elem->GetType() == TStreamerInfo::kSTLp) ||
1314  (elem->GetType() == TStreamerInfo::kSTLp + TStreamerInfo::kOffsetL)))
1315  oldStyle = kTRUE;
1316  }
1317 
1318  if (streamer) {
1319  if (isPreAlloc) {
1320  for (Int_t j = 0; j < n; j++) {
1321  if (!start[j])
1322  start[j] = ((TClass *)cl)->New();
1323  }
1324  }
1325  if (oldStyle)
1326  (*streamer)(*this, (void *)start, n);
1327  else
1328  StreamObjectExtra((void *)start, streamer, cl, 0, onFileClass);
1329  return;
1330  }
1331 
1332  if (!isPreAlloc) {
1333 
1334  for (Int_t j = 0; j < n; j++) {
1335  if (oldStyle) {
1336  if (!start[j])
1337  start[j] = ((TClass *)cl)->New();
1338  ((TClass *)cl)->Streamer(start[j], *this);
1339  continue;
1340  }
1341 
1342  // delete the object or collection
1343  if (start[j] && TStreamerInfo::CanDelete())
1344  ((TClass *)cl)->Destructor(start[j], kFALSE); // call delete and desctructor
1345  start[j] = ReadObjectAny(cl);
1346  }
1347 
1348  } else { // case //-> in comment
1349 
1350  for (Int_t j = 0; j < n; j++) {
1351  if (!start[j])
1352  start[j] = ((TClass *)cl)->New();
1353  StreamObject(start[j], cl, onFileClass);
1354  }
1355  }
1356 
1357  if (gDebug > 2)
1358  Info("ReadFastArray", "(void ** Done");
1359 
1360  // TBuffer::ReadFastArray(startp, cl, n, isPreAlloc, s);
1361 }
1362 
1363 ////////////////////////////////////////////////////////////////////////////////
1364 /// Reads array size, written in raw data table.
1365 /// Used in ReadArray methods, where TBuffer need to read array size first.
1366 
1367 Int_t TBufferSQL2::SqlReadArraySize()
1368 {
1369  const char *value = SqlReadValue(sqlio::Array);
1370  if (!value || (strlen(value) == 0))
1371  return 0;
1372  Int_t sz = atoi(value);
1373  return sz;
1374 }
1375 
1376 template <typename T>
1377 R__ALWAYS_INLINE void TBufferSQL2::SqlWriteArray(T *arr, Int_t arrsize, Bool_t withsize)
1378 {
1379  if (!withsize && (arrsize <= 0))
1380  return;
1381  PushStack()->SetArray(withsize ? arrsize : -1);
1382  Int_t indx = 0;
1383  if (fCompressLevel > 0) {
1384  while (indx < arrsize) {
1385  Int_t curr = indx++;
1386  while ((indx < arrsize) && (arr[indx] == arr[curr]))
1387  indx++;
1388  SqlWriteBasic(arr[curr]);
1389  Stack()->ChildArrayIndex(curr, indx - curr);
1390  }
1391  } else {
1392  for (; indx < arrsize; indx++) {
1393  SqlWriteBasic(arr[indx]);
1394  Stack()->ChildArrayIndex(indx, 1);
1395  }
1396  }
1397  PopStack();
1398 }
1399 
1400 ////////////////////////////////////////////////////////////////////////////////
1401 /// Write array of Bool_t to buffer
1402 
1403 void TBufferSQL2::WriteArray(const Bool_t *b, Int_t n)
1404 {
1405  SqlWriteArray(b, n, kTRUE);
1406 }
1407 
1408 ////////////////////////////////////////////////////////////////////////////////
1409 /// Write array of Char_t to buffer
1410 
1411 void TBufferSQL2::WriteArray(const Char_t *c, Int_t n)
1412 {
1413  SqlWriteArray(c, n, kTRUE);
1414 }
1415 
1416 ////////////////////////////////////////////////////////////////////////////////
1417 /// Write array of UChar_t to buffer
1418 
1419 void TBufferSQL2::WriteArray(const UChar_t *c, Int_t n)
1420 {
1421  SqlWriteArray(c, n, kTRUE);
1422 }
1423 
1424 ////////////////////////////////////////////////////////////////////////////////
1425 /// Write array of Short_t to buffer
1426 
1427 void TBufferSQL2::WriteArray(const Short_t *h, Int_t n)
1428 {
1429  SqlWriteArray(h, n, kTRUE);
1430 }
1431 
1432 ////////////////////////////////////////////////////////////////////////////////
1433 /// Write array of UShort_t to buffer
1434 
1435 void TBufferSQL2::WriteArray(const UShort_t *h, Int_t n)
1436 {
1437  SqlWriteArray(h, n, kTRUE);
1438 }
1439 
1440 ////////////////////////////////////////////////////////////////////////////////
1441 /// Write array of Int_ to buffer
1442 
1443 void TBufferSQL2::WriteArray(const Int_t *i, Int_t n)
1444 {
1445  SqlWriteArray(i, n, kTRUE);
1446 }
1447 
1448 ////////////////////////////////////////////////////////////////////////////////
1449 /// Write array of UInt_t to buffer
1450 
1451 void TBufferSQL2::WriteArray(const UInt_t *i, Int_t n)
1452 {
1453  SqlWriteArray(i, n, kTRUE);
1454 }
1455 
1456 ////////////////////////////////////////////////////////////////////////////////
1457 /// Write array of Long_t to buffer
1458 
1459 void TBufferSQL2::WriteArray(const Long_t *l, Int_t n)
1460 {
1461  SqlWriteArray(l, n, kTRUE);
1462 }
1463 
1464 ////////////////////////////////////////////////////////////////////////////////
1465 /// Write array of ULong_t to buffer
1466 
1467 void TBufferSQL2::WriteArray(const ULong_t *l, Int_t n)
1468 {
1469  SqlWriteArray(l, n, kTRUE);
1470 }
1471 
1472 ////////////////////////////////////////////////////////////////////////////////
1473 /// Write array of Long64_t to buffer
1474 
1475 void TBufferSQL2::WriteArray(const Long64_t *l, Int_t n)
1476 {
1477  SqlWriteArray(l, n, kTRUE);
1478 }
1479 
1480 ////////////////////////////////////////////////////////////////////////////////
1481 /// Write array of ULong64_t to buffer
1482 
1483 void TBufferSQL2::WriteArray(const ULong64_t *l, Int_t n)
1484 {
1485  SqlWriteArray(l, n, kTRUE);
1486 }
1487 
1488 ////////////////////////////////////////////////////////////////////////////////
1489 /// Write array of Float_t to buffer
1490 
1491 void TBufferSQL2::WriteArray(const Float_t *f, Int_t n)
1492 {
1493  SqlWriteArray(f, n, kTRUE);
1494 }
1495 
1496 ////////////////////////////////////////////////////////////////////////////////
1497 /// Write array of Double_t to buffer
1498 
1499 void TBufferSQL2::WriteArray(const Double_t *d, Int_t n)
1500 {
1501  SqlWriteArray(d, n, kTRUE);
1502 }
1503 
1504 ////////////////////////////////////////////////////////////////////////////////
1505 /// Write array of Bool_t to buffer
1506 
1507 void TBufferSQL2::WriteFastArray(const Bool_t *b, Int_t n)
1508 {
1509  SqlWriteArray(b, n);
1510 }
1511 
1512 ////////////////////////////////////////////////////////////////////////////////
1513 /// Write array of Char_t to buffer
1514 /// it will be reproduced as CharStar node with string as attribute
1515 
1516 void TBufferSQL2::WriteFastArray(const Char_t *c, Int_t n)
1517 {
1518  Bool_t usedefault = (n == 0);
1519 
1520  const Char_t *ccc = c;
1521  // check if no zeros in the array
1522  if (!usedefault)
1523  for (int i = 0; i < n; i++)
1524  if (*ccc++ == 0) {
1525  usedefault = kTRUE;
1526  break;
1527  }
1528 
1529  if (usedefault) {
1530  SqlWriteArray(c, n);
1531  } else {
1532  Char_t *buf = new Char_t[n + 1];
1533  memcpy(buf, c, n);
1534  buf[n] = 0;
1535  SqlWriteValue(buf, sqlio::CharStar);
1536  delete[] buf;
1537  }
1538 }
1539 
1540 ////////////////////////////////////////////////////////////////////////////////
1541 /// Write array of UChar_t to buffer
1542 
1543 void TBufferSQL2::WriteFastArray(const UChar_t *c, Int_t n)
1544 {
1545  SqlWriteArray(c, n);
1546 }
1547 
1548 ////////////////////////////////////////////////////////////////////////////////
1549 /// Write array of Short_t to buffer
1550 
1551 void TBufferSQL2::WriteFastArray(const Short_t *h, Int_t n)
1552 {
1553  SqlWriteArray(h, n);
1554 }
1555 
1556 ////////////////////////////////////////////////////////////////////////////////
1557 /// Write array of UShort_t to buffer
1558 
1559 void TBufferSQL2::WriteFastArray(const UShort_t *h, Int_t n)
1560 {
1561  SqlWriteArray(h, n);
1562 }
1563 
1564 ////////////////////////////////////////////////////////////////////////////////
1565 /// Write array of Int_t to buffer
1566 
1567 void TBufferSQL2::WriteFastArray(const Int_t *i, Int_t n)
1568 {
1569  SqlWriteArray(i, n);
1570 }
1571 
1572 ////////////////////////////////////////////////////////////////////////////////
1573 /// Write array of UInt_t to buffer
1574 
1575 void TBufferSQL2::WriteFastArray(const UInt_t *i, Int_t n)
1576 {
1577  SqlWriteArray(i, n);
1578 }
1579 
1580 ////////////////////////////////////////////////////////////////////////////////
1581 /// Write array of Long_t to buffer
1582 
1583 void TBufferSQL2::WriteFastArray(const Long_t *l, Int_t n)
1584 {
1585  SqlWriteArray(l, n);
1586 }
1587 
1588 ////////////////////////////////////////////////////////////////////////////////
1589 /// Write array of ULong_t to buffer
1590 
1591 void TBufferSQL2::WriteFastArray(const ULong_t *l, Int_t n)
1592 {
1593  SqlWriteArray(l, n);
1594 }
1595 
1596 ////////////////////////////////////////////////////////////////////////////////
1597 /// Write array of Long64_t to buffer
1598 
1599 void TBufferSQL2::WriteFastArray(const Long64_t *l, Int_t n)
1600 {
1601  SqlWriteArray(l, n);
1602 }
1603 
1604 ////////////////////////////////////////////////////////////////////////////////
1605 /// Write array of ULong64_t to buffer
1606 
1607 void TBufferSQL2::WriteFastArray(const ULong64_t *l, Int_t n)
1608 {
1609  SqlWriteArray(l, n);
1610 }
1611 
1612 ////////////////////////////////////////////////////////////////////////////////
1613 /// Write array of Float_t to buffer
1614 
1615 void TBufferSQL2::WriteFastArray(const Float_t *f, Int_t n)
1616 {
1617  SqlWriteArray(f, n);
1618 }
1619 
1620 ////////////////////////////////////////////////////////////////////////////////
1621 /// Write array of Double_t to buffer
1622 
1623 void TBufferSQL2::WriteFastArray(const Double_t *d, Int_t n)
1624 {
1625  SqlWriteArray(d, n);
1626 }
1627 
1628 ////////////////////////////////////////////////////////////////////////////////
1629 /// Write array of n characters into the I/O buffer.
1630 /// Used only by TLeafC, just dummy implementation here
1631 
1632 void TBufferSQL2::WriteFastArrayString(const Char_t *c, Int_t n)
1633 {
1634  SqlWriteArray(c, n);
1635 }
1636 
1637 ////////////////////////////////////////////////////////////////////////////////
1638 /// Same functionality as TBuffer::WriteFastArray(...) but
1639 /// instead of calling cl->Streamer(obj,buf) call here
1640 /// buf.StreamObject(obj, cl). In that case it is easy to understand where
1641 /// object data is started and finished
1642 
1643 void TBufferSQL2::WriteFastArray(void *start, const TClass *cl, Int_t n, TMemberStreamer *streamer)
1644 {
1645  if (streamer) {
1646  StreamObjectExtra(start, streamer, cl, 0);
1647  // (*streamer)(*this, start, 0);
1648  return;
1649  }
1650 
1651  char *obj = (char *)start;
1652  if (!n)
1653  n = 1;
1654  int size = cl->Size();
1655 
1656  for (Int_t j = 0; j < n; j++, obj += size)
1657  StreamObject(obj, cl);
1658 }
1659 
1660 ////////////////////////////////////////////////////////////////////////////////
1661 /// Same functionality as TBuffer::WriteFastArray(...) but
1662 /// instead of calling cl->Streamer(obj,buf) call here
1663 /// buf.StreamObject(obj, cl). In that case it is easy to understand where
1664 /// object data is started and finished
1665 
1666 Int_t TBufferSQL2::WriteFastArray(void **start, const TClass *cl, Int_t n, Bool_t isPreAlloc, TMemberStreamer *streamer)
1667 {
1668 
1669  Bool_t oldStyle = kFALSE; // flag used to reproduce old-style I/O actions for kSTLp
1670 
1671  if ((fIOVersion < 2) && !isPreAlloc) {
1672  TStreamerElement *elem = Stack(0)->GetElement();
1673  if (elem && ((elem->GetType() == TStreamerInfo::kSTLp) ||
1674  (elem->GetType() == TStreamerInfo::kSTLp + TStreamerInfo::kOffsetL)))
1675  oldStyle = kTRUE;
1676  }
1677 
1678  if (streamer) {
1679  if (oldStyle)
1680  (*streamer)(*this, (void *)start, n);
1681  else
1682  StreamObjectExtra((void *)start, streamer, cl, 0);
1683  return 0;
1684  }
1685 
1686  int strInfo = 0;
1687 
1688  Int_t res = 0;
1689 
1690  if (!isPreAlloc) {
1691 
1692  for (Int_t j = 0; j < n; j++) {
1693  // must write StreamerInfo if pointer is null
1694  if (!strInfo && !start[j] && !oldStyle)
1695  ForceWriteInfo(((TClass *)cl)->GetStreamerInfo(), kFALSE);
1696  strInfo = 2003;
1697  if (oldStyle)
1698  ((TClass *)cl)->Streamer(start[j], *this);
1699  else
1700  res |= WriteObjectAny(start[j], cl);
1701  }
1702 
1703  } else {
1704  // case //-> in comment
1705 
1706  for (Int_t j = 0; j < n; j++) {
1707  if (!start[j])
1708  start[j] = ((TClass *)cl)->New();
1709  StreamObject(start[j], cl);
1710  }
1711  }
1712  return res;
1713 
1714  // return TBuffer::WriteFastArray(startp, cl, n, isPreAlloc, s);
1715 }
1716 
1717 ////////////////////////////////////////////////////////////////////////////////
1718 /// Stream object to/from buffer
1719 
1720 void TBufferSQL2::StreamObject(void *obj, const TClass *cl, const TClass *onFileClass)
1721 {
1722  if (fIOVersion < 2) {
1723  TStreamerElement *elem = Stack(0)->GetElement();
1724  if (elem && (elem->GetType() == TStreamerInfo::kTObject)) {
1725  ((TObject *)obj)->TObject::Streamer(*this);
1726  return;
1727  } else if (elem && (elem->GetType() == TStreamerInfo::kTNamed)) {
1728  ((TNamed *)obj)->TNamed::Streamer(*this);
1729  return;
1730  }
1731  }
1732 
1733  if (gDebug > 1)
1734  Info("StreamObject", "class %s", (cl ? cl->GetName() : "none"));
1735  if (IsReading())
1736  SqlReadObject(obj, 0, nullptr, 0, onFileClass);
1737  else
1738  SqlWriteObject(obj, cl, kTRUE);
1739 }
1740 
1741 ////////////////////////////////////////////////////////////////////////////////
1742 /// Stream object to/from buffer
1743 
1744 void TBufferSQL2::StreamObjectExtra(void *obj, TMemberStreamer *streamer, const TClass *cl, Int_t n,
1745  const TClass *onFileClass)
1746 {
1747  if (!streamer)
1748  return;
1749 
1750  if (gDebug > 1)
1751  Info("StreamObjectExtra", "class = %s", cl->GetName());
1752  // (*streamer)(*this, obj, n);
1753 
1754  if (IsReading())
1755  SqlReadObject(obj, 0, streamer, n, onFileClass);
1756  else
1757  SqlWriteObject(obj, cl, kTRUE, streamer, n);
1758 }
1759 
1760 ////////////////////////////////////////////////////////////////////////////////
1761 /// Reads Bool_t value from buffer
1762 
1763 void TBufferSQL2::ReadBool(Bool_t &b)
1764 {
1765  SqlReadBasic(b);
1766 }
1767 
1768 ////////////////////////////////////////////////////////////////////////////////
1769 /// Reads Char_t value from buffer
1770 
1771 void TBufferSQL2::ReadChar(Char_t &c)
1772 {
1773  SqlReadBasic(c);
1774 }
1775 
1776 ////////////////////////////////////////////////////////////////////////////////
1777 /// Reads UChar_t value from buffer
1778 
1779 void TBufferSQL2::ReadUChar(UChar_t &c)
1780 {
1781  SqlReadBasic(c);
1782 }
1783 
1784 ////////////////////////////////////////////////////////////////////////////////
1785 /// Reads Short_t value from buffer
1786 
1787 void TBufferSQL2::ReadShort(Short_t &h)
1788 {
1789  SqlReadBasic(h);
1790 }
1791 
1792 ////////////////////////////////////////////////////////////////////////////////
1793 /// Reads UShort_t value from buffer
1794 
1795 void TBufferSQL2::ReadUShort(UShort_t &h)
1796 {
1797  SqlReadBasic(h);
1798 }
1799 
1800 ////////////////////////////////////////////////////////////////////////////////
1801 /// Reads Int_t value from buffer
1802 
1803 void TBufferSQL2::ReadInt(Int_t &i)
1804 {
1805  SqlReadBasic(i);
1806 }
1807 
1808 ////////////////////////////////////////////////////////////////////////////////
1809 /// Reads UInt_t value from buffer
1810 
1811 void TBufferSQL2::ReadUInt(UInt_t &i)
1812 {
1813  SqlReadBasic(i);
1814 }
1815 
1816 ////////////////////////////////////////////////////////////////////////////////
1817 /// Reads Long_t value from buffer
1818 
1819 void TBufferSQL2::ReadLong(Long_t &l)
1820 {
1821  SqlReadBasic(l);
1822 }
1823 
1824 ////////////////////////////////////////////////////////////////////////////////
1825 /// Reads ULong_t value from buffer
1826 
1827 void TBufferSQL2::ReadULong(ULong_t &l)
1828 {
1829  SqlReadBasic(l);
1830 }
1831 
1832 ////////////////////////////////////////////////////////////////////////////////
1833 /// Reads Long64_t value from buffer
1834 
1835 void TBufferSQL2::ReadLong64(Long64_t &l)
1836 {
1837  SqlReadBasic(l);
1838 }
1839 
1840 ////////////////////////////////////////////////////////////////////////////////
1841 /// Reads ULong64_t value from buffer
1842 
1843 void TBufferSQL2::ReadULong64(ULong64_t &l)
1844 {
1845  SqlReadBasic(l);
1846 }
1847 
1848 ////////////////////////////////////////////////////////////////////////////////
1849 /// Reads Float_t value from buffer
1850 
1851 void TBufferSQL2::ReadFloat(Float_t &f)
1852 {
1853  SqlReadBasic(f);
1854 }
1855 
1856 ////////////////////////////////////////////////////////////////////////////////
1857 /// Reads Double_t value from buffer
1858 
1859 void TBufferSQL2::ReadDouble(Double_t &d)
1860 {
1861  SqlReadBasic(d);
1862 }
1863 
1864 ////////////////////////////////////////////////////////////////////////////////
1865 /// Reads array of characters from buffer
1866 
1867 void TBufferSQL2::ReadCharP(Char_t *c)
1868 {
1869  const char *buf = SqlReadCharStarValue();
1870  if (buf)
1871  strcpy(c, buf);
1872 }
1873 
1874 ////////////////////////////////////////////////////////////////////////////////
1875 /// Read a TString
1876 
1877 void TBufferSQL2::ReadTString(TString &s)
1878 {
1879  if (fIOVersion < 2) {
1880  // original TBufferFile method can not be used, while used TString methods are private
1881  // try to reimplement close to the original
1882  Int_t nbig;
1883  UChar_t nwh;
1884  *this >> nwh;
1885  if (nwh == 0) {
1886  s.Resize(0);
1887  } else {
1888  if (nwh == 255)
1889  *this >> nbig;
1890  else
1891  nbig = nwh;
1892 
1893  char *data = new char[nbig];
1894  data[nbig] = 0;
1895  ReadFastArray(data, nbig);
1896  s = data;
1897  delete[] data;
1898  }
1899  } else {
1900  // TODO: new code - direct reading of string
1901  }
1902 }
1903 
1904 ////////////////////////////////////////////////////////////////////////////////
1905 /// Write a TString
1906 
1907 void TBufferSQL2::WriteTString(const TString &s)
1908 {
1909  if (fIOVersion < 2) {
1910  // original TBufferFile method, keep for compatibility
1911  Int_t nbig = s.Length();
1912  UChar_t nwh;
1913  if (nbig > 254) {
1914  nwh = 255;
1915  *this << nwh;
1916  *this << nbig;
1917  } else {
1918  nwh = UChar_t(nbig);
1919  *this << nwh;
1920  }
1921  const char *data = s.Data();
1922  WriteFastArray(data, nbig);
1923  } else {
1924  // TODO: make writing of string directly
1925  }
1926 }
1927 
1928 ////////////////////////////////////////////////////////////////////////////////
1929 /// Read a std::string
1930 
1931 void TBufferSQL2::ReadStdString(std::string *obj)
1932 {
1933  if (fIOVersion < 2) {
1934  if (!obj) {
1935  Error("ReadStdString", "The std::string address is nullptr but should not");
1936  return;
1937  }
1938  Int_t nbig;
1939  UChar_t nwh;
1940  *this >> nwh;
1941  if (nwh == 0) {
1942  obj->clear();
1943  } else {
1944  if (obj->size()) {
1945  // Insure that the underlying data storage is not shared
1946  (*obj)[0] = '\0';
1947  }
1948  if (nwh == 255) {
1949  *this >> nbig;
1950  obj->resize(nbig, '\0');
1951  ReadFastArray((char *)obj->data(), nbig);
1952  } else {
1953  obj->resize(nwh, '\0');
1954  ReadFastArray((char *)obj->data(), nwh);
1955  }
1956  }
1957  } else {
1958  // TODO: direct reading of std string
1959  }
1960 }
1961 
1962 ////////////////////////////////////////////////////////////////////////////////
1963 /// Write a std::string
1964 
1965 void TBufferSQL2::WriteStdString(const std::string *obj)
1966 {
1967  if (fIOVersion < 2) {
1968  if (!obj) {
1969  *this << (UChar_t)0;
1970  WriteFastArray("", 0);
1971  return;
1972  }
1973 
1974  UChar_t nwh;
1975  Int_t nbig = obj->length();
1976  if (nbig > 254) {
1977  nwh = 255;
1978  *this << nwh;
1979  *this << nbig;
1980  } else {
1981  nwh = UChar_t(nbig);
1982  *this << nwh;
1983  }
1984  WriteFastArray(obj->data(), nbig);
1985  } else {
1986  // TODO: make writing of string directly
1987  }
1988 }
1989 
1990 ////////////////////////////////////////////////////////////////////////////////
1991 /// Read a char* string
1992 
1993 void TBufferSQL2::ReadCharStar(char *&s)
1994 {
1995  delete[] s;
1996  s = nullptr;
1997 
1998  Int_t nch;
1999  *this >> nch;
2000  if (nch > 0) {
2001  s = new char[nch + 1];
2002  ReadFastArray(s, nch);
2003  s[nch] = 0;
2004  }
2005 }
2006 
2007 ////////////////////////////////////////////////////////////////////////////////
2008 /// Write a char* string
2009 
2010 void TBufferSQL2::WriteCharStar(char *s)
2011 {
2012  Int_t nch = 0;
2013  if (s) {
2014  nch = strlen(s);
2015  *this << nch;
2016  WriteFastArray(s, nch);
2017  } else {
2018  *this << nch;
2019  }
2020 }
2021 
2022 ////////////////////////////////////////////////////////////////////////////////
2023 /// Writes Bool_t value to buffer
2024 
2025 void TBufferSQL2::WriteBool(Bool_t b)
2026 {
2027  SqlWriteBasic(b);
2028 }
2029 
2030 ////////////////////////////////////////////////////////////////////////////////
2031 /// Writes Char_t value to buffer
2032 
2033 void TBufferSQL2::WriteChar(Char_t c)
2034 {
2035  SqlWriteBasic(c);
2036 }
2037 
2038 ////////////////////////////////////////////////////////////////////////////////
2039 /// Writes UChar_t value to buffer
2040 
2041 void TBufferSQL2::WriteUChar(UChar_t c)
2042 {
2043  SqlWriteBasic(c);
2044 }
2045 
2046 ////////////////////////////////////////////////////////////////////////////////
2047 /// Writes Short_t value to buffer
2048 
2049 void TBufferSQL2::WriteShort(Short_t h)
2050 {
2051  SqlWriteBasic(h);
2052 }
2053 
2054 ////////////////////////////////////////////////////////////////////////////////
2055 /// Writes UShort_t value to buffer
2056 
2057 void TBufferSQL2::WriteUShort(UShort_t h)
2058 {
2059  SqlWriteBasic(h);
2060 }
2061 
2062 ////////////////////////////////////////////////////////////////////////////////
2063 /// Writes Int_t value to buffer
2064 
2065 void TBufferSQL2::WriteInt(Int_t i)
2066 {
2067  SqlWriteBasic(i);
2068 }
2069 
2070 ////////////////////////////////////////////////////////////////////////////////
2071 /// Writes UInt_t value to buffer
2072 
2073 void TBufferSQL2::WriteUInt(UInt_t i)
2074 {
2075  SqlWriteBasic(i);
2076 }
2077 
2078 ////////////////////////////////////////////////////////////////////////////////
2079 /// Writes Long_t value to buffer
2080 
2081 void TBufferSQL2::WriteLong(Long_t l)
2082 {
2083  SqlWriteBasic(l);
2084 }
2085 
2086 ////////////////////////////////////////////////////////////////////////////////
2087 /// Writes ULong_t value to buffer
2088 
2089 void TBufferSQL2::WriteULong(ULong_t l)
2090 {
2091  SqlWriteBasic(l);
2092 }
2093 
2094 ////////////////////////////////////////////////////////////////////////////////
2095 /// Writes Long64_t value to buffer
2096 
2097 void TBufferSQL2::WriteLong64(Long64_t l)
2098 {
2099  SqlWriteBasic(l);
2100 }
2101 
2102 ////////////////////////////////////////////////////////////////////////////////
2103 /// Writes ULong64_t value to buffer
2104 
2105 void TBufferSQL2::WriteULong64(ULong64_t l)
2106 {
2107  SqlWriteBasic(l);
2108 }
2109 
2110 ////////////////////////////////////////////////////////////////////////////////
2111 /// Writes Float_t value to buffer
2112 
2113 void TBufferSQL2::WriteFloat(Float_t f)
2114 {
2115  SqlWriteBasic(f);
2116 }
2117 
2118 ////////////////////////////////////////////////////////////////////////////////
2119 /// Writes Double_t value to buffer
2120 
2121 void TBufferSQL2::WriteDouble(Double_t d)
2122 {
2123  SqlWriteBasic(d);
2124 }
2125 
2126 ////////////////////////////////////////////////////////////////////////////////
2127 /// Writes array of characters to buffer
2128 
2129 void TBufferSQL2::WriteCharP(const Char_t *c)
2130 {
2131  SqlWriteValue(c, sqlio::CharStar);
2132 }
2133 
2134 ////////////////////////////////////////////////////////////////////////////////
2135 /// converts Char_t to string and creates correspondent sql structure
2136 
2137 Bool_t TBufferSQL2::SqlWriteBasic(Char_t value)
2138 {
2139  char buf[50];
2140  snprintf(buf, sizeof(buf), "%d", value);
2141  return SqlWriteValue(buf, sqlio::Char);
2142 }
2143 
2144 ////////////////////////////////////////////////////////////////////////////////
2145 /// converts Short_t to string and creates correspondent sql structure
2146 
2147 Bool_t TBufferSQL2::SqlWriteBasic(Short_t value)
2148 {
2149  char buf[50];
2150  snprintf(buf, sizeof(buf), "%hd", value);
2151  return SqlWriteValue(buf, sqlio::Short);
2152 }
2153 
2154 ////////////////////////////////////////////////////////////////////////////////
2155 /// converts Int_t to string and creates correspondent sql structure
2156 
2157 Bool_t TBufferSQL2::SqlWriteBasic(Int_t value)
2158 {
2159  char buf[50];
2160  snprintf(buf, sizeof(buf), "%d", value);
2161  return SqlWriteValue(buf, sqlio::Int);
2162 }
2163 
2164 ////////////////////////////////////////////////////////////////////////////////
2165 /// converts Long_t to string and creates correspondent sql structure
2166 
2167 Bool_t TBufferSQL2::SqlWriteBasic(Long_t value)
2168 {
2169  char buf[50];
2170  snprintf(buf, sizeof(buf), "%ld", value);
2171  return SqlWriteValue(buf, sqlio::Long);
2172 }
2173 
2174 ////////////////////////////////////////////////////////////////////////////////
2175 /// converts Long64_t to string and creates correspondent sql structure
2176 
2177 Bool_t TBufferSQL2::SqlWriteBasic(Long64_t value)
2178 {
2179  std::string buf = std::to_string(value);
2180  return SqlWriteValue(buf.c_str(), sqlio::Long64);
2181 }
2182 
2183 ////////////////////////////////////////////////////////////////////////////////
2184 /// converts Float_t to string and creates correspondent sql structure
2185 
2186 Bool_t TBufferSQL2::SqlWriteBasic(Float_t value)
2187 {
2188  char buf[200];
2189  ConvertFloat(value, buf, sizeof(buf), kTRUE);
2190  return SqlWriteValue(buf, sqlio::Float);
2191 }
2192 
2193 ////////////////////////////////////////////////////////////////////////////////
2194 /// converts Double_t to string and creates correspondent sql structure
2195 
2196 Bool_t TBufferSQL2::SqlWriteBasic(Double_t value)
2197 {
2198  char buf[200];
2199  ConvertDouble(value, buf, sizeof(buf), kTRUE);
2200  return SqlWriteValue(buf, sqlio::Double);
2201 }
2202 
2203 ////////////////////////////////////////////////////////////////////////////////
2204 /// converts Bool_t to string and creates correspondent sql structure
2205 
2206 Bool_t TBufferSQL2::SqlWriteBasic(Bool_t value)
2207 {
2208  return SqlWriteValue(value ? sqlio::True : sqlio::False, sqlio::Bool);
2209 }
2210 
2211 ////////////////////////////////////////////////////////////////////////////////
2212 /// converts UChar_t to string and creates correspondent sql structure
2213 
2214 Bool_t TBufferSQL2::SqlWriteBasic(UChar_t value)
2215 {
2216  char buf[50];
2217  snprintf(buf, sizeof(buf), "%u", value);
2218  return SqlWriteValue(buf, sqlio::UChar);
2219 }
2220 
2221 ////////////////////////////////////////////////////////////////////////////////
2222 /// converts UShort_t to string and creates correspondent sql structure
2223 
2224 Bool_t TBufferSQL2::SqlWriteBasic(UShort_t value)
2225 {
2226  char buf[50];
2227  snprintf(buf, sizeof(buf), "%hu", value);
2228  return SqlWriteValue(buf, sqlio::UShort);
2229 }
2230 
2231 ////////////////////////////////////////////////////////////////////////////////
2232 /// converts UInt_t to string and creates correspondent sql structure
2233 
2234 Bool_t TBufferSQL2::SqlWriteBasic(UInt_t value)
2235 {
2236  char buf[50];
2237  snprintf(buf, sizeof(buf), "%u", value);
2238  return SqlWriteValue(buf, sqlio::UInt);
2239 }
2240 
2241 ////////////////////////////////////////////////////////////////////////////////
2242 /// converts ULong_t to string and creates correspondent sql structure
2243 
2244 Bool_t TBufferSQL2::SqlWriteBasic(ULong_t value)
2245 {
2246  char buf[50];
2247  snprintf(buf, sizeof(buf), "%lu", value);
2248  return SqlWriteValue(buf, sqlio::ULong);
2249 }
2250 
2251 ////////////////////////////////////////////////////////////////////////////////
2252 /// converts ULong64_t to string and creates correspondent sql structure
2253 
2254 Bool_t TBufferSQL2::SqlWriteBasic(ULong64_t value)
2255 {
2256  std::string buf = std::to_string(value);
2257  return SqlWriteValue(buf.c_str(), sqlio::ULong64);
2258 }
2259 
2260 //______________________________________________________________________________
2261 
2262 Bool_t TBufferSQL2::SqlWriteValue(const char *value, const char *tname)
2263 {
2264  // create structure in stack, which holds specified value
2265 
2266  Stack()->AddValue(value, tname);
2267 
2268  return kTRUE;
2269 }
2270 
2271 ////////////////////////////////////////////////////////////////////////////////
2272 /// Read current value from table and convert it to Char_t value
2273 
2274 void TBufferSQL2::SqlReadBasic(Char_t &value)
2275 {
2276  const char *res = SqlReadValue(sqlio::Char);
2277  if (res) {
2278  int n;
2279  sscanf(res, "%d", &n);
2280  value = n;
2281  } else
2282  value = 0;
2283 }
2284 
2285 ////////////////////////////////////////////////////////////////////////////////
2286 /// Read current value from table and convert it to Short_t value
2287 
2288 void TBufferSQL2::SqlReadBasic(Short_t &value)
2289 {
2290  const char *res = SqlReadValue(sqlio::Short);
2291  if (res)
2292  sscanf(res, "%hd", &value);
2293  else
2294  value = 0;
2295 }
2296 
2297 ////////////////////////////////////////////////////////////////////////////////
2298 /// Read current value from table and convert it to Int_t value
2299 
2300 void TBufferSQL2::SqlReadBasic(Int_t &value)
2301 {
2302  const char *res = SqlReadValue(sqlio::Int);
2303  if (res)
2304  sscanf(res, "%d", &value);
2305  else
2306  value = 0;
2307 }
2308 
2309 ////////////////////////////////////////////////////////////////////////////////
2310 /// Read current value from table and convert it to Long_t value
2311 
2312 void TBufferSQL2::SqlReadBasic(Long_t &value)
2313 {
2314  const char *res = SqlReadValue(sqlio::Long);
2315  if (res)
2316  sscanf(res, "%ld", &value);
2317  else
2318  value = 0;
2319 }
2320 
2321 ////////////////////////////////////////////////////////////////////////////////
2322 /// Read current value from table and convert it to Long64_t value
2323 
2324 void TBufferSQL2::SqlReadBasic(Long64_t &value)
2325 {
2326  const char *res = SqlReadValue(sqlio::Long64);
2327  if (res)
2328  value = (Long64_t)std::stoll(res);
2329  else
2330  value = 0;
2331 }
2332 
2333 ////////////////////////////////////////////////////////////////////////////////
2334 /// Read current value from table and convert it to Float_t value
2335 
2336 void TBufferSQL2::SqlReadBasic(Float_t &value)
2337 {
2338  const char *res = SqlReadValue(sqlio::Float);
2339  if (res)
2340  sscanf(res, "%f", &value);
2341  else
2342  value = 0.;
2343 }
2344 
2345 ////////////////////////////////////////////////////////////////////////////////
2346 /// Read current value from table and convert it to Double_t value
2347 
2348 void TBufferSQL2::SqlReadBasic(Double_t &value)
2349 {
2350  const char *res = SqlReadValue(sqlio::Double);
2351  if (res)
2352  sscanf(res, "%lf", &value);
2353  else
2354  value = 0.;
2355 }
2356 
2357 ////////////////////////////////////////////////////////////////////////////////
2358 /// Read current value from table and convert it to Bool_t value
2359 
2360 void TBufferSQL2::SqlReadBasic(Bool_t &value)
2361 {
2362  const char *res = SqlReadValue(sqlio::Bool);
2363  if (res)
2364  value = (strcmp(res, sqlio::True) == 0);
2365  else
2366  value = kFALSE;
2367 }
2368 
2369 ////////////////////////////////////////////////////////////////////////////////
2370 /// Read current value from table and convert it to UChar_t value
2371 
2372 void TBufferSQL2::SqlReadBasic(UChar_t &value)
2373 {
2374  const char *res = SqlReadValue(sqlio::UChar);
2375  if (res) {
2376  unsigned int n;
2377  sscanf(res, "%ud", &n);
2378  value = n;
2379  } else
2380  value = 0;
2381 }
2382 
2383 ////////////////////////////////////////////////////////////////////////////////
2384 /// Read current value from table and convert it to UShort_t value
2385 
2386 void TBufferSQL2::SqlReadBasic(UShort_t &value)
2387 {
2388  const char *res = SqlReadValue(sqlio::UShort);
2389  if (res)
2390  sscanf(res, "%hud", &value);
2391  else
2392  value = 0;
2393 }
2394 
2395 ////////////////////////////////////////////////////////////////////////////////
2396 /// Read current value from table and convert it to UInt_t value
2397 
2398 void TBufferSQL2::SqlReadBasic(UInt_t &value)
2399 {
2400  const char *res = SqlReadValue(sqlio::UInt);
2401  if (res)
2402  sscanf(res, "%u", &value);
2403  else
2404  value = 0;
2405 }
2406 
2407 ////////////////////////////////////////////////////////////////////////////////
2408 /// Read current value from table and convert it to ULong_t value
2409 
2410 void TBufferSQL2::SqlReadBasic(ULong_t &value)
2411 {
2412  const char *res = SqlReadValue(sqlio::ULong);
2413  if (res)
2414  sscanf(res, "%lu", &value);
2415  else
2416  value = 0;
2417 }
2418 
2419 ////////////////////////////////////////////////////////////////////////////////
2420 /// Read current value from table and convert it to ULong64_t value
2421 
2422 void TBufferSQL2::SqlReadBasic(ULong64_t &value)
2423 {
2424  const char *res = SqlReadValue(sqlio::ULong64);
2425  if (res)
2426  value = (ULong64_t)std::stoull(res);
2427  else
2428  value = 0;
2429 }
2430 
2431 ////////////////////////////////////////////////////////////////////////////////
2432 /// Read string value from current stack node
2433 
2434 const char *TBufferSQL2::SqlReadValue(const char *tname)
2435 {
2436  if (fErrorFlag > 0)
2437  return 0;
2438 
2439  if (!fCurrentData) {
2440  Error("SqlReadValue", "No object data to read from");
2441  fErrorFlag = 1;
2442  return 0;
2443  }
2444 
2445  if (!fIgnoreVerification)
2446  if (!fCurrentData->VerifyDataType(tname)) {
2447  fErrorFlag = 1;
2448  return 0;
2449  }
2450 
2451  fReadBuffer = fCurrentData->GetValue();
2452 
2453  fCurrentData->ShiftToNextValue();
2454 
2455  if (gDebug > 4)
2456  Info("SqlReadValue", "%s = %s", tname, fReadBuffer.Data());
2457 
2458  return fReadBuffer.Data();
2459 }
2460 
2461 ////////////////////////////////////////////////////////////////////////////////
2462 /// Read CharStar value, if it has special code, request it from large table
2463 
2464 const char *TBufferSQL2::SqlReadCharStarValue()
2465 {
2466  const char *res = SqlReadValue(sqlio::CharStar);
2467  if (!res || !fSQL)
2468  return nullptr;
2469 
2470  Long64_t objid = Stack()->DefineObjectId(kTRUE);
2471 
2472  Int_t strid = fSQL->IsLongStringCode(objid, res);
2473  if (strid <= 0)
2474  return res;
2475 
2476  fSQL->GetLongString(objid, strid, fReadBuffer);
2477 
2478  return fReadBuffer.Data();
2479 }
2480 
2481 ////////////////////////////////////////////////////////////////////////////////
2482 /// Push stack with structural information about streamed object
2483 
2484 TSQLStructure *TBufferSQL2::PushStack()
2485 {
2486  TSQLStructure *res = new TSQLStructure;
2487  if (!fStk) {
2488  fStructure = res;
2489  } else {
2490  fStk->Add(res);
2491  }
2492 
2493  fStk = res; // add in the stack
2494  return fStk;
2495 }
2496 
2497 ////////////////////////////////////////////////////////////////////////////////
2498 /// Pop stack
2499 
2500 TSQLStructure *TBufferSQL2::PopStack()
2501 {
2502  if (!fStk)
2503  return nullptr;
2504  fStk = fStk->GetParent();
2505  return fStk;
2506 }
2507 
2508 ////////////////////////////////////////////////////////////////////////////////
2509 /// returns head of stack
2510 
2511 TSQLStructure *TBufferSQL2::Stack(Int_t depth)
2512 {
2513  TSQLStructure *curr = fStk;
2514  while ((depth-- > 0) && curr)
2515  curr = curr->GetParent();
2516  return curr;
2517 }
2518 
2519 ////////////////////////////////////////////////////////////////////////////////
2520 /// Return current streamer info element
2521 
2522 TVirtualStreamerInfo *TBufferSQL2::GetInfo()
2523 {
2524  return Stack()->GetStreamerInfo();
2525 }