This file is indexed.

/usr/include/speech_tools/EST_String.h is in libestools2.1-dev 1:2.1~release-6.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
/*************************************************************************/
/*                                                                       */
/*                Centre for Speech Technology Research                  */
/*                     University of Edinburgh, UK                       */
/*                        Copyright (c) 1997                             */
/*                        All Rights Reserved.                           */
/*                                                                       */
/*  Permission is hereby granted, free of charge, to use and distribute  */
/*  this software and its documentation without restriction, including   */
/*  without limitation the rights to use, copy, modify, merge, publish,  */
/*  distribute, sublicense, and/or sell copies of this work, and to      */
/*  permit persons to whom this work is furnished to do so, subject to   */
/*  the following conditions:                                            */
/*   1. The code must retain the above copyright notice, this list of    */
/*      conditions and the following disclaimer.                         */
/*   2. Any modifications must be clearly marked as such.                */
/*   3. Original authors' names are not deleted.                         */
/*   4. The authors' names are not used to endorse or promote products   */
/*      derived from this software without specific prior written        */
/*      permission.                                                      */
/*                                                                       */
/*  THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK        */
/*  DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING      */
/*  ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT   */
/*  SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE     */
/*  FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES    */
/*  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN   */
/*  AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,          */
/*  ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF       */
/*  THIS SOFTWARE.                                                       */
/*                                                                       */
/*************************************************************************/

#ifndef __EST_STRING_H__
#define __EST_STRING_H__

class EST_String;
class EST_Regex;

#define EST_Regex_max_subexpressions 10

#include <cstring>
#include <iostream>
#include <climits>
using namespace std;
#include "EST_Chunk.h"
#include "EST_strcasecmp.h"
#include "EST_bool.h"

extern "C" void abort(void);

/** A non-copyleft implementation of a string class to use with
  * compilers that aren't GNU C++.
  *
  * Strings are reference-counted and reasonably efficient (eg you
  * can pass them around, into and out of functions and so on
  * without worrying too much about the cost).
  *
  * The associated class EST_Regex can be used to represent regular
  * expressions.
  *
  * @see EST_Chunk
  * @see EST_Regex
  * @see string_example
  * @author Alan W Black <awb@cstr.ed.ac.uk>
  * @author Richard Caley <rjc@cstr.ed.ac.uk>
  * @version $Id: EST_String.h,v 1.7 2009/07/03 17:13:56 awb Exp $
  */

class EST_String {

    /** For better libg++ compatibility. 
      * 
      * Includes String from char constructor which
      * tends to mask errors in use. Also reverses the () and [] operators.
      */
#   define __FSF_COMPATIBILITY__ (0)

    /** Allow gsub() to be used in multi-threaded applications
      * This will cause gsub to use a local table of substitution points
      * walloced for each gsub. Otherwise one global one is used which
      * should be faster, but non reentrant.
      */
#   define __GSUB_REENTRANT__ (1)

/// Gripe about weird arguments like Nulls
#define __STRING_ARG_GRIPE__ (1)

///  When we find something to gripe about we die then and there.
#define __GRIPE_FATAL__ (1)

#if __GRIPE_FATAL__
#    define gripe(WHAT) (cerr<< ("oops! " WHAT "\n"),abort())
#else
#    define gripe(WHAT) (cerr<< ("oops! " WHAT "\n"))
#endif

#if __STRING_ARG_GRIPE__
#   define safe_strlen(S) ((S)?strlen(S):(gripe("null strlen"),0))
#   define CHECK_STRING_ARG(S) if (!(S)) gripe("null string arg")
#else
#   define safe_strlen(S) ((S)?strlen(S):0)
#   define CHECK_STRING_ARG(S) /* empty */
#endif

public:
    /// Global version string.
    static const char *version;

    /// Constant empty string
    static const EST_String Empty;

    /// Type of string size field.
    typedef int EST_string_size;
    /// Maximum string size.
#  define MAX_STRING_SIZE (INT_MAX)

private:
    /// Smart pointer to actual memory.
    EST_ChunkPtr memory;
    /// Size of string.
    EST_string_size size;

    // Make sure this is exactly the same as an EST_String. This is being too
    // clever by half.
  
    struct EST_dumb_string {
	EST_ChunkPtr memory;
	EST_string_size size;
    } ;

    /// Flags indicating which bit of a string to extract.
    enum EST_chop_direction {
	Chop_Before = -1,
	Chop_At     = 0,
	Chop_After  = 1
    };

