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