mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-22 01:59:02 +00:00
Do not compile our strings if we do not need them.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@211 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
c35b288b74
commit
8abfae28a6
591
src/LString.C
591
src/LString.C
@ -1,591 +0,0 @@
|
||||
/* This file is part of
|
||||
* ======================================================
|
||||
*
|
||||
* LyX, The Document Processor
|
||||
*
|
||||
* Copyright (C) 1995 Matthias Ettrich
|
||||
* Copyright (C) 1995-1998 The LyX Team.
|
||||
*
|
||||
*======================================================*/
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "LString.h"
|
||||
#endif
|
||||
|
||||
// #include <assert.h> // Hmm, make depend crashes with this one in. (Asger)
|
||||
#include "LString.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
// $Id: LString.C,v 1.1 1999/09/27 18:44:36 larsbj Exp $
|
||||
|
||||
#if !defined(lint) && !defined(WITH_WARNINGS)
|
||||
static char vcid[] = "$Id: LString.C,v 1.1 1999/09/27 18:44:36 larsbj Exp $";
|
||||
#endif /* lint */
|
||||
|
||||
static const unsigned short xtra = 4;
|
||||
// The extra space is used to reduce the number of allocations
|
||||
// and copies required if a string is unshared. The performance
|
||||
// boost can be considerable -- in some tests using LyX I found
|
||||
// a 97% reduction in the runtime of operator+=(char) in some
|
||||
// code for writing LaTeX files using LStrings.
|
||||
// This was originally implemented using:
|
||||
// xtra = 4 - (sizeof(srep) + len) % 4;
|
||||
// where len is the length of the new string.
|
||||
// This was intended to ensure the string was always aligned
|
||||
// within 4-byte boundaries but after testing with xtra = 4,
|
||||
// and finding a significant improvement I decided to just
|
||||
// leave it at 4. ARRae.
|
||||
|
||||
LString::LString()
|
||||
{
|
||||
static srep empty_rep;
|
||||
|
||||
p = &empty_rep;
|
||||
empty_rep.n++;
|
||||
}
|
||||
|
||||
|
||||
LString::LString(char const *s)
|
||||
{
|
||||
static srep empty_rep;
|
||||
|
||||
if (s && *s) {
|
||||
// > 99 %
|
||||
register unsigned int const len = strlen(s);
|
||||
p = (srep *) new char[sizeof(srep) + len + xtra];
|
||||
p->l = len;
|
||||
p->n = 0;
|
||||
p->e = xtra;
|
||||
memcpy(p->s, s, len + 1);
|
||||
} else {
|
||||
// < 1 %
|
||||
p = &empty_rep;
|
||||
empty_rep.n++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LString::LString(char const c)
|
||||
{
|
||||
static srep empty_rep;
|
||||
|
||||
if (c) {
|
||||
p = (srep *) new char[sizeof(srep) + 1 + xtra];
|
||||
p->l = 1;
|
||||
p->n = 0;
|
||||
p->e = xtra;
|
||||
p->s[0] = c;
|
||||
p->s[1] = '\0';
|
||||
} else {
|
||||
p = &empty_rep;
|
||||
empty_rep.n++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LString& LString::operator=(char const *s)
|
||||
{
|
||||
static srep empty_rep;
|
||||
// assert(p);
|
||||
|
||||
lose(); // disconnect self
|
||||
|
||||
if (s && *s) {
|
||||
register unsigned int const len = strlen(s);
|
||||
p = (srep *) new char[sizeof(srep) + len + xtra];
|
||||
p->l = len;
|
||||
p->n = 0;
|
||||
p->e = xtra;
|
||||
memcpy(p->s, s, len + 1);
|
||||
} else {
|
||||
p = &empty_rep;
|
||||
empty_rep.n++;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
LString& LString::operator=(LString const &x)
|
||||
{
|
||||
// assert(p);
|
||||
x.p->n++; // protect against ``st = st''
|
||||
|
||||
lose(); // disconnect self
|
||||
|
||||
p = x.p;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
LString& LString::operator=(char c)
|
||||
{
|
||||
static srep empty_rep;
|
||||
|
||||
// assert(p);
|
||||
|
||||
lose(); // disconnect self
|
||||
|
||||
if (c) {
|
||||
p = (srep *) new char[sizeof(srep) + 1 + xtra];
|
||||
p->l = 1;
|
||||
p->n = 0;
|
||||
p->e = xtra;
|
||||
p->s[0] = c;
|
||||
p->s[1] = '\0';
|
||||
} else {
|
||||
p = &empty_rep;
|
||||
empty_rep.n++;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
LString &LString::clean()
|
||||
{
|
||||
static srep empty_rep;
|
||||
|
||||
lose();
|
||||
p = &empty_rep;
|
||||
empty_rep.n++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char& LString::operator[](int i)
|
||||
{
|
||||
#ifdef DEVEL_VERSION
|
||||
if (i < 0 || i >= length()) {
|
||||
fprintf(stderr,"LString::operator[]: Index out of range: '%s' %d\n", p->s, i);
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (p->n > 0) { // clone to maintain value semantics
|
||||
srep * np = (srep *) new char[sizeof(srep) + p->l];
|
||||
np->l = p->l;
|
||||
np->n = 0;
|
||||
np->e = 0;
|
||||
memcpy(np->s, p->s, length() + 1);
|
||||
p->n--;
|
||||
p = np;
|
||||
}
|
||||
return p->s[i];
|
||||
}
|
||||
|
||||
#ifndef const
|
||||
char const& LString::operator[](int i) const
|
||||
{
|
||||
#ifdef DEVEL_VERSION
|
||||
if (i < 0 || i >= length()) {
|
||||
fprintf(stderr,"LString::operator[] const: Index out of range: '%s' i:%d.\n",p->s,i);
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
return p->s[i];
|
||||
}
|
||||
#endif /* ndef const */
|
||||
|
||||
LString &LString::operator+=(LString const & x)
|
||||
{
|
||||
if (x.empty()) return *this;
|
||||
|
||||
register unsigned int const len = length() + x.length();
|
||||
if (p->n || p->e < x.length()) {
|
||||
srep *np = (srep *) new char[sizeof(srep) + len + xtra];
|
||||
np->l = len;
|
||||
np->n = 0;
|
||||
np->e = xtra;
|
||||
memcpy(np->s, p->s, length());
|
||||
memcpy(np->s + length(), x.p->s, x.length() + 1);
|
||||
lose(); // disconnect self
|
||||
p = np;
|
||||
} else {
|
||||
// in cases where x += x and x is short the
|
||||
// explicit setting of the '\0' stops any problems
|
||||
memcpy(p->s + length(), x.p->s, x.length());
|
||||
p->s[len] = '\0';
|
||||
p->l += x.length();
|
||||
p->e -= x.length();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
LString &LString::operator+=(char const *x)
|
||||
{
|
||||
if (!x || *x==0) return *this;
|
||||
|
||||
register unsigned int const xlen = strlen(x);
|
||||
register unsigned int const len = length() + xlen;
|
||||
if (p->n || p->e < xlen) {
|
||||
srep *np = (srep *) new char[sizeof(srep) + len + xtra];
|
||||
np->l = len;
|
||||
np->n = 0;
|
||||
np->e = xtra;
|
||||
memcpy(np->s, p->s, length());
|
||||
memcpy(np->s + length(), x, xlen + 1);
|
||||
lose(); // disconnect self
|
||||
p = np;
|
||||
} else {
|
||||
// Explicitly setting the '\0' stops any
|
||||
// problems caused by x += x.c_str()
|
||||
memcpy(p->s + length(), x, xlen);
|
||||
p->s[len] = '\0';
|
||||
p->l += xlen;
|
||||
p->e -= xlen;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
LString &LString::operator+=(char c)
|
||||
{
|
||||
register unsigned int const len = length() + 1;
|
||||
if (!p->n && p->e) {
|
||||
// 80% (from profiling)
|
||||
// This is where all the speed gains are made.
|
||||
p->s[length()] = c;
|
||||
p->s[len] = '\0';
|
||||
p->l = len;
|
||||
p->e -= 1;
|
||||
} else {
|
||||
// 20%
|
||||
srep *np = (srep *) new char[sizeof(srep) + len + xtra];
|
||||
np->l = len;
|
||||
np->n = 0;
|
||||
np->e = xtra;
|
||||
memcpy(np->s, p->s, length());
|
||||
np->s[length()] = c;
|
||||
np->s[len] = '\0';
|
||||
lose(); // disconnect self
|
||||
p = np;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
LString &LString::operator+=(int i)
|
||||
{
|
||||
return this->operator+=((long)i);
|
||||
}
|
||||
|
||||
|
||||
LString &LString::operator+=(long i)
|
||||
{
|
||||
unsigned int tmplen = 0;
|
||||
long a = i;
|
||||
// calculate the length of i
|
||||
if (!i) {
|
||||
tmplen = 1;
|
||||
} else {
|
||||
if (a < 0) {
|
||||
tmplen++; // minus sign
|
||||
a = -a; // switch sign
|
||||
}
|
||||
while(a >= 1) { a = a/10; tmplen++;}
|
||||
}
|
||||
char *str = new char[tmplen + 1];
|
||||
sprintf(str, "%ld", i);
|
||||
this->operator+=(str);
|
||||
delete[] str;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
char * LString::copy() const
|
||||
{
|
||||
char * new_string = new char[length()+1];
|
||||
memcpy(new_string, p->s, length() + 1);
|
||||
return new_string;
|
||||
}
|
||||
|
||||
|
||||
bool LString::contains(char const *a) const
|
||||
{
|
||||
return strstr(p->s, a) != NULL;
|
||||
}
|
||||
|
||||
|
||||
LString& LString::substring(int i1, int i2)
|
||||
{
|
||||
#ifdef DEVEL_VERSION
|
||||
if (i1 > i2 || i1 >= length() || i2 >= length()) {
|
||||
fprintf(stderr,
|
||||
"LString::substring: Wrong indexing in substring:"
|
||||
" '%s' i1=%d i2=%d\n", p->s, i1, i2);
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (i1==i2)
|
||||
this->operator=(p->s[i1]);
|
||||
else {
|
||||
char *str = new char[i2 - i1 +2];
|
||||
int i;
|
||||
for (i=0; i1<=i2; str[i++] = p->s[i1++]);
|
||||
str[i] = 0;
|
||||
this->operator=(str);
|
||||
delete[] (char*)str;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
// ale970405+lasgoutt-970425
|
||||
LString LString::token(char delim, int n) const
|
||||
{
|
||||
int k=0, i;
|
||||
LString tokbuf;
|
||||
|
||||
tokbuf = *this;
|
||||
// Find delimiter or end of string
|
||||
for (i = 0; i < tokbuf.length(); i++) {
|
||||
if (tokbuf[i] == delim) {
|
||||
if (n > 0) {
|
||||
k = i+1;
|
||||
n--;
|
||||
} else break;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the token if not empty
|
||||
if (n == 0 && k<i){
|
||||
return tokbuf.substring(k, i-1);
|
||||
} else {
|
||||
return LString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// this could probably be faster and/or cleaner, but it seems to work (JMarc)
|
||||
int LString::tokenPos(char delim, LString const &tok)
|
||||
{
|
||||
int i=0;
|
||||
LString str = *this;
|
||||
LString tmptok;
|
||||
|
||||
while (!str.empty()) {
|
||||
str.split(tmptok, delim);
|
||||
if (tok==tmptok)
|
||||
return i;
|
||||
i++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
LString& LString::split(LString & piece, char delim)
|
||||
{
|
||||
int i=0;
|
||||
// Find delimiter or end of string
|
||||
while (i<length() && p->s[i] != delim)
|
||||
i++;
|
||||
// If not the first, we go for a substring
|
||||
if (i>0) {
|
||||
piece = *this;
|
||||
piece.substring(0, i-1);
|
||||
} else
|
||||
piece.clean();
|
||||
|
||||
if (i < length()-1)
|
||||
this->substring(i+1, length()-1);
|
||||
else
|
||||
clean();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
LString& LString::split(char delim)
|
||||
{
|
||||
int i=0;
|
||||
// Find delimiter or end of string
|
||||
while (i<length() && p->s[i] != delim)
|
||||
i++;
|
||||
|
||||
if (i < length()-1)
|
||||
this->substring(i+1, length()-1);
|
||||
else
|
||||
clean();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
// ale970521
|
||||
LString& LString::rsplit(LString & piece, char delim)
|
||||
{
|
||||
int i=length()-1;
|
||||
// Find delimiter or begin of string
|
||||
while (i>=0 && p->s[i] != delim)
|
||||
i--;
|
||||
// If not the last, we go for a substring
|
||||
if (i < length()-1) {
|
||||
piece = *this;
|
||||
piece.substring(0, i-1);
|
||||
this->substring(i+1, length()-1);
|
||||
} else {
|
||||
piece.clean();
|
||||
clean();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
LString& LString::strip(char const c)
|
||||
{
|
||||
int i=length()-1;
|
||||
for (; i>=0 && p->s[i] == c; i--);
|
||||
if (i<0)
|
||||
clean();
|
||||
else
|
||||
this->substring(0, i);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
LString& LString::frontStrip(char const c)
|
||||
{
|
||||
int i=0;
|
||||
while (i < length() && p->s[i] == c) i++;
|
||||
if (i > 0)
|
||||
if (i == length())
|
||||
clean();
|
||||
else
|
||||
this->substring (i, length()-1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
bool LString::prefixIs(char const * pre) const
|
||||
{
|
||||
if ((int) strlen(pre) > length())
|
||||
return false;
|
||||
else
|
||||
return strncmp(p->s, pre, strlen(pre))==0;
|
||||
}
|
||||
|
||||
|
||||
bool LString::suffixIs(char c) const
|
||||
{
|
||||
if (empty()) return false;
|
||||
return p->s[length()-1] == c;
|
||||
}
|
||||
|
||||
|
||||
bool LString::suffixIs(char const * suf) const
|
||||
{
|
||||
int suflen = (int) strlen(suf);
|
||||
if (suflen > length())
|
||||
return false;
|
||||
else
|
||||
return strncmp(p->s + (length()-suflen), suf, suflen)==0;
|
||||
}
|
||||
|
||||
|
||||
LString& LString::subst(char oldchar, char newchar)
|
||||
{
|
||||
for (int i=0; i<length() ; i++)
|
||||
if (p->s[i]==oldchar)
|
||||
p->s[i]=newchar;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
LString& LString::subst(char const * oldstr, LString const & newstr)
|
||||
{
|
||||
LString lstr = *this;
|
||||
char * str = lstr.copy();
|
||||
char * first;
|
||||
|
||||
while((first=strstr(str,oldstr))){
|
||||
if (first==str) lstr.clean();
|
||||
else lstr.substring(0,first-str-1);
|
||||
lstr+=newstr;
|
||||
lstr+=first+strlen(oldstr);
|
||||
delete[] (char*)str;
|
||||
str = lstr.copy();
|
||||
}
|
||||
delete[] (char*)str;
|
||||
return *this=lstr;
|
||||
}
|
||||
|
||||
|
||||
LString& LString::lowercase()
|
||||
{
|
||||
for (int i=0; i<length() ; i++)
|
||||
p->s[i] = tolower((unsigned char) p->s[i]);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
bool LString::regexMatch(LString const & pattern) const
|
||||
{
|
||||
if (pattern.empty())
|
||||
return true;
|
||||
if (empty())
|
||||
return false;
|
||||
|
||||
int si=0, pi=0;
|
||||
int const sl = length();
|
||||
int const pl = pattern.length();
|
||||
|
||||
while (si < sl && pi < pl) {
|
||||
if (pattern[pi]=='*') {
|
||||
// Skip all consequtive *s
|
||||
while (pattern[pi] == '*') {
|
||||
pi++;
|
||||
if (pi == pl)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get next chunk of pattern to match
|
||||
LString temp= pattern;
|
||||
temp.substring(pi, pl-1);
|
||||
LString chunk;
|
||||
temp.split(chunk, '*');
|
||||
|
||||
if (!chunk.empty() && pattern[pl-1] == '*' &&
|
||||
temp.empty())
|
||||
temp = '*';
|
||||
|
||||
if (temp.empty()) {
|
||||
// Last chunk, see if tail matches
|
||||
temp = *this;
|
||||
temp.substring(sl - chunk.length(), sl - 1);
|
||||
return temp == chunk;
|
||||
} else {
|
||||
// Middle chunk, see if we can find a match
|
||||
bool match = false;
|
||||
while (!match && si<sl) {
|
||||
temp = *this;
|
||||
temp.substring(si, sl - 1);
|
||||
match = temp.prefixIs(chunk.c_str());
|
||||
si++;
|
||||
};
|
||||
if (!match)
|
||||
return false;
|
||||
si += chunk.length()-1;
|
||||
pi += chunk.length();
|
||||
if (si==sl && pi==pl-1)
|
||||
return true;
|
||||
}
|
||||
} else if (operator[](si++) != pattern[pi++]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (pi < pl || si < sl)
|
||||
return false;
|
||||
return true;
|
||||
}
|
@ -12,6 +12,9 @@
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
// If we use STL string, there is no need to compile this class.
|
||||
#ifdef USE_INCLUDED_STRING
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "lyxstring.h"
|
||||
#endif
|
||||
@ -1620,3 +1623,5 @@ istream & getline(istream & is, lyxstring & s,
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
#endif /* USE_INCLUDED_STRING */
|
||||
|
Loading…
Reference in New Issue
Block a user