]> git.lyx.org Git - lyx.git/blob - src/support/lyxstring.h
split LyXText::rowlist_ into individual Paragraph::rows_ chunks
[lyx.git] / src / support / lyxstring.h
1 // -*- C++ -*-
2 /**
3  * \file lyxstring.h
4  * This file is part of LyX, the document processor.
5  * Licence details can be found in the file COPYING.
6  *
7  * \author Lars Gullik Bjønnes
8  *
9  * Full author contact details are available in file CREDITS
10  */
11
12 // This one is heavily based on the string class in The C++
13 // Programming Language by Bjarne Stroustrup
14
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
19 // right behavior.
20
21 #ifndef LYXSTRING_H
22 #define LYXSTRING_H
23
24 #include <iosfwd>
25
26 #if 0
27 #include <iterator>
28 #endif
29
30 #include <cstring> // for size_t
31
32 namespace lyx {
33
34 /** A string class for LyX
35
36   This is a permanent String class. It is modeled closely after the C++ STL
37   string class. In comparison with STL string lyxstring lack support for
38   reverse iterators and allocators, also char_traits is not used. In most
39   other senses it is written to be  a drop in replacement for STL string
40   (or as a transition tool). So documentation for STL string should be
41   valid for lyxstring too.
42
43   Notes for usage:
44
45   When you declare an lyxstring, it is initially empty. There is no need to
46   do things like #lyxstring a= "";#, especially not in constructors.
47
48   If you want to use a default empty lyxstring as a parameter, use
49
50         #void foo(lyxstring par = lyxstring()); // Correct#
51
52   rather than
53
54         #void foo(lyxstring par = "");  // WRONG!#
55         #void foo(lyxstring par = 0);   // WRONG!#
56
57   (The last one is only wrong because some compilers can't handle it.)
58
59   Methods that take an index as parameter all follow this rule: Valid indexes
60   go from 0 to length()-1.
61   \begin{tabular}{rl}
62   Correct: & #foo.substring(0, length()-1);# \\
63   Wrong:   & #bar.substring(0, length());#
64   \end{tabular}
65
66   It is important that you declare lyxstring as const if possible, because
67   some methods are much more efficient in const versions.
68
69   If you want to check whether a string is empty, do
70
71         #if (foo.empty()) something right#
72
73   rather than something along the lines of
74
75         #if (!foo) completely wrong#
76
77 When you want to copy an lyxstring, just do
78
79         #lyxstring a, b = "String";#
80         #a = b; // That's it!#
81
82   not something like
83
84         #lyxstring a, b = "String";#
85         #a = b.copy(); // This leaks. // and does not work either. #
86
87   The class automatically handles deep copying when required.
88 */
89 class string {
90 public:
91         /* Typedefs */
92
93         ///
94         typedef char value_type;
95
96         ///
97         typedef value_type * pointer;
98
99         ///
100         typedef value_type & reference;
101
102         ///
103         typedef value_type const & const_reference;
104
105         ///
106         typedef size_t size_type;
107
108         ///
109         typedef int difference_type;
110
111         ///
112         typedef value_type * iterator;
113         ///
114         typedef const value_type * const_iterator;
115 #if 0
116         ///
117         typedef reverse_iterator<iterator, value_type, reference>
118         reverse_iterator;
119         ///
120         typedef reverse_iterator<const_iterator, const value_type,
121                 const_reference> const_reverse_iterator;
122
123 #endif
124
125         ///
126         iterator begin();
127         ///
128         const_iterator begin() const;
129         ///
130         iterator end();
131         ///
132         const_iterator end() const;
133 #if 0
134         ///
135         reverse_iterator rbegin();
136         ///
137         const_reverse_iterator rbegin() const;
138         ///
139         reverse_iterator rend();
140         ///
141         const_reverse_iterator rend() const;
142 #endif
143         /* Constructors and Deconstructors. lyxstring has the same
144           constructors as STL, except the one using iterators, one other
145           difference is that lyxstring, do not allow the optional allocator
146           parameter. */
147
148         /// "all characters" marker
149         static const size_type npos;
150
151         /// #string x;#
152         string();
153
154         /// #string x(string ...)#
155         string(string const &, size_type pos = 0, size_type n = npos);
156
157         /// #string x("abc", 2) -> "ab"#
158         string(value_type const *, size_type n);
159
160         // #string x("abc")#
161         string(value_type const *);
162
163         /// string(5, 'n') -> "nnnnn"
164         string(size_type n, value_type c);
165
166 #if 0
167         ///
168         string(const_iterator first, const_iterator last);
169 #else
170         ///
171         template<class InputIterator>
172         string(InputIterator begin, InputIterator end) {
173                 while (begin != end) {
174                         push_back(*begin);
175                         ++begin;
176                 }
177         }
178 #endif
179         ///
180         ~string();
181
182         /// number of characters
183         size_type size() const;
184
185         /// largest possible string
186         size_type max_size() const { return npos - 1; }
187
188         ///
189         size_type length() const { return size(); }
190
191         ///
192         bool empty() const { return size() == 0; }
193
194         ///
195         void resize(size_type n, value_type c);
196
197         ///
198         void resize(size_type n) { resize(n, ' '); }
199
200         /// size of the memory (in number of elements) allocated.
201         size_type capacity() const;
202
203         ///
204         void reserve(size_type res_arg = 0);
205
206         ///
207         string & operator=(string const &);
208
209         ///
210         string & operator=(value_type const *);
211
212         ///
213         string & operator=(value_type);
214
215         ///
216         string & assign(string const &);
217
218         ///
219         string & assign(string const &, size_type pos, size_type n);
220
221         ///
222         string & assign(value_type const * p, size_type n);
223
224         ///
225         string & assign(value_type const * p);
226
227         ///
228         string & assign(size_type n, value_type c);
229
230 #if 1
231         ///
232         string & assign(const_iterator first, const_iterator last);
233 #else
234         ///
235         template<class InputIterator>
236         string & assign(InputIterator begin, InputIterator end) {
237                 clear;
238                 while (begin != end) {
239                         push_back((*begin));
240                         ++begin;
241                 }
242         }
243 #endif
244
245         /// unchecked access
246         const_reference operator[](size_type) const;
247
248         /// unchecked access
249         reference operator[](size_type);
250
251         /// checked access
252         const_reference at(size_type) const;
253
254         /// checked access
255         reference at(size_type);
256
257         // add characters after (*this)[length()-1]:
258
259         ///
260         string & operator+=(string const &);
261
262         ///
263         string & operator+=(value_type const *);
264
265         ///
266         string & operator+=(value_type);
267
268         ///
269         void push_back(value_type);
270
271         ///
272         string & append(string const &);
273
274         ///
275         string & append(string const &, size_type pos, size_type n);
276
277         ///
278         string & append(value_type const *, size_type n);
279
280         ///
281         string & append(value_type const *);
282
283         ///
284         string & append(size_type n, value_type);
285
286 #if 1
287         ///
288         string & append(iterator first, iterator last);
289 #else
290         ///
291         template<class InputIterator>
292         string & append(InputIterator begin, InputIterator end) {
293                 while (begin != end) {
294                         push_back((*begin));
295                         ++begin;
296                 }
297                 return *this;
298         }
299 #endif
300         // insert characters before (*this)[pos]:
301
302         ///
303         string & insert(size_type pos, string const &);
304
305         ///
306         string & insert(size_type pos, string const &,
307                         size_type pos2, size_type n);
308
309         ///
310         string & insert(size_type pos, value_type const * p,
311                          size_type n);
312
313         ///
314         string & insert(size_type pos, value_type const * p);
315
316         ///
317         string & insert(size_type pos, size_type n, value_type c);
318
319         // insert characters before p
320
321         ///
322         iterator insert(iterator p, value_type c);
323
324         ///
325         void insert(iterator p, size_type n , value_type c);
326
327 #if 1
328         ///
329         void insert(iterator p, iterator first, iterator last);
330 #else
331         ///
332         template<class InputIterator>
333         void insert(iterator p, InputIterator begin, InputIterator end) {
334                 iterator it;
335                 while (begin != end) {
336                         it = insert(p, (*begin));
337                         ++begin;
338                 }
339         }
340 #endif
341
342         ///
343         size_type find(string const &, size_type i = 0) const;
344
345         ///
346         size_type find(value_type const * p,
347                          size_type i, size_type n) const;
348
349         ///
350         size_type find(value_type const * p, size_type i = 0) const;
351
352         ///
353         size_type find(value_type c, size_type i = 0) const;
354
355         ///
356         size_type rfind(string const &, size_type i = npos) const;
357
358         ///
359         size_type rfind(value_type const * p, size_type i, size_type n) const;
360
361         ///
362         size_type rfind(value_type const * p, size_type i = npos) const;
363
364         ///
365         size_type rfind(value_type c, size_type i = npos) const;
366
367         ///
368         size_type find_first_of(string const &, size_type i = 0) const;
369
370         ///
371         size_type find_first_of(value_type const * p, size_type i,
372                                 size_type n) const;
373
374         ///
375         size_type find_first_of(value_type const * p, size_type i = 0) const;
376
377         ///
378         size_type find_first_of(value_type c, size_type i = 0) const;
379
380         ///
381         size_type find_last_of(string const &, size_type i = npos) const;
382
383         ///
384         size_type find_last_of(value_type const * p, size_type i,
385                                size_type n) const;
386
387         ///
388         size_type find_last_of(value_type const * p, size_type i = npos) const;
389
390         ///
391         size_type find_last_of(value_type c, size_type i = npos) const;
392
393         ///
394         size_type find_first_not_of(string const &, size_type i = 0) const;
395
396         ///
397         size_type find_first_not_of(value_type const * p, size_type i,
398                                     size_type n) const;
399
400         ///
401         size_type find_first_not_of(value_type const * p,
402                                     size_type i = 0) const;
403
404         ///
405         size_type find_first_not_of(value_type c, size_type i = 0) const;
406
407         ///
408         size_type find_last_not_of(string const &,
409                                    size_type i = npos) const;
410
411         ///
412         size_type find_last_not_of(value_type const * p, size_type i,
413                                    size_type n) const;
414
415         ///
416         size_type find_last_not_of(value_type const * p,
417                                    size_type i = npos) const;
418
419         ///
420         size_type find_last_not_of(value_type c, size_type i = npos) const;
421
422         // replace [(*this)[i], (*this)[i+n]] with other characters:
423
424         ///
425         string & replace(size_type i, size_type n, string const & str);
426
427         ///
428         string & replace(size_type i, size_type n, string const & s,
429                           size_type i2, size_type n2);
430
431         ///
432         string & replace(size_type i, size_type n, value_type const * p,
433                           size_type n2);
434
435         ///
436         string & replace(size_type i, size_type n, value_type const * p);
437
438         ///
439         string & replace(size_type i, size_type n,
440                             size_type n2, value_type c);
441
442         /// FY! FY! FY! go away !
443         string & replace(size_type i, size_type n,
444                             value_type c);
445
446         ///
447         string & replace(iterator i, iterator i2, const string & str);
448
449         ///
450         string & replace(iterator i, iterator i2,
451                           value_type const * p, size_type n);
452
453         ///
454         string & replace(iterator i, iterator i2, value_type const * p);
455
456         ///
457         string & replace(iterator i, iterator i2,
458                             size_type n , value_type c);
459
460         ///
461         string & replace(iterator i, iterator i2, iterator j, iterator j2);
462
463         ///
464         void swap(string & str);
465
466         /// Erase n chars from position i.
467         string & erase(size_type i = 0, size_type n = npos);
468
469         ///
470         string & clear() {
471                 return erase(0, npos);
472         }
473
474         ///
475         iterator erase(iterator i);
476
477         ///
478         iterator erase(iterator first, iterator last);
479
480         ///
481         value_type const * c_str() const;
482
483         /* Note that this is STL compilant, so you can not assume
484           that the returned array has a trailing '\0'. */
485         value_type const * data() const;
486
487         /* This one returns a verbatim copy. Not the trailing '\0'
488           The caller must provide a buffer with engough room.
489           */
490         size_type copy(value_type * buf, size_type len,
491                        size_type pos = 0) const;
492
493
494         ///
495         int compare(string const & str) const;
496
497         ///
498         int compare(value_type const * p) const;
499
500         ///
501         int compare(size_type pos, size_type n, string const & str) const;
502
503         ///
504         int compare(size_type pos, size_type n, string const & str,
505                     size_type pos2, size_type n2) const;
506
507         ///
508         int compare(size_type pos, size_type n, value_type const * p,
509                     size_type n2 = npos) const;
510
511
512         ///
513         string substr(size_type i = 0, size_type n = npos) const;
514
515 private:
516         // These three operators can be used to discover erronous use of
517         // ints and strings. However a conforming C++ compiler will flag
518         // a lot of char operations as ambigous when they are compiled
519         // in. Use them for debugging only (or perhaps not even then.)
520         // Lgb.
521         //
522         //string & operator+(int);
523         //
524         //string & operator=(int);
525         //
526         //string & operator+=(int);
527
528         /// Compare this with s. works with embedded '\0' chars also.
529         int internal_compare(size_type pos, size_type n,
530                              value_type const * s,
531                              size_type slen, size_type n2) const;
532
533         /// Forward declaration of the string representation
534         struct Srep;
535         // DEC cxx requires this.
536         friend struct Srep;
537
538         /// A string is a pointer to it's representation
539         Srep * rep;
540
541         /* Note: The empty_rep is a local static in each function that
542             benefits from one. There is no "global" empty srep but string
543             doesn't need one (no code actually relies upon a single
544             empty srep).
545             This overcomes *all* "static initialization" problems,
546             at maximum speed, with a small overhead of a few local static
547             empty_reps.
548         */
549
550 #ifdef ENABLE_ASSERTIONS
551         /// lyxstringInvariant is used to test the lyxstring Invariant
552         friend class stringInvariant;
553 #endif
554 };
555
556 // The usual comparison operators ==, !=, >, <, >=, <= are
557 // provided for lyxstrings
558
559 bool operator==(string const &, string const &);
560 bool operator==(string::value_type const *, string const &);
561 bool operator==(string const &, string::value_type const *);
562
563
564 bool operator!=(string const &, string const &);
565 bool operator!=(string::value_type const *, string const &);
566 bool operator!=(string const &, string::value_type const *);
567
568
569 bool operator>(string const &, string const &);
570 bool operator>(string::value_type const *, string const &);
571 bool operator>(string const &, string::value_type const *);
572
573
574 bool operator<(string const &, string const &);
575 bool operator<(string::value_type const *, string const &);
576 bool operator<(string const &, string::value_type const *);
577
578
579 bool operator>=(string const &, string const &);
580 bool operator>=(string::value_type const *, string const &);
581 bool operator>=(string const &, string::value_type const *);
582
583
584 bool operator<=(string const &, string const &);
585 bool operator<=(string::value_type const *, string const &);
586 bool operator<=(string const &, string::value_type const *);
587
588
589 // Concatenation
590
591 string operator+(string const & a, string const & b);
592 string operator+(char const * a, string const & b);
593 string operator+(string::value_type a, string const & b);
594 string operator+(string const & a, string::value_type const * b);
595 string operator+(string const & a, string::value_type b);
596
597 void swap(string & s1, string & s2);
598
599 std::istream & operator>>(std::istream &, string &);
600 std::ostream & operator<<(std::ostream &, string const &);
601 std::istream & getline(std::istream &, string &, string::value_type delim = '\n');
602
603 } // namespace lyx
604
605 #endif