Introduction of class SuperString
authorArjen Baart <arjen@andromeda.nl>
Fri, 12 Jun 2020 08:07:38 +0000 (10:07 +0200)
committerArjen Baart <arjen@andromeda.nl>
Fri, 12 Jun 2020 08:07:38 +0000 (10:07 +0200)
23 files changed:
ChangeLog
TODO
doc/Makefile.am
doc/UTC.html [deleted file]
doc/complex.html [deleted file]
doc/hour.html [deleted file]
doc/index.html [deleted file]
doc/manual.xml
doc/string.html [deleted file]
doc/string.xml
doc/superstring.xml [new file with mode: 0644]
src/Makefile.am
src/String.h
src/string.cpp
src/superstring.cpp [new file with mode: 0644]
test/Makefile.am
test/string_cat.cpp
test/string_split_join.cpp [new file with mode: 0644]
test/superstring_assign.cpp [new file with mode: 0644]
test/superstring_assign.exp [new file with mode: 0644]
test/superstring_basics.cpp [new file with mode: 0644]
test/superstring_basics.exp [new file with mode: 0644]
test/superstring_cat.cpp [new file with mode: 0644]

index b959431..0b1e076 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Jun 11, 2020 - Release 0.3.1
+============================
+
+  - Introduction of class SuperString
+
 Feb 07, 2020 - Release 0.3
 ============================
 
diff --git a/TODO b/TODO
index b5014a3..12b3b72 100644 (file)
--- a/TODO
+++ b/TODO
@@ -16,3 +16,4 @@ Things to do:
 - UTC: Convert to and from time_t, struct tm
 
 - xml: Add access to attributes
+- xml: Xinclude processing
index cb8ac88..ad337d8 100644 (file)
@@ -7,7 +7,7 @@ SUFFIXES = .obj .eps .png
 .obj.eps:
        tgif -print -eps -color $<
 
-XMLS = manual.xml string.xml date.xml hour.xml utc.xml Integer.xml xml.xml
+XMLS = manual.xml string.xml superstring.xml date.xml hour.xml utc.xml Integer.xml xml.xml
 IMAGES=
 
 PICTURES=
