mainhandler.cpp 7.93 KB
Newer Older
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1 2 3 4 5
/******************************************************************************
 *
 * $Id$
 *
 *
6
 * Copyright (C) 1997-2013 by Dimitri van Heesch.
Dimitri van Heesch's avatar
Dimitri van Heesch committed
7 8 9 10 11 12 13 14 15
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation under the terms of the GNU General Public License is hereby 
 * granted. No representations are made about the suitability of this software 
 * for any purpose. It is provided "as is" without express or implied warranty.
 * See the GNU General Public License for more details.
 *
 */

16
#include <qxml.h>
Dimitri van Heesch's avatar
Dimitri van Heesch committed
17
#include "mainhandler.h"
18
#include "compoundhandler.h"
19
#include "sectionhandler.h"
20
#include "graphhandler.h"
21 22
#include "dochandler.h"
#include "memberhandler.h"
23
#include "debug.h"
Dimitri van Heesch's avatar
Dimitri van Heesch committed
24

25

26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
class ErrorHandler : public QXmlErrorHandler
{
    public:
      virtual ~ErrorHandler() {}
      bool warning( const QXmlParseException & )
      {
        return FALSE;
      }
      bool error( const QXmlParseException & )
      {
        return FALSE;
      }
      bool fatalError( const QXmlParseException &exception )
      {
        debug(1,"Fatal error at line %d column %d: %s\n",
            exception.lineNumber(),exception.columnNumber(),
            exception.message().data());
        return FALSE;
      }
      QString errorString() { return ""; }

    private:
      QString errorMsg;
};

//--------------------------------------------------------------------------

class CompoundEntryIterator : public ICompoundIterator, 
                              public QListIterator<CompoundEntry>
{
  public:
    CompoundEntryIterator(const MainHandler *m,const QList<CompoundEntry> &list) :
      QListIterator<CompoundEntry>(list), m_mainHandler(m) {}
    virtual ~CompoundEntryIterator() {}

    virtual void toFirst()
    { 
      QListIterator<CompoundEntry>::toFirst(); 
    }
    virtual void toLast()
    { 
      QListIterator<CompoundEntry>::toLast(); 
    }
    virtual void toNext()
    { 
      QListIterator<CompoundEntry>::operator++(); 
    }
    virtual void toPrev()
    { 
      QListIterator<CompoundEntry>::operator--(); 
    }
    virtual ICompound *current() const
    { 
      CompoundEntry *ch = QListIterator<CompoundEntry>::current(); 
Dimitri van Heesch's avatar
Dimitri van Heesch committed
80
      return ch ? m_mainHandler->compoundById(ch->id.utf8()) : 0;
81 82 83 84 85 86 87 88 89 90 91 92 93
    }
    virtual void release()
    { delete this; }

  private:
    const MainHandler *m_mainHandler;
};

//--------------------------------------------------------------------------

MainHandler::MainHandler() : m_compoundDict(2999), m_compoundNameDict(2999),
                             m_memberDict(12251), m_memberNameDict(12251),
                             m_compoundsLoaded(1009)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
94 95
{
  m_compounds.setAutoDelete(TRUE);
96
  m_memberNameDict.setAutoDelete(TRUE);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
97 98
  addStartHandler("doxygenindex"); 
  addEndHandler("doxygenindex");
99 100 101 102 103 104 105
  addStartHandler("compound",this,&MainHandler::startCompound);
  addEndHandler("compound");
  addStartHandler("member",this,&MainHandler::startMember);
  addEndHandler("member",this,&MainHandler::endMember);
  addStartHandler("name",this,&MainHandler::startName);
  addEndHandler("name",this,&MainHandler::endName);
  m_curCompound = 0;
106
  m_insideMember = FALSE;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
107 108 109 110
}