    /// Simple utility which removes const-ness from memory
    static inline EST_ChunkPtr &NON_CONST_CHUNKPTR(const EST_ChunkPtr &ecp) 
	{ return *((EST_ChunkPtr *)&ecp);}

    /// private constructor which uses the buffer given.
    EST_String(int len, EST_ChunkPtr cp) {
	size=len;
	memory = cp;
    }

    /// Is more than one String represented by the same memory?
    int shareing (void) { return memory.shareing();}

    /**@name Finding substrings */
    //@{
    /// Find substring 
    int locate(const char *it, int len, int from, int &start, int &end) const;
    /// Find substring
    int locate(const EST_String &s, int from, int &start, int &end) const
	{ return locate((const char *)s.memory, s.size, from, start, end); }
    /// Find match for regexp.
    int locate(EST_Regex &ex, int from, int &start, int &end, int *starts=NULL, int *ends=NULL) const;
    //@}


    /**@name Extract Substrings */
    //@{
    int extract(const char *it, int len, int from, int &start, int &end) const;
    int extract(const EST_String &s, int from, int &start, int &end) const
	{ return extract((const char *)s.memory, s.size, from, start, end); }
    int extract(EST_Regex &ex, int from, int &start, int &end) const;
    //@}

    /**@name Chop out part of string */
    //@{
    /// Locate subsring and chop.
    EST_String chop_internal(const char *s, int length, int pos, EST_chop_direction directionult) const;
    /// Chop at given position.
    EST_String chop_internal(int pos, int length, EST_chop_direction directionult) const;
  
    /// Locate match for expression and chop.
    EST_String chop_internal(EST_Regex &ex, int pos, EST_chop_direction directionult) const;
    //@}

    /**@name Global search and replace */
    //@{
    /// Substitute for string
    int gsub_internal(const char *os, int olength, const char *s, int length);
    /// Substitute for matches of regexp.
    int gsub_internal(EST_Regex &ex, const char *s, int length);
    //@}

    /// Split the string down into parts. 
    int split_internal(EST_String result[], int max, const char* s_seperator, int slen, EST_Regex *re_separator, char quote) const;

    int Int(bool *ok_p) const;
    long Long(bool *ok_p) const;
    float Float(bool *ok_p) const;
    double Double(bool *ok_p) const;
public:

    /// Construct an empty string.
    EST_String(void) :memory() {size=0;}

    /// Construct from char *
    EST_String(const char *s);

    /// Construct from part of char * or fill with given character.
    EST_String(const char *s, int start_or_fill, int len);

    /// Construct from C string.
    EST_String(const char *s, int s_size, int start, int len);

    // Create from EST_String
    EST_String(const EST_String &s, int start, int len);

    /** Copy constructor
      * We have to declare our own copy constructor to lie to the
      * compiler about the constness of the RHS.
      */
    EST_String(const EST_String &s) {
      memory = NON_CONST_CHUNKPTR(s.memory);
      size = s.size;
    }

#if __FSF_COMPATIBILITY__
    /** Construct from single char.
      * This constructor is not usually included as it can mask errors.
      * @see  __FSF_COMPATIBILITY__
      */
    EST_String(const char c);
#endif

    /// Destructor.
    ~EST_String() {
	size=0;
	memory=NULL;
    }

    /// Length of string ({\em not} length of underlying chunk)
    int length(void) const { return size; }
    /// Size of underlying chunk.
    int space (void) const { return memory.size(); }
    /// Get a const-pointer to the actual memory.
    const char *str(void) const { return size==0?"":(const char *)memory; }
    /// Get a writable pointer to the actual memory.
    char *updatable_str(void) { return size==0?(char *)"":(char *)memory; }
    void make_updatable(void) { cp_make_updatable(memory, size+1);}


    /// Build string from a single character.
    static EST_String FromChar(const char c) 
	{ const char s[2] = { c, 0 }; return EST_String(s); }

    /// Build string from an integer.
    static EST_String Number(int i, int base=10);

    /// Build string from a long integer.
    static EST_String Number(long i, int base=10);

    /// Build string from a double.
    static EST_String Number(double d);

    /// Build string from a float
    static EST_String Number(float f);

    /// Convert to an integer
    int Int(bool &ok) const { return Int(&ok); }
    int Int(void) const { return Int((bool *)NULL); }

    /// Convert to a long
    long Long(bool &ok) const { return Long(&ok); }
    long Long(void) const { return Long((bool *)NULL); }

    /// Convert to a float
    float Float(bool &ok) const { return Float(&ok); }
    float Float(void) const { return Float((bool *)NULL); }

