home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 July / macformat-026.iso / mac / Shareware City / Developers / NString 1.0 beta / Sources / NString.h < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-23  |  36.6 KB  |  810 lines  |  [TEXT/KAHL]

  1. /*    
  2.  
  3. _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
  4.  
  5.         NSTRING - a dynamic string class based on the string handling
  6.             functions of the NEWTON programming language.
  7.             NEWTON is being developed for VAX/VMS and DEC Alpha
  8.             systems by the staff of the compilation lab (LCO) of the
  9.             Swiss Federal Institute of Technology (EPFL).
  10.  
  11.         Version 1.0 - beta
  12.         
  13.         Copyright © 20th November, 1994 by Joël "Obiwan" François
  14.  
  15. _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
  16.  
  17. */
  18.  
  19. #ifndef _NSTRING_H_
  20. #define _NSTRING_H_
  21.  
  22. #include <iostream.h>
  23. #include "Alphabet.h"
  24.  
  25. class NString
  26. {
  27.     public:
  28.  
  29.         // NOTE: Unless otherwise specified, the reference returned by functions that return
  30.         //     an NString& is always a reference to the current NString object, to allow concatenation
  31.         //        of NString operations.
  32.  
  33.  
  34.         /*-------- Public Constructors & Destructor --------*/
  35.  
  36.         NString (void);                                                                            //        NString s;
  37.             // constructor: create an empty NString.
  38.         
  39.         NString (const char *s);                                                                //        NString s("Hello World");
  40.             // constructor: NString initialized with a given C-String.
  41.  
  42.         NString (const char c);                                                                //        NString s('P');
  43.             // constructor: NString initialized with a character.
  44.             // If the character is a NUL character, a runtime error will be raised.
  45.         
  46.         inline NString (const NString& s);                                                //        NString s(a);
  47.             // constructor: NString copied from an existing NString.
  48.             
  49.         ~NString (void);
  50.             // destructor
  51.  
  52.         /*-------- Assignment --------*/
  53.  
  54.         NString& operator= (const char *s);                                            //        s = "Hello World";
  55.             // build an NString from a C-String
  56.  
  57.         NString& operator= (const char c);                                                //        s = 'M';
  58.             // build an NString from a character
  59.             // If the character is a NUL character, a runtime error will be raised.
  60.             
  61.         NString& operator= (const NString& s);                                        //        s = t;
  62.             // copy an NString
  63.  
  64.         /*-------- Getting at the information contained in an NString --------*/
  65.         
  66.         char *string (void) const;                                                            //        C_str = s.stringcopy();
  67.             // get a copy of the C-String contained in the NString.
  68.             // NOTE: You must free() the returned pointer after usage.
  69.             
  70.         inline char *string (char *s) const;                                                //        s.string(C_str);
  71.             // get a copy of the C-String contained in the NString.
  72.             // The provided char pointer is used to store the copy.
  73.             // WARNING: The provided buffer must be large enough
  74.             // to hold the string; no boundary checks are done !
  75.  
  76.         // NOTE: The string() functions return solely a COPY of the C-string contained in the NString.
  77.         //        It is NOT possible to return a pointer to the original string, as this pointer might change
  78.         //        during subsequent NString-operations !  Moreover, this way the class user cannot
  79.         //        corrupt class integrity by modifying string data directly.
  80.  
  81.         inline unsigned long int length (void) const;                                    //        l = s.length();
  82.             // get the length of the NString
  83.  
  84.         /*-------- Accessing single characters in the NString --------*/
  85.  
  86.         char operator[] (const unsigned long int k) const;                            //        c = s[3];
  87.             // read the kth character of the NString; s[1] is the first character;
  88.             // if (k > s.length) a runtime error will occur.
  89.             // Thus the terminating NUL-byte can't be read.
  90.             
  91.         char setchar (const unsigned long int k, const char c);                        //        s.setchar(2, 'Q');
  92.             // modify the kth character of the NString; the first character is numbered 1;
  93.             // if (k > s.length) a runtime error will occur. Thus the terminating NUL-byte can't be modified.
  94.             // This is necessary to prevent corruption of the NString by altering it's terminator.
  95.             // Also, if (c == '\0') a runtime error will be raised, as placing a NUL character in the middle
  96.             //        of the NString would corrupt it.
  97.             // The return value is the character that formerly resided at index k in the NString.
  98.  
  99.         /*-------- Comparing NStrings --------*/
  100.  
  101.         inline int operator== (const char *s) const;                                    //        if (s == "Yes") ...;
  102.  
  103.         inline int operator!= (const char *s) const;                                    //        if (s != "No") ...;
  104.  
  105.         inline int operator>= (const char *s) const;                                    //        if (s >= "alpha") ...;
  106.  
  107.         inline int operator<= (const char *s) const;                                    //        if (s <= "beta") ...;
  108.  
  109.         inline int operator> (const char *s) const;                                        //        if (s > "alpha") ...;
  110.  
  111.         inline int operator< (const char *s) const;                                        //        if (s < "beta") ...;
  112.  
  113.         inline int compare (const char *s) const;                                        //        if (s.compare("Hello") == 0) ...;
  114.             // simply returns the result of strcmp()
  115.             //        zero means (*this == s)
  116.             //        greater than zero means (*this > s)
  117.             //        less than zero means (*this < s)
  118.  
  119.         inline int operator== (const NString& s) const;                                //        if (s == t) ...;
  120.  
  121.         inline int operator!= (const NString& s) const;                                //        if (s != t) ...;
  122.  
  123.         inline int operator>= (const NString& s) const;                                //        if (s >= t) ...;
  124.  
  125.         inline int operator<= (const NString& s) const;                                //        if (s <= t) ...;
  126.  
  127.         inline int operator> (const NString& s) const;                                //        if (s > t) ...;
  128.  
  129.         inline int operator< (const NString& s) const;                                //        if (s < t) ...;
  130.  
  131.         inline int compare (const NString& s) const;                                    //        if (s.compare(t) != 0) ...;
  132.             // simply returns the result of strcmp()
  133.             //        zero means (*this == s)
  134.             //        greater than zero means (*this > s)
  135.             //        less than zero means (*this < s)
  136.  
  137.         inline int operator== (const char c) const;                                    //        if (s == 'R') ...;
  138.  
  139.         inline int operator!= (const char c) const;                                        //        if (s != 'L') ...;
  140.  
  141.         inline int operator>= (const char c) const;                                        //        if (s >= 'A') ...;
  142.  
  143.         inline int operator<= (const char c) const;                                        //        if (s <= 'B') ...;
  144.  
  145.         inline int operator> (const char c) const;                                        //        if (s > 'A') ...;
  146.  
  147.         inline int operator< (const char c) const;                                        //        if (s < 'B') ...;
  148.  
  149.         inline int compare (const char c) const;                                            //        if (s.compare('N') == 0) ...;
  150.             //        0        means (*this == c)
  151.             //        1        means (*this > s)
  152.             //        -1    means (*this < s)
  153.  
  154.  
  155.         inline const NString& min (const NString& other) const;                    //        t = s.min(NString("help"));
  156.             //    return this NString if (*this < other), "other" otherwise.
  157.  
  158.         inline const NString& max (const NString& other) const;                    //        t = s.max(t);
  159.             //    return this NString if (*this > other), "other" otherwise
  160.  
  161.         /*-------- Concatenating NStrings --------*/
  162.  
  163.         // Note: An attempt to add a NUL character to an NString will always result in a runtime error.
  164.  
  165.         NString& operator+= (const char *s);                                            //        s += ".txt";
  166.             // extend an NString by adding a C-String
  167.  
  168.         NString& operator+= (const NString& s);                                        //        s += t;
  169.             // extend an NString by adding another NString
  170.  
  171.         NString& operator+= (const char c);                                            //        s += 'c';
  172.             // extend an NString by adding a character
  173.  
  174.         NString operator+ (const char *s) const;                                        //        u = s + ".sit";
  175.             // create a new NString that is the concatenation of
  176.             //        an NString with a C-String
  177.  
  178.         NString operator+ (NString& s) const;                                            //        u = s + t;
  179.             // create a new NString that is the concatenation of
  180.             //        two NStrings
  181.  
  182.         NString operator+ (const char c) const;                                        //        u = s + 'M';
  183.             // create a new NString that is the concatenation of
  184.             //        an NString with a character
  185.  
  186.         friend NString operator+ (const char *s, const NString& ns);            //     s = "***" + t;
  187.             // form a new NString by inserting a C-String at the
  188.             //        beginning of an NString.
  189.  
  190.         friend NString operator+ (const char c, const NString& ns);            //     s = '>' + t;
  191.             // form a new NString by adding a character to the
  192.             //        beginning of an NString.
  193.  
  194.         NString& operator*= (const unsigned long int k);                            //     s *= 2;
  195.             // change the NString to k times its original string
  196.             // k==0 results in an empty string; k==1 leaves the NString unchanged
  197.             
  198.         NString operator* (const unsigned long int k) const;                        //        s = t * 3;
  199.             // build a new NString consisting of the original string k times concatenated
  200.             // k==0 results in an empty string; k==1 returns a copy of the original NString
  201.  
  202.         /*-------- Copying parts of an NString --------*/
  203.  
  204.         NString fromto (unsigned long int from, unsigned long int to) const;    //        t = s.fromto(2,5)
  205.             // return an NString consisting of the substring of the original NString
  206.             // ranging from character # "from" to character # "to".
  207.             // The first character is counted as # 1, the last as # s.length().
  208.             // Both of the border characters are included in the new string.
  209.             // If either parameter is out of range, only the valid part is returned.
  210.             // If "from" > "to", an empty NString is returned.
  211.             
  212.         inline NString from (unsigned long int from) const;                        //        t = s.from(3);
  213.             // return the substring ranging from character # "from" to
  214.             //     the end of the original NString.
  215.             // This function is equivalent to "s.fromto(from, s.length())"
  216.             // The considerations stated under "fromto" apply.
  217.             
  218.         inline NString to (unsigned long int to) const;                                    //        t = s.to(5);
  219.             // return the substring ranging from the beginning of the
  220.             //     original NString to character # "to".
  221.             // This function is equivalent to "s.fromto(0, to)"
  222.             // The considerations stated under "fromto" apply.
  223.  
  224.         /*-------- Cutting parts out of an NString --------*/
  225.  
  226.         NString& cut(unsigned long int at, unsigned long int n);                    //        s.cut(3,2);
  227.             // remove the substring of length "n" starting at letter # "at".
  228.             //    (The first character of the string is character # 1.)
  229.             // If either parameter is out of range, only the valid part is cut.
  230.             // If n==0, no change is done to the NString.
  231.             // The function returns a reference to the modified NString; the
  232.             //        cut part is lost.
  233.  
  234.         /*-------- Iterator --------*/
  235.  
  236.         enum direction_t {FORWARD, BACKWARD};
  237.  
  238.         NString& through(int (*action)(const char, const unsigned long int, NString&), direction_t dir = FORWARD);
  239.             //    traverse the NString in the specified directon, calling at each step the given function.
  240.             // The "action" function receives as parameters the current character, its position in
  241.             //        the NString (starting from 1) and a reference to the NString being traversed.
  242.             //    If the NString is empty, the iterator does nothing.
  243.             //    If the NString is altered during iteration, these modifications will NOT affect the iteration
  244.             //        process, as the string being traversed is actually a copy of the original string.
  245.             //    The "action" may interrupt the iteration process by returning a non-zero value.
  246.             //        Zero must be returned for the iteration to proceed until the end of the string is reached.
  247.             //    The iterator returns a reference to the NString being traversed.
  248.             
  249.             //    Example: "s.through(&print, NString::BACKWARD)" where print() has been previously defined;
  250.  
  251.         /*-------- Transforming NStrings --------*/
  252.  
  253.         NString upcase (void) const;                                                        //        t = s.upcase();
  254.             //    get a new NString consisting of the original one converted to upper case.
  255.  
  256.         NString lowcase (void) const;                                                        //        t = s.lowcase();
  257.             //    get a new NString consisting of the original one converted to lower case.
  258.  
  259.         NString& toupcase (void);                                                            //        s.toupcase();
  260.             // convert this NString to uppercase.
  261.             
  262.         NString& tolowcase (void);                                                            //        s.tolowcase();
  263.             // convert this NString to lowercase.
  264.  
  265.         NString& clear (void);                                                                //        s.clear();
  266.             // clear this NString.
  267.  
  268.         /*-------- Getting context position in an NString --------*/
  269.  
  270.         unsigned long int leftpos (const char *s) const;                                //        k = s.leftpos("loop");
  271.  
  272.         unsigned long int leftpos (const char c) const;                                    //        k = s.leftpos('L');
  273.  
  274.         inline unsigned long int leftpos (const NString& s) const;                    //        k = s.leftpos(t);
  275.  
  276.         unsigned long int leftpos (const Alphabet& a) const;                            //        k = s.leftpos(alpha);
  277.             //    return the position of the leftmost occurrence of
  278.             //        the context in the NString.
  279.             //    The first character of the NString has position 1.
  280.             //    If an occurrence cannot be found, zero is returned.
  281.             //    If the context is an empty string, leftpos() returns 1,
  282.             //        as an empty string can be found everywhere.
  283.  
  284.  
  285.         unsigned long int rightpos (const char *s) const;                            //        k = s.rightpos("end");
  286.  
  287.         unsigned long int rightpos (const char c) const;                                //        k = s.rightpos('R');
  288.  
  289.         inline unsigned long int rightpos (const NString& s) const;                //        k = s.rightpos(t);
  290.  
  291.         unsigned long int rightpos (const Alphabet& a) const;                        //        k = s.rightpos(alpha);
  292.             //    return the position of the rightmost occurrence of
  293.             //        the context in the NString.
  294.             //    The first character of the NString has position 1.
  295.             //    If an occurrence cannot be found, zero is returned.
  296.             //    If the context is an empty string, rightpos() returns "s.length()+1",
  297.             //        as an empty string can be found everywhere.
  298.             // In the case of an alphabet-context, the result is the position
  299.             //        of the first letter that is encountered when scanning the NString
  300.             //        backwards AND that is contained in the alphabet. For example,
  301.             //        if "alpha" contains the letters 'a', 'm' and 'r', and the NString "s"
  302.             //        contains the string "Superman", the call "s.rightpos(alpha)"
  303.             //        returns the value 7, i.e. the position of the letter 'a'.
  304.  
  305.         /*-------- Copying context-dependant parts of an NString --------*/
  306.  
  307.         NString leftof (const char *context) const;                                        //        t = s.leftof("begin");
  308.  
  309.         NString leftof (const char context) const;                                        //        t = s.leftof('b');
  310.  
  311.         NString leftof (const NString& context) const;                                //        t = s.leftof(t);
  312.  
  313.         NString leftof (const Alphabet& context) const;                                //        t = s.leftof(alpha);
  314.             //    return the initial part of the NString not containing
  315.             //        the leftmost context occurrence.
  316.             // The result of this function will be:
  317.             //        • context occurrence not found: the entire NString
  318.             //        • context occurrence at position 1: an empty NString
  319.             //        • context occurrence not starting at position 1: "to(leftpos(context)-1)"
  320.  
  321.  
  322.         NString atleft (const char *context) const;                                        //        t = s.atleft("begin");
  323.  
  324.         NString atleft (const char context) const;                                        //        t = s.atleft('b');
  325.  
  326.         NString atleft (const NString& context) const;                                //        t = s.atleft(t);
  327.  
  328.         NString atleft (const Alphabet& context) const;                                //        t = s.atleft(alpha);
  329.             //    return the final part of the NString starting at the position of
  330.             //        the leftmost context occurrence.
  331.             // The result of this function will be:
  332.             //        • context occurrence not found: an empty NString
  333.             //        • context occurrence found and context is not empty string: "from(leftpos(context))"
  334.             //        • context is empty string: the entire NString
  335.             //    The following test will always yield true: (s == s.leftof(context) + s.atleft(context))
  336.  
  337.  
  338.         NString toleft (const char *context) const;                                        //        t = s.toleft("while");
  339.  
  340.         NString toleft (const char context) const;                                        //        t = s.toleft('w');
  341.  
  342.         NString toleft (const NString& context) const;                                //        t = s.toleft(t);
  343.  
  344.         NString toleft (const Alphabet& context) const;                                //        t = s.toleft(alpha);
  345.             //    return the initial part of the NString just containing the
  346.             //        leftmost occurrence of the context.
  347.             // The result of this function will be:
  348.             //        • context occurrence not found: the entire NString
  349.             //        • context occurrence found and context is not empty string: "to(leftpos(context) + context_length - 1)"
  350.             //        • context is empty string: an empty NString
  351.  
  352.  
  353.         NString leftcut (const char *context) const;                                    //        t = s.leftcut("while");
  354.  
  355.         NString leftcut (const char context) const;                                        //        t = s.leftcut('w');
  356.  
  357.         NString leftcut (const NString& context) const;                                //        t = s.leftcut(t);
  358.  
  359.         NString leftcut (const Alphabet& context) const;                                //        t = s.leftcut(alpha);
  360.             //    return the final part of the NString starting after
  361.             //        and not containing the leftmost occurrence of the context.
  362.             // The result of this function will be:
  363.             //        • context occurrence not found: an empty NString
  364.             //        • context is empty string: the entire NString
  365.             //        • context occurrence found and context is not empty string: "from(leftpos(context) + context_length)"
  366.             //    The following test will always yield true: (s == s.toleft(context) + s.leftcut(context))
  367.  
  368.  
  369.         NString rightof (const char *context) const;                                    //        t = s.rightof("begin");
  370.  
  371.         NString rightof (const char context) const;                                    //        t = s.rightof('b');
  372.  
  373.         NString rightof (const NString& context) const;                                //        t = s.rightof(t);
  374.  
  375.         NString rightof (const Alphabet& context) const;                            //        t = s.rightof(alpha);
  376.             //    return the final part of the NString not containing
  377.             //        the rightmost context occurrence.
  378.             // The result of this function will be:
  379.             //        • context occurrence not found: the entire NString
  380.             //        • context occurrence at the end of the string: an empty NString
  381.             //        • context occurrence not ending the string: "from(rightpos(context) + context_length)"
  382.  
  383.  
  384.         NString atright (const char *context) const;                                    //        t = s.atright("begin");
  385.  
  386.         NString atright (const char context) const;                                    //        t = s.atright('b');
  387.         
  388.         NString atright (const NString& context) const;                                //        t = s.atright(t);
  389.  
  390.         NString atright (const Alphabet& context) const;                            //        t = s.atright(alpha);
  391.             //    return the final part of the NString starting at the position of
  392.             //        the rightmost context occurrence.
  393.             // The result of this function will be:
  394.             //        • context occurrence not found: the entire NString
  395.             //        • context occurrence found and context is not empty string: "from(rightpos(context))"
  396.             //        • context is empty string: an empty NString
  397.  
  398.  
  399.         NString toright (const char *context) const;                                    //        t = s.toright("while");
  400.  
  401.         NString toright (const char context) const;                                    //        t = s.toright('w');
  402.  
  403.         NString toright (const NString& context) const;                                //        t = s.toright(t);
  404.  
  405.         NString toright (const Alphabet& context) const;                            //        t = s.toright(alpha);
  406.             //    return the initial part of the NString just containing the
  407.             //        rightmost occurrence of the context.
  408.             // The result of this function will be:
  409.             //        • context occurrence not found: an empty NString
  410.             //        • context occurrence found and context is not empty string: "to(rightpos(context) + context_length - 1)"
  411.             //        • context is empty string: the entire NString
  412.             //    The following test will always yield true: (s == s.toright(context) + s.rightof(context))
  413.  
  414.  
  415.         NString rightcut (const char *context) const;                                    //        t = s.rightcut("while");
  416.  
  417.         NString rightcut (const char context) const;                                    //        t = s.rightcut('w');
  418.  
  419.         NString rightcut (const NString& context) const;                            //        t = s.rightcut(t);
  420.  
  421.         NString rightcut (const Alphabet& context) const;                            //        t = s.rightcut(alpha);
  422.             //    return the initial part of the NString ending at
  423.             //        and not containing the rightmost occurrence of the context.
  424.             // The result of this function will be:
  425.             //        • context occurrence not found: an empty NString
  426.             //        • context occurrence found at the beginning of the string: an empty NString
  427.             //        • context is empty string: the entire NString
  428.             //        • context occurrence found and context is not empty string: "to(rightpos(context) - 1)"
  429.             //    The following test will always yield true: (s == s.rightcut(context) + s.atright(context))
  430.  
  431.  
  432.         inline char leftocc (const Alphabet& a) const;                                    //        c = s.leftocc(Alphabet("abc"));
  433.             // of the letters contained in the alphabet, return the one that 
  434.             //        has the leftmost position in the NString. If there is no such letter
  435.             //        in the alphabet, the NUL-character ('\0') is returned, as this
  436.             //        character cannot be part of any NString.
  437.  
  438.         inline char rightocc (const Alphabet& a) const;                                //        c = s.rightocc(Alphabet("abc"));
  439.             // of the letters contained in the alphabet, return the one that 
  440.             //        has the rightmost position in the NString. If there is no such letter
  441.             //        in the alphabet, the NUL-character ('\0') is returned, as this
  442.             //        character cannot be part of any NString.
  443.  
  444.  
  445.         friend NString span (const char context, const NString& s);                //        t = span('-', s);
  446.  
  447.         friend NString span (const Alphabet& context, const NString& s);        //        t = span(alpha, s);
  448.             //    return the initial substring of the NString "s" that
  449.             //        consists of nothing but "context"-characters.
  450.             // e.g: span("-", NString("--Test==")) would return "--".
  451.  
  452.         friend NString span (const NString& s, const char context);                //        t = span(s, '*');
  453.  
  454.         friend NString span (const NString& s, const Alphabet& context);        //        t = span(s, alpha);
  455.             //    return the final substring of the NString "s" that
  456.             //        consists of nothing but "context"-characters.
  457.             
  458.             
  459.         friend NString operator- (const char c, const NString& s);                //        t = '*' - s;
  460.  
  461.         friend NString operator- (const Alphabet& ctx, const NString& s);    //        t = alpha - s;
  462.             //    return the final part of the NString "s" that remains
  463.             //        when all of the initial occurrences of the context
  464.             //        have been stripped.
  465.             
  466.         NString operator- (const char c) const;                                            //        t = s - ')';
  467.  
  468.         NString operator- (const Alphabet& ctx) const;                                //        t = s - alpha;
  469.             //    return the initial part of the NString that remains
  470.             //        when all of the final occurrences of the context
  471.             //        have been stripped.
  472.             
  473.         NString& operator-= (const char c);                                            //        s -= '0';
  474.  
  475.         NString& operator-= (const Alphabet& ctx);                                    //        s -= alpha;
  476.             //    remove all of the initial occurrences of the context
  477.             //        from the NString.
  478.  
  479.         /*-------- Context-related tests --------*/
  480.  
  481.         inline int startswith (const char *context) const;                            //        if (s.startswith("repeat")) ...
  482.  
  483.         inline int startswith (const char context) const;                                //        if (s.startswith('Q')) ...
  484.  
  485.         inline int startswith (const NString& context) const;                        //        if (s.startswith(t)) ...
  486.  
  487.         inline int startswith (const Alphabet& context) const;                        //        if (s.startswith(alpha)) ...
  488.             //    return non-zero if the NString starts with the given context,
  489.             //        zero otherwise.
  490.  
  491.  
  492.         int endswith (const char *context) const;                                        //        if (s.endswith("repeat")) ...
  493.  
  494.         inline int endswith (const char context) const;                                //        if (s.endswith('Q')) ...
  495.  
  496.         inline int endswith (const NString& context) const;                            //        if (s.endswith(t)) ...
  497.  
  498.         inline int endswith (const Alphabet& context) const;                        //        if (s.endswith(alpha)) ...
  499.             //    return non-zero if the NString ends with the given context,
  500.             //        zero otherwise.
  501.  
  502.  
  503.         inline int contains (const char *context) const;                                //        if (s.contains("take")) ...
  504.  
  505.         inline int contains (const char context) const;                                //        if (s.contains('<')) ...
  506.  
  507.         inline int contains (const NString& context) const;                            //        if (s.contains(t)) ...
  508.  
  509.         inline int contains (const Alphabet& context) const;                        //        if (s.contains(alpha)) ...
  510.             //    return non-zero if the NString (entirely) contains the given context,
  511.             //        zero otherwise. In the case of an alphabet, this means that
  512.             //        EVERY letter of the alphabet must be contained in the NString.
  513.             // If "context" is an empty alphabet, non-zero is returned.
  514.  
  515.  
  516.         inline int disjointed (const Alphabet& alpha) const;                            //        if (s.disjointed(alpha)) ...
  517.             // return non-zero iff none of the alphabet's letters
  518.             //        occurs in the NString, zero otherwise.
  519.             // If "alpha" is empty, non-zero is returned.
  520.  
  521.  
  522.         /*-------- Input / Output --------*/
  523.  
  524.         friend ostream& operator<< (ostream& theStream, const NString& theString);    //        cout << s;
  525.             // output the NString onto the stream "theStream".
  526.             // Field width and fill character are supported in the same way
  527.             //        as for C-strings.
  528.  
  529.         friend istream& operator>> (istream& theStream, NString& theString);            //        cin >> s;
  530.             // skip whitespace, then input a character string from "theStream"
  531.             //        and store it in "theString". Whitespace following the string
  532.             //        is treated as terminator and left on the stream for subsequent reads.
  533.             // The NUL character is considered whitespace in this context.
  534.             // Field width and the "ios::skipws" flag are currently ignored.
  535.             // If the operator is used on a stream that is not in good condition,
  536.             //        the operation is a null operation and "theString" is left unmodified.
  537.             // Note that a call like "cin >> s" is perfectly safe if "s" is an NString,
  538.             //        as NStrings dynamically allocate the needed memory.
  539.             
  540.         friend istream& get (istream& theStream, NString& theString,
  541.                                         const unsigned long int maxLength, const char terminator = '\n');
  542.             // input characters from the stream "theStream" into the NString "theString",
  543.             //        but don't make the string any longer than "maxLength".
  544.             //        If "maxLength" == 0, this constraint is ignored.
  545.             // If a "terminator" character is encountered, it is left on the stream for
  546.             //        subsequent reads and the current input process terminates.
  547.             //        "terminator" may be set to '\0', if no special terminator character is
  548.             //        desired.
  549.             // Whitespace is treated as any other character.
  550.             //    NUL characters preceding useful string data are skipped.
  551.             // A NUL character following string data always acts like a terminator.
  552.             // If the function is used on a stream that is not in good condition,
  553.             //        the operation is a null operation and "theString" is left unmodified.
  554.  
  555.         friend inline istream& get (istream& theStream, NString& theString, const char terminator = '\n');
  556.             // equivalent to the preceding "get()" function, but without string length limitation.
  557.  
  558.  
  559.         inline NString& operator<< (const char *s);
  560.         inline NString& operator<< (const NString& s);
  561.         inline NString& operator<< (const char c);
  562.         NString& operator<< (const unsigned long int n);
  563.         NString& operator<< (const signed long int n);
  564.         NString& operator<< (const unsigned short int n);
  565.         NString& operator<< (const signed short int n);
  566.         NString& operator<< (const double n);
  567.         NString& operator<< (const float n);
  568.         NString& operator<< (const void *p);
  569.         inline NString& operator<< (NString& (*manip)(NString&));
  570.         
  571.             // append the given data to the NString "out". This way an NString can be used
  572.             // in a way similar to an output string stream. For example, if s is an empty
  573.             // NString and t is an NString containing "apple", the following line:
  574.             //        s << "I don't know the word " << t << '.';
  575.             // would write the string "I don't know the word apple." into s.
  576.             //
  577.             // In this version, the following conventions have been used:
  578.             //     • floats are output with 6 decimal digits, doubles with 12;
  579.             //     • integers are converted as decimal values.
  580.  
  581.         friend inline NString& endl (NString& s);
  582.         friend inline NString& clear (NString& s);
  583.             // Currently, the only manipulators that are defined are "endl" and "clear",
  584.             // used to append '\n' to, resp. to clear the NString. Using other predefined manipulators,
  585.             // such as "hex" or "setprecision" does not yet produce the desired effect.
  586.             // Other manipulators may be defined by the class user, though.
  587.  
  588.  
  589.         /*-------- Memory Management --------*/
  590.  
  591.         static int SetBufferSizeStep (unsigned long int NewSizeStep);
  592.             // permit the class-user to change the Buffer Size Step value. Buffer size for any NString
  593.             //        will be kept at a multiple bytes of this value. NewSizeStep must be a strictly positive
  594.             //        integer. The function returns 0 on failure, 1 on success.
  595.             //        The default Buffer Size Step is 100 bytes.
  596.             
  597.         static unsigned long int GetBufferSizeStep (void);
  598.             // return the current Buffer Size Step value.
  599.  
  600.         static int SetDeallocationTrigger (float NewValue);
  601.             // set a new value for DeallocationTrigger. This value ranging from 0.0 to 0.99
  602.             //        assures that an additional BufferSizeStep bytes that have been allocated are not
  603.             //        freed when the new buffer size would drop just below the next BufferSizeStep limit.
  604.             // Example: Suppose you have a string of 102 bytes and the default values for BufferSizeStep (100 bytes)
  605.             //        and DeallocationTrigger (0.2, the equivalent of 20%). The string's internal buffer has thus
  606.             //        been sized at 200 bytes. By now cutting out of this string a substring of, let's say, 20 bytes,
  607.             //        the string length drops to 82 bytes. Still, the internal buffer size remains unchanged (200 bytes)
  608.             //        until the string is shortened by a further 3 bytes, because the limit is situated at 80 bytes,
  609.             //        which represent 80% of the current BufferSizeStep. You can set this limit by specifying a
  610.             //        DeallocationTrigger value equal to the remaining 20% necessary to complete the unit.
  611.             //    This technique avoids frequent buffer reallocations for strings that often change their size
  612.             //        as long as it stays close to a multiple of BufferSizeStep. "SetDeallocationTrigger()" returns
  613.             //        0 if the new value could not be accepted, 1 on success.
  614.         
  615.         static float GetDeallocationTrigger (void);
  616.             // return the current DeallocationTrigger value.
  617.  
  618.  
  619.         /*-------- Error Handling --------*/
  620.         
  621. #ifdef USE_EXCEPTIONS
  622.  
  623.         class Exception
  624.         {
  625.             public:
  626.             
  627.                 enum { MAX_MSG_LENGTH = 255 };
  628.                 
  629.                 const unsigned long int ErrorLine;
  630.                 char ErrorFile[MAX_MSG_LENGTH + 1];
  631.                 char ErrorFunction[MAX_MSG_LENGTH + 1];
  632.                 char ErrorMessage[MAX_MSG_LENGTH + 1];
  633.                 
  634.                 Exception (const unsigned long int line, const char *file, const char *function, const char *message);
  635.  
  636.                 ~Exception (void) {}
  637.                     
  638.                 virtual void PrintError (ostream& theStream = cerr);
  639.         };
  640.         
  641.         class OutOfMemory : public Exception
  642.         {
  643.             public:
  644.                 OutOfMemory (const unsigned long int line, const char *file, const char *function)
  645.                     : Exception (line, file, function, "Out of memory") {}
  646.         };
  647.  
  648.         class UsageError : public Exception
  649.         {
  650.             public:
  651.                 UsageError (const unsigned long int line, const char *file, const char *function, const char *message)
  652.                     : Exception (line, file, function, message) {}
  653.         };
  654.  
  655.         // Note: Generally, if an exception is thrown, the NString remains in a coherent state.
  656.         //            Still, in certain cases, the NString may already have been modified before the error condition
  657.         //            was detected.
  658.  
  659. #else
  660.         
  661.         static void (*panic)(const unsigned long int line, const char *file,
  662.                                         const char *function, const char *message);
  663.             // vector pointing to a (fatal) error-handling routine for systems without exception support.
  664.             // The vector may be altered by the user to point to a user-defined error-handling routine.
  665.             // CAUTION: The routine pointed to by this vector MUST NOT return to the caller !!
  666.  
  667.         static void NString_Error (const unsigned long int line, const char *file,
  668.                                                 const char *function, const char *message);
  669.             // primitive error-handling routine for compiling on those systems that do not yet have
  670.             // exception handling support. Prints a message to standard out, then exits with return code 1.
  671.             
  672. #endif
  673.         
  674.  
  675.     private:
  676.         
  677.         struct strbody
  678.         {
  679.             unsigned long int len;                    // the string's length, without the terminating NUL
  680.             unsigned long int bufsize;                // the size of the buffer pre-allocated for the string data
  681.             char *str;                                    // the string as a null-terminated C-String
  682.             unsigned int refs;                        // the number of instances that currently use this strbody
  683.             
  684.             inline strbody();                        // constructor to initialize a strbody struct
  685.         };
  686.         
  687.         strbody *sb;                                    // the instance's pointer to the actual (shared) data
  688.         
  689.         
  690.         int DuplicateSB (void);
  691.             // duplicate the current string body (including its string buffer), then connect self to the copy.
  692.             //     Will NOT deallocate the old body, even if now unused,
  693.             //  thus should not be called when (sb->refs == 1).
  694.             // If duplication fails, the current string body remains untouched and zero is returned.
  695.             // A non-zero value is returned on success.
  696.  
  697.         int GetNewSB (unsigned long int new_length);
  698.             // disconnect self from old string body, then replace it by a new one of length "new_length".
  699.             // Actual buffer "sb->str" will have length "new_length"+1 (plus the bytes necessary to make
  700.             // the size a multiple of BufferSizeStep).
  701.             // A zero-byte is placed automatically at the ending position of the future string in the buffer,
  702.             // even though the buffer is not yet completely initialized. Also, the new length is inscribed
  703.             // into the new string body.
  704.             // If allocation fails, the current string body remains untouched and zero is returned.
  705.             // A non-zero value is returned on success.
  706.         
  707.         NString (const unsigned long int l);
  708.             // constructor: create an uninitialized NString with a bufferlength of (at least) "l+1".
  709.             // A zero-byte is placed automatically at the ending position of the future string in the buffer,
  710.             // even though the buffer is not yet completely initialized.
  711.         
  712.  
  713.         static unsigned long int BufferSizeStep;
  714.             // the buffer size for any NString will be kept at a multiple bytes of this value. May be modified
  715.             // with the public method "SetBufferSizeStep()".
  716.             
  717.         static float DeallocationTrigger;
  718.             // see the explanation for the public routine "SetDeallocationTrigger()" ...
  719.  
  720.         static unsigned long int DeallocationMargin;
  721.             // when a buffer size decrease of exactly BufferSizeStep bytes is asked, it is only done
  722.             // if there is at least a distance of DeallocationMargin bytes between the non-aligned new size
  723.             // and the next multiple of BufferSizeStep. This value is set internally based on the formula:
  724.             // DeallocationMargin = DeallocationTrigger * BufferSizeStep
  725.  
  726.  
  727.         char *AllocStrBuf (unsigned long int size);
  728.             // try to allocate the nearest multiple to "size+1" of "BufferSizeStep" bytes for the
  729.             // string buffer inside the current stringbody, then inscribe string length (== "size")
  730.             // and actual buffer size (multiple of "BufferSizeStep") into the stringbody.
  731.             // This is a low level routine that ignores the number of references to the stringbody.
  732.             // Return the pointer to the allocated memory block, NULL on failure.
  733.             // If the allocation fails, the string body is left unchanged.
  734.             
  735.         char *ReallocStrBuf (unsigned long int size);
  736.             // try to modify the size of the current stringbody's buffer to the nearest multiple to "size+1"
  737.             // of "BufferSizeStep" bytes. Inscribe the new buffer size into the stringbody.
  738.             // The new length of the string is NOT inscribed in the string body; this must be done by the caller !
  739.             // This is a low level routine that ignores the number of references to the stringbody.
  740.             // Return the pointer to the new memory block, NULL on failure.
  741.             // If the reallocation fails, the string body is left unchanged.
  742.  
  743. #ifndef USE_EXCEPTIONS
  744.  
  745.         static void Out_of_Memory (unsigned int line, const char *file, const char *function);
  746.             //    prepare "out of memory" message to pass to the "panic" routine.
  747.             // Useful on systems without exception support.
  748.  
  749. #endif
  750.  
  751.         /*-------- Friends in the alphabet class --------*/
  752.  
  753.         friend Alphabet::Alphabet (const NString& source);
  754.         friend Alphabet& Alphabet::operator= (const NString& source);
  755.         friend Alphabet& Alphabet::operator+= (const NString& source);
  756.         friend inline Alphabet Alphabet::operator+ (const NString& source) const;
  757.         friend Alphabet& Alphabet::operator-= (const NString& source);
  758.         friend int Alphabet::contains (const NString& elements) const;
  759.         friend inline Alphabet& Alphabet::operator*= (const NString& string);
  760.         friend inline Alphabet Alphabet::operator* (const NString& string) const;
  761.         friend inline int Alphabet::operator== (const NString& other) const;
  762.         friend inline int Alphabet::operator!= (const NString& other) const;
  763.         friend inline int Alphabet::operator<= (const NString& other) const;
  764.         friend inline int Alphabet::operator< (const NString& other) const;
  765.         
  766.         
  767.         // SOME WORDS ON COMPILING:
  768.         //
  769.         //        When compiling the NString and Alphabet classes, you may define
  770.         //     the macro NSTRING_DEBUG to be a non-zero value. According to the bits
  771.         //        that are set in NSTRING_DEBUG, various information is written to stdout:
  772.         //        set bit 0 to show calls to Alphabet constructors;
  773.         //        set bit 1 to show calls to NString constructors and destructors;
  774.         //        set bit 2 to show memory allocation concerning the NString internal buffer.
  775.         //
  776.         //        Furthermore, you may compile the classes with the macro USE_EXCEPTIONS defined
  777.         //        to create exception-supporting code.
  778.         //
  779.         //        WARNING: Be sure to use the same compiler settings when compiling a project
  780.         //        that uses a precompiled version of the NString/Alphabet classes, as were used
  781.         //        when compiling the library. It would be a good idea to use standard ANSI settings
  782.         //        in both cases. For example, tell the compiler to always treat "enums" as "ints",
  783.         //        otherwise some functions that take "enum" parameters, such as "NString::through()"
  784.         //        or "Alphabet::through()" will probably cause your program to crash !
  785.  
  786.  
  787.         // NEEDED STUFF FOR CLASS USAGE:
  788.         //
  789.         //        Once the NString and Alphabet classes are compiled into a library or an object file,
  790.         //        you will need to link it into your application to use it. Moreover, the following
  791.         //        include files must remain accessible, and should be stored together in one directory:
  792.         //
  793.         //        - NString.h
  794.         //        - Alphabet.h
  795.         //        - NString_Inlines.h
  796.         //        - Alphabet_Inlines.h
  797.         //
  798.         //        Usually it will suffice that you #include "NString.h", the other files are included
  799.         //        automatically. If usage of the Alphabet class is desired without the need for NString,
  800.         //        it should be sufficient to #include "Alphabet.h".
  801.         //
  802.         //        It is also necessary to link your projects with a library containing the iostreams
  803.         //        routines, otherwise you might get link errors, as NString uses these routines.
  804.         
  805. };
  806.  
  807. #include "NString_Inlines.h"
  808.  
  809. #endif
  810.