[project @ 2005-02-28 23:43:20 by unknown_lamer]
authorunknown_lamer <unknown>
Mon, 28 Feb 2005 23:43:20 +0000 (23:43 +0000)
committerunknown_lamer <unknown>
Mon, 28 Feb 2005 23:43:20 +0000 (23:43 +0000)
This should fix a few issues with String handling

2005-02-28  Clinton Ebadi  <clinton@unknownlamer.org>

* source/Socket.C (readLine): return String (buf.c_str ()) instead
of String (buf) so that only the buffer up to the first null is returned
(readLine): Added a comment explaining the usage of buf
(readLine): Changed type of length (std::string::size_type instead
of std::size_t)

* source/String.C: Reimplemented String on top of std::string to
fix a few bugs and potential memory leaks
(toLower): use Utils::to_lower
(toUpper): Use Utils::to_upper
(trim): Use Utils::trim_str

* source/String.H: removed srep, replaced it with a std::string (my_string)

ChangeLog
TODO
source/Socket.C
source/String.C
source/String.H

index 6d45e56..18e5b53 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
 2005-02-28  Clinton Ebadi  <clinton@unknownlamer.org>
 
+       * source/Socket.C (readLine): return String (buf.c_str ()) instead
+       of String (buf) so that only the buffer up to the first null is returned
+       (readLine): Added a comment explaining the usage of buf
+       (readLine): Changed type of length (std::string::size_type instead
+       of std::size_t)
+
+       * source/String.C: Reimplemented String on top of std::string to
+       fix a few bugs and potential memory leaks
+       (toLower): use Utils::to_lower
+       (toUpper): Use Utils::to_upper
+       (trim): Use Utils::trim_str
+
+       * source/String.H: removed srep, replaced it with a std::string (my_string)
+
        * source/Utils.C (to_upper): Applied patch from Jos Hulzink
        <josh@stack.nl>
        (trim_str): Appled patch from Jos Hulzink <josh@stack.nl> (fixes
@@ -15,9 +29,6 @@
        * source/Bot.H (COPYRIGHT_STRING): Remove Michael Wilson because
        he is a lazy bum and never submitted the String replacing patch
 
-       * source/String.C: remove
-       * source/String.H: remove
-
 2005-01-23  Clinton Ebadi  <clinton@unknownlamer.org>
 
        * configure.ac: Remove CC++ test
diff --git a/TODO b/TODO
index 8b9ba05..c85c714 100644 (file)
--- a/TODO
+++ b/TODO
@@ -54,6 +54,8 @@ Networking:
    - Store authorized users and passwords in bot.telnet file
    - Bot master can add new telnet users
    - MUST HAVE PASSWORD
+* See if Socket::readLine could be sped up (profile it first to see if
+   it even matters)
 
 Definitely 3.0:
 * Remove gh_* when Guile 1.8 is released
index a2fb81d..33a42d0 100644 (file)
@@ -249,11 +249,25 @@ Socket::write(String s, bool m)
 String
 Socket::readLine()
 {
+  // fixme: this could probably be sped up (use some faster way of
+  // reading from the socket than reading a char at a time)
+
+  // We allocate the buffer statically to keep from having to overhead
+  // of reallocating a new buffer every time we call this (which is
+  // every time anything happens on IRC so the overhead of
+  // re-allocating a buffer every time is potentially too large). 
+  //
+  // Since it is static, and the length of lines will differ for each
+  // read, an embedded \0 is inserted after the last character of the
+  // line and then a copy of the the c_str is returned as a String so
+  // that only the line that was just read is returned.
   static std::string buf (512, ' ');
-  int pos = 0, nb;
-  char r;
-  std::size_t length = buf.length ();
 
+  int pos = 0; // pos in buffer
+  int nb; // number of bytes read by ::read
+  char r; // temp var for storing output of read into
+  std::string::size_type length = buf.length ();
+  
   do 
     {
       nb = ::read(fd->fd, &r, 1);
@@ -277,12 +291,15 @@ Socket::readLine()
          }
     } while (r != '\n');
   
-if (pos > 1 && buf[pos-2] == '\r')
+  if (pos > 1 && buf[pos-2] == '\r')
     buf[pos-2] = '\0';
   else
-  buf[pos-1] = '\0';
-
-  return String(buf);
+    buf[pos-1] = '\0';
+  
+  // c_str () is used because the String constructor for std::string
+  // will copy the entire std::string into it when we only want it to
+  // copy up to the first null.
+  return String (buf.c_str ());
 }
 
 String
