]> git.donarmstrong.com Git - lilypond.git/commitdiff
flower-1.1.4
authorfred <fred>
Mon, 3 Mar 1997 13:57:50 +0000 (13:57 +0000)
committerfred <fred>
Mon, 3 Mar 1997 13:57:50 +0000 (13:57 +0000)
24 files changed:
flower/NEWS
flower/Sources.make
flower/assoc-iter.hh [new file with mode: 0644]
flower/assoc.hh
flower/choleski.cc
flower/data-file.cc [new file with mode: 0644]
flower/data-file.hh [new file with mode: 0644]
flower/fproto.hh
flower/lgetopt.cc
flower/lgetopt.hh
flower/matdebug.cc
flower/pcursor.hh
flower/smat.cc
flower/string-data.hh [new file with mode: 0644]
flower/string-handle.hh [new file with mode: 0644]
flower/string-handle.inl [new file with mode: 0644]
flower/string.hh
flower/stringtest.cc
flower/stringutil.cc
flower/text-db.cc [new file with mode: 0644]
flower/text-db.hh [new file with mode: 0644]
flower/text-stream.cc [new file with mode: 0644]
flower/text-stream.hh [new file with mode: 0644]
flower/varray.hh

index d6d6d86aed3c938ad0247a5505c968a646539bcc..36c03ddcd46c0f66f4eb975df29a5f4e5c5b24a4 100644 (file)
@@ -1,4 +1,7 @@
-pl 1.1.3-1
+
+pl 1.1.4
+       - great file-renaming.
+       - String cleanup (binary <-> null terminate), several bugfixes
        - great renaming of String and String_convert interfaces
        - more conversions moved (copied actually) to String_convert
        - String indexing now all base = 0, not found = -1
index 82454e3e3cf84e9f5a3cacb3234ea986f65eab26..4e08bec73582c836a9411c12f7042869d6b677ea 100644 (file)
@@ -1,18 +1,21 @@
 
-cc=choleski.cc datafile.cc dstream.cc lgetopt.cc matdebug.cc matrix.cc\
-path.cc scalar.cc smat.cc string.cc string-convert.cc stringutil.cc\
-textdb.cc textstream.cc unionfind.cc vector.cc 
+cc=choleski.cc data-file.cc dstream.cc lgetopt.cc libc-extension.cc matdebug.cc\
+       matrix.cc\
+       path.cc scalar.cc smat.cc string.cc string-convert.cc stringutil.cc\
+       text-db.cc text-stream.cc unionfind.cc vector.cc 
 
 templatecc=cursor.tcc list.tcc plist.tcc interval.tcc\
        pcursor.tcc
 
-inl=link.inl list.inl  cursor.inl plist.inl stringdata.inl stringhandle.inl
+inl=link.inl list.inl  cursor.inl plist.inl string-data.inl string-handle.inl
 
-hh=assoc.hh associter.hh choleski.hh compare.hh cursor.hh dstream.hh\
-fproto.hh handle.hh interval.hh iterate.hh lgetopt.hh link.hh list.hh\
-matrix.hh path.hh pcursor.hh plist.hh rational.hh real.hh scalar.hh\
-smat.hh string.hh string-convert.hh stringhandle.hh stringdata.hh\
-textdb.hh textstream.hh unionfind.hh pqueue.hh\
-varray.hh vector.hh vsmat.hh datafile.hh
+hh=assoc.hh assoc-iter.hh choleski.hh compare.hh cursor.hh data-file.hh \
+       dstream.hh\
+       fproto.hh handle.hh interval.hh iterate.hh lgetopt.hh \
+       libc-extension.hh link.hh list.hh\
+       matrix.hh path.hh pcursor.hh plist.hh rational.hh real.hh scalar.hh\
+       smat.hh string.hh string-convert.hh string-handle.hh string-data.hh\
+       text-db.hh text-stream.hh unionfind.hh pqueue.hh\
+       varray.hh vector.hh vsmat.hh 
 
 extra=stringtest.cc
