// -*- C++ -*- /* This file is part of * ====================================================== * * LyX, The Document Processor * * Copyright (C) 1995 1996 Matthias Ettrich * and the LyX Team. *
*======================================================*/
// This one is heavily based on the string class in The C++ // Programming Language by Bjarne Stroustrup
#ifndef _LSTRING_H_ #define _LSTRING_H_
#ifdef __GNUG__ #pragma interface #endif
#include <config.h> // needed at least for compiler that do not // understand 'explicit' (JMarc) #ifdef _AIX // AIX has strange ideas about where definitions like strcasecmp // should go (JMarc) #include <strings.h> #else #include <string.h> #endif
/** A string class for LyX This is a permanent String class. It was supposed to be superseeded with QString when we switch to the Qt library, but now it's so developed that it is as good as theirs (or maybe even better :-)
Notes for usage:
When you declare an LString, it is initially empty. There is no need to do things like #LString a= "";#, especially not in constructors.
If you want to use a default empty LString as a parameter, use #void foo(LString par = LString()); // Correct# rather than
#void foo(LString par = ""); // WRONG!# #void foo(LString par = 0); // WRONG!#
(The last one is only wrong because some compilers can't handle it.)
Methods that take an index as parameter all follow this rule: Valid indexes go from 0 to length()-1. \begin{tabular}{rl} Correct: & #foo.substring(0, length()-1);# \\ Wrong: & #bar.substring(0, length());# \end{tabular} It is important that you declare LStrings as const if possible, because some methods are much more efficient in const versions. If you want to check whether a string is empty, do
#if (foo.empty()) something right#
rather than something along the lines of
#if (!foo) completely wrong#
When you use the #.copy()# method, LString calls "#new []#", so you have to release the memory with #delete[]#. Don't preallocate memory.
When you want to copy an LString, just do #LString a, b = "String";# #a = b; // That's it!#
not something like #LString a, b = "String";# #a = b.copy(); // This leaks.# The class automatically handles deep copying when required.
*/ class LString { public: /**@name Constructors and Deconstructors */ //@{ /// #LString x;#
LString(); /// #LString x(LString ...)#
LString(LString const &); /// #LString x("abc")#
LString(charconst*); /// #LString x('a')# explicit LString(charconst); // not all C++ compilers understands explicit as of now
/**@name Methods */ //@{ /// to comply with the STL strings bool empty() const; /// //bool isEmpty() const; /// //bool notEmpty() const; /// int length() const;
// should be renamed to erase() (STL) /** equivalent to *this = empty. But usable outside LString
implementation */
LString &clean();
/// This should be renamed to c_str() charconst* c_str() const;
// we should make the caller supply the storage to copy into. (STL) /** This one returns a verbatim copy. Only temporary. The caller should call delete [] when done with the string
*/ char * copy() const;
/// bool contains(charconst *) const;
// Remove and replace (STL) /// Truncate to substring. I.e. #"abcdef".substring(2,4)="cde"#
LString& substring(int i1, int i2);
/** Splits the string by the first delim. Splits the string by the first appearance of delim. The leading string up to delim is returned in piece (not including delim), while the original string is cut from after the delimiter. Example: #s1=""; s2="a;bc".split(s1, ';') -> s1=="a"; s2 == "bc";#
*/
LString& split(LString& piece, char delim); /// Same as split but does not return a piece
LString& split(char delim); /// Same as split but uses the last delim.
LString& rsplit(LString& piece, char delim);
/** Extracts a token from this string at the nth delim. Doesn't modify the original string. Similar to strtok. Example: #"a;bc;d".token(';', 1) == "bc";# #"a;bc;d".token(';', 2) == "d";#
*/
LString token(char delim, int n=0) const;
/** Search a token in this string using the delim. Doesn't modify the original string. Returns -1 in case of failure. Example: #"a;bc;d".tokenPos(';', "bc") == 1;# #"a;bc;d".token(';', "d") == 2;#
*/ int tokenPos(char delim, LString const &tok);
/** Strips characters off the end of a string. #"abccc".strip('c') = "ab".#
*/
LString& strip(charconst c = ' ');
/** Strips characters of the beginning of a string.
#"cccba".frontstrip('c') = "ba"#. */
LString& frontStrip(charconst c = ' ');
/// Does the string start with this prefix? bool prefixIs(charconst *) const;
/// Does the string end with this char? bool suffixIs(char) const;
/// Does the string end with this suffix? bool suffixIs(charconst *) const;
/// Substitute all "oldchar"s with "newchar"
LString& subst(char oldchar, char newchar);
/// Substitutes all instances of oldstr with newstr
LString& subst(charconst * oldstr, LString const & newstr);
/** Compares a string and a (simple) regular expression The only element allowed is "*" for any string of characters
*/ bool regexMatch(LString const & pattern) const;
/// Lowercases a string
LString& lowercase();
/// Counts how many of character c there is in string int countChar(constchar c) const;
/// Position of the character c from the beggining int charPos(constchar c) const;
protected: private: /// A string representation struct srep { /// Length unsignedint l; /// Reference count (number of references - 1) unsignedshort n; /// Extra space at end of allocated string unsignedshort e; /// Data. At least 1 char for trailing null. char s[1]; ///
srep() { n = 0; l = 0; e = 0; s[0] = '\0'; }
};
/** The empty srep is a local static in each function that needs one. There is no "global" empty srep but LString doesn't need one (no code actually relies upon a single empty srep). This overcomes *all* "static initialization" problems, at maximum speed, with a small overhead of 6 local static empty_reps.
*/ // This is the only other option (or a variant of this anyway) // I originally offered this style of empty_rep in 9709 but // it was rejected for requiring too many function calls and pointer operations(!) // and because another implementation was to be trialed (which has since // apparently failed for some compilers). ARRae // static srep& empty_rep() // { // static srep mt; // return mt; // }
/// A string is a pointer to it's representation
srep *p; /// void lose();
};
inline LString::LString(LString const &x)
{
x.p->n++;
p = x.p;
}