/////////////////////////////////////////////////////////////////////////////
// Copyright 2004 NVIDIA Corporation.  All Rights Reserved.
// 
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// 
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA nor the names of its contributors
//   may be used to endorse or promote products derived from this software
//   without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// (This is the Modified BSD License)
/////////////////////////////////////////////////////////////////////////////

// Note: heavily edited for the XRT project

#ifndef __TYPE_H__
#define __TYPE_H__

#include <string>

#include "public.h"

#undef VOID
#undef FLOAT
#undef COLOR
#undef STRING
#undef CHAR
#undef BOOLEAN

namespace xrt
{
	// Base data types
	enum BaseType
	{
		UNKNOWN = 0,
		VOID,
		STRING,
		FLOAT,
		HALF,
		DOUBLE,
		POINT,
		VECTOR,
		NORMAL,
		COLOR,
		HPOINT,
		MATRIX,
		CHAR,
		UNSIGNED_CHAR,
		SHORT,
		UNSIGNED_SHORT,
		INTEGER,
		UNSIGNED_INTEGER,
		BOOLEAN,
		LAST
	};

	// Return the name, for printing and whatnot, of a BaseType
	PUBLIC const char *BaseTypeName (int t);

	// Return the size, in bytes, of a single item of a BaseType
	PUBLIC int BaseTypeSize (int t);

	// Return the number of floats comprising a BaseType
	// (e.g., 3 for POINT).  Return 0 for all types not comprised of floats.
	PUBLIC int  BaseTypeNFloats (int t);

	// Interpolation types
	enum Interpolation
	{
		CONSTANT = 0,       // Constant for all pieces/faces
		PERPIECE = 1,       // Piecewise constant per piece/face ( = RSL uniform )
		LINEAR = 2,         // Linearly interpolated across each piece/face ( = RSL varying/facevarying )
		VERTEX = 3          // Interpolated like vertices
	};

	enum Permissions
	{
		NONE = 0x0,
		READ =  0x1,
		WRITE = 0x2,
		RW	= 0x3
	};

	// Type is a simple type descriptor.  Contains a base type, array
	// length, and other attributes.  This structure is no bigger than an
	// int, and so can be very cheaply passed around.
	class PUBLIC Type
	{
	public:
		Type ( void ) { /* Uninitialized! */ }

		Type ( Permissions permissions, BaseType type, unsigned int array = 1, 
			Interpolation interpolation = CONSTANT )
			: permissions( permissions ), base( type ), interpolation( interpolation )
		{
			arrayLength = array;
			reserved = 0;
		}
    // Construct from base type and interp, or base only (assume non-array)
		Type ( BaseType type, Interpolation interpolation = CONSTANT ) 
			: permissions( NONE ), arrayLength( 1 ), base( type ), interpolation( interpolation )
		{
			reserved = 0;
		}
		// Construct from base type,interpolation and length, or base only ( assume non-array )
		Type ( BaseType type, unsigned int array, Interpolation interpolation = CONSTANT )
			: permissions( NONE ), base( type ), interpolation( interpolation )
		{
			arrayLength = array;
			reserved = 0;
		}

		// Construct from a string (e.g., "vertex float[3]").  If no valid
		// type could be assembled, set base type to UNKNOWN.
		Type ( const char *typeString ) 
		{
			if ( !fromString( typeString ) )
				base = UNKNOWN;
			permissions = NONE;
		}

		// Set this to the type described in the string.  Return the
		// length of the part of the string that describes the type.  If
		// no valid type could be assembled, return 0 and do not modify
		// *this.  If name is not NULL, store the word(s) in the string
		// after the type ( presumably the variable name ) in name.
		int fromString ( const char *typeString, char **name = NULL );

		// Store the string representation of the type in typestring.  Don't
		// overwrite more than maxlen bytes of typestring!  Return true upon
		// success, false upon failure (including failure to fit).
		std::string toString () const;

		// Return size of one element of this type, in bytes
		unsigned int size() const { return arrayLength * BaseTypeSize( base ); }
		unsigned int nFloats() const { return arrayLength * BaseTypeNFloats( base ); }

		// Demote the type to a non-array
		void unarray (void) { arrayLength = 1; }

		friend bool operator== ( Type a, Type b ) {return a.field == b.field; }
		friend bool operator!= ( Type a, Type b ) {return a.field != b.field; }
		bool match( Type, bool = false );
		bool isArray() const { return arrayLength != 1; }
		bool isResizable() const { return arrayLength == 0; }


		union
		{
			unsigned int field;
			struct
			{
				unsigned int base:5;			// Base type of the data -- one of BaseType
				unsigned int arrayLength:22;	// Array length (up to 4M), or 1 if not an array
				unsigned int interpolation:2;	// Sometimes used: interpolation type
				unsigned int permissions:2;		// read/write
				unsigned int reserved:1;		// Future expansion
			};
		};
	private:
	};
}
#endif //__TYPE_H__
