<commit_before>/*
** Copyright 1993 by Miron Livny, and Mike Litzkow
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted,
** provided that the above copyright notice appear in all copies and that
** both that copyright notice and this permission notice appear in
** supporting documentation, and that the names of the University of
** Wisconsin and the copyright holders not be used in advertising or
** publicity pertaining to distribution of the software without specific,
** written prior permission.  The University of Wisconsin and the
** copyright holders make no representations about the suitability of this
** software for any purpose.  It is provided "as is" without express
** or implied warranty.
**
** THE UNIVERSITY OF WISCONSIN AND THE COPYRIGHT HOLDERS DISCLAIM ALL
** WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE UNIVERSITY OF
** WISCONSIN OR THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT
** OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
** OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
** OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
** OR PERFORMANCE OF THIS SOFTWARE.
**
** Author:  Mike Litzkow
**
*/

#define _POSIX_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>
#include "types.h"
#include "util_lib_proto.h"
#include "proc_obj.h"
#include "filter.h"
#include "alloc.h"

static char *_FileName_ = __FILE__;		/* Used by EXCEPT (see except.h)     */

DBM		*Q;

char	*param();
char	*MyName;
char	*Spool;

int		PrioAdjustment;
int		NewPriority;
int		PrioritySet;
int		AdjustmentSet;
ProcFilter	*PFilter = new ProcFilter();
int		InvokingUid;		// user id of person ivoking this program
char	*InvokingUserName;	// user name of person ivoking this program

const int MIN_PRIO = -20;
const int MAX_PRIO = 20;
const int MATCH = 0;

	// Prototypes of local interest only
void usage();
int compute_adj( char * );
void init_params();
void do_it( ProcObj * );
int calc_prio( int old_prio );
void init_user_credentials();

	// Tell folks how to use this program
void
usage()
{
	fprintf( stderr, "Usage: %s [{+|-}priority ] [-p priority] ", MyName );
	fprintf( stderr, "[ -a ] [user | cluster | cluster.proc] ...\n" );
	exit( 1 );
}

int
main( int argc, char *argv[] )
{
	char	queue_name[_POSIX_PATH_MAX];
	char	*arg;
	int		prio_adj;
	List<ProcObj>	*proc_list;
	ProcObj			*p;

	MyName = argv[0];

	config( MyName, (CONTEXT *)0 );
	init_params();

	if( argc < 2 ) {
		usage();
	}

	PrioritySet = 0;
	AdjustmentSet = 0;

	for( argv++; arg = *argv; argv++ ) {
		if( (arg[0] == '-' || arg[0] == '+') && isdigit(arg[1]) ) {
			PrioAdjustment = compute_adj(arg);
			AdjustmentSet = TRUE;
		} else if( arg[0] == '-' && arg[1] == 'p' ) {
			argv++;
			NewPriority = atoi(*argv);
			PrioritySet = TRUE;
		} else {
			if( !PFilter->Append(arg) ) {
				usage();
			}
		}
	}

	if( PrioritySet == FALSE && AdjustmentSet == FALSE ) {
		fprintf( stderr,
			"You must specify a new priority or priority adjustment.\n");
		usage();
		exit(1);
	}

	if( PrioritySet && (NewPriority < MIN_PRIO || NewPriority > MAX_PRIO) ) {
		fprintf( stderr,
			"Invalid priority specified.  Must be between %d and %d.\n",
			MIN_PRIO, MAX_PRIO );
		exit(1);
	}

		/* Open job queue */
	(void)sprintf( queue_name, "%s/job_queue", Spool );
	if( (Q=OpenJobQueue(queue_name,O_RDWR,0)) == NULL ) {
		EXCEPT( "OpenJobQueue(%s)", queue_name );
	}

	LockJobQueue( Q, WRITER );

		// Create a list of all procs we're interested in
	PFilter->Install();
	proc_list = ProcObj::create_list( Q, ProcFilter::Func );

		// Process the list
	proc_list->Rewind();
	while( p = proc_list->Next() ) {
		do_it( p );
	}

		// Clean up
	LockJobQueue( Q, UNLOCK );
	CloseJobQueue( Q );
	ProcObj::delete_list( proc_list );
	delete PFilter;

#if defined(ALLOC_DEBUG)
	print_alloc_stats();
#endif

	exit( 0 );
}

/*
  Given the old priority of a given process, calculate the new
  one based on information gotten from the command line arguments.
*/
int
calc_prio( int old_prio )
{
	int		answer;

	if( AdjustmentSet == TRUE && PrioritySet == FALSE ) {
		answer = old_prio + PrioAdjustment;
		if( answer > MAX_PRIO )
			answer = MAX_PRIO;
		else if( answer < MIN_PRIO )
			answer = MIN_PRIO;
	} else {
		answer = NewPriority;
	}
	return answer;
}

/*
  Given a command line argument specifing a relative adjustment
  of priority of the form "+adj" or "-adj", return the correct
  value as a positive or negative integer.
*/
int
compute_adj( char *arg )
{
	char *ptr;
	int val;

	ptr = arg+1;

	val = atoi(ptr);

	if( *arg == '-' ) {
		return( -val );
	} else {
		return( val );
	}
}

extern "C" int SetSyscalls( int foo ) { return foo; }

void
init_params()
{
	Spool = param("SPOOL");
	if( Spool == NULL ) {
		EXCEPT( "SPOOL not specified in config file\n" );
	}
}

void
do_it( ProcObj *p )
{
	int		old_prio;
	int		new_prio;

	if( p->perm_to_modify() ) {
		old_prio = p->get_prio();
		new_prio = calc_prio( old_prio );
		p->set_prio( new_prio );
		p->store( Q );
	} else {
		fprintf( stderr,
			"%d.%d: Permission Denied\n",
			p->get_cluster_id(), p->get_proc_id()
		);
	}
}
<commit_msg>Modified to work with new includes in condor_includes directory.<commit_after>/*
** Copyright 1993 by Miron Livny, and Mike Litzkow
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted,
** provided that the above copyright notice appear in all copies and that
** both that copyright notice and this permission notice appear in
** supporting documentation, and that the names of the University of
** Wisconsin and the copyright holders not be used in advertising or
** publicity pertaining to distribution of the software without specific,
** written prior permission.  The University of Wisconsin and the
** copyright holders make no representations about the suitability of this
** software for any purpose.  It is provided "as is" without express
** or implied warranty.
**
** THE UNIVERSITY OF WISCONSIN AND THE COPYRIGHT HOLDERS DISCLAIM ALL
** WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE UNIVERSITY OF
** WISCONSIN OR THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT
** OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
** OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
** OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
** OR PERFORMANCE OF THIS SOFTWARE.
**
** Author:  Mike Litzkow
**
*/

#define _POSIX_SOURCE

#include "condor_common.h"
#include "condor_constants.h"
#include "condor_debug.h"
#include "condor_config.h"
#include "proc_obj.h"
#include "filter.h"
#include "alloc.h"

static char *_FileName_ = __FILE__;		/* Used by EXCEPT (see except.h)     */

DBM		*Q;

char	*param();
char	*MyName;
char	*Spool;

int		PrioAdjustment;
int		NewPriority;
int		PrioritySet;
int		AdjustmentSet;
ProcFilter	*PFilter = new ProcFilter();
int		InvokingUid;		// user id of person ivoking this program
char	*InvokingUserName;	// user name of person ivoking this program

const int MIN_PRIO = -20;
const int MAX_PRIO = 20;

	// Prototypes of local interest only
void usage();
int compute_adj( char * );
void init_params();
void do_it( ProcObj * );
int calc_prio( int old_prio );
void init_user_credentials();

	// Tell folks how to use this program
void
usage()
{
	fprintf( stderr, "Usage: %s [{+|-}priority ] [-p priority] ", MyName );
	fprintf( stderr, "[ -a ] [user | cluster | cluster.proc] ...\n" );
	exit( 1 );
}

int
main( int argc, char *argv[] )
{
	char	queue_name[_POSIX_PATH_MAX];
	char	*arg;
	int		prio_adj;
	List<ProcObj>	*proc_list;
	ProcObj			*p;

	MyName = argv[0];

	config( MyName, (CONTEXT *)0 );
	init_params();

	if( argc < 2 ) {
		usage();
	}

	PrioritySet = 0;
	AdjustmentSet = 0;

	for( argv++; arg = *argv; argv++ ) {
		if( (arg[0] == '-' || arg[0] == '+') && isdigit(arg[1]) ) {
			PrioAdjustment = compute_adj(arg);
			AdjustmentSet = TRUE;
		} else if( arg[0] == '-' && arg[1] == 'p' ) {
			argv++;
			NewPriority = atoi(*argv);
			PrioritySet = TRUE;
		} else {
			if( !PFilter->Append(arg) ) {
				usage();
			}
		}
	}

	if( PrioritySet == FALSE && AdjustmentSet == FALSE ) {
		fprintf( stderr,
			"You must specify a new priority or priority adjustment.\n");
		usage();
		exit(1);
	}

	if( PrioritySet && (NewPriority < MIN_PRIO || NewPriority > MAX_PRIO) ) {
		fprintf( stderr,
			"Invalid priority specified.  Must be between %d and %d.\n",
			MIN_PRIO, MAX_PRIO );
		exit(1);
	}

		/* Open job queue */
	(void)sprintf( queue_name, "%s/job_queue", Spool );
	if( (Q=OpenJobQueue(queue_name,O_RDWR,0)) == NULL ) {
		EXCEPT( "OpenJobQueue(%s)", queue_name );
	}

	LockJobQueue( Q, WRITER );

		// Create a list of all procs we're interested in
	PFilter->Install();
	proc_list = ProcObj::create_list( Q, ProcFilter::Func );

		// Process the list
	proc_list->Rewind();
	while( p = proc_list->Next() ) {
		do_it( p );
	}

		// Clean up
	LockJobQueue( Q, UNLOCK );
	CloseJobQueue( Q );
	ProcObj::delete_list( proc_list );
	delete PFilter;

#if defined(ALLOC_DEBUG)
	print_alloc_stats();
#endif

	exit( 0 );
}

/*
  Given the old priority of a given process, calculate the new
  one based on information gotten from the command line arguments.
*/
int
calc_prio( int old_prio )
{
	int		answer;

	if( AdjustmentSet == TRUE && PrioritySet == FALSE ) {
		answer = old_prio + PrioAdjustment;
		if( answer > MAX_PRIO )
			answer = MAX_PRIO;
		else if( answer < MIN_PRIO )
			answer = MIN_PRIO;
	} else {
		answer = NewPriority;
	}
	return answer;
}

/*
  Given a command line argument specifing a relative adjustment
  of priority of the form "+adj" or "-adj", return the correct
  value as a positive or negative integer.
*/
int
compute_adj( char *arg )
{
	char *ptr;
	int val;

	ptr = arg+1;

	val = atoi(ptr);

	if( *arg == '-' ) {
		return( -val );
	} else {
		return( val );
	}
}

extern "C" int SetSyscalls( int foo ) { return foo; }

void
init_params()
{
	Spool = param("SPOOL");
	if( Spool == NULL ) {
		EXCEPT( "SPOOL not specified in config file\n" );
	}
}

void
do_it( ProcObj *p )
{
	int		old_prio;
	int		new_prio;

	if( p->perm_to_modify() ) {
		old_prio = p->get_prio();
		new_prio = calc_prio( old_prio );
		p->set_prio( new_prio );
		p->store( Q );
	} else {
		fprintf( stderr,
			"%d.%d: Permission Denied\n",
			p->get_cluster_id(), p->get_proc_id()
		);
	}
}
<|endoftext|>


<commit_before>#include <FFGL.h>
#include <FFGLLib.h>

#include "PluginDefinition.h"

#include <fstream>
#include <cmath>
#include <sys/time.h>

Parameter::Parameter(string name, float min, float max, float value)
: Name(name)
, RangeMin(min)
, RangeMax(max)
, UniformLocation(-1)
{
    Value = (value - min) / (max - min);
}

float Parameter::GetScaledValue() const {
    return RangeMin + Value * (RangeMax - RangeMin);
}