diff --git a/doc/UTC.html b/doc/UTC.html
deleted file mode 100644 (file)
index 9575996..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-<html>
-<head>
-<title>UTC - ANDROMEDA CLASS LIBRARY</title>
-</head>
-<body bgcolor=white>
-
-<h2> NAME</h2>
-UTC - Universal Time Coordinated class
-<h2> SYNOPSIS</h2>
-<pre>
-#include <date.h>
-
-UTC clock;
-</pre>
-<h2> DESCRIPTION</h2>
-
-
-<h3>Construction</h3>
-
-<h5>UTC()</h5>
-<h5>UTC(date d, hour t)</h5>
-<h5>UTC(string)</h5>
-
-<h3>Assignment</h3>
-
-<h5>operator=(string &)</h5>
-
-<h3>Conversion</h3>
-
-<h5>string()</h5>
-
-<h3>Relational operations</h3>
-
-<h5>operator==(UTC &)</h5>
-<h5>operator!=(UTC &)</h5>
-<h5>operator&lt;(UTC &)</h5>
-<h5>operator&lt;=(UTC &)</h5>
-<h5>operator&gt;(UTC &)</h5>
-<h5>operator&gt;=(UTC &)</h5>
-
-<h3>Attributes</h3>
-
-<h5>date day()</h5>
-<h5>hour hour()</h5>
-
-<h3>Arithmetic</h3>
-
-<h5>UTC operator+(UTC &t1, UTC &t2)</h5>
-<h5>UTC operator-(UTC &t1, UTC &t2)</h5>
-<h5>UTC &operator+=(UTC &t)</h5>
-<h5>UTC &operator-=(UTC &t)</h5>
-<h5>UTC &operator++()</h5>
-<h5>UTC &operator--()</h5>
-
-<h3>Stream I/O</h3>
-
-<h5>ostream &operator<<(ostream &str, UTC &t)</h5>
-<h5>istream &operator>>(istream &str, UTC &t)</h5>
-
-<h2> SEE ALSO</h2>
-
-<a href="date.html">date</a>
-<a href="hour.html">hour</a>
-
-<h2> DIAGNOSTICS</h2>
-
-</body>
-</html>
diff --git a/doc/complex.html b/doc/complex.html
deleted file mode 100644 (file)
index a73eb32..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>complex - ANDROMEDA CLASS LIBRARY</TITLE>
-<!--Created by Applixware HTML Authoring System, Release 4.3 on Fri Jun 19 13:20:00 1998-->
-</HEAD>
-<BODY BGCOLOR="#ffffff">
-<H2>NAME</H2>
-<P>complex - Complex number arithmetic</P>
-<H2>SYNOPSIS</H2>
-<P>complex z;</P>
-<H2>DESCRIPTION</H2>
-<P>The <I>complex</I> class encapsulates a comples number consisting of a real
-and an imaginary part.</P>
-<H3>Construction</H3>
-<H3>Assignment</H3>
-<H3>Conversion</H3>
-<H3>Relational Operators</H3>
-<H3>Attributes</H3>
-<H3>Arithmetic</H3>
-<H3>Mathematical operations</H3>
-<H3>Stream I/O</H3>
-<H2>SEE ALSO</H2>
-<H2>DIAGNOSTICS</H2>
-</BODY>
-</HTML>
diff --git a/doc/hour.html b/doc/hour.html
deleted file mode 100644 (file)
index 5539b9d..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-<html>
-<head>
-<title>hour - ANDROMEDA CLASS LIBRARY</title>
-</head>
-<body bgcolor=white>
-
-<h2> NAME</h2>
-hour - Time class
-<h2> SYNOPSIS</h2>
-<pre>
-#include <date.h>
-
-hour t;
-</pre>
-<h2> DESCRIPTION</h2>
-
-The <em>hour</em> class encapsulates a time in hours, minutes and seconds.
-
-<h3>Construction</h3>
-
-<h5>hour()</h5>
-<h5>hour(int hour, short minute, short second)</h5>
-<h5>hour(string)</h5>
-
-Format is HH:MM:SS
-
-<h5>hour(long)</h5>
-
-A number of seconds.
-
-<h3>Assignment</h3>
-
-<h5>operator=(hour &)</h5>
-<h5>operator=(string &)</h5>
-<h5>operator=(long)</h5>
-
-<h3>Conversion</h3>
-
-<h5>long()</h5>
-
-Converts to a number of seconds.
-
-<h5>string()</h5>
-
-<h3>Relational operations</h3>
-
-<h5>operator==(hour &)</h5>
-<h5>operator!=(hour &)</h5>
-<h5>operator&lt;(hour &)</h5>
-<h5>operator&lt;=(hour &)</h5>
-<h5>operator&gt;(hour &)</h5>
-<h5>operator&gt;=(hour &)</h5>
-
-<h3>Attributes</h3>
-
-<h5>int hour()</h5>
-<h5>short minute()</h5>
-<h5>short second()</h5>
-
-<h3>Arithmetic</h3>
-
-<h5>hour operator+(hour &t1, hour &t2)</h5>
-<h5>hour operator-(hour &t1, hour &t2)</h5>
-<h5>hour &operator+=(hour &t)</h5>
-<h5>hour &operator-=(hour &t)</h5>
-<h5>hour &operator++()</h5>
-<h5>hour &operator--()</h5>
-
-<h3>Stream I/O</h3>
-
-<h5>ostream &operator<<(ostream &str, hour &t)</h5>
-<h5>istream &operator>>(istream &str, hour &t)</h5>
-
-<h2> SEE ALSO</h2>
-
-<a href="date.html">date</a>
-<a href="UTC.html">UTC</a>
-
-<h2> DIAGNOSTICS</h2>
-
-</body>
-</html>
diff --git a/doc/index.html b/doc/index.html
deleted file mode 100644 (file)
index d5668a1..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>ANDROMEDA CLASS LIBRARY Class index</TITLE>
-<!--Created by Applixware HTML Authoring System, Release 4.3 on Mon Jun 22 10:51:41 1998-->
-</HEAD>
-<BODY BGCOLOR="#ffffff">
-<UL>
-<LI><A HREF="string.html">string</A>
-<LI><A HREF="date.html">date</A>
-<LI><A HREF="hour.html">hour</A>
-<LI><A HREF="UTC.html">UTC</A>
-<LI><A HREF="complex.html">complex</A>
-<LI><A HREF="../GNU/index.html">GNU Standard C++ library</A>
-<LI>???</UL>
-</BODY>
-</HTML>
index 32e8d08..629da30 100644 (file)
@@ -7,6 +7,8 @@
     <toc/>
     <xi:include href="string.xml"
          xmlns:xi="http://www.w3.org/2001/XInclude"/>
+    <xi:include href="superstring.xml"
+         xmlns:xi="http://www.w3.org/2001/XInclude"/>
     <xi:include href="date.xml"
          xmlns:xi="http://www.w3.org/2001/XInclude"/>
     <xi:include href="hour.xml"