    /// Convert to a double
    double Double(bool &ok) const { return Double(&ok); }
    double Double(void) const { return Double((bool *)NULL); }

    /**@name Before */
    //@{
    /// Part before position
    EST_String before(int pos, int len=0) const
	{ return chop_internal(pos, len, Chop_Before); }
    /// Part before first matching substring after pos.
    EST_String before(const char *s, int pos=0) const
	{ return chop_internal(s, safe_strlen(s), pos, Chop_Before); }
    /// Part before first matching substring after pos.
    EST_String before(const EST_String &s, int pos=0) const
	{ return chop_internal(s.str(), s.size, pos, Chop_Before); }
    /// Part before first match of regexp after pos.
    EST_String before(EST_Regex &e, int pos=0) const
	{ return chop_internal(e,  pos, Chop_Before); }
    //@}

    /**@name At */
    //@{
    /// Return part at position
    EST_String at(int from, int len=0) const
	{ return EST_String(str(),size,from<0?(size+from):from,len); }
    /// Return part where substring found (not useful, included for completeness)
    EST_String at(const char *s, int pos=0) const
	{ return chop_internal(s, safe_strlen(s), pos, Chop_At); }
    /// Return part where substring found (not useful, included for completeness)
    EST_String at(const EST_String &s, int pos=0) const
	{ return chop_internal(s.str(), s.size, pos, Chop_At); }
    /// Return part matching regexp.
    EST_String at(EST_Regex &e, int pos=0) const
	{ return chop_internal(e,  pos, Chop_At); }
    //@}

    /**@name After */
    //@{
    /// Part after pos+len
    EST_String after(int pos, int len=1) const
	{ return chop_internal(pos, len, Chop_After); }
    /// Part after substring.
    EST_String after(const char *s, int pos=0) const
	{ return chop_internal(s, safe_strlen(s), pos, Chop_After); }
    /// Part after substring.
    EST_String after(const EST_String &s, int pos=0) const
	{ return chop_internal(s.str(), s.size, pos, Chop_After); }
    /// Part after match of regular expression.
    EST_String after(EST_Regex &e, int pos=0) const
	{ return chop_internal(e,  pos, Chop_After); }
    //@}
  
    /**@name Search for something */
    //@{
    /// Find a substring.
    int search(const char *s, int len, int &mlen, int pos=0) const
	{ int start, end;
	if (locate(s, len, pos, start, end))
	{ mlen=end-start; return start; }
	return -1;
	}

    /// Find a substring.
    int search(const EST_String s, int &mlen, int pos=0) const
	{ int start, end;
	if (locate(s, pos, start, end))
	{ mlen=end-start; return start; }
	return -1;
	}

    /// Find a match of the regular expression.
    int search(EST_Regex &re, int &mlen, int pos=0, int *starts=NULL, int *ends=NULL) const
	{ int start=0, end=0;
	if (locate(re, pos, start, end, starts, ends))
	{ mlen=end-start; return start; }
	return -1;
	}
    //@}


    /**@name Get position of something */
    //@{
    /// Position of substring (starting at pos)
    int index(const char *s, int pos=0) const
	{ int start, end; return locate(s, safe_strlen(s), pos, start, end)?start:-1; }
    /// Position of substring (starting at pos)
    int index(const EST_String &s, int pos=0) const
	{ int start, end; return locate(s, pos, start, end)?start:-1; }
    /// Position of match of regexp (starting at pos)
    int index(EST_Regex &ex, int pos=0) const
	{ int start, end; return locate(ex, pos, start, end)?start:-1; }
    //@}
  
    /**@name Does string contain something? */
    //@{
    /// Does it contain this substring?
    int contains(const char *s, int pos=-1) const
	{ int start, end; return extract(s, safe_strlen(s), pos, start, end); }
    /// Does it contain this substring?
    int contains(const EST_String &s, int pos=-1) const
	{ int start, end; return extract(s, pos, start, end); }
    /// Does it contain this character?
    int contains(const char c, int pos=-1) const
	{ int start, end; char s[2] = {c,0}; return extract(s, 1, pos, start, end); }
    /// Does it contain a match for  this regular expression?
    int contains(EST_Regex &ex, int pos=-1) const
	{ int start, end; return extract(ex, pos, start, end); }
    //@}

    /**@name Does string exactly match? */
    //@{
    /// Exactly match this string?
    int matches(const char *e, int pos=0) const;
    /// Exactly match this string?
    int matches(const EST_String &e, int pos=0) const;
    /// Exactly matches this regular expression, can return ends of sub-expressions.
    int matches(EST_Regex &e, int pos=0, int *starts=NULL, int *ends=NULL) const;
    //@}