static CFFGLPluginInfo PluginInfo (
	ShaderPlugin::CreateInstance,	// Create method
                                   "CORTEX",								// Plugin unique ID
                                   "Cortex",					// Plugin name
                                   1,						   			// API major version number
                                   500,								  // API minor version number
                                   0,										// Plugin major version number
                                   002,									// Plugin minor version number
                                   FF_SOURCE,						// Plugin type
                                   "Visual form constant synthesizer",	// Plugin description
                                   "by Nathan Lachenmyer" // About
);

#include "shader_vert.glsl"
#include "shader_frag.glsl"

ShaderPlugin::ShaderPlugin()
: CFreeFrameGLPlugin()
, m_initResources(1)
{
	SetMinInputs(0);
	SetMaxInputs(0);
    SetTimeSupported(true);
    m_HostSupportsSetTime = false;

    m_time = 0;
    m_timeLocation = -1;

    m_resolution[0] = 0;
    m_resolution[1] = 0;
    m_resolution[2] = 0;
    m_resolutionLocation = -1;

    // To FFGLize an arbitrary shader, replace shader_frag.glsl and the parameters below.
    // Parameter(uniform name, minimum value, maximum value, default value)
    // Standard parameters/float uniforms only for now.

    m_parameters.push_back(Parameter("sVert", 0.0, 1.0, 0.0));
    m_parameters.push_back(Parameter("sHorizon", 0.0, 1.0, 0.0));
    m_parameters.push_back(Parameter("sDiag", 0.0, 1.0, 0.0));
    m_parameters.push_back(Parameter("sDiagAlt", 0.0, 1.0, 0.0));
    m_parameters.push_back(Parameter("sArms", 0.0, 1.0, 0.0));
    m_parameters.push_back(Parameter("sRings", 0.0, 1.0, 1.0));
    m_parameters.push_back(Parameter("sSpiral", 0.0, 1.0, 0.0));
    m_parameters.push_back(Parameter("sSpiralAlt", 0.0, 1.0, 0.0));
    m_parameters.push_back(Parameter("vertPeriod", -20.0, 10.0, 4.0));
    m_parameters.push_back(Parameter("horizonPeriod", -20.0, 20.0, 4.0));
    m_parameters.push_back(Parameter("diagPeriod", -20.0, 20.0, 4.0));
    m_parameters.push_back(Parameter("diagAltPeriod", -20.0, 20.0, 4.0));
    m_parameters.push_back(Parameter("armPeriod", -20.0, 20.0, 4.0));
    m_parameters.push_back(Parameter("ringPeriod", -20.0, 20.0, 4.0));
    m_parameters.push_back(Parameter("spiralPeriod", -20.0, 20.0, 4.0));
    m_parameters.push_back(Parameter("spiralAltPeriod", -20.0, 20.0, 4.0));
    m_parameters.push_back(Parameter("numVert", 0.0, 100.0, 40.0));
    m_parameters.push_back(Parameter("numHorizon", 0.0, 100.0, 40.0));
    m_parameters.push_back(Parameter("numDiag", 0.0, 100.0, 40.0));
    m_parameters.push_back(Parameter("numDiagAlt", 0.0, 100.0, 40.0));
    m_parameters.push_back(Parameter("numArms", 0.0, 24.0, 4.0));
    m_parameters.push_back(Parameter("numRings", 0.0, 24.0, 4.0));
    m_parameters.push_back(Parameter("numSpiral", 0.0, 24.0, 4.0));
    m_parameters.push_back(Parameter("numSpiralAlt", 0.0, 24.0, 4.0));

    for (int ii = 0; ii < m_parameters.size(); ii++) {
        auto p = m_parameters[ii];
        SetParamInfo(ii, p.Name.c_str(), FF_TYPE_STANDARD, p.Value);
    }
}

DWORD ShaderPlugin::InitGL(const FFGLViewportStruct *vp)
{
    m_extensions.Initialize();
    if (m_extensions.multitexture==0 || m_extensions.ARB_shader_objects==0)
        return FF_FAIL;

    m_shader.SetExtensions(&m_extensions);
    m_shader.Compile(vertexShaderCode, fragmentShaderCode);

    m_shader.BindShader();

    for (auto& p : m_parameters) {
        p.UniformLocation = m_shader.FindUniform(p.Name.c_str());
        if (p.UniformLocation < 0) {
            fprintf(stderr, "Could not locate uniform %s in shader!", p.Name.c_str());
        }
    }

    m_timeLocation = m_shader.FindUniform("iGlobalTime");
    m_resolutionLocation = m_shader.FindUniform("iResolution");
    m_resolution[0] = vp->width;
    m_resolution[1] = vp->height;

    m_shader.UnbindShader();

    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    return FF_SUCCESS;
}

DWORD ShaderPlugin::DeInitGL()
{
  m_shader.FreeGLResources();

  return FF_SUCCESS;
}

DWORD ShaderPlugin::ProcessOpenGL(ProcessOpenGLStruct *pGL) {

    m_shader.BindShader();

    for (auto& p : m_parameters) {
        m_extensions.glUniform1fARB(p.UniformLocation, p.GetScaledValue());
    }

    if (!m_HostSupportsSetTime)
    {
        update_time(&m_time, m_startTime);
    }

    m_extensions.glUniform1fARB(m_timeLocation, m_time);
    m_extensions.glUniform3fvARB(m_resolutionLocation, 3, m_resolution);

	glBegin(GL_QUADS);
    //m_extensions.glMultiTexCoord2f(GL_TEXTURE0, 0, 0);
	glVertex4f(-1, -1, 0, 1);
    //m_extensions.glMultiTexCoord2f(GL_TEXTURE0, 0, m_resolution[1]);
	glVertex4f(-1, 1, 0, 1);
    //m_extensions.glMultiTexCoord2f(GL_TEXTURE0, m_resolution[0], m_resolution[1]);
	glVertex4f(1, 1, 0, 1);
    //m_extensions.glMultiTexCoord2f(GL_TEXTURE0, m_resolution[0], 0);
	glVertex4f(1, -1, 0, 1);
	glEnd();

    m_shader.UnbindShader();

    return FF_SUCCESS;
}

DWORD ShaderPlugin::GetParameter(DWORD dwIndex)
{
	DWORD dwRet;

    if (dwIndex < m_parameters.size()) {
        auto p = m_parameters[dwIndex];
        *((float *)(unsigned)&dwRet) = p.Value;
        return dwRet;
    } else {
        return FF_FAIL;
	}
}

DWORD ShaderPlugin::SetParameter(const SetParameterStruct* pParam)
{
    if (pParam != NULL && pParam->ParameterNumber < m_parameters.size()) {
        auto& p = m_parameters[pParam->ParameterNumber];
        p.Value = *((float *)(unsigned)&(pParam->NewParameterValue));
        return FF_SUCCESS;
    } else {
        return FF_FAIL;
    }
}

DWORD ShaderPlugin::SetTime(double time)
{
    m_HostSupportsSetTime = true;
    m_time = time;
    return FF_SUCCESS;
}

void update_time(double *t, const double t0)
{
#ifdef _WIN32
    //amount of time since plugin init, in seconds (same as SetTime):
    *t = double(GetTickCount())/1000.0 - t0;
#else
    timeval time;
    gettimeofday(&time, NULL);
    long millis = (time.tv_sec * 1000) + (time.tv_usec / 1000);
    *t = double(millis)/1000.0f - t0;
#endif
    return;
}

<commit_msg>Added artist name (morphogen) to the internal plugin info<commit_after>#include <FFGL.h>
#include <FFGLLib.h>

#include "PluginDefinition.h"

#include <fstream>
#include <cmath>
#include <sys/time.h>

Parameter::Parameter(string name, float min, float max, float value)
: Name(name)
, RangeMin(min)
, RangeMax(max)
, UniformLocation(-1)
{
    Value = (value - min) / (max - min);
}

float Parameter::GetScaledValue() const {
    return RangeMin + Value * (RangeMax - RangeMin);
}

static CFFGLPluginInfo PluginInfo (
	ShaderPlugin::CreateInstance,	// Create method
                                   "CORTEX",								// Plugin unique ID
                                   "cortex",					// Plugin name
                                   1,						   			// API major version number
                                   500,								  // API minor version number
                                   0,										// Plugin major version number
                                   002,									// Plugin minor version number
                                   FF_SOURCE,						// Plugin type
                                   "Visual form constant synthesizer",	// Plugin description
                                   "by Nathan Lachenmyer (morphogen)" // About
);

#include "shader_vert.glsl"
#include "shader_frag.glsl"

ShaderPlugin::ShaderPlugin()
: CFreeFrameGLPlugin()
, m_initResources(1)
{
	SetMinInputs(0);
	SetMaxInputs(0);
    SetTimeSupported(true);
    m_HostSupportsSetTime = false;

    m_time = 0;
    m_timeLocation = -1;

    m_resolution[0] = 0;
    m_resolution[1] = 0;
    m_resolution[2] = 0;
    m_resolutionLocation = -1;

    // To FFGLize an arbitrary shader, replace shader_frag.glsl and the parameters below.
    // Parameter(uniform name, minimum value, maximum value, default value)
    // Standard parameters/float uniforms only for now.

    m_parameters.push_back(Parameter("sVert", 0.0, 1.0, 0.0));
    m_parameters.push_back(Parameter("sHorizon", 0.0, 1.0, 0.0));
    m_parameters.push_back(Parameter("sDiag", 0.0, 1.0, 0.0));
    m_parameters.push_back(Parameter("sDiagAlt", 0.0, 1.0, 0.0));
    m_parameters.push_back(Parameter("sArms", 0.0, 1.0, 0.0));
    m_parameters.push_back(Parameter("sRings", 0.0, 1.0, 1.0));
    m_parameters.push_back(Parameter("sSpiral", 0.0, 1.0, 0.0));
    m_parameters.push_back(Parameter("sSpiralAlt", 0.0, 1.0, 0.0));
    m_parameters.push_back(Parameter("vertPeriod", -20.0, 10.0, 4.0));
    m_parameters.push_back(Parameter("horizonPeriod", -20.0, 20.0, 4.0));
    m_parameters.push_back(Parameter("diagPeriod", -20.0, 20.0, 4.0));
    m_parameters.push_back(Parameter("diagAltPeriod", -20.0, 20.0, 4.0));
    m_parameters.push_back(Parameter("armPeriod", -20.0, 20.0, 4.0));
    m_parameters.push_back(Parameter("ringPeriod", -20.0, 20.0, 4.0));
    m_parameters.push_back(Parameter("spiralPeriod", -20.0, 20.0, 4.0));
    m_parameters.push_back(Parameter("spiralAltPeriod", -20.0, 20.0, 4.0));
    m_parameters.push_back(Parameter("numVert", 0.0, 100.0, 40.0));
    m_parameters.push_back(Parameter("numHorizon", 0.0, 100.0, 40.0));
    m_parameters.push_back(Parameter("numDiag", 0.0, 100.0, 40.0));
    m_parameters.push_back(Parameter("numDiagAlt", 0.0, 100.0, 40.0));
    m_parameters.push_back(Parameter("numArms", 0.0, 24.0, 4.0));
    m_parameters.push_back(Parameter("numRings", 0.0, 24.0, 4.0));
    m_parameters.push_back(Parameter("numSpiral", 0.0, 24.0, 4.0));
    m_parameters.push_back(Parameter("numSpiralAlt", 0.0, 24.0, 4.0));

    for (int ii = 0; ii < m_parameters.size(); ii++) {
        auto p = m_parameters[ii];
        SetParamInfo(ii, p.Name.c_str(), FF_TYPE_STANDARD, p.Value);
    }
}

DWORD ShaderPlugin::InitGL(const FFGLViewportStruct *vp)
{
    m_extensions.Initialize();
    if (m_extensions.multitexture==0 || m_extensions.ARB_shader_objects==0)
        return FF_FAIL;

    m_shader.SetExtensions(&m_extensions);
    m_shader.Compile(vertexShaderCode, fragmentShaderCode);

    m_shader.BindShader();

    for (auto& p : m_parameters) {
        p.UniformLocation = m_shader.FindUniform(p.Name.c_str());
        if (p.UniformLocation < 0) {
            fprintf(stderr, "Could not locate uniform %s in shader!", p.Name.c_str());
        }
    }

    m_timeLocation = m_shader.FindUniform("iGlobalTime");
    m_resolutionLocation = m_shader.FindUniform("iResolution");
    m_resolution[0] = vp->width;
    m_resolution[1] = vp->height;

    m_shader.UnbindShader();

    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    return FF_SUCCESS;
}

