1 //////////////////////////////////////////////////////////////////////////////
4 // ADLib, Prop and their related set of tools and documentation are in the
5 // public domain. The author(s) of this software reserve no copyrights on
6 // the source code and any code generated using the tools. You are encouraged
7 // to use ADLib and Prop to develop software, in both academic and commercial
8 // settings, and are free to incorporate any part of ADLib and Prop into
11 // Although you are under no obligation to do so, we strongly recommend that
12 // you give away all software developed using our tools.
14 // We also ask that credit be given to us when ADLib and/or Prop are used in
15 // your programs, and that this notice be preserved intact in all the source
18 // This software is still under development and we welcome any suggestions
19 // and help from the users.
23 //////////////////////////////////////////////////////////////////////////////
25 #ifndef variable_sized_string_h
26 #define variable_sized_string_h
28 /////////////////////////////////////////////////////////////////////////////
31 // Class |String| behaves very much like C's `char *' and can be
32 // used as such in most situations. It handles its own storage management.
33 // For compatibility with C style strings, class String keeps an extra
34 // nul character at the end. However, nul characters *are* allowed in
36 /////////////////////////////////////////////////////////////////////////////
40 #include <AD/generic/generic.h> // Generic definitions
42 ////////////////////////////////////////////////////////////////////////////
43 // The GNU C++ class library already has classes String and SubString.
44 // Xlib already has typedef String.
45 ////////////////////////////////////////////////////////////////////////////
46 #if defined(__GNUG__) || defined(X11)
47 # define String String_
48 # define SubString SubString_
49 # define StringImpl StringImpl_
52 ////////////////////////////////////////////////////////////////////////////
53 // Forward declarations.
54 ////////////////////////////////////////////////////////////////////////////
62 ////////////////////////////////////////////////////////////////////////////
63 // Class StringImpl, the actual implementation of a string.
64 // We use a simple reference counted, copy on write implementation.
65 ////////////////////////////////////////////////////////////////////////////
68 friend class SubString
;
69 unsigned long ref
; // reference count
70 size_t len
; // logical length
71 size_t capacity
; // actual capacity
72 char string
[1]; // actual data
73 void * operator new (size_t, size_t, size_t);
74 void operator delete (void *);
75 inline void dec_ref() { if (--ref
== 0) delete this; }
76 inline void inc_ref() { ++ref
; }
77 static StringImpl
* empty_string
;
78 static StringImpl
* make_empty_string();
82 ////////////////////////////////////////////////////////////////////////////
84 ////////////////////////////////////////////////////////////////////////////
86 { friend class String
;
87 StringImpl
* impl
; // the actual string implementation
88 size_t start
; // starting index
89 size_t len
; // logical length
91 SubString(StringImpl
*, size_t, size_t);
93 inline ~SubString() { if (--impl
->ref
== 0) delete impl
; }
95 ///////////////////////////////////////////////////////////////////////
97 ///////////////////////////////////////////////////////////////////////
98 operator String () const;
100 ///////////////////////////////////////////////////////////////////////
102 ///////////////////////////////////////////////////////////////////////
103 inline size_t length() const { return len
; }
104 inline size_t size() const { return len
; }
105 inline size_t capacity() const { return impl
->capacity
; }
106 inline Bool
is_empty() const { return len
== 0; }
107 inline Bool
is_full() const { return false; }
108 inline char operator [] (int i
) const { return impl
->string
[start
+i
]; }
109 inline char& operator [] (int i
) { return impl
->string
[start
+i
]; }
112 ////////////////////////////////////////////////////////////////////////////
114 ////////////////////////////////////////////////////////////////////////////
116 StringImpl
* impl
; // the actual string implementation
117 inline String(StringImpl
* s
) : impl(s
) {}
118 void copy_on_write(size_t extra
);
120 ///////////////////////////////////////////////////////////////////////
121 // Constructors and destructor
122 ///////////////////////////////////////////////////////////////////////
123 String(); // Make empty String
124 String(size_t initial_capacity
); // Make an uninitialized String
125 String(char c
, size_t times
= 1); // Make String initialized with c's
126 String(const char * s
, int l
= -1); // e.g. String = "abcde";
127 inline String(const String
& s
) // e.g. String s1 = s2;
128 : impl(s
.impl
) { impl
->inc_ref(); }
129 inline ~String() { impl
->dec_ref(); }
131 ///////////////////////////////////////////////////////////////////////
133 ///////////////////////////////////////////////////////////////////////
134 inline operator const char * () const { return impl
->string
; }
135 inline const char * str() const { return impl
->string
; }
137 ///////////////////////////////////////////////////////////////////////
139 ///////////////////////////////////////////////////////////////////////
140 inline String
& operator = (const String
& s
)
141 { if (this != &s
) { s
.impl
->inc_ref(); dec_ref(); impl
= s
.impl
; }
144 String
& operator = (const char *);
146 ///////////////////////////////////////////////////////////////////////
147 // Splice a new (sub)string into location:
148 // e.g. String S = "The quick brown fox";
149 // S.splice(4,5,"slow");
151 // S now becomes "The slow brown fox";
152 ///////////////////////////////////////////////////////////////////////
153 String
& splice(int location
, int len
, const char *, int size
= -1);
154 String
& splice(int location
, int len
, char c
, int size
= 1);
155 String
& splice(int location
, int len
, const String
& s
);
157 ///////////////////////////////////////////////////////////////////////
159 ///////////////////////////////////////////////////////////////////////
160 inline size_t length() const { return impl
->len
; }
161 inline size_t size() const { return impl
->len
; }
162 inline size_t capacity() const { return impl
->capacity
; }
163 inline Bool
is_empty() const { return impl
->len
== 0; }
164 inline Bool
is_full() const { return false; }
165 inline char operator [] (int i
) const { return impl
->string
[i
]; }
166 inline char& operator [] (int i
) { return impl
->string
[i
]; }
168 ///////////////////////////////////////////////////////////////////////
169 // Substring extraction
170 ///////////////////////////////////////////////////////////////////////
171 SubString
at (int left
, int length
) const;
172 SubString
left (int length
) const;
173 SubString
right (int length
) const;
175 ///////////////////////////////////////////////////////////////////////
177 ///////////////////////////////////////////////////////////////////////
178 friend String
operator + (const String
&, const String
&);
179 friend String
operator + (const String
&, const char *);
180 friend String
operator + (const char *, const String
&);
182 ///////////////////////////////////////////////////////////////////////
184 ///////////////////////////////////////////////////////////////////////
185 String
operator * (int times
);
187 ///////////////////////////////////////////////////////////////////////
189 ///////////////////////////////////////////////////////////////////////
190 String
& operator += (const String
&);
191 String
& operator += (const char *);
192 String
& operator += (char);
194 ///////////////////////////////////////////////////////////////////////
196 ///////////////////////////////////////////////////////////////////////
197 inline friend Bool
operator == (const String
& a
, const String
& b
) { return a
.compare(b
) == 0; }
198 inline friend Bool
operator == (const String
& a
, const char * b
) { return a
.compare(b
) == 0; }
199 inline friend Bool
operator == (const char * a
, const String
& b
) { return b
.compare(a
) == 0; }
200 inline friend Bool
operator != (const String
& a
, const String
& b
) { return a
.compare(b
) != 0; }
201 inline friend Bool
operator != (const String
& a
, const char * b
) { return a
.compare(b
) != 0; }
202 inline friend Bool
operator != (const char * a
, const String
& b
) { return b
.compare(a
) != 0; }
203 inline friend Bool
operator > (const String
& a
, const String
& b
) { return a
.compare(b
) > 0; }
204 inline friend Bool
operator > (const String
& a
, const char * b
) { return a
.compare(b
) > 0; }
205 inline friend Bool
operator > (const char * a
, const String
& b
) { return b
.compare(a
) < 0; }
206 inline friend Bool
operator < (const String
& a
, const String
& b
) { return a
.compare(b
) < 0; }
207 inline friend Bool
operator < (const String
& a
, const char * b
) { return a
.compare(b
) < 0; }
208 inline friend Bool
operator < (const char * a
, const String
& b
) { return b
.compare(a
) > 0; }
209 inline friend Bool
operator >= (const String
& a
, const String
& b
) { return a
.compare(b
) >= 0; }
210 inline friend Bool
operator >= (const String
& a
, const char * b
) { return a
.compare(b
) >= 0; }
211 inline friend Bool
operator >= (const char * a
, const String
& b
) { return b
.compare(a
) <= 0; }
212 inline friend Bool
operator <= (const String
& a
, const String
& b
) { return a
.compare(b
) <= 0; }
213 inline friend Bool
operator <= (const String
& a
, const char * b
) { return a
.compare(b
) <= 0; }
214 inline friend Bool
operator <= (const char * a
, const String
& b
) { return b
.compare(a
) >= 0; }
216 ///////////////////////////////////////////////////////////////////////
218 ///////////////////////////////////////////////////////////////////////
219 int compare (const String
&) const;
220 int compare (const char *, int len
= -1) const;
221 int case_insensitive_compare (const String
&) const;
222 int case_insensitive_compare (const char *, int len
= -1) const;
223 int collate (const String
&) const;
224 int collate (const char *, int len
= -1) const;
226 ///////////////////////////////////////////////////////////////////////
227 // In place operations
228 ///////////////////////////////////////////////////////////////////////
229 String
& toupper(); // make all upper case
230 String
& tolower(); // make all lower case
231 String
& trunc(int len
); // truncate the length to `len'
233 ///////////////////////////////////////////////////////////////////////
234 // Searching: returns a non-negative index if found
235 ///////////////////////////////////////////////////////////////////////
236 int contains (RegExp
&) const;
237 int contains (char) const;
238 int contains (const char *, int len
= -1) const;
239 int contains (const String
&) const;
241 ///////////////////////////////////////////////////////////////////////
243 ///////////////////////////////////////////////////////////////////////
244 friend ostream
& operator << (ostream
& out
, const String
& s
);
245 friend istream
& operator >> (istream
&, String
&);