-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
-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
--- /dev/null
+/*
+ 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
#include "varray.hh"
#include <assert.h>
+/**
+ A helper for Assoc
+ */
template<class K, class V>
struct Assoc_ent_ {
bool free;
};
-/** mindblowingly stupid Associative array implementation.Hungarian: map
+/** mindblowingly stupid Associative array implementation.
+ Hungarian: map
*/
template<class K, class V>
struct Assoc {
int i = find_creat(key);
arr[i].val = val;
}
- /*
- should create "set" template
- */
V& operator[](K key) {
return arr[find_creat(key)].val;
}
assert((original()-P).norm() / P.norm() < EPS);
#endif
}
-
+
Matrix
Choleski_decomposition::original() const
{
--- /dev/null
+#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;
+ }
+ }
+}
+
+
--- /dev/null
+/*
+ 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
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;
/*
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);
ostream &
-long_option_init::printon(ostream &errorout)
+Long_option_init::printon(ostream &errorout)
{
if (shortname)
errorout <<"-" << shortname;
*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:
exit(2);
}
-long_option_init *
-Getopt_long::parseshort() {
+Long_option_init *
+Getopt_long::parseshort()
+{
char c=argv[optind][optindind];
beet=0;
assert(c);
return beet;
}
-long_option_init *
+Long_option_init *
Getopt_long::operator()() {
if (!next())
return 0;
}
}
-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;
table_len = i;
}
-bool Getopt_long::next() {
+bool
+Getopt_long::next()
+{
+
error = E_NOERROR;
while (optind < argc && !argv[optind][optindind]) {
optind++;
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;
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();
/// 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
#include "matrix.hh"
static Dstream *dout = 0;
+
/**
Set the debugging output. Will not delete/swallow argument.
*/
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(); }
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
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];
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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
--- /dev/null
+/* -*-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
#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
/// 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
/// 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;
/// convert to a double
double value_f() const;
- // *****
};
#include "compare.hh"
// String quoteString(String message, String quote);
-#include "string-convert.hh"
-
#endif
-// 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;
#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"
--- /dev/null
+#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());
+ }
+}
+
+
--- /dev/null
+#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
--- /dev/null
+#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;
+}
+
--- /dev/null
+
+#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
/**
- 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 {
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 ;