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 * ======================================================*/
15 // If we use STL string, there is no need to compile this class.
16 #ifdef USE_INCLUDED_STRING
19 #pragma implementation "lyxstring.h"
22 #include "lyxstring.h"
31 // Reference count has been checked, empty_rep removed and
32 // introduced again in a similar guise. Where is empty_rep _really_
35 // Insertion and replace is implemented, as far as I can see everything
36 // works, but could perhaps be done smarter.
38 // All the different find functions need a good look over.
39 // I have so far not tested them extensively and would be
40 // happy if others took the time to have a peek.
43 #warning temporarily here for debugging purposes only
45 lyxstring::size_type lyxstring::size() const
51 //--------------------------------------------------------------------------
55 /** Testing of the lyxstring invariant
56 * By creating an object that tests the lyxstring invariant during its
57 * construction *and* its deconstruction we greatly simplify our code.
58 * Calling TestlyxstringInvariant() upon entry to an lyxstring method
59 * will test the invariant upon entry to the code. If the Asserts fail
60 * then we know from the stack trace that the corruption occurred *before*
61 * entry to this method. We can also be sure it didn't happen in any of
62 * the tested lyxstring methods. It is therefore likely to be due to some
63 * other external force.
64 * Several lyxstring methods have multiple exit points which would otherwise
65 * require us to insert a separate test before each return. But since we
66 * created an object its destructor will be called upon exit (any exit!).
67 * We thus get testing at both start and end of a method with one line of
68 * code at the head of a method. More importantly, we get good testing
69 * everytime we run the code.
70 * NOTE: just because we test the invariant doesn't mean we can forget
71 * about testing pre and post conditions specific to any given method.
72 * This test simply proves that the lyxstring/Srep is in a valid state it
73 * does *not* prove that the method did what it was supposed to.
75 class lyxstringInvariant
78 lyxstringInvariant(lyxstring const *);
79 ~lyxstringInvariant();
82 lyxstring const * object;
85 // To test if this scheme works "as advertised" uncomment the printf's in
86 // the constructor and destructor below and then uncomment the printf and the
87 // call to TestlyxstringInvariant() in lyxstring::operator=(char const *).
88 // The correct output when LyX has been recompiled and run is:
89 // lyxstringInvariant constructor
90 // lyxstring::operator=(char const *)
91 // lyxstringInvariant constructor
92 // lyxstringInvariant destructor completed
93 // lyxstringInvariant destructor completed
94 // NOTE: The easiest way to catch this snippet of the output is to wait for
95 // the splash screen to disappear and then open and close Help->Credits
97 lyxstringInvariant::lyxstringInvariant(lyxstring const * ls) : object(ls)
99 // printf("lyxstringInvariant constructor\n");
103 lyxstringInvariant::~lyxstringInvariant()
106 // printf("lyxstringInvariant destructor completed\n");
109 void lyxstringInvariant::helper() const
111 // Some of these tests might look pointless but they are
112 // all part of the invariant and if we want to make sure
113 // we have a bullet proof implementation then we need to
114 // test every last little thing we *know* should be true.
115 // I may have missed a test or two, so feel free to fill
116 // in the gaps. ARRae.
117 // NOTE: Don't put TestlyxstringInvariant() in any of the
118 // lyxstring methods used below otherwise you'll get an
119 // infinite recursion and a crash.
122 Assert(object->rep->s); // s is never 0
123 Assert(object->rep->res); // always some space allocated
124 Assert(object->size() <= object->rep->res);
125 Assert(object->rep->ref >= 1); // its in use so it must be referenced
126 Assert(object->rep->ref < (1 << 8*sizeof(lyxstring::Srep::ref)) - 1);
127 // if it does ever == then we should be generating a new copy
128 // and starting again. (Is char always 8-bits?)
130 #define TestlyxstringInvariant(s) lyxstringInvariant lyxstring_invariant(s);
132 #define TestlyxstringInvariant(s)
133 #endif //DEVEL_VERSION
134 //-------------------------------------------------------------------------
136 ///////////////////////////////////////
137 // Constructors and Deconstructors.
138 ///////////////////////////////////////
141 lyxstring::Srep::Srep(lyxstring::size_type nsz, const value_type * p)
143 // can be called with p==0 by lyxstring::assign(const value_type *, size_type)
148 s = new value_type[res + 1]; // add space for terminator
150 // if sz = 0 nothing gets copied and we have an error
153 // possibly allows for large but empty string
154 sz = 0; // this line should be redundant
160 lyxstring::Srep::Srep(lyxstring::size_type nsz, value_type ch)
165 s = new value_type[res + 1]; // add space for terminator
168 // if ch == '\0' strlen(lyxstring.c_str()) == 0 so sz = 0
169 // allows for large but empty string
175 void lyxstring::Srep::assign(lyxstring::size_type nsz, const value_type * p)
177 // can be called with p==0 by lyxstring::assign(const value_type *, size_type)
183 s = new value_type[res + 1]; // add space for terminator
188 // if sz = 0 nothing gets copied and we have an error
192 sz = 0; // this line should be redundant
198 void lyxstring::Srep::assign(lyxstring::size_type nsz, value_type ch)
204 s = new value_type[res + 1]; // add space for terminator
208 // if ch == '\0' strlen(lyxstring.c_str()) == 0 so sz = 0
209 // allows for a large empty string
215 void lyxstring::Srep::append(lyxstring::size_type asz, const value_type * p)
217 register unsigned int const len = sz + asz;
220 value_type * tmp = new value_type[res + 1];
222 memcpy(tmp + sz, p, asz);
227 memcpy(s + sz, p, asz);
233 void lyxstring::Srep::push_back(value_type c)
235 s[sz] = c; // it is always room to put a value_type at the end
239 value_type * tmp = new value_type[res + 1];
247 void lyxstring::Srep::insert(lyxstring::size_type pos, const value_type * p,
248 lyxstring::size_type n)
253 value_type * tmp = new value_type[res + 1];
255 memcpy(tmp + pos, p, n);
256 memcpy(tmp + pos + n, & s[pos], sz - pos);
261 memmove(s + pos + n, & s[pos], sz - pos);
262 memcpy(s + pos, p, n);
268 void lyxstring::Srep::resize(size_type n, value_type c)
271 // This resets sz to res_arg
272 res = min(n, npos - 2); // We keep no xtra when we resize
273 value_type * tmp = new value_type[res + 1];
274 memcpy(tmp, s, min(sz, res));
276 memset(tmp + sz, c, res - sz);
283 void lyxstring::Srep::reserve(lyxstring::size_type res_arg)
285 // This keeps the old sz, but
286 // increases res with res_arg
288 value_type * tmp = new value_type[res + 1];
295 void lyxstring::Srep::replace(lyxstring::size_type i, lyxstring::size_type n,
296 value_type const * p, size_type n2)
298 // can be called with p=0 and n2=0
299 Assert(i < sz && ((!p && !n2) || p));
302 if (res >= n2 + sz) {
303 memmove(s + i + n2, &s[i + n], sz - i);
304 memcpy(s + i, p, n2);
307 res = sz + n2 + xtra;
308 value_type * tmp = new value_type[res + 1];
310 memcpy(tmp + i, p, n2);
311 memcpy(tmp + i + n2, &s[i + n], sz - i);
319 lyxstring::size_type const lyxstring::npos = static_cast<lyxstring::size_type>(-1);
321 lyxstring::lyxstring()
323 static Srep empty_rep(0, "");
329 lyxstring::lyxstring(lyxstring const & x, size_type pos, size_type n)
331 Assert(pos < x.rep->sz || pos == 0);
332 if (pos == 0 && n >= x.length()) { // this is the default
336 rep = new Srep(min(n, x.rep->sz - pos), &(x.rep->s[pos]));
341 lyxstring::lyxstring(value_type const * s, size_type n)
343 Assert(s); // we don't allow null pointers
344 static Srep empty_rep(0, "");
345 if (s && *s && n) { // s is not empty string and n > 0
346 rep = new Srep(min(strlen(s), n), s);
354 lyxstring::lyxstring(value_type const * s)
356 // yes we allow them just don't initalize them
357 // Assert(s); // we don't allow null pointers
358 static Srep empty_rep(0, "");
359 if (s && *s) { // s is not empty string
360 rep = new Srep(strlen(s), s);
368 lyxstring::lyxstring(size_type n, value_type c)
370 rep = new Srep(n, c);
374 lyxstring::lyxstring(iterator first, iterator last)
376 rep = new Srep(last - first, first);
380 ///////////////////////
382 ///////////////////////
384 lyxstring::iterator lyxstring::begin()
390 lyxstring::const_iterator lyxstring::begin() const
396 lyxstring::iterator lyxstring::end()
398 return rep->s + rep->sz;
402 lyxstring::const_iterator lyxstring::end() const
404 return rep->s + rep->sz;
408 reverse_iterator lyxstring::rbegin()
410 return reverse_iterator( end() );
414 const_reverse_iterator lyxstring::rbegin() const
416 return const_reverse_iterator( end() );
420 reverse_iterator lyxstring::rend()
422 return reverse_iterator( begin() );
426 const_reverse_iterator lyxstring::rend() const
428 return const_reverse_iterator( begin() );
432 ///////////////////////
434 ///////////////////////
436 void lyxstring::resize(size_type n, value_type c)
438 TestlyxstringInvariant(this);
440 // This resets sz to res_arg
441 rep = rep->get_own_copy();
446 lyxstring::size_type lyxstring::capacity() const
452 void lyxstring::reserve(size_type res_arg)
454 TestlyxstringInvariant(this);
456 rep = rep->get_own_copy();
457 rep->reserve(res_arg);
465 lyxstring & lyxstring::operator=(lyxstring const & x)
467 TestlyxstringInvariant(this);
473 lyxstring & lyxstring::operator=(value_type const * s)
476 TestlyxstringInvariant(this);
477 // printf("lyxstring::operator=(value_type const *)\n");
483 lyxstring & lyxstring::operator=(value_type c)
485 TestlyxstringInvariant(this);
489 if (rep->ref == 1) // recycle rep
493 rep = new Srep(1, s);
499 lyxstring & lyxstring::assign(lyxstring const & x)
501 TestlyxstringInvariant(this);
503 x.rep->ref++; // protect against ``st = st''
504 if (--rep->ref == 0) delete rep;
505 rep = x.rep; // share representation
510 lyxstring & lyxstring::assign(lyxstring const & x, size_type pos, size_type n)
512 TestlyxstringInvariant(this);
514 return assign(x.substr(pos, n));
518 lyxstring & lyxstring::assign(value_type const * s, size_type n)
521 TestlyxstringInvariant(this);
523 n = min(strlen(s), n);
524 if (rep->ref == 1) // recycle rep
528 rep = new Srep(n, s);
534 lyxstring & lyxstring::assign(value_type const * s)
537 TestlyxstringInvariant(this);
539 return assign(s, strlen(s));
543 lyxstring & lyxstring::assign(size_type n, value_type ch)
545 TestlyxstringInvariant(this);
547 rep = rep->get_own_copy();
553 lyxstring & lyxstring::assign(iterator first, iterator last)
555 TestlyxstringInvariant(this);
557 rep = rep->get_own_copy();
558 rep->assign(last - first, first);
567 lyxstring::const_reference lyxstring::operator[](size_type pos) const
569 Assert(pos < rep->sz);
575 lyxstring::reference lyxstring::operator[](size_type pos)
577 Assert(pos < rep->sz);
578 TestlyxstringInvariant(this);
580 rep = rep->get_own_copy();
585 lyxstring::const_reference lyxstring::at(size_type n) const
593 lyxstring::reference lyxstring::at(size_type n)
596 TestlyxstringInvariant(this);
598 rep = rep->get_own_copy();
607 lyxstring & lyxstring::operator+=(lyxstring const & x)
609 TestlyxstringInvariant(this);
615 lyxstring & lyxstring::operator+=(value_type const * x)
618 TestlyxstringInvariant(this);
624 lyxstring & lyxstring::operator+=(value_type c)
626 TestlyxstringInvariant(this);
633 void lyxstring::push_back(value_type c)
635 TestlyxstringInvariant(this);
637 rep = rep->get_own_copy();
642 lyxstring & lyxstring::append(lyxstring const & x)
644 TestlyxstringInvariant(this);
646 if (x.empty()) return *this;
647 rep = rep->get_own_copy();
648 rep->append(x.length(), x.rep->s);
653 lyxstring & lyxstring::append(lyxstring const & x, size_type pos, size_type n)
655 TestlyxstringInvariant(this);
657 return append(x.substr(pos, n));
661 lyxstring & lyxstring::append(value_type const * p, size_type n)
664 TestlyxstringInvariant(this);
666 if (!*p || !n) return *this;
667 rep = rep->get_own_copy();
668 rep->append(min(n, strlen(p)), p);
673 lyxstring & lyxstring::append(value_type const * p)
676 TestlyxstringInvariant(this);
678 if (!*p) return *this;
679 rep = rep->get_own_copy();
680 rep->append(strlen(p), p);
685 lyxstring & lyxstring::append(size_type n, value_type c)
687 TestlyxstringInvariant(this);
689 value_type * tmp = new value_type[n];
691 rep = rep->get_own_copy();
698 lyxstring & lyxstring::append(iterator first, iterator last)
700 TestlyxstringInvariant(this);
702 rep = rep->get_own_copy();
703 rep->append(last - first, first);
707 // insert value_typeacters before (*this)[pos]
709 lyxstring & lyxstring::insert(size_type pos, lyxstring const & x)
711 TestlyxstringInvariant(this);
713 return insert(pos, x, 0, x.rep->sz);
717 lyxstring & lyxstring::insert(size_type pos, lyxstring const & x,
718 size_type pos2, size_type n)
720 TestlyxstringInvariant(this);
722 rep = rep->get_own_copy();
723 rep->insert(pos, &(x.rep->s[pos2]), min(n, x.rep->sz));
728 lyxstring & lyxstring::insert(size_type pos, value_type const * p, size_type n)
731 TestlyxstringInvariant(this);
734 // insert nothing and you change nothing
735 rep = rep->get_own_copy();
736 rep->insert(pos, p, min(n, strlen(p)));
742 lyxstring & lyxstring::insert(size_type pos, value_type const * p)
745 TestlyxstringInvariant(this);
748 // insert nothing and you change nothing
749 rep = rep->get_own_copy();
750 rep->insert(pos, p, strlen(p));
756 lyxstring & lyxstring::insert(size_type pos, size_type n, value_type c)
758 TestlyxstringInvariant(this);
760 rep = rep->get_own_copy();
761 value_type * tmp = new value_type[n];
763 rep->insert(pos, tmp, n);
769 lyxstring::iterator lyxstring::insert(iterator p, value_type c)
771 TestlyxstringInvariant(this);
773 // what iterator is this supposed to return??
774 size_type tmp = p - begin();
775 insert(p - begin(), 1, c);
776 return begin() + tmp + 1; // ??
780 void lyxstring::insert(iterator p, size_type n , value_type c)
782 TestlyxstringInvariant(this);
784 insert(p - begin(), n , c);
788 void lyxstring::insert(iterator p, iterator first, iterator last)
790 TestlyxstringInvariant(this);
792 insert(p - begin(), first, last - first);
800 // All the below find functions should be verified,
801 // it is very likely that I have mixed up or interpreted
802 // some of the parameters wrong, also some of the funcs can surely
803 // be written more effectively.
805 lyxstring::size_type lyxstring::find(lyxstring const & a, size_type i) const
807 if (!rep->sz) return npos;
810 TestlyxstringInvariant(this);
812 for (size_type t = i; rep->sz - t >= a.length(); ++t) {
813 // search until (*this)[i] == a[0]
814 if (rep->s[t] == a[0]) {
815 // check if the rest of the value_types match
817 for (size_type j = 0; j < a.length(); ++j) {
818 if (rep->s[t + j] != a[j]) {
830 lyxstring::size_type lyxstring::find(value_type const * ptr, size_type i,
834 if (!rep->sz || !*ptr) return npos;
837 TestlyxstringInvariant(this);
839 // What is "n" here? is it the number of value_types to use in ptr
840 // or does "i" and "n" togeter form a substring to search
841 // for ptr in? For now I will assume that "n" tells the length
843 n = min(n, strlen(ptr));
844 for (size_type t = i; length() - t >= n; ++t) {
845 // search until (*this)[i] == a[0]
846 if (rep->s[t] == ptr[0]) {
847 // check if the rest of the value_types match
849 for (size_type j = 0; j < n; ++j) {
850 if (rep->s[t + j] != ptr[j]) {
862 lyxstring::size_type lyxstring::find(value_type const * s, size_type i) const
865 if (!rep->sz) return npos;
868 TestlyxstringInvariant(this);
870 if (!s || !*s) return npos;
871 return find(s, i, strlen(s));
875 lyxstring::size_type lyxstring::find(value_type c, size_type i) const
877 if (!rep->sz) return npos;
880 TestlyxstringInvariant(this);
882 for (size_type t = 0; t + i < length(); ++t) {
883 if (rep->s[t + i] == c) return t + i;
889 lyxstring::size_type lyxstring::rfind(lyxstring const & a, size_type i) const
891 TestlyxstringInvariant(this);
893 size_type ii = min(length() - 1, i);
895 if (a[a.length() - 1] == rep->s[ii]) {
896 int t = length() - 2;
897 size_type l = ii - 1;
898 for (; t >= 0; --t, --l) {
899 if (a[t] != rep->s[l]) break;
901 if (a[t] == rep->s[l]) return l;
908 lyxstring::size_type lyxstring::rfind(value_type const * ptr, size_type i,
912 TestlyxstringInvariant(this);
913 if (!*ptr) return npos;
915 size_type ii = min(length() - 1, i);
917 if (ptr[n - 1] == rep->s[ii]) {
919 size_type l = ii - 1;
920 for (; t >= 0; --t, --l) {
921 if (ptr[t] != rep->s[l]) break;
923 if (ptr[t] == rep->s[l]) return l;
930 lyxstring::size_type lyxstring::rfind(value_type const * ptr, size_type i) const
933 TestlyxstringInvariant(this);
934 if (!*ptr) return npos;
936 size_type ii = min(length() - 1, i);
938 if (ptr[strlen(ptr) - 1] == rep->s[ii]) {
939 int t = strlen(ptr) - 2;
940 size_type l = ii - 1;
941 for (; t >= 0; --t, --l) {
942 if (ptr[t] != rep->s[l]) break;
944 if (ptr[t] == rep->s[l]) return l;
951 lyxstring::size_type lyxstring::rfind(value_type c, size_type i) const
953 TestlyxstringInvariant(this);
955 size_type ii = min(length() - 1, i);
956 for (size_type t = ii; t != 0; --t) {
957 if (rep->s[t] == c) return t;
963 lyxstring::size_type lyxstring::find_first_of(lyxstring const & a,
967 TestlyxstringInvariant(this);
969 for (size_type t = i; t < length(); ++t) {
970 if (a.find(rep->s[t]) != npos) return t;
976 lyxstring::size_type lyxstring::find_first_of(value_type const * ptr, size_type i,
979 Assert(ptr && i < rep->sz);
980 TestlyxstringInvariant(this);
983 for (size_type t = i; t < length(); ++t) {
984 if(memchr(ptr, rep->s[t], n) != 0) return t;
990 lyxstring::size_type lyxstring::find_first_of(value_type const * ptr,
993 Assert(ptr && i < rep->sz);
994 TestlyxstringInvariant(this);
996 for (size_type t = i; t < length(); ++t) {
997 if (strchr(ptr, rep->s[t]) != 0) return t;
1003 lyxstring::size_type lyxstring::find_first_of(value_type c, size_type i) const
1005 Assert(i < rep->sz);
1006 TestlyxstringInvariant(this);
1008 for (size_type t = i; t < length(); ++t) {
1009 if (rep->s[t] == c) return t;
1015 lyxstring::size_type lyxstring::find_last_of(lyxstring const & a,
1018 TestlyxstringInvariant(this);
1020 size_type ii = min(length() - 1, i);
1021 for (int t = ii; t >= 0; --t) {
1022 if (a.find(rep->s[t]) != npos) return t;
1027 lyxstring::size_type lyxstring::find_last_of(value_type const * ptr, size_type i,
1031 TestlyxstringInvariant(this);
1032 if (!n) return npos;
1034 size_type ii = min(length() - 1, i);
1035 for (int t = ii; t >= 0; --t) {
1036 if(memchr(ptr, rep->s[t], n) != 0) return t;
1042 lyxstring::size_type lyxstring::find_last_of(value_type const * ptr,
1046 TestlyxstringInvariant(this);
1048 size_type ii = min(length() - 1, i);
1049 for (int t = ii; t >= 0; --t) {
1050 if (strchr(ptr, rep->s[t]) != 0) return t;
1056 lyxstring::size_type lyxstring::find_last_of(value_type c, size_type i) const
1058 TestlyxstringInvariant(this);
1060 if (!rep->sz) return npos;
1061 size_type ii = min(length() - 1, i);
1062 for (int t = ii; t >= 0; --t) {
1063 if (rep->s[t] == c) return t;
1069 lyxstring::size_type lyxstring::find_first_not_of(lyxstring const & a,
1072 TestlyxstringInvariant(this);
1074 if (!rep->sz) return npos;
1075 Assert(i < rep->sz);
1076 for (size_type t = i; t < length(); ++t) {
1077 if (a.find(rep->s[t]) == npos) return t;
1083 lyxstring::size_type lyxstring::find_first_not_of(value_type const * ptr, size_type i,
1086 Assert(ptr && i < rep->sz);
1087 TestlyxstringInvariant(this);
1089 if (!n) return (i < length()) ? i : npos;
1090 for (size_type t = i; t < length(); ++t) {
1091 if(memchr(ptr, rep->s[t], n) == 0) return t;
1097 lyxstring::size_type lyxstring::find_first_not_of(value_type const * ptr,
1100 Assert(ptr && i < rep->sz);
1101 TestlyxstringInvariant(this);
1103 for (size_type t = i; t < length(); ++t) {
1104 if (strchr(ptr, rep->s[t]) == 0) return t;
1110 lyxstring::size_type lyxstring::find_first_not_of(value_type c, size_type i) const
1112 if (!rep->sz) return npos;
1113 Assert(i < rep->sz);
1114 TestlyxstringInvariant(this);
1116 for (size_type t = i; t < length(); ++t) {
1117 if (rep->s[t] != c) return t;
1123 lyxstring::size_type lyxstring::find_last_not_of(lyxstring const & a,
1126 TestlyxstringInvariant(this);
1128 size_type ii = min(length() - 1, i);
1129 for (int t = ii; t >= 0; --t) {
1130 if (a.find(rep->s[t]) == npos) return t;
1136 lyxstring::size_type lyxstring::find_last_not_of(value_type const * ptr, size_type i,
1140 TestlyxstringInvariant(this);
1142 size_type ii = min(length() - 1, i);
1143 if (!n) return (ii >= 0) ? ii : npos;
1144 for (int t = ii; t >= 0; --t) {
1145 if(memchr(ptr, rep->s[t], n) == 0) return t;
1151 lyxstring::size_type lyxstring::find_last_not_of(value_type const * ptr,
1155 TestlyxstringInvariant(this);
1157 size_type ii = min(length() - 1, i);
1158 for (int t = ii; t >= 0; --t) {
1159 if (strchr(ptr, rep->s[t]) == 0) return t;
1165 lyxstring::size_type lyxstring::find_last_not_of(value_type c, size_type i) const
1167 TestlyxstringInvariant(this);
1169 size_type ii = min(length() - 1, i);
1170 for (int t = ii; t >= 0; --t) {
1171 if (rep->s[t] != c) return t;
1181 lyxstring & lyxstring::replace(size_type i, size_type n, lyxstring const & x)
1183 Assert(i < rep->sz || i == 0);
1184 TestlyxstringInvariant(this);
1186 return replace(i, n, x, 0, x.length());
1190 lyxstring & lyxstring::replace(size_type i,size_type n, lyxstring const & x,
1191 size_type i2, size_type n2)
1193 Assert((i < rep->sz || i == 0) && (i2 < x.rep->sz || i2 == 0));
1194 TestlyxstringInvariant(this);
1196 rep = rep->get_own_copy();
1197 rep->replace(i, min(n, rep->sz), &(x.rep->s[i2]), min(n2, x.rep->sz));
1202 lyxstring & lyxstring::replace(size_type i, size_type n, value_type const * p,
1205 Assert(p && i < rep->sz);
1206 TestlyxstringInvariant(this);
1208 rep = rep->get_own_copy();
1209 rep->replace(i, min(n, rep->sz), p, min(n2, strlen(p)));
1214 lyxstring & lyxstring::replace(size_type i, size_type n, value_type const * p)
1216 Assert(p && i < rep->sz);
1217 TestlyxstringInvariant(this);
1219 return replace(i, min(n, rep->sz), p, (!p) ? 0 : strlen(p));
1223 lyxstring & lyxstring::replace(size_type i, size_type n, size_type n2, value_type c)
1225 Assert(i < rep->sz);
1226 TestlyxstringInvariant(this);
1228 rep = rep->get_own_copy();
1229 value_type * tmp = new value_type[n2];
1231 rep->replace(i, min(n, rep->sz), tmp, n2);
1237 lyxstring & lyxstring::replace(iterator i, iterator i2, const lyxstring & str)
1239 TestlyxstringInvariant(this);
1241 return replace(i - begin(), i2 - i, str);
1245 lyxstring & lyxstring::replace(iterator i, iterator i2,
1246 value_type const * p, size_type n)
1249 TestlyxstringInvariant(this);
1251 return replace(i - begin(), i2 - i, p, n);
1255 lyxstring & lyxstring::replace(iterator i, iterator i2, value_type const * p)
1258 TestlyxstringInvariant(this);
1260 return replace(i - begin(), i2 - i, p);
1264 lyxstring & lyxstring::replace(iterator i, iterator i2, size_type n , value_type c)
1266 TestlyxstringInvariant(this);
1268 return replace(i - begin(), i2 - i, n, c);
1272 lyxstring & lyxstring::replace(iterator i, iterator i2, iterator j, iterator j2)
1274 TestlyxstringInvariant(this);
1276 return replace(i - begin(), i2 - i, j, j2 - j);
1280 lyxstring & lyxstring::erase(size_type i, size_type n)
1282 Assert(i < rep->sz || i == 0);
1283 TestlyxstringInvariant(this);
1285 rep = rep->get_own_copy();
1286 if (i == 0 && n >= rep->sz) {
1289 n = min(n, rep->sz - i);
1290 memmove(&(rep->s[i]), &(rep->s[i + n]), rep->sz - i - n);
1297 lyxstring::iterator lyxstring::erase(iterator i)
1299 TestlyxstringInvariant(this);
1301 // what iterator is this supposed to return?
1302 // the iterator after the one erased
1303 erase(i - begin(), 1);
1304 return begin(); // BUG
1308 lyxstring::iterator lyxstring::erase(iterator first, iterator last)
1310 TestlyxstringInvariant(this);
1312 erase(first - begin(), last - first);
1313 return begin(); // BUG
1317 /////////////////////////////////////
1318 // Conversion to C-style Strings
1319 /////////////////////////////////////
1321 lyxstring::value_type const * lyxstring::c_str() const
1323 rep->s[length()] = '\0';
1328 lyxstring::value_type const * lyxstring::data() const
1334 lyxstring::size_type lyxstring::copy(value_type * buf, size_type len, size_type pos) const
1337 TestlyxstringInvariant(this);
1339 register int nn = min(len, length() - pos);
1340 memcpy(buf, &(rep->s[pos]), nn);
1345 ////////////////////
1347 ////////////////////
1349 // Compare funcs should be verified.
1350 // Should we try to make them work with '\0' value_types?
1351 // An STL string can usually contain '\0' value_types.
1353 int lyxstring::compare(lyxstring const & str) const
1355 TestlyxstringInvariant(this);
1357 return compare(0, rep->sz, str.rep->s, str.rep->sz);
1361 int lyxstring::compare(value_type const * s) const
1364 TestlyxstringInvariant(this);
1366 return compare(0, rep->sz, s, (!s) ? 0 : strlen(s));
1370 int lyxstring::compare(size_type pos, size_type n, lyxstring const & str) const
1372 TestlyxstringInvariant(this);
1374 return compare(pos, n, str.rep->s, str.rep->sz);
1378 int lyxstring::compare(size_type pos, size_type n, lyxstring const & str,
1379 size_type pos2, size_type n2) const
1381 TestlyxstringInvariant(this);
1383 return compare(pos, n, str.rep->s + pos2, n2);
1387 int lyxstring::compare(size_type pos, size_type n, value_type const * s,
1390 Assert(s && (pos < rep->sz || pos == 0));
1391 TestlyxstringInvariant(this);
1393 if ((rep->sz == 0 || n == 0) && (!*s || n2 == 0)) return 0;
1395 // since n > n2, min(n,n2) == 0, c == 0 (stops segfault also)
1397 // remember that n can very well be a lot larger than rep->sz
1398 // so we have to ensure that n is no larger than rep->sz
1399 n = min(n, rep->sz);
1400 n2 = min(n2, strlen(s));
1402 return memcmp(&(rep->s[pos]), s, n);
1403 int c = memcmp(&(rep->s[pos]), s, min(n,n2));
1416 // i = index, n = length
1417 lyxstring lyxstring::substr(size_type i, size_type n) const
1419 Assert(i < rep->sz || i == 0);
1420 TestlyxstringInvariant(this);
1422 return lyxstring(*this, i, n);
1427 /////////////////////////////////////////////
1428 // String operators, non member functions
1429 /////////////////////////////////////////////
1431 bool operator==(lyxstring const & a, lyxstring const & b)
1433 return a.compare(b) == 0;
1437 bool operator==(lyxstring::value_type const * a, lyxstring const & b)
1440 return b.compare(a) == 0;
1444 bool operator==(lyxstring const & a, lyxstring::value_type const * b)
1447 return a.compare(b) == 0;
1451 bool operator!=(lyxstring const & a, lyxstring const & b)
1453 return a.compare(b) != 0;
1457 bool operator!=(lyxstring::value_type const * a, lyxstring const & b)
1460 return b.compare(a) != 0;
1464 bool operator!=(lyxstring const & a, lyxstring::value_type const * b)
1467 return a.compare(b) != 0;
1471 bool operator>(lyxstring const & a, lyxstring const & b)
1473 return a.compare(b) > 0;
1477 bool operator>(lyxstring::value_type const * a, lyxstring const & b)
1480 return b.compare(a) < 0; // since we reverse the parameters
1484 bool operator>(lyxstring const & a, lyxstring::value_type const * b)
1487 return a.compare(b) > 0;
1491 bool operator<(lyxstring const & a, lyxstring const & b)
1493 return a.compare(b) < 0;
1497 bool operator<(lyxstring::value_type const * a, lyxstring const & b)
1500 return b.compare(a) > 0; // since we reverse the parameters
1504 bool operator<(lyxstring const & a, lyxstring::value_type const * b)
1507 return a.compare(b) < 0;
1511 bool operator>=(lyxstring const & a, lyxstring const & b)
1513 return a.compare(b) >= 0;
1517 bool operator>=(lyxstring::value_type const * a, lyxstring const & b)
1520 return b.compare(a) <= 0; // since we reverse the parameters
1524 bool operator>=(lyxstring const & a, lyxstring::value_type const * b)
1527 return a.compare(b) >= 0;
1531 bool operator<=(lyxstring const & a, lyxstring const & b)
1533 return a.compare(b) <= 0;
1537 bool operator<=(lyxstring::value_type const * a, lyxstring const & b)
1540 return b.compare(a) >= 0; // since we reverse the parameters
1544 bool operator<=(lyxstring const & a, lyxstring::value_type const * b)
1547 return a.compare(b) <= 0;
1551 lyxstring operator+(lyxstring const & a, lyxstring const & b)
1559 lyxstring operator+(lyxstring::value_type const * a, lyxstring const & b)
1568 lyxstring operator+(lyxstring::value_type a, lyxstring const & b)
1577 lyxstring operator+(lyxstring const & a, lyxstring::value_type const * b)
1586 lyxstring operator+(lyxstring const & a, lyxstring::value_type b)
1595 istream & operator>>(istream & is, lyxstring & s)
1597 // very bad solution
1600 lyxstring tmp(nome);
1601 if (!tmp.empty()) s = tmp;
1605 ostream & operator<<(ostream & o, lyxstring const & s)
1607 return o.write(s.data(), s.length());
1610 istream & getline(istream & is, lyxstring & s,
1611 lyxstring::value_type delim)
1613 // very bad solution
1627 #endif /* USE_INCLUDED_STRING */