Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include "iom.h"
+
#include <cstdio>
#include <cstdlib>
#include <cerrno>
#if 1 // older unices need these includes for select (2)
# include <unistd.h>
# include <sys/types.h>
+# include <time.h>
+#endif
+
+// for IOM_SIG
+#if IOM_SIG
+# include <signal.h>
+# include <fcntl.h>
#endif
// if the BSDs would at least be marginally POSIX-compatible.. *sigh*
// until that happens, sys/select.h must come last
#include <sys/select.h>
-// for IOM_SIG
-#include <signal.h>
-
-#include "iom.h"
-
// TSTAMP_MAX must still fit into a positive struct timeval
#define TSTAMP_MAX (double)(1UL<<31)
+#define TIMEVAL timeval
+#define TV_FRAC tv_usec
+#define TV_MULT 1000000L
+
+#if IOM_IO
+static io_manager_vec<io_watcher> iow;
+#endif
+#if IOM_CHECK
+static io_manager_vec<check_watcher> cw;
+#endif
+#if IOM_TIME
+static io_manager_vec<time_watcher> tw;
+#endif
+#if IOM_IDLE
+static io_manager_vec<idle_watcher> iw;
+#endif
+#if IOM_SIG
+static int sigpipe[2]; // signal signalling pipe
+static sigset_t sigs;
+struct sig_vec : io_manager_vec<sig_watcher> {
+ int pending;
+ sig_vec ()
+ : pending (false)
+ { }
+};
+static vector<sig_vec *> sw;
+#endif
+
// this is a dummy time watcher to ensure that the first
// time watcher is _always_ valid, this gets rid of a lot
// of null-pointer-checks
}
tw0 ()
- : time_watcher (this, &tw0::cb)
- { }
+ : time_watcher (this, &tw0::cb)
+ { }
} tw0;
tstamp NOW;
+
+#if IOM_TIME
+inline void set_now (void)
+{
+ struct timeval tv;
+
+ gettimeofday (&tv, 0);
+ NOW = (tstamp)tv.tv_sec + (tstamp)tv.tv_usec / 1000000.;
+}
+#endif
+
static bool iom_valid;
-io_manager iom;
-template<class watcher>
-void io_manager::reg (watcher *w, io_manager_vec<watcher> &queue)
+// used for initialisation only
+static struct init {
+ init ()
+ {
+#if IOM_SIG
+ sigemptyset (&sigs);
+
+ if (pipe (sigpipe))
+ {
+ perror ("io_manager: unable to create signal pipe, aborting.");
+ abort ();
+ }
+
+ fcntl (sigpipe[0], F_SETFL, O_NONBLOCK);
+ fcntl (sigpipe[1], F_SETFL, O_NONBLOCK);
+#endif
+
+ iom_valid = true;
+
+#if IOM_TIME
+ set_now ();
+
+ tw0.start (TSTAMP_MAX);
+#endif
+ }
+
+ static void required ();
+} init;
+
+void
+init::required ()
{
if (!iom_valid)
- abort ();
+ {
+ write (2, "io_manager: early registration attempt, aborting.\n",
+ sizeof ("io_manager: early registration attempt, aborting.\n") - 1);
+ abort ();
+ }
+}
+
+template<class watcher>
+void io_manager::reg (watcher &w, io_manager_vec<watcher> &queue)
+{
+ init::required ();
- if (!w->active)
+ if (!w.active)
{
#if IOM_CHECK
queue.activity = true;
#endif
- queue.push_back (w);
- w->active = queue.size ();
+ queue.push_back (&w);
+ w.active = queue.size ();
}
}
template<class watcher>
-void io_manager::unreg (watcher *w, io_manager_vec<watcher> &queue)
+void io_manager::unreg (watcher &w, io_manager_vec<watcher> &queue)
{
if (!iom_valid)
return;
- if (w->active)
+ if (w.active)
{
- queue [w->active - 1] = 0;
- w->active = 0;
+ queue [w.active - 1] = 0;
+ w.active = 0;
}
}
void time_watcher::trigger ()
{
call (*this);
-
- iom.reg (this);
+ io_manager::reg (*this);
}
-void io_manager::reg (time_watcher *w) { reg (w, tw); }
-void io_manager::unreg (time_watcher *w) { unreg (w, tw); }
+void io_manager::reg (time_watcher &w) { io_manager::reg (w, tw); }
+void io_manager::unreg (time_watcher &w) { io_manager::unreg (w, tw); }
#endif
#if IOM_IO
-void io_manager::reg (io_watcher *w) { reg (w, iow); }
-void io_manager::unreg (io_watcher *w) { unreg (w, iow); }
+void io_manager::reg (io_watcher &w) { io_manager::reg (w, iow); }
+void io_manager::unreg (io_watcher &w) { io_manager::unreg (w, iow); }
#endif
#if IOM_CHECK
-void io_manager::reg (check_watcher *w) { reg (w, cw); }
-void io_manager::unreg (check_watcher *w) { unreg (w, cw); }
+void io_manager::reg (check_watcher &w) { io_manager::reg (w, cw); }
+void io_manager::unreg (check_watcher &w) { io_manager::unreg (w, cw); }
#endif
#if IOM_IDLE
-void io_manager::reg (idle_watcher *w) { reg (w, iw); }
-void io_manager::unreg (idle_watcher *w) { unreg (w, iw); }
-#endif
-
-#if IOM_TIME
-inline void set_now (void)
-{
- struct timeval tv;
-
- gettimeofday (&tv, 0);
-
- NOW = (tstamp)tv.tv_sec + (tstamp)tv.tv_usec / 1000000;
-}
+void io_manager::reg (idle_watcher &w) { io_manager::reg (w, iw); }
+void io_manager::unreg (idle_watcher &w) { io_manager::unreg (w, iw); }
#endif
#if IOM_SIG
-// race conditions galore
-
-void io_manager::sighandler (int signum)
+static void
+sighandler (int signum)
{
- assert (0 < signum && signum <= iom.sw.size ());
-
- sig_vec &sv = *iom.sw [signum - 1];
+ sw [signum - 1]->pending = true;
- for (int i = sv.size (); i--; )
- if (!sv[i])
- sv.erase_unordered (i);
- else
- sv[i]->call (*sv[i]);
+ // we use a pipe for signal notifications, as most current
+ // OSes (Linux...) do not implement pselect correctly. ugh.
+ char ch = signum; // actual content not used
+ write (sigpipe[1], &ch, 1);
}
-void io_manager::reg (sig_watcher *w)
+void io_manager::reg (sig_watcher &w)
{
- assert (0 < w->signum);
+ assert (0 < w.signum);
- sw.reserve (w->signum);
+ sw.reserve (w.signum);
- sig_vec *&sv = sw [w->signum - 1];
+ while (sw.size () < w.signum) // pathetic
+ sw.push_back (0);
+
+ sig_vec *&sv = sw[w.signum - 1];
if (!sv)
{
sv = new sig_vec;
+ sigaddset (&sigs, w.signum);
+ sigprocmask (SIG_BLOCK, &sigs, NULL);
+
struct sigaction sa;
- sa.sa_handler = io_manager::sighandler;
+ sa.sa_handler = sighandler;
sigfillset (&sa.sa_mask);
- sa.sa_flags = 0;
+ sa.sa_flags = SA_RESTART;
- if (sigaction (w->signum, &sa, 0))
+ if (sigaction (w.signum, &sa, 0))
{
- perror ("Error while installing signal handler");
+ perror ("io_manager: error while installing signal handler, ignoring.");
abort ();
}
+
}
- reg (w, *sv);
+ io_manager::reg (w, *sv);
}
-void io_manager::unreg (sig_watcher *w)
+void io_manager::unreg (sig_watcher &w)
{
- assert (0 < w->signum && w->signum <= sw.size ());
+ if (!w.active)
+ return;
+
+ assert (0 < w.signum && w.signum <= sw.size ());
- unreg (w, *sw [w->signum - 1]);
+ io_manager::unreg (w, *sw[w.signum - 1]);
}
void sig_watcher::start (int signum)
{
stop ();
this->signum = signum;
- iom.reg (this);
+ io_manager::reg (*this);
}
#endif
-
+
void io_manager::loop ()
{
+ init::required ();
+
#if IOM_TIME
set_now ();
#endif
for (;;)
{
- struct timeval *to = 0;
- struct timeval tval;
+ struct TIMEVAL *to = 0;
+ struct TIMEVAL tval;
#if IOM_IDLE
if (iw.size ())
{
tval.tv_sec = 0;
- tval.tv_usec = 0;
+ tval.TV_FRAC = 0;
to = &tval;
}
else
#endif
-
{
#if IOM_TIME
time_watcher *next;
{
double diff = next->at - NOW;
tval.tv_sec = (int)diff;
- tval.tv_usec = (int) ((diff - tval.tv_sec) * 1000000);
+ tval.TV_FRAC = (int) ((diff - tval.tv_sec) * TV_MULT);
to = &tval;
}
break;
}
else
{
- unreg (next);
+ unreg (*next);
next->call (*next);
}
}
#endif
-
}
#if IOM_CHECK
if (tw.activity)
{
tval.tv_sec = 0;
- tval.tv_usec = 0;
+ tval.TV_FRAC = 0;
to = &tval;
}
#endif
-#if IOM_IO
+#if IOM_IO || IOM_SIG
fd_set rfd, wfd;
FD_ZERO (&rfd);
int fds = 0;
+# if IOM_IO
for (io_manager_vec<io_watcher>::iterator i = iow.end (); i-- > iow.begin (); )
if (*i)
{
if ((*i)->fd >= fds) fds = (*i)->fd + 1;
}
+# endif
if (!to && !fds) //TODO: also check idle_watchers and check_watchers
break; // no events
+# if IOM_SIG
+ FD_SET (sigpipe[0], &rfd);
+ if (sigpipe[0] >= fds) fds = sigpipe[0] + 1;
+# endif
+
+# if IOM_SIG
+ // there is no race, as we use a pipe for signals, so select
+ // will return if a signal is caught.
+ sigprocmask (SIG_UNBLOCK, &sigs, NULL);
+# endif
fds = select (fds, &rfd, &wfd, NULL, to);
+# if IOM_SIG
+ sigprocmask (SIG_BLOCK, &sigs, NULL);
+# endif
+
# if IOM_TIME
set_now ();
# endif
if (fds > 0)
- for (int i = iow.size (); i--; )
- if (!iow[i])
- iow.erase_unordered (i);
- else
+ {
+# if IOM_SIG
+ if (FD_ISSET (sigpipe[0], &rfd))
{
- short revents = iow[i]->events;
+ char ch;
+
+ while (read (sigpipe[0], &ch, 1) > 0)
+ ;
+
+ for (sig_vec **svp = sw.end (); svp-- > sw.begin (); )
+ if (*svp && (*svp)->pending)
+ {
+ sig_vec &sv = **svp;
+ for (int i = sv.size (); i--; )
+ if (!sv[i])
+ sv.erase_unordered (i);
+ else
+ sv[i]->call (*sv[i]);
+
+ sv.pending = false;
+ }
+ }
+# endif
- if (!FD_ISSET (iow[i]->fd, &rfd)) revents &= ~EVENT_READ;
- if (!FD_ISSET (iow[i]->fd, &wfd)) revents &= ~EVENT_WRITE;
+# if IOM_IO
+ for (int i = iow.size (); i--; )
+ if (!iow[i])
+ iow.erase_unordered (i);
+ else
+ {
+ short revents = iow[i]->events;
- if (revents)
- iow[i]->call (*iow[i], revents);
- }
+ if (!FD_ISSET (iow[i]->fd, &rfd)) revents &= ~EVENT_READ;
+ if (!FD_ISSET (iow[i]->fd, &wfd)) revents &= ~EVENT_WRITE;
+
+ if (revents)
+ iow[i]->call (*iow[i], revents);
+ }
+#endif
+ }
else if (fds < 0 && errno != EINTR)
{
- perror ("Error while waiting for I/O or time event");
+ perror ("io_manager: fatal error while waiting for I/O or time event, aborting.");
abort ();
}
#if IOM_IDLE
#else
break;
#endif
-
}
}
-io_manager::io_manager ()
-{
- iom_valid = true;
-
-#if IOM_TIME
- set_now ();
-
- tw0.start (TSTAMP_MAX);
-#endif
-}
-
-io_manager::~io_manager ()
-{
- iom_valid = false;
-}
-
}
};
+// only used as a namespace, and for initialisation purposes
class io_manager {
-#if IOM_IO
- io_manager_vec<io_watcher> iow;
-#endif
-#if IOM_CHECK
- io_manager_vec<check_watcher> cw;
-#endif
-#if IOM_TIME
- io_manager_vec<time_watcher> tw;
-#endif
-#if IOM_IDLE
- io_manager_vec<idle_watcher> iw;
-#endif
-#if IOM_SIG
- typedef io_manager_vec<sig_watcher> sig_vec;
- vector<sig_vec *> sw;
- static void sighandler (int signum);
-#endif
-
template<class watcher>
- void reg (watcher *w, io_manager_vec<watcher> &queue);
+ static void reg (watcher &w, io_manager_vec<watcher> &queue);
template<class watcher>
- void unreg (watcher *w, io_manager_vec<watcher> &queue);
+ static void unreg (watcher &w, io_manager_vec<watcher> &queue);
public:
// register a watcher
#if IOM_IO
- void reg (io_watcher *w); void unreg (io_watcher *w);
+ static void reg (io_watcher &w); static void unreg (io_watcher &w);
#endif
#if IOM_TIME
- void reg (time_watcher *w); void unreg (time_watcher *w);
+ static void reg (time_watcher &w); static void unreg (time_watcher &w);
#endif
#if IOM_CHECK
- void reg (check_watcher *w); void unreg (check_watcher *w);
+ static void reg (check_watcher &w); static void unreg (check_watcher &w);
#endif
#if IOM_IDLE
- void reg (idle_watcher *w); void unreg (idle_watcher *w);
+ static void reg (idle_watcher &w); static void unreg (idle_watcher &w);
#endif
#if IOM_SIG
- void reg (sig_watcher *w); void unreg (sig_watcher *w);
+ static void reg (sig_watcher &w); static void unreg (sig_watcher &w);
#endif
- void loop ();
-
- io_manager ();
- ~io_manager ();
+ static void loop ();
};
-extern io_manager iom; // a singleton, together with it's construction/destruction problems.
-
struct watcher {
int active; /* 0 == inactive, else index into respective vector */
void set (int fd_, short events_) { fd = fd_; events = events_; }
void set (short events_) { set (fd, events_); }
- void start () { iom.reg (this); }
- void start (int fd_, short events_) { set (fd_, events_); iom.reg (this); }
- void stop () { iom.unreg (this); }
+ void start () { io_manager::reg (*this); }
+ void start (int fd_, short events_) { set (fd_, events_); io_manager::reg (*this); }
+ void stop () { io_manager::unreg (*this); }
template<class O1, class O2>
io_watcher (O1 *object, void (O2::*method) (io_watcher &, short))
void set (tstamp when) { at = when; }
void operator () () { trigger (); }
- void start () { iom.reg (this); }
- void start (tstamp when) { set (when); iom.reg (this); }
- void stop () { iom.unreg (this); }
+ void start () { io_manager::reg (*this); }
+ void start (tstamp when) { set (when); io_manager::reg (*this); }
+ void stop () { io_manager::unreg (*this); }
template<class O1, class O2>
time_watcher (O1 *object, void (O2::*method) (time_watcher &))
#if IOM_CHECK
// run before checking for new events
struct check_watcher : watcher, callback1<void, check_watcher &> {
- void start () { iom.reg (this); }
- void stop () { iom.unreg (this); }
+ void start () { io_manager::reg (*this); }
+ void stop () { io_manager::unreg (*this); }
template<class O1, class O2>
check_watcher (O1 *object, void (O2::*method) (check_watcher &))
#if IOM_IDLE
// run after checking for any i/o, but before waiting
struct idle_watcher : watcher, callback1<void, idle_watcher &> {
- void start () { iom.reg (this); }
- void stop () { iom.unreg (this); }
+ void start () { io_manager::reg (*this); }
+ void stop () { io_manager::unreg (*this); }
template<class O1, class O2>
idle_watcher (O1 *object, void (O2::*method) (idle_watcher &))
int signum;
void start (int signum);
- void stop () { iom.unreg (this); }
+ void stop () { io_manager::unreg (*this); }
template<class O1, class O2>
sig_watcher (O1 *object, void (O2::*method) (sig_watcher &))
if (!t->init (argc, argv))
return EXIT_FAILURE;
- iom.loop ();
+ io_manager::loop ();
return EXIT_SUCCESS;
}
printf ("rxvt-unicode daemon listening on %s.\n", sockname);
free (sockname);
- iom.loop ();
+ io_manager::loop ();
return EXIT_SUCCESS;
}
#ifndef RXVT_UTIL_H
#define RXVT_UTIL_H
+#include <cstring>
+
extern class byteorder {
static unsigned int e; // at least 32 bits
public:
template<typename T, typename U>
static inline T max (T a, U b) { return a > b ? a : (T)b; }
-#include "simplevec.h"
+struct zero_initialized {
+ void *operator new (size_t s);
+ void operator delete (void *p, size_t s);
+};
+
+/* simplevec taken (and heavily modified), from:
+ *
+ * MICO --- a free CORBA implementation
+ * Copyright (C) 1997-98 Kay Roemer & Arno Puder
+ */
+template<class T>
+struct simplevec {
+ typedef T* iterator;
+ typedef const T* const_iterator;
+ typedef unsigned long size_type;
+
+private:
+ size_type _last, _size;
+ T *_buf;
+
+public:
+ const_iterator begin () const
+ {
+ return &_buf[0];
+ }
+ iterator begin ()
+ {
+ return &_buf[0];
+ }
+ const_iterator end () const
+ {
+ return &_buf[_last];
+ }
+ iterator end ()
+ {
+ return &_buf[_last];
+ }
+ size_type capacity () const
+ {
+ return _size;
+ }
+ size_type size () const
+ {
+ return _last;
+ }
+
+private:
+ static T *alloc (size_type n)
+ {
+ return (T *)::operator new ((size_t) (n * sizeof (T)));
+ }
+ static void dealloc (T *buf)
+ {
+ if (buf)
+ ::operator delete (buf);
+ }
+
+ void reserve (iterator where, size_type n)
+ {
+ if (_last + n <= _size) {
+ memmove (where+n, where, (end ()-where)*sizeof (T));
+ } else {
+ size_type sz = _last+n;
+ sz = (_size == 0) ? max (sz, 5) : max (sz, 2*_size);
+ T *nbuf = alloc (sz);
+ if (_buf) {
+ memcpy (nbuf, begin (), (where-begin ())*sizeof (T));
+ memcpy (nbuf + (where-begin ()) + n, where,
+ (end ()-where)*sizeof (T));
+ dealloc (_buf);
+ }
+ _buf = nbuf;
+ _size = sz;
+ }
+ }
+
+public:
+ void reserve (size_type sz)
+ {
+ if (_size < sz) {
+ sz = (_size == 0) ? max (sz, 5) : max (sz, 2*_size);
+ T *nbuf = alloc (sz);
+ if (_buf) {
+ memcpy (nbuf, begin (), size ()*sizeof (T));
+ dealloc (_buf);
+ }
+ _buf = nbuf;
+ _size = sz;
+ }
+ }
+ simplevec ()
+ : _last(0), _size(0), _buf(0)
+ {
+ }
+ simplevec (size_type n, const T& t = T ())
+ : _last(0), _size(0), _buf(0)
+ {
+ insert (begin (), n, t);
+ }
+ simplevec (const_iterator first, const_iterator last)
+ : _last(0), _size(0), _buf(0)
+ {
+ insert (begin (), first, last);
+ }
+ simplevec (const simplevec<T> &v)
+ : _last(0), _size(0), _buf(0)
+ {
+ reserve (v._last);
+ memcpy (_buf, v.begin (), v.size ()*sizeof (T));
+ _last = v._last;
+ }
+ simplevec<T> &operator= (const simplevec<T> &v)
+ {
+ if (this != &v) {
+ _last = 0;
+ reserve (v._last);
+ memcpy (_buf, v.begin (), v.size ()*sizeof (T));
+ _last = v._last;
+ }
+ return *this;
+ }
+ ~simplevec ()
+ {
+ dealloc (_buf);
+ }
+ const T &front () const
+ {
+ //ministl_assert (size () > 0);
+ return _buf[0];
+ }
+ T &front ()
+ {
+ //ministl_assert (size () > 0);
+ return _buf[0];
+ }
+ const T &back () const
+ {
+ //ministl_assert (size () > 0);
+ return _buf[_last-1];
+ }
+ T &back ()
+ {
+ //ministl_assert (size () > 0);
+ return _buf[_last-1];
+ }
+ bool empty () const
+ {
+ return _last == 0;
+ }
+ void clear ()
+ {
+ _last = 0;
+ }
+ void push_back (const T &t)
+ {
+ reserve (_last+1);
+ *end () = t;
+ ++_last;
+ }
+ void push_back (T &t)
+ {
+ reserve (_last+1);
+ *end () = t;
+ ++_last;
+ }
+ void pop_back ()
+ {
+ //ministl_assert (size () > 0);
+ --_last;
+ }
+ const T &operator[] (size_type idx) const
+ {
+ //ministl_assert (idx < size ());
+ return _buf[idx];
+ }
+ T &operator[] (size_type idx)
+ {
+ //ministl_assert (idx < size ());
+ return _buf[idx];
+ }
+ iterator insert (iterator pos, const T &t)
+ {
+ //ministl_assert (pos <= end ());
+ long at = pos - begin ();
+ reserve (pos, 1);
+ pos = begin ()+at;
+ *pos = t;
+ ++_last;
+ return pos;
+ }
+ iterator insert (iterator pos, const_iterator first, const_iterator last)
+ {
+ //ministl_assert (pos <= end ());
+ long n = last - first;
+ long at = pos - begin ();
+ if (n > 0) {
+ reserve (pos, n);
+ pos = begin ()+at;
+ memcpy (pos, first, (last-first)*sizeof (T));
+ _last += n;
+ }
+ return pos;
+ }
+ iterator insert (iterator pos, size_type n, const T &t)
+ {
+ //ministl_assert (pos <= end ());
+ long at = pos - begin ();
+ if (n > 0) {
+ reserve (pos, n);
+ pos = begin ()+at;
+ for (int i = 0; i < n; ++i)
+ pos[i] = t;
+ _last += n;
+ }
+ return pos;
+ }
+ void erase (iterator first, iterator last)
+ {
+ if (last != first) {
+ memmove (first, last, (end ()-last)*sizeof (T));
+ _last -= last - first;
+ }
+ }
+ void erase (iterator pos)
+ {
+ if (pos != end ()) {
+ memmove (pos, pos+1, (end ()- (pos+1))*sizeof (T));
+ --_last;
+ }
+ }
+};
+
+template<class T>
+bool operator== (const simplevec<T> &v1, const simplevec<T> &v2)
+{
+ if (v1.size () != v2.size ())
+ return false;
+ return !v1.size () || !memcmp (&v1[0], &v2[0], v1.size ()*sizeof (T));
+}
+
+template<class T>
+bool operator< (const simplevec<T> &v1, const simplevec<T> &v2)
+{
+ unsigned long minlast = min (v1.size (), v2.size ());
+ for (unsigned long i = 0; i < minlast; ++i) {
+ if (v1[i] < v2[i])
+ return true;
+ if (v2[i] < v1[i])
+ return false;
+ }
+ return v1.size () < v2.size ();
+}
+
template<typename T>
struct vector : simplevec<T>
}
};
-struct zero_initialized {
- void *operator new (size_t s);
- void operator delete (void *p, size_t s);
-};
-
#endif
+++ /dev/null
-// -*- c++ -*-
-/*
- * MICO --- a free CORBA implementation
- * Copyright (C) 1997-98 Kay Roemer & Arno Puder
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send comments and/or bug reports to:
- * mico@informatik.uni-frankfurt.de
- */
-
-#ifndef __ministl_simplevec_h__
-#define __ministl_simplevec_h__
-
-#include <cstring>
-
-template<class T>
-class simplevec {
-public:
- typedef T* iterator;
- typedef const T* const_iterator;
- typedef unsigned long size_type;
-private:
- size_type _last, _size;
- T *_buf;
-
-public:
- const_iterator begin () const
- {
- return &_buf[0];
- }
- iterator begin ()
- {
- return &_buf[0];
- }
- const_iterator end () const
- {
- return &_buf[_last];
- }
- iterator end ()
- {
- return &_buf[_last];
- }
- size_type capacity () const
- {
- return _size;
- }
- size_type size () const
- {
- return _last;
- }
-
-private:
- static T *alloc (size_type n)
- {
- return (T *)::operator new ((size_t) (n * sizeof (T)));
- }
- static void dealloc (T *buf)
- {
- if (buf)
- ::operator delete (buf);
- }
-
- void reserve (iterator where, size_type n)
- {
- if (_last + n <= _size) {
- memmove (where+n, where, (end ()-where)*sizeof (T));
- } else {
- size_type sz = _last+n;
- sz = (_size == 0) ? max (sz, 5) : max (sz, 2*_size);
- T *nbuf = alloc (sz);
- if (_buf) {
- memcpy (nbuf, begin (), (where-begin ())*sizeof (T));
- memcpy (nbuf + (where-begin ()) + n, where,
- (end ()-where)*sizeof (T));
- dealloc (_buf);
- }
- _buf = nbuf;
- _size = sz;
- }
- }
-public:
- void reserve (size_type sz)
- {
- if (_size < sz) {
- sz = (_size == 0) ? max (sz, 5) : max (sz, 2*_size);
- T *nbuf = alloc (sz);
- if (_buf) {
- memcpy (nbuf, begin (), size ()*sizeof (T));
- dealloc (_buf);
- }
- _buf = nbuf;
- _size = sz;
- }
- }
- simplevec ()
- : _last (0), _size (0), _buf (0)
- {
- }
- simplevec (size_type n, const T& t = T ())
- : _last (0), _size (0), _buf (0)
- {
- insert (begin (), n, t);
- }
- simplevec (const_iterator first, const_iterator last)
- : _last (0), _size (0), _buf (0)
- {
- insert (begin (), first, last);
- }
- simplevec (const simplevec<T> &v)
- : _last (0), _size (0), _buf (0)
- {
- reserve (v._last);
- memcpy (_buf, v.begin (), v.size ()*sizeof (T));
- _last = v._last;
- }
- simplevec<T> &operator= (const simplevec<T> &v)
- {
- if (this != &v) {
- _last = 0;
- reserve (v._last);
- memcpy (_buf, v.begin (), v.size ()*sizeof (T));
- _last = v._last;
- }
- return *this;
- }
- ~simplevec ()
- {
- dealloc (_buf);
- }
- const T &front () const
- {
- //ministl_assert (size () > 0);
- return _buf[0];
- }
- T &front ()
- {
- //ministl_assert (size () > 0);
- return _buf[0];
- }
- const T &back () const
- {
- //ministl_assert (size () > 0);
- return _buf[_last-1];
- }
- T &back ()
- {
- //ministl_assert (size () > 0);
- return _buf[_last-1];
- }
- bool empty () const
- {
- return _last == 0;
- }
- void clear ()
- {
- _last = 0;
- }
- void push_back (const T &t)
- {
- reserve (_last+1);
- *end () = t;
- ++_last;
- }
- void push_back (T &t)
- {
- reserve (_last+1);
- *end () = t;
- ++_last;
- }
- void pop_back ()
- {
- //ministl_assert (size () > 0);
- --_last;
- }
- const T &operator[] (size_type idx) const
- {
- //ministl_assert (idx < size ());
- return _buf[idx];
- }
- T &operator[] (size_type idx)
- {
- //ministl_assert (idx < size ());
- return _buf[idx];
- }
- iterator insert (iterator pos, const T &t)
- {
- //ministl_assert (pos <= end ());
- long at = pos - begin ();
- reserve (pos, 1);
- pos = begin ()+at;
- *pos = t;
- ++_last;
- return pos;
- }
- iterator insert (iterator pos, const_iterator first, const_iterator last)
- {
- //ministl_assert (pos <= end ());
- long n = last - first;
- long at = pos - begin ();
- if (n > 0) {
- reserve (pos, n);
- pos = begin ()+at;
- memcpy (pos, first, (last-first)*sizeof (T));
- _last += n;
- }
- return pos;
- }
- iterator insert (iterator pos, size_type n, const T &t)
- {
- //ministl_assert (pos <= end ());
- long at = pos - begin ();
- if (n > 0) {
- reserve (pos, n);
- pos = begin ()+at;
- for (int i = 0; i < n; ++i)
- pos[i] = t;
- _last += n;
- }
- return pos;
- }
- void erase (iterator first, iterator last)
- {
- if (last != first) {
- memmove (first, last, (end ()-last)*sizeof (T));
- _last -= last - first;
- }
- }
- void erase (iterator pos)
- {
- if (pos != end ()) {
- memmove (pos, pos+1, (end ()- (pos+1))*sizeof (T));
- --_last;
- }
- }
-};
-
-template<class T>
-bool operator== (const simplevec<T> &v1, const simplevec<T> &v2)
-{
- if (v1.size () != v2.size ())
- return false;
- return !v1.size () || !memcmp (&v1[0], &v2[0], v1.size ()*sizeof (T));
-}
-
-template<class T>
-bool operator< (const simplevec<T> &v1, const simplevec<T> &v2)
-{
- unsigned long minlast = min (v1.size (), v2.size ());
- for (unsigned long i = 0; i < minlast; ++i) {
- if (v1[i] < v2[i])
- return true;
- if (v2[i] < v1[i])
- return false;
- }
- return v1.size () < v2.size ();
-}
-
-#endif
-