String: Implement String != regex operator
[libacl.git] / src / String.h
1 /**************************************************************************
2 **  (c) Copyright 1997, Andromeda Technology & Automation
3 ***************************************************************************
4 ** MODULE INFORMATION *
5 ***********************
6 **      FILE NAME      : String.h
7 **      SYSTEM NAME    : Andromeda X-Windows Encapsulation
8 **      VERSION NUMBER : $Revision: 1.4 $
9 **
10 **  DESCRIPTION      :  Character String class definition
11 **
12 **  EXPORTED OBJECTS : class String
13 **  LOCAL    OBJECTS : class substring
14 **  MODULES  USED    :
15 ***************************************************************************
16 **  ADMINISTRATIVE INFORMATION *
17 ********************************
18 **      ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl
19 **      CREATION DATE   : Nov 17, 1995
20 **      LAST UPDATE     : Mar 31, 2010
21 **      MODIFICATIONS   : 
22 **************************************************************************/
23
24 /*****************************
25    $Log: String.h,v $
26    Revision 1.4  2007/05/04 13:56:05  arjen
27    Added a copy contructor to the regex class. This prevents multiple frees in the destructor.
28
29    Revision 1.3  2002/11/03 13:18:57  arjen
30    New functions - String::escape() and String::unescape()
31
32    Revision 1.2  2002/09/28 06:45:51  arjen
33    New feature: subtring selection by regular expression.
34    Bugfix: use the std: namespace for STL classes istream and ostream
35
36    Revision 1.1  2002/07/25 08:01:26  arjen
37    First checkin, AXE release 0.2
38
39 *****************************/
40
41 // static const char RCSID[] = "$Id: String.h,v 1.4 2007/05/04 13:56:05 arjen Exp $";
42
43 #ifndef STRING_H
44 #define STRING_H
45
46 #include <stdlib.h>
47 #include <iostream>
48 #include <vector>
49 #include <string.h>
50
51 #include <regex.h>
52
53 //  Forward declarations.
54 class substring;
55 class regex;
56 class SuperString;
57
58 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
59 **  NAME           : String - Character String class.
60 **  MEMBERS        : p -> s : Pointer to the actual String data.
61 **                   p -> n : Number of references to this String.
62 **  OPERATORS      : =      : Assign a String, char *, char to a String.
63 **                   +, +=  : concatenate Strings
64 **                   ~      : Length of a String
65 **                   []     : Individual character access.
66 **                   !      : Empty String test.
67 **                   ()     : Substring selection.
68 **                   ostream << : String to output stream.
69 **                   istream << : String from input stream.
70 **                   ==, !=, <,
71 **                   >, <=, >= : String comparison.
72 **  METHODS        :
73 **
74 **  DESCRIPTION    : The String class counts the references to a String to
75 **                   minimize copying and uses standard C++ character strings
76 **                   as constants.
77 **
78 **  RELATIONS      : substring
79 **  SEE ALSO       :
80 **  LAST MODIFIED  : Aug 27, 1999
81 **+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
82 */
83
84 class String
85 {
86    friend class substring;
87    friend class regex;
88
89    struct srep
90    {
91       char  *s;    // pointer to data;
92       int    n;    // reference count
93    } *p;
94
95 public:
96
97    String(const char *);      // String x = "abc"
98    String(char);              // String x = 'a'
99    String();                  // String x;
100    String(const String &);    // String x = String ...
101    String(const substring &); // String x = String(s, l)
102
103    String& operator=(const char);
104    String& operator=(const char *);
105    String& operator=(const String &);
106    ~String();
107
108    /*  Numerical conversion */
109
110    String(int);              //  String x(12);  x = "12"
111    String(long);             //  String x(12);  x = "12"
112    String(unsigned long);    //  String x(12);  x = "12"
113
114    operator int()
115    {
116       return strtol(p->s, 0, 0);
117    }
118
119    operator long()
120    {
121       return strtol(p->s, 0, 0);
122    }
123
124    operator unsigned long()
125    {
126       return strtoul(p->s, 0, 0);
127    }
128
129    long dec(void)
130    {
131       return strtol(p->s, 0, 10);
132    }
133
134    long oct(void)
135    {
136       return strtol(p->s, 0, 8);
137    }
138
139    long hex(void) 
140    {
141       return strtol(p->s, 0, 16);
142    }
143
144    String(double);
145    operator double()
146    {
147       return strtod(p->s, 0);
148    }
149
150
151    char& operator[](size_t i);    //  Individual character access
152
153    int operator~() const      //  Length of the String
154    {
155       return p->s ? strlen(p->s) : 0;
156    }
157
158    operator char*()
159    {
160       if (p->s && p->s[0])
161          return p->s;
162       else
163          return 0;
164    }
165    operator const char*() const
166    {
167       if (p->s && p->s[0])
168          return p->s;
169       else
170          return 0;
171    }
172
173    operator bool()   //  Test for empty String
174    {
175       return p->s != 0 && p->s[0] != '\0';
176    }
177
178    /*
179     *   String concatenation.
180     *   char and char* are handled by constructors.
181     */
182
183    String& operator+=(const String&);
184    String& operator+=(const char *);
185    friend String operator+(const String&, const String&);
186    friend String operator+(const String&, const char *);
187    friend String operator+(const char *,  const String&);
188
189    /*
190     *  Shifting characters out
191     *            "abcdefgh" <<= 3  = "defgh"
192     *            "abcdefgh" >>= 3  = "abcde"
193     */
194
195    friend String operator<<(const String &x, int n);
196    String & operator<<=(int n);
197
198    friend String operator>>(const String &x, int n);
199    String & operator>>=(int n);
200
201    /*
202     *   Substring selection
203     *
204     *   A substring can be selected by a start index and a length or
205     *   by matching a regular expression.
206     *
207     *   Selecting a substring by regular expression, combined with
208     *   the lvalue semantics of the substring class is a particularly
209     *   powerful concept. Possible uses are for example:
210     *
211     *   (assuming String S, M; regex R;)
212     *   M = S(R);             ->  Returns matching part of S into M.
213     *   S(R) = "replacement"; -> replace matching part of S.
214     *   S(R) = "";            -> Removes matching part from S.
215     *   S(R) == S;            -> true if and only if all of S matches R exactly.
216     */
217
218    substring operator()(int start, int len);
219    substring operator()(const regex &r);
220
221    /*
222     *   Input and output
223     */
224
225    friend std::ostream& operator<<(std::ostream &, const String &);
226    // Read one line and remove the trailing line feed.
227    friend std::istream& operator>>(std::istream &, String &);
228
229    /*
230     *   String comparison tests
231     */
232
233    friend int operator==(const String& x, const String& y)
234    {
235       return strcmp(x.p->s, y.p->s) == 0;
236    }
237
238    friend int operator!=(const String& x, const String& y)
239    {
240       return strcmp(x.p->s, y.p->s) != 0;
241    }
242
243    friend int operator<=(const String& x, const String& y)
244    {
245       return strcmp(x.p->s, y.p->s) <= 0;
246    }
247
248    friend int operator>=(const String& x, const String& y)
249    {
250       return strcmp(x.p->s, y.p->s) >= 0;
251    }
252
253    friend int operator<(const String& x, const String& y)
254    {
255       return strcmp(x.p->s, y.p->s) < 0;
256    }
257
258    friend int operator>(const String& x, const String& y)
259    {
260       return strcmp(x.p->s, y.p->s) > 0;
261    }
262
263    friend int operator==(const String& x, const char * y)
264    {
265       return strcmp(x.p->s, y) == 0;
266    }
267
268    friend int operator!=(const String& x, const char * y)
269    {
270       return strcmp(x.p->s, y) != 0;
271    }
272
273    friend int operator<=(const String& x, const char * y)
274    {
275       return strcmp(x.p->s, y) <= 0;
276    }
277
278    friend int operator>=(const String& x, const char * y)
279    {
280       return strcmp(x.p->s, y) >= 0;
281    }
282
283    friend int operator<(const String& x, const char * y)
284    {
285       return strcmp(x.p->s, y) < 0;
286    }
287
288    friend int operator>(const String& x, const char * y)
289    {
290       return strcmp(x.p->s, y) > 0;
291    }
292
293    /*
294     *  Modifiers
295     */
296
297    String upper();   //  Convert to upper case (ASCII)
298    String lower();   //  Convert to lower case (ASCII)
299    String escape();   //  Insert backslashes to escape special characters
300    String unescape(); //  Remove backslashes from escape codes.
301
302    /*
303     *  Character searching and Pattern matching
304     */
305
306    int index(char c);
307    int rindex(char c);
308
309    int in(String & x);
310
311    //  Regular expression pattern matching
312  
313    friend bool operator == (const String &s, const regex &r);
314    friend bool operator == (const regex &r, const String &s);
315    friend bool operator != (const String &s, const regex &r);
316    friend bool operator != (const regex &r, const String &s);
317
318    SuperString split(const String &separator);
319
320 };
321    /*
322     *   Other operators to think about...
323     *
324     *
325     *   Numeric conversion with strtod and strtol and vice-versa,
326     *   so we can do:
327     *                 String nr = 123  //  nr = "123"
328     *                 float x = 2.32; String f = x;  // f = "2.32"
329     *                             f = "3.145";
330     *                         int i = f;           // i = 3
331     *
332     *   String matching:
333     *       int index(String&, start=0)  // Find position of substring
334     *
335     *
336     *  Literature:  Bjarne Stroustrup, Section 6.9
337     *               DDJ October 1991, pg 24
338     */
339
340
341 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
342 **  NAME           : substring - Determine part of a String object.
343 **  MEMBERS        : str   : The String object of which this is a substring
344 **                   start : index of the first substring character.
345 **                   len   : Number of characters in the substring
346 **  OPERATORS      : =     : Assignment of a String or char *
347 **  METHODS        :
348 **
349 **  DESCRIPTION    : This implements substring selection from a String object
350 **                   with l-value semantics.
351 **
352 **  RELATIONS      : String
353 **  SEE ALSO       :
354 **  LAST MODIFIED  :
355 **+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
356 */
357
358 class substring
359 {
360    friend class String;
361
362    String     *str;   //  Where I am a substring of.
363    int  start, len;
364
365 public:
366    String& operator=(const String &); 
367    String& operator=(const char *s)
368    {
369       *this = String(s);
370       return *str;
371    }
372 };
373
374 /*  Regular expression matching */
375
376 class regex
377 {
378    friend class String;
379
380    regex_t    expression;
381    String     original;
382
383 public:
384
385    regex(const String & reg);
386    regex(const char * reg);
387    regex(const regex & reg);
388    ~regex();
389
390    regex& operator=(const regex &);
391
392    friend bool operator == (const String &s, const regex &r);
393    friend bool operator == (const regex &r, const String &s);
394    friend bool operator != (const String &s, const regex &r);
395    friend bool operator != (const regex &r, const String &s);
396 };
397
398 class SuperString
399 {
400    std::vector<String> _ss;
401
402 public:
403
404    SuperString()  {};
405
406    SuperString(const String &s)
407    {
408       std::vector<String> __ss(1, s);
409       _ss = __ss;
410    }
411
412    SuperString(const int n)
413    {
414       std::vector<String> __ss(n);
415       _ss = __ss;
416    }
417
418    operator bool()   //  Test for empty SuperString
419    {
420       return _ss.size() != 0;
421    }
422
423    int operator~() const      //  Length of the SuperString
424    {
425       return _ss.size();
426    }
427
428    String& operator[](size_t i)    //  Individual String access
429    {
430       return _ss.at(i);
431    }
432
433    // Adding Strings and SuperStrings
434
435    friend SuperString operator+(const SuperString&, const String&);
436    friend SuperString operator+(const String&, const SuperString&);
437    friend SuperString operator+(const SuperString&, const SuperString&);
438    SuperString& operator+=(const String&);
439
440    /*
441     *   SuperString comparison tests
442     */
443
444    friend int operator==(const SuperString& x, const SuperString& y)
445    {
446       return x._ss == y._ss;
447    }
448
449    friend int operator!=(const SuperString& x, const SuperString& y)
450    {
451       return x._ss != y._ss;
452    }
453
454    friend int operator<=(const SuperString& x, const SuperString& y)
455    {
456       return x._ss <= y._ss;
457    }
458
459    friend int operator>=(const SuperString& x, const SuperString& y)
460    {
461       return x._ss >= y._ss;
462    }
463
464    friend int operator<(const SuperString& x, const SuperString& y)
465    {
466       return x._ss < y._ss;
467    }
468
469    friend int operator>(const SuperString& x, const SuperString& y)
470    {
471       return x._ss > y._ss;
472    }
473
474    String join(const String &separator);
475 };
476
477 /*
478  *  Exception classes
479  */
480
481
482 class StringException
483 {
484    String message;
485
486 public:
487
488    StringException(String m)
489    {
490       message = m;
491    }
492
493    String what()
494    {
495       return message;
496    }
497 };
498
499 #define ERROR_MSG_SIZE 200
500
501 class RegexException
502 {
503    String message;
504
505 public:
506
507    RegexException(int errcode, regex_t *preg)
508    {
509       char errbuf[ERROR_MSG_SIZE];
510
511       regerror(errcode, preg, errbuf, ERROR_MSG_SIZE);
512       message = errbuf;
513    }
514
515    String what()
516    {
517       return message;
518    }
519 };
520
521 #endif  /* STRING_H */