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