    /**@name Global replacement */
    //@{
    /// Substitute one string for another.
    int gsub(const char *os, const EST_String &s)
	{ return gsub_internal(os, safe_strlen(os), s, s.size); }
    /// Substitute one string for another.
    int gsub(const char *os, const char *s)
	{ return gsub_internal(os, safe_strlen(os), s, safe_strlen(s)); }
    /// Substitute one string for another.
    int gsub(const EST_String &os, const EST_String &s)
	{ return gsub_internal(os, os.size, s, s.size); }
    /// Substitute one string for another.
    int gsub(const EST_String &os, const char *s)
	{ return gsub_internal(os, os.size, s, safe_strlen(s)); }

    /// Substitute string for matches of regular expression.
    int gsub(EST_Regex &ex, const EST_String &s)
	{ return gsub_internal(ex, s, s.size); }
    /// Substitute string for matches of regular expression.
    int gsub(EST_Regex &ex, const char *s)
	{ return gsub_internal(ex, s, safe_strlen(s)); }
    /// Substitute string for matches of regular expression.
    int gsub(EST_Regex &ex, int bracket_num)
	{ return gsub_internal(ex, NULL, bracket_num); }
    /// Substitute the result of a match into a string.
    int subst(EST_String source, 
	      int (&starts)[EST_Regex_max_subexpressions], 
	      int (&ends)[EST_Regex_max_subexpressions]);
    //@}

    /**@name Frequency counts */
    //@{
    /// Number of occurrences of substring
    int freq(const char *s) const;
    /// Number of occurrences of substring
    int freq(const EST_String &s) const;
    /// Number of matches of regular expression.
    int freq(EST_Regex &s) const;
    //@}

    /**@name Quoting */
    //@{
    /// Return the string in quotes with internal quotes protected.
    EST_String quote(const char quotec) const;
    /// Return in quotes if there is something to protect (e.g. spaces)
    EST_String quote_if_needed(const char quotec) const;
    /// Remove quotes and unprotect internal quotes.
    EST_String unquote(const char quotec) const;
    /// Remove quotes if any.
    EST_String unquote_if_needed(const char quotec) const;
    //@}

#if __FSF_COMPATIBILITY__
    const char operator [] (int i) const { return memory[i]; }
    char &operator () (int i) { return memory(i); }
#else
    /**@name Operators */
    //@{
    /// Function style access to constant strings.
    const char operator () (int i) const { return memory[i]; }
    /// Array style access to writable strings.
    char &operator [] (int i) { return memory(i); }
#endif

    /// Cast to const char * by simply giving access to pointer.
    operator const char*() const {return str(); }
    operator const char*() {return str(); }
    /// Cast to char *, may involve copying.
    operator char*() { return updatable_str(); }

    /**@name Add to end of string. */
    //@{
    /// Add C string to end of EST_String
    EST_String &operator += (const char *b);
    /// Add EST_String to end of EST_String
    EST_String &operator += (const EST_String b);
    //@}

    /**@name Assignment */
    //@{
    /// Assign C string to EST_String
    EST_String &operator = (const char *str);
    /// Assign single character to EST_String
    EST_String &operator = (const char c);
    /// Assign EST_String to EST_String.
    EST_String &operator = (const EST_String &s);
    //@}

    /**@name Concatenation */
    //@{
    /// Concatenate  two EST_Strings
    friend EST_String operator + (const EST_String &a, const EST_String &b);
    /// Concatenate C String with EST_String
    friend EST_String operator + (const char *a, const EST_String &b);
    /// Concatenate EST_String with C String
    friend EST_String operator + (const EST_String &a, const char *b);
    //@}

    /// Repeat string N times
    friend EST_String operator * (const EST_String &s, int n);

    /**@name relational operators */
    //@{
    ///
    friend int operator == (const char *a, const EST_String &b);
    ///
    friend int operator == (const EST_String &a, const char *b)
	{ return b == a; }
    ///
    friend int operator == (const EST_String &a, const EST_String &b);

    ///
    friend int operator != (const char *a, const EST_String &b)
	{ return !(a==b); }
    ///
    friend int operator != (const EST_String &a, const char *b)
	{ return !(a==b); }
    ///
    friend int operator != (const EST_String &a, const EST_String &b)
	{ return !(a==b); }

