/***********************************************************************

  Copyright by Telelogic AB 1998

  This Program is owned by Telelogic and is protected by national
  copyright laws and international copyright treaties. Telelogic grants
  you the right to use this Program on one computer or in one local
  computer network at any one time.

  Under this License you may only modify the source code for the purpose
  of adapting it to your environment. You must reproduce and include any
  copyright and trademark notices on all copies of the source code.  You
  may not use, copy, merge, modify or transfer the Program except as
  provided in this License.

  Telelogic does not warrant that the Program will meet your
  requirements or that the operation of the Program will be
  uninterrupted and error free. You are solely responsible that the
  selection of the Program and the modification of the source code will
  achieve your intended results and that the results are actually
  obtained.

************************************************************************/

#ifndef _stlmini_h
#define _stlmini_h

// These classes emulate a tiny subset of the ANSI C++ standard library
// If you have access to a compiler providing an implementation of
// the standard C++ library, you might consider including the
// standard ansi headers instead of this file.

#if defined(__BORLANDC__)
# pragma option -w-inl  // Remove inline warnings
#endif

#if defined (__GNUC__) || defined(__BORLANDC__) || defined _MSC_VER || (defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x500))
#define STANDARD_BOOL
#endif

#if defined(__GNUC__)  || (defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x500))
#define STANDARD_LIBRARY_AVAILABLE 
#define NEW_HEADER_SYNTAX_SUPPORTED
#endif

#if defined(_MSC_VER) 
#define STANDARD_LIBRARY_AVAILABLE // MSVC++ should use STL libs
#define NEW_HEADER_SYNTAX_SUPPORTED
#define STL_DUMMY_RELATIONAL_OPERATORS_NEEDED // Indicates that STL
// implementation is faulty and makes extra (unnecessary) requirements of
// relational operators of container element types
#endif

#ifndef STANDARD_BOOL
#define bool int
#define true 1
#define false 0
#endif

#ifdef STANDARD_LIBRARY_AVAILABLE

# ifdef NEW_HEADER_SYNTAX_SUPPORTED

#  include <string>
#  include <list>
#  include <iostream>
#  include <fstream>
using namespace std;

# else

#  include <string.h>
#  include <list.h>
#  include <iostream.h>
#  include <fstream.h>

# endif // NEW_HEADER_SYNTAX_SUPPORTED

#else

////////////////////////////////////////////////////////////
// Mini STL version

#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <iostream.h>
#include <fstream.h>

// The following is a work-around for the SparWorks C++ compiler.
// The line should read: "static const unsigned npos=-1"

static const unsigned sdt_npos = -1;

class string {
public:
  string() : string_(::strdup("")) {}
  string(const char *s) : string_(::strdup(s)) {}
  string(const char *s, int count)
    {
      char *ptr = new char[count+1];

      strncpy(ptr, s, count);
      ptr[count] = '\0';
      string_ = ptr;
    }
  string(const string &s) : string_(::strdup(s.c_str())) {}
  ~string() { ::free(string_); }

  string &operator= (const string &s)
    {
      free(string_);
      string_ = ::strdup (s.c_str());
      return *this;
    }

  void operator+= (char c)
    {
      int len = size();
      string_ = (char *) ::realloc(string_, len + 2);
      string_[len] = c;
      string_[len + 1] = '\0';
    }
  
  void operator+= (char *s)
    {
      int len = size();
      string_ = (char *) ::realloc(string_, len + ::strlen(s) + 1);
      ::strcat (string_, s);
    }
  
  void operator+= (const string &s)
    {
      int len = size();
      string_ = (char *) ::realloc(string_, len + s.size() + 1);
      ::strcat (string_, s.c_str());
    }
  
  const char *c_str() const               { return string_; }
  unsigned size() const                   { return ::strlen(string_); }
  unsigned length() const                   { return ::strlen(string_); }
  char operator[] (unsigned i) const      { return string_[i]; }
  bool empty()
    {
      bool status;

      if (!string_)
	return true;
      
      if (!::strlen(string_))
	return true;

      return false;
    }

  unsigned find(const char *s) const
    {
      char *ptr = ::strstr(string_, s);
      
      return ptr ? ptr - string_ : sdt_npos;
    }
  
  friend ostream &operator<<(ostream &os, const string &s)
    { os << s.c_str(); return os; }
  friend bool operator== (const string &s1, const string &s2)
    { return ::strcmp(s1.string_, s2.string_) == 0; }  
  friend bool operator!= (const string &s1, const string &s2)
    { return ::strcmp(s1.string_, s2.string_) != 0; }
  
  
private:
  char *string_;
};