MainHandler::~MainHandler()
{
111
  debug(2,"MainHandler::~MainHandler()\n");
Dimitri van Heesch's avatar
Dimitri van Heesch committed
112 113
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
114 115
void MainHandler::startCompound(const QXmlAttributes& attrib)
{
116
  m_curCompound = new CompoundEntry(257);
117
  m_curCompound->id = attrib.value("refid");
118
  m_compounds.append(m_curCompound);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
119
  m_compoundDict.insert(m_curCompound->id.utf8(),m_curCompound);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
120 121
}

122
void MainHandler::startName(const QXmlAttributes& /*attrib*/)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
123
{
124
  m_curString = "";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
125 126
}

127
void MainHandler::endName()
Dimitri van Heesch's avatar
Dimitri van Heesch committed
128
{
129 130 131 132 133 134 135
  if (m_insideMember)
  {
    m_curMember->name = m_curString;
  }
  else
  {
    m_curCompound->name = m_curString;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
136
    m_compoundNameDict.insert(m_curString.utf8(),m_curCompound);
137
  }
138 139 140 141
}

void MainHandler::startMember(const QXmlAttributes& attrib)
{
142
  m_insideMember = TRUE;
143
  m_curMember = new MemberEntry;
144
  m_curMember->id = attrib.value("refid");
145
  m_curMember->compound = m_curCompound;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
146
  m_memberDict.insert(m_curMember->id.utf8(),m_curMember);
147 148 149 150
}

void MainHandler::endMember()
{
Dimitri van Heesch's avatar
Dimitri van Heesch committed
151
  m_curCompound->memberDict.insert(m_curMember->name.utf8(),m_curMember);
152
  QList<CompoundEntry> *cel=0;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
153
  if ((cel=m_memberNameDict.find(m_curMember->name.utf8()))==0)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
154
  {
155
    cel = new QList<CompoundEntry>;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
156
    m_memberNameDict.insert(m_curMember->name.utf8(),cel);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
157
  }
158
  cel->append(m_curCompound);
159
  m_insideMember = FALSE;
160 161 162 163 164 165 166 167 168 169 170 171
}

void MainHandler::setDebugLevel(int level)
{
  ::setDebugLevel(level);
}

void MainHandler::dump()
{
  QListIterator<CompoundEntry> cli(m_compounds);
  CompoundEntry *ce;
  for (cli.toFirst();(ce=cli.current());++cli)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
172
  {
173 174 175 176 177 178 179
    debug(2,"compound id=`%s' name=`%s'\n",ce->id.data(),ce->name.data());
    QDictIterator<MemberEntry> mdi(ce->memberDict);
    MemberEntry *me;
    for (mdi.toFirst();(me=mdi.current());++mdi)
    {
      debug(2,"  member id=`%s' name=`%s'\n",me->id.data(),me->name.data());
    }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
180 181 182
  }
}

183
bool MainHandler::readXMLDir(const char * xmlDirName)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
184
{
185 186 187 188 189 190
  m_xmlDirName = xmlDirName;
  QString xmlFileName=m_xmlDirName+"/index.xml";
  QFile xmlFile(xmlFileName);
  //printf("Trying %s xmlFile.exists()=%d isReadable()=%d\n",
  //    xmlFileName.data(),xmlFile.exists(),xmlFile.isReadable());
  if (xmlFile.exists())
Dimitri van Heesch's avatar
Dimitri van Heesch committed
191
  {
192 193 194 195 196 197 198 199
    ErrorHandler errorHandler;
    QXmlInputSource source( xmlFile );
    QXmlSimpleReader reader;
    reader.setContentHandler( this );
    reader.setErrorHandler( &errorHandler );
    reader.parse( source );
    dump();
    return TRUE;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
200
  }
201 202 203 204 205 206 207
  return FALSE;
}

ICompoundIterator *MainHandler::compounds() const
{
  return new CompoundEntryIterator(this,m_compounds);
}
208

209
ICompound *MainHandler::compoundById(const char *id) const
210
{
211 212
  QString ids = id;
  if (ids.isEmpty()) return 0;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
213
  CompoundHandler *ch = m_compoundsLoaded[ids.utf8()];
214
  if (ch) // compound already in memory
215
  {
216
    ch->addref(); // returning alias -> increase reference counter
Dimitri van Heesch's avatar
Dimitri van Heesch committed
217
    return ch->toICompound(); 
218
  }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
219
  CompoundEntry *ce = m_compoundDict.find(ids.utf8());
220 221 222 223 224 225 226 227
  if (ce==0) return 0; // id not found
  // create and load a new compound
  ch = new CompoundHandler(m_xmlDirName);
  if (!ch->parseXML(id))
  {
    // compound could not be initialized.
    delete ch;
    return 0;
228 229
  }

230 231 232 233
  // we disregard the constness here, because the object stays conceptually
  // unchanged.
  MainHandler *that = (MainHandler *)this;
  ch->initialize(that);
234
  //printf("loading compound %s in memory\n",id);
235
  that->m_compoundsLoaded.insert(id,ch);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
236
  return ch->toICompound();
Dimitri van Heesch's avatar
Dimitri van Heesch committed
237
}
Dimitri van Heesch's avatar
Dimitri van Heesch committed
238

239
void MainHandler::unloadCompound(CompoundHandler *ch)
240
{
241
  //printf("unloading compound %s from memory\n",ch->id()->latin1());
242
  bool result = m_compoundsLoaded.remove(ch->id()->latin1()); 
243
  if (!result) debug(1,"Failed to unload component!\n");
244
}
245

246
ICompound *MainHandler::compoundByName(const char *name) const
247
{
248 249
  QString nameStr = name;
  if (nameStr.isEmpty()) return 0;
250 251
  CompoundEntry *ce = m_compoundNameDict[name];
  if (ce==0) return 0; // name not found
Dimitri van Heesch's avatar
Dimitri van Heesch committed
252
  return compoundById(ce->id.utf8());
253
}
254

255
ICompound *MainHandler::memberById(const char *id) const
256
{
257 258
  QString ids = id;
  if (ids.isEmpty()) return 0;
259 260
  MemberEntry *me = m_memberDict[id];
  if (me==0) return 0; // id not found
Dimitri van Heesch's avatar
Dimitri van Heesch committed
261
  return compoundById(me->compound->id.utf8());
262 263
}

264
ICompoundIterator *MainHandler::memberByName(const char *name) const
265
{
266 267
  QString nameStr = name;
  if (nameStr.isEmpty()) return 0;
268 269 270 271 272 273 274 275 276 277 278
  QList<CompoundEntry> *cel = m_memberNameDict[name];
  if (cel==0) return 0; // name not found
  return new CompoundEntryIterator(this,*cel);
}

IDoxygen *createObjectModel()
{
  compoundhandler_init();
  sectionhandler_init();
  memberhandler_init();
  dochandler_init();
279
  graphhandler_init();
280 281 282 283 284
  return new MainHandler;
}

void MainHandler::release()
{
285
  //printf("MainHandler::release()\n");
286 287 288 289
  QDictIterator<CompoundHandler> chi(m_compoundsLoaded);
  CompoundHandler *ch;
  for (chi.toFirst();(ch=chi.current());++chi)
  {
290
    debug(1,"Compound %s not released\n",ch->name()->latin1());
291
  }
292
  graphhandler_exit();
293 294 295 296 297
  dochandler_exit();
  memberhandler_exit();
  sectionhandler_exit();
  compoundhandler_exit();
  delete this;
298 299
}