DWORD ShaderPlugin::DeInitGL()
{
  m_shader.FreeGLResources();

  return FF_SUCCESS;
}

DWORD ShaderPlugin::ProcessOpenGL(ProcessOpenGLStruct *pGL) {

    m_shader.BindShader();

    for (auto& p : m_parameters) {
        m_extensions.glUniform1fARB(p.UniformLocation, p.GetScaledValue());
    }

    if (!m_HostSupportsSetTime)
    {
        update_time(&m_time, m_startTime);
    }

    m_extensions.glUniform1fARB(m_timeLocation, m_time);
    m_extensions.glUniform3fvARB(m_resolutionLocation, 3, m_resolution);

	glBegin(GL_QUADS);
    //m_extensions.glMultiTexCoord2f(GL_TEXTURE0, 0, 0);
	glVertex4f(-1, -1, 0, 1);
    //m_extensions.glMultiTexCoord2f(GL_TEXTURE0, 0, m_resolution[1]);
	glVertex4f(-1, 1, 0, 1);
    //m_extensions.glMultiTexCoord2f(GL_TEXTURE0, m_resolution[0], m_resolution[1]);
	glVertex4f(1, 1, 0, 1);
    //m_extensions.glMultiTexCoord2f(GL_TEXTURE0, m_resolution[0], 0);
	glVertex4f(1, -1, 0, 1);
	glEnd();

    m_shader.UnbindShader();

    return FF_SUCCESS;
}

DWORD ShaderPlugin::GetParameter(DWORD dwIndex)
{
	DWORD dwRet;

    if (dwIndex < m_parameters.size()) {
        auto p = m_parameters[dwIndex];
        *((float *)(unsigned)&dwRet) = p.Value;
        return dwRet;
    } else {
        return FF_FAIL;
	}
}

DWORD ShaderPlugin::SetParameter(const SetParameterStruct* pParam)
{
    if (pParam != NULL && pParam->ParameterNumber < m_parameters.size()) {
        auto& p = m_parameters[pParam->ParameterNumber];
        p.Value = *((float *)(unsigned)&(pParam->NewParameterValue));
        return FF_SUCCESS;
    } else {
        return FF_FAIL;
    }
}

DWORD ShaderPlugin::SetTime(double time)
{
    m_HostSupportsSetTime = true;
    m_time = time;
    return FF_SUCCESS;
}

void update_time(double *t, const double t0)
{
#ifdef _WIN32
    //amount of time since plugin init, in seconds (same as SetTime):
    *t = double(GetTickCount())/1000.0 - t0;
#else
    timeval time;
    gettimeofday(&time, NULL);
    long millis = (time.tv_sec * 1000) + (time.tv_usec / 1000);
    *t = double(millis)/1000.0f - t0;
#endif
    return;
}

<|endoftext|>


<commit_before>#include "shader.h"

namespace D3DLIB
{
	BufferDirectory::BufferDirectory()
	{
		buffers = std::vector<ID3D11Buffer**>();
	}
	void BufferDirectory::Add(ID3D11Buffer** buffer)
	{
		buffers.push_back(buffer);
	}
	void BufferDirectory::Add(ID3D11Buffer** bufferlist[], int count)
	{
		for (int i = 0; i < count; i++)
		{
			Add(bufferlist[i]);
		}
	}
	void BufferDirectory::Shutdown()
	{
		for (vector<ID3D11Buffer**>::iterator p = buffers.begin(); p != buffers.end(); ++p)
		{
			(*((ID3D11Buffer**)*p))->Release();
			(*((ID3D11Buffer**)*p)) = 0;
		}
	}

	Shader::Shader()
	{

	}
	Shader::Shader(const Shader& other)
	{
	}
	Shader::~Shader()
	{
	}

	bool Shader::Initialize(ID3D11Device* device, HWND hwnd)
	{
		return false;
	}
	bool Shader::Render(ID3D11DeviceContext* deviceContext, int indexCount, D3DXMATRIX worldMatrix, D3DXMATRIX viewMatrix,
									D3DXMATRIX projectionMatrix, Transform transform, Orientation orient)
	{
		return false;
	}

	void Shader::GetQuaternion(D3DXQUATERNION &quad, float rotX, float rotY, float rotZ, Orientation orient)
	{
		quad = D3DXQUATERNION();
		if (orient.upaxis == Ypositive)
		{
			D3DXQuaternionRotationYawPitchRoll(&quad, rotX, rotY, rotZ);
		}
		if (orient.upaxis == Zpositive)
		{
			D3DXQuaternionRotationYawPitchRoll(&quad, rotZ, rotY - 90.0f, rotX);
		}
		return;
	}

	void Shader::ThrowBlobError(ID3D10Blob* errorMessage, HWND hwnd, WCHAR* shaderFilename)
	{
		char* compileErrors;
		unsigned long bufferSize, i;
		ofstream fout;

		// Get a pointer to the error message text buffer.
		compileErrors = (char*)(errorMessage->GetBufferPointer());

		// Get the length of the message.
		bufferSize = errorMessage->GetBufferSize();

		// Open a file to write the error message to.
		fout.open("shader-error.txt");

		// Write out the error message.
		for(i=0; i<bufferSize; i++)
		{
			fout << compileErrors[i];
		}

		// Close the file.
		fout.close();

		// Release the error message.
		errorMessage->Release();
		errorMessage = 0;

		// Pop a message up on the screen to notify the user to check the text file for compile errors.
		DisplayMessage(hwnd, Error, false, false, shaderFilename, L"Shader Compilation Error - Check shader-error.txt");

		return;
	}

}<commit_msg>Memory Allocate Buffer<commit_after>#include "shader.h"

namespace D3DLIB
{
	BufferDirectory::BufferDirectory()
	{
		buffers = std::vector<ID3D11Buffer**>();
	}
	void BufferDirectory::Add(ID3D11Buffer** buffer)
	{
		buffers.push_back(buffer);
	}
	void BufferDirectory::Add(ID3D11Buffer** bufferlist[], int count)
	{
		for (int i = 0; i < count; i++)
		{
			Add(bufferlist[i]);
		}
	}
	void BufferDirectory::Shutdown()
	{
		for (vector<ID3D11Buffer**>::iterator p = buffers.begin(); p != buffers.end(); ++p)
		{
			(*((ID3D11Buffer**)*p))->Release();
			(*((ID3D11Buffer**)*p)) = 0;
			delete (*((ID3D11Buffer**)*p));
		}
	}

	Shader::Shader()
	{

	}
	Shader::Shader(const Shader& other)
	{
	}
	Shader::~Shader()
	{
	}

	bool Shader::Initialize(ID3D11Device* device, HWND hwnd)
	{
		return false;
	}
	bool Shader::Render(ID3D11DeviceContext* deviceContext, int indexCount, D3DXMATRIX worldMatrix, D3DXMATRIX viewMatrix,
									D3DXMATRIX projectionMatrix, Transform transform, Orientation orient)
	{
		return false;
	}

	void Shader::GetQuaternion(D3DXQUATERNION &quad, float rotX, float rotY, float rotZ, Orientation orient)
	{
		quad = D3DXQUATERNION();
		if (orient.upaxis == Ypositive)
		{
			D3DXQuaternionRotationYawPitchRoll(&quad, rotX, rotY, rotZ);
		}
		if (orient.upaxis == Zpositive)
		{
			D3DXQuaternionRotationYawPitchRoll(&quad, rotZ, rotY - 90.0f, rotX);
		}
		return;
	}

	void Shader::ThrowBlobError(ID3D10Blob* errorMessage, HWND hwnd, WCHAR* shaderFilename)
	{
		char* compileErrors;
		unsigned long bufferSize, i;
		ofstream fout;

		// Get a pointer to the error message text buffer.
		compileErrors = (char*)(errorMessage->GetBufferPointer());

		// Get the length of the message.
		bufferSize = errorMessage->GetBufferSize();

		// Open a file to write the error message to.
		fout.open("shader-error.txt");

		// Write out the error message.
		for(i=0; i<bufferSize; i++)
		{
			fout << compileErrors[i];
		}

		// Close the file.
		fout.close();

		// Release the error message.
		errorMessage->Release();
		errorMessage = 0;

		// Pop a message up on the screen to notify the user to check the text file for compile errors.
		DisplayMessage(hwnd, Error, false, false, shaderFilename, L"Shader Compilation Error - Check shader-error.txt");

		return;
	}

}<|endoftext|>


<commit_before>#include "OrthographicCamera.h"
#include <limits>
OrthographicCamera::OrthographicCamera()
  : Camera() {

}

OrthographicCamera::OrthographicCamera(const Point3D& position, const Vector3D& forward, const Vector3D& up, const uint32_t near, const uint32_t far, const float zoom)
  : Camera(position, forward, up, near, far, zoom) {

}

OrthographicCamera::~OrthographicCamera() {

}

const Point3D OrthographicCamera::imageSpaceToWorldSpace(const uint16_t pixel_image_x, const uint16_t pixel_image_y) const {
  //TODO: anctual conversion
  return Point3D();
}

const Triangle2D OrthographicCamera::worldSpaceToScreenSpace(const Triangle3D& triangle3D) const {
  //TODO: actual projection
  return Triangle2D();
}

const float OrthographicCamera::getDepth(const Point3D& pixel_world, const Triangle3D& triangle) const {
  bool out_hit;
  const Point3D intersection_point = triangle.intersect(out_hit, pixel_world, this->m_forward);
  if (!out_hit) {
    return std::numeric_limits<float>::max();
  }

  return pixel_world.distance(intersection_point);
}
<commit_msg>Implemented  worldSpace to Screen Space transformation<commit_after>#include "OrthographicCamera.h"
#include <limits>
OrthographicCamera::OrthographicCamera()
  : Camera() {

}

OrthographicCamera::OrthographicCamera(const Point3D& position, const Vector3D& forward, const Vector3D& up, const uint32_t near, const uint32_t far, const float zoom)
  : Camera(position, forward, up, near, far, zoom) {

}

OrthographicCamera::~OrthographicCamera() {

}

const Point3D OrthographicCamera::imageSpaceToWorldSpace(const uint16_t pixel_image_x, const uint16_t pixel_image_y) const {
  //TODO: anctual conversion
  return Point3D();
}

const Triangle2D OrthographicCamera::worldSpaceToScreenSpace(const Triangle3D& triangle3D) const {
  //Because is an orthographic projection, we just get x and y
  return Triangle2D{
    Point2D(triangle3D.v1.x, triangle3D.v1.y),
    Point2D(triangle3D.v2.x, triangle3D.v2.y),
    Point2D(triangle3D.v3.x, triangle3D.v3.y)
  };
}