diff --git a/doc/string.html b/doc/string.html
deleted file mode 100644 (file)
index e9121e1..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>string - ANDROMEDA CLASS LIBRARY</TITLE>
-<!--Created by Applixware HTML Authoring System, Release 4.3 on Fri Jun 19 11:53:50 1998-->
-</HEAD>
-<BODY BGCOLOR="#ffffff">
-<H1>class string</H1>
-<CENTER>
-<HR ALIGN=CENTER SIZE=1>
-</CENTER>
-<H2>NAME</H2>
-<P>String - C++ string class</P>
-<H2>SYNOPSIS</H2>
-<PRE>
-<P>#include &lt;Stringc.h&gt;</P>
-</PRE>
-<H2>DESCRIPTION</H2>
-<P>The C++ String class can be used to represent character strings and perform
-operation upon them. Many operations are defined for normal operators but may
-have different semantics. E.g. the + operator is used to concatenate (add)
-strings together.</P>
-<P>Substrings may be selected from strings to create other strings. Also,
-substrings have lvalue semantics, meaning a string may be assigned to a
-substring expression.</P>
-<H3>Construction and assignment.</H3>
-<P><B>String()</B></P>
-<P>The default constructor creates an empty string.</P>
-<P><B>String(const char *)</B></P>
-<P><B>String(char)</B></P>
-<P><B>String(const String &amp;)</B></P>
-<P>Other constructors are provided to initialize strings from character
-pointers, single characters or other strings. These constuctors also take care
-of typecasting:</P>
-<PRE>
-<P>String x;          // Contruct an empty string
-String abc(&quot;abc&quot;); // Convert a char * to a string
-String p('p');     // A string with one character in it.
-</P>
-</PRE>
-<P>Another string (or string expression), a char* or a single character can be
-assigned to a string:</P>
-<PRE>
-<P>String x, y;
-
-x = &quot;abc&quot;;
-y = x;
-x = 'p';</P>
-</PRE>
-<H3>Relational operators.</H3>
-<P>All relational operators (==, != , &lt;, &lt;=, &gt; and &gt;=) are
-available to compare strings alphabethically. Note that the comparison is done
-in the local character set, which will be ASCII in most cases. This also means
-that case is significant.</P>
-<H3>Adding strings together.</H3>
-<P>String can be added together, i.e. concatenated, with the <B>+</B>
-operator. Of course, the <B>+= </B>operator can be used as well. Example:
-</P>
-<PRE>
-<P>String x, y, z;
-
-x = &quot;abc&quot;
-y = &quot;def&quot;
-z = x + y;   //  z = &quot;abcdef&quot;
-y += x;      //  y = &quot;defabc&quot;</P>
-</PRE>
-<H3>String length, testing and character access</H3>
-<P>The length of a string can be determined with the <B>~ </B>operator. Do not
-confuse this with the bit-wise inversion operator !</P>
-<PRE>
-<P>String x = &quot;Hello&quot;;
-int    l = ~x;      // l = 5</P>
-</PRE>
-<P>The test for an empty string is done with the <B>! </B>operator. Note that
-there is no test for a non-empty string.</P>
-<PRE>
-<P>if (!x)
-   cout &lt;&lt; &quot;String x is empty\n&quot;;</P>
-</PRE>
-<P>Access to individual characters is provided like in ordinary C strings. The 
-<B>[] </B>operator selects an individual character for both read and write access:
-</P>
-<PRE>
-<P>String x = &quot;Hello&quot;;
-
-char c = x[1];       // c = 'e'
-x[2] = 'L';          // x = &quot;HeLlo&quot;</P>
-</PRE>
-<H3>Substring expressions.</H3>
-<P>A substring is a part of a string denoted by its start index and its
-length. The start index is counted from zero. To extract a substring from a
-string use:</P>
-<PRE>
-<P>String x = &quot;abcdefghijkl&quot;;
-String y = x(3,5);         // y = &quot;defgh&quot;</P>
-</PRE>
-<P>A substring expression can also be used as an lvalue. This means that a
-string can be assigned to a substring. The length of the substring does not
-need to be equal to the length of the string that is assigned to it.</P>
-<PRE>
-<P>String x = &quot;abcdefghijkl&quot;;
-String y = &quot;12345678&quot;;
-
-x(3,5) = y;           // x = &quot;abc12345678ijkl&quot;</P>
-</PRE>
-<P>Note that assigning a string to a zero-length substring will simply insert
-the a string into another string. Reversely, assigning an empty string to a
-substring will remove the characters from the original string. This property
-can be used to truncate a string to its first n characters by:</P>
-<PRE>
-<P>x(n, ~x-n) = &quot;&quot;;</P>
-</PRE>
-<H3>Numerical Conversion</H3>
-<P>Strings are coverted to and from numerical types (integer or floating
-point) by constructors and conversion operators. A numerical value is
-converted to a string with the number constructor:</P>
-<PRE>
-<P>String n(12);   // n = &quot;12&quot;</P>
-<P>String x(2.32); // x = &quot;2.32&quot;</P>
-</PRE>
-<P>These functions use a default format to convert the number to a string.
-Specifically, an integer is converted with the &quot;%d&quot; format from
-printf and a floating point is converted with the &quot;%g&quot; format.
-</P>
-<P>A string is converted to a number with the type-casting operators: operator
-long() and operator double(). The conversion to a long integer recognizes C
-syntax for numerical literals. Numbers starting with '0' are regarded as octal
-and numbers starting with '0x' are regarded as hexadecimal.</P>
-<P>Special member functions allow conversion of strings to and from numbers in
-a specific format. The functions dec(), oct() and hex() convert the string
-using decimal, octal and hexadecimal, respectively.</P>
-<H3>Shifting</H3>
-<P>Shifting a string moves all characters in the string a number of places to
-the left or to the right. Characters on the other end of the string simply
-fall off. Unlike shifting a binary number, shifting a string does not pad the
-string. Rather, shifting a string <I>n</I> places either to the left or to the
-right, renders the string <I>n</I> characters shorter. Example:</P>
-<PRE>
-<P>&quot;abcdefgh&quot; &lt;&lt; 3 = &quot;defgh&quot;</P>
-<P>&quot;abcdefgh&quot; &gt;&gt; 3 = &quot;abcde&quot;</P>
-</PRE>
-<P>The shift operators &lt;&lt; and &gt;&gt; can be combined with assignment:
-&lt;&lt;= and &gt;&gt;=.</P>
-<P>Do not confuse these shift operators with stream I/O operators.</P>
-<H3>Operations</H3>
-<H5>String upper(void)</H5>
-<P>Convert the string to all upper-case characters.</P>
-<H5>String lower(void)</H5>
-<P>Convert the string to all lower-case characters.</P>
-<H3>Pattern matching</H3>
-<H5>int in(String &amp;x)</H5>
-<P>Find the string x within the string. Returns the index where <I>x</I> was
-found. Returns -1 if x was not found in the string. see also strstr().
-</P>
-<H3>Stream I/O.</H3>
-<P>A string can be written to a stream like any other type with the <B>&lt;&lt;
-</B>operator. The left hand side of the expression must be a stream. To read a
-string from a stream, use the <B>&gt;&gt; </B>operator, with a stream on the
-left hand side:</P>
-<PRE>
-<P>String x;
-
-cin &gt;&gt; x;
-cout &lt;&lt; x;</P>
-</PRE>
-<P>Note that reading a string from a istream behaves like reading a character
-array from an istream. I.e., characters are read from the stream until the
-first whitespace character.</P>
-<H2>SEE ALSO</H2>
-<P>Bjarne Stroustrup, Section 6.9,<BR>
-DDJ October 1991, pg 24</P>
-<H2>DIAGNOSTICS</H2>
-</BODY>
-</HTML>
index cf53e99..998bfcd 100644 (file)
@@ -111,6 +111,7 @@ char c = x[1];       // c = 'e'
 x[2] = 'L';          // x = &quot;HeLlo&quot;
 </example>
 </section>