diff --git a/flower/assoc-iter.hh b/flower/assoc-iter.hh
new file mode 100644 (file)
index 0000000..34b88df
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+  associter.hh -- part of flowerlib
+
+  (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef ASSOCITER_HH
+#define ASSOCITER_HH
+
+#include "assoc.hh"
+
+/// an iterator for the #Assoc# class
+template<class K, class V>
+struct Assoc_iter {
+    int i;
+    Assoc<K,V> &assoc_;
+    /// we don't want to be bothered by const correctness
+    Assoc_iter(const Assoc<K,V> &a) :
+       assoc_((Assoc<K,V> &)a)
+    {  
+       i= next(0);
+    }
+    int next(int j) {
+       while (j < assoc_.arr.size() && assoc_.arr[j].free)
+           j++;
+       return j;
+    }
+    bool ok() const {
+       return i < assoc_.arr.size();
+    }
+    void OK()const {
+       assert(!ok() || !assoc_.arr[i].free);
+    }
+    void operator++(int) { i++; i = next(i); }
+    K key() { return assoc_.arr[i].key; }
+    V &val() { return assoc_.arr[i].val; }    
+};
+
+#endif
index 07afb8a27ce45499aa8d7c6d191cbdad7573fdf3..99e20914b7aa31094643cd59533844772d668e54 100644 (file)
@@ -4,6 +4,9 @@
 #include "varray.hh"
 #include <assert.h>
 
+/**
+  A helper for Assoc
+ */
 template<class K, class V>
 struct Assoc_ent_ {
     bool free;
@@ -12,7 +15,8 @@ struct Assoc_ent_ {
 };
 
 
-/** mindblowingly stupid Associative array implementation.Hungarian: map
+/** mindblowingly stupid Associative array implementation.
+  Hungarian: map
  */
 template<class K, class V>
 struct Assoc {
@@ -62,9 +66,6 @@ public:
        int i = find_creat(key);
        arr[i].val = val;
     }
-    /*
-    should create "set" template
-    */
     V& operator[](K key) {
        return arr[find_creat(key)].val;
     }
index 4202a9b1e5eed0a3b64349f7fcb1954ea5a5b073..1d64f949acdc775844c65d58f16dc8778937f2be 100644 (file)
@@ -59,7 +59,7 @@ Choleski_decomposition::Choleski_decomposition(Matrix P)
     assert((original()-P).norm() / P.norm() < EPS);
 #endif
 }
-     
+
 Matrix
 Choleski_decomposition::original() const
 {
diff --git a/flower/data-file.cc b/flower/data-file.cc
new file mode 100644 (file)
index 0000000..0dad79c
--- /dev/null
@@ -0,0 +1,95 @@
+#include <fstream.h>
+#include <ctype.h>
+
+#include "data-file.hh"
+
+void 
+Data_file::gobble_white()
+{
+    char c;
+    
+    while ((c=data_get()) == ' ' ||c == '\t')
+       if (eof()) 
+           break;
+
+    data_unget(c);
+}
+
+String
+Data_file::get_word() 
+{// should handle escape seq's
+    String s;
+
+    while (1) 
+       {
+       char    c  = data_get();
+       
+       if (isspace(c) || eof()) 
+           {
+           data_unget(c);
+           break;
+           }
+       
+       
+       if (c == '\"')
+           {
+           rawmode= true;
+
+           while ((c  = data_get()) != '\"')
+               if (eof())
+                   error("EOF in a string");           
+               else
+                   s += c;
+           
+
+           rawmode= false;
+           }       
+       else
+           s += c;             
+       }
+    
+    return s;        
+}
+
+/**  get a char 
+   Only class member who uses text_file::get
+   */
+char
+Data_file::data_get() {
+    char c =  get(); 
+    if (!rawmode && c == '#') // gobble comment
+       {       
+       while ((c = get()) != '\n' && !eof()) 
+           ;
+           return '\n';
+       }    
+
+    return c;
+}
+
+/// read line, gobble '\n'    
+String Data_file::get_line()     
+{
+    char c; 
+    String s;
+
+    while ((c  = data_get()) != '\n' && !eof())
+       s += c;
+    return s;  
+}
+
+/// gobble stuff before first entry on a line.    
+void
+Data_file::gobble_leading_white() 
+{
+    // eat blank lines.
+    while (!eof()) {
+       char c = data_get();                
+       if (!isspace(c)) {
+           data_unget(c);
+           break;
+       }
+    }
+}
+
+
diff --git a/flower/data-file.hh b/flower/data-file.hh
new file mode 100644 (file)
index 0000000..dae9e56
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+  data-file.hh -- declare Data_file
+
+  source file of the LilyPond music typesetter
+
+  (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#ifndef DATAFILE_HH
+#define DATAFILE_HH
+
+#include "text-stream.hh"
+
+/// read a data file
+class Data_file : private Text_stream
+{
+    
+ public:
+    bool rawmode;
+
+    Text_stream::line;    
+    Text_stream::eof;
+    Text_stream::get_name;    
+
+    char data_get();    
+    void data_unget(char c) {
+       unget(c);
+    }
+
+    /// read line, eat #\n#
+    String get_line();
+    
+    /// read a word till next space, leave space. Also does quotes
+    String get_word();
+
+    /// gobble horizontal white stuff.
+    void gobble_white();
+
+    /// gobble empty stuff before first field.
+    void gobble_leading_white();
+    Data_file(String s) : Text_stream(s) {
+       //*mlog << "(" << s << flush;   
+       rawmode=  false;        
+    }
+
+    ~Data_file()  {
+       //      *mlog << ")"<<flush;    
+    }    
+
+    warning(String s) {
+       message("warning: " + s);
+    }
+    error(String s){
+       message(s);
+       exit(1);    
+    }
+};
+#endif // DATAFILE_HH
index 509d25d3fa7c80cd1357193ce7d686f582ce9bb5..57469fead57711b5ced16bda6f84a835cbedb08b 100644 (file)
@@ -16,25 +16,25 @@ template<class T> struct IPointerList;
 template<class T> struct Cursor;
 template<class T> struct PCursor;
 template<class T> struct Link;
-template<class T> struct Handle ;
-template<class T>struct Interval_t ;
+template<class T> struct Handle;
+template<class T>struct Interval_t;
 #include "real.hh"
 
 typedef Interval_t<Real> Interval;
 
-struct Choleski_decomposition ;
+struct Choleski_decomposition;
 
-struct long_option_init ;
-struct Getopt_long ;
-struct Matrix ;
-struct String_data ;
-struct String_handle ;
+struct Long_option_init;
+struct Getopt_long;
+struct Matrix;
+struct String_data;
+struct String_handle;
 struct String_convert;
 struct String;
-struct virtual_smat ;
-struct Vector  ;
-class Text_stream;
-class Data_file ;
+struct virtual_smat;
+struct Vector ;
+struct Text_stream;
+struct Data_file;
 struct Text_db;
 struct Scalar;
 typedef unsigned char Byte;
index 523d54ee5fa758a4a8d4db63d486eefee4559d19..a56c64c6dbd40c98043f5e4474e2360f49a3508d 100644 (file)
@@ -1,7 +1,6 @@
 /*
    process command line, GNU style.
 
-
    this is (Copyleft) 1996, Han-Wen Nienhuys, <hanwen@stack.nl>
  */
 #include <stdio.h>
 #include "lgetopt.hh"
 
 long
-Getopt_long::intarg() {
+Getopt_long::intarg()
+{
     long l;
     if (sscanf(optarg, "%ld", &l) != 1)
        report(E_ILLEGALARG);
     
     return l;
 }
-long_option_init *
-Getopt_long::parselong() {
+
+Long_option_init *
+Getopt_long::parselong()
+{
     const char *optnm = argv[optind] + 2 ;
     assert(*optnm);
     
@@ -64,7 +66,7 @@ Getopt_long::parselong() {
 
 
 ostream &
-long_option_init::printon(ostream &errorout)
+Long_option_init::printon(ostream &errorout)
 {
     if (shortname)     
        errorout <<"-" << shortname;
@@ -91,7 +93,8 @@ Getopt_long::report(Errorcod c)
        *errorout << "requires an argument"<<endl;
        break;
     case  E_NOARGEXPECT:
-       *errorout << "option `--" << beet->longname << "' does not allow an argument"<<endl;
+       *errorout << "option `--" <<
+           beet->longname << "' does not allow an argument"<<endl;
        break;
        
     case E_UNKNOWNOPTION:
@@ -112,8 +115,9 @@ Getopt_long::report(Errorcod c)
     exit(2); 
 }
     
-long_option_init *
-Getopt_long::parseshort() {
+Long_option_init *
+Getopt_long::parseshort()
+{
     char c=argv[optind][optindind];
     beet=0;
     assert(c);
@@ -150,7 +154,7 @@ Getopt_long::parseshort() {
     return beet;
 }
 
-long_option_init *
+Long_option_init *
 Getopt_long::operator()() {
     if (!next())
        return 0;
@@ -169,7 +173,8 @@ Getopt_long::operator()() {
     }
 }
 
-Getopt_long::Getopt_long(int c, char **v, long_option_init *lo) {
+Getopt_long::Getopt_long(int c, char **v, Long_option_init *lo)
+{
     the_opts = lo;
     errorout = &cerr;
     argv = v;
@@ -184,7 +189,10 @@ Getopt_long::Getopt_long(int c, char **v, long_option_init *lo) {
     table_len = i;
 }
 
-bool Getopt_long::next() {
+bool
+Getopt_long::next()
+{
+
     error = E_NOERROR;
     while (optind < argc && !argv[optind][optindind]) {
        optind++;
index 31fb2c55ebe609b4d9e778f45b417f450577d83f..3b2b0348b3a9a0698682d0de6b72b571e6423d88 100644 (file)
@@ -6,7 +6,10 @@
 
 class ostream;
 
-struct long_option_init {
+/**
+  a struct this for initialising the commandline options.
+ */
+struct Long_option_init {
     bool take_arg;
     const char* longname;
     char        shortname;
@@ -29,34 +32,31 @@ public:
 private:
 
     /// the option info.
-    long_option_init *the_opts;
+    Long_option_init *the_opts;
     int table_len;
     
     /// if doing short option, argv[optind][optindind] is processed next.
     int optindind;
 
     /// the option found
-    long_option_init *beet;
+    Long_option_init *beet;
 
     /// get ready for processing next error.
     bool next();
-    long_option_init *parselong();
-    long_option_init *parseshort();
+    Long_option_init *parselong();
+    Long_option_init *parseshort();
     
     ostream *errorout;
 
     /// report an error and abort
     void report(Errorcod c);
 public:
-    /**  what to do with  errors. 
-       report messages on  #*os#, and abort.
-       if #os# is null, then do not report nor abort, just set #error#
-      */
-       
-    void seterror(ostream *os);
+
     /// argument. Set to 0 if not present
     char* optarg;
 
+    /// current error status
+    Errorcod error;
 
     /// return an integer (with err. detect)
     long intarg();
@@ -69,17 +69,26 @@ public:
     /// the arg. count
     int argc;
     
+    /* *************** */
+    
+    /**
+      What to do with  errors. 
+       report messages on  #*os#, and abort.
+       if #os# is null, then do not report nor abort, just set #error#
+      */
+       
+    void seterror(ostream *os);
+
     /// construct: pass arguments and option info.
-    Getopt_long(int c,  char **v, long_option_init *lo);
+    Getopt_long(int c,  char **v, Long_option_init *lo);
 
     /**  get the next option. 
       @return pointer to next option found.
       0 if error occurred, or next argument is no option.
       */
-    long_option_init *operator()();
+    Long_option_init *operator()();
 
     char *current_arg();
     char * get_next_arg();
-    Errorcod error;
 };
 #endif
index 1a5d8679037cd795fa77f376899cbb47cd453eb8..bcc2843bcaa43e0fe85bdd2cb4d93c9ef9eca8da 100644 (file)
@@ -2,6 +2,7 @@
 #include "matrix.hh"
 
 static Dstream *dout = 0;
+
 /**
   Set the debugging output. Will not delete/swallow argument.
  */
index 1215270e3b6b02338ed0db07dc119dfe0aa52f51..ea360078d1a0c53fec53e6bad315a75bc2b6617b 100644 (file)
@@ -25,14 +25,14 @@ public:
     Cursor<void*>::ok;
     Cursor<void*>::del;
     Cursor<void*>::backspace;
-    T get() {
+    T get_p() {
        T p = ptr();
        Cursor<void*>::del();
        return p;
     }
     T get_prev() {
        (*this)--;
-       return get();
+       return get_p();
     }
     
     PointerList<T> &list() { return (PointerList<T>&)Cursor<void*>::list(); }
index d89e3bc285e9c2482af7ae844dad4252a8eb0b19..dcc61ce44ef26eadb600db6c8b9fcd3155ec1e82 100644 (file)
@@ -19,16 +19,6 @@ Full_storage::OK() const
     assert(maxh >= h && maxw >= w);
     assert(h >= 0 && w >= 0);
     assert(els||!maxh);
-    if (maxh>0) {              // access outer elts.
-       Real *r = els[maxh -1];
-       #if 0
-       if (maxw>0) {
-           assert(r);
-           Real s = r[maxw -1]; // accessing unitialised memory.
-           s = sin(s);
-       }
-       #endif
-    }
 #endif
 }
 void
@@ -59,7 +49,7 @@ Full_storage::resize_rows(int neww)
        return;
     }
     for (int i=0; i < maxh ; i++) {
-       Real* newa=new Real[neww];
+       Real* newa = new Real[neww];
        for (int k=0; k < w; k++)
            newa[k] = els[i][k];
 
diff --git a/flower/string-data.hh b/flower/string-data.hh
new file mode 100644 (file)
index 0000000..d4f4b6b
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+  string-data.hh -- declare  String_data
+
+  source file of the LilyPond music typesetter
+
+  (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#ifndef STRINGDATA_HH
+#define STRINGDATA_HH
+
+
+/**Internal String struct.
+   the data itself. Handles simple tasks (resizing, resetting)
+   */
+class String_data {
+    // GNU malloc: storage overhead is 8 bytes anyway.
+
+friend class String_handle;
+    int maxlen;        // maxlen is arraysize-1
+    
+    int length_i_;
+    Byte* data_byte_p_;
+    int references;
+
+    /// init to ""
+    String_data();
+
+    /// init from src. Conservative allocation.
+    String_data(String_data const &src); 
+    
+    ~String_data();
+
+    /** POST: maxlen >= j.
+      @param j, maximum stringlength_i_.    
+      contents thrown away.
+    */
+    void setmax(int j);
+    
+    /** POST: maxlen >= j.
+      @param j, maximum stringlength_i_.
+      contents are kept if it grows.
+      */
+    void remax(int j);
+
+    /// check if writeable.
+    void OKW();
+
+    /// check state.
+    void OK();
+
+    /// reduce memory usage.
+    void tighten();
+
+    // assignment.
+    void set( Byte const* byte_c_l, int length_i );
+
+    void set( char const* ch_c_l );
+    
+    /// concatenation.
+    void append( Byte const* byte_c_l, int length_i );
+
+    void operator += ( char const* ch_c_l );
+
+    char const* ch_c_l() const; 
+
+    char* ch_l();
+
+    Byte const* byte_c_l() const;
+
+    // idem, non const
+    Byte* byte_l();
+
+    void trunc(int j);
+
+    /** access element. not really safe. Can alter length_i_ without
+      #String_data# knowing it.  */
+    Byte &operator [](int j);
+    Byte operator [](int j) const;
+    bool null_terminated_b()const;
+};
+
+
+
+#ifdef STRING_UTILS_INLINED
+#ifndef INLINE
+#define INLINE inline
+#endif
+#include "string-data.inl"
+
+#endif
+
+
+#endif // STRING_DATA_HH
diff --git a/flower/string-handle.hh b/flower/string-handle.hh
new file mode 100644 (file)
index 0000000..fe109d8
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+  string-handle.hh -- declare String_handle
+
+  source file of the LilyPond music typesetter
+
+  (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#ifndef STRINGHANDLE_HH
+#define STRINGHANDLE_HH
+#include "fproto.hh"
+
+
+/**
+  Reference counting for strings.
+  
+   handles ref. counting, and provides a very thin interface using
+   Byte *
+
+   */
+class String_handle {
+    String_data* data;
+    
+    /// decrease ref count. Named kind of like a Tanenbaum semafore 
+    void down();
+
+    /// increase ref count
+    void up(String_data *d);
+    
+    /** make sure data has only one reference.      
+       POST: data->references == 1
+      */
+    void copy();
+    
+public:
+    String_handle();
+    ~String_handle();
+    String_handle(String_handle const & src);
+
+    Byte const* byte_c_l() const;
+    char const* ch_c_l() const;
+    Byte* byte_l();
+    char* ch_l();    
+    bool null_terminated_b()const;
+    void operator =(String_handle const &src);
+    void operator += (char const *s);
+    Byte operator[](int j) const;
+
+    /** Access elements. WARNING: NOT SAFE
+       don't use this for loops. Use byte_c_l()
+       */
+    Byte &operator[](int j);
+    void append( Byte const* byte_c_l, int length_i );
+    void set( Byte const* byte_c_l, int length_i );
+    void operator = (char const *p);
+    void trunc(int j);
+    int length_i() const;
+};
+
+#ifdef STRING_UTILS_INLINED
+#ifndef INLINE
+#define INLINE inline
+#endif
+#include "string-handle.inl"
+/* we should be resetting INLINE. oh well. */
+#endif
+
+
+#endif // STRINGHANDLE_HH
diff --git a/flower/string-handle.inl b/flower/string-handle.inl
new file mode 100644 (file)
index 0000000..7286fd6
--- /dev/null
@@ -0,0 +1,156 @@
+/* -*-c++-*-
+   
+  stringhandle.inl -- implement String_handle
+
+  source file of Flower lib
+
+  (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+#ifndef STRINGHANDLE_INL
+#define STRINGHANDLE_INL
+
+#include <assert.h>
+#include <memory.h>
+
+#include "string-data.hh"
+#include "string-handle.hh"
+
+INLINE void 
+String_handle::down() 
+{ 
+    if (!(--data->references)) delete data; data = 0; 
+}
+
+/// increase ref count
+INLINE void 
+String_handle::up(String_data *d) 
+{ 
+    data=d; data->references ++; 
+}
+
+INLINE void 
+String_handle::copy() 
+{
+    if (data->references !=1){
+       String_data *newdata = new String_data(*data);
+       down();
+       up(newdata);
+    }
+}
+
+INLINE
+String_handle::String_handle() 
+{
+    up(new String_data);
+}
+
+INLINE
+String_handle::~String_handle() 
+{      
+    down();
+}    
+
+INLINE
+String_handle::String_handle(String_handle const & src) 
+{      
+    up(src.data);
+}
+
+INLINE Byte* 
+String_handle::byte_l() 
+{
+    copy();
+    return data->byte_l();
+}
+
+INLINE char* 
+String_handle::ch_l() 
+{
+    copy();
+    return (char*)data->byte_l();
+}
+
+INLINE Byte 
+const* String_handle::byte_c_l() const 
+{
+    return data->byte_c_l();
+}
+
+INLINE char const* 
+String_handle::ch_c_l() const 
+{
+    return (char const*)data->byte_c_l();
+}
+
+INLINE void 
+String_handle::operator =(String_handle const &src) 
+{
+    if (this == &src)
+       return;
+    down();
+    up(src.data);
+}
+
+INLINE void 
+String_handle::operator += (char const *s) 
+{      
+    copy();
+    *data += s;
+}    
+
+
+INLINE Byte 
+String_handle::operator[](int j) const 
+{ 
+    return (*data)[j]; 
+}
+
+// !NOT SAFE!
+// don't use this for loops. Use byte_c_l()
+INLINE Byte &
+String_handle::operator[](int j) 
+{
+    copy();    // hmm. Not efficient
+    return data->byte_l()[j];
+}
+
+INLINE void 
+String_handle::append( Byte const* byte_c_l, int length_i ) 
+{
+    copy();
+    data->append( byte_c_l, length_i );
+}
+                          
+INLINE void 
+String_handle::set( Byte const* byte_c_l, int length_i ) 
+{
+    copy();
+    data->set( byte_c_l, length_i );
+}
+                          
+INLINE void 
+String_handle::operator = (char const *p) 
+{
+    copy();
+    data->set( p );
+}
+                          
+INLINE void 
+String_handle::trunc(int j) 
+{
+    copy(); data->trunc(j); 
+}
+
+INLINE int 
+String_handle::length_i() const 
+{ 
+    return data->length_i_; 
+}
+
+INLINE bool
+String_handle::null_terminated_b() const {
+    return data->null_terminated_b();
+}
+
+#endif
index 7aa19047d1731e29b200f3db2fbd1dda5a26336a..8cef141169d3a8b568c2acad7cd968c69fa68dde 100644 (file)
@@ -15,7 +15,7 @@
 #include <iostream.h>
 #include <Rational.h>
 
-#include "stringhandle.hh"
+#include "string-handle.hh"
 
 /** 
  
 \item
   ref counting through #String_handle#
 \item
-
-  conversion from bool, int, double, char* , char.
+  conversion from bool, int, double, char* , char.  
 \item
-
   to be moved to String_convert:
   conversion to int, upcase, downcase 
 
 \item
-
   printable. 
 
 \item
   No operator[] is provided, since this would be enormously  slow. If needed,
   convert to char const* .
 \end{itemize}
+
 */
 class String
 {
 protected:
-    String_handle strh_; // should derive String from String_handle?
+    String_handle strh_; 
 
+    bool null_terminated();
+    
 public:
 
-    /**   init to "". needed because other constructors are provided.*/
+    /** init to empty string. This is needed because other
+      constructors are provided.*/
     String() {  }                  
     String(Rational);
+
     /// String s = "abc";
     String( char const* source ); 
-
     String( Byte const* byte_c_l, int length_i ); 
     
     /// "ccccc"
     String( char c, int n = 1 );
 
-    /// String s( 10 );
-    String( int i );
-
+    String( int i , char const *fmt=0);
+    String ( double f , char const* fmt =0);
     /// 'true' or 'false'
     String(bool );
 
-    /// String s( 3.14, 6, '#' );
-    String ( double f , char const* fmt =0);
-    String(  int i,  int n,  char c = ' ' );
-
     ///  return a "new"-ed copy of contents
     Byte* copy_byte_p() const; //  return a "new"-ed copy of contents
 
@@ -91,12 +87,15 @@ public:
     /// deprecated; use ch_c_l()
     operator char const* () const { return ch_c_l(); }
     
-    String operator =( const String & source ) { strh_ = source.strh_; return *this; }
+    String &operator =( const String & source );
 
     /// concatenate s
     void operator += (char const* s) { strh_ += s; }
     void operator += (String s);
 
+    void append(String);
+    void prepend(String);
+
     char operator []( int n ) const { return strh_[n]; }
 
     /// return n leftmost chars
@@ -130,17 +129,12 @@ public:
     /// index of rightmost element of string 
     int index_last_i( char const* string ) const;
 
-    /**
-      index of leftmost c.
-      
-    @return
-    -1 if not found, else index
-    */
     int index_i(char c ) const;
-    int index_i(char const* string ) const;
-    int index_any_i(char const* string ) const;
-
+    int index_i(String ) const;
+    int index_any_i(String ) const;
 
+    void to_upper();
+    void to_lower();
     /// provide Stream output
     void print_on(ostream& os) const;
 
@@ -157,7 +151,6 @@ public:
 
     /// convert to a double
     double value_f() const;
-    // *****     
 };
 
 #include "compare.hh"
@@ -197,6 +190,4 @@ operator << ( ostream& os, String d )
 
 // String quoteString(String message, String quote);
 
-#include "string-convert.hh"
-
 #endif
index c0c50da5c6e4acd586d79a74c57d9b27d44ceaea..2f085a26d7d674cf9636a7f82db59ce545f5d694 100644 (file)
-// stringtest.cc
-
+/*
+  stupid test program to verify stringlib
+  stringtest.cc
+  */
 #include <iostream.h>
 #include "string.hh"
+#include "varray.hh"
+#include "string-convert.hh"
+
+void
+ctors()
+{
+    cout << "constructors"<<endl;
+
+    String str( "hai" );
+    String def;
+    String fromi(10);
+    String fromc('c');
+    String fromf(1.32e-2, "%g");
+
+    cout << str << endl;
+    cout << def << endl;
+    cout << fromi<< endl;
+    cout << fromc<< endl;       
+    cout << fromf<< endl;
+}
+
+void
+cmp()
+{
+    Array<String> a;
+    a.push("abcd");
+    a.push("zxy");
+    a.push("abc");
+    a.push("");
+    a.sort(String::compare_i);
+    cout << "compares: "<<endl;
+    for (int i=0; i < a.size(); i++)
+       cout << a[i] << endl;
+}
+
+
+void
+searching()
+{
+    String hay = "foobarbazblub";
+
+    char c =   'b';
+    String cstr =c;
+    String set = "bar";
+    cout << "hay = \"" << hay << "\" len="<< hay.length_i()<<endl;
+    cout << "index_i('"<< c<<"') " << c << "= " << hay.index_i(c) <<endl;
+    cout << "last_index_i('"<< c<<"') " << c << "= " << hay.index_last_i(c) <<endl;    
+//    cout << "last index of cstr " << c << ": " << hay.index_last_i(cstr) <<endl;    
+//    cout << "index_last_i(\""<<set<<"\"): " << hay.index_last_i(set) <<endl;
+    cout << "index_i(\""<<set<<"\"): " << hay.index_i(set) <<endl;    
+    cout << "index_any(\"" << set << "\"): " << cstr << ": " << hay.index_any_i(cstr) <<endl;
+
+    
+    
+}
+
+
+void
+kutenpeer()
+{
+    String str( "hai" );
+    for (int i=-1; i < str.length_i()+2; i++) {
+       cout<<" left_str(" << i<<"): " << str.left_str( i ) << endl;
+       cout<<" right_str( "<<i<<"): " << str.right_str( i ) << endl;
+    }
+    str = "blonde haren";
+    cout << str<<endl;
+    cout << "mid(2,6)="<<str.mid_str(2,3)<<endl;
+    cout << "nomid(2,6)="<<str.nomid_str(2,3)<<endl;
+}
 
 int 
 main()
 {
+    ctors();
+    cmp();
+    searching();
+    kutenpeer();
     String str( "hai" );
     cout <<  str << endl;
     cout << "left" << endl;
-    cout << "  0:" << str.left_str( 0 ) << endl;
-    cout << "  1:" << str.left_str( 1 ) << endl;
-    cout << "  2:" << str.left_str( 2 ) << endl;
-    cout << "  3:" << str.left_str( 3 ) << endl;
-    cout << "  4:" << str.left_str( 4 ) << endl;
-    cout << "right" << endl;
-    cout << "  0:" << str.right_str( 0 ) << endl;
-    cout << "  1:" << str.right_str( 1 ) << endl;
-    cout << "  2:" << str.right_str( 2 ) << endl;
-    cout << "  3:" << str.right_str( 3 ) << endl;
-    cout << "  4:" << str.right_str( 4 ) << endl;
-
     str += " daar";
     cout << str << endl;
 
-    str = String( "hallo" ) + " daar" + '!';
+    str = String( "Hallo" ) + " daaR" + '!';
     cout << str << endl;
 
+    cout << "up: " << str.upper_str() << " down: " << str.lower_str()<<endl;
+    
     if ( str == String( "" ) )
         cout << str << " is empty" << endl;
+    else
+       cout << str << " is not empty"<<endl;
+
+    
     String fn = "";
     if ( fn == "" )
         cout << fn << " is empty" << endl;
-
+    else
+       assert(false);
+    
     fn = "";
     fn += "";
     delete fn.copy_byte_p();
-
     delete str.copy_byte_p();
 
     cout << String_convert::bin2hex_str( String( (char)0xff ) ) << endl;
index 55e4fa1426e2ac8e6f6bcd8db12cb8798f534f90..43c8e15d8259b8a309ce8363fc8b07b03f86f0cf 100644 (file)
@@ -27,7 +27,7 @@ mymemmove( void* dest, void const* src, size_t n )
 
 #define INLINE
 
-#include "stringhandle.hh"
-#include "stringdata.hh"
-#include "stringdata.inl"
-#include "stringhandle.inl"
+#include "string-handle.hh"
+#include "string-data.hh"
+#include "string-data.inl"
+#include "string-handle.inl"
diff --git a/flower/text-db.cc b/flower/text-db.cc
new file mode 100644 (file)
index 0000000..ebfc992
--- /dev/null
@@ -0,0 +1,48 @@
+#include "text-db.hh"
+bool
+Text_db::eof()
+{
+    Data_file::gobble_leading_white();
+    return  Data_file::eof();
+}
+
+void
+Text_db::gobble_leading_white()
+{
+    while (1) {
+       Data_file::gobble_leading_white();
+       if (eof())
+           return ;
+       char c;
+       if  ((c = data_get()) !='\n'){
+           data_unget (c);
+           return ;
+       }       
+    }  
+}
+
+
+Text_record
+Text_db::get_record() 
+{
+   while (1) {
+       String s;
+       Array<String> fields;
+       assert(!eof());
+       
+       while ((s = get_word()) != "")
+           {
+           fields.push(s);     
+           gobble_white();
+           }
+            
+
+       if (get_line() != "")
+           assert(false);
+      
+       assert (fields.size());
+       return Text_record(fields, get_name(), line());
+   }
+}
+
+
diff --git a/flower/text-db.hh b/flower/text-db.hh
new file mode 100644 (file)
index 0000000..3535a84
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef TEXTDB_HH
+#define TEXTDB_HH
+
+#include "data-file.hh"
+
+/**a "const" Array. Contents can't be changed. do "#" comments, read quote enclosed  fields */
+
+class Text_record : Array<String>  
+{
+    int line_no;
+    String filename;
+    
+public:
+    Text_record() { } // needed because of other ctor
+
+    /// report an error in this line.
+    message(String s) {
+       cerr << '\n'<< filename << ": "<< line_no << s << "\n";
+    }         
+    String operator[](int j) {
+       return Array<String>::operator[](j);
+    }
+
+    Text_record(Array<String> s, String fn, int j) : Array<String>(s) { 
+       filename = fn; line_no = j; 
+    }
+    Array<String>::size;           
+};
+
+/** abstraction for a datafile.
+    add a subrec/fieldsep/record separator
+    */
+
+class Text_db : private Data_file
+{
+    void gobble_leading_white();
+public:
+    /// get a line with records
+    Text_record    get_record();
+
+    Text_db(String fn):Data_file(fn) { }
+    Data_file::error;
+    bool eof();
+
+    /// get next line.
+    Text_record operator++(int) {
+       return get_record();
+    }
+    /// are we done yet?
+    operator bool() {
+       return !eof();
+    }
+};
+
+#endif
diff --git a/flower/text-stream.cc b/flower/text-stream.cc
new file mode 100644 (file)
index 0000000..a2d3e4b
--- /dev/null
@@ -0,0 +1,31 @@
+#include "text-stream.hh"
+
+Text_stream::Text_stream(String fn)
+{
+    ios::sync_with_stdio();
+    if (fn == "") 
+           {
+           name = "<STDIN>";       
+           f = stdin;
+           }
+       
+       else 
+           {
+           name = fn;      
+           f = fopen(fn, "r");
+           }
+       
+       if (!f) {
+           cerr <<__FUNCTION__<< ": can't open `" << fn << "'\n";
+           exit(1);
+       }
+
+       line_no = 1;
+    }
+
+void
+Text_stream::message(String s)
+{
+    cerr << "\n"<<get_name() << ": " << line()<<": "<<s<<endl;
+}
+
diff --git a/flower/text-stream.hh b/flower/text-stream.hh
new file mode 100644 (file)
index 0000000..437f869
--- /dev/null
@@ -0,0 +1,74 @@
+
+#ifndef TEXTSTR_HH
+#define TEXTSTR_HH
+
+#include <stdio.h>
+#include <ctype.h>
+#include "string.hh"
+#include "varray.hh"
+
+/**
+  line counting input stream. 
+  a stream for textfiles. linecounting. Thin interface getchar and
+  ungetchar.  (ungetc is unlimited) 
+  
+  should protect get and unget against improper use
+*/
+
+
+class Text_stream
+{
+    int line_no;
+
+    // could just have used streams. 
+    FILE *f;  
+    Array<char> pushback;
+    String name;
+    
+ public:
+    Text_stream(String fn);
+    String get_name() { return name; }
+    bool eof() {
+       return feof(f);
+    }
+    bool eol() {
+       return (peek() == '\n');
+    }
+    char peek() {
+       char c = get();
+       unget(c);
+       return c;
+    }
+    int line(){
+       return line_no;
+    }
+
+    char    get() {
+       char c;
+       
+       if (pushback.empty())
+           c = getc(f);        
+       else 
+           c = pushback.pop();
+
+       if (c =='\n')
+           line_no++;
+       return c;       
+    }
+    void unget(char c) {
+       if (c =='\n')
+           line_no--;
+       pushback.push(c);
+    }
+    ~Text_stream (){
+       if (!eof()) 
+           cerr <<__FUNCTION__<< ": closing unended file";
+    
+       fclose(f);
+    }
+
+    /// GNU format message.
+    void message(String s); 
+};
+
+#endif
index d2c2f5532191e48dcaf41f340fb6145457a207ef..febf3e7601b4ce52bf6d4b12b62dcabd06dd0e3f 100644 (file)
@@ -17,13 +17,18 @@ inline void arrcpy(T*dest, T*src, int count) {
 
 
 /**
-  scaleable array/stack template, for T with def ctor.
+  Scaleable array/stack template, for a type T with default constructor.
+  
+  
   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
+  best suited for simple types, such as int, double or String, it
+  provides a paranoidly safe replacement for the new T[int] construct.
 
   It uses stack terminology, (push, pop, top), and  can be used as a stack.
+
+  
   */
 template<class T>
 class Array {
@@ -146,7 +151,7 @@ public:
        size_--;
     }
     // quicksort.
-    void sort (int (*compare)(T& , T& ),
+    void sort (int (*compare)( T const&,T const&),
               int lower = -1, int upper = -1 ) {
        if (lower < 0) {
            lower = 0 ;