-/****************************************************************************
- PROJECT: FlowerSoft C++ library
- FILE : string.cc
+/*
- Rehacked by HWN 3/nov/95
- removed String &
- introduced Class String_handle
---*/
+ string.cc - implement String
+
+ (c) 1997 Han-Wen Nienhuys & Jan Nieuwenhuizen
+
+ */
-#include <string.h>
#include <stdlib.h>
#include <stdio.h>
-#include <ctype.h>
+
#include <assert.h>
+#include <string.h>
#include "string.hh"
+#include "libc-extension.hh"
+#include "string-convert.hh"
+#ifdef STRING_DEBUG
+void* mymemmove (void* dest, void const* src, size_t n);
+#define memmove mymemmove
+#endif
-static char* strlwr( char* s )
+// return array, alloced with new.
+Byte*
+String::copy_byte_p() const
{
- char* p = s;
-
- while( *p )
- {
- *p = tolower( *p ); /* a macro on some compilers */
- p++;
- }
- return s;
+ Byte const* src = strh_.byte_C();
+ Byte* dest = new Byte[strh_.length_i() + 1];
+ memcpy (dest, src, strh_.length_i() + 1);
+ return dest;
+}
+void
+String::print_on (ostream& os) const
+{
+ if (!strh_.is_binary_bo())
+ os << ch_C();
+ else
+ for (int i = 0; i < length_i(); i++)
+ os << (Byte)(*this)[ i ];
}
+\f
+/*
+ copying, constructing.
+ */
+String&
+String::operator = (String const&source)
+{
+ strh_ = source.strh_;
+ return *this;
+}
+
-static char* strupr( char* s )
+String::String (Rational r)
{
- char* p = s;
+ *this = String_convert::rational_str (r);
+}
- while( *p )
- {
- *p = toupper( *p ); /* a macro on some compilers */
- p++;
- }
- return s;
+String::String (double f, char const* fmt)
+{
+ *this= String_convert::double_str (f,fmt);
}
-// return array, alloced with new.
-char *
-String::copy_array() const
+String::String (char c, int n)
{
- const char *src = data;
- char *dest = new char[data.len() + 1];
- strcpy(dest, src);
- return dest;
+ *this = String_convert::char_str (c,n);
}
-void
-String::printOn(ostream& os) const
+/**
+ @see
+ String_convert::int_str
+ */
+String::String (int i, char const * format)
{
- os << (const char*) data;
+ *this = String_convert::int_str (i,format);
}
String::String (bool b)
{
- *this = (const char *) (b ? "true" : "false");
+ *this = (char const*) (b ? "true" : "false");
}
-String::String( const char* source )
+
+String::String (char const* source)
{
- assert(source);
- data = source;
+ assert (source);
+ strh_ = source;
}
+String::String (Byte const* byte_l, int length_i)
+{
+ strh_.set (byte_l, length_i);
+}
+\f
+void
+String::append (String s)
+{
+ strh_.append (s.byte_C(), s.length_i());
+}
void
String::operator +=(String s)
{
- *this += (const char *) s;
+ append (s);
}
-int
-String::len() const
+void
+String::prepend (String s)
{
- return data.len();
+ s += *this;
+ *this = s;
}
-String::String(char c, int n)
+int
+String::length_i() const
{
- int l = n;
- assert(n >= 0 && n <= 80); // what the fuck is 80?
-//min(max( n, 0 ), 80);
- char s[81];
- memset(s, c, l);
- s[l] = 0;
- data = s;
+ return strh_.length_i();
}
-String::String(int i)
+Byte const*
+String::byte_C() const
{
- char digits[ 81 ]; // who the FUCK is 80???
- digits[ 0 ] = '\0';
- sprintf(digits, "%d", i ); // assume radix 10
- data = digits;
+ return strh_.byte_C();
}
-String::String( const int i, const int n, const char c )
+char const*
+String::ch_C() const
{
- char fillChar = c;
- if ( fillChar)
- fillChar = '0';
-
- String v( i );
-
- data = String( fillChar, n - v.len() ) + String( v );
- // String convd to const char *
+ return strh_.ch_C();
}
-const char*
-String::cptr() const
+Byte*
+String::byte_l()
{
- return data;
+ return strh_.byte_l();
}
+char*
+String::ch_l()
+{
+ return strh_.ch_l();
+}
-
-// signed comparison, analogous to strcmp;
+bool
+String::empty_b () const
+{
+ return !length_i ();
+}
+/**
+ Do a signed comparison, analogous to memcmp;
+ */
int
-String::compare( const char* test ) const
+String::compare_i (String const& s1, String const& s2)
{
- if (test == (const char *) data)
+ Byte const* p1 = s1.byte_C();
+ Byte const* p2 = s2.byte_C();
+ if (p1 == p2)
return 0;
- return strcmp(data, test);
-}
+ int i1 = s1.length_i();
+ int i2 = s2.length_i();
+ int result= memcmp (p1, p2, i1 <? i2);
+ return result ? result : i1-i2;
+}
+\f
int
-String::lastPos( const char c ) const
+String::index_last_i (char const c) const
{
- const char *me = data;
- int pos = 0;
- if ( len() )
- {
- const char* p = strrchr(me, c );
- if ( p )
- pos = p - me + 1;
- }
- return pos;
+ if (!length_i())
+ return -1;
+
+ char const* me = strh_.ch_C();
+ char const* p = memrchr (me, length_i(), c);
+ if (p)
+ return p - me;
+ return -1;
}
int
-String::lastPos( const char* string ) const
-{
- int pos = 0;
- int length = strlen( string );
- if ( len() && length )
- {
- int nextpos = this->pos( string );
- while( nextpos )
- {
- pos += nextpos;
- nextpos = right( len() - pos - length + 1 ).pos( string );
- }
- }
- return pos;
-}
-
-// find c
-// return 0 if not found.
-
-// ? should return len()?, as in string.left(pos(delimiter))
-int
-String::pos(char c ) const
+String::index_last_i (char const* string) const // UGK!
{
- const char *me = data;
- int pos = 0;
- if ( len() )
- {
- const char* p = strchr( me, c );
- if ( p )
- pos = p - me + 1;
- }
- return pos;
+ assert (false); // broken
+ int length = strlen (string); // ugrh
+ if (!length_i() || !length)
+ return -1;
+
+ int next_i = index_i (string);
+ if (next_i == -1)
+ return -1;
+
+ int index_i = 0;
+ while (next_i >= 0)
+ {
+ index_i += next_i;
+ next_i = right_str (length_i() - index_i - length).index_i (string );
+ }
+ return index_i;
}
-// find searchfor. (what if this == "" && searchfor == "") ???
+/** find a character.
+
+ @return
+ the index of the leftmost character #c# (0 <= return < length_i()),
+ or -1 if not found.
+
+ ? should return length_i()?, as in string.left_str (index_i (delimiter))
+*/
int
-String::pos( const char* searchfor ) const
+String::index_i (char c) const
{
- const char *me = data;
- int pos = 0;
- if ( len() && searchfor)
- {
- const char* p = strstr(me, searchfor);
- if ( p )
- pos = p - me + 1;
- }
- return pos;
+ char const* me = strh_.ch_C();
+ char const* p = (char const *) memchr (me,c, length_i());
+ if (p)
+ return p - me;
+ return -1;
}
-// find chars of a set.
+/**
+ find the substring.
+
+ @return
+1 index of leftmost occurrence of #searchfor#
+ */
int
-String::posAny( const char* string ) const
+String::index_i (String searchfor) const
{
- int pos = 0;
- const char *s = (const char *)data;
- if ( len() && string )
- {
- const char* p = strpbrk( s, string );
- if ( p )
- pos = p - s + 1;
- }
- return pos;
+ char const* me = strh_.ch_C();
+ char const* p = (char const *) memmem (
+ me, length_i(), searchfor.ch_C(), searchfor.length_i ());
+
+ if (p)
+ return p - me;
+ else
+ return -1;
}
+/** find chars of a set.
+
+ @return
+ the index of the leftmost occurance of an element of #set#
+ */
+int
+String::index_any_i (String set) const
+{
+ int n = length_i();
+ if (!n)
+ return -1;
+
+ void const * me_l = (void const *) strh_.ch_C();
+ for (int i=0; i < set.length_i(); i++)
+ {
+ char * found=(char*) memchr (me_l, set[i], n );
+ if (found)
+ {
+ return found - me_l;
+ }
+ }
+ return -1;
+}
+\f
String
-String::left( int n ) const
+String::left_str (int n) const
{
- if (n >= len())
+ if (n >= length_i())
return *this;
- String retval;
- if (n < 1)
- return retval;
-
- retval = *this;
- retval.data.trunc(n);
- return retval;
+ String retval;
+ if (n < 1)
+ return retval;
+
+ retval = *this;
+ retval.strh_.trunc (n);
+ return retval;
}
-
-// n rightmst chars
String
-String::right( int n ) const
+String::right_str (int n) const
{
- if (n > len())
+ if (n > length_i())
return *this;
-
- String retval;
- if ( n < 1)
- return retval;
-
- const char *src = (const char *)data + len() - n;
- retval += src;
-
- return retval;
+
+ if (n < 1)
+ return "";
+
+ return String (strh_.byte_C() + length_i() - n, n);
}
String
-String::nomid( const int pos, const int n ) const
+String::nomid_str (int index_i, int n) const
{
- String retval;
-
- if ( pos < 1 )
- return String("");
- if ( pos > len())
+ if (index_i < 0)
+ {
+ n += index_i;
+ index_i = 0;
+ }
+ if (n <= 0)
return *this;
-
- return String( String( left( pos - 1 ) ) + right( len() - pos - n + 1 ));
+
+ return
+ left_str (index_i) +
+ right_str (length_i() - index_i - n) ;
}
-
+/*
+ proposal: change to "cut()"
+ */
String
-String::mid( int pos, int n ) const
+String::mid_str (int index_i, int n) const
{
- String retval;
+ if (index_i <0)
+ {
+ n += index_i;
+ index_i=0;
+ }
+
+ if (!length_i() || (index_i < 0) || (index_i >= length_i () ) || (n < 1 ) )
+ return String();
- // HWN. This SUX:
- // pos 1 == data->string[ 0 ];
- // pos 0 allowed for convenience
- if ( !len() || ( pos < 0 ) || ( pos > len() ) && ( n < 1 ) )
- return retval;
+ if ((n > length_i()) || (index_i + n > length_i () ) )
+ n = length_i() - index_i;
- retval = ((const char *) data) + pos -1;
- if (n > retval.len())
- n =retval.len();
- retval.data.trunc(n);
- return retval;
+ return String (byte_C() + index_i, n);
}
-
-
-// to uppercase
+\f
String
-String::upper()
+String::upper_str() const
{
- char *s = data.array_for_modify();
- strupr(s );
- return *this;
+ String str = *this;
+ str.to_upper();
+ return str;
}
-
-
-// to lowercase
-String String::lower()
+void
+String::to_upper()
{
- char *s = data.array_for_modify();
- strlwr(s);
- return *this;
+ char *s = (char*)strh_.byte_l();
+ strnupr (s ,length_i());
}
-String::String (double f, const char *fmt)
+void
+String::to_lower()
{
- /* worst case would be printing HUGE (or 1/HUGE), which is approx
- 2e318, this number would have approx 318 zero's in its string.
-
- 1024 is a safe length for the buffer
- */
-
- char buf[1024];
- if (!fmt)
- sprintf(buf, "%f", f);
- else
- sprintf(buf, fmt,f);
- *this = buf;
+ char* s = strh_.ch_l();
+ strnlwr (s,length_i());
}
-long
-String::value() const
+
+String
+String::lower_str() const
{
- long l =0;
- if (len()) {
- int conv = sscanf(data, "%ld", &l);
- assert(conv);
- }
- return l;
+ String str = *this;
+ str.to_lower();
+ return str;
}
-
-double
-String::fvalue() const
+String
+String::reversed_str() const
{
- double d =0;
- if (len()) {
- int conv = sscanf(data, "%lf", &d);
- assert(conv);
- }
- return d;
+ String str = *this;
+ strrev (str.byte_l(), str.length_i ());
+ return str;
}
-
-String quoteString( String msg, String quote)
+int
+String::value_i() const
{
- return msg + " `" + quote + "' ";
+ return String_convert::dec2_i (*this);
}
-
-char *strrev(char *s)
+double
+String::value_f() const
{
- char c;
- char *p = s;
- char *q = s + strlen(s) - 1;
-
- while (q > p) {
- c = *p;
- *p++ = *q;
- *q-- = c;
- }
- return s;
+ return String_convert::dec2_f (*this);
}
-String
-String::reversed() const
-{
- String retval=*this;
- char *s = retval.data.array_for_modify();
- strrev(s);
- return retval;
-}