#ifndef BABBLEMUD_UTILS_H
#define BABBLEMUD_UTILS_H

#include <string>
#include <iostream>
#include <sstream>
#include <algorithm>



// Some convenient typedefs
//   -dhaley aug-15-04
typedef unsigned long ulong;
typedef unsigned char byte;
typedef unsigned int uint;

#ifdef WIN32
typedef __int64 int64;
typedef unsigned __int64 uint64;
#else
typedef long long int64;
typedef unsigned long long uint64;
#endif

// make a string on-the-fly
#define MAKE_STRING(msg) \
   (((ostringstream&) (ostringstream() << boolalpha << msg)).str())

#define NUMITEMS(arg) (sizeof (arg) / sizeof (arg [0]))

// see Josuttis p12 and Meyers p38
struct DeleteObject
  {
  template <typename T>
  void operator() (const T* ptr) const { delete ptr; };
  };
// similar concept for maps
struct DeleteMapObject
  {
  template <typename T>
  void operator() (const T item) const { delete item.second; };
  };

// see Josuttis p 118
// prints items in a collection with an optional leading string
// and optional leading/trailing strings for each element
template <class T>
inline void PRINT_ELEMENTS (const T& coll, 
                            const char* optcstr="",
                            const char* predelim="",
                            const char* postdelim=" ")
  {
  typename T::const_iterator pos;

  cout << optcstr;
  for (pos = coll.begin (); pos != coll.end (); ++pos)
    cout << predelim << *pos << postdelim;
  cout << endl;
  } // end of PRINT_ELEMENTS

template <class T>
inline void PRINT_MAP_ELEMENTS (const T& coll, 
                            const char* optcstr="",
                            const char* prekeydelim="",
                            const char* postkeydelim="=",
                            const char* predatadelim="",
                            const char* postdatadelim=" "
                            )
  {
  typename T::const_iterator pos;

  cout << optcstr;
  for (pos = coll.begin (); pos != coll.end (); ++pos)
    cout << prekeydelim << pos->first << postkeydelim <<
            predatadelim << pos->second << postdatadelim;

  cout << endl;
  } // end of PRINT_MAP_ELEMENTS

// safe_for_each.  Apply a function to every element of a range.
// should handle correctly an element deleting itself 
// See Josuttis p 205.

template <class ITER, class F> inline
F safe_for_each (ITER first, ITER last, F func) 
  {
  while (first != last)
    func (*first++);
  return func;
  }

// for_each_noreturn. Apply a function without returning it.
// This resolves the problem of the extra copy constructor which
// under some circumstances doesn't work perfectly.
// we do it this way so we use ++iter and not iter++ (for speed)

template <class ITER, class F> inline
void for_each_noreturn (ITER first, ITER last, F func) 
  {
  for ( ; first != last ; ++first) 
    func (*first);
  }

// my function to get the n'th element in a container
// (starting at zero)
template <class ITER> inline
ITER get_n (ITER first, ITER last, int count)
  {
  for ( ; count > 0 && first != last ; ++first)
    --count;
  if (count == 0) // in case negative, for example
    return first;
  else 
    return last;
  }

// ISEQ - iterator sequence - replaces container.begin (), container.end ()
// see Stroustrup p513
// honestly, I think this is a mess, because you need to specialise
// every routine (eg. for_each, find, find_it, generate etc. etc.)
  
// A define is clearer here. :)
  
#define ISEQ(container) (container).begin (), (container).end ()

// converts generic data (eg. int, float)
template <typename T>
const T convertString (const string & s, const string & errormessage)
{
T result;
istringstream is (s);

  is >> ws >> result >> ws;
  if (is.fail () || !is.eof ())
    throw runtime_error (MAKE_STRING (errormessage << "'" << s << "'"));
        
return result;
}

#endif // BABBLEMUD_UTILS_H