index 060d820..30665e1 100644 (file)
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
 
 #include "String.H"
+#include "Utils.H"
 
 #include <cstring>
 #include <cctype>
 #include <sstream>
+#include <iostream>
 
 String::String()
 {
-  p = new srep;
-  len = 0;
-  p->s = 0;
 }
 
 String::String(const char *s)
 {
-  p = new srep;
-  len = strlen(s);
-  p->s = new char[len + 1];
-  std::strcpy(p->s, s);
+  my_string = s;
 }
 
 String::String(const std::string & s)
 {
-  p = new srep;
-  // We do this instead of just s.length () because there might be a
-  // \0 in the string before the end (e.g. this is a message from the
-  // Socket's buffer).
-  const char* temp_str = s.c_str ();
-  len = strlen (temp_str);
-  p->s = new char[len + 1];
-  std::strcpy (p->s, temp_str);
+  my_string = s;
 }
 
 String::String(const String & s)
 {
-  s.p->n++;
-  p = s.p;
-  len = s.len;
+  my_string = s.my_string;
 }
 
 String::String(long i)
 {
   std::ostringstream temp;
   temp << i;
-
-  p = new srep;
-  len = strlen(temp.str().c_str ());
-  p->s = new char[len + 1];
-  strcpy(p->s, temp.str().c_str ());
+  my_string = temp.str ();
 }
 
 String::String(char c)
 {
-  p = new srep;
-  p->s = new char[2];
-  p->s[0] = c;
-  p->s[1] = '\0';
-  len = 1;
+  my_string = std::string (1, c);
 }
 
 String::~String()
 {
-  if (--p->n == 0) {
-    delete[] p->s;
-    delete p;
-  }
+  
 }
 
 String &
 String::operator=(const char *s)
 {
-  if (p->n > 1) {
-    p->n--;
-    p = new srep;
-  }
-  else
-    delete[] p->s;
-  
-  len = strlen(s);
-  p->s = new char[len + 1];
-  strcpy(p->s, s);
-  
+  my_string = s;
+
   return *this;
 }
 
 String &
 String::operator=(const String & s)
 {
-  s.p->n++; // protection contre st = st
-  if (--p->n == 0) {
-    delete[] p->s;
-    delete p;
-  }
-  p = s.p;
-  len = s.len;
+  my_string = s.my_string;
+
   return *this;
 }
 
 String &
 String::operator=(const std::string & s)
 {
-  if (p->n > 1) {
-    p->n--;
-    p = new srep;
-  }
-  else
-    delete[] p->s;
-  
-  len = s.length ();
-  p->s = new char[len + 1];
-  strcpy(p->s, s.c_str ());
+  my_string = s;
   
   return *this;
 }
@@ -134,57 +87,40 @@ String::operator=(const std::string & s)
 int
 String::length() const
 {
-  return len;
+  return my_string.length ();
 }
 
 int
 String::find(char c)
 {
-  if (!strchr(p->s, c))
-    return -1;
-  
-  return (int)(strchr(p->s, c) - p->s);
+  return my_string.find (c);
 }
 
 void
-String::fill(char c)
+String::fill (char c)
 {
-  for (char * s = p->s; *s; s++)
-    *s = c;
+  my_string.replace (0, 
+                    my_string.length () - 1, 
+                    my_string.length (),
+                    c);
 }
 
 String
