Fix for UBSan build
[platform/upstream/doxygen.git] / src / membergroup.cpp
1 /******************************************************************************
2  *
3  * $Id: membergroup.cpp,v 1.19 2001/03/19 19:27:41 root Exp $
4  *
5  * Copyright (C) 1997-2012 by Dimitri van Heesch.
6  *
7  * Permission to use, copy, modify, and distribute this software and its
8  * documentation under the terms of the GNU General Public License is hereby 
9  * granted. No representations are made about the suitability of this software 
10  * for any purpose. It is provided "as is" without express or implied warranty.
11  * See the GNU General Public License for more details.
12  *
13  * Documents produced by Doxygen are derivative works derived from the
14  * input used in their production; they are not affected by this license.
15  *
16  */
17
18 #include "qtbc.h"
19 #include "membergroup.h"
20 #include "memberlist.h"
21 #include "outputlist.h"
22 #include "util.h"
23 #include "classdef.h"
24 #include "namespacedef.h"
25 #include "filedef.h"
26 #include "language.h"
27 #include "groupdef.h"
28 #include "doxygen.h"
29 #include "docparser.h"
30 #include "marshal.h"
31 #include "entry.h"
32 #include "md5.h"
33
34 //static QCString idToName(int id)
35 //{
36 //  QCString result;
37 //  result.sprintf("mgroup_%d",id);
38 //  return result;
39 //}
40
41 MemberGroup::MemberGroup()
42 {
43 }
44
45 MemberGroup::MemberGroup(Definition *parent,
46       int id,const char *hdr,const char *d,const char *docFile) 
47 {
48   //printf("New member group id=%d header=%s desc=%s\n",id,hdr,d);
49   memberList      = new MemberList(MemberList::memberGroup);
50   grpId           = id;
51   grpHeader       = hdr;
52   doc             = d;
53   scope           = 0;
54   inSameSection   = TRUE;
55   inDeclSection   = 0;
56   m_numDecMembers = -1;
57   m_numDocMembers = -1;
58   m_parent        = parent;
59   m_docFile       = docFile;
60   m_xrefListItems = 0;
61   //printf("Member group docs=`%s'\n",doc.data());
62 }
63
64 MemberGroup::~MemberGroup()
65 {
66   delete memberList;
67 }
68
69 void MemberGroup::insertMember(MemberDef *md)
70 {
71   //printf("MemberGroup::insertMember m_parent=%s memberList=%p count=%d"
72   //       " member section list: %p: md=%p:%s\n",
73   //       m_parent ? m_parent->name().data() : "<null>",
74   //       memberList->first() ? memberList->first()->getSectionList(m_parent) : 0,
75   //       memberList->count(),
76   //       md->getSectionList(m_parent),
77   //       md,md->name().data());
78
79   MemberDef *firstMd = memberList->first();
80   if (inSameSection && memberList->count()>0 && 
81       firstMd->getSectionList(m_parent)!=md->getSectionList(m_parent))
82   {
83     inSameSection=FALSE;
84   }
85   else if (inDeclSection==0)
86   {
87     inDeclSection = md->getSectionList(m_parent);
88     //printf("inDeclSection=%p type=%d\n",inDeclSection,inDeclSection->listType());
89   }
90   memberList->append(md);
91
92   // copy the group of the first member in the memberGroup
93   GroupDef *gd;
94   if (firstMd && (gd=firstMd->getGroupDef()))
95   {
96     md->setGroupDef(gd, firstMd->getGroupPri(), 
97                     firstMd->getGroupFileName(), firstMd->getGroupStartLine(), 
98                     firstMd->getGroupHasDocs());
99     gd->insertMember(md);
100   }
101 }
102
103
104 void MemberGroup::setAnchors(ClassDef *context)
105 {
106   ::setAnchors(context,'z',memberList,grpId);
107 }
108
109 void MemberGroup::writeDeclarations(OutputList &ol,
110                ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,
111                bool showInline)
112 {
113   //printf("MemberGroup::writeDeclarations() %s\n",grpHeader.data());
114   QCString ldoc = doc;
115   if (!ldoc.isEmpty()) ldoc.prepend("<a name=\""+anchor()+"\" id=\""+anchor()+"\"></a>");
116   memberList->writeDeclarations(ol,cd,nd,fd,gd,grpHeader,ldoc,FALSE,showInline);
117 }
118
119 void MemberGroup::writePlainDeclarations(OutputList &ol,
120                ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,
121                ClassDef *inheritedFrom,const char *inheritId
122               )
123 {
124   //printf("MemberGroup::writePlainDeclarations() memberList->count()=%d\n",memberList->count());
125   memberList->writePlainDeclarations(ol,cd,nd,fd,gd,inheritedFrom,inheritId);
126 }
127
128 void MemberGroup::writeDocumentation(OutputList &ol,const char *scopeName,
129                Definition *container,bool showEnumValues,bool showInline)
130 {
131   memberList->writeDocumentation(ol,scopeName,container,0,showEnumValues,showInline);
132 }
133
134 void MemberGroup::writeDocumentationPage(OutputList &ol,const char *scopeName,
135                Definition *container)
136 {
137   memberList->writeDocumentationPage(ol,scopeName,container);
138 }
139
140 void MemberGroup::addGroupedInheritedMembers(OutputList &ol,ClassDef *cd,
141                MemberList::ListType lt,
142                ClassDef *inheritedFrom,const QCString &inheritId)
143 {
144   //printf("** addGroupedInheritedMembers()\n");
145   MemberListIterator li(*memberList);
146   MemberDef *md;
147   for (li.toFirst();(md=li.current());++li)
148   {
149     //printf("matching %d == %d\n",lt,md->getSectionList(m_parent)->listType());
150     if (lt==md->getSectionList(m_parent)->listType())
151     {
152       MemberList ml(lt);
153       ml.append(md);
154       ml.writePlainDeclarations(ol,cd,0,0,0,inheritedFrom,inheritId);
155     }
156   }
157 }
158
159 int MemberGroup::countGroupedInheritedMembers(MemberList::ListType lt)
160 {
161   //printf("** countGroupedInheritedMembers()\n");
162   int count=0;
163   MemberListIterator li(*memberList);
164   MemberDef *md;
165   for (li.toFirst();(md=li.current());++li)
166   {
167     //printf("matching %d == %d\n",lt,md->getSectionList(m_parent)->listType());
168     if (lt==md->getSectionList(m_parent)->listType())
169     {
170       count++;
171     }
172   }
173   return count;
174 }
175
176
177 /*! Add this group as a subsection of the declaration section, instead
178  *  of rendering it in its own section
179  */
180 void MemberGroup::addToDeclarationSection()
181 {
182   if (inDeclSection)
183   {
184     //printf("Adding group %p to list %p (type=%d)\n",this,
185     //                              inDeclSection,inDeclSection->listType());
186     inDeclSection->addMemberGroup(this);
187   }
188 }
189
190 int MemberGroup::countDecMembers(GroupDef *gd)
191 {
192   if (m_numDecMembers==-1) /* number of member not cached */
193   {
194     memberList->countDecMembers(gd);
195     m_numDecMembers = memberList->numDecMembers();
196   }
197   return m_numDecMembers;
198 }
199
200 int MemberGroup::countDocMembers()
201 {
202   if (m_numDocMembers==-1)
203   {
204     memberList->countDocMembers();
205     m_numDocMembers = memberList->numDocMembers();
206   }
207   return m_numDocMembers;
208 }
209
210 int MemberGroup::countInheritableMembers(ClassDef *inheritedFrom) const
211 {
212   return memberList->countInheritableMembers(inheritedFrom);
213 }
214
215
216 void MemberGroup::distributeMemberGroupDocumentation()
217 {
218   //printf("MemberGroup::distributeMemberGroupDocumentation() %s\n",grpHeader.data());
219   MemberDef *md=memberList->first();
220   while (md)
221   {
222     //printf("checking md=%s\n",md->name().data());
223     // find the first member of the group with documentation
224     if (!md->documentation().isEmpty()       ||
225         !md->briefDescription().isEmpty()    ||
226         !md->inbodyDocumentation().isEmpty()
227        )
228     {
229       //printf("found it!\n");
230       break;
231     }
232     md=memberList->next();
233   }
234   if (md) // distribute docs of md to other members of the list
235   {
236     //printf("Member %s has documentation!\n",md->name().data());
237     MemberDef *omd=memberList->first();
238     while (omd)
239     {
240       if (md!=omd && omd->documentation().isEmpty() && 
241                      omd->briefDescription().isEmpty() && 
242                      omd->inbodyDocumentation().isEmpty()
243          )
244       {
245         //printf("Copying documentation to member %s\n",omd->name().data());
246         omd->setBriefDescription(md->briefDescription(),md->briefFile(),md->briefLine());
247         omd->setDocumentation(md->documentation(),md->docFile(),md->docLine());
248         omd->setInbodyDocumentation(md->inbodyDocumentation(),md->inbodyFile(),md->inbodyLine());
249       }
250       omd=memberList->next();
251     }
252   }
253 }
254
255 int MemberGroup::varCount() const
256 {
257   return memberList->varCount();
258 }
259
260 int MemberGroup::funcCount() const      
261
262   return memberList->funcCount(); 
263 }
264
265 int MemberGroup::enumCount() const      
266
267   return memberList->enumCount(); 
268 }
269
270 int MemberGroup::enumValueCount() const 
271
272   return memberList->enumValueCount(); 
273 }
274
275 int MemberGroup::typedefCount() const   
276
277   return memberList->typedefCount(); 
278 }
279
280 int MemberGroup::protoCount() const     
281
282   return memberList->protoCount(); 
283 }
284
285 int MemberGroup::defineCount() const    
286
287   return memberList->defineCount(); 
288 }
289
290 int MemberGroup::friendCount() const    
291
292   return memberList->friendCount(); 
293 }
294
295 int MemberGroup::numDecMembers() const  
296
297   return memberList->numDecMembers(); 
298 }
299
300 int MemberGroup::numDocMembers() const  
301
302   return memberList->numDocMembers(); 
303 }
304
305 void MemberGroup::setInGroup(bool b)
306 {
307   memberList->setInGroup(b);
308 }
309
310 QCString MemberGroup::anchor() const
311 {
312   uchar md5_sig[16];
313   QCString sigStr(33);
314   QCString locHeader = grpHeader;
315   if (locHeader.isEmpty()) locHeader="[NOHEADER]";
316   MD5Buffer((const unsigned char *)locHeader.data(),locHeader.length(),md5_sig);
317   MD5SigToString(md5_sig,sigStr.data(),33);
318   return "amgrp"+sigStr;
319 }
320
321 void MemberGroup::addListReferences(Definition *def)
322 {
323   memberList->addListReferences(def);
324   if (m_xrefListItems && def)
325   {
326     QCString name = def->getOutputFileBase()+"#"+anchor();
327     addRefItem(m_xrefListItems,
328         name,
329         theTranslator->trGroup(TRUE,TRUE),
330         name,
331         grpHeader,0);
332   }
333 }
334
335 void MemberGroup::findSectionsInDocumentation()
336 {
337   docFindSections(doc,0,this,m_docFile);
338   memberList->findSectionsInDocumentation();
339 }
340
341 void MemberGroup::marshal(StorageIntf *s)
342 {
343   marshalMemberList(s,memberList);
344   marshalObjPointer(s,inDeclSection); // reference only
345   marshalInt(s,grpId);
346   marshalQCString(s,grpHeader);
347   marshalQCString(s,fileName);
348   marshalObjPointer(s,scope);
349   marshalQCString(s,doc);
350   marshalBool(s,inSameSection);
351   marshalInt(s,m_numDecMembers);
352   marshalInt(s,m_numDocMembers);
353   marshalObjPointer(s,m_parent);
354   marshalQCString(s,m_docFile);
355   marshalItemInfoList (Doxygen::symbolStorage,m_xrefListItems);
356 }
357
358 void MemberGroup::unmarshal(StorageIntf *s)
359 {
360   memberList      = unmarshalMemberList(s);
361   inDeclSection   = (MemberList *)unmarshalObjPointer(s); 
362   grpId           = unmarshalInt(s);
363   grpHeader       = unmarshalQCString(s);
364   fileName        = unmarshalQCString(s);
365   scope           = (Definition *)unmarshalObjPointer(s);
366   doc             = unmarshalQCString(s);
367   inSameSection   = unmarshalBool(s);
368   m_numDecMembers = unmarshalInt(s);
369   m_numDocMembers = unmarshalInt(s);
370   m_parent        = (Definition *)unmarshalObjPointer(s);
371   m_docFile       = unmarshalQCString(s);
372   m_xrefListItems = unmarshalItemInfoList (Doxygen::symbolStorage);
373 }
374
375 void MemberGroup::setRefItems(const QList<ListItemInfo> *sli)
376 {
377   if (sli)
378   {
379     // deep copy the list
380     if (m_xrefListItems==0) 
381     {
382       m_xrefListItems=new QList<ListItemInfo>;
383       m_xrefListItems->setAutoDelete(TRUE);
384     }
385     QListIterator<ListItemInfo> slii(*sli);
386     ListItemInfo *lii;
387     for (slii.toFirst();(lii=slii.current());++slii)
388     {
389       m_xrefListItems->append(new ListItemInfo(*lii));
390     } 
391   }
392 }
393 //--------------------------------------------------------------------------
394
395 void MemberGroupInfo::setRefItems(const QList<ListItemInfo> *sli)
396 {
397   if (!sli) return;
398   if (m_sli==0)
399   {
400     m_sli = new QList<ListItemInfo>;
401     m_sli->setAutoDelete(TRUE);
402   }
403   QListIterator<ListItemInfo> slii(*sli);
404   ListItemInfo *ili;
405   for (slii.toFirst();(ili=slii.current());++slii)
406   {
407     m_sli->append(new ListItemInfo(*ili));
408   }
409 }