const float OrthographicCamera::getDepth(const Point3D& pixel_world, const Triangle3D& triangle) const {
  //TODO: Get Z coordinate

  bool out_hit;
  const Point3D intersection_point = triangle.intersect(out_hit, pixel_world, this->m_forward);
  if (!out_hit) {
    return std::numeric_limits<float>::max();
  }

  return pixel_world.distance(intersection_point);
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015-2017 Nagisa Sekiguchi
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "dbus_util.h"

namespace ydsh {

// ###################################
// ##     BaseTypeDescriptorMap     ##
// ###################################

BaseTypeDescriptorMap::BaseTypeDescriptorMap(SymbolTable *pool) {
#define ADD(type, desc) this->map.insert(std::make_pair((unsigned long) (&type), desc))
    ADD(pool->get(TYPE::Int64), DBUS_TYPE_INT64);
    ADD(pool->get(TYPE::Uint64), DBUS_TYPE_UINT64);
    ADD(pool->get(TYPE::Int32), DBUS_TYPE_INT32);
    ADD(pool->get(TYPE::Uint32), DBUS_TYPE_UINT32);
    ADD(pool->get(TYPE::Int16), DBUS_TYPE_INT16);
    ADD(pool->get(TYPE::Uint16), DBUS_TYPE_UINT16);
    ADD(pool->get(TYPE::Byte), DBUS_TYPE_BYTE);

    ADD(pool->get(TYPE::Float), DBUS_TYPE_DOUBLE);

    ADD(pool->get(TYPE::Boolean), DBUS_TYPE_BOOLEAN);

    ADD(pool->get(TYPE::String), DBUS_TYPE_STRING);
    ADD(pool->get(TYPE::ObjectPath), DBUS_TYPE_OBJECT_PATH);

    ADD(pool->get(TYPE::UnixFD), DBUS_TYPE_UNIX_FD);
#undef ADD
}

/**
 * return DBUS_TYPE_INVALID, if not base type.
 */
int BaseTypeDescriptorMap::getDescriptor(DSType &type) {
    auto iter = this->map.find((unsigned long) &type);
    if(iter != this->map.end()) {
        return iter->second;
    }
    return DBUS_TYPE_INVALID;
}

// ###############################
// ##     DescriptorBuilder     ##
// ###############################

const char *DescriptorBuilder::buildDescriptor(DSType &type) {
    this->buf.clear();
    type.accept(this);
    return this->buf.c_str();
}

void DescriptorBuilder::visitFunctionType(FunctionType *type) {
    fatal("unsupported type: %s\n", this->pool->getTypeName(*type));
}

void DescriptorBuilder::visitBuiltinType(BuiltinType *type) {
    int dbusType = this->typeMap->getDescriptor(*type);
    if(dbusType == DBUS_TYPE_INVALID) {
        if(*type == this->pool->get(TYPE::Variant)) {
            this->append(DBUS_TYPE_VARIANT);
            return;
        }
        fatal("unsupported type: %s\n", this->pool->getTypeName(*type));
    }
    this->append(dbusType);
}

void DescriptorBuilder::visitReifiedType(ReifiedType *type) {
    unsigned int elementSize = type->getElementTypes().size();
    if(elementSize == 1) {  // Array
        this->append(DBUS_TYPE_ARRAY);
        type->getElementTypes()[0]->accept(this);
    } else if(elementSize == 2) {   // Map
        this->append(DBUS_TYPE_ARRAY);
        this->append(DBUS_DICT_ENTRY_BEGIN_CHAR);
        type->getElementTypes()[0]->accept(this);
        type->getElementTypes()[1]->accept(this);
        this->append(DBUS_DICT_ENTRY_END_CHAR);
    } else {
        fatal("unsupported type: %s\n", this->pool->getTypeName(*type));
    }
}

void DescriptorBuilder::visitTupleType(TupleType *type) {
    this->append(DBUS_STRUCT_BEGIN_CHAR);
    for(DSType *elementType : type->getElementTypes()) {
        elementType->accept(this);
    }
    this->append(DBUS_STRUCT_END_CHAR);
}

void DescriptorBuilder::visitInterfaceType(InterfaceType *type) {
    fatal("unsupported type: %s\n", this->pool->getTypeName(*type));
}

void DescriptorBuilder::visitErrorType(ErrorType *type) {
    fatal("unsupported type: %s\n", this->pool->getTypeName(*type));
}

// ############################
// ##     MessageBuilder     ##
// ############################

void MessageBuilder::appendArg(DBusMessageIter *iter, DSType &argType, const DSValue &arg) {
    this->iter = iter;
    if(this->typeMap == nullptr) {
        this->typeMap = new BaseTypeDescriptorMap(this->pool);
    }

    this->append(&argType, arg.get());

    this->iter = nullptr;
}

void MessageBuilder::visitFunctionType(FunctionType *type) {
    fatal("unsupported type: %s\n", this->pool->getTypeName(*type));
}

void MessageBuilder::visitBuiltinType(BuiltinType *type) {
    int dbusType = this->typeMap->getDescriptor(*type);
    switch(dbusType) {
    case DBUS_TYPE_INT64: {
        auto value = (dbus_int64_t) (typeAs<Long_Object>(this->peek()))->getValue();
        dbus_message_iter_append_basic(this->iter, dbusType, &value);
        return;
    }
    case DBUS_TYPE_UINT64: {
        dbus_uint64_t value = (typeAs<Long_Object>(this->peek()))->getValue();
        dbus_message_iter_append_basic(this->iter, dbusType, &value);
        return;
    }
    case DBUS_TYPE_INT32: {
        dbus_int32_t value = (typeAs<Int_Object>(this->peek()))->getValue();
        dbus_message_iter_append_basic(this->iter, dbusType, &value);
        return;
    }
    case DBUS_TYPE_UINT32: {
        dbus_uint32_t value = (typeAs<Int_Object>(this->peek()))->getValue();
        dbus_message_iter_append_basic(this->iter, dbusType, &value);
        return;
    }
    case DBUS_TYPE_INT16: {
        dbus_int16_t value = (typeAs<Int_Object>(this->peek()))->getValue();
        dbus_message_iter_append_basic(this->iter, dbusType, &value);
        return;
    }
    case DBUS_TYPE_UINT16: {
        dbus_uint16_t value = (typeAs<Int_Object>(this->peek()))->getValue();
        dbus_message_iter_append_basic(this->iter, dbusType, &value);
        return;
    }
    case DBUS_TYPE_BYTE: {
        unsigned char value = (typeAs<Int_Object>(this->peek()))->getValue();
        dbus_message_iter_append_basic(this->iter, dbusType, &value);
        return;
    }
    case DBUS_TYPE_DOUBLE: {
        double value = (typeAs<Float_Object>(this->peek()))->getValue();
        dbus_message_iter_append_basic(this->iter, dbusType, &value);
        return;
    }
    case DBUS_TYPE_BOOLEAN: {
        dbus_bool_t value = (typeAs<Boolean_Object>(this->peek()))->getValue() ? TRUE : FALSE;
        dbus_message_iter_append_basic(this->iter, dbusType, &value);
        return;
    }
    case DBUS_TYPE_STRING: {
        const char *value = (typeAs<String_Object>(this->peek()))->getValue();
        dbus_message_iter_append_basic(this->iter, dbusType, &value);
        return;
    }
    case DBUS_TYPE_OBJECT_PATH: {
        const char *value = (typeAs<String_Object>(this->peek()))->getValue();
        dbus_message_iter_append_basic(this->iter, dbusType, &value);
        return;
    }
    case DBUS_TYPE_UNIX_FD: {
        fatal("unsupported dbus type: UNIX_FD\n");
        break;
    }
    default:
        if(*type == this->pool->get(TYPE::Variant)) {    //variant
            DSType *actualType = this->peek()->getType();
            const char *desc = this->getBuilder()->buildDescriptor(*actualType);

            DBusMessageIter subIter{};
            DBusMessageIter *curIter = this->openContainerIter(DBUS_TYPE_VARIANT, desc, &subIter);

            // append value
            this->append(actualType, this->peek());

            this->closeContainerIter(curIter, &subIter);
            return;
        }

        fatal("unsupported type: %s\n", this->pool->getTypeName(*type));
    }
}

void MessageBuilder::visitReifiedType(ReifiedType *type) {
    unsigned int elementSize = type->getElementTypes().size();
    if(elementSize == 1) {  // Array
        DSType *elementType = type->getElementTypes()[0];
        const char *desc = this->getBuilder()->buildDescriptor(*elementType);

        DBusMessageIter subIter{};
        DBusMessageIter *curIter = this->openContainerIter(DBUS_TYPE_ARRAY, desc, &subIter);

        // append element
        auto *arrayObj = typeAs<Array_Object>(this->peek());
        for(auto &e : arrayObj->getValues()) {
            this->append(elementType, e.get());
        }

        this->closeContainerIter(curIter, &subIter);
    } else if(elementSize == 2) {   // Map
        DSType *keyType = type->getElementTypes()[0];
        DSType *valueType = type->getElementTypes()[1];

        const char *desc = (this->getBuilder()->buildDescriptor(*type) + 1);

        DBusMessageIter subIter{};
        DBusMessageIter *curIter = this->openContainerIter(DBUS_TYPE_ARRAY, desc, &subIter);

        // append entry
        auto *mapObj = typeAs<Map_Object>(this->peek());
        for(auto &pair : mapObj->getValueMap()) {
            DBusMessageIter entryIter{};
            DBusMessageIter *oldIter = this->openContainerIter(DBUS_TYPE_DICT_ENTRY, nullptr, &entryIter);

            // append key, value
            this->append(keyType, pair.first.get());
            this->append(valueType, pair.second.get());

            this->closeContainerIter(oldIter, &entryIter);
        }

        this->closeContainerIter(curIter, &subIter);
    } else {
        fatal("unsupported type: %s\n", this->pool->getTypeName(*type));
    }
}

void MessageBuilder::visitTupleType(TupleType *type) {
    DBusMessageIter *curIter = this->iter;
    DBusMessageIter subIter{};
    dbus_message_iter_open_container(this->iter, DBUS_TYPE_STRUCT, nullptr, &subIter);

    // append element
    this->iter = &subIter;

    auto *tupleObj = typeAs<Tuple_Object>(this->peek());
    unsigned int size = tupleObj->getElementSize();
    for(unsigned int i = 0; i < size; i++) {
        this->append(type->getElementTypes()[i], tupleObj->get(i).get());
    }

    this->iter = curIter;
    dbus_message_iter_close_container(this->iter, &subIter);
}

void MessageBuilder::visitInterfaceType(InterfaceType *type) {
    fatal("unsupported type: %s\n", this->pool->getTypeName(*type));
}

void MessageBuilder::visitErrorType(ErrorType *type) {
    fatal("unsupported type: %s\n", this->pool->getTypeName(*type));
}

void MessageBuilder::append(DSType *type, DSObject *value) {
    this->objStack.push_back(value);
    type->accept(this);
    this->objStack.pop_back();
}

DescriptorBuilder *MessageBuilder::getBuilder() {
    if(this->descBuilder == nullptr) {
        this->descBuilder = new DescriptorBuilder(this->pool, this->typeMap);
    }
    return this->descBuilder;
}

DBusMessageIter *MessageBuilder::openContainerIter(int dbusType, const char *desc, DBusMessageIter *subIter) {
    dbus_message_iter_open_container(this->iter, dbusType, desc, subIter);
    DBusMessageIter *old = this->iter;
    this->iter = subIter;
    return old;
}

void MessageBuilder::closeContainerIter(DBusMessageIter *parentIter, DBusMessageIter *subIter) {
    this->iter = parentIter;
    dbus_message_iter_close_container(this->iter, subIter);
}

static DSType &decodeTypeDescriptorImpl(SymbolTable *pool, const char *&desc) {
    int kind = *(desc++);
    switch(kind) {
    case DBUS_TYPE_INT64:
        return pool->get(TYPE::Int64);
    case DBUS_TYPE_UINT64:
        return pool->get(TYPE::Uint64);
    case DBUS_TYPE_INT32:
        return pool->get(TYPE::Int32);
    case DBUS_TYPE_UINT32:
        return pool->get(TYPE::Uint32);
    case DBUS_TYPE_INT16:
        return pool->get(TYPE::Int16);
    case DBUS_TYPE_UINT16:
        return pool->get(TYPE::Uint16);
    case DBUS_TYPE_BYTE:
        return pool->get(TYPE::Byte);
    case DBUS_TYPE_DOUBLE:
        return pool->get(TYPE::Float);
    case DBUS_TYPE_BOOLEAN:
        return pool->get(TYPE::Boolean);
    case DBUS_TYPE_STRING:
        return pool->get(TYPE::String);
    case DBUS_TYPE_OBJECT_PATH:
        return pool->get(TYPE::ObjectPath);
    case DBUS_TYPE_UNIX_FD:
        fatal("unsupported dbus type: UNIX_FD\n");
        return pool->get(TYPE::UnixFD);
    case DBUS_TYPE_ARRAY: {
        int nextKind = *desc;
        if(nextKind == DBUS_DICT_ENTRY_BEGIN_CHAR) {    // map
            desc++; // consume begin char

            std::vector<DSType *> types(2);
            types[0] = &decodeTypeDescriptorImpl(pool, desc);
            types[1] = &decodeTypeDescriptorImpl(pool, desc);

            desc++; // consume end char

            return pool->createReifiedType(pool->getMapTemplate(), std::move(types));
        }
        // array
        std::vector<DSType *> types(1);
        types[0] = &decodeTypeDescriptorImpl(pool, desc);
        return pool->createReifiedType(pool->getArrayTemplate(), std::move(types));
    }
    case DBUS_STRUCT_BEGIN_CHAR: {  // Tuple
        std::vector<DSType *> types;
        do {
            types.push_back(&decodeTypeDescriptorImpl(pool, desc));
        } while(*desc != DBUS_STRUCT_END_CHAR);
        return pool->createTupleType(std::move(types));
    }
    case DBUS_TYPE_VARIANT: {
        return pool->get(TYPE::Variant);
    }
    default:
        fatal("unsupported dbus type: %c\n", kind);
    }
}

DSType &decodeTypeDescriptor(SymbolTable *pool, const char *desc) {
    const char *copyDesc = desc;
    return decodeTypeDescriptorImpl(pool, copyDesc);
}

} // namespace ydsh<commit_msg>Revert "replace static_cast with typeAs"<commit_after>/*
 * Copyright (C) 2015-2017 Nagisa Sekiguchi
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "dbus_util.h"

namespace ydsh {

// ###################################
// ##     BaseTypeDescriptorMap     ##
// ###################################

BaseTypeDescriptorMap::BaseTypeDescriptorMap(SymbolTable *pool) {
#define ADD(type, desc) this->map.insert(std::make_pair((unsigned long) (&type), desc))
    ADD(pool->get(TYPE::Int64), DBUS_TYPE_INT64);
    ADD(pool->get(TYPE::Uint64), DBUS_TYPE_UINT64);
    ADD(pool->get(TYPE::Int32), DBUS_TYPE_INT32);
    ADD(pool->get(TYPE::Uint32), DBUS_TYPE_UINT32);
    ADD(pool->get(TYPE::Int16), DBUS_TYPE_INT16);
    ADD(pool->get(TYPE::Uint16), DBUS_TYPE_UINT16);
    ADD(pool->get(TYPE::Byte), DBUS_TYPE_BYTE);

    ADD(pool->get(TYPE::Float), DBUS_TYPE_DOUBLE);

    ADD(pool->get(TYPE::Boolean), DBUS_TYPE_BOOLEAN);

    ADD(pool->get(TYPE::String), DBUS_TYPE_STRING);
    ADD(pool->get(TYPE::ObjectPath), DBUS_TYPE_OBJECT_PATH);

    ADD(pool->get(TYPE::UnixFD), DBUS_TYPE_UNIX_FD);
#undef ADD
}

/**
 * return DBUS_TYPE_INVALID, if not base type.
 */
int BaseTypeDescriptorMap::getDescriptor(DSType &type) {
    auto iter = this->map.find((unsigned long) &type);
    if(iter != this->map.end()) {
        return iter->second;
    }
    return DBUS_TYPE_INVALID;
}

// ###############################
// ##     DescriptorBuilder     ##
// ###############################

const char *DescriptorBuilder::buildDescriptor(DSType &type) {
    this->buf.clear();
    type.accept(this);
    return this->buf.c_str();
}

void DescriptorBuilder::visitFunctionType(FunctionType *type) {
    fatal("unsupported type: %s\n", this->pool->getTypeName(*type));
}

void DescriptorBuilder::visitBuiltinType(BuiltinType *type) {
    int dbusType = this->typeMap->getDescriptor(*type);
    if(dbusType == DBUS_TYPE_INVALID) {
        if(*type == this->pool->get(TYPE::Variant)) {
            this->append(DBUS_TYPE_VARIANT);
            return;
        }
        fatal("unsupported type: %s\n", this->pool->getTypeName(*type));
    }
    this->append(dbusType);
}

void DescriptorBuilder::visitReifiedType(ReifiedType *type) {
    unsigned int elementSize = type->getElementTypes().size();
    if(elementSize == 1) {  // Array
        this->append(DBUS_TYPE_ARRAY);
        type->getElementTypes()[0]->accept(this);
    } else if(elementSize == 2) {   // Map
        this->append(DBUS_TYPE_ARRAY);
        this->append(DBUS_DICT_ENTRY_BEGIN_CHAR);
        type->getElementTypes()[0]->accept(this);
        type->getElementTypes()[1]->accept(this);
        this->append(DBUS_DICT_ENTRY_END_CHAR);
    } else {
        fatal("unsupported type: %s\n", this->pool->getTypeName(*type));
    }
}

void DescriptorBuilder::visitTupleType(TupleType *type) {
    this->append(DBUS_STRUCT_BEGIN_CHAR);
    for(DSType *elementType : type->getElementTypes()) {
        elementType->accept(this);
    }
    this->append(DBUS_STRUCT_END_CHAR);
}

void DescriptorBuilder::visitInterfaceType(InterfaceType *type) {
    fatal("unsupported type: %s\n", this->pool->getTypeName(*type));
}

void DescriptorBuilder::visitErrorType(ErrorType *type) {
    fatal("unsupported type: %s\n", this->pool->getTypeName(*type));
}

// ############################
// ##     MessageBuilder     ##
// ############################

void MessageBuilder::appendArg(DBusMessageIter *iter, DSType &argType, const DSValue &arg) {
    this->iter = iter;
    if(this->typeMap == nullptr) {
        this->typeMap = new BaseTypeDescriptorMap(this->pool);
    }

    this->append(&argType, arg.get());

    this->iter = nullptr;
}

void MessageBuilder::visitFunctionType(FunctionType *type) {
    fatal("unsupported type: %s\n", this->pool->getTypeName(*type));
}

void MessageBuilder::visitBuiltinType(BuiltinType *type) {
    int dbusType = this->typeMap->getDescriptor(*type);
    switch(dbusType) {
    case DBUS_TYPE_INT64: {
        auto value = (dbus_int64_t) (static_cast<Long_Object *>(this->peek()))->getValue();
        dbus_message_iter_append_basic(this->iter, dbusType, &value);
        return;
    }
    case DBUS_TYPE_UINT64: {
        dbus_uint64_t value = (static_cast<Long_Object *>(this->peek()))->getValue();
        dbus_message_iter_append_basic(this->iter, dbusType, &value);
        return;
    }
    case DBUS_TYPE_INT32: {
        dbus_int32_t value = (static_cast<Int_Object *>(this->peek()))->getValue();
        dbus_message_iter_append_basic(this->iter, dbusType, &value);
        return;
    }
    case DBUS_TYPE_UINT32: {
        dbus_uint32_t value = (static_cast<Int_Object *>(this->peek()))->getValue();
        dbus_message_iter_append_basic(this->iter, dbusType, &value);
        return;
    }
    case DBUS_TYPE_INT16: {
        dbus_int16_t value = (static_cast<Int_Object *>(this->peek()))->getValue();
        dbus_message_iter_append_basic(this->iter, dbusType, &value);
        return;
    }
    case DBUS_TYPE_UINT16: {
        dbus_uint16_t value = (static_cast<Int_Object *>(this->peek()))->getValue();
        dbus_message_iter_append_basic(this->iter, dbusType, &value);
        return;
    }
    case DBUS_TYPE_BYTE: {
        unsigned char value = (static_cast<Int_Object *>(this->peek()))->getValue();
        dbus_message_iter_append_basic(this->iter, dbusType, &value);
        return;
    }
    case DBUS_TYPE_DOUBLE: {
        double value = (static_cast<Float_Object *>(this->peek()))->getValue();
        dbus_message_iter_append_basic(this->iter, dbusType, &value);
        return;
    }
    case DBUS_TYPE_BOOLEAN: {
        dbus_bool_t value = (static_cast<Boolean_Object *>(this->peek()))->getValue() ? TRUE : FALSE;
        dbus_message_iter_append_basic(this->iter, dbusType, &value);
        return;
    }
    case DBUS_TYPE_STRING: {
        const char *value = (static_cast<String_Object *>(this->peek()))->getValue();
        dbus_message_iter_append_basic(this->iter, dbusType, &value);
        return;
    }
    case DBUS_TYPE_OBJECT_PATH: {
        const char *value = (static_cast<String_Object *>(this->peek()))->getValue();
        dbus_message_iter_append_basic(this->iter, dbusType, &value);
        return;
    }
    case DBUS_TYPE_UNIX_FD: {
        fatal("unsupported dbus type: UNIX_FD\n");
        break;
    }
    default:
        if(*type == this->pool->get(TYPE::Variant)) {    //variant
            DSType *actualType = this->peek()->getType();
            const char *desc = this->getBuilder()->buildDescriptor(*actualType);

            DBusMessageIter subIter{};
            DBusMessageIter *curIter = this->openContainerIter(DBUS_TYPE_VARIANT, desc, &subIter);

            // append value
            this->append(actualType, this->peek());

            this->closeContainerIter(curIter, &subIter);
            return;
        }

        fatal("unsupported type: %s\n", this->pool->getTypeName(*type));
    }
}

void MessageBuilder::visitReifiedType(ReifiedType *type) {
    unsigned int elementSize = type->getElementTypes().size();
    if(elementSize == 1) {  // Array
        DSType *elementType = type->getElementTypes()[0];
        const char *desc = this->getBuilder()->buildDescriptor(*elementType);

        DBusMessageIter subIter{};
        DBusMessageIter *curIter = this->openContainerIter(DBUS_TYPE_ARRAY, desc, &subIter);

        // append element
        auto *arrayObj = static_cast<Array_Object *>(this->peek());
        for(auto &e : arrayObj->getValues()) {
            this->append(elementType, e.get());
        }

        this->closeContainerIter(curIter, &subIter);
    } else if(elementSize == 2) {   // Map
        DSType *keyType = type->getElementTypes()[0];
        DSType *valueType = type->getElementTypes()[1];

        const char *desc = (this->getBuilder()->buildDescriptor(*type) + 1);

        DBusMessageIter subIter{};
        DBusMessageIter *curIter = this->openContainerIter(DBUS_TYPE_ARRAY, desc, &subIter);

        // append entry
        auto *mapObj = static_cast<Map_Object *>(this->peek());
        for(auto &pair : mapObj->getValueMap()) {
            DBusMessageIter entryIter{};
            DBusMessageIter *oldIter = this->openContainerIter(DBUS_TYPE_DICT_ENTRY, nullptr, &entryIter);

            // append key, value
            this->append(keyType, pair.first.get());
            this->append(valueType, pair.second.get());

            this->closeContainerIter(oldIter, &entryIter);
        }

        this->closeContainerIter(curIter, &subIter);
    } else {
        fatal("unsupported type: %s\n", this->pool->getTypeName(*type));
    }
}

void MessageBuilder::visitTupleType(TupleType *type) {
    DBusMessageIter *curIter = this->iter;
    DBusMessageIter subIter{};
    dbus_message_iter_open_container(this->iter, DBUS_TYPE_STRUCT, nullptr, &subIter);

    // append element
    this->iter = &subIter;

    auto *tupleObj = static_cast<Tuple_Object *>(this->peek());
    unsigned int size = tupleObj->getElementSize();
    for(unsigned int i = 0; i < size; i++) {
        this->append(type->getElementTypes()[i], tupleObj->get(i).get());
    }

    this->iter = curIter;
    dbus_message_iter_close_container(this->iter, &subIter);
}

void MessageBuilder::visitInterfaceType(InterfaceType *type) {
    fatal("unsupported type: %s\n", this->pool->getTypeName(*type));
}

void MessageBuilder::visitErrorType(ErrorType *type) {
    fatal("unsupported type: %s\n", this->pool->getTypeName(*type));
}

void MessageBuilder::append(DSType *type, DSObject *value) {
    this->objStack.push_back(value);
    type->accept(this);
    this->objStack.pop_back();
}

DescriptorBuilder *MessageBuilder::getBuilder() {
    if(this->descBuilder == nullptr) {
        this->descBuilder = new DescriptorBuilder(this->pool, this->typeMap);
    }
    return this->descBuilder;
}

DBusMessageIter *MessageBuilder::openContainerIter(int dbusType, const char *desc, DBusMessageIter *subIter) {
    dbus_message_iter_open_container(this->iter, dbusType, desc, subIter);
    DBusMessageIter *old = this->iter;
    this->iter = subIter;
    return old;
}

void MessageBuilder::closeContainerIter(DBusMessageIter *parentIter, DBusMessageIter *subIter) {
    this->iter = parentIter;
    dbus_message_iter_close_container(this->iter, subIter);
}

static DSType &decodeTypeDescriptorImpl(SymbolTable *pool, const char *&desc) {
    int kind = *(desc++);
    switch(kind) {
    case DBUS_TYPE_INT64:
        return pool->get(TYPE::Int64);
    case DBUS_TYPE_UINT64:
        return pool->get(TYPE::Uint64);
    case DBUS_TYPE_INT32:
        return pool->get(TYPE::Int32);
    case DBUS_TYPE_UINT32:
        return pool->get(TYPE::Uint32);
    case DBUS_TYPE_INT16:
        return pool->get(TYPE::Int16);
    case DBUS_TYPE_UINT16:
        return pool->get(TYPE::Uint16);
    case DBUS_TYPE_BYTE:
        return pool->get(TYPE::Byte);
    case DBUS_TYPE_DOUBLE:
        return pool->get(TYPE::Float);
    case DBUS_TYPE_BOOLEAN:
        return pool->get(TYPE::Boolean);
    case DBUS_TYPE_STRING:
        return pool->get(TYPE::String);
    case DBUS_TYPE_OBJECT_PATH:
        return pool->get(TYPE::ObjectPath);
    case DBUS_TYPE_UNIX_FD:
        fatal("unsupported dbus type: UNIX_FD\n");
        return pool->get(TYPE::UnixFD);
    case DBUS_TYPE_ARRAY: {
        int nextKind = *desc;
        if(nextKind == DBUS_DICT_ENTRY_BEGIN_CHAR) {    // map
            desc++; // consume begin char

            std::vector<DSType *> types(2);
            types[0] = &decodeTypeDescriptorImpl(pool, desc);
            types[1] = &decodeTypeDescriptorImpl(pool, desc);

            desc++; // consume end char

            return pool->createReifiedType(pool->getMapTemplate(), std::move(types));
        }
        // array
        std::vector<DSType *> types(1);
        types[0] = &decodeTypeDescriptorImpl(pool, desc);
        return pool->createReifiedType(pool->getArrayTemplate(), std::move(types));
    }
    case DBUS_STRUCT_BEGIN_CHAR: {  // Tuple
        std::vector<DSType *> types;
        do {
            types.push_back(&decodeTypeDescriptorImpl(pool, desc));
        } while(*desc != DBUS_STRUCT_END_CHAR);
        return pool->createTupleType(std::move(types));
    }
    case DBUS_TYPE_VARIANT: {
        return pool->get(TYPE::Variant);
    }
    default:
        fatal("unsupported dbus type: %c\n", kind);
    }
}

DSType &decodeTypeDescriptor(SymbolTable *pool, const char *desc) {
    const char *copyDesc = desc;
    return decodeTypeDescriptorImpl(pool, copyDesc);
}

} // namespace ydsh<|endoftext|>


<commit_before>/* json11
 *
 * json11 is a tiny JSON library for C++11, providing JSON parsing and serialization.
 *
 * The core object provided by the library is json11::Json. A Json object represents any JSON
 * value: null, bool, number (int or double), string (std::string), array (std::vector), or
 * object (std::map).
 *
 * Json objects act like values: they can be assigned, copied, moved, compared for equality or
 * order, etc. There are also helper methods Json::dump, to serialize a Json to a string, and
 * Json::parse (static) to parse a std::string as a Json object.
 *
 * Internally, the various types of Json object are represented by the JsonValue class
 * hierarchy.
 *
 * A note on numbers - JSON specifies the syntax of number formatting but not its semantics,
 * so some JSON implementations distinguish between integers and floating-point numbers, while
 * some don't. In json11, we choose the latter. Because some JSON implementations (namely
 * Javascript itself) treat all numbers as the same type, distinguishing the two leads
 * to JSON that will be *silently* changed by a round-trip through those implementations.
 * Dangerous! To avoid that risk, json11 stores all numbers as double internally, but also
 * provides integer helpers.
 *
 * Fortunately, double-precision IEEE754 ('double') can precisely store any integer in the
 * range +/-2^53, which includes every 'int' on most systems. (Timestamps often use int64
 * or long long to avoid the Y2038K problem; a double storing microseconds since some epoch
 * will be exact for +/- 275 years.)
 */

/* Copyright (c) 2013 Dropbox, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#pragma once

#include <string>
#include <vector>
#include <map>
#include <memory>
#include <initializer_list>

namespace json11 {

class Json;
class JsonValue;

namespace detail
{

/* A helper class for implementing the traits below. */
struct TraitsHelpers
{
    static std::false_type test_member_encode(...);
    static std::false_type test_free_encode(...);
    static std::false_type test_member_decode(...);
    static std::false_type test_free_decode(...);

    template<class S>
    static std::true_type test_member_encode(
        const S&,
        decltype(std::declval<S>().to_json())* = 0
    );

    template<class S>
    static std::true_type test_free_encode(
        const S&,
        decltype(to_json(std::declval<S>()))* = 0
    );

    template<class S>
    static std::true_type test_member_decode(
        const S&,
        decltype(S::from_json(std::declval<Json>()))* = 0
    );

    template<class S>
    static std::true_type test_free_decode(
        const S&,
        decltype(from_json(std::declval<Json>(), std::declval<S&>()))* = 0
    );

};

/* Inherits from std::true_type if t.to_json() is a valid expression. */
template<class T>
struct has_member_to_json :
    decltype(TraitsHelpers::test_member_encode(std::declval<T>()))
{
};

/* Inherits from std::true_type if to_json(t) is a valid expression. */
template<class T>
struct has_free_to_json :
    decltype(TraitsHelpers::test_free_encode(std::declval<T>()))
{
};

/*
 * Inherits from std::true_type if to_json(t) is valid but t.to_json()
 * is not.
 */
template<class T>
struct has_only_free_to_json :
    std::integral_constant<
        bool,
        !has_member_to_json<T>::value && has_free_to_json<T>::value
    >
{ };

/*
 * Inherits from std::true_type if T::from_json(Json()) is
 * a valid expression.
 */
template<class T>
struct has_member_from_json :
    decltype(TraitsHelpers::test_member_decode(std::declval<T>()))
{
};

/*
 * Inherits from std::true_type if from_json(Json(), t) is
 * a valid expression.
 */
template<class T>
struct has_free_from_json :
    decltype(TraitsHelpers::test_free_decode(std::declval<T>()))
{
};

/*
 * Inherits from std::true_type if from_json(Json(), t) is valid
 * but t.from_json(Json()) is not.
 */
template<class T>
struct has_only_free_from_json :
    std::integral_constant<
        bool,
        !has_member_from_json<T>::value && has_free_from_json<T>::value
    >
{ };

}

