// This may look like C code, but it is really -*- C++ -*-
// 
// <copyright> 
//  
//  Copyright (c) 1995
//  Institute for Information Processing and Computer Supported New Media (IICM), 
//  Graz University of Technology, Austria. 
//  
// </copyright> 
// 
// 
// <file> 
// 
// Name:        buffer.h
// 
// Purpose:     
// 
// Created:     27 Nov 95   Joerg Faschingbauer
// 
// Modified:    
// 
// Description: 
// 
// 
// </file> 
#ifndef hg_utils_buffer_h
#define hg_utils_buffer_h

#include "smartptr.h"
#include "types.h"

class RString ;

class OBuffer : public RefCounted {
public:
   OBuffer (int size=0) ; // preallocate size bytes 
   ~OBuffer() ;

   // STATE INQUIRY
   bool ok() const { return count_>0; }
   bool operator !() const { return !ok(); }
   operator void*() const { return (void*)ok(); }

   // pointer to the internal buffer and its length (as written by the
   // user)
   const char* data() const { return data_; }
   int count() const { return count_; }
   // total number of bytes allocated
   int size() const { return size_; }


   // ADDING TO THE BUFFER
   // (these operations logarithmically grow the internal buffer on demand)

   // append 1 char
   OBuffer& write (char c) ;
   // append n characters (memcpy())
   OBuffer& write (const char*, int) ;
    // same as write (char)
   OBuffer& write (const char*) ;
   OBuffer& operator << (char c) { return write(c); }
   // append a null terminated string (strlen(), followed by memcpy())
   OBuffer& operator << (const char*) ;
   // same as write (const char*, int)
   OBuffer& operator << (const RString&) ;

   // overwrite the content starting at pos with the given buffer
   OBuffer& fixup (int pos, const char*, int) ;
   
   // MANIPULATING THE INTERNAL BUFFER

   // get a pointer to the internal buffer. it is the user's
   // responsibility to delete it (delete[]! not free()!). the
   // object's state is as if you had constructed by default. NOTE
   // that if you want to know the buffer's count and size, you should
   // inquire them before freeze() since they are zero afterwards.
   char* freeze() ;
   // same as above (zeroing the buffer), except that the buffer is
   // freed.
   void free() ;

   // keep the internal buffer of size() bytes (as grown up to this
   // point), and reset count() to zero).
   void reset() { count_ = 0; }

   // free() the old buffer, if any, and make the data my own. if size
   // is not given, or size is less than count, the buffer is assumed
   // to have count bytes.
   void init (int count, char* data, int size=0) ;
   
private:
   void enlarge_(int) ;
   void do_enlarge_(int) ;

private:
   char* data_ ;
   int size_ ;
   int count_ ;

private:
   OBuffer (const OBuffer&) {}
   OBuffer& operator = (const OBuffer&) { return *this; }

public:
   static const char* version5 ;
} ;
static const char* dc_common_obuffer_version = OBuffer::version5 ;

inline void OBuffer :: enlarge_(int amount) {
   if (count_ + amount > size_)
      do_enlarge_(amount) ;
}
inline OBuffer& OBuffer :: write (const char* it) {
    return operator << (it) ;
    
}

SmartPtrdeclare (OBufferPtr, OBuffer) ;


#endif
