#ifndef TEMPBUF_H
#define TEMPBUF_H
#pragma interface
/*#pragma once*/
// A TempBuf is a buffer that grows as needed.
// The initial allocation is TEMP_SHORT_BUF, and is on the stack.
// If that isn't enough, more is allocated on the heap when needed.
// Everthing is deleted on scope exit (by TempBuf's destructor).
// Use the copy() method if you need a permanent copy.

#define TEMP_SHORT_BUF 32

extern "C" void free(void*);

#if 0
template<class T> class TTempBuf {
  public:
    T _short_buf[16];
    T * _base;
    T *_ptr;
    T *_lim;
    int size() const { return _ptr - _base; }
    // set_size: Change size to 'new_size'. If this is an increase,
    // and 'fill >= 0', then use 'fill' to set the new characters.
    void set_size(int new_size, int fill = -1);
    T *string() { return _base; }
    T *copy(int add_nul = 1) const; 
    TTempBuf() { _base = _short_buf; _ptr = _base; _lim = _base+TEMP_SHORT_BUF;}
    void extend(int needed);
    void put(T ch) { if (_ptr == _lim) extend(1); *_ptr++ = ch; }
    ~TTempBuf() { if (_base != _short_buf) free(_base); }
};
#endif
struct TTempBuf {
    char _short_buf[TEMP_SHORT_BUF];
    char *_base;
    char *_ptr;
    char *_lim;
    int size() const { return _ptr - _base; }
    void extend(int needed); // 'needed' is in bytes.
    char *copy(int add_nul = 1) const; 
};

#if 0
class TempBufbuf : public strstreambuf {
  TempBuf *tbuf;
  int index;
  TempBufbuf(TempBuf*tb) { tbuf = bf; index = 0; }
  int overflow(int ch = EOF);
};
int TempBufbuf:overflow(int ch)
{
  if (ch == EOF)
    return 0;
  if (index >=  _lim-_base) {
    index = _lim - _base;
    extend(1);
  }
  _base[index++] = ch;
  return ch;
}
#endif

class TempBuf : public TTempBuf {
  public:
    // set_size: Change size to 'new_size'. If this is an increase,
    // and 'fill >= 0', then use 'fill' to set the new characters.
    void set_size(int new_size, int fill = -1);
    char *string() { return _base; }
    TempBuf() { _base = _short_buf; _ptr = _base; _lim = _base+TEMP_SHORT_BUF;}
    void put(char ch) { if (_ptr == _lim) extend(1); *_ptr++ = ch; }
//    ~TempBuf() { if (_base != _short_buf) free(_base); }
};

// This is a TempBuf customized for (void*)objects.

class TempPtrBuf : public TempBuf {
  public:
    int count() { return (void**)_ptr - (void**)_base; }
    void putp(const void *ptr) {
	if (_ptr + sizeof(void*) > _lim) extend(sizeof(void*));
	*((const void**)_ptr)++ = ptr;
    }
    void **base() { return (void**)_base; }
};
#endif /*!TEMPBUF_H*/