-String::pad(int n)
+String::pad (int n)
 {
-  int l = len;
-
-  if (n <= l)
-    return subString(0, n-1);
-
-  char *temp = new char[n+1];
-  strcpy(temp, p->s);
+  std::string temp = my_string;
 
-  for (int i = l; i < n; i++)
-    temp[i] = ' ';
-  temp[n] = '\0';
+  temp.resize (n, ' ');
 
-  String res(temp);
-  delete temp;
-
-  return res;
+  return temp;
 }
 
 String
-String::subString(int debut, int fin)
+String::subString (int start, int end)
 {
-  if (fin < debut) return "";
+  if (end < start) return "";
 
-  char * temp = new char[fin-debut+2];
-  strncpy(temp, p->s + debut, fin - debut + 1);
-  temp[fin - debut + 1] = '\0';
-  String res(temp);
-  delete temp;
-  return res;
+  return my_string.substr (start, (end - start) + 1);
 }
 
 String
@@ -194,9 +130,9 @@ String::substr (int s, int e)
 }
 
 String
-String::subString(int debut)
+String::subString (int start)
 {
-  return subString(debut, len - 1);
+  return subString (start, my_string.length () - 1);
 }
 
 String
@@ -208,241 +144,183 @@ String::substr (int s)
 String
 String::toLower()
 {
-  char *temp = new char[len + 1];
-
-  for (int i = 0; i < len + 1; i++)
-    if (isupper(p->s[i]))
-      temp[i] = tolower(p->s[i]);
-    else
-      temp[i] = p->s[i];
-
-  String res(temp);
-  delete temp;
-  return res;
+  return Utils::to_lower (my_string);
 }
 
 String
 String::toUpper()
 {
-  char *temp = new char[len + 1];
-
-  for (int i = 0; i < len + 1; i++)
-    if (islower(p->s[i]))
-      temp[i] = toupper(p->s[i]);
-    else
-      temp[i] = p->s[i];
-
-  String res(temp);
-  delete temp;
-  return res;
+  return Utils::to_upper (my_string);
 }
 
 String
 String::trim()
 {
-  int i = 0, j = len - 1;
-
-  while (i < j && (p->s[i] == ' ' || p->s[i] == '\t' || p->s[i] == '\r'))
-    i++;
-  
-  while (j > 0 && (p->s[j] == ' ' || p->s[j] == '\t' || p->s[j] == '\r'))
-    j--;
-  
-  return subString(i, j);
+  return Utils::trim_str (my_string);
 }
 
 int
-String::indexOf(char c)
+String::indexOf (char c)
 {
-  char *s = std::strchr(p->s, c);
-  if (s)
-    return p->s - s;
-  
-  return -1;
+  std::string::size_type pos = my_string.find (c);
+
+  if (pos == std::string::npos)
+    return -1;
+  else
+    return pos;
 }
 
 char &
