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