*
* LyX, The Document Processor
*
- * Copyright (C) 1995 Matthias Ettrich
- * Copyright (C) 1995-1999 The LyX Team.
+ * Copyright 1995 Matthias Ettrich
+ * Copyright 1995-2000 The LyX Team.
*
- *======================================================*/
+ * ====================================================== */
// This one is heavily based on the string class in The C++
// Programming Language by Bjarne Stroustrup
+// This class is supposed to be functionaly equivalent to a
+// standard conformant string. This mean among others that we
+// are useing the same requirements. Before you change anything
+// in this file consult me and/or the standard to discover the
+// right behavior.
+
#ifndef LYXSTRING_H
#define LYXSTRING_H
#pragma interface
#endif
-#ifdef HAVE_CONFIG_H
-#include <config.h> // needed at least for compilers that do not
-#endif // understand `explicit' (JMarc)
+#include <iosfwd>
#if 0
#include <iterator>
#endif
-#include <cstring>
-#include "LAssert.h"
+#include <cstring> // for size_t
+
/** A string class for LyX
This is a permanent String class. It is modeled closely after the C++ STL
- string class. In comparison with STL string LString lack support for
- reverse iterators and allocators, in all other senses it is written to be
- a drop in replacement for STL string (or as a transition tool). So
- documentation for STL string should be valid for LString too.
+ string class. In comparison with STL string lyxstring lack support for
+ reverse iterators and allocators, also char_traits is not used. In most
+ other senses it is written to be a drop in replacement for STL string
+ (or as a transition tool). So documentation for STL string should be
+ valid for lyxstring too.
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.
+ When you declare an lyxstring, it is initially empty. There is no need to
+ do things like #lyxstring a= "";#, especially not in constructors.
- If you want to use a default empty LString as a parameter, use
+ If you want to use a default empty lyxstring as a parameter, use
- #void foo(LString par = LString()); // Correct#
+ #void foo(lyxstring par = lyxstring()); // Correct#
rather than
- #void foo(LString par = ""); // WRONG!#
- #void foo(LString par = 0); // WRONG!#
+ #void foo(lyxstring par = ""); // WRONG!#
+ #void foo(lyxstring par = 0); // WRONG!#
(The last one is only wrong because some compilers can't handle it.)
Wrong: & #bar.substring(0, length());#
\end{tabular}
- It is important that you declare LStrings as const if possible, because
+ It is important that you declare lyxstring 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) completely wrong#
-When you want to copy an LString, just do
+When you want to copy an lyxstring, just do
- #LString a, b = "String";#
+ #lyxstring a, b = "String";#
#a = b; // That's it!#
not something like
- #LString a, b = "String";#
- #a = b.copy(); // This leaks.#
+ #lyxstring a, b = "String";#
+ #a = b.copy(); // This leaks. // and does not work either. #
The class automatically handles deep copying when required.
*/
class lyxstring {
public:
- /**@name Typedefs */
- //@{
+ /* Typedefs */
///
typedef char value_type;
#if 0
///
typedef reverse_iterator<iterator, value_type, reference>
-reverse_iterator;
+ reverse_iterator;
///
typedef reverse_iterator<const_iterator, const value_type,
-const_reference> const_reverse_iterator;
+ const_reference> const_reverse_iterator;
#endif
- //@}
///
iterator begin();
///
const_reverse_iterator rend() const;
#endif
- /**@name Constructors and Deconstructors. lyxstring has the same
+ /* Constructors and Deconstructors. lyxstring has the same
constructors as STL, except the one using iterators, one other
difference is that lyxstring, do not allow the optional allocator
parameter. */
- //@{
/// "all characters" marker
static const size_type npos;
/// #lyxstring x;#
- inline lyxstring();
+ lyxstring();
/// #lyxstring x(lyxstring ...)#
lyxstring(lyxstring const &, size_type pos = 0, size_type n = npos);
/// #lyxstring x("abc", 2) -> "ab"#
lyxstring(value_type const *, size_type n);
- /// #lyxstring x("abc")#
+ // #lyxstring x("abc")#
lyxstring(value_type const *);
/// lyxstring(5, 'n') -> "nnnnn"
lyxstring(size_type n, value_type c);
+#if 1
///
- lyxstring(iterator first, iterator last);
-
+ lyxstring(const_iterator first, const_iterator last);
+#else
///
- ~lyxstring() { if (--rep->ref == 0) delete rep; }
-
- //@}
+ template<class InputIterator>
+ lyxstring::lyxstring(InputIterator begin, InputIterator end) {
+ while (begin != end) {
+ push_back((*begin));
+ ++begin;
+ }
+ }
+#endif
+ ///
+ ~lyxstring();
-
- /**@name Size and Capacity */
- //@{
-
/// number of characters
- size_type size() const; // { return rep->sz; }
+ size_type size() const;
/// largest possible string
- size_type max_size() const { return npos -1; }
+ size_type max_size() const { return npos - 1; }
///
size_type length() const { return size(); }
///
void reserve(size_type res_arg = 0);
- //@}
-
-
- /**@name Assignment */
- //@{
-
///
lyxstring & operator=(lyxstring const &);
///
lyxstring & assign(size_type n, value_type c);
+#if 1
///
- lyxstring & assign(iterator first, iterator last);
-
- //@}
+ lyxstring & assign(const_iterator first, const_iterator last);
+#else
+ ///
+ template<class InputIterator>
+ lyxstring & assign(InputIterator begin, InputIterator end) {
+ clear;
+ while (begin != end) {
+ push_back((*begin));
+ ++begin;
+ }
+ }
+#endif
- /**@name Element Access. Since lyxstring does not use exceptions,
- an abort is called on out-of-range access to at(). */
-
/// unchecked access
const_reference operator[](size_type) const;
/// checked access
reference at(size_type);
- //@}
-
-
- /**@name Insert */
- //@{
-
// add characters after (*this)[length()-1]:
///
lyxstring & operator+=(value_type const *);
///
- inline lyxstring & operator+=(value_type);
+ lyxstring & operator+=(value_type);
///
void push_back(value_type);
///
lyxstring & append(size_type n, value_type);
+#if 1
///
lyxstring & append(iterator first, iterator last);
-
+#else
+ ///
+ template<class InputIterator>
+ lyxstring & append(InputIterator begin, InputIterator end) {
+ while (begin != end) {
+ push_back((*begin));
+ ++begin;
+ }
+ return *this;
+ }
+#endif
// insert characters before (*this)[pos]:
///
///
void insert(iterator p, size_type n , value_type c);
+#if 1
///
void insert(iterator p, iterator first, iterator last);
+#else
+ ///
+ template<class InputIterator>
+ void insert(iterator p, InputIterator begin, InputIterator end) {
+ iterator it;
+ while (begin != end) {
+ it = insert(p, (*begin));
+ ++begin;
+ }
+ }
+#endif
- //@}
-
- /**@name Find */
- //@{
-
///
size_type find(lyxstring const &, size_type i = 0) const;
size_type find_first_of(lyxstring const &, size_type i = 0) const;
///
- size_type find_first_of(value_type const * p, size_type i, size_type n) const;
+ size_type find_first_of(value_type const * p, size_type i,
+ size_type n) const;
///
size_type find_first_of(value_type const * p, size_type i = 0) const;
size_type find_last_of(lyxstring const &, size_type i = npos) const;
///
- size_type find_last_of(value_type const * p, size_type i, size_type n) const;
+ size_type find_last_of(value_type const * p, size_type i,
+ size_type n) const;
///
size_type find_last_of(value_type const * p, size_type i = npos) const;
size_type n) const;
///
- size_type find_first_not_of(value_type const * p, size_type i = 0) const;
+ size_type find_first_not_of(value_type const * p,
+ size_type i = 0) const;
///
size_type find_first_not_of(value_type c, size_type i = 0) const;
///
- size_type find_last_not_of(lyxstring const &, size_type i = npos) const;
+ size_type find_last_not_of(lyxstring const &,
+ size_type i = npos) const;
///
size_type find_last_not_of(value_type const * p, size_type i,
size_type n) const;
///
- size_type find_last_not_of(value_type const * p, size_type i = npos) const;
+ size_type find_last_not_of(value_type const * p,
+ size_type i = npos) const;
///
size_type find_last_not_of(value_type c, size_type i = npos) const;
- //*}
-
-
- /**@name Replace */
- //@{
-
// replace [(*this)[i], (*this)[i+n]] with other characters:
///
- lyxstring & replace(size_type i,size_type n, lyxstring const & str);
+ lyxstring & replace(size_type i, size_type n, lyxstring const & str);
///
- lyxstring & replace(size_type i,size_type n, lyxstring const & s,
+ lyxstring & replace(size_type i, size_type n, lyxstring const & s,
size_type i2, size_type n2);
///
- lyxstring & replace(size_type i,size_type n, value_type const * p,
+ lyxstring & replace(size_type i, size_type n, value_type const * p,
size_type n2);
///
- lyxstring & replace(size_type i,size_type n, value_type const * p);
+ lyxstring & replace(size_type i, size_type n, value_type const * p);
///
- lyxstring & replace(size_type i, size_type n, size_type n2, value_type c);
+ lyxstring & replace(size_type i, size_type n,
+ size_type n2, value_type c);
+
+ /// FY! FY! FY! go away !
+ lyxstring & replace(size_type i, size_type n,
+ value_type c);
///
lyxstring & replace(iterator i, iterator i2, const lyxstring & str);
lyxstring & replace(iterator i, iterator i2, value_type const * p);
///
- lyxstring & replace(iterator i, iterator i2, size_type n , value_type c);
-
+ lyxstring & replace(iterator i, iterator i2,
+ size_type n , value_type c);
+
///
lyxstring & replace(iterator i, iterator i2, iterator j, iterator j2);
+ ///
+ void swap(lyxstring & str);
+
/// Erase n chars from position i.
lyxstring & erase(size_type i = 0, size_type n = npos);
///
iterator erase(iterator first, iterator last);
- //@}
-
-
- /**@name Conversion to C-style Strings */
- //@{
-
///
value_type const * c_str() const;
- /** Note that this is STL compilant, so you can not assume
+ /* Note that this is STL compilant, so you can not assume
that the returned array has a trailing '\0'. */
value_type const * data() const;
- /** This one returns a verbatim copy. Not the trailing '\0'
+ /* This one returns a verbatim copy. Not the trailing '\0'
The caller must provide a buffer with engough room.
*/
- size_type copy(value_type * buf, size_type len, size_type pos = 0) const;
-
- //@}
+ size_type copy(value_type * buf, size_type len,
+ size_type pos = 0) const;
- /**@name Comparisons. Combined > and == */
- //@{
-
///
int compare(lyxstring const & str) const;
int compare(size_type pos, size_type n, value_type const * p,
size_type n2 = npos) const;
- //@}
-
-
- /**@name Substrings */
- //@{
-
///
lyxstring substr(size_type i = 0, size_type n = npos) const;
- //@}
-
private:
- ///
- lyxstring & operator+(int);
- ///
- lyxstring & operator=(int);
- ///
- lyxstring & operator+=(int);
-
- /// A string representation
- struct Srep {
- ///
- static lyxstring::size_type const xtra =
- static_cast<lyxstring::size_type>(8);
- /// size
- lyxstring::size_type sz;
- /// Reference count
- unsigned short ref;
- /// The total amount of data reserved for this representaion
- lyxstring::size_type res;
- /// Data. At least 1 char for trailing null.
- lyxstring::value_type * s;
-
- ///
- Srep(lyxstring::size_type nsz, const lyxstring::value_type * p);
- ///
- Srep(lyxstring::size_type nsz, lyxstring::value_type ch);
- ///
- ~Srep() { delete[] s; }
- ///
- Srep * get_own_copy()
- {
- if (ref == 1) return this;
- ref--;
- return new Srep(sz, s);
- }
+ // These three operators can be used to discover erronous use of
+ // ints and strings. However a conforming C++ compiler will flag
+ // a lot of char operations as ambigous when they are compiled
+ // in. Use them for debugging only (or perhaps not even then.)
+ // Lgb.
+ //
+ //lyxstring & operator+(int);
+ //
+ //lyxstring & operator=(int);
+ //
+ //lyxstring & operator+=(int);
+
+ /// Compare this with s. works with embedded '\0' chars also.
+ int internal_compare(size_type pos, size_type n,
+ value_type const * s,
+ size_type slen, size_type n2) const;
- ///
- void assign(lyxstring::size_type nsz, const lyxstring::value_type * p);
- ///
- void assign(lyxstring::size_type nsz, lyxstring::value_type ch);
- ///
- void append(lyxstring::size_type asz, const lyxstring::value_type * p);
- ///
- void push_back(lyxstring::value_type c);
- ///
- void insert(lyxstring::size_type pos,
- const lyxstring::value_type * p,
- lyxstring::size_type n);
- ///
- void resize(lyxstring::size_type n, lyxstring::value_type c);
- ///
- void reserve(lyxstring::size_type res_arg);
- ///
- void replace(lyxstring::size_type i, lyxstring::size_type n,
- lyxstring::value_type const * p, lyxstring::size_type n2);
- private:
- Srep(const Srep &);
- Srep & operator=(const Srep &);
- };
-
- /** The empty_rep is a local static in each function that
+ /// Forward declaration of the string representation
+ struct Srep;
+ // DEC cxx requires this.
+ friend struct Srep;
+
+ /// A string is a pointer to it's representation
+ Srep * rep;
+
+ /* Note: The empty_rep is a local static in each function that
benefits from one. There is no "global" empty srep but lyxstring
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 a few local static
empty_reps.
- */
+ */
- /// A string is a pointer to it's representation
- Srep * rep;
-
-#ifdef DEVEL_VERSION
+#ifdef ENABLE_ASSERTIONS
/// lyxstringInvariant is used to test the lyxstring Invariant
friend class lyxstringInvariant;
-#endif //DEVEL_VERSION
+#endif
};
// The usual comparison operators ==, !=, >, <, >=, <= are
lyxstring operator+(lyxstring const & a, lyxstring::value_type const * b);
lyxstring operator+(lyxstring const & a, lyxstring::value_type b);
-class istream; class ostream;
-istream & operator>>(istream &, lyxstring &);
-ostream & operator<<(ostream &, lyxstring const &);
-istream & getline(istream &, lyxstring &, lyxstring::value_type delim = '\n');
+void swap(lyxstring & s1, lyxstring & s2);
+
+std::istream & operator>>(std::istream &, lyxstring &);
+std::ostream & operator<<(std::ostream &, lyxstring const &);
+std::istream & getline(std::istream &, lyxstring &, lyxstring::value_type delim = '\n');
#endif