Go to the documentation of this file.00001 #include "CondCore/DBCommon/interface/BlobStreamerPluginFactory.h"
00002 #include "CondCore/DBCommon/interface/Exception.h"
00003 #include "TBufferBlobStreamingService.h"
00004
00005 #include <algorithm>
00006 #include <typeinfo>
00007 #include <string>
00008 #include <cstring>
00009
00010 #include "TBufferFile.h"
00011 #include "Reflex/Reflex.h"
00012 #include "Cintex/Cintex.h"
00013
00014 typedef void (TBuffer::*WriteArrayFn_t)(const void *obj, Int_t n);
00015 typedef void (TBuffer::*ReadArrayFn_t)(void *obj, Int_t n);
00016
00017 #define PRIMITIVE(x) { \
00018 typeid(x), \
00019 reinterpret_cast<WriteArrayFn_t>( \
00020 (void (TBuffer::*)(const x*, Int_t))&TBuffer::WriteFastArray), \
00021 reinterpret_cast<ReadArrayFn_t>( \
00022 (void (TBuffer::*)(x*, Int_t))&TBuffer::ReadFastArray) \
00023 }
00024
00025 struct Primitive {
00026 const std::type_info &type;
00027 WriteArrayFn_t writeArrayFn;
00028 ReadArrayFn_t readArrayFn;
00029
00030 inline bool operator == (const std::type_info &other) const
00031 { return type == other; }
00032 } static const primitives[] = {
00033 PRIMITIVE(Bool_t),
00034 PRIMITIVE(Char_t),
00035 PRIMITIVE(UChar_t),
00036 PRIMITIVE(Short_t),
00037 PRIMITIVE(UShort_t),
00038 PRIMITIVE(Int_t),
00039 PRIMITIVE(UInt_t),
00040 PRIMITIVE(Long_t),
00041 PRIMITIVE(ULong_t),
00042 PRIMITIVE(Long64_t),
00043 PRIMITIVE(ULong64_t),
00044 PRIMITIVE(Float_t),
00045 PRIMITIVE(Double_t)
00046 };
00047
00048 static const std::size_t nPrimitives =
00049 (sizeof primitives / sizeof primitives[0]);
00050
00051 #undef PRIMTIVE
00052
00053 cond::TBufferBlobTypeInfo::TBufferBlobTypeInfo( Reflex::Type const & type_)
00054 : m_arraySize(0), m_class(0), m_primitive(0)
00055 {
00056 static bool cintexInitialized = false;
00057 if (!cintexInitialized) {
00058 cintexInitialized = true;
00059 ROOT::Cintex::Cintex::Enable();
00060 }
00061
00062 Reflex::Type type = type_;
00063 while(true) {
00064 type = type.FinalType();
00065
00066 if (!type.IsArray())
00067 break;
00068
00069 if (!m_arraySize)
00070 m_arraySize = 1;
00071 m_arraySize *= type.ArrayLength();
00072 type = type.ToType();
00073 }
00074
00075 if (type.IsClass()) {
00076 const std::type_info &typeInfo = type.TypeInfo();
00077 m_class = TClass::GetClass(typeInfo);
00078 if (!m_class)
00079 throw cond::Exception("TBufferBlobTypeInfo::TBufferBlobTypeInfo "
00080 "No ROOT class registered for " + type.Name());
00081 } else if (type.IsFundamental()) {
00082 if (!m_arraySize)
00083 throw cond::Exception("TBufferBlobTypeInfo::TBufferBlobTypeInfo "
00084 "Only arrays of primitive types supported. "
00085 "Please to not use a Blob for this member.");
00086
00087 m_primitive = std::find(primitives, primitives + nPrimitives,
00088 type.TypeInfo()) - primitives;
00089 if (m_primitive >= nPrimitives)
00090 throw cond::Exception("TBufferBlobTypeInfo::TBufferBlobTypeInfo "
00091 "Cannot handle primitive type " + type.Name());
00092 } else
00093 throw cond::Exception("TBufferBlobTypeInfo::TBufferBlobTypeInfo "
00094 "Cannot handle C++ type " + type.Name());
00095 }
00096
00097
00098 cond::TBufferBlobStreamingService::TBufferBlobStreamingService(){
00099 }
00100
00101 cond::TBufferBlobStreamingService::~TBufferBlobStreamingService(){
00102 }
00103
00104 #include <boost/bind.hpp>
00105 namespace {
00106 char * reallocInBlob( boost::shared_ptr<coral::Blob> theBlob, char* p, size_t newsize, size_t oldsize) {
00107
00108 theBlob->resize(newsize);
00109 return (char*)theBlob->startingAddress();
00110
00111 }
00112 }
00113
00114 boost::shared_ptr<coral::Blob> cond::TBufferBlobStreamingService::write( const void* addr,
00115 Reflex::Type const & classDictionary,
00116 bool ){
00117 TBufferBlobTypeInfo theType( classDictionary );
00118 if (theType.m_class && theType.m_class->GetActualClass(addr) != theType.m_class)
00119 throw cond::Exception("TBufferBlobWriter::write object to stream is "
00120 "not of actual class.");
00121
00122 boost::shared_ptr<coral::Blob> theBlob( new coral::Blob );
00123
00124
00125
00126
00127 TBufferFile buffer(TBufferFile::kWrite);
00128 buffer.InitMap();
00129
00130 if (theType.m_arraySize && !theType.m_class)
00131 (buffer.*primitives[theType.m_primitive].writeArrayFn)(addr, theType.m_arraySize);
00132 else if (theType.m_arraySize)
00133 buffer.WriteFastArray(const_cast<void*>(addr), theType.m_class, theType.m_arraySize);
00134 else
00135 buffer.StreamObject(const_cast<void*>(addr), theType.m_class);
00136
00137 Int_t size = buffer.Length();
00138
00139 theBlob->resize(size);
00140 void *startingAddress = theBlob->startingAddress();
00141 std::memcpy(startingAddress, buffer.Buffer(), size);
00142
00143 return theBlob;
00144 }
00145
00146 void cond::TBufferBlobStreamingService::read( const coral::Blob& blobData,
00147 void* addr,
00148 Reflex::Type const & classDictionary ){
00149 TBufferBlobTypeInfo theType( classDictionary );
00150 const void *startingAddress = blobData.startingAddress();
00151 size_t size = blobData.size();
00152 if (!size)
00153 return;
00154
00155 TBufferFile buffer(TBufferFile::kRead, size,
00156 const_cast<void*>(startingAddress), kFALSE);
00157
00158 buffer.InitMap();
00159
00160 if (theType.m_arraySize && !theType.m_class)
00161 (buffer.*primitives[theType.m_primitive].readArrayFn)(addr, theType.m_arraySize);
00162 else if (theType.m_arraySize)
00163 buffer.ReadFastArray(addr, theType.m_class, theType.m_arraySize);
00164 else
00165 buffer.StreamObject(addr, theType.m_class);
00166 }
00167