]> git.lyx.org Git - lyx.git/blob - src/support/lyxstring.h
some using changes small changes in lyxfont and some other things, read the Changelog
[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         /**@name Typedefs */
94         //@{
95         
96         ///
97         typedef char value_type;
98
99         ///
100         typedef value_type * pointer;
101
102         ///
103         typedef value_type & reference;
104
105         ///
106         typedef value_type const & const_reference;
107
108         ///
109         typedef size_t size_type;
110
111         ///
112         typedef int difference_type;
113
114         ///
115         typedef value_type * iterator;
116         ///
117         typedef const value_type * const_iterator;
118 #if 0
119         ///
120         typedef reverse_iterator<iterator, value_type, reference>
121         reverse_iterator;
122         ///
123         typedef reverse_iterator<const_iterator, const value_type,
124                 const_reference> const_reverse_iterator;
125
126 #endif
127         //@}
128
129         ///
130         iterator begin();
131         ///
132         const_iterator begin() const;
133         ///
134         iterator end();
135         ///
136         const_iterator end() const;
137 #if 0
138         ///
139         reverse_iterator rbegin();
140         ///
141         const_reverse_iterator rbegin() const;
142         ///
143         reverse_iterator rend();
144         ///
145         const_reverse_iterator rend() const;
146 #endif
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
150           parameter. */
151         //@{
152         
153         /// "all characters" marker
154         static const size_type npos;
155
156         /// #lyxstring x;# 
157         lyxstring();
158         
159         /// #lyxstring x(lyxstring ...)# 
160         lyxstring(lyxstring const &, size_type pos = 0, size_type n = npos);
161         
162         /// #lyxstring x("abc", 2) -> "ab"#
163         lyxstring(value_type const *, size_type n);
164         
165         /// #lyxstring x("abc")#
166         lyxstring(value_type const *);
167         
168         /// lyxstring(5, 'n') -> "nnnnn"
169         lyxstring(size_type n, value_type c);
170
171 #if 1
172         ///
173         lyxstring(const_iterator first, const_iterator last);
174 #else
175         ///
176         template<class InputIterator>
177         lyxstring::lyxstring(InputIterator begin, InputIterator end) {
178                 while (begin != end) {
179                         push_back((*begin));
180                         ++begin;
181                 }
182         }
183 #endif
184         ///
185         ~lyxstring();
186
187         //@}
188
189         
190         /**@name Size and Capacity */
191         //@{
192         
193         /// number of characters
194         size_type size() const;
195
196         /// largest possible string
197         size_type max_size() const { return npos - 1; }
198
199         ///
200         size_type length() const { return size(); }
201
202         ///
203         bool empty() const { return size() == 0; }
204
205         ///
206         void resize(size_type n, value_type c);
207
208         ///
209         void resize(size_type n) { resize(n, ' '); }
210
211         /// size of the memory (in number of elements) allocated.
212         size_type capacity() const;
213
214         ///
215         void reserve(size_type res_arg = 0);
216         
217         //@}
218
219         /**@name Assignment */
220         //@{
221
222         ///
223         lyxstring & operator=(lyxstring const &);
224         
225         ///
226         lyxstring & operator=(value_type const *);
227         
228         ///
229         lyxstring & operator=(value_type);
230
231         ///
232         lyxstring & assign(lyxstring const &);
233         
234         ///
235         lyxstring & assign(lyxstring const &, size_type pos, size_type n);
236         
237         ///
238         lyxstring & assign(value_type const * p, size_type n);
239         
240         ///
241         lyxstring & assign(value_type const * p);
242         
243         ///
244         lyxstring & assign(size_type n, value_type c);
245
246 #if 1
247         ///
248         lyxstring & assign(const_iterator first, const_iterator last);
249 #else
250         ///
251         template<class InputIterator>
252         lyxstring & assign(InputIterator begin, InputIterator end) {
253                 clear;
254                 while (begin != end) {
255                         push_back((*begin));
256                         ++begin;
257                 }
258         }
259 #endif
260         //@}
261
262         /**@name Element Access. Since lyxstring does not use exceptions,
263           an abort is called on out-of-range access to at(). */
264         
265         /// unchecked access
266         const_reference operator[](size_type) const;
267         
268         /// unchecked access
269         reference operator[](size_type);
270         
271         /// checked access
272         const_reference at(size_type) const;
273         
274         /// checked access
275         reference at(size_type);
276
277         //@}
278
279         /**@name Insert */
280         //@{
281         
282         // add characters after (*this)[length()-1]:
283         
284         ///
285         lyxstring & operator+=(lyxstring const &);
286         
287         ///
288         lyxstring & operator+=(value_type const *);
289         
290         ///
291         lyxstring & operator+=(value_type);
292
293         ///
294         void push_back(value_type);
295
296         ///
297         lyxstring & append(lyxstring const &);
298
299         ///
300         lyxstring & append(lyxstring const &, size_type pos, size_type n);
301
302         ///
303         lyxstring & append(value_type const *, size_type n);
304
305         ///
306         lyxstring & append(value_type const *);
307
308         ///
309         lyxstring & append(size_type n, value_type);
310
311 #if 1
312         ///
313         lyxstring & append(iterator first, iterator last);
314 #else
315         ///
316         template<class InputIterator>
317         lyxstring & append(InputIterator begin, InputIterator end) {
318                 while (begin != end) {
319                         push_back((*begin));
320                         ++begin;
321                 }
322                 return *this;
323         }
324 #endif
325         // insert characters before (*this)[pos]:
326
327         ///
328         lyxstring & insert(size_type pos, lyxstring const &);
329         
330         ///
331         lyxstring & insert(size_type pos, lyxstring const &,
332                         size_type pos2, size_type n);
333         
334         ///
335         lyxstring & insert(size_type pos, value_type const * p,
336                          size_type n);
337
338         ///
339         lyxstring & insert(size_type pos, value_type const * p);
340
341         ///
342         lyxstring & insert(size_type pos, size_type n, value_type c);
343
344         // insert characters before p
345
346         ///
347         iterator insert(iterator p, value_type c);
348
349         ///
350         void insert(iterator p, size_type n , value_type c);
351
352 #if 1
353         ///
354         void insert(iterator p, iterator first, iterator last);
355 #else
356         ///
357         template<class InputIterator>
358         void insert(iterator p, InputIterator begin, InputIterator end) {
359                 iterator it;
360                 while (begin != end) {
361                         it = insert(p, (*begin));
362                         ++begin;
363                 }
364         }
365 #endif
366         
367         //@}
368
369         /**@name Find */
370         //@{
371
372         ///
373         size_type find(lyxstring const &, size_type i = 0) const;
374         
375         ///
376         size_type find(value_type const * p,
377                          size_type i, size_type n) const;
378         
379         ///
380         size_type find(value_type const * p, size_type i = 0) const;
381         
382         ///
383         size_type find(value_type c, size_type i = 0) const;
384
385         ///
386         size_type rfind(lyxstring const &, size_type i = npos) const;
387         
388         ///
389         size_type rfind(value_type const * p, size_type i, size_type n) const;
390         
391         ///
392         size_type rfind(value_type const * p, size_type i = npos) const;
393         
394         ///
395         size_type rfind(value_type c, size_type i = npos) const;
396
397         ///
398         size_type find_first_of(lyxstring const &, size_type i = 0) const;
399         
400         ///
401         size_type find_first_of(value_type const * p, size_type i,
402                                 size_type n) const;
403         
404         ///
405         size_type find_first_of(value_type const * p, size_type i = 0) const;
406         
407         ///
408         size_type find_first_of(value_type c, size_type i = 0) const;
409
410         ///
411         size_type find_last_of(lyxstring const &, size_type i = npos) const;
412         
413         ///
414         size_type find_last_of(value_type const * p, size_type i,
415                                size_type n) const;
416         
417         ///
418         size_type find_last_of(value_type const * p, size_type i = npos) const;
419         
420         ///
421         size_type find_last_of(value_type c, size_type i = npos) const;
422
423         ///
424         size_type find_first_not_of(lyxstring const &, size_type i = 0) const;
425         
426         ///
427         size_type find_first_not_of(value_type const * p, size_type i,
428                                     size_type n) const;
429         
430         ///
431         size_type find_first_not_of(value_type const * p,
432                                     size_type i = 0) const;
433         
434         ///
435         size_type find_first_not_of(value_type c, size_type i = 0) const;
436
437         ///
438         size_type find_last_not_of(lyxstring const &,
439                                    size_type i = npos) const;
440         
441         ///
442         size_type find_last_not_of(value_type const * p, size_type i,
443                                    size_type n) const;
444         
445         ///
446         size_type find_last_not_of(value_type const * p,
447                                    size_type i = npos) const;
448         
449         ///
450         size_type find_last_not_of(value_type c, size_type i = npos) const;
451
452         //*}
453
454         
455         /**@name Replace */
456         //@{
457
458         // replace [(*this)[i], (*this)[i+n]] with other characters:
459
460         ///
461         lyxstring & replace(size_type i, size_type n, lyxstring const & str);
462
463         ///
464         lyxstring & replace(size_type i, size_type n, lyxstring const & s,
465                           size_type i2, size_type n2);
466
467         ///
468         lyxstring & replace(size_type i, size_type n, value_type const * p,
469                           size_type n2);
470
471         ///
472         lyxstring & replace(size_type i, size_type n, value_type const * p);
473
474         ///
475         lyxstring & replace(size_type i, size_type n,
476                             size_type n2, value_type c);
477
478         ///
479         lyxstring & replace(iterator i, iterator i2, const lyxstring & str);
480
481         ///
482         lyxstring & replace(iterator i, iterator i2,
483                           value_type const * p, size_type n);
484
485         ///
486         lyxstring & replace(iterator i, iterator i2, value_type const * p);
487
488         ///
489         lyxstring & replace(iterator i, iterator i2,
490                             size_type n , value_type c);
491
492         ///
493         lyxstring & replace(iterator i, iterator i2, iterator j, iterator j2);
494
495         ///
496         void swap(lyxstring & str);
497         
498         /// Erase n chars from position i.
499         lyxstring & erase(size_type i = 0, size_type n = npos);
500
501         ///
502         lyxstring & clear() {
503                 return erase(0, npos);
504         }
505
506         ///
507         iterator erase(iterator i);
508
509         ///
510         iterator erase(iterator first, iterator last);
511
512         //@}
513
514         
515         /**@name Conversion to C-style Strings */
516         //@{
517         
518         /// 
519         value_type const * c_str() const;
520
521         /** Note that this is STL compilant, so you can not assume
522           that the returned array has a trailing '\0'. */
523         value_type const * data() const;
524
525         /** This one returns a verbatim copy. Not the trailing '\0'
526           The caller must provide a buffer with engough room.
527           */
528         size_type copy(value_type * buf, size_type len,
529                        size_type pos = 0) const;
530
531         //@}
532
533         
534         /**@name Comparisons. Combined > and == */
535         //@{
536         
537         ///
538         int compare(lyxstring const & str) const; 
539
540         ///
541         int compare(value_type const * p) const;
542
543         ///
544         int compare(size_type pos, size_type n, lyxstring const & str) const;
545
546         ///
547         int compare(size_type pos, size_type n, lyxstring const & str,
548                     size_type pos2, size_type n2) const;
549
550         ///
551         int compare(size_type pos, size_type n, value_type const * p,
552                     size_type n2 = npos) const;
553         
554         //@}
555
556         
557         
558         /**@name Substrings */
559         //@{
560
561         ///
562         lyxstring substr(size_type i = 0, size_type n = npos) const;
563         
564         //@}
565
566 private:
567         // These three operators can be used to discover erronous use of
568         // ints and strings. However a conforming C++ compiler will flag
569         // a lot of char operations as ambigous when they are compiled
570         // in. Use them for debugging only (or perhaps not even then.)
571         // Lgb.
572         //
573         //lyxstring & operator+(int);
574         //
575         //lyxstring & operator=(int);
576         //
577         //lyxstring & operator+=(int);
578
579         /// Compare this with s. works with embedded '\0' chars also.
580         int internal_compare(size_type pos, size_type n,
581                              value_type const * s,
582                              size_type slen, size_type n2) const;
583                 
584         /// Forward declaration of the string representation
585         struct Srep;
586         // DEC cxx requires this.
587         friend struct Srep;
588
589         /// A string is a pointer to it's representation
590         Srep * rep;
591
592         /** Note: The empty_rep is a local static in each function that
593             benefits from one. There is no "global" empty srep but lyxstring
594             doesn't need one (no code actually relies upon a single
595             empty srep).
596             This overcomes *all* "static initialization" problems,
597             at maximum speed, with a small overhead of a few local static
598             empty_reps.
599         */
600
601 #ifdef ENABLE_ASSERTIONS
602         /// lyxstringInvariant is used to test the lyxstring Invariant
603         friend class lyxstringInvariant;
604 #endif
605 };
606
607 // The usual comparison operators ==, !=, >, <, >=, <= are
608 // provided for lyxstrings
609
610 bool operator==(lyxstring const &, lyxstring const &);
611 bool operator==(lyxstring::value_type const *, lyxstring const &);
612 bool operator==(lyxstring const &, lyxstring::value_type const *);
613
614
615 bool operator!=(lyxstring const &, lyxstring const &);
616 bool operator!=(lyxstring::value_type const *, lyxstring const &);
617 bool operator!=(lyxstring const &, lyxstring::value_type const *);
618
619
620 bool operator>(lyxstring const &, lyxstring const &);
621 bool operator>(lyxstring::value_type const *, lyxstring const &);
622 bool operator>(lyxstring const &, lyxstring::value_type const *);
623
624
625 bool operator<(lyxstring const &, lyxstring const &);
626 bool operator<(lyxstring::value_type const *, lyxstring const &);
627 bool operator<(lyxstring const &, lyxstring::value_type const *);
628
629
630 bool operator>=(lyxstring const &, lyxstring const &);
631 bool operator>=(lyxstring::value_type const *, lyxstring const &);
632 bool operator>=(lyxstring const &, lyxstring::value_type const *);
633
634
635 bool operator<=(lyxstring const &, lyxstring const &);
636 bool operator<=(lyxstring::value_type const *, lyxstring const &);
637 bool operator<=(lyxstring const &, lyxstring::value_type const *);
638
639
640 // Concatenation
641
642 lyxstring operator+(lyxstring const & a, lyxstring const & b);
643 lyxstring operator+(char const * a, lyxstring const & b);
644 lyxstring operator+(lyxstring::value_type a, lyxstring const & b);
645 lyxstring operator+(lyxstring const & a, lyxstring::value_type const * b);
646 lyxstring operator+(lyxstring const & a, lyxstring::value_type b);
647
648 void swap(lyxstring & s1, lyxstring & s2);
649
650 istream & operator>>(istream &, lyxstring &);
651 ostream & operator<<(ostream &, lyxstring const &);
652 istream & getline(istream &, lyxstring &, lyxstring::value_type delim = '\n');
653
654 #endif