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 \
qcollection.h \
qconfig.h \
qcstring.h \
scstring.h \
qdatastream.h \
qdatetime.h \
qdict.h \
......@@ -54,7 +53,7 @@ HEADERS = qarray.h \
SOURCES = qbuffer.cpp \
qcollection.cpp \
scstring.cpp \
qcstring.cpp \
qdatastream.cpp \
qdatetime.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
QCString Definition::getSourceAnchor() const
{
QCString anchorStr;
const int maxAnchorStrLen = 20;
char anchorStr[maxAnchorStrLen];
if (m_impl->body && m_impl->body->startLine!=-1)
{
if (Htags::useHtags)
{
anchorStr.sprintf("L%d",m_impl->body->startLine);
snprintf(anchorStr,maxAnchorStrLen,"L%d",m_impl->body->startLine);
}
else
{
anchorStr.sprintf("l%05d",m_impl->body->startLine);
snprintf(anchorStr,maxAnchorStrLen,"l%05d",m_impl->body->startLine);
}
}
return anchorStr;
......@@ -1163,8 +1164,9 @@ void Definition::_writeSourceRefList(OutputList &ol,const char *scopeName,
{
ol.disable(OutputGenerator::Latex);
}
QCString lineStr,anchorStr;
anchorStr.sprintf("l%05d",md->getStartBodyLine());
const int maxLineNrStr = 10;
char anchorStr[maxLineNrStr];
snprintf(anchorStr,maxLineNrStr,"l%05d",md->getStartBodyLine());
//printf("Write object link to %s\n",md->getBodyDef()->getSourceFileBase().data());
ol.writeObjectLink(0,md->getBodyDef()->getSourceFileBase(),anchorStr,name);
ol.popGeneratorState();
......
......@@ -54,7 +54,7 @@ class DirDef : public Definition
bool isLinkableInProject() const;
bool isLinkable() const;
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);
FileList * getFiles() const { return m_fileList; }
void addFile(FileDef *fd);
......
......@@ -96,7 +96,7 @@ class FileDef : public Definition
QCString absFilePath() const { return m_filePath; }
/*! 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. */
bool isSource() const { return m_isSource; }
......
......@@ -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
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)
{
// TODO: this is an expensive function that is called a lot -> optimize it
const QCString begin = "<!--BEGIN " + name + "-->";
const QCString end = "<!--END " + name + "-->";
const QCString nobegin = "<!--BEGIN !" + name + "-->";
......@@ -1341,9 +1308,11 @@ void HtmlCodeGenerator::writeLineNumber(const char *ref,const char *filename,
const char *anchor,int l)
{
if (!m_streamSet) return;
QCString lineNumber,lineAnchor;
lineNumber.sprintf("%5d",l);
lineAnchor.sprintf("l%05d",l);
const int maxLineNrStr = 10;
char lineNumber[maxLineNrStr];
char lineAnchor[maxLineNrStr];
snprintf(lineNumber,maxLineNrStr,"%5d",l);
snprintf(lineAnchor,maxLineNrStr,"l%05d",l);
m_t << "<div class=\"line\">";
m_t << "<a name=\"" << lineAnchor << "\"></a><span class=\"lineno\">";
......
......@@ -63,7 +63,7 @@ class MemberGroup
MemberListType lt,
ClassDef *inheritedFrom,const QCString &inheritId);
QCString documentation() const { return doc; }
const QCString &documentation() const { return doc; }
bool allMembersInSameSection() const { return inSameSection; }
void addToDeclarationSection();
int countDecMembers(GroupDef *gd=0);
......
......@@ -264,8 +264,9 @@ void writePageRef(OutputDocInterface &od,const char *cn,const char *mn)
*/
QCString generateMarker(int id)
{
QCString result;
result.sprintf("@%d",id);
const int maxMarkerStrLen = 20;
char result[maxMarkerStrLen];
snprintf(result,maxMarkerStrLen,"@%d",id);
return result;
}
......@@ -4913,8 +4914,10 @@ FileDef *findFileDef(const FileNameDict *fnDict,const char *n,bool &ambig)
ambig=FALSE;
if (n==0) return 0;
QCString key;
key.sprintf("%p:",fnDict);
const int maxAddrSize = 20;
char addr[maxAddrSize];
snprintf(addr,maxAddrSize,"%p:",fnDict);
QCString key = addr;
key+=n;
g_findFileDefCache.setAutoDelete(TRUE);
......@@ -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,
const char *projName,const char *projNum,const char *projBrief)
{
......
......@@ -192,7 +192,7 @@ void mergeArguments(ArgumentList *,ArgumentList *,bool forceNameOverwrite=FALSE)
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);
......
......@@ -1445,7 +1445,7 @@ bool VhdlDocGen::isNumber(const QCString& s)
void VhdlDocGen::formatString(const QCString &s, OutputList& ol,const MemberDef* mdef)
{
QCString qcs = s;
QCString temp(qcs.length());
QCString temp;
qcs.stripPrefix(":");
qcs.stripPrefix("is");
qcs.stripPrefix("IS");
......@@ -1464,7 +1464,7 @@ void VhdlDocGen::formatString(const QCString &s, OutputList& ol,const MemberDef*
if (j>0) b=qcs[j-1];
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+=" ";
}
......@@ -2322,6 +2322,7 @@ void VhdlDocGen::writePlainVHDLDeclarations(
{
SDict<QCString> pack(1009);
pack.setAutoDelete(TRUE);
bool first=TRUE;
MemberDef *md;
......
......@@ -92,7 +92,7 @@ int VhdlParser::levelCounter;
static QList<VhdlConfNode> configL;
struct
static struct
{
QCString doc;
bool brief;
......@@ -217,7 +217,7 @@ void VHDLLanguageScanner::parseInput(const char *fileName,const char *fileBuf,En
VhdlParser::current=new Entry();
VhdlParser::initEntry(VhdlParser::current);
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);
delete VhdlParser::current;
......@@ -226,7 +226,7 @@ void VHDLLanguageScanner::parseInput(const char *fileName,const char *fileBuf,En
if (!inLine)
VhdlParser::mapLibPackage(root);
delete lineParse;
delete[] lineParse;
yyFileName.resize(0);
libUse.clear();
VhdlDocGen::resetCodeVhdlParserState();
......
......@@ -11,7 +11,7 @@ TMAKE_CC = gcc
TMAKE_CFLAGS = -pipe -fsigned-char
TMAKE_CFLAGS_WARN_ON = -Wall -W
TMAKE_CFLAGS_WARN_OFF =
TMAKE_CFLAGS_RELEASE = -O2
TMAKE_CFLAGS_RELEASE = -O3
TMAKE_CFLAGS_DEBUG = -g
TMAKE_CFLAGS_SHLIB = -fPIC
TMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses
......
......@@ -11,7 +11,7 @@ TMAKE_CC = cc
TMAKE_CFLAGS = -pipe
TMAKE_CFLAGS_WARN_ON = -Wall -W -Wno-deprecated-declarations
TMAKE_CFLAGS_WARN_OFF =
TMAKE_CFLAGS_RELEASE = -O2
TMAKE_CFLAGS_RELEASE = -O3
TMAKE_CFLAGS_DEBUG = -g -fstack-protector
TMAKE_CFLAGS_SHLIB = -fPIC
TMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses
......
......@@ -32,6 +32,7 @@ void VhdlParserIF::parseVhdlfile(const char* inputBuffer,bool inLine)
// fprintf(stderr,"\n\nparsed lines: %d\n",yyLineNr);
// fprintf(stderr,"\n\nerrors : %d\n\n",myErr->getErrorCount());
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