1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright (C) 1995 Matthias Ettrich
7 * Copyright (C) 1995-1999 The LyX Team.
9 * ======================================================*/
16 #pragma implementation "lyxstring.h"
19 #include "lyxstring.h"
26 // Reference count has been checked, empty_rep removed and
27 // introduced again in a similar guise. Where is empty_rep _really_
30 // Insertion and replace is implemented, as far as I can see everything
31 // works, but could perhaps be done smarter.
33 // All the different find functions need a good look over.
34 // I have so far not tested them extensively and would be
35 // happy if others took the time to have a peek.
38 #warning temporarily here for debugging purposes only
40 lyxstring::size_type lyxstring::size() const
46 //--------------------------------------------------------------------------
50 /** Testing of the lyxstring invariant
51 * By creating an object that tests the lyxstring invariant during its
52 * construction *and* its deconstruction we greatly simplify our code.
53 * Calling TestlyxstringInvariant() upon entry to an lyxstring method
54 * will test the invariant upon entry to the code. If the Asserts fail
55 * then we know from the stack trace that the corruption occurred *before*
56 * entry to this method. We can also be sure it didn't happen in any of
57 * the tested lyxstring methods. It is therefore likely to be due to some
58 * other external force.
59 * Several lyxstring methods have multiple exit points which would otherwise
60 * require us to insert a separate test before each return. But since we
61 * created an object its destructor will be called upon exit (any exit!).
62 * We thus get testing at both start and end of a method with one line of
63 * code at the head of a method. More importantly, we get good testing
64 * everytime we run the code.
65 * NOTE: just because we test the invariant doesn't mean we can forget
66 * about testing pre and post conditions specific to any given method.
67 * This test simply proves that the lyxstring/Srep is in a valid state it
68 * does *not* prove that the method did what it was supposed to.
70 class lyxstringInvariant
73 lyxstringInvariant(lyxstring const *);
74 ~lyxstringInvariant();
77 lyxstring const * object;
80 // To test if this scheme works "as advertised" uncomment the printf's in
81 // the constructor and destructor below and then uncomment the printf and the
82 // call to TestlyxstringInvariant() in lyxstring::operator=(char const *).
83 // The correct output when LyX has been recompiled and run is:
84 // lyxstringInvariant constructor
85 // lyxstring::operator=(char const *)
86 // lyxstringInvariant constructor
87 // lyxstringInvariant destructor completed
88 // lyxstringInvariant destructor completed
89 // NOTE: The easiest way to catch this snippet of the output is to wait for
90 // the splash screen to disappear and then open and close Help->Credits
92 lyxstringInvariant::lyxstringInvariant(lyxstring const * ls) : object(ls)
94 // printf("lyxstringInvariant constructor\n");
98 lyxstringInvariant::~lyxstringInvariant()
101 // printf("lyxstringInvariant destructor completed\n");
104 void lyxstringInvariant::helper() const
106 // Some of these tests might look pointless but they are
107 // all part of the invariant and if we want to make sure
108 // we have a bullet proof implementation then we need to
109 // test every last little thing we *know* should be true.
110 // I may have missed a test or two, so feel free to fill
111 // in the gaps. ARRae.
112 // NOTE: Don't put TestlyxstringInvariant() in any of the
113 // lyxstring methods used below otherwise you'll get an
114 // infinite recursion and a crash.
117 Assert(object->rep->s); // s is never 0
118 Assert(object->rep->res); // always some space allocated
119 Assert(object->size() <= object->rep->res);
120 Assert(object->rep->ref >= 1); // its in use so it must be referenced
121 Assert(object->rep->ref < (1 << 8*sizeof(lyxstring::Srep::ref)) - 1);
122 // if it does ever == then we should be generating a new copy
123 // and starting again. (Is char always 8-bits?)
125 #define TestlyxstringInvariant(s) lyxstringInvariant lyxstring_invariant(s);
127 #define TestlyxstringInvariant(s)
128 #endif //DEVEL_VERSION
129 //-------------------------------------------------------------------------
131 ///////////////////////////////////////
132 // Constructors and Deconstructors.
133 ///////////////////////////////////////
136 lyxstring::Srep::Srep(lyxstring::size_type nsz, const value_type * p)
138 // can be called with p==0 by lyxstring::assign(const value_type *, size_type)
143 s = new value_type[res + 1]; // add space for terminator
145 // if sz = 0 nothing gets copied and we have an error
148 // possibly allows for large but empty string
149 sz = 0; // this line should be redundant
155 lyxstring::Srep::Srep(lyxstring::size_type nsz, value_type ch)
160 s = new value_type[res + 1]; // add space for terminator
163 // if ch == '\0' strlen(lyxstring.c_str()) == 0 so sz = 0
164 // allows for large but empty string
170 void lyxstring::Srep::assign(lyxstring::size_type nsz, const value_type * p)
172 // can be called with p==0 by lyxstring::assign(const value_type *, size_type)
178 s = new value_type[res + 1]; // add space for terminator
183 // if sz = 0 nothing gets copied and we have an error
187 sz = 0; // this line should be redundant
193 void lyxstring::Srep::assign(lyxstring::size_type nsz, value_type ch)
199 s = new value_type[res + 1]; // add space for terminator
203 // if ch == '\0' strlen(lyxstring.c_str()) == 0 so sz = 0
204 // allows for a large empty string
210 void lyxstring::Srep::append(lyxstring::size_type asz, const value_type * p)
212 register unsigned int const len = sz + asz;
215 value_type * tmp = new value_type[res + 1];
217 memcpy(tmp + sz, p, asz);
222 memcpy(s + sz, p, asz);
228 void lyxstring::Srep::push_back(value_type c)
230 s[sz] = c; // it is always room to put a value_type at the end
234 value_type * tmp = new value_type[res + 1];
242 void lyxstring::Srep::insert(lyxstring::size_type pos, const value_type * p,
243 lyxstring::size_type n)
248 value_type * tmp = new value_type[res + 1];
250 memcpy(tmp + pos, p, n);
251 memcpy(tmp + pos + n, & s[pos], sz - pos);
256 memmove(s + pos + n, & s[pos], sz - pos);
257 memcpy(s + pos, p, n);
263 void lyxstring::Srep::resize(size_type n, value_type c)
266 // This resets sz to res_arg
267 res = min(n, npos - 2); // We keep no xtra when we resize
268 value_type * tmp = new value_type[res + 1];
269 memcpy(tmp, s, min(sz, res));
271 memset(tmp + sz, c, res - sz);
278 void lyxstring::Srep::reserve(lyxstring::size_type res_arg)
280 // This keeps the old sz, but
281 // increases res with res_arg
283 value_type * tmp = new value_type[res + 1];
290 void lyxstring::Srep::replace(lyxstring::size_type i, lyxstring::size_type n,
291 value_type const * p, size_type n2)
293 // can be called with p=0 and n2=0
294 Assert(i < sz && ((!p && !n2) || p));
297 if (res >= n2 + sz) {
298 memmove(s + i + n2, &s[i + n], sz - i);
299 memcpy(s + i, p, n2);
302 res = sz + n2 + xtra;
303 value_type * tmp = new value_type[res + 1];
305 memcpy(tmp + i, p, n2);
306 memcpy(tmp + i + n2, &s[i + n], sz - i);
314 lyxstring::size_type const lyxstring::npos = static_cast<lyxstring::size_type>(-1);
316 lyxstring::lyxstring()
318 static Srep empty_rep(0, "");
324 lyxstring::lyxstring(lyxstring const & x, size_type pos, size_type n)
326 Assert(pos < x.rep->sz || pos == 0);
327 if (pos == 0 && n >= x.length()) { // this is the default
331 rep = new Srep(min(n, x.rep->sz - pos), &(x.rep->s[pos]));
336 lyxstring::lyxstring(value_type const * s, size_type n)
338 Assert(s); // we don't allow null pointers
339 static Srep empty_rep(0, "");
340 if (*s && n) { // s is not empty string and n > 0
341 rep = new Srep(min(strlen(s), n), s);
349 lyxstring::lyxstring(value_type const * s)
351 Assert(s); // we don't allow null pointers
352 static Srep empty_rep(0, "");
353 if (*s) { // s is not empty string
354 rep = new Srep(strlen(s), s);
362 lyxstring::lyxstring(size_type n, value_type c)
364 rep = new Srep(n, c);
368 lyxstring::lyxstring(iterator first, iterator last)
370 rep = new Srep(last - first, first);
374 ///////////////////////
376 ///////////////////////
378 lyxstring::iterator lyxstring::begin()
384 lyxstring::const_iterator lyxstring::begin() const
390 lyxstring::iterator lyxstring::end()
392 return rep->s + rep->sz;
396 lyxstring::const_iterator lyxstring::end() const
398 return rep->s + rep->sz;
402 reverse_iterator lyxstring::rbegin()
404 return reverse_iterator( end() );
408 const_reverse_iterator lyxstring::rbegin() const
410 return const_reverse_iterator( end() );
414 reverse_iterator lyxstring::rend()
416 return reverse_iterator( begin() );
420 const_reverse_iterator lyxstring::rend() const
422 return const_reverse_iterator( begin() );
426 ///////////////////////
428 ///////////////////////
430 void lyxstring::resize(size_type n, value_type c)
432 TestlyxstringInvariant(this);
434 // This resets sz to res_arg
435 rep = rep->get_own_copy();
440 lyxstring::size_type lyxstring::capacity() const
446 void lyxstring::reserve(size_type res_arg)
448 TestlyxstringInvariant(this);
450 rep = rep->get_own_copy();
451 rep->reserve(res_arg);
459 lyxstring & lyxstring::operator=(lyxstring const & x)
461 TestlyxstringInvariant(this);
467 lyxstring & lyxstring::operator=(value_type const * s)
470 TestlyxstringInvariant(this);
471 // printf("lyxstring::operator=(value_type const *)\n");
477 lyxstring & lyxstring::operator=(value_type c)
479 TestlyxstringInvariant(this);
483 if (rep->ref == 1) // recycle rep
487 rep = new Srep(1, s);
493 lyxstring & lyxstring::assign(lyxstring const & x)
495 TestlyxstringInvariant(this);
497 x.rep->ref++; // protect against ``st = st''
498 if (--rep->ref == 0) delete rep;
499 rep = x.rep; // share representation
504 lyxstring & lyxstring::assign(lyxstring const & x, size_type pos, size_type n)
506 TestlyxstringInvariant(this);
508 return assign(x.substr(pos, n));
512 lyxstring & lyxstring::assign(value_type const * s, size_type n)
515 TestlyxstringInvariant(this);
517 n = min(strlen(s), n);
518 if (rep->ref == 1) // recycle rep
522 rep = new Srep(n, s);
528 lyxstring & lyxstring::assign(value_type const * s)
531 TestlyxstringInvariant(this);
533 return assign(s, strlen(s));
537 lyxstring & lyxstring::assign(size_type n, value_type ch)
539 TestlyxstringInvariant(this);
541 rep = rep->get_own_copy();
547 lyxstring & lyxstring::assign(iterator first, iterator last)
549 TestlyxstringInvariant(this);
551 rep = rep->get_own_copy();
552 rep->assign(last - first, first);
561 lyxstring::const_reference lyxstring::operator[](size_type pos) const
563 Assert(pos < rep->sz);
569 lyxstring::reference lyxstring::operator[](size_type pos)
571 Assert(pos < rep->sz);
572 TestlyxstringInvariant(this);
574 rep = rep->get_own_copy();
579 lyxstring::const_reference lyxstring::at(size_type n) const
587 lyxstring::reference lyxstring::at(size_type n)
590 TestlyxstringInvariant(this);
592 rep = rep->get_own_copy();
601 lyxstring & lyxstring::operator+=(lyxstring const & x)
603 TestlyxstringInvariant(this);
609 lyxstring & lyxstring::operator+=(value_type const * x)
612 TestlyxstringInvariant(this);
618 lyxstring & lyxstring::operator+=(value_type c)
620 TestlyxstringInvariant(this);
627 void lyxstring::push_back(value_type c)
629 TestlyxstringInvariant(this);
631 rep = rep->get_own_copy();
636 lyxstring & lyxstring::append(lyxstring const & x)
638 TestlyxstringInvariant(this);
640 if (x.empty()) return *this;
641 rep = rep->get_own_copy();
642 rep->append(x.length(), x.rep->s);
647 lyxstring & lyxstring::append(lyxstring const & x, size_type pos, size_type n)
649 TestlyxstringInvariant(this);
651 return append(x.substr(pos, n));
655 lyxstring & lyxstring::append(value_type const * p, size_type n)
658 TestlyxstringInvariant(this);
660 if (!*p || !n) return *this;
661 rep = rep->get_own_copy();
662 rep->append(min(n, strlen(p)), p);
667 lyxstring & lyxstring::append(value_type const * p)
670 TestlyxstringInvariant(this);
672 if (!*p) return *this;
673 rep = rep->get_own_copy();
674 rep->append(strlen(p), p);
679 lyxstring & lyxstring::append(size_type n, value_type c)
681 TestlyxstringInvariant(this);
683 value_type * tmp = new value_type[n];
685 rep = rep->get_own_copy();
692 lyxstring & lyxstring::append(iterator first, iterator last)
694 TestlyxstringInvariant(this);
696 rep = rep->get_own_copy();
697 rep->append(last - first, first);
701 // insert value_typeacters before (*this)[pos]
703 lyxstring & lyxstring::insert(size_type pos, lyxstring const & x)
705 TestlyxstringInvariant(this);
707 return insert(pos, x, 0, x.rep->sz);
711 lyxstring & lyxstring::insert(size_type pos, lyxstring const & x,
712 size_type pos2, size_type n)
714 TestlyxstringInvariant(this);
716 rep = rep->get_own_copy();
717 rep->insert(pos, &(x.rep->s[pos2]), min(n, x.rep->sz));
722 lyxstring & lyxstring::insert(size_type pos, value_type const * p, size_type n)
725 TestlyxstringInvariant(this);
728 // insert nothing and you change nothing
729 rep = rep->get_own_copy();
730 rep->insert(pos, p, min(n, strlen(p)));
736 lyxstring & lyxstring::insert(size_type pos, value_type const * p)
739 TestlyxstringInvariant(this);
742 // insert nothing and you change nothing
743 rep = rep->get_own_copy();
744 rep->insert(pos, p, strlen(p));
750 lyxstring & lyxstring::insert(size_type pos, size_type n, value_type c)
752 TestlyxstringInvariant(this);
754 rep = rep->get_own_copy();
755 value_type * tmp = new value_type[n];
757 rep->insert(pos, tmp, n);
763 lyxstring::iterator lyxstring::insert(iterator p, value_type c)
765 TestlyxstringInvariant(this);
767 // what iterator is this supposed to return??
768 size_type tmp = p - begin();
769 insert(p - begin(), 1, c);
770 return begin() + tmp + 1; // ??
774 void lyxstring::insert(iterator p, size_type n , value_type c)
776 TestlyxstringInvariant(this);
778 insert(p - begin(), n , c);
782 void lyxstring::insert(iterator p, iterator first, iterator last)
784 TestlyxstringInvariant(this);
786 insert(p - begin(), first, last - first);
794 // All the below find functions should be verified,
795 // it is very likely that I have mixed up or interpreted
796 // some of the parameters wrong, also some of the funcs can surely
797 // be written more effectively.
799 lyxstring::size_type lyxstring::find(lyxstring const & a, size_type i) const
801 if (!rep->sz) return npos;
804 TestlyxstringInvariant(this);
806 for (size_type t = i; rep->sz - t >= a.length(); ++t) {
807 // search until (*this)[i] == a[0]
808 if (rep->s[t] == a[0]) {
809 // check if the rest of the value_types match
811 for (size_type j = 0; j < a.length(); ++j) {
812 if (rep->s[t + j] != a[j]) {
824 lyxstring::size_type lyxstring::find(value_type const * ptr, size_type i,
828 if (!rep->sz || !*ptr) return npos;
831 TestlyxstringInvariant(this);
833 // What is "n" here? is it the number of value_types to use in ptr
834 // or does "i" and "n" togeter form a substring to search
835 // for ptr in? For now I will assume that "n" tells the length
837 n = min(n, strlen(ptr));
838 for (size_type t = i; length() - t >= n; ++t) {
839 // search until (*this)[i] == a[0]
840 if (rep->s[t] == ptr[0]) {
841 // check if the rest of the value_types match
843 for (size_type j = 0; j < n; ++j) {
844 if (rep->s[t + j] != ptr[j]) {
856 lyxstring::size_type lyxstring::find(value_type const * s, size_type i) const
859 if (!rep->sz) return npos;
862 TestlyxstringInvariant(this);
864 if (!s || !*s) return npos;
865 return find(s, i, strlen(s));
869 lyxstring::size_type lyxstring::find(value_type c, size_type i) const
871 if (!rep->sz) return npos;
874 TestlyxstringInvariant(this);
876 for (size_type t = 0; t + i < length(); ++t) {
877 if (rep->s[t + i] == c) return t + i;
883 lyxstring::size_type lyxstring::rfind(lyxstring const & a, size_type i) const
885 TestlyxstringInvariant(this);
887 size_type ii = min(length() - 1, i);
889 if (a[a.length() - 1] == rep->s[ii]) {
890 int t = length() - 2;
891 size_type l = ii - 1;
892 for (; t >= 0; --t, --l) {
893 if (a[t] != rep->s[l]) break;
895 if (a[t] == rep->s[l]) return l;
902 lyxstring::size_type lyxstring::rfind(value_type const * ptr, size_type i,
906 TestlyxstringInvariant(this);
907 if (!*ptr) return npos;
909 size_type ii = min(length() - 1, i);
911 if (ptr[n - 1] == rep->s[ii]) {
913 size_type l = ii - 1;
914 for (; t >= 0; --t, --l) {
915 if (ptr[t] != rep->s[l]) break;
917 if (ptr[t] == rep->s[l]) return l;
924 lyxstring::size_type lyxstring::rfind(value_type const * ptr, size_type i) const
927 TestlyxstringInvariant(this);
928 if (!*ptr) return npos;
930 size_type ii = min(length() - 1, i);
932 if (ptr[strlen(ptr) - 1] == rep->s[ii]) {
933 int t = strlen(ptr) - 2;
934 size_type l = ii - 1;
935 for (; t >= 0; --t, --l) {
936 if (ptr[t] != rep->s[l]) break;
938 if (ptr[t] == rep->s[l]) return l;
945 lyxstring::size_type lyxstring::rfind(value_type c, size_type i) const
947 TestlyxstringInvariant(this);
949 size_type ii = min(length() - 1, i);
950 for (size_type t = ii; t != 0; --t) {
951 if (rep->s[t] == c) return t;
957 lyxstring::size_type lyxstring::find_first_of(lyxstring const & a,
961 TestlyxstringInvariant(this);
963 for (size_type t = i; t < length(); ++t) {
964 if (a.find(rep->s[t]) != npos) return t;
970 lyxstring::size_type lyxstring::find_first_of(value_type const * ptr, size_type i,
973 Assert(ptr && i < rep->sz);
974 TestlyxstringInvariant(this);
977 for (size_type t = i; t < length(); ++t) {
978 if(memchr(ptr, rep->s[t], n) != 0) return t;
984 lyxstring::size_type lyxstring::find_first_of(value_type const * ptr,
987 Assert(ptr && i < rep->sz);
988 TestlyxstringInvariant(this);
990 for (size_type t = i; t < length(); ++t) {
991 if (strchr(ptr, rep->s[t]) != 0) return t;
997 lyxstring::size_type lyxstring::find_first_of(value_type c, size_type i) const
1000 TestlyxstringInvariant(this);
1002 for (size_type t = i; t < length(); ++t) {
1003 if (rep->s[t] == c) return t;
1009 lyxstring::size_type lyxstring::find_last_of(lyxstring const & a,
1012 TestlyxstringInvariant(this);
1014 size_type ii = min(length() - 1, i);
1015 for (int t = ii; t >= 0; --t) {
1016 if (a.find(rep->s[t]) != npos) return t;
1021 lyxstring::size_type lyxstring::find_last_of(value_type const * ptr, size_type i,
1025 TestlyxstringInvariant(this);
1026 if (!n) return npos;
1028 size_type ii = min(length() - 1, i);
1029 for (int t = ii; t >= 0; --t) {
1030 if(memchr(ptr, rep->s[t], n) != 0) return t;
1036 lyxstring::size_type lyxstring::find_last_of(value_type const * ptr,
1040 TestlyxstringInvariant(this);
1042 size_type ii = min(length() - 1, i);
1043 for (int t = ii; t >= 0; --t) {
1044 if (strchr(ptr, rep->s[t]) != 0) return t;
1050 lyxstring::size_type lyxstring::find_last_of(value_type c, size_type i) const
1052 TestlyxstringInvariant(this);
1054 if (!rep->sz) return npos;
1055 size_type ii = min(length() - 1, i);
1056 for (int t = ii; t >= 0; --t) {
1057 if (rep->s[t] == c) return t;
1063 lyxstring::size_type lyxstring::find_first_not_of(lyxstring const & a,
1066 TestlyxstringInvariant(this);
1068 if (!rep->sz) return npos;
1069 Assert(i < rep->sz);
1070 for (size_type t = i; t < length(); ++t) {
1071 if (a.find(rep->s[t]) == npos) return t;
1077 lyxstring::size_type lyxstring::find_first_not_of(value_type const * ptr, size_type i,
1080 Assert(ptr && i < rep->sz);
1081 TestlyxstringInvariant(this);
1083 if (!n) return (i < length()) ? i : npos;
1084 for (size_type t = i; t < length(); ++t) {
1085 if(memchr(ptr, rep->s[t], n) == 0) return t;
1091 lyxstring::size_type lyxstring::find_first_not_of(value_type const * ptr,
1094 Assert(ptr && i < rep->sz);
1095 TestlyxstringInvariant(this);
1097 for (size_type t = i; t < length(); ++t) {
1098 if (strchr(ptr, rep->s[t]) == 0) return t;
1104 lyxstring::size_type lyxstring::find_first_not_of(value_type c, size_type i) const
1106 if (!rep->sz) return npos;
1107 Assert(i < rep->sz);
1108 TestlyxstringInvariant(this);
1110 for (size_type t = i; t < length(); ++t) {
1111 if (rep->s[t] != c) return t;
1117 lyxstring::size_type lyxstring::find_last_not_of(lyxstring const & a,
1120 TestlyxstringInvariant(this);
1122 size_type ii = min(length() - 1, i);
1123 for (int t = ii; t >= 0; --t) {
1124 if (a.find(rep->s[t]) == npos) return t;
1130 lyxstring::size_type lyxstring::find_last_not_of(value_type const * ptr, size_type i,
1134 TestlyxstringInvariant(this);
1136 size_type ii = min(length() - 1, i);
1137 if (!n) return (ii >= 0) ? ii : npos;
1138 for (int t = ii; t >= 0; --t) {
1139 if(memchr(ptr, rep->s[t], n) == 0) return t;
1145 lyxstring::size_type lyxstring::find_last_not_of(value_type const * ptr,
1149 TestlyxstringInvariant(this);
1151 size_type ii = min(length() - 1, i);
1152 for (int t = ii; t >= 0; --t) {
1153 if (strchr(ptr, rep->s[t]) == 0) return t;
1159 lyxstring::size_type lyxstring::find_last_not_of(value_type c, size_type i) const
1161 TestlyxstringInvariant(this);
1163 size_type ii = min(length() - 1, i);
1164 for (int t = ii; t >= 0; --t) {
1165 if (rep->s[t] != c) return t;
1175 lyxstring & lyxstring::replace(size_type i, size_type n, lyxstring const & x)
1177 Assert(i < rep->sz || i == 0);
1178 TestlyxstringInvariant(this);
1180 return replace(i, n, x, 0, x.length());
1184 lyxstring & lyxstring::replace(size_type i,size_type n, lyxstring const & x,
1185 size_type i2, size_type n2)
1187 Assert((i < rep->sz || i == 0) && (i2 < x.rep->sz || i2 == 0));
1188 TestlyxstringInvariant(this);
1190 rep = rep->get_own_copy();
1191 rep->replace(i, min(n, rep->sz), &(x.rep->s[i2]), min(n2, x.rep->sz));
1196 lyxstring & lyxstring::replace(size_type i, size_type n, value_type const * p,
1199 Assert(p && i < rep->sz);
1200 TestlyxstringInvariant(this);
1202 rep = rep->get_own_copy();
1203 rep->replace(i, min(n, rep->sz), p, min(n2, strlen(p)));
1208 lyxstring & lyxstring::replace(size_type i, size_type n, value_type const * p)
1210 Assert(p && i < rep->sz);
1211 TestlyxstringInvariant(this);
1213 return replace(i, min(n, rep->sz), p, (!p) ? 0 : strlen(p));
1217 lyxstring & lyxstring::replace(size_type i, size_type n, size_type n2, value_type c)
1219 Assert(i < rep->sz);
1220 TestlyxstringInvariant(this);
1222 rep = rep->get_own_copy();
1223 value_type * tmp = new value_type[n2];
1225 rep->replace(i, min(n, rep->sz), tmp, n2);
1231 lyxstring & lyxstring::replace(iterator i, iterator i2, const lyxstring & str)
1233 TestlyxstringInvariant(this);
1235 return replace(i - begin(), i2 - i, str);
1239 lyxstring & lyxstring::replace(iterator i, iterator i2,
1240 value_type const * p, size_type n)
1243 TestlyxstringInvariant(this);
1245 return replace(i - begin(), i2 - i, p, n);
1249 lyxstring & lyxstring::replace(iterator i, iterator i2, value_type const * p)
1252 TestlyxstringInvariant(this);
1254 return replace(i - begin(), i2 - i, p);
1258 lyxstring & lyxstring::replace(iterator i, iterator i2, size_type n , value_type c)
1260 TestlyxstringInvariant(this);
1262 return replace(i - begin(), i2 - i, n, c);
1266 lyxstring & lyxstring::replace(iterator i, iterator i2, iterator j, iterator j2)
1268 TestlyxstringInvariant(this);
1270 return replace(i - begin(), i2 - i, j, j2 - j);
1274 lyxstring & lyxstring::erase(size_type i, size_type n)
1276 Assert(i < rep->sz || i == 0);
1277 TestlyxstringInvariant(this);
1279 rep = rep->get_own_copy();
1280 if (i == 0 && n >= rep->sz) {
1283 n = min(n, rep->sz - i);
1284 memmove(&(rep->s[i]), &(rep->s[i + n]), rep->sz - i - n);
1291 lyxstring::iterator lyxstring::erase(iterator i)
1293 TestlyxstringInvariant(this);
1295 // what iterator is this supposed to return?
1296 // the iterator after the one erased
1297 erase(i - begin(), 1);
1298 return begin(); // BUG
1302 lyxstring::iterator lyxstring::erase(iterator first, iterator last)
1304 TestlyxstringInvariant(this);
1306 erase(first - begin(), last - first);
1307 return begin(); // BUG
1311 /////////////////////////////////////
1312 // Conversion to C-style Strings
1313 /////////////////////////////////////
1315 lyxstring::value_type const * lyxstring::c_str() const
1317 rep->s[length()] = '\0';
1322 lyxstring::value_type const * lyxstring::data() const
1328 lyxstring::size_type lyxstring::copy(value_type * buf, size_type len, size_type pos) const
1331 TestlyxstringInvariant(this);
1333 register int nn = min(len, length() - pos);
1334 memcpy(buf, &(rep->s[pos]), nn);
1339 ////////////////////
1341 ////////////////////
1343 // Compare funcs should be verified.
1344 // Should we try to make them work with '\0' value_types?
1345 // An STL string can usually contain '\0' value_types.
1347 int lyxstring::compare(lyxstring const & str) const
1349 TestlyxstringInvariant(this);
1351 return compare(0, rep->sz, str.rep->s, str.rep->sz);
1355 int lyxstring::compare(value_type const * s) const
1358 TestlyxstringInvariant(this);
1360 return compare(0, rep->sz, s, (!s) ? 0 : strlen(s));
1364 int lyxstring::compare(size_type pos, size_type n, lyxstring const & str) const
1366 TestlyxstringInvariant(this);
1368 return compare(pos, n, str.rep->s, str.rep->sz);
1372 int lyxstring::compare(size_type pos, size_type n, lyxstring const & str,
1373 size_type pos2, size_type n2) const
1375 TestlyxstringInvariant(this);
1377 return compare(pos, n, str.rep->s + pos2, n2);
1381 int lyxstring::compare(size_type pos, size_type n, value_type const * s,
1384 Assert(s && (pos < rep->sz || pos == 0));
1385 TestlyxstringInvariant(this);
1387 if ((rep->sz == 0 || n == 0) && (!*s || n2 == 0)) return 0;
1389 // since n > n2, min(n,n2) == 0, c == 0 (stops segfault also)
1391 // remember that n can very well be a lot larger than rep->sz
1392 // so we have to ensure that n is no larger than rep->sz
1393 n = min(n, rep->sz);
1394 n2 = min(n2, strlen(s));
1396 return memcmp(&(rep->s[pos]), s, n);
1397 int c = memcmp(&(rep->s[pos]), s, min(n,n2));
1410 // i = index, n = length
1411 lyxstring lyxstring::substr(size_type i, size_type n) const
1413 Assert(i < rep->sz || i == 0);
1414 TestlyxstringInvariant(this);
1416 return lyxstring(*this, i, n);
1421 /////////////////////////////////////////////
1422 // String operators, non member functions
1423 /////////////////////////////////////////////
1425 bool operator==(lyxstring const & a, lyxstring const & b)
1427 return a.compare(b) == 0;
1431 bool operator==(lyxstring::value_type const * a, lyxstring const & b)
1434 return b.compare(a) == 0;
1438 bool operator==(lyxstring const & a, lyxstring::value_type const * b)
1441 return a.compare(b) == 0;
1445 bool operator!=(lyxstring const & a, lyxstring const & b)
1447 return a.compare(b) != 0;
1451 bool operator!=(lyxstring::value_type const * a, lyxstring const & b)
1454 return b.compare(a) != 0;
1458 bool operator!=(lyxstring const & a, lyxstring::value_type const * b)
1461 return a.compare(b) != 0;
1465 bool operator>(lyxstring const & a, lyxstring const & b)
1467 return a.compare(b) > 0;
1471 bool operator>(lyxstring::value_type const * a, lyxstring const & b)
1474 return b.compare(a) < 0; // since we reverse the parameters
1478 bool operator>(lyxstring const & a, lyxstring::value_type const * b)
1481 return a.compare(b) > 0;
1485 bool operator<(lyxstring const & a, lyxstring const & b)
1487 return a.compare(b) < 0;
1491 bool operator<(lyxstring::value_type const * a, lyxstring const & b)
1494 return b.compare(a) > 0; // since we reverse the parameters
1498 bool operator<(lyxstring const & a, lyxstring::value_type const * b)
1501 return a.compare(b) < 0;
1505 bool operator>=(lyxstring const & a, lyxstring const & b)
1507 return a.compare(b) >= 0;
1511 bool operator>=(lyxstring::value_type const * a, lyxstring const & b)
1514 return b.compare(a) <= 0; // since we reverse the parameters
1518 bool operator>=(lyxstring const & a, lyxstring::value_type const * b)
1521 return a.compare(b) >= 0;
1525 bool operator<=(lyxstring const & a, lyxstring const & b)
1527 return a.compare(b) <= 0;
1531 bool operator<=(lyxstring::value_type const * a, lyxstring const & b)
1534 return b.compare(a) >= 0; // since we reverse the parameters
1538 bool operator<=(lyxstring const & a, lyxstring::value_type const * b)
1541 return a.compare(b) <= 0;
1545 lyxstring operator+(lyxstring const & a, lyxstring const & b)
1553 lyxstring operator+(lyxstring::value_type const * a, lyxstring const & b)
1562 lyxstring operator+(lyxstring::value_type a, lyxstring const & b)
1571 lyxstring operator+(lyxstring const & a, lyxstring::value_type const * b)
1580 lyxstring operator+(lyxstring const & a, lyxstring::value_type b)
1589 istream & operator>>(istream & is, lyxstring & s)
1591 // very bad solution
1594 lyxstring tmp(nome);
1595 if (!tmp.empty()) s = tmp;
1599 ostream & operator<<(ostream & o, lyxstring const & s)
1601 return o.write(s.data(), s.length());
1604 istream & getline(istream & is, lyxstring & s,
1605 lyxstring::value_type delim = '\n')
1607 // very bad solution