class Json final {
public:
    // Types
    enum Type {
        NUL, NUMBER, BOOL, STRING, ARRAY, OBJECT
    };

    // Array and object typedefs
    typedef std::vector<Json> array;
    typedef std::map<std::string, Json> object;

    // Constructors for the various types of JSON value.
    Json() noexcept;                // NUL
    Json(std::nullptr_t) noexcept;  // NUL
    Json(double value);             // NUMBER
    Json(int value);                // NUMBER
    Json(bool value);               // BOOL
    Json(const std::string &value); // STRING
    Json(std::string &&value);      // STRING
    Json(const char * value);       // STRING
    Json(const array &values);      // ARRAY
    Json(array &&values);           // ARRAY
    Json(const object &values);     // OBJECT
    Json(object &&values);          // OBJECT

    // Implicit constructor: anything with a to_json() member function.
    template<class T, typename std::enable_if<
        detail::has_member_to_json<T>::value, int>::type = 0>
    Json(const T& t) : Json(t.to_json()) { }

    // Implicit constructor: anything with only a to_json() free function.
    template<class T, typename std::enable_if<
        detail::has_only_free_to_json<T>::value, int>::type = 0>
    Json(const T& t) : Json(to_json(t)) { }

    // Implicit constructor: map-like objects (std::map, std::unordered_map, etc)
    template <class M, typename std::enable_if<
        std::is_constructible<std::string, decltype(std::declval<M>().begin()->first)>::value
        && std::is_constructible<Json, decltype(std::declval<M>().begin()->second)>::value,
            int>::type = 0>
    Json(const M & m) : Json(object(m.begin(), m.end())) {}

