/**
 * @file
 * $Id$
 * $Revision$
 * $Author$
 * $Date$
 *
 * This file is part of The iWear Framework.
 *
 * The iWear Framework 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 as in version 2 of the License.

 * 
 * The iWear Framework 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.
 * 
 * You should have received a copy of the GNU General Public License along with
 * The iWear Framework; if not, write to the Free Software Foundation, Inc., 59
 * Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef __IWREMOTE_TYPE_H
#define __IWREMOTE_TYPE_H

#include <string>


namespace iwear
{
    namespace net
    {
/**
 * denotes a type specifier, so the one that might be before a variable or
 * function argument declaration
 */
struct Type
{
    /**
     * the identifier, like uint32_t or string or a user type
     */
  string id;

    /**
     * If this is a reference type, which in fact is a reference to an
     * associated object, so as a parameter its a uid on remote passing
     */
  bool reference;

PH2  bool is_enum;
    /**
     * returns true if its a builtin pod type (with RPCStream primitives)
     */
  bool builtin( void ) const;

    /**
     * returns the size of the type if available without an actual object.
     * For things like strings, containers and user objects its not available
     * without an actual object.
     */
  virtual string get_static_size( void ) const;

    /**
     * A non-pod type needs to return the dynamic size of the object, to be
     * determined at runtime, if its not such a type the static size is returned.
     * @param var is the name of the variable to use to get the size from
     */
  virtual string get_dynamic_size( const string& var );

  Type( const string& _id, bool ref )
	: id(_id), reference(ref), is_enum(false) { }

  virtual ~Type() { }

    virtual void print( std::ostream& o ) const;
};

inline std::ostream& operator<<( std::ostream& o, const Type& t )
{
    t.print(o);
    return o;
}
/**
 * we support certain container types like lists, sets etc.
 * This type does not contribute to the crcid, since when iterating through the
 * container, it will come in the same order into the other container, no
 * matter which one it is...
 */
struct ContainerType: public Type
{
    /**
     * the container type, whats allowed is (the parser will have checked it):
     * set, list, vector, queue
     * of course only of supported Types
     */
  string container;

    /**
     * the types of the to-be contained data (might be containers as well)
     */
  list<Type*> ids;

    /**
     * returns an empty string, since we cannot determine the static size of a
     * container, there is nothing such
     */
  virtual string get_static_size( void ) const;
    /**
     * returns the code to determine the static size. The data is added to the
     * variable sz
     * @param var contains the name of the container variable in the program 
     */
  virtual string get_dynamic_size( const string& var );

    /**
     * Expected number of template parameters.
     */
    uint32_t expected;

  ContainerType( const string& cont, Type* _id, const string& did, bool ref, uint32_t ex )
	: Type(did,ref), container(cont), expected(ex) { if(_id) ids.push_back(_id); }

    virtual void print( std::ostream& o ) const;
};

struct TypeDef: public Type
{
    // The type this typedef is typedefed to
    Type* dtype;
    TypeDef( const string& d, Type* t ) : Type(d,false), dtype(t) { }
    virtual void print( std::ostream& o ) const;
};

}
}
#endif