    ///
    friend inline int operator < (const char *a, const EST_String &b)
	{ return compare(a,b) < 0; }
    ///
    friend inline int operator < (const EST_String &a, const char *b) 
	{ return compare(a,b) < 0; }
    ///
    friend inline int operator < (const EST_String &a, const EST_String &b) 
	{ return compare(a,b) < 0; }
    ///
    friend inline int operator > (const char *a, const EST_String &b) 
	{ return compare(a,b) > 0; }
    ///
    friend inline int operator > (const EST_String &a, const char *b) 
	{ return compare(a,b) > 0; }
    ///
    friend inline int operator > (const EST_String &a, const EST_String &b) 
	{ return compare(a,b) > 0; }
    ///
    friend inline int operator <= (const char *a, const EST_String &b) 
	{ return compare(a,b) <= 0; }
    ///
    friend inline int operator <= (const EST_String &a, const char *b) 
	{ return compare(a,b) <= 0; }
    ///
    friend inline int operator <= (const EST_String &a, const EST_String &b) 
	{ return compare(a,b) <= 0; }
    ///
    friend inline int operator >= (const char *a, const EST_String &b) 
	{ return compare(a,b) >= 0; }
    ///
    friend inline int operator >= (const EST_String &a, const char *b) 
	{ return compare(a,b) >= 0; }
    ///
    friend inline int operator >= (const EST_String &a, const EST_String &b) 
	{ return compare(a,b) >= 0; }
    //@}

    //@}

    /**@name String comparison.
     * All these operators return -1, 0 or 1 to indicate the sort
     * order of the strings.
     */
    //@{
    /// 
    friend int compare(const EST_String &a, const EST_String &b);
    /// 
    friend int compare(const EST_String &a, const char *b);
    /// 
    friend inline int compare(const char *a, const EST_String &b)
	{ return -compare(b,a);  }
    /** Case folded comparison.
      *
      * The table argument can defined how upper and lower
      * case characters correspond. The default works for
      * ASCII.
      */
    //@{
    friend int fcompare(const EST_String &a, const EST_String &b, 
			const unsigned char *table=NULL);

    friend int fcompare(const EST_String &a, const char *b, 
				const unsigned char *table=NULL);
    ///
    friend inline int fcompare(const EST_String &a, const EST_String &b, 
			       const EST_String &table) 
	{ return fcompare(a, b, (const unsigned char *)(const char *)table); }
    //@}
    //@}
    //@}


    /**@name Split a string into parts.
      * 
      * These functions divide up a string producing an array of
      * substrings.
      */
    //@{
    /// Split at a given separator.
    friend int split(const EST_String & s, EST_String result[], 
		     int max, const EST_String& seperator, char quote=0)
	{ return s.split_internal(result, max, (const char *)seperator, seperator.length(), NULL, quote); }
    /// Split at a given separator.
    friend int split(const EST_String &s, EST_String result[], 
		     int max, const char *seperator, char quote=0)
	{ return s.split_internal(result, max, seperator, strlen(seperator), NULL, quote); }
    /// Split at each match of the regular expression.
    friend int split(const EST_String & s, EST_String result[], int max, 
		     EST_Regex& seperator, char quote=0)
	{ return s.split_internal(result, max, NULL, 0, &seperator, quote); }
    //@}

    /// Convert to upper case.
    friend EST_String upcase(const EST_String &s);
    /// Convert to lower case.
    friend EST_String downcase(const EST_String &s);

    /** Concatenate a number of strings. 
      * This is more efficient than multiple uses of + or +=
      */
    static EST_String cat(const EST_String s1, 
			  const EST_String s2 = Empty, 
			  const EST_String s3 = Empty, 
			  const EST_String s4 = Empty, 
			  const EST_String s5 = Empty,
			  const EST_String s6 = Empty,
			  const EST_String s7 = Empty,
			  const EST_String s8 = Empty,
			  const EST_String s9 = Empty
	);

  /*  Hacky way to ignore volatile */
      EST_String & ignore_volatile(void) volatile { return *((EST_String *)(void *)this); }

    /// Stream output for EST_String.
    friend ostream &operator << (ostream &s, const EST_String &str);
    friend class EST_Regex;

}; 

EST_ChunkPtr chunk_allocate(int bytes);
EST_ChunkPtr chunk_allocate(int bytes, const char *initial, int initial_len);
EST_ChunkPtr chunk_allocate(int bytes, const EST_ChunkPtr &initial, int initial_start, int initial_len);

int operator == (const char *a, const EST_String &b);
int operator == (const EST_String &a, const EST_String &b);
ostream &operator << (ostream &s, const EST_String &str);

#include "EST_Regex.h"

#endif