1 /*************************************************************************** 2 dstructdesc.hpp - GDL struct descriptor 3 ------------------- 4 begin : July 22 2002 5 copyright : (C) 2002 by Marc Schellens 6 email : m_schellens@users.sf.net 7 ***************************************************************************/ 8 9 /*************************************************************************** 10 * * 11 * This program is free software; you can redistribute it and/or modify * 12 * it under the terms of the GNU General Public License as published by * 13 * the Free Software Foundation; either version 2 of the License, or * 14 * (at your option) any later version. * 15 * * 16 ***************************************************************************/ 17 18 #ifndef DSTRUCTDESC_HPP_ 19 #define DSTRUCTDESC_HPP_ 20 21 #include "includefirst.hpp" // USE_EIGEN3 22 23 #include <vector> 24 #include <deque> 25 #include <string> 26 #include <functional> 27 28 #include "basegdl.hpp" 29 #include "dpro.hpp" 30 #include "typedefs.hpp" 31 #include "overload.hpp" 32 33 class DStructBase 34 { 35 private: 36 std::vector<SizeT> tagOffset; // data offset of tags 37 38 protected: 39 std::vector<BaseGDL*> tags; // Data_<Sp> for data, 'Sp' for structList elements Add(BaseGDL * t)40 void Add( BaseGDL* t) 41 { 42 tags.push_back(t); // grabs 43 // attention: there is a subtle difference for NBytes() 44 // for SpDString (considers sizeof( DString)), used here 45 // and DStringGDL (considers actual string sizes) 46 SizeT nBytes = tags.back()->NBytes(); 47 48 // 2-May-2019 GVJ 49 // Align data in structures according to data lengthin accord with IDL). 50 /******************** 51 #ifdef USE_EIGEN 52 (This forced all data to be aligned on 16-bytes. There was no perceptible perfomance gain, 53 nor was any penalty found for simply using 2-byte alignment. 54 55 const int alignmentInBytes = 2; // there was no performance difference. 56 57 assert( sizeof( char*) <= 16); 58 const int alignmentInBytes = 16; // set to multiple of 16 >= sizeof( char*) 59 #else 60 const int alignmentInBytes = sizeof( char*); 61 #endif 62 ******************/ 63 64 const int alignmentInBytes = sizeof( char*); 65 66 // The old way: 67 /****** 68 SizeT exceed = nBytes % alignmentInBytes; 69 if( exceed > 0) 70 nBytes += alignmentInBytes - exceed; 71 *****/ 72 // replacement: 73 SizeT Align = (nBytes < alignmentInBytes)? nBytes: alignmentInBytes; 74 SizeT initOffset = tagOffset.back(); 75 SizeT Oddbytes = initOffset % Align; 76 if(Oddbytes > 0) { 77 tagOffset.pop_back(); 78 tagOffset.push_back( initOffset + (Align-Oddbytes)); 79 } 80 81 // valid tagOffset (used by NBytes()) 82 tagOffset.push_back( tagOffset.back() + nBytes); 83 } 84 85 public: DStructBase()86 DStructBase(): tagOffset( 1, 0) 87 {} 88 DStructBase(const DStructBase * d_)89 DStructBase( const DStructBase* d_): tags( d_->NTags()) 90 { 91 SizeT nTags = d_->NTags(); 92 for( SizeT t=0; t<nTags; ++t) 93 { 94 tags[ t] = d_->tags[ t]->GetTag(); 95 } 96 tagOffset = d_->tagOffset; 97 } 98 99 virtual ~DStructBase(); 100 operator [](const SizeT d1)101 BaseGDL*& operator[] (const SizeT d1) 102 { return tags[d1];} operator [](const SizeT d1) const103 const BaseGDL* operator[] (const SizeT d1) const 104 { return tags[d1];} 105 Offset(SizeT t,SizeT ix) const106 SizeT Offset( SizeT t, SizeT ix) const 107 { 108 return (tagOffset[ t] + ix * NBytes()); 109 } Offset(SizeT t) const110 SizeT Offset( SizeT t) const 111 { 112 return tagOffset[ t]; 113 } 114 NTags() const115 SizeT NTags() const { return tags.size();} NBytes() const116 SizeT NBytes() const { return tagOffset.back();} 117 118 bool ContainsStringPtrObject(); 119 }; 120 121 122 class DStructDesc; 123 typedef std::vector<DStructDesc*> StructListT; 124 125 // descriptor of structs layout ************************************************ 126 // unnamed struct 127 // this is never used directly, only DStructDesc (see below) 128 class DUStructDesc: public DStructBase 129 { 130 private: 131 std::vector<std::string> tNames; // tag names 132 133 public: DUStructDesc()134 DUStructDesc(): DStructBase() 135 {} 136 DUStructDesc(const DUStructDesc * d_)137 DUStructDesc( const DUStructDesc* d_): 138 DStructBase( d_), 139 tNames( d_->tNames) 140 {} 141 142 // ~DUStructDesc(); 143 144 void AddTag( const std::string& tagName, const BaseGDL* data); 145 TagIndex(const std::string & tN) const146 int TagIndex( const std::string& tN) const 147 { 148 for( SizeT i=0; i< tNames.size(); i++) 149 if( tNames[i] == tN) return static_cast<int>(i); 150 return -1; 151 } TagName(const SizeT ix) const152 const std::string& TagName( const SizeT ix) const 153 { 154 return tNames[ ix]; 155 } 156 }; 157 158 // named struct 159 class DStructDesc: public DUStructDesc 160 { 161 private: 162 163 SizeT refCount; 164 165 bool isUnnamed; 166 167 // operatorList != NULL means inherited from GDL_OBJECT 168 OperatorList* operatorList; 169 // avoid extra allocation 170 // char operatorListBuffer[ sizeof(operatorList)]; 171 // ONLY FOR GDL_OBJECT InitOperatorList()172 void InitOperatorList() { assert( operatorList == NULL); operatorList = new OperatorList();} 173 friend void InitStructs(); // restrict usage to definition of GDL_OBECT 174 175 private: 176 177 std::string name; 178 StructListT parent; // parent classes 179 IDList noDirectMembers; 180 181 FunListT fun; // member functions 182 ProListT pro; // member procedures 183 DStructDesc(const DStructDesc &)184 DStructDesc( const DStructDesc&) {} // disabeld 185 186 public: DStructDesc(const std::string & n)187 DStructDesc( const std::string& n): DUStructDesc(), refCount( 1), operatorList( NULL), name(n) 188 { 189 // name=n; 190 // if this is to be changed, see also: 191 // DStructGDL::DStructGDL( const string& name_) // (dstructgdl.cpp) 192 isUnnamed = (name[0] == '$'); 193 } 194 195 // private: 196 // // this is only used for unnamed structs -> only copy name from 'this' 197 // DStructDesc( const DStructDesc* d_): 198 // DUStructDesc( d_), 199 // name( d_->name) // must be "$..." 200 // {} 201 // public: 202 ~DStructDesc(); 203 204 friend bool operator==(const DStructDesc& left, const DStructDesc& right); 205 friend bool operator!=(const DStructDesc& left, const DStructDesc& right); 206 Name() const207 const std::string& Name() const { return name;} 208 FunList()209 FunListT& FunList() 210 { 211 return fun; 212 } 213 FindInFunList(const std::string & n)214 DFun* FindInFunList( const std::string& n) 215 { 216 FunListT::iterator p=std::find_if(fun.begin(),fun.end(),Is_eq<DFun>(n)); 217 if( p != fun.end()) return *p; 218 return NULL; 219 } 220 ProList()221 ProListT& ProList() 222 { 223 return pro; 224 } 225 FindInProList(const std::string & n)226 DPro* FindInProList( const std::string& n) 227 { 228 ProListT::iterator p=std::find_if(pro.begin(),pro.end(),Is_eq<DPro>(n)); 229 if( p != pro.end()) return *p; 230 return NULL; 231 } 232 233 DPro* GetPro( const std::string& pName); 234 DPro* GetPro( const std::string& pName, const std::string& parentName); 235 DFun* GetFun( const std::string& pName); 236 DFun* GetFun( const std::string& pName, const std::string& parentName); 237 238 // if this is to be changed, see also: 239 // DStructGDL::DStructGDL( const string& name_) // (dstructgdl.cpp) IsUnnamed() const240 bool IsUnnamed() const { return isUnnamed;} 241 242 // bool InheritsGDL_OBJECT() const { return (operatorList != NULL);} GetOperatorList() const243 OperatorList* GetOperatorList() const { return operatorList;} 244 GetOperator(SizeT i) const245 DSubUD* GetOperator( SizeT i) const 246 { if( operatorList == NULL) return NULL; return (*operatorList)[ i];} 247 SetOperator(SizeT i,DSubUD * op)248 void SetOperator( SizeT i, DSubUD* op) 249 { if( operatorList == NULL) return; operatorList->SetOperator( i, op);} 250 251 // copy appropiate member subroutines from fun and pro lists 252 void SetupOperators(); 253 IsParent(const std::string & p) const254 bool IsParent( const std::string& p) const 255 { 256 if( p == name) return true; 257 258 SizeT nParents=parent.size(); 259 for( SizeT i=0; i<nParents; i++) 260 { 261 if( parent[i]->IsParent( p)) return true; 262 } 263 return false; 264 } 265 266 void AddParent( DStructDesc*); 267 void AddParentListOnly( DStructDesc*); //for restore 268 269 /** 270 * @brief fills a std::vector of strings with all the object's direct ancestors names 271 * @param pNames the std::vector of strings returned filled. 272 * 273 * fills the @pNames std::vector of strings with all the object's direct ancestors names 274 */ GetParentNames(std::vector<std::string> & pNames) const275 void GetParentNames(std::vector< std::string>& pNames) const { 276 SizeT nParents = parent.size(); 277 for (SizeT i = 0; i < nParents; ++i) { 278 pNames.push_back(parent[i]->Name()); 279 } 280 } 281 /** 282 * @brief fills a std::set of strings with all the object's direct ancestors names 283 * @param pNames the std::set of strings returned filled. 284 * 285 * fills the @pNames std::set (ordered) of strings with all the object's direct ancestors names 286 */ GetParentNames(std::set<std::string> & pNames) const287 void GetParentNames(std::set< std::string>& pNames) const { 288 SizeT nParents = parent.size(); 289 for (SizeT i = 0; i < nParents; ++i) { 290 pNames.insert(parent[i]->Name()); 291 } 292 } 293 /** 294 * @brief fills a std::vector of strings with all the object's ancestors names (direct, inherited) 295 * @param aaNames the vector of strings returned filled. 296 * 297 * fills the @aaNames vector of strings with all the object's parents names 298 */ GetAllAncestorsNames(std::vector<std::string> & aaNames) const299 void GetAllAncestorsNames(std::vector< std::string>& aaNames) const { 300 SizeT nParents = parent.size(); 301 for (SizeT i = 0; i < nParents; ++i) { 302 aaNames.push_back(parent[i]->Name()); 303 } 304 //parents of parents... 305 for (SizeT i = 0; i < nParents; ++i) { 306 parent[i]->GetAllAncestorsNames(aaNames); 307 } 308 //remove dupes? 309 } 310 311 /** 312 * @brief fills a std::set of strings with all the object's ancestors names (direct, inherited) 313 * @param aaNames the vector of strings returned filled. 314 * 315 * fills the @aaNames vector of strings with all the object's parents names 316 */ GetAllAncestorsNames(std::set<std::string> & aaNames) const317 void GetAllAncestorsNames(std::set< std::string>& aaNames) const { 318 SizeT nParents = parent.size(); 319 for (SizeT i = 0; i < nParents; ++i) { 320 aaNames.insert(parent[i]->Name()); 321 } 322 //parents of parents... 323 for (SizeT i = 0; i < nParents; ++i) { 324 parent[i]->GetAllAncestorsNames(aaNames); 325 } 326 } 327 /** 328 * @brief fills a std::set of strings with all the object's non-direct ancestors 329 * @param aNames the vector of strings returned filled. 330 * 331 * fills the @aNames std::set of strings with all the object's non-direct ancestors 332 */ GetAncestorsNames(std::set<std::string> & aNames) const333 void GetAncestorsNames(std::set< std::string>& aNames) const { 334 std::vector<DStructDesc*>direct; 335 SizeT nParents = parent.size(); 336 for (SizeT i = 0; i < nParents; ++i) { 337 direct.push_back(parent[i]); 338 } 339 //parents of parents... 340 for (SizeT i = 0; i < nParents; ++i) { 341 direct[i]->GetAllAncestorsNames(aNames); 342 } 343 } 344 GetNumberOfParents()345 int GetNumberOfParents(){ 346 return parent.size(); 347 } 348 349 void AssureIdentical( DStructDesc* d); 350 // DStructDesc* FindEqual( const StructListT& sL); 351 352 // for unnamed structs (typetraits.cpp) AddRef()353 void AddRef() 354 { 355 ++refCount; 356 } Delete()357 void Delete() 358 { 359 if( --refCount) return; 360 delete this; 361 } 362 }; 363 364 365 class DStruct_eq: public std::unary_function<DStructDesc,bool> 366 { 367 std::string name; 368 369 public: DStruct_eq(const std::string & s)370 explicit DStruct_eq(const std::string& s): name(s) {} operator ()(const DStructDesc * v) const371 bool operator() (const DStructDesc* v) const { return v->Name() == name;} 372 }; 373 374 DStructDesc* FindInStructList(StructListT, const std::string& name); 375 DStructDesc* FindObjectInStructList(StructListT, const std::string& name); 376 377 // actually holding the data ********************************************** 378 // class DStructGDL see dstructgdl.hpp 379 380 #endif 381