-String::operator[](int i)
+String::operator[] (int i)
 {
-  if (i < 0 || len < i) {
+  if (i < 0 || my_string.length () < i) {
     std::cerr << "String index out of range\n";
     std::exit(1);
   }
-  return p->s[i];
+  return my_string[i];
 }
 
 const char &
 String::operator[](int i) const
 {
-  if (i < 0 || len < i) {
+  if (i < 0 || my_string.length () < i) {
     std::cerr << "String index out of range\n";
     exit(1);
   }
-  return p->s[i];
+  return my_string[i];
 }
 
 bool
 String::operator==(const char *s) const
 {
-  return std::strcmp(p->s, s) == 0;
+  return my_string == s;
 }
 
 bool
 String::operator==(const String & s) const
 {
-  return (p == s.p) || (std::strcmp(p->s, s.p->s) == 0);
+  return my_string == s.my_string;
 }
 
 bool
 String::operator==(const std::string & s) const
 {
-  return (p->s == s.c_str ()) || (std::strcmp (p->s, s.c_str()) == 0);
+  return my_string == s;
 }
 
 bool
 String::operator!=(const char *s) const
 {
-  return std::strcmp(p->s, s) != 0;
+  return my_string != s;
 }
 
 bool
 String::operator!=(const String & s) const
 {
-  return std::strcmp(p->s, s.p->s) != 0;
+  return my_string != s.my_string;
 }
 
 bool
 String::operator!=(const std::string & s) const
 {
-  return ! (*this == s);
+  return my_string != s;
 }
 
 bool
 String::operator<(const String & s) const
 {
-  return std::strcmp(p->s, s.p->s) < 0;
+  return my_string < s.my_string;
 }
 
 bool
 String::operator<(const std::string & s) const
 {
-  return std::strcmp(p->s, s.c_str ()) < 0;
+  return my_string < s;
 }
 
 bool
 String::operator>(const String & s) const
 {
-  return std::strcmp(p->s, s.p->s) > 0;
+  return my_string > s.my_string;
 }
 
 bool
 String::operator<=(const String & s) const
 {
-  return std::strcmp(p->s, s.p->s) <= 0;
+  return my_string <= s.my_string;
 }
 
 bool
 String::operator<=(const std::string & s) const
 {
-  return (*this < s) || (*this == s);
+  return my_string <= s;
 }
 
 bool
 String::operator>=(const String & s) const
 {
-  return std::strcmp(p->s, s.p->s) >= 0;
+  return my_string >= s.my_string;
 }
 
 bool String::operator>=(const std::string & s) const
 {
-  return ! (*this < s);
+  return my_string >= s;
 }
 
 String
 String::operator+(const char *s)
 {
-  char *temp = new char[len + std::strlen(s) + 1];
-
-  std::strcpy(temp, p->s);
-  std::strcat(temp, s);
-
-  String res(temp);
-  delete temp;
-
-  return res;
+  return my_string + s;
 }
 
 String
 String::operator+(const String & s)
 {
-  char * temp = new char[len + s.len + 1];
-
-  std::strcpy(temp, p->s);
-  std::strcat(temp, s.p->s);
-
-  String res(temp);
-  delete temp;
-
-  return res;
+  return my_string + s.my_string;
 }
 
 String
 String::operator+(const std::string & s)
 {
-  char * temp = new char[len + s.length () + 1];
-  std::strcpy (temp, p->s);
-  std::strcat (temp, s.c_str ());
-
-  String res (temp);
-  delete temp;
-
-  return res;
+  return my_string + s;
 }
 
 String::operator const char *() const
 {
-  return p->s;
+  return my_string.c_str ();
 }
 
 String::operator std::string () const
 {
-  return std::string (p->s);
+  return my_string;
 }
 
 std::ostream &
 operator<<(std::ostream & s, const String & st)
 {
-  return s << st.p->s;
+  return s << st.my_string;
 }
 
 std::istream &
 operator>>(std::istream & s, String & st)
 {
-  if (st.p->n > 1) {
-    st.p->n--;
-    st.p = new String::srep;
-  }
-  else
-    delete[] st.p->s;
-  
-  char buf[2048];
-  char c;
+  // The original version of string grabbed an entire line with
+  // operator>> so this version has to too (otherwise I'd just replace
+  // String with std::string everywhere because it would be just as
+  // painful)
 
-  s.getline (buf, 2048, '\n');
-  //s.get(c);
+  std::string temp;
 
-  st.len = strlen(buf);
-  st.p->s = new char[st.len + 1];
-  strcpy(st.p->s, buf);
+  std::getline (s, temp);
+
+  st.my_string = temp;
 
   return s;
 }
 
 std::string operator+(const std::string & s, const String & p)
 {
-  std::string temp = s;
-  temp += p.p->s;
-  return temp;
+  return s + p.my_string;
 }
 
 bool operator==(const std::string & s, const String & p)
index 70f6a55..de6cbed 100644 (file)
 
 class String {
 
-  struct srep {
-    char *s;  // pointer on the data
-    int n;    // reference counter
-    srep() 
-      { n = 1; }
-  };
-  srep *p;
-  int len;
-  
+  std::string my_string;
+
 public:
   String();
   String(const char *);