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