+
 <section>
 <heading>Substring expressions.</heading>
 
diff --git a/doc/superstring.xml b/doc/superstring.xml
new file mode 100644 (file)
index 0000000..467c767
--- /dev/null
@@ -0,0 +1,124 @@
+<?xml version="1.0"?>
+<chapter>
+<heading>class SuperString</heading>
+<para>
+A SuperString is a sequence of Strings, just like a String is a sequence of characters.
+A SuperString is in fact a string of Strings.
+Many operations that can be applied to String objects are also available for SuperSting objects,
+for example realtional operators, adding to SuperString objects, access to individual characters
+and 'substring' expressions.
+
+Split and join operations convert Strings into SuperStrings and vice versa.
+In that sense, split and join are complementary operations.
+The split() method of a string creates a SuperString.
+Conversily, the join() method of a SuperString creates a String.
+</para>
+
+<section>
+<heading>Construction and assignment.</heading>
+<para>
+The default constructor creates an empty superstring, one that does not contain any strings.
+A superstring constructed from a string creates a superstring with one element.
+Other contructors can create a SuperString from STL collectors (list and vector) of strings.
+</para>
+<description>
+<item tag="SuperString()">
+  The default constructor creates an empty string.
+</item>
+<item tag="SuperString(const String &amp;s)">
+Create a SuperSting with one element.
+</item>
+<item tag="SuperString(const int n)">
+Create a SuperSting with n empty elements.
+</item>
+</description>
+
+<para>
+Another SuperString, String or SuperString expression can be
+assigned to a SuperString:
+</para>
+<example>
+SuperString x, y;
+String z(&quot;abc&quot;);
+
+x = z;  // Create a SuperString with one element
+y = x;
+</example>
+</section>
+
+<section>
+<heading>SuperString length, testing and element access</heading>
+
+<para>
+The length of a SuperString can be determined with the <strong>~ </strong>operator.
+This is the number of Strings in the SuperString.
+Do not confuse this with the bit-wise inversion operator !
+</para>
+<example>
+
+SuperString xx(5);
+int    l = ~xx;      // l = 5
+
+</example>
+<para>
+The test for an empty string is done with the <strong>bool</strong>operator.
+This operator returns true if the SuperString object contains 1 or more Strings.
+It does not mean, however, that the String objects inside the SuperSting are not empty.
+</para>
+<example>
+if (!x)
+   cout &lt;&lt; &quot;String x is empty\n&quot;;
+</example>
+<para>
+Access to individual String elements is provided like in ordinary arrays. The 
+<strong>[] </strong>operator selects an individual String for both read and write access:
+</para>
+<example>
+SuperString xx(3);
+
+String s = "Hello";
+xx[2] = s;
+</example>
+<para>
+Access out of range will throw a std::out_of_range exception.
+</para>
+</section>
+
+<section>
+<heading>Adding to SuperStrings</heading>
+
+<para>
+SuperString objects can be added together, i.e. concatenated, with the <strong>+</strong>
+operator. Of course, the <strong>+= </strong>operator can be used as well. Example:
+</para>
+<example>
+SuperString x, y, z;
+
+SuperString x(&quot;abc&quot;);
+SuperString y(&quot;def&quot;);
+
+z = x + y;   //  z = [ &quot;abc&quot;, &quot;def&quot; ]
+y += z;      //  y = [ &quot;def&quot;, &quot;abc&quot;, &quot;def&quot; ]
+</example>
+</section>
+<para>
+ split on a regex ? how to split on an empty string ?
+
+split and join for csv formats. quoting and escape , ?
+
+
+
+the + operater can add strings and superstrings to append or prepend the one to the other. the result us always a superstring.
+
+add characters and strings ?    ->  TODO
+
+stream io is not possible. the split and join functions must be used instead
+
+the substring expression creates a selection of strings of the superstring just like the substring expression of a string creates a selection of characters.
+a substring expression with regex argument selects all strings that match the expression. implements a sort of grep function. this means the substring may not be a consequitive subset of the superstring.
+
+assigning to a substring repleces all strings in the substring
+
+convert to and from a std vector or list
+</para>
+</chapter>
index 1371d53..de2e50a 100644 (file)
@@ -1,6 +1,6 @@
 lib_LTLIBRARIES = libACL.la
 