    // Implicit constructor: vector-like objects (std::list, std::vector, std::set, etc)
    template <class V, typename std::enable_if<
        std::is_constructible<Json, decltype(*std::declval<V>().begin())>::value,
            int>::type = 0>
    Json(const V & v) : Json(array(v.begin(), v.end())) {}

    // This prevents Json(some_pointer) from accidentally producing a bool. Use
    // Json(bool(some_pointer)) if that behavior is desired.
    Json(void *) = delete;

    // Accessors
    Type type() const;

    bool is_null()   const { return type() == NUL; }
    bool is_number() const { return type() == NUMBER; }
    bool is_bool()   const { return type() == BOOL; }
    bool is_string() const { return type() == STRING; }
    bool is_array()  const { return type() == ARRAY; }
    bool is_object() const { return type() == OBJECT; }

    // Return the enclosed value if this is a number, 0 otherwise. Note that json11 does not
    // distinguish between integer and non-integer numbers - number_value() and int_value()
    // can both be applied to a NUMBER-typed object.
    double number_value() const;
    int int_value() const;

    // Return the enclosed value if this is a boolean, false otherwise.
    bool bool_value() const;
    // Return the enclosed string if this is a string, "" otherwise.
    const std::string &string_value() const;
    // Return the enclosed std::vector if this is an array, or an empty vector otherwise.
    const array &array_items() const;
    // Return the enclosed std::map if this is an object, or an empty map otherwise.
    const object &object_items() const;

    // Return a reference to arr[i] if this is an array, Json() otherwise.
    const Json & operator[](size_t i) const;
    // Return a reference to obj[key] if this is an object, Json() otherwise.
    const Json & operator[](const std::string &key) const;

    // Serialize.
    void dump(std::string &out) const;
    std::string dump() const {
        std::string out;
        dump(out);
        return out;
    }

    // Parse. If parse fails, return Json() and assign an error message to err.
    static Json parse(const std::string & in, std::string & err);
    static Json parse(const char * in, std::string & err) {
        if (in) {
            return parse(std::string(in), err);
        } else {
            err = "null input";
            return nullptr;
        }
    }
    // Parse multiple objects, concatenated or separated by whitespace
    static std::vector<Json> parse_multi(const std::string & in, std::string & err);

    /* Converts a Json object to type T if T has a from_json method. */
    template<class T>
    T as(typename std::enable_if<
            detail::has_member_from_json<T>::value
        >::type* = 0) const
    {
        return T::from_json(*this);
    }

    /*
     * Converts a Json object to type T if from_json(Json(), some_t) exists and
     * T is default constructible.
     */
    template<class T>
    T as(typename std::enable_if<
            detail::has_only_free_from_json<T>::value
        >::type* = 0
    ) const
    {
        T result;
        from_json(*this, result);
        return result;
    }

    template<class T>
    T as(decltype(std::declval<T>().begin())* = 0) const
    {
        typedef decltype(std::declval<T>().begin()) It;
        typedef typename std::iterator_traits<It>::value_type S;
        T result;
        for (auto js : array_items())
        {
            result.push_back(js.as<S>());
        }
        return result;
    }

    bool operator== (const Json &rhs) const;
    bool operator<  (const Json &rhs) const;
    bool operator!= (const Json &rhs) const { return !(*this == rhs); }
    bool operator<= (const Json &rhs) const { return !(rhs < *this); }
    bool operator>  (const Json &rhs) const { return  (rhs < *this); }
    bool operator>= (const Json &rhs) const { return !(*this < rhs); }

    /* has_shape(types, err)
     *
     * Return true if this is a JSON object and, for each item in types, has a field of
     * the given type. If not, return false and set err to a descriptive message.
     */
    typedef std::initializer_list<std::pair<std::string, Type>> shape;
    bool has_shape(const shape & types, std::string & err) const;

private:
    std::shared_ptr<JsonValue> m_ptr;
};

