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