-libACL_la_SOURCES = string.cpp regex.cpp date.cpp parsedate.c dateyacc.y datelex.c \
+libACL_la_SOURCES = string.cpp regex.cpp superstring.cpp date.cpp parsedate.c dateyacc.y datelex.c \
                     hour.cpp utc.cpp \
                     Integer.cpp \
                     xml.cpp \
index d32b276..2fb6f18 100644 (file)
@@ -45,6 +45,7 @@
 
 #include <stdlib.h>
 #include <iostream>
+#include <vector>
 #include <string.h>
 
 #include <regex.h>
@@ -52,6 +53,7 @@
 //  Forward declarations.
 class substring;
 class regex;
+class SuperString;
 
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 **  NAME           : String - Character String class.
@@ -311,6 +313,9 @@ public:
    friend bool operator == (const String &s, const regex &r);
    friend bool operator == (const regex &r, const String &s);
    // TODO: The != operator
+
+   SuperString split(const String &separator);
+
 };
    /*
     *   Other operators to think about...
@@ -404,4 +409,45 @@ public:
    }
 };
 
+class SuperString
+{
+   std::vector<String> _ss;
+
+public:
+
+   SuperString()  {};
+
+   SuperString(const String &s)
+   {
+      std::vector<String> __ss(1, s);
+      _ss = __ss;
+   }
+
+   SuperString(const int n)
+   {
+      std::vector<String> __ss(n);
+      _ss = __ss;
+   }
+
+   operator bool()   //  Test for empty SuperString
+   {
+      return _ss.size() != 0;
+   }
+
+   int operator~() const      //  Length of the SuperString
+   {
+      return _ss.size();
+   }
+
+   String& operator[](size_t i)    //  Individual String access
+   {
+      return _ss.at(i);
+   }
+
+   // Adding Strings and SuperStrings
+
+   friend SuperString operator+(const SuperString&, const String&);
+   SuperString& operator+=(const String&);
+};
+
 #endif  /* STRING_H */
