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