]> git.lyx.org Git - lyx.git/blob - src/support/lyxstring.h
make doc++ able to generate the source documentation for lyx
[lyx.git] / src / support / lyxstring.h
1 // -*- C++ -*-
2 /* This file is part of
3  * ======================================================
4  * 
5  *           LyX, The Document Processor
6  *       
7  *          Copyright 1995 Matthias Ettrich
8  *          Copyright 1995-2000 The LyX Team.
9  *
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         ///
445         lyxstring & replace(iterator i, iterator i2, const lyxstring & str);
446
447         ///
448         lyxstring & replace(iterator i, iterator i2,
449                           value_type const * p, size_type n);
450
451         ///
452         lyxstring & replace(iterator i, iterator i2, value_type const * p);
453
454         ///
455         lyxstring & replace(iterator i, iterator i2,
456                             size_type n , value_type c);
457
458         ///
459         lyxstring & replace(iterator i, iterator i2, iterator j, iterator j2);
460
461         ///
462         void swap(lyxstring & str);
463         
464         /// Erase n chars from position i.
465         lyxstring & erase(size_type i = 0, size_type n = npos);
466
467         ///
468         lyxstring & clear() {
469                 return erase(0, npos);
470         }
471
472         ///
473         iterator erase(iterator i);
474
475         ///
476         iterator erase(iterator first, iterator last);
477
478         /// 
479         value_type const * c_str() const;
480
481         /* Note that this is STL compilant, so you can not assume
482           that the returned array has a trailing '\0'. */
483         value_type const * data() const;
484
485         /* This one returns a verbatim copy. Not the trailing '\0'
486           The caller must provide a buffer with engough room.
487           */
488         size_type copy(value_type * buf, size_type len,
489                        size_type pos = 0) const;
490
491         
492         ///
493         int compare(lyxstring const & str) const; 
494
495         ///
496         int compare(value_type const * p) const;
497
498         ///
499         int compare(size_type pos, size_type n, lyxstring const & str) const;
500
501         ///
502         int compare(size_type pos, size_type n, lyxstring const & str,
503                     size_type pos2, size_type n2) const;
504
505         ///
506         int compare(size_type pos, size_type n, value_type const * p,
507                     size_type n2 = npos) const;
508         
509         
510         ///
511         lyxstring substr(size_type i = 0, size_type n = npos) const;
512         
513 private:
514         // These three operators can be used to discover erronous use of
515         // ints and strings. However a conforming C++ compiler will flag
516         // a lot of char operations as ambigous when they are compiled
517         // in. Use them for debugging only (or perhaps not even then.)
518         // Lgb.
519         //
520         //lyxstring & operator+(int);
521         //
522         //lyxstring & operator=(int);
523         //
524         //lyxstring & operator+=(int);
525
526         /// Compare this with s. works with embedded '\0' chars also.
527         int internal_compare(size_type pos, size_type n,
528                              value_type const * s,
529                              size_type slen, size_type n2) const;
530                 
531         /// Forward declaration of the string representation
532         struct Srep;
533         // DEC cxx requires this.
534         friend struct Srep;
535
536         /// A string is a pointer to it's representation
537         Srep * rep;
538
539         /* Note: The empty_rep is a local static in each function that
540             benefits from one. There is no "global" empty srep but lyxstring
541             doesn't need one (no code actually relies upon a single
542             empty srep).
543             This overcomes *all* "static initialization" problems,
544             at maximum speed, with a small overhead of a few local static
545             empty_reps.
546         */
547
548 #ifdef ENABLE_ASSERTIONS
549         /// lyxstringInvariant is used to test the lyxstring Invariant
550         friend class lyxstringInvariant;
551 #endif
552 };
553
554 // The usual comparison operators ==, !=, >, <, >=, <= are
555 // provided for lyxstrings
556
557 bool operator==(lyxstring const &, lyxstring const &);
558 bool operator==(lyxstring::value_type const *, lyxstring const &);
559 bool operator==(lyxstring const &, lyxstring::value_type const *);
560
561
562 bool operator!=(lyxstring const &, lyxstring const &);
563 bool operator!=(lyxstring::value_type const *, lyxstring const &);
564 bool operator!=(lyxstring const &, lyxstring::value_type const *);
565
566
567 bool operator>(lyxstring const &, lyxstring const &);
568 bool operator>(lyxstring::value_type const *, lyxstring const &);
569 bool operator>(lyxstring const &, lyxstring::value_type const *);
570
571
572 bool operator<(lyxstring const &, lyxstring const &);
573 bool operator<(lyxstring::value_type const *, lyxstring const &);
574 bool operator<(lyxstring const &, lyxstring::value_type const *);
575
576
577 bool operator>=(lyxstring const &, lyxstring const &);
578 bool operator>=(lyxstring::value_type const *, lyxstring const &);
579 bool operator>=(lyxstring const &, lyxstring::value_type const *);
580
581
582 bool operator<=(lyxstring const &, lyxstring const &);
583 bool operator<=(lyxstring::value_type const *, lyxstring const &);
584 bool operator<=(lyxstring const &, lyxstring::value_type const *);
585
586
587 // Concatenation
588
589 lyxstring operator+(lyxstring const & a, lyxstring const & b);
590 lyxstring operator+(char const * a, lyxstring const & b);
591 lyxstring operator+(lyxstring::value_type a, lyxstring const & b);
592 lyxstring operator+(lyxstring const & a, lyxstring::value_type const * b);
593 lyxstring operator+(lyxstring const & a, lyxstring::value_type b);
594
595 void swap(lyxstring & s1, lyxstring & s2);
596
597 std::istream & operator>>(std::istream &, lyxstring &);
598 std::ostream & operator<<(std::ostream &, lyxstring const &);
599 std::istream & getline(std::istream &, lyxstring &, lyxstring::value_type delim = '\n');
600
601 #endif