// Extendible reusable string buffer -*- c++ -*-

#ifndef STRINGBUFFER_H_
# define STRINGBUFFER_H_
# ifdef __GNUC__
#  pragma interface
# endif // __GNUC__

/** @file StringBuffer.h
 * Extendible reusable string buffer
 */

/* Copyright © 1999-2001 Marko Mäkelä (msmakela@tcs.hut.fi).

   This file is part of MARIA, a reachability analyzer and model checker
   for high-level Petri nets.

   MARIA is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   MARIA 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
   General Public License for more details.

   The GNU General Public License is often shipped with GNU software, and
   is generally kept in a file called COPYING or LICENSE.  If you do not
   have a copy of the license, write to the Free Software Foundation,
   59 Temple Place, Suite 330, Boston, MA 02111 USA. */

/** Extendible reusable string buffer */
class StringBuffer
{
public:
  /** Constructor */
  StringBuffer ();
  /** Copy constructor */
  StringBuffer (const class StringBuffer& old);
  /** Assignment operator */
  class StringBuffer& operator= (const class StringBuffer& old);
  /** Destructor */
  ~StringBuffer ();

  /** Create a copy of the string */
  char* copy () const;
  /** Get current string length */
  unsigned getLength () const { return myLength; }
  /** Get maximum string length */
  unsigned getMaxLength () const { return myMaxLength; }
  /** Get the string buffer */
  const char* getString () const { return myString; }
  /** Assignment operator
   * @param string	NUL-terminated string to be assigned
   */
  class StringBuffer& operator= (const char* string);

  /**
   * Guarantee that getMaxLength () <= length and clear the string.
   * @param length	length of string requested
   * @return		pointer to string buffer (relocated when necessary)
   */
  char* create (unsigned length);

  /**
   * Guarantee that getMaxLength () - getLength () <= length
   * and set myLength += length.
   * @param length	amount of additional space requested
   * @return		pointer to string buffer (relocated when necessary)
   */
  char* extend (unsigned length);

  /**
   * Append a NUL-terminated string to the buffer.
   * @param string	string to be appended
   */
  void append (const char* string);

  /**
   * Append a string buffer
   * @param buf		string to be appended
   */
  void append (const class StringBuffer& buf);

  /**
   * Append an unsigned number to the buffer.
   * @param num		number to be appended
   */
  void append (unsigned num);

  /**
   * Append a signed number to the buffer.
   * @param num		number to be appended
   */
  void append (signed num);

  /**
   * Append a number of a character to the buffer
   * @param c		character to be appended
   * @param num		number of characters to append
   */
  void append (char c, unsigned num);

  /**
   * Append indentation spaces to the buffer.
   * @param num		indentation level
   */
  void indent (unsigned num) {
    append (' ', num);
  }

  /**
   * Append a number of opening parentheses to the buffer.
   * @param num		number of parentheses to add
   */
  void openParen (unsigned num) {
    append ('(', num);
  }

  /**
   * Append a number of closing parentheses to the buffer.
   * @param num		number of parentheses to add
   */
  void closeParen (unsigned num) {
    append (')', num);
  }

  /**
   * Remove a number of characters from the buffer.
   * @param num		number of characters to remove
   */
  void chop (unsigned num) {
    myString[myLength -= num] = 0;
  }

  /**
   * Translate all characters in the buffer except [0-9A-Za-z_] to
   * an underscore followed by a two-digit hexadecimal code.
   * @param offset	offset from which to start escaping
   */
  void escape (unsigned offset = 0);

private:
  /** The string buffer */
  char* myString;
  /** Current string length, excluding the terminating NULL character */
  unsigned myLength;
  /** Maximum string length, excluding the terminating NULL character */
  unsigned myMaxLength;
};

#endif // STRINGBUFFER_H_