// Internal class hierarchy - JsonValue objects are not exposed to users of this API.
class JsonValue {
protected:
    friend class Json;
    friend class JsonInt;
    friend class JsonDouble;
    virtual Json::Type type() const = 0;
    virtual bool equals(const JsonValue * other) const = 0;
    virtual bool less(const JsonValue * other) const = 0;
    virtual void dump(std::string &out) const = 0;
    virtual double number_value() const;
    virtual int int_value() const;
    virtual bool bool_value() const;
    virtual const std::string &string_value() const;
    virtual const Json::array &array_items() const;
    virtual const Json &operator[](size_t i) const;
    virtual const Json::object &object_items() const;
    virtual const Json &operator[](const std::string &key) const;
    virtual ~JsonValue() {}
};

} // namespace json11
<commit_msg>Allow overloading to/from_json for vectors.<commit_after>/* json11
 *
 * json11 is a tiny JSON library for C++11, providing JSON parsing and serialization.
 *
 * The core object provided by the library is json11::Json. A Json object represents any JSON
 * value: null, bool, number (int or double), string (std::string), array (std::vector), or
 * object (std::map).
 *
 * Json objects act like values: they can be assigned, copied, moved, compared for equality or
 * order, etc. There are also helper methods Json::dump, to serialize a Json to a string, and
 * Json::parse (static) to parse a std::string as a Json object.
 *
 * Internally, the various types of Json object are represented by the JsonValue class
 * hierarchy.
 *
 * A note on numbers - JSON specifies the syntax of number formatting but not its semantics,
 * so some JSON implementations distinguish between integers and floating-point numbers, while
 * some don't. In json11, we choose the latter. Because some JSON implementations (namely
 * Javascript itself) treat all numbers as the same type, distinguishing the two leads
 * to JSON that will be *silently* changed by a round-trip through those implementations.
 * Dangerous! To avoid that risk, json11 stores all numbers as double internally, but also
 * provides integer helpers.
 *
 * Fortunately, double-precision IEEE754 ('double') can precisely store any integer in the
 * range +/-2^53, which includes every 'int' on most systems. (Timestamps often use int64
 * or long long to avoid the Y2038K problem; a double storing microseconds since some epoch
 * will be exact for +/- 275 years.)
 */

/* Copyright (c) 2013 Dropbox, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#pragma once

#include <string>
#include <vector>
#include <map>
#include <memory>
#include <initializer_list>

namespace json11 {

class Json;
class JsonValue;

namespace detail
{

/* A helper class for implementing the traits below. */
struct TraitsHelpers
{
    static std::false_type test_member_encode(...);
    static std::false_type test_free_encode(...);
    static std::false_type test_member_decode(...);
    static std::false_type test_free_decode(...);

    template<class S>
    static std::true_type test_member_encode(
        const S&,
        decltype(std::declval<S>().to_json())* = 0
    );

    template<class S>
    static std::true_type test_free_encode(
        const S&,
        decltype(to_json(std::declval<S>()))* = 0
    );

    template<class S>
    static std::true_type test_member_decode(
        const S&,
        decltype(S::from_json(std::declval<Json>()))* = 0
    );

    template<class S>
    static std::true_type test_free_decode(
        const S&,
        decltype(from_json(std::declval<Json>(), std::declval<S&>()))* = 0
    );

};

/* Inherits from std::true_type if t.to_json() is a valid expression. */
template<class T>
struct has_member_to_json :
    decltype(TraitsHelpers::test_member_encode(std::declval<T>()))
{
};

/* Inherits from std::true_type if to_json(t) is a valid expression. */
template<class T>
struct has_free_to_json :
    decltype(TraitsHelpers::test_free_encode(std::declval<T>()))
{
};

/*
 * Inherits from std::true_type if to_json(t) is valid but t.to_json()
 * is not.
 */
template<class T>
struct has_only_free_to_json :
    std::integral_constant<
        bool,
        !has_member_to_json<T>::value && has_free_to_json<T>::value
    >
{ };

template<class T>
struct has_to_json :
    std::integral_constant<
        bool,
        has_member_to_json<T>::value || has_free_to_json<T>::value
    >
{ };

/*
 * Inherits from std::true_type if T::from_json(Json()) is
 * a valid expression.
 */
template<class T>
struct has_member_from_json :
    decltype(TraitsHelpers::test_member_decode(std::declval<T>()))
{
};

/*
 * Inherits from std::true_type if from_json(Json(), t) is
 * a valid expression.
 */
template<class T>
struct has_free_from_json :
    decltype(TraitsHelpers::test_free_decode(std::declval<T>()))
{
};

/*
 * Inherits from std::true_type if from_json(Json(), t) is valid
 * but t.from_json(Json()) is not.
 */
template<class T>
struct has_only_free_from_json :
    std::integral_constant<
        bool,
        !has_member_from_json<T>::value && has_free_from_json<T>::value
    >
{ };

template<class T>
struct has_from_json :
    std::integral_constant<
        bool,
        has_member_from_json<T>::value || has_free_from_json<T>::value
    >
{ };

}

class Json final {
public:
    // Types
    enum Type {
        NUL, NUMBER, BOOL, STRING, ARRAY, OBJECT
    };

    // Array and object typedefs
    typedef std::vector<Json> array;
    typedef std::map<std::string, Json> object;

    // Constructors for the various types of JSON value.
    Json() noexcept;                // NUL
    Json(std::nullptr_t) noexcept;  // NUL
    Json(double value);             // NUMBER
    Json(int value);                // NUMBER
    Json(bool value);               // BOOL
    Json(const std::string &value); // STRING
    Json(std::string &&value);      // STRING
    Json(const char * value);       // STRING
    Json(const array &values);      // ARRAY
    Json(array &&values);           // ARRAY
    Json(const object &values);     // OBJECT
    Json(object &&values);          // OBJECT

    // Implicit constructor: anything with a to_json() member function.
    template<class T, typename std::enable_if<
        detail::has_member_to_json<T>::value, int>::type = 0>
    Json(const T& t) : Json(t.to_json()) { }

    // Implicit constructor: anything with only a to_json() free function.
    template<class T, typename std::enable_if<
        detail::has_only_free_to_json<T>::value, int>::type = 0>
    Json(const T& t) : Json(to_json(t)) { }

    // Implicit constructor: map-like objects (std::map, std::unordered_map, etc)
    template <class M, typename std::enable_if<
        std::is_constructible<std::string, decltype(std::declval<M>().begin()->first)>::value
        && std::is_constructible<Json, decltype(std::declval<M>().begin()->second)>::value,
            int>::type = 0>
    Json(const M & m) : Json(object(m.begin(), m.end())) {}

    // Implicit constructor: vector-like objects (std::list, std::vector, std::set, etc)
    template <class V, typename std::enable_if<
        std::is_constructible<Json, decltype(*std::declval<V>().begin())>::value &&
        !detail::has_to_json<V>::value,
            int>::type = 0>
    Json(const V & v) : Json(array(v.begin(), v.end())) {}

    // This prevents Json(some_pointer) from accidentally producing a bool. Use
    // Json(bool(some_pointer)) if that behavior is desired.
    Json(void *) = delete;

    // Accessors
    Type type() const;

    bool is_null()   const { return type() == NUL; }
    bool is_number() const { return type() == NUMBER; }
    bool is_bool()   const { return type() == BOOL; }
    bool is_string() const { return type() == STRING; }
    bool is_array()  const { return type() == ARRAY; }
    bool is_object() const { return type() == OBJECT; }

    // Return the enclosed value if this is a number, 0 otherwise. Note that json11 does not
    // distinguish between integer and non-integer numbers - number_value() and int_value()
    // can both be applied to a NUMBER-typed object.
    double number_value() const;
    int int_value() const;

    // Return the enclosed value if this is a boolean, false otherwise.
    bool bool_value() const;
    // Return the enclosed string if this is a string, "" otherwise.
    const std::string &string_value() const;
    // Return the enclosed std::vector if this is an array, or an empty vector otherwise.
    const array &array_items() const;
    // Return the enclosed std::map if this is an object, or an empty map otherwise.
    const object &object_items() const;

    // Return a reference to arr[i] if this is an array, Json() otherwise.
    const Json & operator[](size_t i) const;
    // Return a reference to obj[key] if this is an object, Json() otherwise.
    const Json & operator[](const std::string &key) const;

    // Serialize.
    void dump(std::string &out) const;
    std::string dump() const {
        std::string out;
        dump(out);
        return out;
    }

    // Parse. If parse fails, return Json() and assign an error message to err.
    static Json parse(const std::string & in, std::string & err);
    static Json parse(const char * in, std::string & err) {
        if (in) {
            return parse(std::string(in), err);
        } else {
            err = "null input";
            return nullptr;
        }
    }
    // Parse multiple objects, concatenated or separated by whitespace
    static std::vector<Json> parse_multi(const std::string & in, std::string & err);

    /* Converts a Json object to type T if T has a from_json method. */
    template<class T>
    T as(typename std::enable_if<
            detail::has_member_from_json<T>::value
        >::type* = 0) const
    {
        return T::from_json(*this);
    }

    /*
     * Converts a Json object to type T if from_json(Json(), some_t) exists and
     * T is default constructible.
     */
    template<class T>
    T as(typename std::enable_if<
            detail::has_only_free_from_json<T>::value
        >::type* = 0
    ) const
    {
        T result;
        from_json(*this, result);
        return result;
    }

    template<
        class T,
        class = typename std::enable_if<!detail::has_from_json<T>::value>::type
    >
    T as(decltype(std::declval<T>().begin())* = 0) const
    {
        typedef decltype(std::declval<T>().begin()) It;
        typedef typename std::iterator_traits<It>::value_type S;
        T result;
        for (auto js : array_items())
        {
            result.push_back(js.as<S>());
        }
        return result;
    }

    bool operator== (const Json &rhs) const;
    bool operator<  (const Json &rhs) const;
    bool operator!= (const Json &rhs) const { return !(*this == rhs); }
    bool operator<= (const Json &rhs) const { return !(rhs < *this); }
    bool operator>  (const Json &rhs) const { return  (rhs < *this); }
    bool operator>= (const Json &rhs) const { return !(*this < rhs); }

    /* has_shape(types, err)
     *
     * Return true if this is a JSON object and, for each item in types, has a field of
     * the given type. If not, return false and set err to a descriptive message.
     */
    typedef std::initializer_list<std::pair<std::string, Type>> shape;
    bool has_shape(const shape & types, std::string & err) const;

private:
    std::shared_ptr<JsonValue> m_ptr;
};

// Internal class hierarchy - JsonValue objects are not exposed to users of this API.
class JsonValue {
protected:
    friend class Json;
    friend class JsonInt;
    friend class JsonDouble;
    virtual Json::Type type() const = 0;
    virtual bool equals(const JsonValue * other) const = 0;
    virtual bool less(const JsonValue * other) const = 0;
    virtual void dump(std::string &out) const = 0;
    virtual double number_value() const;
    virtual int int_value() const;
    virtual bool bool_value() const;
    virtual const std::string &string_value() const;
    virtual const Json::array &array_items() const;
    virtual const Json &operator[](size_t i) const;
    virtual const Json::object &object_items() const;
    virtual const Json &operator[](const std::string &key) const;
    virtual ~JsonValue() {}
};

} // namespace json11
<|endoftext|>


<commit_before>/*
 * main.cpp
 *
 *  Created on: 2017年1月10日
 *      Author: zhuqian
 */
#include <iostream>
#include <fstream>
#include "tiny_obj_loader.h"
#include <map>

struct Vertex {
	float x, y, z;
};

struct UV {
	float u, v;
};

struct Shape {
	std::string name;
	std::map<int, Vertex> vertices;
	std::map<int, Vertex> normals;
	std::map<int, UV> uvs;
	std::vector<int> indices;
};

int main(int argc, char**argv) {

	std::string inputfile = argv[1];
	tinyobj::attrib_t attrib;
	std::vector<tinyobj::shape_t> shapes;
	std::vector<tinyobj::material_t> materials;

	std::string err;
	bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err,
			inputfile.c_str());

	if (!err.empty()) { // `err` may contain warning message.
		std::cerr << err << std::endl;
	}

	if (!ret) {
		exit(1);
	}

	std::cout << "start pharse obj" << std::endl;
	std::ofstream out(inputfile.substr(0, inputfile.size() - 4) + ".lua");
	out.setf(std::iostream::fixed, std::iostream::floatfield);
