--- /dev/null
+/****************************************************************************
+ PROJECT: FlowerSoft C++ library
+ FILE : string.cc
+
+ Rehacked by HWN 3/nov/95
+ removed String &
+ introduced Class String_handle
+--*/
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <assert.h>
+//#include "globals.hh"
+#include "string.hh"
+
+char* strlwr( char* s )
+{
+ char* p = s;
+
+ while( *p )
+ {
+ *p = tolower( *p ); /* a macro on some compilers */
+ p++;
+ }
+ return s;
+}
+
+char* strupr( char* s )
+{
+ char* p = s;
+
+ while( *p )
+ {
+ *p = toupper( *p ); /* a macro on some compilers */
+ p++;
+ }
+ return s;
+}
+
+// return array, alloced with new.
+char *
+String::copy_array() const
+{
+ const char *src = data;
+ char *dest = new char[data.len() + 1];
+ strcpy(dest, src);
+ return dest;
+}
+
+void
+String::printOn(ostream& os) const
+{
+ os << (const char*) data;
+}
+
+String::String (bool b)
+{
+ *this = (const char *) (b ? "true" : "false");
+}
+String::String( const char* source )
+{
+ assert(source);
+ data = source;
+}
+
+void
+String::operator +=(String s)
+{
+ *this += (const char *) s;
+}
+
+int
+String::len() const
+{
+ return data.len();
+}
+
+String::String(char c, int n)
+{
+ 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;
+}
+
+String::String(int i)
+{
+ char digits[ 81 ]; // who the FUCK is 80???
+ digits[ 0 ] = '\0';
+ sprintf(digits, "%d", i ); // assume radix 10
+ data = digits;
+}
+
+String::String( const int i, const int n, const char c )
+{
+ char fillChar = c;
+ if ( fillChar)
+ fillChar = '0';
+
+ String v( i );
+
+ data = String( fillChar, n - v.len() ) + String( v );
+ // String convd to const char *
+}
+
+String::operator const char *() const
+{
+ return data;
+}
+
+
+
+#ifdef CENTRAL_OBJECT // everything derived from Sortable object
+// comparisons.
+int
+String::operator ==( const Sortable& test ) const
+{
+ const String *s = (const String *) &test;
+ return *this == *s;
+}
+
+int
+String::operator &&(const Object& test) const
+{
+ const String *s = (const String *) &test;
+
+ int i = min( len(), s->len() );
+ return ( i > 0 ) ?
+ ( !strncmp( data, s->data, i ) ) : 0;
+}
+
+int
+String::operator >( const Sortable& test ) const
+{
+ const String *s = (const String *) &test;
+ return strcmp( data, s->data ) > 0;
+}
+#endif
+// signed comparison, analogous to strcmp;
+int
+String::compare( const char* test ) const
+{
+ if (test == (const char *) data)
+ return 0;
+
+ return strcmp(data, test);
+}
+
+
+int
+String::lastPos( const char 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;
+}
+
+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
+{
+ const char *me = data;
+ int pos = 0;
+ if ( len() )
+ {
+ const char* p = strchr( me, c );
+ if ( p )
+ pos = p - me + 1;
+ }
+ return pos;
+}
+
+// find searchfor. (what if this == "" && searchfor == "") ???
+int
+String::pos( const char* searchfor ) 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;
+}
+
+// find chars of a set.
+int
+String::posAny( const char* string ) 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;
+}
+
+String
+String::left( int n ) const
+{
+ if (n >= len())
+ return *this;
+
+ String retval;
+ if (n < 1)
+ return retval;
+
+ retval = *this;
+ retval.data.trunc(n);
+ return retval;
+}
+
+
+// n rightmst chars
+String
+String::right( int n ) const
+{
+ if (n > len())
+ return *this;
+
+ String retval;
+ if ( n < 1)
+ return retval;
+
+ const char *src = (const char *)data + len() - n;
+ retval += src;
+
+ return retval;
+}
+
+
+String
+String::nomid( const int pos, const int n ) const
+{
+ String retval;
+
+ if ( pos < 1 )
+ return String("");
+ if ( pos > len())
+ return *this;
+
+ return String( String( left( pos - 1 ) ) + right( len() - pos - n + 1 ));
+}
+
+
+String
+String::mid( int pos, int n ) const
+{
+ String retval;
+
+ // HWN. This SUX:
+ // pos 1 == data->string[ 0 ];
+ // pos 0 allowed for convenience
+ if ( !len() || ( pos < 0 ) || ( pos > len() ) && ( n < 1 ) )
+ return retval;
+
+ retval = ((const char *) data) + pos -1;
+ if (n > retval.len())
+ n =retval.len();
+ retval.data.trunc(n);
+ return retval;
+}
+
+
+// to uppercase
+String
+String::upper()
+{
+ char *s = data.array_for_modify();
+ strupr(s );
+ return *this;
+}
+
+
+// to lowercase
+String String::lower()
+{
+ char *s = data.array_for_modify();
+ strlwr(s);
+ return *this;
+}
+
+String::String (double f, const char *fmt)
+{
+ char buf[100]; // ugly
+ if (!fmt)
+ sprintf(buf, "%f", f);
+ else
+ sprintf(buf, fmt,f);
+ *this = buf;
+}
+
+long
+String::value() const
+{
+ long l =0;
+ if (len()) {
+ int conv = sscanf(data, "%ld", &l);
+ assert(conv);
+ }
+ return l;
+}
+
+double
+String::fvalue() const
+{
+ double d =0;
+ if (len()) {
+ int conv = sscanf(data, "%lf", &d);
+ assert(conv);
+ }
+ return d;
+}
+
+
+String quoteString( String msg, String quote)
+{
+ return msg + " `" + quote + "' ";
+}
+
+
+char *strrev(char *s)
+{
+ char c;
+ char *p = s;
+ char *q = s + strlen(s) - 1;
+
+ while (q > p) {
+ c = *p;
+ *p++ = *q;
+ *q-- = c;
+ }
+ return s;
+}
+
+
+String
+String::reversed() const
+{
+ String retval=*this;
+ char *s = retval.data.array_for_modify();
+ strrev(s);
+ return retval;
+}
--- /dev/null
+/*
+
+ FILE : string.hh -- implement String inline helpclasses,
+ and declare stringclass.
+
+
+ Rehacked by HWN 3/nov/95
+ removed String & 's
+ introduced Class String_handle
+ */
+
+#ifndef STRING_HH
+#define STRING_HH
+
+
+#include <string.h>
+#include <iostream.h>
+
+//#include "globals.hh"
+#include "stringutil.hh"
+
+// whugh
+#ifdef CENTRAL_OBJECT
+#include "sortable.hh"
+#define String__mpp String : public Sortable
+#else
+#define String__mpp String
+#endif
+
+/// the smart string class.
+class String__mpp
+{
+protected:
+ String_handle data; // should derive String from String_handle?
+
+public:
+
+#ifdef CENTRAL_OBJECT // everything derived from Sortable object
+ virtual int operator ==( const Sortable& test ) const;
+ virtual int operator &&( const Object& test ) const;
+ virtual int operator >( const Sortable& test ) const;
+#endif
+
+ /// init to ""
+ String() { }
+ /** needed because other constructors are provided.*/
+
+ /// String s = "abc";
+ String( const char* source );
+
+ /// "ccccc"
+ String( char c, int n = 1 );
+
+ /// String s( 10 );
+ String( int i );
+
+ /// 'true' or 'false'
+ String(bool );
+
+ /// String s( 3.14, 6, '#' );
+ String ( double f , const char *fmt =0);
+ String( int i, int n, char c = ' ' );
+
+ /// return a "new"-ed copy of contents
+ char *copy_array() const; // return a "new"-ed copy of contents
+
+ /// return the data. Don't use for writing the data.
+ virtual operator const char *() const; // virtual???
+
+ String operator =( const String & source ) { data = source.data; return *this; }
+
+ /// concatenate s
+ void operator += (const char *s) { data += s; }
+ void operator += (String s);
+
+ char operator []( int n ) const { return data[n]; }
+
+ /// return n leftmost chars
+ String left( int n ) const;
+
+ /// return n rightmost chars
+ String right( int n ) const;
+
+ /// convert this to upcase
+ String upper();
+
+ /// convert this to downcase
+ String lower(); // & ??
+
+ /// return the "esrever" of *this
+ String reversed() const;
+
+
+ /// return a piece starting at pos (first char = pos 1), length n
+ String mid(int pos, int n ) const;
+
+ /// cut out a middle piece, return remainder
+ String nomid(int pos, int n ) const;
+
+ /// signed comparison, analogous to strcmp;
+ int compare( const char* s ) const;
+
+ /// index of rightmost c
+ int lastPos( char c) const;
+ /// index of rightmost element of string
+ int lastPos( const char* string ) const;
+
+ /// index of leftmost c
+ int pos(char c ) const;
+ /**
+ RETURN:
+ 0 if not found, else index + 1
+ */
+ int pos(const char* string ) const;
+ int posAny(const char* string ) const;
+
+
+ /// provide Stream output
+ void printOn(ostream& os) const;
+
+ /// convert to an integer
+ long value() const;
+
+ /// convert to a double
+ double fvalue() const;
+
+ /// the length of the string
+ int len() const;
+};
+/**
+
+ Intuitive string class. provides
+
+ ref counting thru #String_handle#
+
+ conversion from bool, int, double, char *, char.
+
+ conversion to int, upcase, downcase
+
+
+ printable.
+
+ indexing (pos, posAny, lastPos)
+
+ cutting (left, right, mid)
+
+ concat (+=, +)
+
+ signed comparison (<, >, ==, etc)
+
+ No operator[] is provided, since this would be enormously slow. If needed,
+ convert to const char *.
+*/
+
+
+// because const char* also has an operator ==, this is for safety:
+inline bool operator==(String s1, String s2){ return !(s1.compare(s2));}
+inline bool operator==(String s1, const char *s2){ return !(s1.compare(s2));}
+inline bool operator==(const char *s1, String s2){ return !(s2.compare(s1));}
+inline bool operator!=(String s1, const char *s2 ) { return s1.compare(s2);}
+inline bool operator!=(const char *s1,String s2) { return s2.compare(s1);}
+inline bool operator!=(String s1, String s2 ) { return s1.compare(s2);}
+
+inline String
+operator + (String s1, String s2)
+{
+ s1 += s2;
+ return s1;
+}
+
+inline ostream &
+operator << ( ostream& os, String d )
+{
+ d.printOn(os);
+ return os;
+}
+
+
+String quoteString(String message, String quote);
+
+#endif
--- /dev/null
+/*
+ (c) Han-Wen Nienhuys 1995,96
+
+ Distributed under GNU GPL
+*/
+
+#ifndef SVEC_H
+#define SVEC_H
+#include <assert.h>
+
+/// copy a bare (C-)array from #src# to #dest# sized #count#
+template<class T>
+inline void arrcpy(T*dest, T*src, int count) {
+ for (int i=0; i < count ; i++)
+ *dest++ = *src++;
+}
+
+///scaleable array template, for T with def ctor.
+template<class T>
+class svec {
+protected:
+
+ int max;
+
+ /// the data itself
+ T *thearray;
+
+ /// stretch or shrink array.
+ void remax(int newmax) {
+ T* newarr = new T[newmax];
+ size = (newmax < size) ? newmax : size;
+ arrcpy(newarr, thearray, size);
+
+ delete[] thearray;
+ thearray = newarr;
+ max = newmax;
+ }
+ int size;
+
+public:
+ /// check invariants
+ void OK() const {
+ assert(max >= size && size >=0);
+ if (max) assert(thearray);
+ }
+ /// report the size. See {setsize}
+ int sz() const { return size; }
+
+ /// POST: sz() == 0
+ void clear() { size = 0; }
+
+ svec() { thearray = 0; max =0; size =0; }
+ /// set the size to #s#
+ void set_size(int s) {
+ if (s >= max) remax(s);
+ size = s;
+ }
+ /** POST: sz() == s.
+ Warning: contents are unspecified */
+
+ ~svec() { delete[] thearray; }
+
+ /// return a "new"ed copy of array
+ T* copy_array() const {
+ T* Tarray = new T[size];
+ arrcpy(Tarray, thearray, size);
+ return Tarray;
+ }
+ // depracated
+ operator T* () const {
+ return copy_array();
+ }
+ void operator=(svec const & src) {
+ set_size (src.size);
+ arrcpy(thearray,src.thearray, size);
+ }
+ svec(const svec & src) {
+ thearray = src.copy_array();
+ max = size = src.size;
+ }
+
+ /// tighten array size.
+ void precompute () { remax(size); }
+
+ /// this makes svec behave like an array
+ T &operator[] (const int i) const {
+ assert(i >=0&&i<size);
+ return ((T*)thearray)[i];
+ }
+
+ /// add to the end of array
+ void add(T x) {
+ if (size == max)
+ remax(2*max + 1);
+
+ // T::operator=(T &) is called here. Safe to use with automatic
+ // vars
+ thearray[size++] = x;
+ }
+
+ /// junk last entry.
+ void pop() { size -- ; }
+
+ /// return last entry
+ T& last(int j=0) {
+ return (*this)[size-j-1];
+ }
+ void swap (int i,int j) {
+ T t((*this)[i]);
+ (*this)[i]=(*this)[j];
+ (*this)[j]=t;
+ }
+ bool empty() { return !size; }
+ void insert(T&k, int j) {
+ assert(j >=0 && j<= size);
+ set_size(size+1);
+ for (int i=size-1; i > j; i--)
+ thearray[i] = thearray[i-1];
+ thearray[j] = k;
+ }
+ void del(int i) {
+ assert(i >=0&& i < size);
+ arrcpy(thearray+i, thearray+i+1, size-i);
+ size--;
+ }
+ // quicksort.
+ void sort (int (*compare)(T& , T& ),
+ int lower = -1, int upper = -1 ) {
+ if (lower < 0) {
+ lower = 0 ;
+ upper = sz();
+ }
+ if (lower >= upper)
+ return;
+ swap(lower, (lower+upper)/2);
+ int last = lower;
+ for (int i= lower +1; i <= upper; i++)
+ if (compare(thearray[i], thearray[lower]) < 0 )
+ swap( ++last,i);
+ swap(lower, last);
+ sort(compare, lower, last-1);
+ sort(compare, last+1, lower);
+ }
+};
+/**
+
+ This template implements a scaleable vector. With (or without) range
+ checking. It may be flaky for objects with complicated con- and
+ destructors. The type T should have a default constructor. It is
+ best suited for simple types, such as int, double or String
+
+ */
+
+/// A simple stack based on svec.
+template<class T>
+class sstack : svec<T> {
+ public:
+ T top() { return last(); }
+ T pop() {
+ assert(!empty());
+ T l = last();
+ svec<T>::pop();
+ return l;
+ }
+ void push(T l) { add(l); }
+ bool empty() { return svec<T>::empty(); }
+};
+/**
+ Same as for #svec# goes here.
+*/
+#endif