From 005c31fbe32fda69c46d79187f5d76d7ba944d08 Mon Sep 17 00:00:00 2001 From: unknown_lamer Date: Mon, 28 Feb 2005 23:43:20 +0000 Subject: [PATCH] [project @ 2005-02-28 23:43:20 by unknown_lamer] This should fix a few issues with String handling 2005-02-28 Clinton Ebadi * 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 | 17 +++- TODO | 2 + source/Socket.C | 31 ++++-- source/String.C | 266 +++++++++++++----------------------------------- source/String.H | 11 +- 5 files changed, 114 insertions(+), 213 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6d45e56..18e5b53 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,19 @@ 2005-02-28 Clinton Ebadi + * 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 (trim_str): Appled patch from Jos Hulzink (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 * configure.ac: Remove CC++ test diff --git a/TODO b/TODO index 8b9ba05..c85c714 100644 --- 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 diff --git a/source/Socket.C b/source/Socket.C index a2fb81d..33a42d0 100644 --- a/source/Socket.C +++ b/source/Socket.C @@ -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 diff --git a/source/String.C b/source/String.C index 060d820..30665e1 100644 --- a/source/String.C +++ b/source/String.C @@ -17,116 +17,69 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. #include "String.H" +#include "Utils.H" #include #include #include +#include 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) diff --git a/source/String.H b/source/String.H index 70f6a55..de6cbed 100644 --- a/source/String.H +++ b/source/String.H @@ -24,15 +24,8 @@ 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 *); -- 2.20.1