//	out << inputfile.substr(0, inputfile.size() - 4)
//			<< "_vertices={type=\"point3f\",\n value={";
//	for (size_t i = 0; i < attrib.vertices.size(); ++i) {
//		out << attrib.vertices[i];
//		if (i != (attrib.vertices.size() - 1)) {
//			out << ",";
//		}
//		if (i % 9 == 8) {
//			out << "\n";
//		}
//	}
//	out << "}}\n";
//
//	out << inputfile.substr(0, inputfile.size() - 4)
//			<< "_normals={type=\"normal3f\",\n value={";
//	for (size_t i = 0; i < attrib.normals.size(); ++i) {
//		out << attrib.normals[i];
//		if (i != (attrib.normals.size() - 1)) {
//			out << ",";
//		}
//		if (i % 9 == 8) {
//			out << "\n";
//		}
//	}
//	out << "}}\n";
//
//	out << inputfile.substr(0, inputfile.size() - 4)
//			<< "_uvs={type=\"point2f\",\n value={";
//	for (size_t i = 0; i < attrib.texcoords.size(); ++i) {
//		out << attrib.texcoords[i];
//		if (i != (attrib.texcoords.size() - 1)) {
//			out << ",";
//		}
//		if (i % 6 == 5) {
//			out << "\n";
//		}
//	}
//	out << "}}\n";

	Shape *ss = new Shape[shapes.size()];

	for (size_t s = 0; s < shapes.size(); s++) {
		// Loop over faces(polygon)
		size_t index_offset = 0;
		ss[s].name = shapes[s].name;
		int index = 0;
		std::map<int, int> indexMap;
		std::cout << "shape:" << ss[s].name << std::endl;
		std::cout <<"-->triangle num:"<<shapes[s].mesh.num_face_vertices.size()<< std::endl;
		for (size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) {

			int fv = shapes[s].mesh.num_face_vertices[f];
			for (size_t v = 0; v < fv; v++) {
				tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v];

				if (indexMap.find(idx.vertex_index) == indexMap.end()) {
					indexMap[idx.vertex_index] = index;
					index++;
					//std::cout<<index<<" ";
				}

				ss[s].indices.push_back(indexMap[idx.vertex_index]);

				if (attrib.vertices.size() > 0) {
					Vertex vertex;
					vertex.x = attrib.vertices[3 * idx.vertex_index];
					vertex.y = attrib.vertices[3 * idx.vertex_index + 1];
					vertex.z = attrib.vertices[3 * idx.vertex_index + 2];
					ss[s].vertices[indexMap[idx.vertex_index]] = vertex;
				}
				if (attrib.normals.size() > 0) {
					Vertex normal;
					normal.x = attrib.normals[3 * idx.normal_index];
					normal.y = attrib.normals[3 * idx.normal_index + 1];
					normal.z = attrib.normals[3 * idx.normal_index + 2];
					ss[s].normals[indexMap[idx.vertex_index]] = normal;
				}
				if (attrib.texcoords.size() > 0) {
					UV uv;
					uv.u = attrib.texcoords[2 * idx.texcoord_index];
					uv.v = attrib.texcoords[2 * idx.texcoord_index + 1];
					ss[s].uvs[indexMap[idx.vertex_index]] = uv;
				}

			}
			index_offset += fv;
		}
		std::cout << "-->vertex num:" << ss[s].vertices.size() << std::endl;
		std::cout << "-->normal num:" << ss[s].normals.size() << std::endl;
		std::cout << "--uv num:" << ss[s].uvs.size() << std::endl;

	}
	out <<"local mesh={}\n";
	out <<"mesh[\"shapes\"]={}\n";

	//开始写文件
	for (int i = 0; i < shapes.size(); ++i) {
		out <<"mesh.shapes[" << i << "]={\n  ";

		out << "indices={ type=\"int[]\" ,value={";
		for (int v = 0; v < ss[i].indices.size(); ++v) {
			out << ss[i].indices[v];
			if (v != ss[i].indices.size() - 1) {
				out << ",";
			}
		}
		out << "}},\n";

		out << "vertices={ type=\"point3f\" ,value={";
		for (int v = 0; v < ss[i].vertices.size(); ++v) {
			out << ss[i].vertices[v].x << ",";
			out << ss[i].vertices[v].y << ",";
			out << ss[i].vertices[v].z;
			if (v != ss[i].vertices.size() - 1) {
				out << ",";
			}
			if (v % 3 == 2) {
				out << "\n";
			}
		}
		out << "}},"; //vertex end
		out << "\n  ";

		out << "normals={ type=\"normal3f\" ,value={";
		for (int v = 0; v < ss[i].normals.size(); ++v) {
			out << ss[i].normals[v].x << ",";
			out << ss[i].normals[v].y << ",";
			out << ss[i].normals[v].z;
			if (v != ss[i].normals.size() - 1) {
				out << ",";
			}
			if (v % 3 == 2) {
				out << "\n";
			}
		}
		out << "}},"; //normal end
		out << "\n";

		out << "uvs={ type=\"point2f\" ,value={";
		for (int v = 0; v < ss[i].uvs.size(); ++v) {
			out << ss[i].uvs[v].u << ",";
			out << ss[i].uvs[v].v;
			if (v != ss[i].uvs.size() - 1) {
				out << ",";
			}
			if (v % 3 == 2) {
				out << "\n";
			}
		}
		out << "}}"; //uv end
		out << "\n";

		out << "}\n";
	}
	out << "return mesh\n";
	return 0;
}

<commit_msg>上传部分objtolua代码的结构修改<commit_after>/*
 * main.cpp
 *
 *  Created on: 2017年1月10日
 *      Author: zhuqian
 */
#include <iostream>
#include <fstream>
#include "tiny_obj_loader.h"
#include <map>

struct Vertex {
	float x, y, z;
};

struct UV {
	float u, v;
};

struct Shape {
	std::string name;
	std::map<int, Vertex> vertices;
	std::map<int, Vertex> normals;
	std::map<int, UV> uvs;
	std::vector<int> indices;
};

int main(int argc, char**argv) {

	std::string inputfile = argv[1];
	tinyobj::attrib_t attrib;
	std::vector<tinyobj::shape_t> shapes;
	std::vector<tinyobj::material_t> materials;

	std::string err;
	bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err,
			inputfile.c_str());

	if (!err.empty()) { // `err` may contain warning message.
		std::cerr << err << std::endl;
	}

	if (!ret) {
		exit(1);
	}

	std::cout << "start pharse obj" << std::endl;
	std::ofstream out(inputfile.substr(0, inputfile.size() - 4) + ".lua");
	out.setf(std::iostream::fixed, std::iostream::floatfield);
//	out << inputfile.substr(0, inputfile.size() - 4)
//			<< "_vertices={type=\"point3f\",\n value={";
//	for (size_t i = 0; i < attrib.vertices.size(); ++i) {
//		out << attrib.vertices[i];
//		if (i != (attrib.vertices.size() - 1)) {
//			out << ",";
//		}
//		if (i % 9 == 8) {
//			out << "\n";
//		}
//	}
//	out << "}}\n";
//
//	out << inputfile.substr(0, inputfile.size() - 4)
//			<< "_normals={type=\"normal3f\",\n value={";
//	for (size_t i = 0; i < attrib.normals.size(); ++i) {
//		out << attrib.normals[i];
//		if (i != (attrib.normals.size() - 1)) {
//			out << ",";
//		}
//		if (i % 9 == 8) {
//			out << "\n";
//		}
//	}
//	out << "}}\n";
//
//	out << inputfile.substr(0, inputfile.size() - 4)
//			<< "_uvs={type=\"point2f\",\n value={";
//	for (size_t i = 0; i < attrib.texcoords.size(); ++i) {
//		out << attrib.texcoords[i];
//		if (i != (attrib.texcoords.size() - 1)) {
//			out << ",";
//		}
//		if (i % 6 == 5) {
//			out << "\n";
//		}
//	}
//	out << "}}\n";

	Shape *ss = new Shape[shapes.size()];

	for (size_t s = 0; s < shapes.size(); s++) {
		// Loop over faces(polygon)
		size_t index_offset = 0;
		ss[s].name = shapes[s].name;
		int index = 0;
		std::map<int, int> indexMap;
		std::cout << "shape:" << ss[s].name << std::endl;
		for (size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) {

			int fv = shapes[s].mesh.num_face_vertices[f];
			for (size_t v = 0; v < fv; v++) {
				tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v];

				if (indexMap.find(idx.vertex_index) == indexMap.end()) {
					indexMap[idx.vertex_index] = index;
					index++;
				}

				ss[s].indices.push_back(indexMap[idx.vertex_index]);
				std::cout<<"Index:"<<indexMap[idx.vertex_index]<<" ";
				if (attrib.vertices.size() > 0) {
					Vertex vertex;
					vertex.x = attrib.vertices[3 * idx.vertex_index];
					vertex.y = attrib.vertices[3 * idx.vertex_index + 1];
					vertex.z = attrib.vertices[3 * idx.vertex_index + 2];
					ss[s].vertices[indexMap[idx.vertex_index]] = vertex;
					std::cout<<"V["<<vertex.x<<" "<<vertex.y<<" "<<vertex.z<<"] ";
				}
				if (attrib.normals.size() > 0) {
					Vertex normal;
					normal.x = attrib.normals[3 * idx.normal_index];
					normal.y = attrib.normals[3 * idx.normal_index + 1];
					normal.z = attrib.normals[3 * idx.normal_index + 2];
					ss[s].normals[indexMap[idx.vertex_index]] = normal;
					std::cout<<"N["<<normal.x<<" "<<normal.y<<" "<<normal.z<<"] ";
				}
				if (attrib.texcoords.size() > 0) {
					UV uv;
					uv.u = attrib.texcoords[2 * idx.texcoord_index];
					uv.v = attrib.texcoords[2 * idx.texcoord_index + 1];

					ss[s].uvs[indexMap[idx.vertex_index]] = uv;
					std::cout<<"UV["<<uv.u<<" "<<uv.v<<"] "<< std::endl;
				}

			}
			index_offset += fv;
		}
		std::cout <<"triangle num:"<<shapes[s].mesh.num_face_vertices.size()<< std::endl;
		std::cout << "vertex num:" << ss[s].vertices.size() << std::endl;
		std::cout << "normal num:" << ss[s].normals.size() << std::endl;
		std::cout << "uv num:" << ss[s].uvs.size() << std::endl;

	}
	out <<"local mesh={}\n";
	out <<"mesh[\"shapes\"]={}\n";

	//开始写文件
	for (int i = 0; i < shapes.size(); ++i) {
		out <<"mesh.shapes[" << i << "]={\n  ";

		out << "indices={ type=\"int[]\" ,value={";
		for (int v = 0; v < ss[i].indices.size(); ++v) {
			out << ss[i].indices[v];
			if (v != ss[i].indices.size() - 1) {
				out << ",";
			}
		}
		out << "}},\n";

		out << "vertices={ type=\"point3f\" ,value={";
		for (int v = 0; v < ss[i].vertices.size(); ++v) {
			out << ss[i].vertices[v].x << ",";
			out << ss[i].vertices[v].y << ",";
			out << ss[i].vertices[v].z;
			if (v != ss[i].vertices.size() - 1) {
				out << ",";
			}
			if (v % 3 == 2) {
				out << "\n";
			}
		}
		out << "}},"; //vertex end
		out << "\n  ";

		out << "normals={ type=\"normal3f\" ,value={";
		for (int v = 0; v < ss[i].normals.size(); ++v) {
			out << ss[i].normals[v].x << ",";
			out << ss[i].normals[v].y << ",";
			out << ss[i].normals[v].z;
			if (v != ss[i].normals.size() - 1) {
				out << ",";
			}
			if (v % 3 == 2) {
				out << "\n";
			}
		}
		out << "}},"; //normal end
		out << "\n";

		out << "uvs={ type=\"point2f\" ,value={";
		for (int v = 0; v < ss[i].uvs.size(); ++v) {
			out << ss[i].uvs[v].u << ",";
			out << ss[i].uvs[v].v;
			if (v != ss[i].uvs.size() - 1) {
				out << ",";
			}
			if (v % 3 == 2) {
				out << "\n";
			}
		}
		out << "}}"; //uv end
		out << "\n";

		out << "}\n";
	}
	out << "return mesh\n";
	return 0;
}

<|endoftext|>


<commit_before><commit_msg>Fixed spelling and typos.<commit_after><|endoftext|>