/////////////////////////////////////////////////////////////////////////////
// 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: this file is lifted from the public interfaces of the Gelato renderer.
// It has been heavily edited for the XRT project.

// There is a TypeDesc struct in the OpenImageIO project that serves a similar 
// purpose but this one is more compact and also more suited to the needs of this 
// renderer

#ifndef PARAMTYPE_H
#define PARAMTYPE_H

#ifndef NULL
#define NULL 0
#endif

#undef VOID

#include "public.h"

namespace xrt {

// Base data types
enum BaseType {
	UNKNOWN = 0,
	VOID,
	STRING,
	FLOAT, HALF, DOUBLE,
	POINT, VECTOR, NORMAL,
	COLOR,
	HPOINT, MATRIX,
	INT8, UINT8, INT16, UINT16, INT, UINT,
	LAST
};
// Interpolation types
enum Interpolation {
	CONSTANT = 0,       // Constant for all pieces/faces
	PERPIECE = 1,       // Piecewise constant per piece/face
	LINEAR = 2,         // Linearly interpolated across each piece/face
	VERTEX = 3          // Interpolated like vertices
};

// ParamType 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 ParamType {
public:
    ParamType (void) { /* Uninitialized! */ }

    // Construct from base type and interp, or base only (assume non-array)
    ParamType (BaseType base, Interpolation detail=CONSTANT) {
        basetype = base;
        arraylen = 1;
        interpolation = detail;
        reserved = 0;
    }

    // Construct with array length
    ParamType (BaseType base, unsigned int array,
               Interpolation det=CONSTANT) {
        basetype = base;
        arraylen = array;
        interpolation = det;
        reserved = 0;
    }

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

    // 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 shortname is not NULL, store the word(s) in the string
    // after the type (presumably the variable name) in shortname.
    int fromString (const char *typestring, const char **shortname=NULL);

    /// Return the name, for printing and whatnot.  For example,
    /// "float", "int[5]", "normal"
    const char *c_str() const;

    // Return size of one element of this type, in bytes
    int datasize (void) const { return arraylen*BaseTypeSize(basetype); }

    int nfloats (void) const { return arraylen*BaseTypeNFloats(basetype); }

	bool operator== (const ParamType &t) {
        return bitfield == t.bitfield;
    } 

	bool operator!= (const ParamType &t) {
        return bitfield != t.bitfield;
    } 

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

	bool isarray (void) const { return arraylen != 1; }
	bool isResizable (void) const { return arraylen == 0; }

	union
	{
		unsigned int bitfield;
		struct
		{
			unsigned int basetype:5;      // Base type of the data -- one of BaseType
			unsigned int arraylen:22;     // Array len (up to 4M), or 1 if not an array
			unsigned int interpolation:2; // Sometimes used: interpolation type
			unsigned int reserved:3;      // Future expansion
		};
	};

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

	// Return the size, in bytes, of a single item of a BaseType
	static 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.
	static int BaseTypeNFloats (int t);
};


}; /* end namespace xrt */

#endif /* !defined(PARAMTYPE_H) */
