2 /* This file is part of
3 * ======================================================
5 * LyX, The Document Processor
7 * Copyright 1995 Matthias Ettrich
8 * Copyright 1995-2000 The LyX Team.
10 * ====================================================== */
12 // This one is heavily based on the string class in The C++
13 // Programming Language by Bjarne Stroustrup
15 // This class is supposed to be functionaly equivalent to a
16 // standard conformant string. This mean among others that we
17 // are useing the same requirements. Before you change anything
18 // in this file consult me and/or the standard to discover the
34 #include <cstring> // for size_t
36 /** A string class for LyX
38 This is a permanent String class. It is modeled closely after the C++ STL
39 string class. In comparison with STL string lyxstring lack support for
40 reverse iterators and allocators, also char_traits is not used. In most
41 other senses it is written to be a drop in replacement for STL string
42 (or as a transition tool). So documentation for STL string should be
43 valid for lyxstring too.
47 When you declare an lyxstring, it is initially empty. There is no need to
48 do things like #lyxstring a= "";#, especially not in constructors.
50 If you want to use a default empty lyxstring as a parameter, use
52 #void foo(lyxstring par = lyxstring()); // Correct#
56 #void foo(lyxstring par = ""); // WRONG!#
57 #void foo(lyxstring par = 0); // WRONG!#
59 (The last one is only wrong because some compilers can't handle it.)
61 Methods that take an index as parameter all follow this rule: Valid indexes
62 go from 0 to length()-1.
64 Correct: & #foo.substring(0, length()-1);# \\
65 Wrong: & #bar.substring(0, length());#
68 It is important that you declare lyxstring as const if possible, because
69 some methods are much more efficient in const versions.
71 If you want to check whether a string is empty, do
73 #if (foo.empty()) something right#
75 rather than something along the lines of
77 #if (!foo) completely wrong#
79 When you want to copy an lyxstring, just do
81 #lyxstring a, b = "String";#
82 #a = b; // That's it!#
86 #lyxstring a, b = "String";#
87 #a = b.copy(); // This leaks. // and does not work either. #
89 The class automatically handles deep copying when required.
97 typedef char value_type;
100 typedef value_type * pointer;
103 typedef value_type & reference;
106 typedef value_type const & const_reference;
109 typedef size_t size_type;
112 typedef int difference_type;
115 typedef value_type * iterator;
117 typedef const value_type * const_iterator;
120 typedef reverse_iterator<iterator, value_type, reference>
123 typedef reverse_iterator<const_iterator, const value_type,
124 const_reference> const_reverse_iterator;
132 const_iterator begin() const;
136 const_iterator end() const;
139 reverse_iterator rbegin();
141 const_reverse_iterator rbegin() const;
143 reverse_iterator rend();
145 const_reverse_iterator rend() const;
147 /**@name Constructors and Deconstructors. lyxstring has the same
148 constructors as STL, except the one using iterators, one other
149 difference is that lyxstring, do not allow the optional allocator
153 /// "all characters" marker
154 static const size_type npos;
159 /// #lyxstring x(lyxstring ...)#
160 lyxstring(lyxstring const &, size_type pos = 0, size_type n = npos);
162 /// #lyxstring x("abc", 2) -> "ab"#
163 lyxstring(value_type const *, size_type n);
165 /// #lyxstring x("abc")#
167 lyxstring(value_type const *);
169 /// lyxstring(5, 'n') -> "nnnnn"
170 lyxstring(size_type n, value_type c);
174 lyxstring(const_iterator first, const_iterator last);
177 template<class InputIterator>
178 lyxstring::lyxstring(InputIterator begin, InputIterator end) {
179 while (begin != end) {
191 /**@name Size and Capacity */
194 /// number of characters
195 size_type size() const;
197 /// largest possible string
198 size_type max_size() const { return npos - 1; }
201 size_type length() const { return size(); }
204 bool empty() const { return size() == 0; }
207 void resize(size_type n, value_type c);
210 void resize(size_type n) { resize(n, ' '); }
212 /// size of the memory (in number of elements) allocated.
213 size_type capacity() const;
216 void reserve(size_type res_arg = 0);
220 /**@name Assignment */
224 lyxstring & operator=(lyxstring const &);
227 lyxstring & operator=(value_type const *);
230 lyxstring & operator=(value_type);
233 lyxstring & assign(lyxstring const &);
236 lyxstring & assign(lyxstring const &, size_type pos, size_type n);
239 lyxstring & assign(value_type const * p, size_type n);
242 lyxstring & assign(value_type const * p);
245 lyxstring & assign(size_type n, value_type c);
249 lyxstring & assign(const_iterator first, const_iterator last);
252 template<class InputIterator>
253 lyxstring & assign(InputIterator begin, InputIterator end) {
255 while (begin != end) {
263 /**@name Element Access. Since lyxstring does not use exceptions,
264 an abort is called on out-of-range access to at(). */
267 const_reference operator[](size_type) const;
270 reference operator[](size_type);
273 const_reference at(size_type) const;
276 reference at(size_type);
283 // add characters after (*this)[length()-1]:
286 lyxstring & operator+=(lyxstring const &);
289 lyxstring & operator+=(value_type const *);
292 lyxstring & operator+=(value_type);
295 void push_back(value_type);
298 lyxstring & append(lyxstring const &);
301 lyxstring & append(lyxstring const &, size_type pos, size_type n);
304 lyxstring & append(value_type const *, size_type n);
307 lyxstring & append(value_type const *);
310 lyxstring & append(size_type n, value_type);
314 lyxstring & append(iterator first, iterator last);
317 template<class InputIterator>
318 lyxstring & append(InputIterator begin, InputIterator end) {
319 while (begin != end) {
326 // insert characters before (*this)[pos]:
329 lyxstring & insert(size_type pos, lyxstring const &);
332 lyxstring & insert(size_type pos, lyxstring const &,
333 size_type pos2, size_type n);
336 lyxstring & insert(size_type pos, value_type const * p,
340 lyxstring & insert(size_type pos, value_type const * p);
343 lyxstring & insert(size_type pos, size_type n, value_type c);
345 // insert characters before p
348 iterator insert(iterator p, value_type c);
351 void insert(iterator p, size_type n , value_type c);
355 void insert(iterator p, iterator first, iterator last);
358 template<class InputIterator>
359 void insert(iterator p, InputIterator begin, InputIterator end) {
361 while (begin != end) {
362 it = insert(p, (*begin));
374 size_type find(lyxstring const &, size_type i = 0) const;
377 size_type find(value_type const * p,
378 size_type i, size_type n) const;
381 size_type find(value_type const * p, size_type i = 0) const;
384 size_type find(value_type c, size_type i = 0) const;
387 size_type rfind(lyxstring const &, size_type i = npos) const;
390 size_type rfind(value_type const * p, size_type i, size_type n) const;
393 size_type rfind(value_type const * p, size_type i = npos) const;
396 size_type rfind(value_type c, size_type i = npos) const;
399 size_type find_first_of(lyxstring const &, size_type i = 0) const;
402 size_type find_first_of(value_type const * p, size_type i,
406 size_type find_first_of(value_type const * p, size_type i = 0) const;
409 size_type find_first_of(value_type c, size_type i = 0) const;
412 size_type find_last_of(lyxstring const &, size_type i = npos) const;
415 size_type find_last_of(value_type const * p, size_type i,
419 size_type find_last_of(value_type const * p, size_type i = npos) const;
422 size_type find_last_of(value_type c, size_type i = npos) const;
425 size_type find_first_not_of(lyxstring const &, size_type i = 0) const;
428 size_type find_first_not_of(value_type const * p, size_type i,
432 size_type find_first_not_of(value_type const * p,
433 size_type i = 0) const;
436 size_type find_first_not_of(value_type c, size_type i = 0) const;
439 size_type find_last_not_of(lyxstring const &,
440 size_type i = npos) const;
443 size_type find_last_not_of(value_type const * p, size_type i,
447 size_type find_last_not_of(value_type const * p,
448 size_type i = npos) const;
451 size_type find_last_not_of(value_type c, size_type i = npos) const;
459 // replace [(*this)[i], (*this)[i+n]] with other characters:
462 lyxstring & replace(size_type i, size_type n, lyxstring const & str);
465 lyxstring & replace(size_type i, size_type n, lyxstring const & s,
466 size_type i2, size_type n2);
469 lyxstring & replace(size_type i, size_type n, value_type const * p,
473 lyxstring & replace(size_type i, size_type n, value_type const * p);
476 lyxstring & replace(size_type i, size_type n,
477 size_type n2, value_type c);
480 lyxstring & replace(iterator i, iterator i2, const lyxstring & str);
483 lyxstring & replace(iterator i, iterator i2,
484 value_type const * p, size_type n);
487 lyxstring & replace(iterator i, iterator i2, value_type const * p);
490 lyxstring & replace(iterator i, iterator i2,
491 size_type n , value_type c);
494 lyxstring & replace(iterator i, iterator i2, iterator j, iterator j2);
497 void swap(lyxstring & str);
499 /// Erase n chars from position i.
500 lyxstring & erase(size_type i = 0, size_type n = npos);
503 lyxstring & clear() {
504 return erase(0, npos);
508 iterator erase(iterator i);
511 iterator erase(iterator first, iterator last);
516 /**@name Conversion to C-style Strings */
520 value_type const * c_str() const;
522 /** Note that this is STL compilant, so you can not assume
523 that the returned array has a trailing '\0'. */
524 value_type const * data() const;
526 /** This one returns a verbatim copy. Not the trailing '\0'
527 The caller must provide a buffer with engough room.
529 size_type copy(value_type * buf, size_type len,
530 size_type pos = 0) const;
535 /**@name Comparisons. Combined > and == */
539 int compare(lyxstring const & str) const;
542 int compare(value_type const * p) const;
545 int compare(size_type pos, size_type n, lyxstring const & str) const;
548 int compare(size_type pos, size_type n, lyxstring const & str,
549 size_type pos2, size_type n2) const;
552 int compare(size_type pos, size_type n, value_type const * p,
553 size_type n2 = npos) const;
559 /**@name Substrings */
563 lyxstring substr(size_type i = 0, size_type n = npos) const;
568 // These three operators can be used to discover erronous use of
569 // ints and strings. However a conforming C++ compiler will flag
570 // a lot of char operations as ambigous when they are compiled
571 // in. Use them for debugging only (or perhaps not even then.)
574 //lyxstring & operator+(int);
576 //lyxstring & operator=(int);
578 //lyxstring & operator+=(int);
580 /// Compare this with s. works with embedded '\0' chars also.
581 int internal_compare(size_type pos, size_type n,
582 value_type const * s,
583 size_type slen, size_type n2) const;
585 /// Forward declaration of the string representation
587 // DEC cxx requires this.
590 /// A string is a pointer to it's representation
593 /** Note: The empty_rep is a local static in each function that
594 benefits from one. There is no "global" empty srep but lyxstring
595 doesn't need one (no code actually relies upon a single
597 This overcomes *all* "static initialization" problems,
598 at maximum speed, with a small overhead of a few local static
602 #ifdef ENABLE_ASSERTIONS
603 /// lyxstringInvariant is used to test the lyxstring Invariant
604 friend class lyxstringInvariant;
608 // The usual comparison operators ==, !=, >, <, >=, <= are
609 // provided for lyxstrings
611 bool operator==(lyxstring const &, lyxstring const &);
612 bool operator==(lyxstring::value_type const *, lyxstring const &);
613 bool operator==(lyxstring const &, lyxstring::value_type const *);
616 bool operator!=(lyxstring const &, lyxstring const &);
617 bool operator!=(lyxstring::value_type const *, lyxstring const &);
618 bool operator!=(lyxstring const &, lyxstring::value_type const *);
621 bool operator>(lyxstring const &, lyxstring const &);
622 bool operator>(lyxstring::value_type const *, lyxstring const &);
623 bool operator>(lyxstring const &, lyxstring::value_type const *);
626 bool operator<(lyxstring const &, lyxstring const &);
627 bool operator<(lyxstring::value_type const *, lyxstring const &);
628 bool operator<(lyxstring const &, lyxstring::value_type const *);
631 bool operator>=(lyxstring const &, lyxstring const &);
632 bool operator>=(lyxstring::value_type const *, lyxstring const &);
633 bool operator>=(lyxstring const &, lyxstring::value_type const *);
636 bool operator<=(lyxstring const &, lyxstring const &);
637 bool operator<=(lyxstring::value_type const *, lyxstring const &);
638 bool operator<=(lyxstring const &, lyxstring::value_type const *);
643 lyxstring operator+(lyxstring const & a, lyxstring const & b);
644 lyxstring operator+(char const * a, lyxstring const & b);
645 lyxstring operator+(lyxstring::value_type a, lyxstring const & b);
646 lyxstring operator+(lyxstring const & a, lyxstring::value_type const * b);
647 lyxstring operator+(lyxstring const & a, lyxstring::value_type b);
649 void swap(lyxstring & s1, lyxstring & s2);
651 std::istream & operator>>(std::istream &, lyxstring &);
652 std::ostream & operator<<(std::ostream &, lyxstring const &);
653 std::istream & getline(std::istream &, lyxstring &, lyxstring::value_type delim = '\n');