index dd159d0..6ad0fd3 100644 (file)
@@ -432,7 +432,6 @@ std::istream& operator>>(std::istream& s, String& x)
  *   The subscript operator is provided for access to individual characters
  */
 
-// TODO: boundary check.
 // TODO: Assignment to an individual character does not decouple references (BUG)
 
 char& String::operator[](size_t i)
@@ -717,3 +716,36 @@ int String::in(String & x)
    else
       return -1;
 }
+
+SuperString String::split(const String &separator)
+{
+   SuperString splitted;
+   char *sep, *part;
+
+   part = p->s;
+   sep = strstr(p->s, separator.p->s);
+
+   while (sep != NULL)
+   {
+      //  Create a new string from the part until the separator
+
+      int  len  = sep - part;
+      char *str = new char[len + 1];
+
+      strncpy(str, part, len);
+      str[len] = '\0';
+      splitted += String(str);
+
+      // Look for the next separator
+
+      sep += ~separator;
+      part = sep;
+      sep = strstr(sep, separator.p->s);
+   }
+
+   // Add the leftover after the last separator.
+
+   splitted += String(part);
+
+   return splitted;
+}
diff --git a/src/superstring.cpp b/src/superstring.cpp
new file mode 100644 (file)
index 0000000..5715ac9
--- /dev/null
@@ -0,0 +1,44 @@
+/**************************************************************************
+**  (c) Copyright 1997, Andromeda Technology & Automation
+***************************************************************************
+** MODULE INFORMATION *
+***********************
+**      FILE NAME      : superstring.cpp
+**      SYSTEM NAME    : Andromeda X-Windows Encapsulation
+**      VERSION NUMBER : $Revision: 1.5 $
+**
+**  DESCRIPTION      :  SuperString class implementation.
+**
+**  EXPORTED OBJECTS : 
+**  LOCAL    OBJECTS : 
+**  MODULES  USED    :
+***************************************************************************
+**  ADMINISTRATIVE INFORMATION *
+********************************
+**      ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl
+**      CREATION DATE   : Jun 10, 2020
+**      LAST UPDATE     : Jun 10, 2020
+**      MODIFICATIONS   : 
+**************************************************************************/
+
+#include <stdio.h>
+#include <ctype.h>
+#include "String.h"
+
+// Addition operators
+
+SuperString operator+(const SuperString& ss, const String& s)
+{
+   SuperString SS(ss);
+
+   SS._ss.push_back(s);
+
+   return SS;
+}
+
+SuperString& SuperString::operator+=(const String& x)
+{
+   _ss.push_back(x);
+
+   return *this;
+}
index 70fd173..7313716 100644 (file)
@@ -4,6 +4,7 @@ AM_CPPFLAGS = -I../src
 LDADD = ../src/.libs/libACL.la
 check_PROGRAMS = string_assign string_basics string_compare string_cat string_convert string_modify \
                  string_shift string_substring string_regex \
+                 superstring_assign superstring_basics superstring_cat string_split_join \
                  date_assign date_parse date_compare date_arithmetic date_attributes date_check_today \
                  hour_assign hour_parse hour_compare hour_arithmetic hour_check_now \
                  utc_assign utc_parse utc_compare utc_arithmetic utc_convert \
@@ -21,6 +22,11 @@ string_shift_SOURCES       = string_shift.cpp
 string_substring_SOURCES   = string_substring.cpp
 string_regex_SOURCES       = string_regex.cpp
 
+superstring_assign_SOURCES  = superstring_assign.cpp
+superstring_basics_SOURCES  = superstring_basics.cpp
+superstring_cat_SOURCES     = superstring_cat.cpp
+string_split_join_SOURCES   = string_split_join.cpp
+
 date_assign_SOURCES        = date_assign.cpp
 date_parse_SOURCES         = date_parse.cpp
 date_compare_SOURCES       = date_compare.cpp
index 56c1da8..71eff4d 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************
  *  Unit test for the String class
  *
- * test relational operators
+ * test addition operators
  ******************************************************
  *
  */
