+++ /dev/null
-/**
- * \file lyxstring.C
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Lars Gullik Bjønnes
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "lyxstring.h"
-
-#include "debug.h"
-
-#include <iostream>
-#include <cstdlib>
-#include <cctype>
-#include <algorithm>
-
-using std::min;
-using std::istream;
-using std::ostream;
-
-// 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.
-
-// Asserts with a STD! are required by the standard.
-// Asserts with a OURS! are added by me.
-// Some asserts could still be missing and some of the existing
-// ones might be wrong or not needed.
-
-// Reference count has been checked, empty_rep removed and
-// introduced again in a similar guise. Where is empty_rep _really_
-// needed?
-
-// We are missing a couple of imporant things from the standard:
-// reverse iterators and methods taking InputIterators as paramters.
-// Also the methods returning iterators is returning the wrong value.
-
-// All the different find functions need a good look over.
-// I have so far not tested them extensively and would be
-// happy if others took the time to have a peek.
-
-// Space allocation of string.
-// I have tried to do this very simple without using any special tricks.
-// Earlier we used a fixed value to enlarge the string with this would
-// cause a lot of reallocations with large strings (especially if
-// push_back was used) and wasting space for very small strings.
-// I have now changed the allocation to use a doubling of reserved
-// space until it is large enough. So far tests show a small speed
-// increase and a noticable memory saving.
-
-// Lgb.
-
-namespace lyx {
-
-using support::BOOST_ASSERT;
-
-///////////////////////////////////////
-// The internal string representation
-///////////////////////////////////////
-
-struct string::Srep {
- /// size
- size_t sz;
- /// Reference count
- size_t ref;
- /// The total amount of data reserved for this representaion
- size_t res;
- /// Data. At least 1 char for trailing null.
- string::value_type * s;
-
- ///
- Srep(string::size_type nsz, const string::value_type * p);
- ///
- Srep(string::size_type nsz, string::value_type ch);
- ///
- ~Srep() { delete[] s; }
- ///
- Srep * get_own_copy() {
- if (ref == 1) return this;
- --ref;
- return new Srep(sz, s);
- }
-
- ///
- void assign(string::size_type nsz, const string::value_type * p);
- ///
- void assign(string::size_type nsz, string::value_type ch);
- ///
- void append(string::size_type asz, const string::value_type * p);
- ///
- void push_back(string::value_type c);
- ///
- void insert(string::size_type pos,
- const string::value_type * p,
- string::size_type n);
- ///
- void resize(string::size_type n, string::value_type c);
- ///
- void reserve(string::size_type res_arg);
- ///
- void replace(string::size_type i, string::size_type n,
- string::value_type const * p, string::size_type n2);
-private:
- Srep(const Srep &);
- Srep & operator=(const Srep &);
-};
-
-
-string::Srep::Srep(string::size_type nsz, const value_type * p)
-{
- // can be called with p == 0 by
- // string::assign(const value_type *, size_type)
-
- sz = nsz;
- ref = 1;
- res = sz ? sz : 1;
- s = new value_type[res + 1]; // add space for terminator
- if (p && sz) {
- // if sz = 0 nothing gets copied and we have an error
- memcpy(s, p, sz);
- } else {
- // possibly allows for large but empty string
- sz = 0; // this line should be redundant
- s[0] = '\0';
- }
-}
-
-
-string::Srep::Srep(string::size_type nsz, value_type ch)
-{
- sz = nsz;
- ref = 1;
- res = sz ? sz : 1;
- s = new value_type[res + 1]; // add space for terminator
- memset(s, ch, sz);
- if (!ch) {
- // if ch == '\0' strlen(string.c_str()) == 0 so sz = 0
- // allows for large but empty string
- sz = 0;
- }
-}
-
-
-void string::Srep::assign(string::size_type nsz, const value_type * p)
-{
- // can be called with p == 0
- // by string::assign(const value_type *, size_type)
-
- if (res < nsz) {
- delete[] s;
- sz = nsz;
- res = sz ? sz : 1;
- s = new value_type[res + 1]; // add space for terminator
- } else {
- sz = nsz;
- }
- if (p && sz) {
- // if sz = 0 nothing gets copied and we have an error
- memcpy(s, p, sz);
- } else {
- // stops segfaults
- sz = 0; // this line should be redundant
- s[0] = '\0';
- }
-}
-
-
-void string::Srep::assign(string::size_type nsz, value_type ch)
-{
- sz = nsz;
- if (res < nsz) {
- delete[] s;
- res = sz ? sz : 1;
- s = new value_type[res + 1]; // add space for terminator
- }
- memset(s, ch, sz);
- if (!ch) {
- // if ch == '\0' strlen(string.c_str()) == 0 so sz = 0
- // allows for a large empty string
- sz = 0;
- }
-}
-
-
-void string::Srep::append(string::size_type asz, const value_type * p)
-{
- register unsigned int const len = sz + asz;
- if (res < len) {
- do {
- res *= 2;
- } while (res < len);
- value_type * tmp = new value_type[res + 1];
- memcpy(tmp, s, sz);
- memcpy(tmp + sz, p, asz);
- sz += asz;
- delete[] s;
- s = tmp;
- } else {
- memcpy(s + sz, p, asz);
- sz += asz;
- }
-}
-
-
-void string::Srep::push_back(value_type c)
-{
- s[sz] = c; // it is always room to put a value_type at the end
- ++sz;
- if (res < sz) {
- do {
- res *= 2;
- } while (res < sz);
- value_type * tmp = new value_type[res + 1];
- memcpy(tmp, s, sz);
- delete[] s;
- s = tmp;
- }
-}
-
-
-void string::Srep::insert(string::size_type pos, const value_type * p,
- string::size_type n)
-{
- if (res < n + sz) {
- do {
- res *= 2;
- } while (res < n + sz);
- value_type * tmp = new value_type[res + 1];
- memcpy(tmp, s, pos);
- memcpy(tmp + pos, p, n);
- memcpy(tmp + pos + n, &s[pos], sz - pos);
- sz += n;
- delete[] s;
- s = tmp;
- } else {
- memmove(s + pos + n, &s[pos], sz - pos);
- memcpy(s + pos, p, n);
- sz += n;
- }
-}
-
-
-void string::Srep::resize(size_type n, value_type c)
-{
- // This resets sz to res_arg
- res = min(n, npos - 2); // We keep no xtra when we resize
- value_type * tmp = new value_type[res + 1];
- memcpy(tmp, s, min(sz, res));
- if (res > sz)
- memset(tmp + sz, c, res - sz);
- delete[] s;
- sz = res;
- s = tmp;
-}
-
-
-void string::Srep::reserve(string::size_type res_arg)
-{
- // This keeps the old sz, but
- // increases res with res_arg
- res += res_arg;
- value_type * tmp = new value_type[res + 1];
- memcpy(tmp, s, sz);
- delete[] s;
- s = tmp;
-}
-
-
-void string::Srep::replace(string::size_type i, string::size_type n,
- value_type const * p, size_type n2)
-{
-// can be called with p= 0 and n2= 0
- n = min(sz - i, n);
- sz -= n;
- if (res >= n2 + sz) {
- memmove(s + i + n2, &s[i + n], sz - i);
- memcpy(s + i, p, n2);
- sz += n2;
- } else {
- do {
- res *= 2;
- } while (res < n2 + sz);
- value_type * tmp = new value_type[res + 1];
- memcpy(tmp, s, i);
- memcpy(tmp + i, p, n2);
- memcpy(tmp + i + n2, &s[i + n], sz - i);
- delete[] s;
- s = tmp;
- sz += n2;
- }
-}
-
-
-///////////////////////////////////////
-// The string Invariant tester
-///////////////////////////////////////
-
-// There are no know bugs in string now, and it have been
-// tested for a long time. so we disable the invariant checker. (Lgb)
-#undef ENABLE_ASSERTIONS
-#ifdef ENABLE_ASSERTIONS
-
-/** Testing of the string invariant
- * By creating an object that tests the string invariant during its
- * construction *and* its deconstruction we greatly simplify our code.
- * Calling TeststringInvariant() upon entry to an string method
- * will test the invariant upon entry to the code. If the Asserts fail
- * then we know from the stack trace that the corruption occurred *before*
- * entry to this method. We can also be sure it didn't happen in any of
- * the tested string methods. It is therefore likely to be due to some
- * other external force.
- * Several string methods have multiple exit points which would otherwise
- * require us to insert a separate test before each return. But since we
- * created an object its destructor will be called upon exit (any exit!).
- * We thus get testing at both start and end of a method with one line of
- * code at the head of a method. More importantly, we get good testing
- * everytime we run the code.
- * NOTE: just because we test the invariant doesn't mean we can forget
- * about testing pre and post conditions specific to any given method.
- * This test simply proves that the string/Srep is in a valid state it
- * does *not* prove that the method did what it was supposed to.
- */
-class stringInvariant {
-public:
- stringInvariant(string const *);
- ~stringInvariant();
-private:
- void helper() const;
- string const * object;
-};
-
-
-// To test if this scheme works "as advertised" uncomment the printf's in
-// the constructor and destructor below and then uncomment the printf and the
-// call to TestlyxstringInvariant() in string::operator=(char const *).
-// The correct output when LyX has been recompiled and run is:
-// lyxstringInvariant constructor
-// string::operator=(char const *)
-// lyxstringInvariant constructor
-// lyxstringInvariant destructor completed
-// lyxstringInvariant destructor completed
-// NOTE: The easiest way to catch this snippet of the output is to wait for
-// the splash screen to disappear and then open and close Help->Credits
-//
-stringInvariant::stringInvariant(string const * ls) : object(ls)
-{
- // printf("stringInvariant constructor\n");
- helper();
-}
-
-
-stringInvariant::~stringInvariant()
-{
- helper();
- // printf("stringInvariant destructor completed\n");
-}
-
-
-void stringInvariant::helper() const
-{
- // Some of these tests might look pointless but they are
- // all part of the invariant and if we want to make sure
- // we have a bullet proof implementation then we need to
- // test every last little thing we *know* should be true.
- // I may have missed a test or two, so feel free to fill
- // in the gaps. ARRae.
- BOOST_ASSERT(object);
- BOOST_ASSERT(object->rep);
- BOOST_ASSERT(object->rep->s); // s is never 0
- BOOST_ASSERT(object->rep->res); // res cannot be 0
- BOOST_ASSERT(object->rep->sz <= object->rep->res);
- BOOST_ASSERT(object->rep->ref >= 1); // its in use so it must be referenced
- BOOST_ASSERT(object->rep->ref < 1UL << (8UL * sizeof(object->rep->ref) - 1));
- // if it does ever == then we should be generating a new copy
- // and starting again. (Is char always 8-bits?)
-}
-#define TeststringInvariant(s) stringInvariant string_invariant(s);
-#else
-#define TeststringInvariant(s)
-#endif /* ENABLE_ASSERTIONS */
-
-
-///////////////////////////////////////
-// Constructors and Deconstructors.
-///////////////////////////////////////
-
-string::size_type const string::npos =
-static_cast<string::size_type>(-1);
-
-
-string::string()
-{
- static Srep empty_rep(0, "");
- ++empty_rep.ref;
- rep = &empty_rep;
-}
-
-
-string::string(string const & x, size_type pos, size_type n)
-{
- BOOST_ASSERT(pos <= x.rep->sz); // STD!
- if (pos == 0 && n >= x.length()) { // this is the default
- x.rep->ref++;
- rep = x.rep;
- } else {
- rep = new Srep(min(n, x.rep->sz - pos), &(x.rep->s[pos]));
- }
-}
-
-
-string::string(value_type const * s, size_type n)
-{
- BOOST_ASSERT(s && n < npos); // STD!
- static Srep empty_rep(0, "");
- if (n) { // n > 0
- rep = new Srep(n, s);
- } else {
- ++empty_rep.ref;
- rep = &empty_rep;
- }
-}
-
-
-string::string(value_type const * s)
-{
- BOOST_ASSERT(s); // STD!
- static Srep empty_rep(0, "");
- if (*s) { // s is not empty string
- rep = new Srep(strlen(s), s);
- } else {
- ++empty_rep.ref;
- rep = &empty_rep;
- }
-}
-
-
-string::string(size_type n, value_type c)
-{
- BOOST_ASSERT(n < npos); // STD!
- rep = new Srep(n, c);
-}
-
-
-#warning string user, have a look here. (Lgb)
-#if 0
-// Commented out to avoid warnings from doxygen. (Lgb)
-string::string(const_iterator first, const_iterator last)
-{
- rep = new Srep(last - first, first);
-}
-#endif
-
-
-string::~string()
-{
- if (--rep->ref == 0) delete rep;
-}
-
-///////////////////////
-// Iterators
-///////////////////////
-
-string::iterator string::begin()
-{
- rep = rep->get_own_copy();
- return rep->s;
-}
-
-
-string::const_iterator string::begin() const
-{
- return rep->s;
-}
-
-
-string::iterator string::end()
-{
- rep = rep->get_own_copy();
- return rep->s + rep->sz;
-}
-
-
-string::const_iterator string::end() const
-{
- return rep->s + rep->sz;
-}
-
-#if 0
-reverse_iterator string::rbegin()
-{
- return reverse_iterator( end() );
-}
-
-
-const_reverse_iterator string::rbegin() const
-{
- return const_reverse_iterator( end() );
-}
-
-
-reverse_iterator string::rend()
-{
- return reverse_iterator( begin() );
-}
-
-
-const_reverse_iterator string::rend() const
-{
- return const_reverse_iterator( begin() );
-}
-#endif
-
-
-///////////////////////
-// Size and Capacity
-///////////////////////
-
-string::size_type string::size() const
-{
- return rep->sz;
-}
-
-
-void string::resize(size_type n, value_type c)
-{
- BOOST_ASSERT(n <= npos); // STD!
- TeststringInvariant(this);
-
- // This resets sz to res_arg
- rep = rep->get_own_copy();
- rep->resize(n, c);
-}
-
-
-string::size_type string::capacity() const
-{
- return rep->res;
-}
-
-
-void string::reserve(size_type res_arg)
-{
- TeststringInvariant(this);
-
- rep = rep->get_own_copy();
- rep->reserve(res_arg);
-}
-
-
-////////////////
-// Assignment
-////////////////
-
-string & string::operator=(string const & x)
-{
- TeststringInvariant(this);
-
- return assign(x);
-}
-
-
-string & string::operator=(value_type const * s)
-{
- BOOST_ASSERT(s); // OURS!
- TeststringInvariant(this);
-// printf("string::operator= (value_type const *)\n");
-
- return assign(s);
-}
-
-
-string & string::operator=(value_type c)
-{
- TeststringInvariant(this);
-
- value_type s[1];
- s[0] = c;
- if (rep->ref == 1) // recycle rep
- rep->assign(1, s);
- else {
- rep->ref--;
- rep = new Srep(1, s);
- }
- return *this;
-}
-
-
-string & string::assign(string const & x)
-{
- TeststringInvariant(this);
-
- x.rep->ref++; // protect against ``st = st''
- if (--rep->ref == 0) delete rep;
- rep = x.rep; // share representation
- return *this;
-}
-
-
-string & string::assign(string const & x, size_type pos, size_type n)
-{
- BOOST_ASSERT(pos <= x.rep->sz); // STD!
- TeststringInvariant(this);
-
- return assign(x.substr(pos, n));
-}
-
-
-string & string::assign(value_type const * s, size_type n)
-{
- BOOST_ASSERT(s && n < npos); // STD!
- TeststringInvariant(this);
-
- if (rep->ref == 1) // recycle rep
- rep->assign(n, s);
- else {
- --rep->ref;
- rep = new Srep(n, s);
- }
- return *this;
-}
-
-
-string & string::assign(value_type const * s)
-{
- BOOST_ASSERT(s); // OURS!
- TeststringInvariant(this);
-
- return assign(s, strlen(s));
-}
-
-
-string & string::assign(size_type n, value_type ch)
-{
- TeststringInvariant(this);
-
- rep = rep->get_own_copy();
- rep->assign(n, ch);
- return *this;
-}
-
-
-string & string::assign(const_iterator first, const_iterator last)
-{
- TeststringInvariant(this);
-
- rep = rep->get_own_copy();
- rep->assign(last - first, first);
- return *this;
-}
-
-
-////////////////////
-// Element Access
-////////////////////
-
-string::const_reference string::operator[](size_type pos) const
-{
-#if 0
- // This is actually what the standard requires,
- BOOST_ASSERT(pos <= rep->sz); // OURS!
- static char const helper = '\0';
- return pos == rep->sz ? helper : rep->s[pos];
-#else
- // but we use this one since it is stricter
- // and more according to the real intent of std::string.
- BOOST_ASSERT(pos < rep->sz); // OURS!
- return rep->s[pos];
-#endif
-}
-
-
-string::reference string::operator[](size_type pos)
-{
- BOOST_ASSERT(pos < rep->sz); // OURS!
- TeststringInvariant(this);
-
- rep = rep->get_own_copy();
- return rep->s[pos];
-}
-
-
-string::const_reference string::at(size_type n) const
-{
- BOOST_ASSERT(n < rep->sz); // STD!
- return rep->s[n];
-}
-
-
-string::reference string::at(size_type n)
-{
- BOOST_ASSERT(n < rep->sz); // STD!
- TeststringInvariant(this);
-
- rep = rep->get_own_copy();
- return rep->s[n];
-}
-
-
-/////////////
-// Insert
-/////////////
-
-string & string::operator+=(string const & x)
-{
- TeststringInvariant(this);
-
- return append(x);
-}
-
-
-string & string::operator+=(value_type const * x)
-{
- BOOST_ASSERT(x); // OURS!
- TeststringInvariant(this);
-
- return append(x);
-}
-
-
-string & string::operator+=(value_type c)
-{
- TeststringInvariant(this);
-
- push_back(c);
- return *this;
-}
-
-
-void string::push_back(value_type c)
-{
- TeststringInvariant(this);
-
- rep = rep->get_own_copy();
- rep->push_back(c);
-}
-
-
-string & string::append(string const & x)
-{
- TeststringInvariant(this);
-
- if (x.empty()) return *this;
- rep = rep->get_own_copy();
- rep->append(x.length(), x.rep->s);
- return *this;
-}
-
-
-string & string::append(string const & x, size_type pos, size_type n)
-{
- BOOST_ASSERT(pos <= x.rep->sz); // STD!
- TeststringInvariant(this);
-
- return append(x.substr(pos, n));
-}
-
-
-string & string::append(value_type const * p, size_type n)
-{
- BOOST_ASSERT(p); // OURS!
- TeststringInvariant(this);
-
- if (!*p || !n) return *this;
- rep = rep->get_own_copy();
- rep->append(n, p);
- return *this;
-}
-
-
-string & string::append(value_type const * p)
-{
- BOOST_ASSERT(p); // OURS!
- return append(p, strlen(p));
-}
-
-
-string & string::append(size_type n, value_type c)
-{
- TeststringInvariant(this);
-
- value_type * tmp = new value_type[n];
- memset(tmp, c, n);
- rep = rep->get_own_copy();
- rep->append(n, tmp);
- delete[] tmp;
- return *this;
-}
-
-
-string & string::append(iterator first, iterator last)
-{
- TeststringInvariant(this);
-
- rep = rep->get_own_copy();
- rep->append(last - first, first);
- return *this;
-}
-
-// insert characters before (*this)[pos]
-
-string & string::insert(size_type pos, string const & x)
-{
- TeststringInvariant(this);
-
- return insert(pos, x, 0, x.rep->sz);
-}
-
-
-string & string::insert(size_type pos, string const & x,
- size_type pos2, size_type n)
-{
- BOOST_ASSERT(pos <= rep->sz && pos2 <= x.rep->sz); // STD!
- TeststringInvariant(this);
-
- rep = rep->get_own_copy();
- rep->insert(pos, &(x.rep->s[pos2]), min(n, x.rep->sz));
- return *this;
-}
-
-
-string & string::insert(size_type pos, value_type const * p, size_type n)
-{
- BOOST_ASSERT(p); // OURS!
- TeststringInvariant(this);
-
- if (*p && n) {
- // insert nothing and you change nothing
- rep = rep->get_own_copy();
- rep->insert(pos, p, n);
- }
- return *this;
-}
-
-
-string & string::insert(size_type pos, value_type const * p)
-{
- BOOST_ASSERT(p); // OURS!
- return insert(pos, p, strlen(p));
-}
-
-
-string & string::insert(size_type pos, size_type n, value_type c)
-{
- TeststringInvariant(this);
-
- rep = rep->get_own_copy();
- value_type * tmp = new value_type[n];
- memset(tmp, c, n);
- rep->insert(pos, tmp, n);
- delete[] tmp;
- return *this;
-}
-
-
-string::iterator string::insert(iterator p, value_type c)
-{
- TeststringInvariant(this);
-
- // what iterator is this supposed to return??
- size_type tmp = p - begin();
- insert(p - begin(), 1, c);
- return begin() + tmp + 1; // ??
-}
-
-
-void string::insert(iterator p, size_type n , value_type c)
-{
- TeststringInvariant(this);
-
- insert(p - begin(), n , c);
-}
-
-
-void string::insert(iterator p, iterator first, iterator last)
-{
- TeststringInvariant(this);
-
- insert(p - begin(), first, last - first);
-}
-
-
-////////////////
-// Find
-////////////////
-
- // All the below find functions should be verified,
- // it is very likely that I have mixed up or interpreted
- // some of the parameters wrong, also some of the funcs can surely
- // be written more effectively.
-
-string::size_type string::find(string const & a, size_type i) const
-{
- if (!rep->sz || i >= rep->sz) return npos;
-
- TeststringInvariant(this);
-
- size_type n = a.length();
- if (!n) return npos;
- for (size_type t = i; rep->sz - t >= n; ++t) {
- // search until (*this)[i] == a[0]
- if (rep->s[t] == a[0]) {
- // check if the rest of the value_types match
- bool equal = true;
- for (size_type j = 1; j < n; ++j) {
- if (rep->s[t + j] != a[j]) {
- equal = false;
- break;
- }
- }
- if (equal) return t;
- }
- }
- return npos;
-}
-
-
-string::size_type string::find(value_type const * ptr, size_type i,
- size_type n) const
-{
- BOOST_ASSERT(ptr); // OURS!
- if (!rep->sz || !*ptr || i >= rep->sz) return npos;
-
- TeststringInvariant(this);
-
- // What is "n" here? is it the number of value_types to use in ptr
- // or does "i" and "n" togeter form a substring to search
- // for ptr in? For now I will assume that "n" tells the length
- // of ptr. (Lgb)
- n = min(n, strlen(ptr));
- if (!n) return npos;
- for (size_type t = i; rep->sz - t >= n; ++t) {
- // search until (*this)[i] == a[0]
- if (rep->s[t] == ptr[0]) {
- // check if the rest of the value_types match
- bool equal = true;
- for (size_type j = 1; j < n; ++j) {
- if (rep->s[t + j] != ptr[j]) {
- equal = false;
- break;
- }
- }
- if (equal) return t;
- }
- }
- return npos;
-}
-
-
-string::size_type string::find(value_type const * s, size_type i) const
-{
- BOOST_ASSERT(s); // OURS!
- if (!rep->sz || i >= rep->sz) return npos;
-
- TeststringInvariant(this);
-
- if (!s || !*s) return npos;
- return find(s, i, strlen(s));
-}
-
-
-string::size_type string::find(value_type c, size_type i) const
-{
- if (!rep->sz || i >= rep->sz) return npos;
-
- TeststringInvariant(this);
-
- for (size_type t = 0; t + i < rep->sz; ++t) {
- if (rep->s[t + i] == c) return t + i;
- }
- return npos;
-}
-
-
-string::size_type string::rfind(string const & a, size_type i) const
-{
- TeststringInvariant(this);
-
- size_type n = a.length();
- if (!n || rep->sz < n)
- return npos;
-
- size_type t = min(rep->sz - n, i);
- do {
- if (rep->s[t] == a[0]) {
- // check if the rest of the value_types match
- bool equal = true;
- for (size_type j = 1; j < n; ++j) {
- if (rep->s[t + j] != a[j]) {
- equal = false;
- break;
- }
- }
- if (equal) return t;
- }
- } while (t-- > 0);
- return npos;
-}
-
-
-string::size_type string::rfind(value_type const * ptr, size_type i,
- size_type n) const
-{
- BOOST_ASSERT(ptr); // OURS!
- TeststringInvariant(this);
-
- n = min(n, strlen(ptr));
- if (!n || rep->sz < n)
- return npos;
-
- size_type t = min(rep->sz - n, i);
- do {
- if (rep->s[t] == ptr[0]) {
- // check if the rest of the value_types match
- bool equal = true;
- for (size_type j = 1; j < n; ++j) {
- if (rep->s[t + j] != ptr[j]) {
- equal = false;
- break;
- }
- }
- if (equal) return t;
- }
- } while (t-- > 0);
- return npos;
-}
-
-
-string::size_type string::rfind(value_type const * ptr,
- size_type i) const
-{
- BOOST_ASSERT(ptr); // OURS!
-
- if (!ptr || !*ptr) return npos;
- return rfind(ptr, i, strlen(ptr));
-}
-
-
-string::size_type string::rfind(value_type c, size_type i) const
-{
- TeststringInvariant(this);
-
- size_type const sz = rep->sz;
- if (sz < 1) return npos;
- size_type ii = min(sz - 1, i);
- do {
- if (rep->s[ii] == c) return ii;
- } while (ii-- > 0);
- return npos;
-}
-
-
-string::size_type string::find_first_of(string const & a,
- size_type i) const
-{
- BOOST_ASSERT(i <= rep->sz); // OURS!
- TeststringInvariant(this);
-
- for (size_type t = i; t < rep->sz; ++t) {
- if (a.find(rep->s[t]) != npos) return t;
- }
- return npos;
-}
-
-
-string::size_type string::find_first_of(value_type const * ptr,
- size_type i,
- size_type n) const
-{
- BOOST_ASSERT(ptr && i <= rep->sz); // OURS!
- TeststringInvariant(this);
- if (!n) return npos;
-
- for (size_type t = i; t < rep->sz; ++t) {
- if (memchr(ptr, rep->s[t], n) != 0) return t;
- }
- return npos;
-}
-
-
-string::size_type string::find_first_of(value_type const * ptr,
- size_type i) const
-{
- BOOST_ASSERT(ptr && i <= rep->sz); // OURS!
- TeststringInvariant(this);
-
- for (size_type t = i; t < rep->sz; ++t) {
- if (strchr(ptr, rep->s[t]) != 0) return t;
- }
- return npos;
-}
-
-
-string::size_type string::find_first_of(value_type c, size_type i) const
-{
- BOOST_ASSERT(i <= rep->sz); // OURS!
- TeststringInvariant(this);
-
- for (size_type t = i; t < rep->sz; ++t) {
- if (rep->s[t] == c) return t;
- }
- return npos;
-}
-
-
-string::size_type string::find_last_of(string const & a,
- size_type i) const
-{
- TeststringInvariant(this);
-
- size_type ii = min(rep->sz - 1, i);
- for (int t = ii; t >= 0; --t) {
- if (a.find(rep->s[t]) != npos) return t;
- }
- return npos;
-}
-
-
-string::size_type string::find_last_of(value_type const * ptr,
- size_type i,
- size_type n) const
-{
- BOOST_ASSERT(ptr); // OURS!
- TeststringInvariant(this);
- if (!n) return npos;
-
- size_type ii = min(rep->sz - 1, i);
- for (int t = ii; t >= 0; --t) {
- if (memchr(ptr, rep->s[t], n) != 0) return t;
- }
- return npos;
-}
-
-
-string::size_type string::find_last_of(value_type const * ptr,
- size_type i) const
-{
- BOOST_ASSERT(ptr); // OURS!
- TeststringInvariant(this);
-
- size_type ii = min(rep->sz - 1, i);
- for (int t = ii; t >= 0; --t) {
- if (strchr(ptr, rep->s[t]) != 0) return t;
- }
- return npos;
-}
-
-
-string::size_type string::find_last_of(value_type c, size_type i) const
-{
- TeststringInvariant(this);
-
- if (!rep->sz) return npos;
- size_type ii = min(rep->sz - 1, i);
- for (int t = ii; t >= 0; --t) {
- if (rep->s[t] == c) return t;
- }
- return npos;
-}
-
-
-string::size_type string::find_first_not_of(string const & a,
- size_type i) const
-{
- TeststringInvariant(this);
-
- if (!rep->sz) return npos;
- BOOST_ASSERT(i <= rep->sz);
- for (size_type t = i; t < rep->sz; ++t) {
- if (a.find(rep->s[t]) == npos) return t;
- }
- return npos;
-}
-
-
-string::size_type string::find_first_not_of(value_type const * ptr,
- size_type i,
- size_type n) const
-{
- BOOST_ASSERT(ptr && i <= rep->sz); // OURS!
- TeststringInvariant(this);
-
- if (!n) return (i < rep->sz) ? i : npos;
- for (size_type t = i; t < rep->sz; ++t) {
- if (memchr(ptr, rep->s[t], n) == 0) return t;
- }
- return npos;
-}
-
-
-string::size_type string::find_first_not_of(value_type const * ptr,
- size_type i) const
-{
- BOOST_ASSERT(ptr && i <= rep->sz); // OURS!
- TeststringInvariant(this);
-
- for (size_type t = i; t < rep->sz; ++t) {
- if (strchr(ptr, rep->s[t]) == 0) return t;
- }
- return npos;
-}
-
-
-string::size_type string::find_first_not_of(value_type c,
- size_type i) const
-{
- if (!rep->sz) return npos;
- BOOST_ASSERT(i <= rep->sz); // OURS!
- TeststringInvariant(this);
-
- for (size_type t = i; t < rep->sz; ++t) {
- if (rep->s[t] != c) return t;
- }
- return npos;
-}
-
-
-string::size_type string::find_last_not_of(string const & a,
- size_type i) const
-{
- TeststringInvariant(this);
-
- size_type ii = min(rep->sz - 1, i);
- for (int t = ii; t >= 0; --t) {
- if (a.find(rep->s[t]) == npos) return t;
- }
- return npos;
-}
-
-
-string::size_type string::find_last_not_of(value_type const * ptr,
- size_type i,
- size_type n) const
-{
- BOOST_ASSERT(ptr); // OURS!
- TeststringInvariant(this);
-
- if (!n) return npos;
- size_type ii = min(rep->sz - 1, i);
-
- for (int t = ii; t >= 0; --t) {
- if (memchr(ptr, rep->s[t], n) == 0) return t;
- }
- return npos;
-}
-
-
-string::size_type string::find_last_not_of(value_type const * ptr,
- size_type i) const
-{
- BOOST_ASSERT(ptr); // OURS!
- TeststringInvariant(this);
-
- size_type ii = min(rep->sz - 1, i);
- for (int t = ii; t >= 0; --t) {
- if (strchr(ptr, rep->s[t]) == 0) return t;
- }
- return npos;
-}
-
-
-string::size_type string::find_last_not_of(value_type c,
- size_type i) const
-{
- TeststringInvariant(this);
-
- size_type ii = min(rep->sz - 1, i);
- for (int t = ii; t >= 0; --t) {
- if (rep->s[t] != c) return t;
- }
- return npos;
-}
-
-
-/////////////////
-// Replace
-/////////////////
-
-string & string::replace(size_type i, size_type n, string const & x)
-{
- BOOST_ASSERT(i <= rep->sz); // OURS!
- TeststringInvariant(this);
-
- return replace(i, n, x, 0, x.rep->sz);
-}
-
-
-string & string::replace(size_type i, size_type n, string const & x,
- size_type i2, size_type n2)
-{
- BOOST_ASSERT(i <= rep->sz && i2 <= x.rep->sz); // STD!
- TeststringInvariant(this);
-
- rep = rep->get_own_copy();
- rep->replace(i, min(n, rep->sz), &(x.rep->s[i2]), min(n2, x.rep->sz));
- return *this;
-}
-
-
-string & string::replace(size_type i, size_type n,
- value_type const * p, size_type n2)
-{
- BOOST_ASSERT(p && i <= rep->sz); // OURS!
- TeststringInvariant(this);
-
- rep = rep->get_own_copy();
- rep->replace(i, min(n, rep->sz), p, min(n2, strlen(p)));
- return *this;
-}
-
-
-string & string::replace(size_type i, size_type n, value_type const * p)
-{
- BOOST_ASSERT(p && i <= rep->sz); // OURS!
- TeststringInvariant(this);
-
- return replace(i, min(n, rep->sz), p, (!p) ? 0 : strlen(p));
-}
-
-
-string & string::replace(size_type i, size_type n,
- size_type n2, value_type c)
-{
- BOOST_ASSERT(i <= rep->sz); // OURS!
- TeststringInvariant(this);
-
- rep = rep->get_own_copy();
- value_type * tmp = new value_type[n2];
- memset(tmp, c, n2);
- rep->replace(i, min(n, rep->sz), tmp, n2);
- delete[] tmp;
- return *this;
-}
-
-
-/// FY! FY! FY! go away !
-string & string::replace(size_type i, size_type n, value_type c)
-{
- return replace(i, n, 1, c);
-}
-
-
-string & string::replace(iterator i, iterator i2, const string & str)
-{
- TeststringInvariant(this);
-
- return replace(i - begin(), i2 - i, str);
-}
-
-
-string & string::replace(iterator i, iterator i2,
- value_type const * p, size_type n)
-{
- BOOST_ASSERT(p); // OURS!
- TeststringInvariant(this);
-
- return replace(i - begin(), i2 - i, p, n);
-}
-
-
-string & string::replace(iterator i, iterator i2, value_type const * p)
-{
- BOOST_ASSERT(p); // OURS!
- TeststringInvariant(this);
-
- return replace(i - begin(), i2 - i, p);
-}
-
-
-string & string::replace(iterator i, iterator i2,
- size_type n , value_type c)
-{
- TeststringInvariant(this);
-
- return replace(i - begin(), i2 - i, n, c);
-}
-
-
-string & string::replace(iterator i, iterator i2,
- iterator j, iterator j2)
-{
- TeststringInvariant(this);
-
- return replace(i - begin(), i2 - i, j, j2 - j);
-}
-
-
-void string::swap(string & str)
-{
- if (rep == str.rep) return;
- Srep * tmp = str.rep;
- str.rep = rep;
- rep = tmp;
-}
-
-
-string & string::erase(size_type i, size_type n)
-{
- BOOST_ASSERT(i <= rep->sz); // STD!
- TeststringInvariant(this);
-
- rep = rep->get_own_copy();
- if (i == 0 && n >= rep->sz) {
- rep->sz = 0;
- } else {
- n = min(n, rep->sz - i);
- memmove(&(rep->s[i]), &(rep->s[i + n]), rep->sz - i - n);
- rep->sz -= n;
- }
- return *this;
-}
-
-
-string::iterator string::erase(iterator i)
-{
- TeststringInvariant(this);
-
- // what iterator is this supposed to return?
- // the iterator after the one erased
- erase(i - begin(), 1);
- return begin(); // BUG
-}
-
-
-string::iterator string::erase(iterator first, iterator last)
-{
- TeststringInvariant(this);
-
- erase(first - begin(), last - first);
- return begin(); // BUG
-}
-
-
-/////////////////////////////////////
-// Conversion to C-style Strings
-/////////////////////////////////////
-
-string::value_type const * string::c_str() const
-{
- rep->s[length()] = '\0';
- return rep->s;
-}
-
-
-string::value_type const * string::data() const
-{
- return rep->s;
-}
-
-
-string::size_type string::copy(value_type * buf, size_type len,
- size_type pos) const
-{
- BOOST_ASSERT(buf); // OURS!
- BOOST_ASSERT(pos <= rep->sz); // STD!
- TeststringInvariant(this);
-
- register int nn = min(len, length() - pos);
- memcpy(buf, &(rep->s[pos]), nn);
- return nn;
-}
-
-
-////////////////////
-// Comparisons
-////////////////////
-
-// Compare funcs should be verified.
-
-int string::internal_compare(size_type pos, size_type n,
- value_type const * s,
- size_type slen, size_type n2) const
-{
- if ((rep->sz == 0 || n == 0) && (!*s || n2 == 0)) return 0;
- if (!*s) return 1;
- // since n > n2, min(n, n2) == 0, c == 0 (stops segfault also)
-
- // remember that n can very well be a lot larger than rep->sz
- // so we have to ensure that n is no larger than rep->sz
- n = min(n, rep->sz);
- n2 = min(n2, slen);
- if (n == n2)
- return memcmp(&(rep->s[pos]), s, n);
- int c = memcmp(&(rep->s[pos]), s, min(n, n2));
- if (c)
- return c;
- if (n < n2)
- return -1;
- return 1;
-}
-
-
-int string::compare(string const & str) const
-{
- TeststringInvariant(this);
- return internal_compare(0, rep->sz, str.rep->s,
- str.rep->sz, str.rep->sz);
-}
-
-
-int string::compare(value_type const * s) const
-{
- BOOST_ASSERT(s); //OURS!
- TeststringInvariant(this);
- int n = (!s) ? 0 : strlen(s);
- return internal_compare(0, rep->sz, s, n, n);
-}
-
-
-int string::compare(size_type pos, size_type n,
- string const & str) const
-{
- BOOST_ASSERT(pos <= rep->sz); // OURS!
- TeststringInvariant(this);
- return internal_compare(pos, n, str.rep->s, str.rep->sz, str.rep->sz);
-}
-
-
-int string::compare(size_type pos, size_type n, string const & str,
- size_type pos2, size_type n2) const
-{
- BOOST_ASSERT(pos <= rep->sz); // OURS!
- BOOST_ASSERT(pos2 <= str.rep->sz); // OURS!
- TeststringInvariant(this);
- return internal_compare(pos, n,
- str.rep->s + pos2,
- str.rep->sz - pos2, n2);
-}
-
-
-int string::compare(size_type pos, size_type n, value_type const * s,
- size_type n2) const
-{
- BOOST_ASSERT(s && pos <= rep->sz); // OURS!
- TeststringInvariant(this);
- return internal_compare(pos, n, s, (!s) ? 0 : strlen(s), n2);
-}
-
-
-/////////////////
-// Substrings
-/////////////////
-
-// i = index, n = length
-string string::substr(size_type i, size_type n) const
-{
- BOOST_ASSERT(i <= rep->sz); // STD!
- TeststringInvariant(this);
-
- return string(*this, i, n);
-}
-
-
-/////////////////////////////////////////////
-// String operators, non member functions
-/////////////////////////////////////////////
-
-bool operator==(string const & a, string const & b)
-{
- return a.compare(b) == 0;
-}
-
-
-bool operator==(string::value_type const * a, string const & b)
-{
- BOOST_ASSERT(a); // OURS!
- return b.compare(a) == 0;
-}
-
-
-bool operator==(string const & a, string::value_type const * b)
-{
- BOOST_ASSERT(b); // OURS!
- return a.compare(b) == 0;
-}
-
-
-bool operator!=(string const & a, string const & b)
-{
- return a.compare(b) != 0;
-}
-
-
-bool operator!=(string::value_type const * a, string const & b)
-{
- BOOST_ASSERT(a); // OURS!
- return b.compare(a) != 0;
-}
-
-
-bool operator!=(string const & a, string::value_type const * b)
-{
- BOOST_ASSERT(b); // OURS!
- return a.compare(b) != 0;
-}
-
-
-bool operator>(string const & a, string const & b)
-{
- return a.compare(b) > 0;
-}
-
-
-bool operator>(string::value_type const * a, string const & b)
-{
- BOOST_ASSERT(a); // OURS!
- return b.compare(a) < 0; // since we reverse the parameters
-}
-
-
-bool operator>(string const & a, string::value_type const * b)
-{
- BOOST_ASSERT(b); // OURS!
- return a.compare(b) > 0;
-}
-
-
-bool operator<(string const & a, string const & b)
-{
- return a.compare(b) < 0;
-}
-
-
-bool operator<(string::value_type const * a, string const & b)
-{
- BOOST_ASSERT(a); // OURS!
- return b.compare(a) > 0; // since we reverse the parameters
-}
-
-
-bool operator<(string const & a, string::value_type const * b)
-{
- BOOST_ASSERT(b); // OURS!
- return a.compare(b) < 0;
-}
-
-
-bool operator>=(string const & a, string const & b)
-{
- return a.compare(b) >= 0;
-}
-
-
-bool operator>=(string::value_type const * a, string const & b)
-{
- BOOST_ASSERT(a); // OURS!
- return b.compare(a) <= 0; // since we reverse the parameters
-}
-
-
-bool operator>=(string const & a, string::value_type const * b)
-{
- BOOST_ASSERT(b); // OURS!
- return a.compare(b) >= 0;
-}
-
-
-bool operator<=(string const & a, string const & b)
-{
- return a.compare(b) <= 0;
-}
-
-
-bool operator<=(string::value_type const * a, string const & b)
-{
- BOOST_ASSERT(a); // OURS!
- return b.compare(a) >= 0; // since we reverse the parameters
-}
-
-
-bool operator<=(string const & a, string::value_type const * b)
-{
- BOOST_ASSERT(b); // OURS!
- return a.compare(b) <= 0;
-}
-
-
-string operator+(string const & a, string const & b)
-{
- string tmp(a);
- tmp += b;
- return tmp;
-}
-
-
-string operator+(string::value_type const * a, string const & b)
-{
- BOOST_ASSERT(a); // OURS!
- string tmp(a);
- tmp += b;
- return tmp;
-}
-
-
-string operator+(string::value_type a, string const & b)
-{
- string tmp;
- tmp += a;
- tmp += b;
- return tmp;
-}
-
-
-string operator+(string const & a, string::value_type const * b)
-{
- BOOST_ASSERT(b); // OURS!
- string tmp(a);
- tmp += b;
- return tmp;
-}
-
-
-string operator+(string const & a, string::value_type b)
-{
- string tmp(a);
- tmp += b;
- return tmp;
-}
-
-
-void swap(string & str1, string & str2)
-{
- str1.swap(str2);
-}
-
-
-istream & operator>>(istream & is, string & s)
-{
-#if 0
- // very bad solution
- char * nome = new char[1024];
- is >> nome;
- string tmp(nome);
- delete [] nome;
- if (!tmp.empty()) s = tmp;
-#else
- // better solution
- int w = is.width(0);
- s.clear();
- char c = 0;
- bool skipspace = true;
- while (is.get(c)) {
- if (isspace(c)) {
- if (!skipspace) {
- is.putback(c);
- break;
- }
- } else {
- s += c;
- skipspace = false;
- }
- if (--w == 1) break;
- }
- if (s.empty()) is.setstate(std::ios::failbit);
-#endif
- return is;
-}
-
-
-ostream & operator<<(ostream & o, string const & s)
-{
- return o.write(s.data(), s.length());
-}
-
-
-istream & getline(istream & is, string & s,
- string::value_type delim)
-{
- // very bad solution
- char tmp = 0;
- s.erase();
- while (is) {
- is.get(tmp);
- if (tmp != delim) {
- s += tmp;
- } else {
- break;
- }
- }
- return is;
-}
-
-} // namespace lyx
-
-#ifdef TEST_MAIN
-int main() {
- lyx::string a = "abcac";
- cout << a.rfind("ab") << endl;
- cout << a.rfind("c") << endl;
- cout << a.rfind("d") << endl;
-}
-#endif
+++ /dev/null
-// -*- C++ -*-
-/**
- * \file lyxstring.h
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Lars Gullik Bjønnes
- *
- * Full author contact details are available in file CREDITS.
- */
-
-// 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
-
-#include <iosfwd>
-
-#if 0
-#include <iterator>
-#endif
-
-#include <cstring> // for size_t
-
-namespace lyx {
-
-/** 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 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 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 lyxstring as a parameter, use
-
- #void foo(lyxstring par = lyxstring()); // Correct#
-
- rather than
-
- #void foo(lyxstring par = ""); // WRONG!#
- #void foo(lyxstring 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 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.empty()) something right#
-
- rather than something along the lines of
-
- #if (!foo) completely wrong#
-
-When you want to copy an lyxstring, just do
-
- #lyxstring a, b = "String";#
- #a = b; // That's it!#
-
- not something like
-
- #lyxstring a, b = "String";#
- #a = b.copy(); // This leaks. // and does not work either. #
-
- The class automatically handles deep copying when required.
-*/
-class string {
-public:
- /* Typedefs */
-
- ///
- typedef char value_type;
-
- ///
- typedef value_type * pointer;
-
- ///
- typedef value_type & reference;
-
- ///
- typedef value_type const & const_reference;
-
- ///
- typedef size_t size_type;
-
- ///
- typedef int difference_type;
-
- ///
- typedef value_type * iterator;
- ///
- typedef const value_type * const_iterator;
-#if 0
- ///
- typedef reverse_iterator<iterator, value_type, reference>
- reverse_iterator;
- ///
- typedef reverse_iterator<const_iterator, const value_type,
- const_reference> const_reverse_iterator;
-
-#endif
-
- ///
- iterator begin();
- ///
- const_iterator begin() const;
- ///
- iterator end();
- ///
- const_iterator end() const;
-#if 0
- ///
- reverse_iterator rbegin();
- ///
- const_reverse_iterator rbegin() const;
- ///
- reverse_iterator rend();
- ///
- const_reverse_iterator rend() const;
-#endif
- /* 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;
-
- /// #string x;#
- string();
-
- /// #string x(string ...)#
- string(string const &, size_type pos = 0, size_type n = npos);
-
- /// #string x("abc", 2) -> "ab"#
- string(value_type const *, size_type n);
-
- // #string x("abc")#
- string(value_type const *);
-
- /// string(5, 'n') -> "nnnnn"
- string(size_type n, value_type c);
-
-#if 0
- ///
- string(const_iterator first, const_iterator last);
-#else
- ///
- template<class InputIterator>
- string(InputIterator begin, InputIterator end) {
- while (begin != end) {
- push_back(*begin);
- ++begin;
- }
- }
-#endif
- ///
- ~string();
-
- /// number of characters
- size_type size() const;
-
- /// largest possible string
- size_type max_size() const { return npos - 1; }
-
- ///
- size_type length() const { return size(); }
-
- ///
- bool empty() const { return size() == 0; }
-
- ///
- void resize(size_type n, value_type c);
-
- ///
- void resize(size_type n) { resize(n, ' '); }
-
- /// size of the memory (in number of elements) allocated.
- size_type capacity() const;
-
- ///
- void reserve(size_type res_arg = 0);
-
- ///
- string & operator=(string const &);
-
- ///
- string & operator=(value_type const *);
-
- ///
- string & operator=(value_type);
-
- ///
- string & assign(string const &);
-
- ///
- string & assign(string const &, size_type pos, size_type n);
-
- ///
- string & assign(value_type const * p, size_type n);
-
- ///
- string & assign(value_type const * p);
-
- ///
- string & assign(size_type n, value_type c);
-
-#if 1
- ///
- string & assign(const_iterator first, const_iterator last);
-#else
- ///
- template<class InputIterator>
- string & assign(InputIterator begin, InputIterator end) {
- clear;
- while (begin != end) {
- push_back((*begin));
- ++begin;
- }
- }
-#endif
-
- /// unchecked access
- const_reference operator[](size_type) const;
-
- /// unchecked access
- reference operator[](size_type);
-
- /// checked access
- const_reference at(size_type) const;
-
- /// checked access
- reference at(size_type);
-
- // add characters after (*this)[length()-1]:
-
- ///
- string & operator+=(string const &);
-
- ///
- string & operator+=(value_type const *);
-
- ///
- string & operator+=(value_type);
-
- ///
- void push_back(value_type);
-
- ///
- string & append(string const &);
-
- ///
- string & append(string const &, size_type pos, size_type n);
-
- ///
- string & append(value_type const *, size_type n);
-
- ///
- string & append(value_type const *);
-
- ///
- string & append(size_type n, value_type);
-
-#if 1
- ///
- string & append(iterator first, iterator last);
-#else
- ///
- template<class InputIterator>
- string & append(InputIterator begin, InputIterator end) {
- while (begin != end) {
- push_back((*begin));
- ++begin;
- }
- return *this;
- }
-#endif
- // insert characters before (*this)[pos]:
-
- ///
- string & insert(size_type pos, string const &);
-
- ///
- string & insert(size_type pos, string const &,
- size_type pos2, size_type n);
-
- ///
- string & insert(size_type pos, value_type const * p,
- size_type n);
-
- ///
- string & insert(size_type pos, value_type const * p);
-
- ///
- string & insert(size_type pos, size_type n, value_type c);
-
- // insert characters before p
-
- ///
- iterator insert(iterator p, value_type c);
-
- ///
- 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
-
- ///
- size_type find(string const &, size_type i = 0) const;
-
- ///
- size_type find(value_type const * p,
- size_type i, size_type n) const;
-
- ///
- size_type find(value_type const * p, size_type i = 0) const;
-
- ///
- size_type find(value_type c, size_type i = 0) const;
-
- ///
- size_type rfind(string const &, size_type i = npos) const;
-
- ///
- size_type rfind(value_type const * p, size_type i, size_type n) const;
-
- ///
- size_type rfind(value_type const * p, size_type i = npos) const;
-
- ///
- size_type rfind(value_type c, size_type i = npos) const;
-
- ///
- size_type find_first_of(string 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 = 0) const;
-
- ///
- size_type find_first_of(value_type c, size_type i = 0) const;
-
- ///
- size_type find_last_of(string 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 = npos) const;
-
- ///
- size_type find_last_of(value_type c, size_type i = npos) const;
-
- ///
- size_type find_first_not_of(string const &, size_type i = 0) const;
-
- ///
- size_type find_first_not_of(value_type const * p, size_type i,
- 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 c, size_type i = 0) const;
-
- ///
- size_type find_last_not_of(string 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 c, size_type i = npos) const;
-
- // replace [(*this)[i], (*this)[i+n]] with other characters:
-
- ///
- string & replace(size_type i, size_type n, string const & str);
-
- ///
- string & replace(size_type i, size_type n, string const & s,
- size_type i2, size_type n2);
-
- ///
- string & replace(size_type i, size_type n, value_type const * p,
- size_type n2);
-
- ///
- string & replace(size_type i, size_type n, value_type const * p);
-
- ///
- string & replace(size_type i, size_type n,
- size_type n2, value_type c);
-
- /// FY! FY! FY! go away !
- string & replace(size_type i, size_type n,
- value_type c);
-
- ///
- string & replace(iterator i, iterator i2, const string & str);
-
- ///
- string & replace(iterator i, iterator i2,
- value_type const * p, size_type n);
-
- ///
- string & replace(iterator i, iterator i2, value_type const * p);
-
- ///
- string & replace(iterator i, iterator i2,
- size_type n , value_type c);
-
- ///
- string & replace(iterator i, iterator i2, iterator j, iterator j2);
-
- ///
- void swap(string & str);
-
- /// Erase n chars from position i.
- string & erase(size_type i = 0, size_type n = npos);
-
- ///
- string & clear() {
- return erase(0, npos);
- }
-
- ///
- iterator erase(iterator i);
-
- ///
- iterator erase(iterator first, iterator last);
-
- ///
- value_type const * c_str() const;
-
- /* 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'
- The caller must provide a buffer with engough room.
- */
- size_type copy(value_type * buf, size_type len,
- size_type pos = 0) const;
-
-
- ///
- int compare(string const & str) const;
-
- ///
- int compare(value_type const * p) const;
-
- ///
- int compare(size_type pos, size_type n, string const & str) const;
-
- ///
- int compare(size_type pos, size_type n, string const & str,
- size_type pos2, size_type n2) const;
-
- ///
- int compare(size_type pos, size_type n, value_type const * p,
- size_type n2 = npos) const;
-
-
- ///
- string substr(size_type i = 0, size_type n = npos) const;
-
-private:
- // 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.
- //
- //string & operator+(int);
- //
- //string & operator=(int);
- //
- //string & 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;
-
- /// 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 string
- 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.
- */
-
-#ifdef ENABLE_ASSERTIONS
- /// lyxstringInvariant is used to test the lyxstring Invariant
- friend class stringInvariant;
-#endif
-};
-
-// The usual comparison operators ==, !=, >, <, >=, <= are
-// provided for lyxstrings
-
-bool operator==(string const &, string const &);
-bool operator==(string::value_type const *, string const &);
-bool operator==(string const &, string::value_type const *);
-
-
-bool operator!=(string const &, string const &);
-bool operator!=(string::value_type const *, string const &);
-bool operator!=(string const &, string::value_type const *);
-
-
-bool operator>(string const &, string const &);
-bool operator>(string::value_type const *, string const &);
-bool operator>(string const &, string::value_type const *);
-
-
-bool operator<(string const &, string const &);
-bool operator<(string::value_type const *, string const &);
-bool operator<(string const &, string::value_type const *);
-
-
-bool operator>=(string const &, string const &);
-bool operator>=(string::value_type const *, string const &);
-bool operator>=(string const &, string::value_type const *);
-
-
-bool operator<=(string const &, string const &);
-bool operator<=(string::value_type const *, string const &);
-bool operator<=(string const &, string::value_type const *);
-
-
-// Concatenation
-
-string operator+(string const & a, string const & b);
-string operator+(char const * a, string const & b);
-string operator+(string::value_type a, string const & b);
-string operator+(string const & a, string::value_type const * b);
-string operator+(string const & a, string::value_type b);
-
-void swap(string & s1, string & s2);
-
-std::istream & operator>>(std::istream &, string &);
-std::ostream & operator<<(std::ostream &, string const &);
-std::istream & getline(std::istream &, string &, string::value_type delim = '\n');
-
-} // namespace lyx
-
-#endif