"Fossies" - the Fresh Open Source Software Archive

Member "speech_tools/include/EST_String.h" (4 Sep 2017, 23527 Bytes) of package /linux/misc/speech_tools-2.5.0-release.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "EST_String.h" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.4-release_vs_2.5.0-release.

    1 /*************************************************************************/
    2 /*                                                                       */
    3 /*                Centre for Speech Technology Research                  */
    4 /*                     University of Edinburgh, UK                       */
    5 /*                        Copyright (c) 1997                             */
    6 /*                        All Rights Reserved.                           */
    7 /*                                                                       */
    8 /*  Permission is hereby granted, free of charge, to use and distribute  */
    9 /*  this software and its documentation without restriction, including   */
   10 /*  without limitation the rights to use, copy, modify, merge, publish,  */
   11 /*  distribute, sublicense, and/or sell copies of this work, and to      */
   12 /*  permit persons to whom this work is furnished to do so, subject to   */
   13 /*  the following conditions:                                            */
   14 /*   1. The code must retain the above copyright notice, this list of    */
   15 /*      conditions and the following disclaimer.                         */
   16 /*   2. Any modifications must be clearly marked as such.                */
   17 /*   3. Original authors' names are not deleted.                         */
   18 /*   4. The authors' names are not used to endorse or promote products   */
   19 /*      derived from this software without specific prior written        */
   20 /*      permission.                                                      */
   21 /*                                                                       */
   22 /*  THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK        */
   23 /*  DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING      */
   24 /*  ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT   */
   25 /*  SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE     */
   26 /*  FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES    */
   27 /*  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN   */
   28 /*  AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,          */
   29 /*  ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF       */
   30 /*  THIS SOFTWARE.                                                       */
   31 /*                                                                       */
   32 /*************************************************************************/
   33 
   34 #ifndef __EST_STRING_H__
   35 #define __EST_STRING_H__
   36 
   37 class EST_String;
   38 class EST_Regex;
   39 
   40 #define EST_Regex_max_subexpressions 10
   41 
   42 #include <cstring>
   43 #include <iostream>
   44 #include <climits>
   45 using namespace std;
   46 #include "EST_Chunk.h"
   47 #include "EST_strcasecmp.h"
   48 #include "EST_bool.h"
   49 
   50 extern "C" void abort(void);
   51 
   52 /** A non-copyleft implementation of a string class to use with
   53   * compilers that aren't GNU C++.
   54   *
   55   * Strings are reference-counted and reasonably efficient (eg you
   56   * can pass them around, into and out of functions and so on
   57   * without worrying too much about the cost).
   58   *
   59   * The associated class EST_Regex can be used to represent regular
   60   * expressions.
   61   *
   62   * @see EST_Chunk
   63   * @see EST_Regex
   64   * @see string_example
   65   * @author Alan W Black <awb@cstr.ed.ac.uk>
   66   * @author Richard Caley <rjc@cstr.ed.ac.uk>
   67   * @version $Id: EST_String.h,v 1.11 2017/02/22 15:50:14 awb Exp $
   68   */
   69 
   70 class EST_String {
   71 
   72     /** For better libg++ compatibility. 
   73       * 
   74       * Includes String from char constructor which
   75       * tends to mask errors in use. Also reverses the () and [] operators.
   76       */
   77 #   define __FSF_COMPATIBILITY__ (0)
   78 
   79     /** Allow gsub() to be used in multi-threaded applications
   80       * This will cause gsub to use a local table of substitution points
   81       * walloced for each gsub. Otherwise one global one is used which
   82       * should be faster, but non reentrant.
   83       */
   84 #   define __GSUB_REENTRANT__ (1)
   85 
   86 /// Gripe about weird arguments like Nulls
   87 #define __STRING_ARG_GRIPE__ (1)
   88 
   89 ///  When we find something to gripe about we die then and there.
   90 #define __GRIPE_FATAL__ (1)
   91 
   92 #if __GRIPE_FATAL__
   93 #    define gripe(WHAT) (cerr<< ("oops! " WHAT "\n"),abort())
   94 #else
   95 #    define gripe(WHAT) (cerr<< ("oops! " WHAT "\n"))
   96 #endif
   97 
   98 #if __STRING_ARG_GRIPE__
   99 #   define safe_strlen(S) ((S)?strlen(S):(gripe("null strlen"),0))
  100 #   define CHECK_STRING_ARG(S) if (!(S)) gripe("null string arg")
  101 #else
  102 #   define safe_strlen(S) ((S)?strlen(S):0)
  103 #   define CHECK_STRING_ARG(S) /* empty */
  104 #endif
  105 
  106 public:
  107     /// Global version string.
  108     static const char *version;
  109 
  110     /// Constant empty string
  111     static const EST_String Empty;
  112 
  113     /// Type of string size field.
  114     typedef int EST_string_size;
  115     /// Maximum string size.
  116 #  define MAX_STRING_SIZE (INT_MAX)
  117 
  118 private:
  119     /// Smart pointer to actual memory.
  120     EST_ChunkPtr memory;
  121     /// Size of string.
  122     EST_string_size size;
  123 
  124     // Make sure this is exactly the same as an EST_String. This is being too
  125     // clever by half.
  126   
  127     struct EST_dumb_string {
  128     EST_ChunkPtr memory;
  129     EST_string_size size;
  130     } ;
  131 
  132     /// Flags indicating which bit of a string to extract.
  133     enum EST_chop_direction {
  134     Chop_Before = -1,
  135     Chop_At     = 0,
  136     Chop_After  = 1
  137     };
  138 
  139     /// Simple utility which removes const-ness from memory
  140     static inline EST_ChunkPtr &NON_CONST_CHUNKPTR(const EST_ChunkPtr &ecp) 
  141     { return *((EST_ChunkPtr *)&ecp);}
  142 
  143     /// private constructor which uses the buffer given.
  144     EST_String(int len, EST_ChunkPtr cp) {
  145     size=len;
  146     memory = cp;
  147     }
  148 
  149     /// Is more than one String represented by the same memory?
  150     int shareing (void) { return memory.shareing();}
  151 
  152     /**@name Finding substrings */
  153     //@{
  154     /// Find substring 
  155     int locate(const char *it, int len, int from, int &start, int &end) const;
  156     /// Find substring
  157     int locate(const EST_String &s, int from, int &start, int &end) const
  158     { return locate((const char *)s.memory, s.size, from, start, end); }
  159     /// Find match for regexp.
  160     int locate(EST_Regex &ex, int from, int &start, int &end, int *starts=NULL, int *ends=NULL) const;
  161     //@}
  162 
  163 
  164     /**@name Extract Substrings */
  165     //@{
  166     int extract(const char *it, int len, int from, int &start, int &end) const;
  167     int extract(const EST_String &s, int from, int &start, int &end) const
  168     { return extract((const char *)s.memory, s.size, from, start, end); }
  169     int extract(EST_Regex &ex, int from, int &start, int &end) const;
  170     //@}
  171 
  172     /**@name Chop out part of string */
  173     //@{
  174     /// Locate subsring and chop.
  175     EST_String chop_internal(const char *s, int length, int pos, EST_chop_direction directionult) const;
  176     /// Chop at given position.
  177     EST_String chop_internal(int pos, int length, EST_chop_direction directionult) const;
  178   
  179     /// Locate match for expression and chop.
  180     EST_String chop_internal(EST_Regex &ex, int pos, EST_chop_direction directionult) const;
  181     //@}
  182 
  183     /**@name Global search and replace */
  184     //@{
  185     /// Substitute for string
  186     int gsub_internal(const char *os, int olength, const char *s, int length);
  187     /// Substitute for matches of regexp.
  188     int gsub_internal(EST_Regex &ex, const char *s, int length);
  189     //@}
  190 
  191     /// Split the string down into parts. 
  192     int split_internal(EST_String result[], int max, const char* s_seperator, int slen, EST_Regex *re_separator, char quote) const;
  193 
  194     int Int(bool *ok_p) const;
  195     long Long(bool *ok_p) const;
  196     float Float(bool *ok_p) const;
  197     double Double(bool *ok_p) const;
  198 public:
  199 
  200     /// Construct an empty string.
  201     EST_String(void) :memory() {size=0;}
  202 
  203     /// Construct from char *
  204     EST_String(const char *s);
  205 
  206     /// Construct from part of char * or fill with given character.
  207     EST_String(const char *s, int start_or_fill, int len);
  208 
  209     /// Construct from C string.
  210     EST_String(const char *s, int s_size, int start, int len);
  211 
  212     // Create from EST_String
  213     EST_String(const EST_String &s, int start, int len);
  214 
  215     /** Copy constructor
  216       * We have to declare our own copy constructor to lie to the
  217       * compiler about the constness of the RHS.
  218       */
  219     #if 0
  220     EST_String(const EST_String &s) {
  221       memory = NON_CONST_CHUNKPTR(s.memory);
  222       size = s.size;
  223     }
  224     #endif
  225 
  226 #if __FSF_COMPATIBILITY__
  227     /** Construct from single char.
  228       * This constructor is not usually included as it can mask errors.
  229       * @see  __FSF_COMPATIBILITY__
  230       */
  231     EST_String(const char c);
  232 #endif
  233 
  234     /// Destructor.
  235     ~EST_String() {
  236     size=0;
  237     memory=NULL;
  238     }
  239 
  240     /// Length of string ({\em not} length of underlying chunk)
  241     int length(void) const { return size; }
  242     /// Size of underlying chunk.
  243     int space (void) const { return memory.size(); }
  244     /// Get a const-pointer to the actual memory.
  245     const char *str(void) const { return size==0?"":(const char *)memory; }
  246     /// Get a writable pointer to the actual memory.
  247     char *updatable_str(void) { return size==0?(char *)"":(char *)memory; }
  248     void make_updatable(void) { cp_make_updatable(memory, size+1);}
  249 
  250 
  251     /// Build string from a single character.
  252     static EST_String FromChar(const char c) 
  253     { const char s[2] = { c, 0 }; return EST_String(s); }
  254 
  255     /// Build string from an integer.
  256     static EST_String Number(int i, int base=10);
  257 
  258     /// Build string from a long integer.
  259     static EST_String Number(long i, int base=10);
  260 
  261     /// Build string from a double.
  262     static EST_String Number(double d);
  263 
  264     /// Build string from a float
  265     static EST_String Number(float f);
  266 
  267     /// Convert to an integer
  268     int Int(bool &ok) const { return Int(&ok); }
  269     int Int(void) const { return Int((bool *)NULL); }
  270 
  271     /// Convert to a long
  272     long Long(bool &ok) const { return Long(&ok); }
  273     long Long(void) const { return Long((bool *)NULL); }
  274 
  275     /// Convert to a float
  276     float Float(bool &ok) const { return Float(&ok); }
  277     float Float(void) const { return Float((bool *)NULL); }
  278 
  279     /// Convert to a double
  280     double Double(bool &ok) const { return Double(&ok); }
  281     double Double(void) const { return Double((bool *)NULL); }
  282 
  283     /**@name Before */
  284     //@{
  285     /// Part before position
  286     EST_String before(int pos, int len=0) const
  287     { return chop_internal(pos, len, Chop_Before); }
  288     /// Part before first matching substring after pos.
  289     EST_String before(const char *s, int pos=0) const
  290     { return chop_internal(s, safe_strlen(s), pos, Chop_Before); }
  291     /// Part before first matching substring after pos.
  292     EST_String before(const EST_String &s, int pos=0) const
  293     { return chop_internal(s.str(), s.size, pos, Chop_Before); }
  294     /// Part before first match of regexp after pos.
  295     EST_String before(EST_Regex &e, int pos=0) const
  296     { return chop_internal(e,  pos, Chop_Before); }
  297     //@}
  298 
  299     /**@name At */
  300     //@{
  301     /// Return part at position
  302     EST_String at(int from, int len=0) const
  303     { return EST_String(str(),size,from<0?(size+from):from,len); }
  304     /// Return part where substring found (not useful, included for completeness)
  305     EST_String at(const char *s, int pos=0) const
  306     { return chop_internal(s, safe_strlen(s), pos, Chop_At); }
  307     /// Return part where substring found (not useful, included for completeness)
  308     EST_String at(const EST_String &s, int pos=0) const
  309     { return chop_internal(s.str(), s.size, pos, Chop_At); }
  310     /// Return part matching regexp.
  311     EST_String at(EST_Regex &e, int pos=0) const
  312     { return chop_internal(e,  pos, Chop_At); }
  313     //@}
  314 
  315     /**@name After */
  316     //@{
  317     /// Part after pos+len
  318     EST_String after(int pos, int len=1) const
  319     { return chop_internal(pos, len, Chop_After); }
  320     /// Part after substring.
  321     EST_String after(const char *s, int pos=0) const
  322     { return chop_internal(s, safe_strlen(s), pos, Chop_After); }
  323     /// Part after substring.
  324     EST_String after(const EST_String &s, int pos=0) const
  325     { return chop_internal(s.str(), s.size, pos, Chop_After); }
  326     /// Part after match of regular expression.
  327     EST_String after(EST_Regex &e, int pos=0) const
  328     { return chop_internal(e,  pos, Chop_After); }
  329     //@}
  330   
  331     /**@name Search for something */
  332     //@{
  333     /// Find a substring.
  334     int search(const char *s, int len, int &mlen, int pos=0) const
  335     { int start, end;
  336     if (locate(s, len, pos, start, end))
  337     { mlen=end-start; return start; }
  338     return -1;
  339     }
  340 
  341     /// Find a substring.
  342     int search(const EST_String s, int &mlen, int pos=0) const
  343     { int start, end;
  344     if (locate(s, pos, start, end))
  345     { mlen=end-start; return start; }
  346     return -1;
  347     }
  348 
  349     /// Find a match of the regular expression.
  350     int search(EST_Regex &re, int &mlen, int pos=0, int *starts=NULL, int *ends=NULL) const
  351     { int start=0, end=0;
  352     if (locate(re, pos, start, end, starts, ends))
  353     { mlen=end-start; return start; }
  354     return -1;
  355     }
  356     //@}
  357 
  358 
  359     /**@name Get position of something */
  360     //@{
  361     /// Position of substring (starting at pos)
  362     int index(const char *s, int pos=0) const
  363     { int start, end; return locate(s, safe_strlen(s), pos, start, end)?start:-1; }
  364     /// Position of substring (starting at pos)
  365     int index(const EST_String &s, int pos=0) const
  366     { int start, end; return locate(s, pos, start, end)?start:-1; }
  367     /// Position of match of regexp (starting at pos)
  368     int index(EST_Regex &ex, int pos=0) const
  369     { int start, end; return locate(ex, pos, start, end)?start:-1; }
  370     //@}
  371   
  372     /**@name Does string contain something? */
  373     //@{
  374     /// Does it contain this substring?
  375     int contains(const char *s, int pos=-1) const
  376     { int start, end; return extract(s, safe_strlen(s), pos, start, end); }
  377     /// Does it contain this substring?
  378     int contains(const EST_String &s, int pos=-1) const
  379     { int start, end; return extract(s, pos, start, end); }
  380     /// Does it contain this character?
  381     int contains(const char c, int pos=-1) const
  382     { int start, end; char s[2] = {c,0}; return extract(s, 1, pos, start, end); }
  383     /// Does it contain a match for  this regular expression?
  384     int contains(EST_Regex &ex, int pos=-1) const
  385     { int start, end; return extract(ex, pos, start, end); }
  386     //@}
  387 
  388     /**@name Does string exactly match? */
  389     //@{
  390     /// Exactly match this string?
  391     int matches(const char *e, int pos=0) const;
  392     /// Exactly match this string?
  393     int matches(const EST_String &e, int pos=0) const;
  394     /// Exactly matches this regular expression, can return ends of sub-expressions.
  395     int matches(EST_Regex &e, int pos=0, int *starts=NULL, int *ends=NULL) const;
  396     //@}
  397 
  398     /**@name Global replacement */
  399     //@{
  400     /// Substitute one string for another.
  401     int gsub(const char *os, const EST_String &s)
  402     { return gsub_internal(os, safe_strlen(os), s, s.size); }
  403     /// Substitute one string for another.
  404     int gsub(const char *os, const char *s)
  405     { return gsub_internal(os, safe_strlen(os), s, safe_strlen(s)); }
  406     /// Substitute one string for another.
  407     int gsub(const EST_String &os, const EST_String &s)
  408     { return gsub_internal(os, os.size, s, s.size); }
  409     /// Substitute one string for another.
  410     int gsub(const EST_String &os, const char *s)
  411     { return gsub_internal(os, os.size, s, safe_strlen(s)); }
  412 
  413     /// Substitute string for matches of regular expression.
  414     int gsub(EST_Regex &ex, const EST_String &s)
  415     { return gsub_internal(ex, s, s.size); }
  416     /// Substitute string for matches of regular expression.
  417     int gsub(EST_Regex &ex, const char *s)
  418     { return gsub_internal(ex, s, safe_strlen(s)); }
  419     /// Substitute string for matches of regular expression.
  420     int gsub(EST_Regex &ex, int bracket_num)
  421     { return gsub_internal(ex, NULL, bracket_num); }
  422     /// Substitute the result of a match into a string.
  423     int subst(EST_String source, 
  424           int (&starts)[EST_Regex_max_subexpressions], 
  425           int (&ends)[EST_Regex_max_subexpressions]);
  426     //@}
  427 
  428     /**@name Frequency counts */
  429     //@{
  430     /// Number of occurrences of substring
  431     int freq(const char *s) const;
  432     /// Number of occurrences of substring
  433     int freq(const EST_String &s) const;
  434     /// Number of matches of regular expression.
  435     int freq(EST_Regex &s) const;
  436     //@}
  437 
  438     /**@name Quoting */
  439     //@{
  440     /// Return the string in quotes with internal quotes protected.
  441     EST_String quote(const char quotec) const;
  442     /// Return in quotes if there is something to protect (e.g. spaces)
  443     EST_String quote_if_needed(const char quotec) const;
  444     /// Remove quotes and unprotect internal quotes.
  445     EST_String unquote(const char quotec) const;
  446     /// Remove quotes if any.
  447     EST_String unquote_if_needed(const char quotec) const;
  448     //@}
  449 
  450 #if __FSF_COMPATIBILITY__
  451     const char operator [] (int i) const { return memory[i]; }
  452     char &operator () (int i) { return memory(i); }
  453 #else
  454     /**@name Operators */
  455     //@{
  456     /// Function style access to constant strings.
  457     const char operator () (int i) const { return memory[i]; }
  458     /// Array style access to writable strings.
  459     char &operator [] (int i) { return memory(i); }
  460 #endif
  461 
  462     /// Cast to const char * by simply giving access to pointer.
  463     operator const char*() const {return str(); }
  464     operator const char*() {return str(); }
  465     /// Cast to char *, may involve copying.
  466     operator char*() { return updatable_str(); }
  467 
  468     /**@name Add to end of string. */
  469     //@{
  470     /// Add C string to end of EST_String
  471     EST_String &operator += (const char *b);
  472     /// Add EST_String to end of EST_String
  473     EST_String &operator += (const EST_String b);
  474     //@}
  475 
  476     /**@name Assignment */
  477     //@{
  478     /// Assign C string to EST_String
  479     EST_String &operator = (const char *str);
  480     /// Assign single character to EST_String
  481     #if 0
  482     EST_String &operator = (const char c);
  483     /// Assign EST_String to EST_String.
  484     EST_String &operator = (const EST_String &s);
  485     #endif
  486     //@}
  487 
  488     /**@name Concatenation */
  489     //@{
  490     /// Concatenate  two EST_Strings
  491     friend EST_String operator + (const EST_String &a, const EST_String &b);
  492     /// Concatenate C String with EST_String
  493     friend EST_String operator + (const char *a, const EST_String &b);
  494     /// Concatenate EST_String with C String
  495     friend EST_String operator + (const EST_String &a, const char *b);
  496     //@}
  497 
  498     /// Repeat string N times
  499     friend EST_String operator * (const EST_String &s, int n);
  500 
  501     /**@name relational operators */
  502     //@{
  503     ///
  504     friend int operator == (const char *a, const EST_String &b);
  505     ///
  506     friend int operator == (const EST_String &a, const char *b)
  507     { return b == a; }
  508     ///
  509     friend int operator == (const EST_String &a, const EST_String &b);
  510 
  511     ///
  512     friend int operator != (const char *a, const EST_String &b)
  513     { return !(a==b); }
  514     ///
  515     friend int operator != (const EST_String &a, const char *b)
  516     { return !(a==b); }
  517     ///
  518     friend int operator != (const EST_String &a, const EST_String &b)
  519     { return !(a==b); }
  520 
  521     ///
  522     friend inline int operator < (const char *a, const EST_String &b)
  523     { return compare(a,b) < 0; }
  524     ///
  525     friend inline int operator < (const EST_String &a, const char *b) 
  526     { return compare(a,b) < 0; }
  527     ///
  528     friend inline int operator < (const EST_String &a, const EST_String &b) 
  529     { return compare(a,b) < 0; }
  530     ///
  531     friend inline int operator > (const char *a, const EST_String &b) 
  532     { return compare(a,b) > 0; }
  533     ///
  534     friend inline int operator > (const EST_String &a, const char *b) 
  535     { return compare(a,b) > 0; }
  536     ///
  537     friend inline int operator > (const EST_String &a, const EST_String &b) 
  538     { return compare(a,b) > 0; }
  539     ///
  540     friend inline int operator <= (const char *a, const EST_String &b) 
  541     { return compare(a,b) <= 0; }
  542     ///
  543     friend inline int operator <= (const EST_String &a, const char *b) 
  544     { return compare(a,b) <= 0; }
  545     ///
  546     friend inline int operator <= (const EST_String &a, const EST_String &b) 
  547     { return compare(a,b) <= 0; }
  548     ///
  549     friend inline int operator >= (const char *a, const EST_String &b) 
  550     { return compare(a,b) >= 0; }
  551     ///
  552     friend inline int operator >= (const EST_String &a, const char *b) 
  553     { return compare(a,b) >= 0; }
  554     ///
  555     friend inline int operator >= (const EST_String &a, const EST_String &b) 
  556     { return compare(a,b) >= 0; }
  557     //@}
  558 
  559     //@}
  560 
  561     /**@name String comparison.
  562      * All these operators return -1, 0 or 1 to indicate the sort
  563      * order of the strings.
  564      */
  565     //@{
  566     /// 
  567     friend int compare(const EST_String &a, const EST_String &b);
  568     /// 
  569     friend int compare(const EST_String &a, const char *b);
  570     /// 
  571     friend inline int compare(const char *a, const EST_String &b)
  572     { return -compare(b,a);  }
  573     /** Case folded comparison.
  574       *
  575       * The table argument can defined how upper and lower
  576       * case characters correspond. The default works for
  577       * ASCII.
  578       */
  579     //@{
  580     friend int fcompare(const EST_String &a, const EST_String &b, 
  581             const unsigned char *table);
  582 
  583     friend inline int fcompare(const EST_String &a, const EST_String &b)
  584         { return fcompare(a,b,NULL); }
  585 
  586 
  587     friend int fcompare(const EST_String &a, const char *b, 
  588                 const unsigned char *table);
  589     ///
  590     friend inline int fcompare(const EST_String &a, const EST_String &b, 
  591                    const EST_String &table) 
  592     { return fcompare(a, b, (const unsigned char *)(const char *)table); }
  593     //@}
  594     //@}
  595     //@}
  596 
  597 
  598     /**@name Split a string into parts.
  599       * 
  600       * These functions divide up a string producing an array of
  601       * substrings.
  602       */
  603     //@{
  604     /// Split at a given separator.
  605     friend int split(const EST_String & s, EST_String result[], 
  606              int max, const EST_String& seperator, char quote=0)
  607     { return s.split_internal(result, max, (const char *)seperator, seperator.length(), NULL, quote); }
  608     /// Split at a given separator.
  609     friend int split(const EST_String &s, EST_String result[], 
  610              int max, const char *seperator, char quote=0)
  611     { return s.split_internal(result, max, seperator, strlen(seperator), NULL, quote); }
  612     /// Split at each match of the regular expression.
  613     friend int split(const EST_String & s, EST_String result[], int max, 
  614              EST_Regex& seperator, char quote=0)
  615     { return s.split_internal(result, max, NULL, 0, &seperator, quote); }
  616     //@}
  617 
  618     /// Convert to upper case.
  619     friend EST_String upcase(const EST_String &s);
  620     /// Convert to lower case.
  621     friend EST_String downcase(const EST_String &s);
  622 
  623     /** Concatenate a number of strings. 
  624       * This is more efficient than multiple uses of + or +=
  625       */
  626     static EST_String cat(const EST_String s1, 
  627               const EST_String s2 = Empty, 
  628               const EST_String s3 = Empty, 
  629               const EST_String s4 = Empty, 
  630               const EST_String s5 = Empty,
  631               const EST_String s6 = Empty,
  632               const EST_String s7 = Empty,
  633               const EST_String s8 = Empty,
  634               const EST_String s9 = Empty
  635     );
  636 
  637   /*  Hacky way to ignore volatile */
  638       EST_String & ignore_volatile(void) volatile { return *((EST_String *)(void *)this); }
  639 
  640     /// Stream output for EST_String.
  641     friend ostream &operator << (ostream &s, const EST_String &str);
  642     friend class EST_Regex;
  643 
  644 }; 
  645 
  646 EST_ChunkPtr chunk_allocate(int bytes);
  647 EST_ChunkPtr chunk_allocate(int bytes, const char *initial, int initial_len);
  648 EST_ChunkPtr chunk_allocate(int bytes, const EST_ChunkPtr &initial, int initial_start, int initial_len);
  649 
  650 int operator == (const char *a, const EST_String &b);
  651 int operator == (const EST_String &a, const EST_String &b);
  652 ostream &operator << (ostream &s, const EST_String &str);
  653 
  654 #include "EST_Regex.h"
  655 
  656 #endif