diff --git a/test/string_split_join.cpp b/test/string_split_join.cpp
new file mode 100644 (file)
index 0000000..63aa7d9
--- /dev/null
@@ -0,0 +1,42 @@
+/*******************************************************
+ *  Unit test for the SuperString class
+ *
+ * test split and join of String and SuperString
+ ******************************************************
+ *
+ */
+
+#include "String.h"
+#include <assert.h>
+
+void print_ss(SuperString ss)
+{
+   std::cout << "[";
+   for (int i = 0; i < ~ss; i++)
+   {
+      if (i != 0)
+         std::cout << ",";
+      std::cout << "\"" << ss[i] << "\"";
+   }
+   std::cout << "]";
+}
+
+int main()
+{
+   String      s0("The_String_To_Split");
+   SuperString ss0;
+
+   ss0 = s0.split("_");
+
+   std::cout << "The string " << s0 << " split on \"_\":\n";
+   print_ss(ss0);
+   std::cout << "\n";
+
+   assert(ss0[0] == "The");
+   assert(ss0[1] == "String");
+   assert(ss0[2] == "To");
+   assert(ss0[3] == "Split");
+
+   return 0;
+}
+
diff --git a/test/superstring_assign.cpp b/test/superstring_assign.cpp
new file mode 100644 (file)
index 0000000..3a9fbca
--- /dev/null
@@ -0,0 +1,92 @@
+/*******************************************************
+ *  Unit test for the SuperString class
+ *
+ * test contrustor and assignment of SuperSting objects
+ ******************************************************
+ *
+ */
+
+#include "String.h"
+#include <assert.h>
+
+int main()
+{
+   // Default contructor: empty string
+   SuperString s0;
+
+   std::cout << "The default contructor makes an empty superstring.\n";
+   assert(~s0 == 0);
+
+   String s1("abc");
+   SuperString ss1(s1);
+
+   std::cout << "Contructor from a String makes a superstring with 1 element.\n";
+   assert(~ss1 == 1);
+
+   SuperString ss2(4);
+
+   std::cout << "Contructor with an integer argument makes a superstring with n elements.\n";
+   assert(~ss2 == 4);
+
+   // The copy contructor
+
+   SuperString ss3(ss2);
+
+   std::cout << "The copy contructor makes a bitwise copy.\n";
+   assert(~ss3 == 4);
+
+   //  Assignment to a SuperSting with n elements should remove the old elements.
+
+   return 0;
+
+   // A string from a literal string
+   String s2("abc");
+
+   std::cout << "A string from a literal string \"abc\": \"" << s2 << "\"\n";
+   assert(~s2 == 3);
+
+   // The copy constructor
+   String s3(s2);
+
+   std::cout << "A string copied from the previous string \"abc\": \"" << s3 << "\"\n";
+   assert(~s3 == 3);
+
+   // Assign a single character
+   String s4;
+   s4 = 'q';
+   std::cout << "A string assigned a single charater 'q': \"" << s4 << "\"\n";
+   assert(~s4 == 1);
+
+   // Initialized with a single character
+   String s5 = 'r';
+
+   std::cout << "A string initialized with a single charater 'r': \"" << s5 << "\"\n";
+   assert(~s5 == 1);
+
+   // Assign a literal string
+   String s6;
+   s6 = "ijk";
+   std::cout << "A string assigned a literal string \"ijk\": \"" << s6 << "\"\n";
+   assert(~s6 == 3);
+
+   // Initialized a literal string
+   String s7 = "lmn";
+   
+   std::cout << "A string initialized with a literal string \"lmn\": \"" << s7 << "\"\n";
+   assert(~s7 == 3);
+
+   // Assign a String object
+   String s8;
+   s8 = s6;
+   std::cout << "A string assigned a String object \"ijk\": \"" << s8 << "\"\n";
+   assert(~s8 == 3);
+
+   // Initialized a String object
+   String s9 = s7;
+   
+   std::cout << "A string initialized with a String object \"lmn\": \"" << s9 << "\"\n";
+   assert(~s9 == 3);
+
+   return 0;
+}
+
diff --git a/test/superstring_assign.exp b/test/superstring_assign.exp
new file mode 100644 (file)
index 0000000..49aff2a
--- /dev/null
@@ -0,0 +1,5 @@
+The default contructor makes an empty superstring.
+Contructor from a String makes a superstring with 1 element.
+Contructor with an integer argument makes a superstring with n elements.
+The copy contructor makes a bitwise copy.
+PASS superstring_assign (exit status: 0)
diff --git a/test/superstring_basics.cpp b/test/superstring_basics.cpp
new file mode 100644 (file)
index 0000000..72b777e
--- /dev/null
@@ -0,0 +1,98 @@
+/*******************************************************
+ *  Unit test for the SuperString class
+ *
+ * test basic SuperString operations
+ ******************************************************
+ *
+ */
+
+#include "String.h"
+#include <assert.h>
+
+int main()
+{
+   // Default contructor: empty SuperString
+   SuperString ss0;
+
+   assert(~ss0 == 0);
+
+   // The length of a string with the ~ operator
+   String s1("abcde");
+   SuperString ss1(s1);
+
+   // check boolean opareations that check for empty strings
+
+   if (ss0)
+   {
+      std::cout << " ss0 is not empty.\n";
+   }
+   else
+   {
+      std::cout << " ss0 is empty.\n";
+   }
+   if (!ss0)
+   {
+      std::cout << " ss0 is empty.\n";
+   }
+   else
+   {
+      std::cout << " ss0 is not empty.\n";
+   }
+
+   if (ss1)
+   {
+      std::cout << " ss1 is not empty.\n";
+   }
+   else
+   {
+      std::cout << " ss1 is empty.\n";
+   }
+   if (!ss1)
+   {
+      std::cout << " ss1 is empty.\n";
+   }
+   else
+   {
+      std::cout << " ss1 is not empty.\n";
+   }
+
+   int    length;
+   SuperString  ss2(5);
+   length = ~ss2;
+   std::cout << "The length of ss2 is " << length << "\n";
+   assert(length == 5);
+
+   // test String access, also outside boundaries (e.g. -1, 666)
+
+   String s2;
+   s2 = ss1[0];
+   std::cout << "First string of ss1 is \"" << s2 << "\"\n";
+   assert(s2 == "abcde");
+
+   // An out of bounds index throws an exception
+
+   try
+   {
+      s2 = ss1[3];
+      std::cout << "Fourth string of ss1 is \"" << s2 << "\"\n";
+   }
+   catch (std::out_of_range e)
+   {
+      std::cout << "SuperString exception: " << e.what() << "\n";
+   }
+
+   //  Fill up a SuperSting with some content.
+
+   SuperString ss3(4);
+   ss3[0] = "abc";
+   ss3[1] = "def";
+   ss3[3] = "xyz";
+
+   for (int i = 0; i < ~ss3; i++)
+   {
+      std::cout << "ss3[" << i << "] = " << ss3[i] << "\n";
+   }
+   return 0;
+
+}
+
diff --git a/test/superstring_basics.exp b/test/superstring_basics.exp
new file mode 100644 (file)
index 0000000..054d1e5
--- /dev/null
@@ -0,0 +1,12 @@
+ ss0 is empty.
+ ss0 is empty.
+ ss1 is not empty.
+ ss1 is not empty.
+The length of ss2 is 5
+First string of ss1 is "abcde"
+SuperString exception: vector::_M_range_check: __n (which is 3) >= this->size() (which is 1)
+ss3[0] = abc
+ss3[1] = def
+ss3[2] = 
+ss3[3] = xyz
+PASS superstring_basics (exit status: 0)
diff --git a/test/superstring_cat.cpp b/test/superstring_cat.cpp
new file mode 100644 (file)
index 0000000..ff16ae0
--- /dev/null
@@ -0,0 +1,58 @@
+/*******************************************************
+ *  Unit test for the SuperString class
+ *
+ * test addition operators
+ ******************************************************
+ *
+ */
+
+#include "String.h"
+#include <assert.h>
+
+void print_ss(SuperString ss)
+{
+   std::cout << "[";
+   for (int i = 0; i < ~ss; i++)
+   {
+      if (i != 0)
+         std::cout << ",";
+      std::cout << "\"" << ss[i] << "\"";
+   }
+   std::cout << "]";
+}
+
+int main()
+{
+   // Add a String to a SuperString, + operator
+
+   SuperString ss0;
+
+   String s1("abc");
+   String s2("def");
+   SuperString ss1(s1);
+
+   ss0 = ss1 + s2;
+
+   print_ss(ss1);
+   std::cout << " + " << s2 << " = ";
+   print_ss(ss0);
+   std::cout << "\n";
+
+   // Add a String to a SuperString, += operator
+
+   SuperString ss2;
+
+   String s3("uvw");
+   String s4("xyz");
+
+   ss2 += s3;
+   print_ss(ss2);
+   std::cout << "\n";
+
+   ss2 += s4;
+   print_ss(ss2);
+   std::cout << "\n";
+
+   return 0;
+}
+