inline string
operator+ (const char *lhs, const string &rhs)
{
  string str (lhs);
  str += rhs;
  return str;
}

inline string
operator+ (const string &lhs, const char *rhs)
{
  string str (lhs);
  str += rhs;
  return str;
}

inline string
operator+ (const string &lhs, const string &rhs)
{
  string str (lhs);
  str += rhs;
  return str;
}

template <class T>
class list {
public:
  struct list_node {
    list_node *next;
    list_node *prev;
    T data;
  };

  typedef T &reference;
  
public:
  class const_iterator {
    friend class list<T>;
  protected:
    list_node *node;
    const_iterator (list_node *x) : node(x) {}
  public:
    const_iterator () {}
    bool operator== (const const_iterator& x) const     { return node == x.node; }
    bool operator!= (const const_iterator& x) const     { return node != x.node; }
    const reference operator* () const                  { return (*node).data; }
    const_iterator& operator++ ()
      { node = (list_node *)((*node).next); return *this; }
    const_iterator operator++ (int)
      { const_iterator tmp = *this; ++*this; return tmp; }
    const_iterator& operator-- ()
      { node = (list_node *)((*node).prev); return *this; }
    const_iterator operator-- (int)
      { const_iterator tmp = *this; --*this; return tmp; }
  };

  class iterator : public const_iterator {
    friend class list<T>;
  protected:
    list_node *node;
    iterator (list_node *x) : node(x) {}
  public:
    iterator () {}
    bool operator== (const iterator& x) const     { return node == x.node; }
    bool operator!= (const iterator& x) const     { return node != x.node; }
    reference operator* () const                  { return (*node).data; }
    iterator& operator++ ()
      { node = (list_node *)((*node).next); return *this; }
    iterator operator++ (int)
      { iterator tmp = *this; ++*this; return tmp; }
    iterator& operator-- ()
      { node = (list_node *)((*node).prev); return *this; }
    iterator operator-- (int)
      { iterator tmp = *this; --*this; return tmp; }
  };

  // list - 
  list() : length_(0)
    {
      head_.next = head_.prev = &head_;
    }
  list(const list<T> &);
  ~list();
  list<T> &operator+= (const list<T> &l);
  list<T> &operator= (const list<T> &l);

  bool empty() const { return length_ == 0; }
  unsigned size() const { return length_; }

  void erase (iterator position)
    {
      position.node->next->prev = position.node->prev;
      position.node->prev->next = position.node->next;
      delete position.node;
      length_--;
    }
  
  iterator insert (iterator position, const T& t)
    {
      length_++;
      list_node *node = new list_node;
      node->data = t;
      node->prev = position.node->prev;
      node->next = position.node;
      position.node->prev->next = node;
      position.node->prev = node;
      return iterator (node);
    }


  const_iterator begin() const { return const_iterator((list_node *) head_.next); }
  const_iterator end() const   { return const_iterator((list_node *) &head_); }

  iterator begin() { return iterator((list_node *) head_.next); }
  iterator end() { return iterator((list_node *) &head_); }

  void push_front (const T &t) { insert (begin(), t); }
  void push_back (const T &t) { insert (end(), t); }

  reference front() const { return *begin(); }
  reference back() const { return *(--end()); }

  void remove(const T& value);
  
private:
  list_node head_;
  unsigned length_;
};  

template <class T>
inline void list<T>::remove(const T& value) {
  iterator first = begin();
  iterator last = end();
  while (first != last) {
    iterator next = first;
    ++next;
    if (&*first == &value) erase(first);
    first = next;
  }
}

template <class T>
inline list<T>::list(const list<T> &l) : length_(0) {
  head_.next = head_.prev = &head_;
  for (list<T>::const_iterator i = l.begin(); i != l.end(); i++)
    push_back (*i);
}

template <class T>
inline list<T>::~list() {
  while (begin() != end())
    erase (begin());
}

template <class T>
inline list<T> &list<T>::operator+= (const list<T> &l) {
  for (list<T>::const_iterator i = l.begin(); i != l.end(); i++)
    push_back (*i);
  return *this;
}  

template <class T>
inline list<T> &list<T>::operator= (const list<T> &l) {
  while (begin() != end())
    erase (begin());
  for (list<T>::const_iterator i = l.begin(); i != l.end(); i++)
    push_back (*i);
  return *this;
}  

#endif 

#endif // _stlmini_h
