Commit 43edc14c authored by Dimitri van Heesch's avatar Dimitri van Heesch

Introduce new optimized string implementation (attempt 2)

parent 151876a8
This diff is collapsed.
This diff is collapsed.
...@@ -7,7 +7,6 @@ HEADERS = qarray.h \ ...@@ -7,7 +7,6 @@ HEADERS = qarray.h \
qcollection.h \ qcollection.h \
qconfig.h \ qconfig.h \
qcstring.h \ qcstring.h \
scstring.h \
qdatastream.h \ qdatastream.h \
qdatetime.h \ qdatetime.h \
qdict.h \ qdict.h \
...@@ -54,7 +53,7 @@ HEADERS = qarray.h \ ...@@ -54,7 +53,7 @@ HEADERS = qarray.h \
SOURCES = qbuffer.cpp \ SOURCES = qbuffer.cpp \
qcollection.cpp \ qcollection.cpp \
scstring.cpp \ qcstring.cpp \
qdatastream.cpp \ qdatastream.cpp \
qdatetime.cpp \ qdatetime.cpp \
qdir.cpp \ qdir.cpp \
......
This diff is collapsed.
/******************************************************************************
*
* Copyright (C) 1997-2004 by Dimitri van Heesch.
*
* 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.
*
* Documents produced by Doxygen are derivative works derived from the
* input used in their production; they are not affected by this license.
*
*/
#ifndef SCSTRING_H
#define SCSTRING_H
#include <stdlib.h>
class QRegExp;
/** This is an alternative implementation of QCString. It provides basically
* the same functions but uses less memory for administration. This class
* is just a wrapper around a plain C string requiring only 4 bytes "overhead".
* QCString features sharing of data and stores the string length, but
* requires 4 + 12 bytes for this (even for the empty string). As doxygen
* uses a LOT of string during a run it saves a lot of memory to use a
* more memory efficient implementation at the cost of relatively low
* runtime overhead.
*/
class SCString
{
public:
SCString() : m_data(0) {} // make null string
SCString( const SCString &s );
SCString( int size );
SCString( const char *str );
SCString( const char *str, uint maxlen );
~SCString();
SCString &operator=( const SCString &s );// deep copy
SCString &operator=( const char *str ); // deep copy
bool isNull() const;
bool isEmpty() const;
uint length() const;
uint size() const { return m_data ? length()+1 : 0; }
char * data() const { return m_data; }
bool resize( uint newlen );
bool truncate( uint pos );
bool fill( char c, int len = -1 );
SCString copy() const;
SCString &sprintf( const char *format, ... );
int find( char c, int index=0, bool cs=TRUE ) const;
int find( const char *str, int index=0, bool cs=TRUE ) const;
int find( const QRegExp &, int index=0 ) const;
int find( const QCString &str, int index, bool cs ) const;
int findRev( char c, int index=-1, bool cs=TRUE) const;
int findRev( const char *str, int index=-1, bool cs=TRUE) const;
int findRev( const QRegExp &, int index=-1 ) const;
int contains( char c, bool cs=TRUE ) const;
int contains( const char *str, bool cs=TRUE ) const;
int contains( const QRegExp & ) const;
bool stripPrefix(const char *prefix);
SCString left( uint len ) const;
SCString right( uint len ) const;
SCString mid( uint index, uint len=0xffffffff) const;
SCString lower() const;
SCString upper() const;
SCString stripWhiteSpace() const;
SCString simplifyWhiteSpace() const;
SCString &assign( const char *str );
SCString &insert( uint index, const char * );
SCString &insert( uint index, char );
SCString &append( const char *s );
SCString &prepend( const char *s );
SCString &remove( uint index, uint len );
SCString &replace( uint index, uint len, const char * );
SCString &replace( const QRegExp &, const char * );
short toShort( bool *ok=0 ) const;
ushort toUShort( bool *ok=0 ) const;
int toInt( bool *ok=0 ) const;
uint toUInt( bool *ok=0 ) const;
long toLong( bool *ok=0 ) const;
ulong toULong( bool *ok=0 ) const;
SCString &setNum( short );
SCString &setNum( ushort );
SCString &setNum( int );
SCString &setNum( uint );
SCString &setNum( long );
SCString &setNum( ulong );
QCString &setNum( float, char f='g', int prec=6 );
QCString &setNum( double, char f='g', int prec=6 );
operator const char *() const;
SCString &operator+=( const char *str );
SCString &operator+=( char c );
char &at( uint index ) const;
char &operator[]( int i ) const { return at(i); }
private:
static void msg_index( uint );
void duplicate( const SCString &s );
void duplicate( const char *str);
SCString &duplicate( const char *str, int);
char * m_data;
};
inline char &SCString::at( uint index ) const
{
return m_data[index];
}
inline void SCString::duplicate( const SCString &s )
{
if (!s.isEmpty())
{
uint l = strlen(s.data());
m_data = (char *)malloc(l+1);
if (m_data) memcpy(m_data,s.data(),l+1);
}
else
m_data=0;
}
inline void SCString::duplicate( const char *str)
{
if (str && str[0]!='\0')
{
uint l = strlen(str);
m_data = (char *)malloc(l+1);
if (m_data) memcpy(m_data,str,l+1);
}
else
m_data=0;
}
inline SCString &SCString::duplicate( const char *str, int)
{
if (m_data) free(m_data);
duplicate(str);
return *this;
}
#endif
...@@ -890,16 +890,17 @@ QCString Definition::getSourceFileBase() const ...@@ -890,16 +890,17 @@ QCString Definition::getSourceFileBase() const
QCString Definition::getSourceAnchor() const QCString Definition::getSourceAnchor() const
{ {
QCString anchorStr; const int maxAnchorStrLen = 20;
char anchorStr[maxAnchorStrLen];
if (m_impl->body && m_impl->body->startLine!=-1) if (m_impl->body && m_impl->body->startLine!=-1)
{ {
if (Htags::useHtags) if (Htags::useHtags)
{ {
anchorStr.sprintf("L%d",m_impl->body->startLine); snprintf(anchorStr,maxAnchorStrLen,"L%d",m_impl->body->startLine);
} }
else else
{ {
anchorStr.sprintf("l%05d",m_impl->body->startLine); snprintf(anchorStr,maxAnchorStrLen,"l%05d",m_impl->body->startLine);
} }
} }
return anchorStr; return anchorStr;
...@@ -1163,8 +1164,9 @@ void Definition::_writeSourceRefList(OutputList &ol,const char *scopeName, ...@@ -1163,8 +1164,9 @@ void Definition::_writeSourceRefList(OutputList &ol,const char *scopeName,
{ {
ol.disable(OutputGenerator::Latex); ol.disable(OutputGenerator::Latex);
} }
QCString lineStr,anchorStr; const int maxLineNrStr = 10;
anchorStr.sprintf("l%05d",md->getStartBodyLine()); char anchorStr[maxLineNrStr];
snprintf(anchorStr,maxLineNrStr,"l%05d",md->getStartBodyLine());
//printf("Write object link to %s\n",md->getBodyDef()->getSourceFileBase().data()); //printf("Write object link to %s\n",md->getBodyDef()->getSourceFileBase().data());
ol.writeObjectLink(0,md->getBodyDef()->getSourceFileBase(),anchorStr,name); ol.writeObjectLink(0,md->getBodyDef()->getSourceFileBase(),anchorStr,name);
ol.popGeneratorState(); ol.popGeneratorState();
......
...@@ -54,7 +54,7 @@ class DirDef : public Definition ...@@ -54,7 +54,7 @@ class DirDef : public Definition
bool isLinkableInProject() const; bool isLinkableInProject() const;
bool isLinkable() const; bool isLinkable() const;
QCString displayName(bool=TRUE) const { return m_dispName; } QCString displayName(bool=TRUE) const { return m_dispName; }
QCString shortName() const { return m_shortName; } const QCString &shortName() const { return m_shortName; }
void addSubDir(DirDef *subdir); void addSubDir(DirDef *subdir);
FileList * getFiles() const { return m_fileList; } FileList * getFiles() const { return m_fileList; }
void addFile(FileDef *fd); void addFile(FileDef *fd);
......
...@@ -96,7 +96,7 @@ class FileDef : public Definition ...@@ -96,7 +96,7 @@ class FileDef : public Definition
QCString absFilePath() const { return m_filePath; } QCString absFilePath() const { return m_filePath; }
/*! Returns the name as it is used in the documentation */ /*! Returns the name as it is used in the documentation */
QCString docName() const { return m_docname; } const QCString &docName() const { return m_docname; }
/*! Returns TRUE if this file is a source file. */ /*! Returns TRUE if this file is a source file. */
bool isSource() const { return m_isSource; } bool isSource() const { return m_isSource; }
......
...@@ -912,40 +912,6 @@ static void writeServerSearchBox(FTextStream &t,const char *relPath,bool highlig ...@@ -912,40 +912,6 @@ static void writeServerSearchBox(FTextStream &t,const char *relPath,bool highlig
//------------------------------------------------------------------------ //------------------------------------------------------------------------
/// substitute all occurrences of \a src in \a s by \a dst
QCString substitute(const char *s,const char *src,const char *dst)
{
if (s==0 || src==0) return s;
const char *p, *q;
int srcLen = qstrlen(src);
int dstLen = dst ? qstrlen(dst) : 0;
int resLen;
if (srcLen!=dstLen)
{
int count;
for (count=0, p=s; (q=strstr(p,src))!=0; p=q+srcLen) count++;
resLen = (int)(p-s)+qstrlen(p)+count*(dstLen-srcLen);
}
else // result has same size as s
{
resLen = qstrlen(s);
}
QCString result(resLen+1);
char *r;
for (r=result.data(), p=s; (q=strstr(p,src))!=0; p=q+srcLen)
{
int l = (int)(q-p);
memcpy(r,p,l);
r+=l;
if (dst) memcpy(r,dst,dstLen);
r+=dstLen;
}
qstrcpy(r,p);
//printf("substitute(%s,%s,%s)->%s\n",s,src,dst,result.data());
return result;
}
//----------------------------------------------------------------------
/// Clear a text block \a s from \a begin to \a end markers /// Clear a text block \a s from \a begin to \a end markers
QCString clearBlock(const char *s,const char *begin,const char *end) QCString clearBlock(const char *s,const char *begin,const char *end)
{ {
...@@ -989,6 +955,7 @@ QCString clearBlock(const char *s,const char *begin,const char *end) ...@@ -989,6 +955,7 @@ QCString clearBlock(const char *s,const char *begin,const char *end)
QCString selectBlock(const QCString& s,const QCString &name,bool enable) QCString selectBlock(const QCString& s,const QCString &name,bool enable)
{ {
// TODO: this is an expensive function that is called a lot -> optimize it
const QCString begin = "<!--BEGIN " + name + "-->"; const QCString begin = "<!--BEGIN " + name + "-->";
const QCString end = "<!--END " + name + "-->"; const QCString end = "<!--END " + name + "-->";
const QCString nobegin = "<!--BEGIN !" + name + "-->"; const QCString nobegin = "<!--BEGIN !" + name + "-->";
...@@ -1341,9 +1308,11 @@ void HtmlCodeGenerator::writeLineNumber(const char *ref,const char *filename, ...@@ -1341,9 +1308,11 @@ void HtmlCodeGenerator::writeLineNumber(const char *ref,const char *filename,
const char *anchor,int l) const char *anchor,int l)
{ {
if (!m_streamSet) return; if (!m_streamSet) return;
QCString lineNumber,lineAnchor; const int maxLineNrStr = 10;
lineNumber.sprintf("%5d",l); char lineNumber[maxLineNrStr];
lineAnchor.sprintf("l%05d",l); char lineAnchor[maxLineNrStr];
snprintf(lineNumber,maxLineNrStr,"%5d",l);
snprintf(lineAnchor,maxLineNrStr,"l%05d",l);
m_t << "<div class=\"line\">"; m_t << "<div class=\"line\">";
m_t << "<a name=\"" << lineAnchor << "\"></a><span class=\"lineno\">"; m_t << "<a name=\"" << lineAnchor << "\"></a><span class=\"lineno\">";
......
...@@ -63,7 +63,7 @@ class MemberGroup ...@@ -63,7 +63,7 @@ class MemberGroup
MemberListType lt, MemberListType lt,
ClassDef *inheritedFrom,const QCString &inheritId); ClassDef *inheritedFrom,const QCString &inheritId);
QCString documentation() const { return doc; } const QCString &documentation() const { return doc; }
bool allMembersInSameSection() const { return inSameSection; } bool allMembersInSameSection() const { return inSameSection; }
void addToDeclarationSection(); void addToDeclarationSection();
int countDecMembers(GroupDef *gd=0); int countDecMembers(GroupDef *gd=0);
......
...@@ -264,8 +264,9 @@ void writePageRef(OutputDocInterface &od,const char *cn,const char *mn) ...@@ -264,8 +264,9 @@ void writePageRef(OutputDocInterface &od,const char *cn,const char *mn)
*/ */
QCString generateMarker(int id) QCString generateMarker(int id)
{ {
QCString result; const int maxMarkerStrLen = 20;
result.sprintf("@%d",id); char result[maxMarkerStrLen];
snprintf(result,maxMarkerStrLen,"@%d",id);
return result; return result;
} }
...@@ -4913,8 +4914,10 @@ FileDef *findFileDef(const FileNameDict *fnDict,const char *n,bool &ambig) ...@@ -4913,8 +4914,10 @@ FileDef *findFileDef(const FileNameDict *fnDict,const char *n,bool &ambig)
ambig=FALSE; ambig=FALSE;
if (n==0) return 0; if (n==0) return 0;
QCString key; const int maxAddrSize = 20;
key.sprintf("%p:",fnDict); char addr[maxAddrSize];
snprintf(addr,maxAddrSize,"%p:",fnDict);
QCString key = addr;
key+=n; key+=n;
g_findFileDefCache.setAutoDelete(TRUE); g_findFileDefCache.setAutoDelete(TRUE);
...@@ -5030,6 +5033,41 @@ QCString showFileDefMatches(const FileNameDict *fnDict,const char *n) ...@@ -5030,6 +5033,41 @@ QCString showFileDefMatches(const FileNameDict *fnDict,const char *n)
//---------------------------------------------------------------------- //----------------------------------------------------------------------
/// substitute all occurrences of \a src in \a s by \a dst
QCString substitute(const QCString &s,const QCString &src,const QCString &dst)
{
if (s.isEmpty() || src.isEmpty()) return s;
const char *p, *q;
int srcLen = src.length();
int dstLen = dst.length();
int resLen;
if (srcLen!=dstLen)
{
int count;
for (count=0, p=s.data(); (q=strstr(p,src))!=0; p=q+srcLen) count++;
resLen = s.length()+count*(dstLen-srcLen);
}
else // result has same size as s
{
resLen = s.length();
}
QCString result(resLen+1);
char *r;
for (r=result.data(), p=s; (q=strstr(p,src))!=0; p=q+srcLen)
{
int l = (int)(q-p);
memcpy(r,p,l);
r+=l;
if (dst) memcpy(r,dst,dstLen);
r+=dstLen;
}
qstrcpy(r,p);
//printf("substitute(%s,%s,%s)->%s\n",s,src,dst,result.data());
return result;
}
//----------------------------------------------------------------------
QCString substituteKeywords(const QCString &s,const char *title, QCString substituteKeywords(const QCString &s,const char *title,
const char *projName,const char *projNum,const char *projBrief) const char *projName,const char *projNum,const char *projBrief)
{ {
......
...@@ -192,7 +192,7 @@ void mergeArguments(ArgumentList *,ArgumentList *,bool forceNameOverwrite=FALSE) ...@@ -192,7 +192,7 @@ void mergeArguments(ArgumentList *,ArgumentList *,bool forceNameOverwrite=FALSE)
QCString substituteClassNames(const QCString &s); QCString substituteClassNames(const QCString &s);
QCString substitute(const char *s,const char *src,const char *dst); QCString substitute(const QCString &s,const QCString &src,const QCString &dst);
QCString clearBlock(const char *s,const char *begin,const char *end); QCString clearBlock(const char *s,const char *begin,const char *end);
......
...@@ -1445,7 +1445,7 @@ bool VhdlDocGen::isNumber(const QCString& s) ...@@ -1445,7 +1445,7 @@ bool VhdlDocGen::isNumber(const QCString& s)
void VhdlDocGen::formatString(const QCString &s, OutputList& ol,const MemberDef* mdef) void VhdlDocGen::formatString(const QCString &s, OutputList& ol,const MemberDef* mdef)
{ {
QCString qcs = s; QCString qcs = s;
QCString temp(qcs.length()); QCString temp;
qcs.stripPrefix(":"); qcs.stripPrefix(":");
qcs.stripPrefix("is"); qcs.stripPrefix("is");
qcs.stripPrefix("IS"); qcs.stripPrefix("IS");
...@@ -1464,7 +1464,7 @@ void VhdlDocGen::formatString(const QCString &s, OutputList& ol,const MemberDef* ...@@ -1464,7 +1464,7 @@ void VhdlDocGen::formatString(const QCString &s, OutputList& ol,const MemberDef*
if (j>0) b=qcs[j-1]; if (j>0) b=qcs[j-1];
if (c=='"' || c==',' || c=='\''|| c=='(' || c==')' || c==':' || c=='[' || c==']' ) // || (c==':' && b!='=')) // || (c=='=' && b!='>')) if (c=='"' || c==',' || c=='\''|| c=='(' || c==')' || c==':' || c=='[' || c==']' ) // || (c==':' && b!='=')) // || (c=='=' && b!='>'))
{ {
if (temp.at(index-1) != ' ') if (temp.length()>=index && temp.at(index-1) != ' ')
{ {
temp+=" "; temp+=" ";
} }
...@@ -2322,6 +2322,7 @@ void VhdlDocGen::writePlainVHDLDeclarations( ...@@ -2322,6 +2322,7 @@ void VhdlDocGen::writePlainVHDLDeclarations(
{ {
SDict<QCString> pack(1009); SDict<QCString> pack(1009);
pack.setAutoDelete(TRUE);
bool first=TRUE; bool first=TRUE;
MemberDef *md; MemberDef *md;
......
...@@ -92,7 +92,7 @@ int VhdlParser::levelCounter; ...@@ -92,7 +92,7 @@ int VhdlParser::levelCounter;
static QList<VhdlConfNode> configL; static QList<VhdlConfNode> configL;
struct static struct
{ {
QCString doc; QCString doc;
bool brief; bool brief;
...@@ -217,7 +217,7 @@ void VHDLLanguageScanner::parseInput(const char *fileName,const char *fileBuf,En ...@@ -217,7 +217,7 @@ void VHDLLanguageScanner::parseInput(const char *fileName,const char *fileBuf,En
VhdlParser::current=new Entry(); VhdlParser::current=new Entry();
VhdlParser::initEntry(VhdlParser::current); VhdlParser::initEntry(VhdlParser::current);
groupEnterFile(fileName,yyLineNr); groupEnterFile(fileName,yyLineNr);
lineParse=new int[200]; lineParse=new int[200]; // Dimitri: dangerous constant: should be bigger than largest token id in VhdlParserConstants.h
VhdlParserIF::parseVhdlfile(fileBuf,inLine); VhdlParserIF::parseVhdlfile(fileBuf,inLine);
delete VhdlParser::current; delete VhdlParser::current;
...@@ -226,7 +226,7 @@ void VHDLLanguageScanner::parseInput(const char *fileName,const char *fileBuf,En ...@@ -226,7 +226,7 @@ void VHDLLanguageScanner::parseInput(const char *fileName,const char *fileBuf,En
if (!inLine) if (!inLine)
VhdlParser::mapLibPackage(root); VhdlParser::mapLibPackage(root);
delete lineParse; delete[] lineParse;
yyFileName.resize(0); yyFileName.resize(0);
libUse.clear(); libUse.clear();
VhdlDocGen::resetCodeVhdlParserState(); VhdlDocGen::resetCodeVhdlParserState();
......
...@@ -11,7 +11,7 @@ TMAKE_CC = gcc ...@@ -11,7 +11,7 @@ TMAKE_CC = gcc
TMAKE_CFLAGS = -pipe -fsigned-char TMAKE_CFLAGS = -pipe -fsigned-char
TMAKE_CFLAGS_WARN_ON = -Wall -W TMAKE_CFLAGS_WARN_ON = -Wall -W
TMAKE_CFLAGS_WARN_OFF = TMAKE_CFLAGS_WARN_OFF =
TMAKE_CFLAGS_RELEASE = -O2 TMAKE_CFLAGS_RELEASE = -O3
TMAKE_CFLAGS_DEBUG = -g TMAKE_CFLAGS_DEBUG = -g
TMAKE_CFLAGS_SHLIB = -fPIC TMAKE_CFLAGS_SHLIB = -fPIC
TMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses TMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses
......
...@@ -11,7 +11,7 @@ TMAKE_CC = cc ...@@ -11,7 +11,7 @@ TMAKE_CC = cc
TMAKE_CFLAGS = -pipe TMAKE_CFLAGS = -pipe
TMAKE_CFLAGS_WARN_ON = -Wall -W -Wno-deprecated-declarations TMAKE_CFLAGS_WARN_ON = -Wall -W -Wno-deprecated-declarations
TMAKE_CFLAGS_WARN_OFF = TMAKE_CFLAGS_WARN_OFF =
TMAKE_CFLAGS_RELEASE = -O2 TMAKE_CFLAGS_RELEASE = -O3
TMAKE_CFLAGS_DEBUG = -g -fstack-protector TMAKE_CFLAGS_DEBUG = -g -fstack-protector
TMAKE_CFLAGS_SHLIB = -fPIC TMAKE_CFLAGS_SHLIB = -fPIC
TMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses TMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses
......
...@@ -32,6 +32,7 @@ void VhdlParserIF::parseVhdlfile(const char* inputBuffer,bool inLine) ...@@ -32,6 +32,7 @@ void VhdlParserIF::parseVhdlfile(const char* inputBuffer,bool inLine)
// fprintf(stderr,"\n\nparsed lines: %d\n",yyLineNr); // fprintf(stderr,"\n\nparsed lines: %d\n",yyLineNr);
// fprintf(stderr,"\n\nerrors : %d\n\n",myErr->getErrorCount()); // fprintf(stderr,"\n\nerrors : %d\n\n",myErr->getErrorCount());
delete myParser; delete myParser;
delete myErr;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment