<commit_before>/*
 *  qimask.cpp
 *
 *  Created by Tobias Wood on 2015/09/22.
 *  Copyright (c) 2015 Tobias Wood.
 *
 *  This Source Code Form is subject to the terms of the Mozilla Public
 *  License, v. 2.0. If a copy of the MPL was not distributed with this
 *  file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 */

#include <iostream>
#include <string>
#include <complex>
#include <getopt.h>

#include "itkComplexToModulusImageFilter.h"
#include "itkOtsuThresholdImageFilter.h"
#include "itkVotingBinaryIterativeHoleFillingImageFilter.h"

#include "QI/Types.h"
#include "QI/Util.h"

using namespace std;

const string usage{
"A tool to generate an image mask using an Otsu filter followed by hole-filling.\n\
This is a simple wrapper around itkOtsuThresholdImageFilter.\n\
Usage is: qimask [options] input \n\
\
For multi-volume input the first volume is used by default.\n\
Complex data can be used with -x (will take magnitude first).\n\
Output will be an image called [input]_mask.\n\
Options:\n\
    --verbose, -v     : Print more messages.\n\
    --out, -o path    : Change the output prefix.\n\
    --vol, -V N       : Use volume N. -1 will select the last volume\n\
    --complex, -x     : Input data is complex, take magnitude first\n\
    --fillh, -F N     : Fill with radius N\n\
    --threads, -T N   : Use a maximum of N threads.\n"
};

static struct option long_options[] = {
    {"verbose", required_argument, 0, 'v'},
    {"out",     required_argument, 0, 'o'},
    {"vol",     required_argument, 0, 'V'},
    {"complex", no_argument, 0,'x'},
    {"fillh",   required_argument, 0, 'F'},
    {"threads", required_argument, 0, 'T'},
    {0, 0, 0, 0}
};
static const char *short_options = "vo:V:xF:T:h";

int main(int argc, char **argv) {
    int indexptr = 0, c, volume = 0, fillh_radius = 0;
    string outPrefix = "";
    bool verbose = false, is_complex = false;
    while ((c = getopt_long(argc, argv, short_options, long_options, &indexptr)) != -1) {
        switch (c) {
        case 'v': verbose = true; break;
        case 'o':
            outPrefix = optarg;
            cout << "Output prefix will be: " << outPrefix << endl;
            break;
        case 'V': volume = atoi(optarg); break;
        case 'x': is_complex = true; break;
        case 'F': fillh_radius = stoi(optarg); break;
        case 'T': {
            int numThreads = stoi(optarg);
            if (numThreads > 0)
                itk::MultiThreader::SetGlobalDefaultNumberOfThreads(numThreads);
        } break;
        case 'h':
            cout << QI::GetVersion() << endl << usage << endl;
            return EXIT_SUCCESS;
        case '?': // getopt will print an error message
            return EXIT_FAILURE;
        default:
            cout << "Unhandled option " << string(1, c) << endl;
            return EXIT_FAILURE;
        }
    }
    if ((argc - optind) != 1) {
        cout << QI::GetVersion() << endl << usage << endl;
        return EXIT_FAILURE;
    }
    string fname(argv[optind]);
    if (verbose) cout << "Opening input file " << fname << endl;
    if (outPrefix == "")
        outPrefix = fname.substr(0, fname.find(".nii"));;
    QI::TimeseriesF::Pointer vols = ITK_NULLPTR;
    if (is_complex) {
        auto inFile = QI::TimeseriesReaderXF::New();
        inFile->SetFileName(fname);
        auto magFilter = itk::ComplexToModulusImageFilter<QI::TimeseriesXF, QI::TimeseriesF>::New();
        magFilter->SetInput(inFile->GetOutput());
        magFilter->Update();
        vols = magFilter->GetOutput();
        vols->DisconnectPipeline();
    } else {
        auto inFile = QI::TimeseriesReaderF::New();
        inFile->SetFileName(fname);
        inFile->Update();
        vols = inFile->GetOutput();
        vols->DisconnectPipeline();
    }

    // Extract one volume to process
    auto vol = itk::ExtractImageFilter<QI::TimeseriesF, QI::ImageF>::New();
    auto region = vols->GetLargestPossibleRegion();
    if (volume == -1) {
        volume = region.GetSize()[3] - 1;
    } else if (volume >= region.GetSize()[3]) {
        cerr << "Specified volume was past end of image, using first." << endl;
        volume = 0;
    }
    region.GetModifiableSize()[3] = 0;
    region.GetModifiableIndex()[3] = volume;
    vol->SetExtractionRegion(region);
    vol->SetInput(vols);
    vol->SetDirectionCollapseToSubmatrix();

    // Use an Otsu Threshold filter to generate the mask
    if (verbose) cout << "Generating Otsu mask" << endl;
    auto otsuFilter = itk::OtsuThresholdImageFilter<QI::ImageF, QI::ImageF>::New();
    otsuFilter->SetInput(vol->GetOutput());
    otsuFilter->SetOutsideValue(1);
    otsuFilter->SetInsideValue(0);
    otsuFilter->Update();

    QI::ImageF::Pointer finalMask = ITK_NULLPTR;
    if (fillh_radius > 0) {
        if (verbose) cout << "Filling holes" << endl;
        auto fillHoles = itk::VotingBinaryIterativeHoleFillingImageFilter<QI::ImageF>::New();
        itk::VotingBinaryIterativeHoleFillingImageFilter<QI::ImageF>::InputSizeType radius;
        radius.Fill(2);
        fillHoles->SetInput(otsuFilter->GetOutput());
        fillHoles->SetRadius(radius);
        fillHoles->SetMajorityThreshold(2); // Corresponds to (rad^3-1)/2 + 2 threshold
        fillHoles->SetBackgroundValue(0.0);
        fillHoles->SetForegroundValue(1.0);
        fillHoles->SetMaximumNumberOfIterations(3);
        fillHoles->Update();
        finalMask = fillHoles->GetOutput();
        finalMask->DisconnectPipeline();
    } else {
        finalMask = otsuFilter->GetOutput();
    }
    if (verbose) cout << "Saving mask" << endl;
    QI::WriteImage(finalMask, outPrefix + "_mask" + QI::OutExt());
    if (verbose) cout << "Finished." << endl;
    return EXIT_SUCCESS;
}

<commit_msg>BUG: Changed output option to be the full filename, not a prefix.<commit_after>/*
 *  qimask.cpp
 *
 *  Created by Tobias Wood on 2015/09/22.
 *  Copyright (c) 2015 Tobias Wood.
 *
 *  This Source Code Form is subject to the terms of the Mozilla Public
 *  License, v. 2.0. If a copy of the MPL was not distributed with this
 *  file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 */

#include <iostream>
#include <string>
#include <complex>
#include <getopt.h>

#include "itkComplexToModulusImageFilter.h"
#include "itkOtsuThresholdImageFilter.h"
#include "itkVotingBinaryIterativeHoleFillingImageFilter.h"

#include "QI/Types.h"
#include "QI/Util.h"

using namespace std;

const string usage{
"A tool to generate an image mask using an Otsu filter followed by hole-filling.\n\
This is a simple wrapper around itkOtsuThresholdImageFilter.\n\
Usage is: qimask [options] input \n\
\
For multi-volume input the first volume is used by default.\n\
Complex data can be used with -x (will take magnitude first).\n\
Output will be an image called [input]_mask.\n\
Options:\n\
    --verbose, -v     : Print more messages.\n\
    --out, -o path    : Change the output prefix.\n\
    --vol, -V N       : Use volume N. -1 will select the last volume\n\
    --complex, -x     : Input data is complex, take magnitude first\n\
    --fillh, -F N     : Fill with radius N\n\
    --threads, -T N   : Use a maximum of N threads.\n"
};

static struct option long_options[] = {
    {"verbose", required_argument, 0, 'v'},
    {"out",     required_argument, 0, 'o'},
    {"vol",     required_argument, 0, 'V'},
    {"complex", no_argument, 0,'x'},
    {"fillh",   required_argument, 0, 'F'},
    {"threads", required_argument, 0, 'T'},
    {0, 0, 0, 0}
};
static const char *short_options = "vo:V:xF:T:h";

int main(int argc, char **argv) {
    int indexptr = 0, c, volume = 0, fillh_radius = 0;
    string outName = "";
    bool verbose = false, is_complex = false;
    while ((c = getopt_long(argc, argv, short_options, long_options, &indexptr)) != -1) {
        switch (c) {
        case 'v': verbose = true; break;
        case 'o': outName = optarg; break;
        case 'V': volume = atoi(optarg); break;
        case 'x': is_complex = true; break;
        case 'F': fillh_radius = stoi(optarg); break;
        case 'T': {
            int numThreads = stoi(optarg);
            if (numThreads > 0)
                itk::MultiThreader::SetGlobalDefaultNumberOfThreads(numThreads);
        } break;
        case 'h':
            cout << QI::GetVersion() << endl << usage << endl;
            return EXIT_SUCCESS;
        case '?': // getopt will print an error message
            return EXIT_FAILURE;
        default:
            cout << "Unhandled option " << string(1, c) << endl;
            return EXIT_FAILURE;
        }
    }
    if ((argc - optind) != 1) {
        cout << QI::GetVersion() << endl << usage << endl;
        return EXIT_FAILURE;
    }
    string fname(argv[optind]);
    if (verbose) cout << "Opening input file " << fname << endl;
    if (outName == "")
        outName = fname.substr(0, fname.find(".nii")) + "_mask";
    QI::TimeseriesF::Pointer vols = ITK_NULLPTR;
    if (is_complex) {
        auto inFile = QI::TimeseriesReaderXF::New();
        inFile->SetFileName(fname);
        auto magFilter = itk::ComplexToModulusImageFilter<QI::TimeseriesXF, QI::TimeseriesF>::New();
        magFilter->SetInput(inFile->GetOutput());
        magFilter->Update();
        vols = magFilter->GetOutput();
        vols->DisconnectPipeline();
    } else {
        auto inFile = QI::TimeseriesReaderF::New();
        inFile->SetFileName(fname);
        inFile->Update();
        vols = inFile->GetOutput();
        vols->DisconnectPipeline();
    }

    // Extract one volume to process
    auto vol = itk::ExtractImageFilter<QI::TimeseriesF, QI::ImageF>::New();
    auto region = vols->GetLargestPossibleRegion();
    if (volume == -1) {
        volume = region.GetSize()[3] - 1;
    } else if (volume >= region.GetSize()[3]) {
        cerr << "Specified volume was past end of image, using first." << endl;
        volume = 0;
    }
    region.GetModifiableSize()[3] = 0;
    region.GetModifiableIndex()[3] = volume;
    vol->SetExtractionRegion(region);
    vol->SetInput(vols);
    vol->SetDirectionCollapseToSubmatrix();

    // Use an Otsu Threshold filter to generate the mask
    if (verbose) cout << "Generating Otsu mask" << endl;
    auto otsuFilter = itk::OtsuThresholdImageFilter<QI::ImageF, QI::ImageF>::New();
    otsuFilter->SetInput(vol->GetOutput());
    otsuFilter->SetOutsideValue(1);
    otsuFilter->SetInsideValue(0);
    otsuFilter->Update();

    QI::ImageF::Pointer finalMask = ITK_NULLPTR;
    if (fillh_radius > 0) {
        if (verbose) cout << "Filling holes" << endl;
        auto fillHoles = itk::VotingBinaryIterativeHoleFillingImageFilter<QI::ImageF>::New();
        itk::VotingBinaryIterativeHoleFillingImageFilter<QI::ImageF>::InputSizeType radius;
        radius.Fill(2);
        fillHoles->SetInput(otsuFilter->GetOutput());
        fillHoles->SetRadius(radius);
        fillHoles->SetMajorityThreshold(2); // Corresponds to (rad^3-1)/2 + 2 threshold
        fillHoles->SetBackgroundValue(0.0);
        fillHoles->SetForegroundValue(1.0);
        fillHoles->SetMaximumNumberOfIterations(3);
        fillHoles->Update();
        finalMask = fillHoles->GetOutput();
        finalMask->DisconnectPipeline();
    } else {
        finalMask = otsuFilter->GetOutput();
    }
    if (verbose) cout << "Saving mask" << endl;
    QI::WriteImage(finalMask, outName + QI::OutExt());
    if (verbose) cout << "Finished." << endl;
    return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>/************************************************************************************

Filename    :   OvrApp.cpp
Content     :   Trivial use of the application framework.
Created     :
Authors     :

Copyright   :   Copyright 2014 Oculus VR, LLC. All Rights reserved.

*************************************************************************************/

#include "Mangaroll.h"
#include "GuiSys.h"
#include "OVR_Locale.h"
#include "Kernel/OVR_Hash.h"
#include "Kernel/OVR_Types.h"
#include "Helpers.h"

#if 0
	#define GL( func )		func; EglCheckErrors();
#else
	#define GL( func )		func;
#endif

using namespace OVR;

#if defined( OVR_OS_ANDROID )
extern "C" {

jlong Java_oculus_MainActivity_nativeSetAppInterface( JNIEnv * jni, jclass clazz, jobject activity,
		jstring fromPackageName, jstring commandString, jstring uriString )
{
	LOG( "nativeSetAppInterface" );
	return (new OvrMangaroll::Mangaroll())->SetActivity( jni, clazz, activity, fromPackageName, commandString, uriString );
}

} // extern "C"

#endif

namespace OvrMangaroll
{

	static const char VERTEX_SHADER[] =
#if defined( OVR_OS_ANDROID )
	"#version 300 es\n"
#endif
	"in vec3 Position;\n"
	"in vec4 VertexColor;\n"
	"in vec2 TexCoord;\n"
	"uniform mat4 Viewm;\n"
	"uniform mat4 Projectionm;\n"
	"uniform mat4 Modelm;\n"
	"out vec4 fragmentColor;\n"
	"out vec2 oTexCoord;\n"
	"void main()\n"
	"{\n"
	"	gl_Position = Projectionm * Viewm * Modelm * vec4( Position, 1.0 );\n"
	"	fragmentColor = VertexColor;\n"
	"   oTexCoord = TexCoord;\n"
	"}\n";

static const char FRAGMENT_SHADER[] =
#if defined( OVR_OS_ANDROID )
	"#version 300 es\n"
#endif
	"in lowp vec4 fragmentColor;\n"
	"uniform sampler2D Texture0;\n"
	"uniform int IsSelected;\n"
	"in lowp vec2 oTexCoord;\n"
	"out lowp vec4 outColor;\n"
	"void main()\n"
	"{\n"
	"	outColor = IsSelected == 1 ? fragmentColor : texture( Texture0, oTexCoord );\n"
	"	//outColor = fragmentColor;\n"
	"}\n";

// setup Cube
struct ovrQuadVertices
{
	Vector3f positions[4];
	Vector4f colors[4];
	Vector2f uv0[4];
};

static ovrQuadVertices quadVertices =
{
	// positions
	{
		Vector3f( +1.0f, +1.0f, -5.0f ), Vector3f( -1.0f, +1.0f, -5.0f ), Vector3f( -1.0f, -1.0f, -5.0f ), Vector3f( +1.0f, -1.0f, -5.0f ),
	},
	// colors
	{
		Vector4f( 1.0f, 0.0f, 1.0f, 1.0f ), Vector4f( 0.0f, 1.0f, 0.0f, 1.0f ), Vector4f( 0.0f, 0.0f, 1.0f, 1.0f ), Vector4f( 1.0f, 0.0f, 0.0f, 1.0f )
	},
	// uvs
	{
		Vector2f(1, 1), Vector2f(0, 1), Vector2f(0, 0), Vector2f(1, 0)
	}
};

static const unsigned short quadIndices[12] =
{
	0, 1, 2, 2, 3, 0,	// front
	0, 2, 1, 2, 0, 3,	// back
};

Mangaroll::Mangaroll()
	: SoundEffectContext( NULL )
	, SoundEffectPlayer( NULL )
	, GuiSys( OvrGuiSys::Create() )
	, Locale( NULL )
	, LastPress(0)
{
	CenterEyeViewMatrix = ovrMatrix4f_CreateIdentity();
}

Mangaroll::~Mangaroll()
{
	OvrGuiSys::Destroy( GuiSys );
}

void Mangaroll::Configure( ovrSettings & settings )
{
	settings.PerformanceParms.CpuLevel = 2;
	settings.PerformanceParms.GpuLevel = 2;
}

void Mangaroll::OneTimeInit( const char * fromPackage, const char * launchIntentJSON, const char * launchIntentURI )
{
	OVR_UNUSED( fromPackage );
	OVR_UNUSED( launchIntentJSON );
	OVR_UNUSED( launchIntentURI );
	const ovrJava * java = app->GetJava();

	SoundEffectContext = new ovrSoundEffectContext( *java->Env, java->ActivityObject );
	SoundEffectContext->Initialize();
	SoundEffectPlayer = new OvrGuiSys::ovrDummySoundEffectPlayer();

	Locale = ovrLocale::Create( *app, "default" );

	String fontName;
	GetLocale().GetString( "@string/font_name", "efigs.fnt", fontName );
	GuiSys->Init( this->app, *SoundEffectPlayer, fontName.ToCStr(), &app->GetDebugLines() );

	int Width, Height;
	WARN("WHOO %s", "Lol");
	Page1 = OVR::LoadTextureFromApplicationPackage("assets/page0006.jpg", TextureFlags_t( TEXTUREFLAG_NO_DEFAULT ), Width, Height);
	WARN("WIIIDITH %d",  Width);
	// Create the program.
	Program = BuildProgram( VERTEX_SHADER, FRAGMENT_SHADER );

	// Create the quad.
	VertexAttribs attribs;
	attribs.position.Resize( 4 );
	attribs.color.Resize( 4 );
	attribs.uv0.Resize(4);
	for ( int i = 0; i < 4; i++ )
	{
		attribs.position[i] = quadVertices.positions[i];
		attribs.color[i] = quadVertices.colors[i];
		attribs.uv0[i] = quadVertices.uv0[i];
	}

	Array< TriangleIndex > indices;
	indices.Resize( 12 );
	for ( int i = 0; i < 12; i++ )
	{
		indices[i] = quadIndices[i];
	}

	Quad.Create( attribs, indices );

	const OvrStoragePaths & paths = app->GetStoragePaths();

	Array<String> SearchPaths;
	paths.PushBackSearchPathIfValid( EST_SECONDARY_EXTERNAL_STORAGE, EFT_ROOT, "RetailMedia/", SearchPaths );
	paths.PushBackSearchPathIfValid( EST_SECONDARY_EXTERNAL_STORAGE, EFT_ROOT, "", SearchPaths );
	paths.PushBackSearchPathIfValid( EST_PRIMARY_EXTERNAL_STORAGE, EFT_ROOT, "RetailMedia/", SearchPaths );
	paths.PushBackSearchPathIfValid( EST_PRIMARY_EXTERNAL_STORAGE, EFT_ROOT, "", SearchPaths );

	StringHash<String> results = RelativeDirectoryFileList(SearchPaths, "Manga/");
	String mangaPath;

	for(StringHash<String>::Iterator it = results.Begin(); it != results.End(); ++it) {
		if(it->Second.GetCharAt(it->Second.GetLengthI()-1) == '/') {
			mangaPath = GetFullPath(SearchPaths, it->Second);
			break;
		}
	}

	Array<String> images = DirectoryFileList(mangaPath.ToCStr());
	Carousel = new PageCarousel();

	for(int i = 0; i < images.GetSizeI(); i++) {
		//WARN("%s -> %s", images[i].ToCStr(), images[i].GetExtension().ToCStr());
		if(images[i].GetExtension() == ".jpg") {
			Carousel->AddPage(new LocalPage(images[i]));
		}
	}

	// Create remote pages
	//Carousel->AddPage(new RemotePage("http://192.168.1.39:8080/000a.jpg", java));
	//Carousel->AddPage(new RemotePage("http://192.168.1.39:8080/000b.jpg", java));
	//Carousel->AddPage(new RemotePage("http://192.168.1.39:8080/000c.jpg", java));
	//Carousel->AddPage(new RemotePage("http://192.168.1.39:8080/001.jpg", java));
	//Carousel->AddPage(new RemotePage("http://192.168.1.39:8080/002.jpg", java));
	//Carousel->AddPage(new RemotePage("http://192.168.1.39:8080/003.jpg", java));
	//Carousel->AddPage(new RemotePage("http://192.168.1.39:8080/004_005.jpg", java));

/*
	Pages.Resize(11);
	Pages[0] = new Page("assets/page0006.jpg");
	Pages[1] = new Page("assets/page0007.jpg");
	Pages[2] = new Page("assets/page0008.jpg");
	Pages[3] = new Page("assets/page0009.jpg");
	Pages[4] = new Page("assets/page0010.jpg");
	Pages[5] = new Page("assets/page0011.jpg");
	Pages[6] = new Page("assets/page0012.jpg");
	Pages[7] = new Page("assets/page0013.jpg");
	Pages[8] = new Page("assets/page0014.jpg");
	Pages[9] = new Page("assets/page0015.jpg");
	Pages[10] = new Page("assets/page0016.jpg");

	Pages[0]->SetNext(Pages[1]);
	Pages[1]->SetNext(Pages[2]);
	Pages[2]->SetNext(Pages[3]);
	Pages[3]->SetNext(Pages[4]);
	Pages[4]->SetNext(Pages[5]);
	Pages[5]->SetNext(Pages[6]);
	Pages[6]->SetNext(Pages[7]);
	Pages[7]->SetNext(Pages[8]);
	Pages[8]->SetNext(Pages[9]);
	Pages[9]->SetNext(Pages[10]);

	Pages[0]->SetOffset(0);*/

	Time::Delta = 0;
	Time::Elapsed = vrapi_GetTimeInSeconds();
}

void Mangaroll::OneTimeShutdown()
{
	delete SoundEffectPlayer;
	SoundEffectPlayer = NULL;

	delete SoundEffectContext;
	SoundEffectContext = NULL;

	DeleteProgram( Program );

	delete Carousel;

}

bool Mangaroll::OnKeyEvent( const int keyCode, const int repeatCount, const KeyEventType eventType )
{
	WARN("KEY: %d", keyCode);
	if ( GuiSys->OnKeyEvent( keyCode, repeatCount, eventType ) )
	{
		return true;
	}
	return false;
}

Vector3f prevLookAt = Vector3f(0, 0, -1.0f);
float angle = 0;

float deltaAngle(float angle1, float angle2) {
    float a = angle1 - angle2;
    a += (a>180) ? -360 : (a<-180) ? 360 : 0;

    return  a;
}
Matrix4f Mangaroll::Frame( const VrFrame & vrFrame )
{
	CenterEyeViewMatrix = vrapi_GetCenterEyeViewMatrix( &app->GetHeadModelParms(), &vrFrame.Tracking, NULL );

	Vector3f v0 = Vector3f(0, 0, -1.0f);
	Vector3f lookAt = ((Quatf)vrFrame.Tracking.HeadPose.Pose.Orientation) * v0;

	float angleA = RadToDegree(atan2(prevLookAt[0], prevLookAt[2]));
	float angleB = RadToDegree(atan2(lookAt[0], lookAt[2]));
	float angleDiff = deltaAngle(angleA, angleB);
	//angleDiff *= -1;
	angle -= angleDiff;

	prevLookAt = lookAt;

	// UPDATE GLOBAL HELPERS
	Time::Delta = vrFrame.DeltaSeconds;
	Time::Elapsed = vrapi_GetTimeInSeconds();
	Frame::Current = &vrFrame;
	HMD::Direction = lookAt;

	if(vrFrame.Input.buttonReleased && Time::Elapsed - LastPress > 0.5f ) {
		AppState::Guide = (GuideType)((AppState::Guide + 1) % 3);
		LastPress = Time::Elapsed;
	}
	// ---------------------

	//WARN("Angle: %f", angle);
	// Update GUI systems after the app frame, but before rendering anything.
	GuiSys->Frame( vrFrame, CenterEyeViewMatrix );

	Carousel->Update(angle);

	return CenterEyeViewMatrix;
}

Matrix4f Mangaroll::DrawEyeView( const int eye, const float fovDegreesX, const float fovDegreesY, ovrFrameParms & frameParms )
{
	const Matrix4f eyeViewMatrix = vrapi_GetEyeViewMatrix( &app->GetHeadModelParms(), &CenterEyeViewMatrix, eye );
	const Matrix4f eyeProjectionMatrix = ovrMatrix4f_CreateProjectionFov( fovDegreesX, fovDegreesY, 0.0f, 0.0f, 0.1f, 0.0f );
	const Matrix4f eyeViewProjection = eyeProjectionMatrix * eyeViewMatrix;

	GL( glClearColor( .5f, .5f, .5f, 1.0f ) );
	GL( glClear( GL_COLOR_BUFFER_BIT ) );
	GL( glUseProgram( Program.program ) );
	GL( glUniformMatrix4fv( Program.uView, 1, GL_TRUE, eyeViewMatrix.M[0] ) );
	GL( glUniformMatrix4fv( Program.uProjection, 1, GL_TRUE, eyeProjectionMatrix.M[0] ) );

	Carousel->Draw(Matrix4f::Identity());
/*
	GL( glActiveTexture(GL_TEXTURE0) );
	GL( glBindTexture(Page1.target, Page1.texture) );
	GL( glBindVertexArray( Quad.vertexArrayObject ) );
	GL( glDrawElements( GL_TRIANGLES, Quad.indexCount, GL_UNSIGNED_SHORT, NULL ) );*/
	GL( glBindVertexArray( 0 ) );
	GL( glUseProgram( 0 ) );

	frameParms.ExternalVelocity = Scene.GetExternalVelocity();
	frameParms.Layers[VRAPI_FRAME_LAYER_TYPE_WORLD].Flags |= VRAPI_FRAME_LAYER_FLAG_CHROMATIC_ABERRATION_CORRECTION;

	GuiSys->RenderEyeView( Scene.GetCenterEyeViewMatrix(), eyeViewMatrix, eyeProjectionMatrix );

	return eyeViewProjection;
}

} // namespace OvrTemplateApp
<commit_msg>Clean up<commit_after>/************************************************************************************

Filename    :   OvrApp.cpp
Content     :   Trivial use of the application framework.
Created     :
Authors     :

Copyright   :   Copyright 2014 Oculus VR, LLC. All Rights reserved.

*************************************************************************************/

#include "Mangaroll.h"
#include "GuiSys.h"
#include "OVR_Locale.h"
#include "Kernel/OVR_Hash.h"
#include "Kernel/OVR_Types.h"
#include "Helpers.h"

#if 0
	#define GL( func )		func; EglCheckErrors();
#else
	#define GL( func )		func;
#endif

using namespace OVR;

#if defined( OVR_OS_ANDROID )
extern "C" {

jlong Java_oculus_MainActivity_nativeSetAppInterface( JNIEnv * jni, jclass clazz, jobject activity,
		jstring fromPackageName, jstring commandString, jstring uriString )
{
	LOG( "nativeSetAppInterface" );
	return (new OvrMangaroll::Mangaroll())->SetActivity( jni, clazz, activity, fromPackageName, commandString, uriString );
}

} // extern "C"

#endif

namespace OvrMangaroll
{

Mangaroll::Mangaroll()
	: SoundEffectContext( NULL )
	, SoundEffectPlayer( NULL )
	, GuiSys( OvrGuiSys::Create() )
	, Locale( NULL )
	, LastPress(0)
{
	CenterEyeViewMatrix = ovrMatrix4f_CreateIdentity();
}

Mangaroll::~Mangaroll()
{
	OvrGuiSys::Destroy( GuiSys );
}

void Mangaroll::Configure( ovrSettings & settings )
{
	settings.PerformanceParms.CpuLevel = 2;
	settings.PerformanceParms.GpuLevel = 2;
}

void Mangaroll::OneTimeInit( const char * fromPackage, const char * launchIntentJSON, const char * launchIntentURI )
{
	OVR_UNUSED( fromPackage );
	OVR_UNUSED( launchIntentJSON );
	OVR_UNUSED( launchIntentURI );
	const ovrJava * java = app->GetJava();

	SoundEffectContext = new ovrSoundEffectContext( *java->Env, java->ActivityObject );
	SoundEffectContext->Initialize();
	SoundEffectPlayer = new OvrGuiSys::ovrDummySoundEffectPlayer();

	Locale = ovrLocale::Create( *app, "default" );

	String fontName;
	GetLocale().GetString( "@string/font_name", "efigs.fnt", fontName );
	GuiSys->Init( this->app, *SoundEffectPlayer, fontName.ToCStr(), &app->GetDebugLines() );

	// --- LOAD MANGA PAGES ---
	const OvrStoragePaths & paths = app->GetStoragePaths();

	Array<String> SearchPaths;
	paths.PushBackSearchPathIfValid( EST_SECONDARY_EXTERNAL_STORAGE, EFT_ROOT, "RetailMedia/", SearchPaths );
	paths.PushBackSearchPathIfValid( EST_SECONDARY_EXTERNAL_STORAGE, EFT_ROOT, "", SearchPaths );
	paths.PushBackSearchPathIfValid( EST_PRIMARY_EXTERNAL_STORAGE, EFT_ROOT, "RetailMedia/", SearchPaths );
	paths.PushBackSearchPathIfValid( EST_PRIMARY_EXTERNAL_STORAGE, EFT_ROOT, "", SearchPaths );

	StringHash<String> results = RelativeDirectoryFileList(SearchPaths, "Manga/");
	String mangaPath;

	for(StringHash<String>::Iterator it = results.Begin(); it != results.End(); ++it) {
		if(it->Second.GetCharAt(it->Second.GetLengthI()-1) == '/') {
			mangaPath = GetFullPath(SearchPaths, it->Second);
			break;
		}
	}

	Array<String> images = DirectoryFileList(mangaPath.ToCStr());
	Carousel = new PageCarousel();

	for(int i = 0; i < images.GetSizeI(); i++) {
		//WARN("%s -> %s", images[i].ToCStr(), images[i].GetExtension().ToCStr());
		if(images[i].GetExtension() == ".jpg") {
			Carousel->AddPage(new LocalPage(images[i]));
		}
	}

	Time::Delta = 0;
	Time::Elapsed = vrapi_GetTimeInSeconds();
}

void Mangaroll::OneTimeShutdown()
{
	delete SoundEffectPlayer;
	SoundEffectPlayer = NULL;

	delete SoundEffectContext;
	SoundEffectContext = NULL;

	delete Carousel;

}

bool Mangaroll::OnKeyEvent( const int keyCode, const int repeatCount, const KeyEventType eventType )
{
	WARN("KEY: %d", keyCode);
	if ( GuiSys->OnKeyEvent( keyCode, repeatCount, eventType ) )
	{
		return true;
	}
	return false;
}

Vector3f prevLookAt = Vector3f(0, 0, -1.0f);
float angle = 0;

float deltaAngle(float angle1, float angle2) {
    float a = angle1 - angle2;
    a += (a>180) ? -360 : (a<-180) ? 360 : 0;

    return  a;
}
Matrix4f Mangaroll::Frame( const VrFrame & vrFrame )
{
	CenterEyeViewMatrix = vrapi_GetCenterEyeViewMatrix( &app->GetHeadModelParms(), &vrFrame.Tracking, NULL );

	Vector3f v0 = Vector3f(0, 0, -1.0f);
	Vector3f lookAt = ((Quatf)vrFrame.Tracking.HeadPose.Pose.Orientation) * v0;

	float angleA = RadToDegree(atan2(prevLookAt[0], prevLookAt[2]));
	float angleB = RadToDegree(atan2(lookAt[0], lookAt[2]));
	float angleDiff = deltaAngle(angleA, angleB);
	//angleDiff *= -1;
	angle -= angleDiff;

	prevLookAt = lookAt;

	// UPDATE GLOBAL HELPERS
	Time::Delta = vrFrame.DeltaSeconds;
	Time::Elapsed = vrapi_GetTimeInSeconds();
	Frame::Current = &vrFrame;
	HMD::Direction = lookAt;

	if(vrFrame.Input.buttonReleased && Time::Elapsed - LastPress > 0.5f ) {
		AppState::Guide = (GuideType)((AppState::Guide + 1) % 3);
		LastPress = Time::Elapsed;
	}
	// ---------------------

	//WARN("Angle: %f", angle);
	// Update GUI systems after the app frame, but before rendering anything.
	GuiSys->Frame( vrFrame, CenterEyeViewMatrix );

	Carousel->Update(angle);

	return CenterEyeViewMatrix;
}

Matrix4f Mangaroll::DrawEyeView( const int eye, const float fovDegreesX, const float fovDegreesY, ovrFrameParms & frameParms )
{
	const Matrix4f eyeViewMatrix = vrapi_GetEyeViewMatrix( &app->GetHeadModelParms(), &CenterEyeViewMatrix, eye );
	const Matrix4f eyeProjectionMatrix = ovrMatrix4f_CreateProjectionFov( fovDegreesX, fovDegreesY, 0.0f, 0.0f, 0.1f, 0.0f );
	const Matrix4f eyeViewProjection = eyeProjectionMatrix * eyeViewMatrix;

	GL( glClearColor( .5f, .5f, .5f, 1.0f ) );
	GL( glClear( GL_COLOR_BUFFER_BIT ) );

	Carousel->Draw(Matrix4f::Identity());

	GL( glBindVertexArray( 0 ) );
	GL( glUseProgram( 0 ) );

	frameParms.ExternalVelocity = Scene.GetExternalVelocity();
	frameParms.Layers[VRAPI_FRAME_LAYER_TYPE_WORLD].Flags |= VRAPI_FRAME_LAYER_FLAG_CHROMATIC_ABERRATION_CORRECTION;

	GuiSys->RenderEyeView( Scene.GetCenterEyeViewMatrix(), eyeViewMatrix, eyeProjectionMatrix );

	return eyeViewProjection;
}

} // namespace OvrTemplateApp
<|endoftext|>


<commit_before>#include <algorithm>
#include <iostream>
#include <list>
#include <map>
#include <string>
#include <vector>

#include "XslApplyTemplates.hpp"
#include "XslForEach.hpp"
#include "XslInstruction.hpp"
#include "XslTemplate.hpp"
#include "XslValueOf.hpp"

#include "../Xml/XmlDocument.hpp"
#include "../Xml/XmlElement.hpp"
#include "../Xml/XmlNode.hpp"
#include "../Xml/XmlText.hpp"

#include "../AppDebug.hpp"

namespace
{
    /**
     * The map of supported XSL instructions. Keys are the names of the instruction's XML tag,
     * value is a functor that applies the given template.
     */
    std::map<std::string, Xsl::Instruction const *> const xslInstructions
    {
       { "apply-templates", new Xsl::ApplyTemplates() },
       { "for-each", new Xsl::ForEach() },
       { "value-of", new Xsl::ValueOf() }
    };

    /**
     * Says which template has a deeper, more "specific", match attribute.
     * i.e : "cd/title" is more specific than "title".
     *
     * @param xslTemplateA first template element that's being compared
     * @param xslTemplateB second template element that's being compared
     *
     * @return true if xslTemplateA has a deeper or equal match than xslTemplateB, false otherwise
     */
    bool
    deeperMatch(Xml::Element const * xslTemplateA, Xml::Element const * xslTemplateB)
    {
        app_assert(xslTemplateA != nullptr);
        app_assert(xslTemplateB != nullptr);

        std::string matchA = xslTemplateA->attribute("match");
        std::string matchB = xslTemplateB->attribute("match");
        return std::count(matchA.begin(), matchA.end(), '/') >= std::count(matchB.begin(), matchB.end(), '/') ;
    }
} // Anonymous namespace

std::vector<Xml::Node *>
Xsl::applyDefaultTemplate(Xml::Node const * context, Xml::Document const & xslDoc, Xml::Log & xslLog)
{
    app_assert(context != nullptr);

    std::vector<Xml::Node *> result;
    if (!context->isElement())
    {
        result.push_back(context->clone());
        return result;
    }
    else
    {
        return findAndApplyTemplate(static_cast<Xml::Element const *>(context), xslDoc, xslLog);
    }
}

Xml::Element const *
Xsl::getTemplate(Xml::Document const & xslDoc, Xml::Element const * element)
{
    app_assert(element != nullptr);

    Xml::Element const * curTemplate = nullptr;

    for (Xml::Element const * xslTemplate : xslDoc.root()->elements())
    {
        app_assert(xslTemplate != nullptr);

        // If the template has a "deeper match" than the currently selected template, we choose is instead
        if (element->matches(xslTemplate->attribute("match")) &&
            (curTemplate == nullptr || deeperMatch(xslTemplate, curTemplate)))
        {
            curTemplate = xslTemplate;
        }
    }

    return curTemplate;
}

std::vector<Xml::Node *>
Xsl::findAndApplyTemplate(Xml::Element const * context, Xml::Document const & xslDoc, Xml::Log & xslLog)
{
    app_assert(context != nullptr);

    Xml::Element const * contextTemplate = getTemplate(xslDoc, context);

    // if the context a template matches the context, we apply it
    if (contextTemplate != nullptr)
    {
        return applyTemplate(context, xslDoc, contextTemplate, xslLog);
    }
    else
    {
        std::vector<Xml::Node *> result;
        for (auto child : context->children())
        {
            app_assert(child != nullptr);

            for (auto rNode : applyDefaultTemplate(child, xslDoc, xslLog))
            {
                app_assert(rNode != nullptr);
                result.push_back(rNode);
            }
        }
        return result;
    }
}

std::vector<Xml::Node *>
Xsl::applyTemplate(Xml::Element const * context, Xml::Document const & xslDoc, Xml::Element const * xslTemplate, Xml::Log & xslLog)
{
    app_assert(context != nullptr);
    app_assert(xslTemplate != nullptr);

    std::vector<Xml::Node *> result;

    // We iterate over the XSL template's children
    for (Xml::Node * templateNode : xslTemplate->children())
    {
        app_assert(templateNode != nullptr);

        if (!templateNode->isElement())
        {
            result.push_back(templateNode->clone());
            continue;
        }

        auto templateElement = static_cast<Xml::Element const *>(templateNode);
        if (templateElement->namespaceName() == "xsl")
        {
            Xml::Element const * xslElement = templateElement;
            auto instructionPair = xslInstructions.find(xslElement->name());

            if (instructionPair == xslInstructions.end()) {
                // Unknown XSL instruction
                xslLog.append("Unknown XSL instruction: " + xslElement->name() + "\n");
                continue;
            }

            Xsl::Instruction const * xslInstruction = instructionPair->second;

            app_assert(xslInstruction != nullptr);

            std::vector <Xml::Node *> resultInstruction = (*xslInstruction)(context, xslDoc, xslElement, xslLog);
            for (auto node : resultInstruction)
            {
                app_assert(node != nullptr);
                result.push_back(node);
            }
        }
        else
        {
            auto clonedElement = static_cast<Xml::Element *>(templateElement->clone());
            auto resultNodes = applyTemplate(context, xslDoc, templateElement, xslLog);

            app_assert(clonedElement != nullptr);

            for (auto rNode : resultNodes) {
                app_assert(rNode != nullptr);
                clonedElement->appendNode(rNode);
            }

            result.push_back(clonedElement);
        }
    }

    return result;
}
<commit_msg>FIX : Support for PI/CDATA/COMMENTS/TEXT in Xsl<commit_after>#include <algorithm>
#include <iostream>
#include <list>
#include <map>
#include <string>
#include <vector>

#include "XslApplyTemplates.hpp"
#include "XslForEach.hpp"
#include "XslInstruction.hpp"
#include "XslTemplate.hpp"
#include "XslValueOf.hpp"

#include "../Xml/XmlDocument.hpp"
#include "../Xml/XmlElement.hpp"
#include "../Xml/XmlForward.hpp"
#include "../Xml/XmlNode.hpp"
#include "../Xml/XmlText.hpp"

#include "../AppDebug.hpp"

namespace
{
    /**
     * The map of supported XSL instructions. Keys are the names of the instruction's XML tag,
     * value is a functor that applies the given template.
     */
    std::map<std::string, Xsl::Instruction const *> const xslInstructions
    {
       { "apply-templates", new Xsl::ApplyTemplates() },
       { "for-each", new Xsl::ForEach() },
       { "value-of", new Xsl::ValueOf() }
    };

    /**
     * Says which template has a deeper, more "specific", match attribute.
     * i.e : "cd/title" is more specific than "title".
     *
     * @param xslTemplateA first template element that's being compared
     * @param xslTemplateB second template element that's being compared
     *
     * @return true if xslTemplateA has a deeper or equal match than xslTemplateB, false otherwise
     */
    bool
    deeperMatch(Xml::Element const * xslTemplateA, Xml::Element const * xslTemplateB)
    {
        app_assert(xslTemplateA != nullptr);
        app_assert(xslTemplateB != nullptr);

        std::string matchA = xslTemplateA->attribute("match");
        std::string matchB = xslTemplateB->attribute("match");
        return std::count(matchA.begin(), matchA.end(), '/') >= std::count(matchB.begin(), matchB.end(), '/') ;
    }
} // Anonymous namespace

std::vector<Xml::Node *>
Xsl::applyDefaultTemplate(Xml::Node const * context, Xml::Document const & xslDoc, Xml::Log & xslLog)
{
    app_assert(context != nullptr);

    std::vector<Xml::Node *> result;

    Xml::ObjectLabel label = context->objectLabel();
    if (label == Xml::ObjectLabel::Text || label == Xml::ObjectLabel::CharacterData ||
        label == Xml::ObjectLabel::ProcessingInstruction)
    {
        result.push_back(context->clone());
    }
    else
    {
        result = findAndApplyTemplate(static_cast<Xml::Element const *>(context), xslDoc, xslLog);
    }

    return result;
}

Xml::Element const *
Xsl::getTemplate(Xml::Document const & xslDoc, Xml::Element const * element)
{
    app_assert(element != nullptr);

    Xml::Element const * curTemplate = nullptr;

    for (Xml::Element const * xslTemplate : xslDoc.root()->elements())
    {
        app_assert(xslTemplate != nullptr);

        // If the template has a "deeper match" than the currently selected template, we choose is instead
        if (element->matches(xslTemplate->attribute("match")) &&
            (curTemplate == nullptr || deeperMatch(xslTemplate, curTemplate)))
        {
            curTemplate = xslTemplate;
        }
    }

    return curTemplate;
}

std::vector<Xml::Node *>
Xsl::findAndApplyTemplate(Xml::Element const * context, Xml::Document const & xslDoc, Xml::Log & xslLog)
{
    app_assert(context != nullptr);

    Xml::Element const * contextTemplate = getTemplate(xslDoc, context);

    // if the context a template matches the context, we apply it
    if (contextTemplate != nullptr)
    {
        return applyTemplate(context, xslDoc, contextTemplate, xslLog);
    }
    else
    {
        std::vector<Xml::Node *> result;
        for (auto child : context->children())
        {
            app_assert(child != nullptr);

            for (auto rNode : applyDefaultTemplate(child, xslDoc, xslLog))
            {
                app_assert(rNode != nullptr);
                result.push_back(rNode);
            }
        }
        return result;
    }
}

std::vector<Xml::Node *>
Xsl::applyTemplate(Xml::Element const * context, Xml::Document const & xslDoc, Xml::Element const * xslTemplate, Xml::Log & xslLog)
{
    app_assert(context != nullptr);
    app_assert(xslTemplate != nullptr);

    std::vector<Xml::Node *> result;

    // We iterate over the XSL template's children
    for (Xml::Node * templateNode : xslTemplate->children())
    {
        app_assert(templateNode != nullptr);

        if (!templateNode->isElement())
        {
            Xml::ObjectLabel label = context->objectLabel();
            if (label == Xml::ObjectLabel::Text || label == Xml::ObjectLabel::CharacterData) {
                result.push_back(templateNode->clone());
            }
            continue;
        }

        auto templateElement = static_cast<Xml::Element const *>(templateNode);
        if (templateElement->namespaceName() == "xsl")
        {
            Xml::Element const * xslElement = templateElement;
            auto instructionPair = xslInstructions.find(xslElement->name());

            if (instructionPair == xslInstructions.end()) {
                // Unknown XSL instruction
                xslLog.append("Unknown XSL instruction: " + xslElement->name() + "\n");
                continue;
            }

            Xsl::Instruction const * xslInstruction = instructionPair->second;

            app_assert(xslInstruction != nullptr);

            std::vector <Xml::Node *> resultInstruction = (*xslInstruction)(context, xslDoc, xslElement, xslLog);
            for (auto node : resultInstruction)
            {
                app_assert(node != nullptr);
                result.push_back(node);
            }
        }
        else
        {
            auto clonedElement = static_cast<Xml::Element *>(templateElement->clone());
            auto resultNodes = applyTemplate(context, xslDoc, templateElement, xslLog);

            app_assert(clonedElement != nullptr);

            for (auto rNode : resultNodes) {
                app_assert(rNode != nullptr);
                clonedElement->appendNode(rNode);
            }

            result.push_back(clonedElement);
        }
    }

    return result;
}
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
//  TEST    Foundation::Execution::ThreadSafetyBuiltinObject
#include    "Stroika/Foundation/StroikaPreComp.h"

#include    <iostream>
#include    <mutex>

#include    "Stroika/Foundation/Characters/String.h"
#include    "Stroika/Foundation/Containers/Sequence.h"
#include    "Stroika/Foundation/Containers/Set.h"
#include    "Stroika/Foundation/Execution/ExternallySynchronizedLock.h"
#include    "Stroika/Foundation/Execution/Sleep.h"
#include    "Stroika/Foundation/Execution/SpinLock.h"
#include    "Stroika/Foundation/Execution/Thread.h"
#include    "Stroika/Foundation/Execution/ThreadPool.h"
#include    "Stroika/Foundation/Execution/WaitableEvent.h"
#include    "Stroika/Foundation/Execution/TimeOutException.h"
#include    "Stroika/Foundation/Math/Common.h"

#include    "../TestHarness/TestHarness.h"

using   namespace   Stroika::Foundation;
using   namespace   Characters;
using   namespace   Containers;

using   Execution::ExternallySynchronizedLock;
using   Execution::Thread;
using   Execution::WaitableEvent;

namespace   {
    namespace AssignAndIterateAtSameTimeTest_ {

        template    <typename ITERABLE_TYPE>
        void    DoIt_ (ITERABLE_TYPE elt1, ITERABLE_TYPE elt2, unsigned int repeatCount)
        {
            /*
             *  To REALLY this this code for thread-safety, use ExternallySynchronizedLock, but to verify it works
             *  without worrying about races, just use mutex.
             */
            //ExternallySynchronizedLock lock;
            mutex lock;

            ITERABLE_TYPE   oneToKeepOverwriting = elt1;
            using ElementType   =   typename ITERABLE_TYPE::ElementType;
            Thread  iterateThread = [&oneToKeepOverwriting, repeatCount, &lock] () {
                for (unsigned int i = 0; i < repeatCount; ++i) {
                    lock_guard<decltype(lock)> critSec (lock);
                    for (ElementType e :  oneToKeepOverwriting) {
                        ElementType e2 = e; // do something
                    }
                }
            };
            Thread  overwriteThread = [&oneToKeepOverwriting, elt1, elt2, repeatCount, &lock] () {
                for (unsigned int i = 0; i < repeatCount; ++i) {
                    for (int ii = 0; ii <= 100; ++ii) {
                        if (Math::IsOdd (ii)) {
                            lock_guard<decltype(lock)> critSec (lock);
                            oneToKeepOverwriting = elt1;
                        }
                        else {
                            lock_guard<decltype(lock)> critSec (lock);
                            oneToKeepOverwriting = elt2;
                        }
                    }
                }
            };
            iterateThread.Start ();
            overwriteThread.Start ();
            iterateThread.WaitForDone ();
            overwriteThread.WaitForDone ();
        }
    }

    void    AssignAndIterateAtSameTimeTest_1_ ()
    {
        Debug::TraceContextBumper traceCtx (SDKSTR ("AssignAndIterateAtSameTimeTest_1_"));
        AssignAndIterateAtSameTimeTest_::DoIt_<String> (String (L"123456789"), String (L"abcdedfghijkqlmopqrstuvwxyz"), 500);
        AssignAndIterateAtSameTimeTest_::DoIt_<Sequence<int>> (Sequence<int> ({1, 3, 4, 5, 6, 33, 12, 13}), Sequence<int> ({4, 5, 6, 33, 12, 13, 1, 3, 99, 33, 4, 5}), 500);
        AssignAndIterateAtSameTimeTest_::DoIt_<Set<int>> (Set<int> ({1, 3, 4, 5, 6, 33, 12, 13}), Set<int> ({4, 5, 6, 33, 12, 13, 34, 388, 3, 99, 33, 4, 5}), 500);
    }
}

namespace   {
    void    DoRegressionTests_ ()
    {
        AssignAndIterateAtSameTimeTest_1_ ();
    }
}

int     main (int argc, const char* argv[])
{
    Stroika::TestHarness::Setup ();
    Stroika::TestHarness::PrintPassOrFail (DoRegressionTests_);
    return EXIT_SUCCESS;
}
<commit_msg>more tweaks to ThreadSafetyBuiltinObject regtest<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
//  TEST    Foundation::Execution::ThreadSafetyBuiltinObject
#include    "Stroika/Foundation/StroikaPreComp.h"

#include    <iostream>
#include    <mutex>

#include    "Stroika/Foundation/Characters/String.h"
#include    "Stroika/Foundation/Containers/Sequence.h"
#include    "Stroika/Foundation/Containers/Set.h"
#include    "Stroika/Foundation/Execution/ExternallySynchronizedLock.h"
#include    "Stroika/Foundation/Execution/Sleep.h"
#include    "Stroika/Foundation/Execution/SpinLock.h"
#include    "Stroika/Foundation/Execution/Thread.h"
#include    "Stroika/Foundation/Execution/ThreadPool.h"
#include    "Stroika/Foundation/Execution/WaitableEvent.h"
#include    "Stroika/Foundation/Execution/TimeOutException.h"
#include    "Stroika/Foundation/Math/Common.h"

#include    "../TestHarness/TestHarness.h"

using   namespace   Stroika::Foundation;
using   namespace   Characters;
using   namespace   Containers;

using   Execution::ExternallySynchronizedLock;
using   Execution::Thread;
using   Execution::WaitableEvent;

namespace   {
    namespace AssignAndIterateAtSameTimeTest_ {

        template    <typename ITERABLE_TYPE>
        void    DoIt_ (ITERABLE_TYPE elt1, ITERABLE_TYPE elt2, unsigned int repeatCount)
        {
            /*
             *  To REALLY this this code for thread-safety, use ExternallySynchronizedLock, but to verify it works
             *  without worrying about races, just use mutex.
             */
			struct no_lock_ {
				void lock () {}
				void unlock () {}
			};
            //no_lock_ lock ;
            mutex lock;

            ITERABLE_TYPE   oneToKeepOverwriting = elt1;
            using ElementType   =   typename ITERABLE_TYPE::ElementType;
            Thread  iterateThread = [&oneToKeepOverwriting, repeatCount, &lock] () {
                for (unsigned int i = 0; i < repeatCount; ++i) {
                    lock_guard<decltype(lock)> critSec (lock);
                    for (ElementType e :  oneToKeepOverwriting) {
                        ElementType e2 = e; // do something
                    }
                }
            };
            Thread  overwriteThread = [&oneToKeepOverwriting, elt1, elt2, repeatCount, &lock] () {
                for (unsigned int i = 0; i < repeatCount; ++i) {
                    for (int ii = 0; ii <= 100; ++ii) {
                        if (Math::IsOdd (ii)) {
                            lock_guard<decltype(lock)> critSec (lock);
                            oneToKeepOverwriting = elt1;
                        }
                        else {
                            lock_guard<decltype(lock)> critSec (lock);
                            oneToKeepOverwriting = elt2;
                        }
                    }
                }
            };
            iterateThread.Start ();
            overwriteThread.Start ();
            iterateThread.WaitForDone ();
            overwriteThread.WaitForDone ();
        }
    }

    void    AssignAndIterateAtSameTimeTest_1_ ()
    {
        Debug::TraceContextBumper traceCtx (SDKSTR ("AssignAndIterateAtSameTimeTest_1_"));
        AssignAndIterateAtSameTimeTest_::DoIt_<String> (String (L"123456789"), String (L"abcdedfghijkqlmopqrstuvwxyz"), 500);
        AssignAndIterateAtSameTimeTest_::DoIt_<Sequence<int>> (Sequence<int> ({1, 3, 4, 5, 6, 33, 12, 13}), Sequence<int> ({4, 5, 6, 33, 12, 13, 1, 3, 99, 33, 4, 5}), 500);
		AssignAndIterateAtSameTimeTest_::DoIt_<Set<int>> (Set<int> ({1, 3, 4, 5, 6, 33, 12, 13}), Set<int> ({4, 5, 6, 33, 12, 13, 34, 388, 3, 99, 33, 4, 5}), 500);
    }
}

namespace   {
    void    DoRegressionTests_ ()
    {
        AssignAndIterateAtSameTimeTest_1_ ();
    }
}

int     main (int argc, const char* argv[])
{
    Stroika::TestHarness::Setup ();
    Stroika::TestHarness::PrintPassOrFail (DoRegressionTests_);
    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include "smc_compiler.h"
#include "gen.h"

using namespace std;

template <typename T>
typename T::mapped_type get(T const& map, typename T::key_type const& key)
{
    typename T::const_iterator iter(map.find(key));
    return iter != map.end() ? iter->second : typename T::mapped_type();
}

static void generate_state_map(state_map_t const& state_map, std::string const& package_name, std::string const& fsmclass, std::string const& class_name, std::map<string, string> const& action_map, transition_set_t const& transition_set, std::map<std::string, parameter_list_t> const& transition_params);

string declare_param(std::map<std::string, parameter_list_t> const& transition_params, std::string const transition_name) {
    parameter_list_t plist = get(transition_params, transition_name);
    string params = "";
    for (auto& param : plist) {
        if (params != "") {
            params += ", ";
        }
        params += param.get_name() + ":" + param.get_type();
    }
    return params;
}

string call_param(std::map<std::string, parameter_list_t> const& transition_params, std::string const transition_name) {
    parameter_list_t plist = get(transition_params, transition_name);
    string call_params = "";
    for (auto& param : plist) {
        call_params += ", " + param.get_name() + ": " + param.get_name();
    }
    return call_params;
}

void gen_swift(
    std::string const& package_name,
    std::string const& fsmclass,
    state_map_list_t const& state_map_list,
    std::string const& start_map,
    std::string const& start_state,
    transition_set_t const& transition_set,
    std::string const& class_name,
    std::map<std::string, std::string> const& action_map,
    std::vector<std::string> const& include_list,
    std::vector<std::string> const& import_list,
    std::map<std::string, parameter_list_t> const& transition_params)
{
    string full_fsm_name = package_name + "_" + fsmclass;

    cout << "// -*- tab-width: 4; -*-\n";
    cout << "// -*- coding: utf-8 -*-\n";
    cout << "\n";
    cout << "//\n";
    cout << "// This file is automatically generated by State Machine Generator.\n";
    cout << "//\n";
    cout << "\n";

    cout << "import Foundation\n";

    for (auto&& include : include_list) {
        cout << "// #include <" << include << ">\n";
    }

    for (auto&& import: import_list) {
        cout << "import " << import << "\n";
    }
    cout << "\n";

//    cout << "public protocol " << package_name << "_Action {\n";
//    for (auto const& action : action_map) {
//        cout << "    func " << action.second << "\n";
//    }
//    cout << "}\n\n";

//    cout << "/*\n";
//    cout << "public class " << class_name << " : " << package_name << "_Action {\n";
//    for (auto const& action : action_map) {
//        cout << "    public func " << action.second << " {}\n";
//    }
//    cout << "}\n";
//    cout << "*/\n";

    cout
        << "\n"
        << "public class " << full_fsm_name << " {\n"
        << "\n"
        << "    private var currentState : " << package_name << "_" << start_map << "_State?\n"
        << "    private var previousState : " << package_name << "_" << start_map << "_State?\n"
        << "    public var debugMode = false\n"
        << "    weak var ctxt : " << class_name << "?\n"
        << "\n"
        << "    public init(context: " << class_name << ") {\n"
        << "        self.currentState = " << package_name << "_" << start_map << "._" << start_state << "\n"
        << "        self.ctxt = context\n"
        << "    }\n"
        << "\n"
        << "    public func enterStartState() {\n"
        << "        if let context = ctxt {\n"
        << "            currentState!.Entry(self, ctxt: context)\n"
        << "        }\n"
        << "    }\n"
        << "\n"
        << "    private func setState(state:" << package_name << "_" << start_map << "_State) {\n"
        << "        currentState = state;\n"
        << "        if (debugMode) {\n"
        << "            NSLog(\"ENTER STATE: %@\", state.getName())\n"
        << "        }\n"
        << "    }\n"
        ;

    for (auto&& transition_name : transition_set) {
        std::string params = declare_param(transition_params, transition_name);
        std::string call_params = call_param(transition_params, transition_name);

        cout << "\n";
        cout << "    public func " << transition_name << "(" << params << ") {\n";
        cout << "        if let context = ctxt {\n";
        cout << "            currentState!." << transition_name << "(self, ctxt: context" << call_params << ")\n";
        cout << "        }\n";
        cout << "    }\n";
    }

    cout << "\n";
    cout << "}\n";
    cout << "\n";
    cout << "\n";
    cout << "\n";

    for (auto&& state_map : state_map_list) {
        generate_state_map(state_map, package_name, fsmclass, class_name, action_map, transition_set, transition_params);
    }
}

static void generate_state_map(state_map_t const& state_map, std::string const& package_name, std::string const& fsmclass, std::string const& class_name, std::map<string, string> const& action_map, transition_set_t const& transition_set, std::map<std::string, parameter_list_t> const& transition_params)
{
    string full_fsm_name = package_name + "_" + fsmclass;

    string const& state_map_name = package_name + "_" + state_map.get_state_map_name();
    state_list_t const& state_list = state_map.get_state_list();

    // カスタムアクションの出力とステート遷移の出力
    auto generate_transition = [&](transition_t const& transition, int indent)
    {
        intented_out out(cout, indent);

        // 遷移先のステートがある場合には Exit() を出力する。
        if ( !transition.get_next_state().empty()) {
            out << "fsm.currentState!.Exit(fsm, ctxt: ctxt)\n";
        }

        // 現在のステートをNULLにセットする。
        out << "fsm.previousState = fsm.currentState\n";

        // カスタムアクションを出力する。
        if ( !transition.get_action_list().empty()) {
            out << "fsm.currentState = nil\n";
            out << "//try {" << "\n";
            out << "// Custom action" << "\n";
        }

        for (auto const& action : transition.get_action_list()) {
            out << "ctxt." << action.func() << "\n";
        }

        // 次の遷移先への移動をfinally区の中に入れるかどうか
        int next_state_indent = 0;

        if ( !transition.get_action_list().empty()) {
            out << "//} finally {" << "\n";
            //next_state_indent++;
        }

        // 遷移先のステートがある場合には Entry() を出力する。
        if (transition.get_next_state().empty()) {
             out(next_state_indent) << "fsm.currentState = fsm.previousState\n";
        }
        else {
             out(next_state_indent) << "fsm.setState(" << state_map_name << "._" << transition.get_next_state() << ")\n";
             out(next_state_indent) << "fsm.currentState!.Entry(fsm, ctxt: ctxt)\n";
        }

        if ( !transition.get_action_list().empty()) {
            out << "//}" << "\n";
        }
    };

    const string state_map_protocol_name = state_map_name + "_State";
    cout << "private protocol " << state_map_protocol_name << " {\n";
    cout << "    func getName() -> String\n";
    cout << "    func Entry(fsm:" << full_fsm_name << ", ctxt:" << class_name << ")\n";
    cout << "    func Exit(fsm:" << full_fsm_name << ", ctxt:" << class_name << ")\n";
    cout << "    func Default(fsm:" << full_fsm_name << ", ctxt:" << class_name << ")\n";
    for (auto&& transition_name : transition_set) {
        if (transition_name != "Default") {
            string params = declare_param(transition_params, transition_name);
            if (params != "") { params = ", " + params; }
            cout << "    func " << transition_name << "(fsm:" << full_fsm_name << ", ctxt:" << class_name << params << ")\n";
        }
    }
    cout << "}\n";

    intented_out out(cout, 0);
    bool need_comma = false;
    out << "let " << state_map_name << " = _" << state_map_name << "()\n";
    cout << "\n";
    out << "public class _" << state_map_name << " {\n";
    for (auto const& state : state_list) {
        cout << "    let _" << state.get_state_name() << " = " << state.get_state_name() << "()\n";
    }

    cout << "\n";
    const string base_state_impl_name = state_map_name + "_StateImpl";

    out(1) << "public class " << base_state_impl_name << " : " << state_map_protocol_name << " {\n";
    out(2) << "func getName() -> String { return \"\" }\n";
    out(2) << "func Entry(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") {}\n";
    out(2) << "func Exit(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") {}\n";
    out(2) << "func Default(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") { abort() }\n";
    for (auto&& transition_name : transition_set) {
        if (transition_name != "Default") {
            string params = declare_param(transition_params, transition_name);
            string calls = call_param(transition_params, transition_name);
            if (params != "") { params = ", " + params; }
            out(2) << "func " << transition_name << "(fsm:" << full_fsm_name << ", ctxt:" << class_name << params << ") {\n";
            out(3) << "Default(fsm, ctxt: ctxt)\n";
            out(2) << "}\n";
        }
    }
    out(1) << "}\n";

    bool default_state_present = false;

    for (auto const& state : state_list) {
        bool default_state = state.get_state_name() == "Default";
        const string func_decl = "override public func ";
        if (default_state)
            default_state_present = true;

        cout << "\n";
        out(1) << "public class " << state.get_state_name() << " : "<< (default_state ? base_state_impl_name : "Default") << " {\n";
        out(2) << func_decl << "getName() -> String { return \"" << state.get_state_name() << "\" }\n\n";
        out(2) << func_decl << "Entry(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") {\n";

        for (auto&& action : state.get_entry()) {
             out(3) << "ctxt." << action.func() << "\n";
        }
        out(2) << "}\n";
        cout << "\n";
        out(2) << func_decl << "Exit(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") {\n";
        for (auto const& action : state.get_exit()) {
             out(3) << "ctxt." << action.func() << "\n";
        }
        out(2) << "}\n";

        for (auto const& transition_name_list_pair : state.get_transitions()) {
            string const& transition_name = transition_name_list_pair.first;

            cout << "\n";
            out(2) << func_decl << transition_name << "(fsm:" << full_fsm_name << ", ctxt:" << class_name;
            for (auto&& parameter : transition_name_list_pair.second.at(0).get_parameter_list()) {
                cout << ", " << parameter.get_name() << ":" << parameter.get_type();
            }
            cout << ") {\n";

            bool else_block = false;
            for (auto&& transition : transition_name_list_pair.second) {
                if ( !transition.get_guard().empty()) {
                    out(3) << (else_block ? "else if" : "if") << " (" << transition.get_guard() << ") {\n";

                    generate_transition(transition, 5);

                    out(3) << "}\n";
                    else_block = true;
                }
                else {
                    if (else_block) {
                        out(3) << "else {\n";
                    }

                    generate_transition(transition, else_block ? 4 : 3);

                    if (else_block) {
                        out(3) << "}\n";
                    }
                }
            }

            out(2) << "}\n";
        }

        cout << "\n";
        out(1) << "}\n"
             ;
        need_comma = true;
    }

    if ( !default_state_present) {
        cout << "\n";
        out(1) << "public class Default : " << state_map_name << "_State {\n";
        out(2) << "public func getName() -> String { return \"DefaultState\" }\n\n";
        out(2) << "public func Entry(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") {}\n";
        out(2) << "public func Exit(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") {}\n";

        for (auto&& transition_name : transition_set) {
             out(2) << "public func " << transition_name << "(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") {}\n";
        }
        out(1) << "}\n";
    }

    cout << "}" << endl;

}
<commit_msg>Refactoring.<commit_after>#include <iostream>
#include <string>
#include "smc_compiler.h"
#include "gen.h"

using namespace std;

static void generate_state_map(state_map_t const& state_map, std::string const& package_name, std::string const& fsmclass, std::string const& class_name, std::map<string, string> const& action_map, transition_set_t const& transition_set, std::map<std::string, parameter_list_t> const& transition_params);

string declare_param(std::map<std::string, parameter_list_t> const& transition_params, std::string const transition_name) {
    auto ite = transition_params.find(transition_name);
    if (ite == transition_params.end())
        return {};

    string params;
    for (auto const& param : ite->second) {
        if ( !params.empty()) {
            params += ", ";
        }
        params += param.get_name() + ":" + param.get_type();
    }
    return params;
}

string call_param(std::map<std::string, parameter_list_t> const& transition_params, std::string const transition_name) {
    auto ite = transition_params.find(transition_name);
    if (ite == transition_params.end())
        return {};

    string call_params;
    for (auto& param : ite->second) {
        call_params += ", " + param.get_name() + ": " + param.get_name();
    }
    return call_params;
}

void gen_swift(
    std::string const& package_name,
    std::string const& fsmclass,
    state_map_list_t const& state_map_list,
    std::string const& start_map,
    std::string const& start_state,
    transition_set_t const& transition_set,
    std::string const& class_name,
    std::map<std::string, std::string> const& action_map,
    std::vector<std::string> const& include_list,
    std::vector<std::string> const& import_list,
    std::map<std::string, parameter_list_t> const& transition_params)
{
    string full_fsm_name = package_name + "_" + fsmclass;

    cout << "// -*- tab-width: 4; -*-\n";
    cout << "// -*- coding: utf-8 -*-\n";
    cout << "\n";
    cout << "//\n";
    cout << "// This file is automatically generated by State Machine Generator.\n";
    cout << "//\n";
    cout << "\n";

    cout << "import Foundation\n";

    for (auto&& include : include_list) {
        cout << "// #include <" << include << ">\n";
    }

    for (auto&& import: import_list) {
        cout << "import " << import << "\n";
    }
    cout << "\n";

//    cout << "public protocol " << package_name << "_Action {\n";
//    for (auto const& action : action_map) {
//        cout << "    func " << action.second << "\n";
//    }
//    cout << "}\n\n";

//    cout << "/*\n";
//    cout << "public class " << class_name << " : " << package_name << "_Action {\n";
//    for (auto const& action : action_map) {
//        cout << "    public func " << action.second << " {}\n";
//    }
//    cout << "}\n";
//    cout << "*/\n";

    cout
        << "\n"
        << "public class " << full_fsm_name << " {\n"
        << "\n"
        << "    private var currentState : " << package_name << "_" << start_map << "_State?\n"
        << "    private var previousState : " << package_name << "_" << start_map << "_State?\n"
        << "    public var debugMode = false\n"
        << "    weak var ctxt : " << class_name << "?\n"
        << "\n"
        << "    public init(context: " << class_name << ") {\n"
        << "        self.currentState = " << package_name << "_" << start_map << "._" << start_state << "\n"
        << "        self.ctxt = context\n"
        << "    }\n"
        << "\n"
        << "    public func enterStartState() {\n"
        << "        if let context = ctxt {\n"
        << "            currentState!.Entry(self, ctxt: context)\n"
        << "        }\n"
        << "    }\n"
        << "\n"
        << "    private func setState(state:" << package_name << "_" << start_map << "_State) {\n"
        << "        currentState = state;\n"
        << "        if (debugMode) {\n"
        << "            NSLog(\"ENTER STATE: %@\", state.getName())\n"
        << "        }\n"
        << "    }\n"
        ;

    for (auto&& transition_name : transition_set) {
        std::string params = declare_param(transition_params, transition_name);
        std::string call_params = call_param(transition_params, transition_name);

        cout << "\n";
        cout << "    public func " << transition_name << "(" << params << ") {\n";
        cout << "        if let context = ctxt {\n";
        cout << "            currentState!." << transition_name << "(self, ctxt: context" << call_params << ")\n";
        cout << "        }\n";
        cout << "    }\n";
    }

    cout << "\n";
    cout << "}\n";
    cout << "\n";
    cout << "\n";
    cout << "\n";

    for (auto&& state_map : state_map_list) {
        generate_state_map(state_map, package_name, fsmclass, class_name, action_map, transition_set, transition_params);
    }
}

static void generate_state_map(state_map_t const& state_map, std::string const& package_name, std::string const& fsmclass, std::string const& class_name, std::map<string, string> const& action_map, transition_set_t const& transition_set, std::map<std::string, parameter_list_t> const& transition_params)
{
    string full_fsm_name = package_name + "_" + fsmclass;

    string const& state_map_name = package_name + "_" + state_map.get_state_map_name();
    state_list_t const& state_list = state_map.get_state_list();

    // カスタムアクションの出力とステート遷移の出力
    auto generate_transition = [&](transition_t const& transition, int indent)
    {
        intented_out out(cout, indent);

        // 遷移先のステートがある場合には Exit() を出力する。
        if ( !transition.get_next_state().empty()) {
            out << "fsm.currentState!.Exit(fsm, ctxt: ctxt)\n";
        }

        // 現在のステートをNULLにセットする。
        out << "fsm.previousState = fsm.currentState\n";

        // カスタムアクションを出力する。
        if ( !transition.get_action_list().empty()) {
            out << "fsm.currentState = nil\n";
            out << "//try {" << "\n";
            out << "// Custom action" << "\n";
        }

        for (auto const& action : transition.get_action_list()) {
            out << "ctxt." << action.func() << "\n";
        }

        // 次の遷移先への移動をfinally区の中に入れるかどうか
        int next_state_indent = 0;

        if ( !transition.get_action_list().empty()) {
            out << "//} finally {" << "\n";
            //next_state_indent++;
        }

        // 遷移先のステートがある場合には Entry() を出力する。
        if (transition.get_next_state().empty()) {
             out(next_state_indent) << "fsm.currentState = fsm.previousState\n";
        }
        else {
             out(next_state_indent) << "fsm.setState(" << state_map_name << "._" << transition.get_next_state() << ")\n";
             out(next_state_indent) << "fsm.currentState!.Entry(fsm, ctxt: ctxt)\n";
        }

        if ( !transition.get_action_list().empty()) {
            out << "//}" << "\n";
        }
    };

    const string state_map_protocol_name = state_map_name + "_State";
    cout << "private protocol " << state_map_protocol_name << " {\n";
    cout << "    func getName() -> String\n";
    cout << "    func Entry(fsm:" << full_fsm_name << ", ctxt:" << class_name << ")\n";
    cout << "    func Exit(fsm:" << full_fsm_name << ", ctxt:" << class_name << ")\n";
    cout << "    func Default(fsm:" << full_fsm_name << ", ctxt:" << class_name << ")\n";
    for (auto&& transition_name : transition_set) {
        if (transition_name != "Default") {
            string params = declare_param(transition_params, transition_name);
            if (params != "") { params = ", " + params; }
            cout << "    func " << transition_name << "(fsm:" << full_fsm_name << ", ctxt:" << class_name << params << ")\n";
        }
    }
    cout << "}\n";

    intented_out out(cout, 0);
    bool need_comma = false;
    out << "let " << state_map_name << " = _" << state_map_name << "()\n";
    cout << "\n";
    out << "public class _" << state_map_name << " {\n";
    for (auto const& state : state_list) {
        cout << "    let _" << state.get_state_name() << " = " << state.get_state_name() << "()\n";
    }

    cout << "\n";
    const string base_state_impl_name = state_map_name + "_StateImpl";

    out(1) << "public class " << base_state_impl_name << " : " << state_map_protocol_name << " {\n";
    out(2) << "func getName() -> String { return \"\" }\n";
    out(2) << "func Entry(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") {}\n";
    out(2) << "func Exit(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") {}\n";
    out(2) << "func Default(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") { abort() }\n";
    for (auto&& transition_name : transition_set) {
        if (transition_name != "Default") {
            string params = declare_param(transition_params, transition_name);
            string calls = call_param(transition_params, transition_name);
            if (params != "") { params = ", " + params; }
            out(2) << "func " << transition_name << "(fsm:" << full_fsm_name << ", ctxt:" << class_name << params << ") {\n";
            out(3) << "Default(fsm, ctxt: ctxt)\n";
            out(2) << "}\n";
        }
    }
    out(1) << "}\n";

    bool default_state_present = false;

    for (auto const& state : state_list) {
        bool default_state = state.get_state_name() == "Default";
        const string func_decl = "override public func ";
        if (default_state)
            default_state_present = true;

        cout << "\n";
        out(1) << "public class " << state.get_state_name() << " : "<< (default_state ? base_state_impl_name : "Default") << " {\n";
        out(2) << func_decl << "getName() -> String { return \"" << state.get_state_name() << "\" }\n\n";
        out(2) << func_decl << "Entry(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") {\n";

        for (auto&& action : state.get_entry()) {
             out(3) << "ctxt." << action.func() << "\n";
        }
        out(2) << "}\n";
        cout << "\n";
        out(2) << func_decl << "Exit(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") {\n";
        for (auto const& action : state.get_exit()) {
             out(3) << "ctxt." << action.func() << "\n";
        }
        out(2) << "}\n";

        for (auto const& transition_name_list_pair : state.get_transitions()) {
            string const& transition_name = transition_name_list_pair.first;

            cout << "\n";
            out(2) << func_decl << transition_name << "(fsm:" << full_fsm_name << ", ctxt:" << class_name;
            for (auto&& parameter : transition_name_list_pair.second.at(0).get_parameter_list()) {
                cout << ", " << parameter.get_name() << ":" << parameter.get_type();
            }
            cout << ") {\n";

            bool else_block = false;
            for (auto&& transition : transition_name_list_pair.second) {
                if ( !transition.get_guard().empty()) {
                    out(3) << (else_block ? "else if" : "if") << " (" << transition.get_guard() << ") {\n";

                    generate_transition(transition, 5);

                    out(3) << "}\n";
                    else_block = true;
                }
                else {
                    if (else_block) {
                        out(3) << "else {\n";
                    }

                    generate_transition(transition, else_block ? 4 : 3);

                    if (else_block) {
                        out(3) << "}\n";
                    }
                }
            }

            out(2) << "}\n";
        }

        cout << "\n";
        out(1) << "}\n"
             ;
        need_comma = true;
    }

    if ( !default_state_present) {
        cout << "\n";
        out(1) << "public class Default : " << state_map_name << "_State {\n";
        out(2) << "public func getName() -> String { return \"DefaultState\" }\n\n";
        out(2) << "public func Entry(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") {}\n";
        out(2) << "public func Exit(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") {}\n";

        for (auto&& transition_name : transition_set) {
             out(2) << "public func " << transition_name << "(fsm:" << full_fsm_name << ", ctxt:" << class_name << ") {}\n";
        }
        out(1) << "}\n";
    }

    cout << "}" << endl;

}
<|endoftext|>


<commit_before>// @(#)root/net:$Id$
// Author: Fons Rademakers   18/12/96

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TServerSocket                                                        //
//                                                                      //
// This class implements server sockets. A server socket waits for      //
// requests to come in over the network. It performs some operation     //
// based on that request and then possibly returns a full duplex socket //
// to the requester. The actual work is done via the TSystem class      //
// (either TUnixSystem or TWinNTSystem).                                //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TServerSocket.h"
#include "TSocket.h"
#include "TSystem.h"
#include "TROOT.h"
#include "TError.h"
#include <string>
#include "TVirtualMutex.h"

// Hook to server authentication wrapper
SrvAuth_t TServerSocket::fgSrvAuthHook = 0;
SrvClup_t TServerSocket::fgSrvAuthClupHook = 0;

// Defaul options for accept
UChar_t TServerSocket::fgAcceptOpt = kSrvNoAuth;

TVirtualMutex *gSrvAuthenticateMutex = 0;

ClassImp(TServerSocket)

//______________________________________________________________________________
static void setaccopt(UChar_t &Opt, UChar_t Mod)
{
   // Kind of macro to parse input options
   // Modify Opt according to modifier Mod
   R__LOCKGUARD2(gSrvAuthenticateMutex);

   if (!Mod) return;

   if ((Mod & kSrvAuth))      Opt |= kSrvAuth;
   if ((Mod & kSrvNoAuth))    Opt &= ~kSrvAuth;
}

//______________________________________________________________________________
TServerSocket::TServerSocket(const char *service, Bool_t reuse, Int_t backlog,
                             Int_t tcpwindowsize)
{
   // Create a server socket object for a named service. Set reuse to true
   // to force reuse of the server socket (i.e. do not wait for the time
   // out to pass). Using backlog one can set the desirable queue length
   // for pending connections.
   // Use tcpwindowsize to specify the size of the receive buffer, it has
   // to be specified here to make sure the window scale option is set (for
   // tcpwindowsize > 65KB and for platforms supporting window scaling).
   // Use IsValid() to check the validity of the
   // server socket. In case server socket is not valid use GetErrorCode()
   // to obtain the specific error value. These values are:
   //  0 = no error (socket is valid)
   // -1 = low level socket() call failed
   // -2 = low level bind() call failed
   // -3 = low level listen() call failed
   // Every valid server socket is added to the TROOT sockets list which
   // will make sure that any open sockets are properly closed on
   // program termination.

   R__ASSERT(gROOT);
   R__ASSERT(gSystem);

   SetName("ServerSocket");

   fSecContext = 0;
   fSecContexts = new TList;

   // If this is a local path, try announcing a UNIX socket service
   ResetBit(TSocket::kIsUnix);
   if (service && (!gSystem->AccessPathName(service) ||
#ifndef WIN32
      service[0] == '/')) {
#else
      service[0] == '/' || (service[1] == ':' && service[2] == '/'))) {
#endif
      SetBit(TSocket::kIsUnix);
      fService = "unix:";
      fService += service;
      fSocket = gSystem->AnnounceUnixService(service, backlog);
      if (fSocket >= 0) {
         R__LOCKGUARD2(gROOTMutex);
         gROOT->GetListOfSockets()->Add(this);
      }
   } else {
      // TCP / UDP socket
      fService = service;
      int port = gSystem->GetServiceByName(service);
      if (port != -1) {
         fSocket = gSystem->AnnounceTcpService(port, reuse, backlog, tcpwindowsize);
         if (fSocket >= 0) {
            R__LOCKGUARD2(gROOTMutex);
            gROOT->GetListOfSockets()->Add(this);
         }
      } else {
         fSocket = -1;
      }
   }
}

//______________________________________________________________________________
TServerSocket::TServerSocket(Int_t port, Bool_t reuse, Int_t backlog,
                             Int_t tcpwindowsize)
{
   // Create a server socket object on a specified port. Set reuse to true
   // to force reuse of the server socket (i.e. do not wait for the time
   // out to pass). Using backlog one can set the desirable queue length
   // for pending connections. If port is 0 a port scan will be done to
   // find a free port. This option is mutual exlusive with the reuse option.
   // Use tcpwindowsize to specify the size of the receive buffer, it has
   // to be specified here to make sure the window scale option is set (for
   // tcpwindowsize > 65KB and for platforms supporting window scaling).
   // Use IsValid() to check the validity of the
   // server socket. In case server socket is not valid use GetErrorCode()
   // to obtain the specific error value. These values are:
   //  0 = no error (socket is valid)
   // -1 = low level socket() call failed
   // -2 = low level bind() call failed
   // -3 = low level listen() call failed
   // Every valid server socket is added to the TROOT sockets list which
   // will make sure that any open sockets are properly closed on
   // program termination.

   R__ASSERT(gROOT);
   R__ASSERT(gSystem);

   SetName("ServerSocket");

   fSecContext = 0;
   fSecContexts = new TList;
   fService = gSystem->GetServiceByPort(port);
   SetTitle(fService);

   fSocket = gSystem->AnnounceTcpService(port, reuse, backlog, tcpwindowsize);
   if (fSocket >= 0) {
      R__LOCKGUARD2(gROOTMutex);
      gROOT->GetListOfSockets()->Add(this);
   }
}

//______________________________________________________________________________
TServerSocket::~TServerSocket()
{
   // Destructor: cleanup authentication stuff (if any) and close

   R__LOCKGUARD2(gSrvAuthenticateMutex);
   if (fSecContexts) {
      if (fgSrvAuthClupHook) {
         // Cleanup the security contexts
         (*fgSrvAuthClupHook)(fSecContexts);
      }
      // Remove the list
      fSecContexts->Delete();
      SafeDelete(fSecContexts);
      fSecContexts = 0;
   }

   Close();
}

//______________________________________________________________________________
TSocket *TServerSocket::Accept(UChar_t Opt)
{
   // Accept a connection on a server socket. Returns a full-duplex
   // communication TSocket object. If no pending connections are
   // present on the queue and nonblocking mode has not been enabled
   // with SetOption(kNoBlock,1) the call blocks until a connection is
   // present. The returned socket must be deleted by the user. The socket
   // is also added to the TROOT sockets list which will make sure that
   // any open sockets are properly closed on program termination.
   // In case of error 0 is returned and in case non-blocking I/O is
   // enabled and no connections are available -1 is returned.
   //
   // Opt can be used to require client authentication; valid options are
   //
   //    kSrvAuth   =   require client authentication
   //    kSrvNoAuth =   force no client authentication
   //
   // Example: use Opt = kSrvAuth to require client authentication.
   //
   // Default options are taken from fgAcceptOpt and are initially
   // equivalent to kSrvNoAuth; they can be changed with the static
   // method TServerSocket::SetAcceptOptions(Opt).
   // The active defaults can be visualized using the static method
   // TServerSocket::ShowAcceptOptions().
   //

   if (fSocket == -1) { return 0; }

   TSocket *socket = new TSocket;

   Int_t soc = gSystem->AcceptConnection(fSocket);
   if (soc == -1) { delete socket; return 0; }
   if (soc == -2) { delete socket; return (TSocket*) -1; }

   // Parse Opt
   UChar_t acceptOpt = fgAcceptOpt;
   setaccopt(acceptOpt,Opt);
   Bool_t auth = (Bool_t)(acceptOpt & kSrvAuth);

   socket->fSocket  = soc;
   socket->fSecContext = 0;
   socket->fService = fService;
   if (!TestBit(TSocket::kIsUnix))
      socket->fAddress = gSystem->GetPeerName(socket->fSocket);
   if (socket->fSocket >= 0) {
      R__LOCKGUARD2(gROOTMutex);
      gROOT->GetListOfSockets()->Add(socket);
   }

   // Perform authentication, if required
   if (auth) {
      if (!Authenticate(socket)) {
         delete socket;
         socket = 0;
      }
   }

   return socket;
}

//______________________________________________________________________________
TInetAddress TServerSocket::GetLocalInetAddress()
{
   // Return internet address of host to which the server socket is bound,
   // i.e. the local host. In case of error TInetAddress::IsValid() returns
   // kFALSE.

   if (fSocket != -1) {
      if (fAddress.GetPort() == -1)
         fAddress = gSystem->GetSockName(fSocket);
      return fAddress;
   }
   return TInetAddress();
}

//______________________________________________________________________________
Int_t TServerSocket::GetLocalPort()
{
   // Get port # to which server socket is bound. In case of error returns -1.

   if (fSocket != -1) {
      if (fAddress.GetPort() == -1)
         fAddress = GetLocalInetAddress();
      return fAddress.GetPort();
   }
   return -1;
}

//______________________________________________________________________________
UChar_t TServerSocket::GetAcceptOptions()
{
   // Return default options for Accept

   return fgAcceptOpt;
}

//______________________________________________________________________________
void TServerSocket::SetAcceptOptions(UChar_t mod)
{
   // Set default options for Accept according to modifier 'mod'.
   // Use:
   //   kSrvAuth                 require client authentication
   //   kSrvNoAuth               do not require client authentication

   setaccopt(fgAcceptOpt,mod);
}

//______________________________________________________________________________
void TServerSocket::ShowAcceptOptions()
{
   // Print default options for Accept

   ::Info("ShowAcceptOptions","    Auth: %d",(Bool_t)(fgAcceptOpt & kSrvAuth));
}

//______________________________________________________________________________
Bool_t TServerSocket::Authenticate(TSocket *sock)
{
   // Check authentication request from the client on new
   // open connection

   if (!fgSrvAuthHook) {
      R__LOCKGUARD2(gSrvAuthenticateMutex);

      // Load libraries needed for (server) authentication ...
      TString srvlib = "libSrvAuth";
      char *p = 0;
      // The generic one
      if ((p = gSystem->DynamicPathName(srvlib, kTRUE))) {
         delete[] p;
         if (gSystem->Load(srvlib) == -1) {
            Error("Authenticate", "can't load %s",srvlib.Data());
            return kFALSE;
         }
      } else {
         Error("Authenticate", "can't locate %s",srvlib.Data());
         return kFALSE;
      }
      //
      // Locate SrvAuthenticate
      Func_t f = gSystem->DynFindSymbol(srvlib,"SrvAuthenticate");
      if (f)
         fgSrvAuthHook = (SrvAuth_t)(f);
      else {
         Error("Authenticate", "can't find SrvAuthenticate");
         return kFALSE;
      }
      //
      // Locate SrvAuthCleanup
      f = gSystem->DynFindSymbol(srvlib,"SrvAuthCleanup");
      if (f)
         fgSrvAuthClupHook = (SrvClup_t)(f);
      else {
         Warning("Authenticate", "can't find SrvAuthCleanup");
      }
   }

   TString confdir;
#ifndef ROOTPREFIX
   // try to guess the config directory...
   if (gSystem->Getenv("ROOTSYS")) {
      confdir = TString(gSystem->Getenv("ROOTSYS"));
   } else {
      // Try to guess it from 'root.exe' path
      char *rootexe = gSystem->Which(gSystem->Getenv("PATH"),
                                     "root.exe", kExecutePermission);
      confdir = rootexe;
      confdir.Resize(confdir.Last('/'));
      delete [] rootexe;
   }
#else
   confdir = TString(ROOTPREFIX);
#endif
   if (!confdir.Length()) {
      Error("Authenticate", "config dir undefined");
      return kFALSE;
   }

   // dir for temporary files
   TString tmpdir = TString(gSystem->TempDirectory());
   if (gSystem->AccessPathName(tmpdir, kWritePermission))
      tmpdir = TString("/tmp");

   // Get Host name
   TString openhost(sock->GetInetAddress().GetHostName());
   if (gDebug > 2)
      Info("Authenticate","OpenHost = %s", openhost.Data());

   // Run Authentication now
   std::string user;
   Int_t meth = -1;
   Int_t auth = 0;
   Int_t type = 0;
   std::string ctkn = "";
   if (fgSrvAuthHook)
      auth = (*fgSrvAuthHook)(sock, confdir, tmpdir, user,
                              meth, type, ctkn, fSecContexts);

   if (gDebug > 2)
      Info("Authenticate","auth = %d, type= %d, ctkn= %s",
            auth, type, ctkn.c_str());

   return auth;
}
<commit_msg>coding style.<commit_after>// @(#)root/net:$Id$
// Author: Fons Rademakers   18/12/96

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TServerSocket                                                        //
//                                                                      //
// This class implements server sockets. A server socket waits for      //
// requests to come in over the network. It performs some operation     //
// based on that request and then possibly returns a full duplex socket //
// to the requester. The actual work is done via the TSystem class      //
// (either TUnixSystem or TWinNTSystem).                                //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TServerSocket.h"
#include "TSocket.h"
#include "TSystem.h"
#include "TROOT.h"
#include "TError.h"
#include <string>
#include "TVirtualMutex.h"

// Hook to server authentication wrapper
SrvAuth_t TServerSocket::fgSrvAuthHook = 0;
SrvClup_t TServerSocket::fgSrvAuthClupHook = 0;

// Defaul options for accept
UChar_t TServerSocket::fgAcceptOpt = kSrvNoAuth;

TVirtualMutex *gSrvAuthenticateMutex = 0;

ClassImp(TServerSocket)

//______________________________________________________________________________
static void SetAuthOpt(UChar_t &opt, UChar_t mod)
{
   // Kind of macro to parse input options
   // Modify opt according to modifier mod.

   R__LOCKGUARD2(gSrvAuthenticateMutex);

   if (!mod) return;

   if ((mod & kSrvAuth))   opt |= kSrvAuth;
   if ((mod & kSrvNoAuth)) opt &= ~kSrvAuth;
}

//______________________________________________________________________________
TServerSocket::TServerSocket(const char *service, Bool_t reuse, Int_t backlog,
                             Int_t tcpwindowsize)
{
   // Create a server socket object for a named service. Set reuse to true
   // to force reuse of the server socket (i.e. do not wait for the time
   // out to pass). Using backlog one can set the desirable queue length
   // for pending connections.
   // Use tcpwindowsize to specify the size of the receive buffer, it has
   // to be specified here to make sure the window scale option is set (for
   // tcpwindowsize > 65KB and for platforms supporting window scaling).
   // Use IsValid() to check the validity of the
   // server socket. In case server socket is not valid use GetErrorCode()
   // to obtain the specific error value. These values are:
   //  0 = no error (socket is valid)
   // -1 = low level socket() call failed
   // -2 = low level bind() call failed
   // -3 = low level listen() call failed
   // Every valid server socket is added to the TROOT sockets list which
   // will make sure that any open sockets are properly closed on
   // program termination.

   R__ASSERT(gROOT);
   R__ASSERT(gSystem);

   SetName("ServerSocket");

   fSecContext = 0;
   fSecContexts = new TList;

   // If this is a local path, try announcing a UNIX socket service
   ResetBit(TSocket::kIsUnix);
   if (service && (!gSystem->AccessPathName(service) ||
#ifndef WIN32
      service[0] == '/')) {
#else
      service[0] == '/' || (service[1] == ':' && service[2] == '/'))) {
#endif
      SetBit(TSocket::kIsUnix);
      fService = "unix:";
      fService += service;
      fSocket = gSystem->AnnounceUnixService(service, backlog);
      if (fSocket >= 0) {
         R__LOCKGUARD2(gROOTMutex);
         gROOT->GetListOfSockets()->Add(this);
      }
   } else {
      // TCP / UDP socket
      fService = service;
      int port = gSystem->GetServiceByName(service);
      if (port != -1) {
         fSocket = gSystem->AnnounceTcpService(port, reuse, backlog, tcpwindowsize);
         if (fSocket >= 0) {
            R__LOCKGUARD2(gROOTMutex);
            gROOT->GetListOfSockets()->Add(this);
         }
      } else {
         fSocket = -1;
      }
   }
}

//______________________________________________________________________________
TServerSocket::TServerSocket(Int_t port, Bool_t reuse, Int_t backlog,
                             Int_t tcpwindowsize)
{
   // Create a server socket object on a specified port. Set reuse to true
   // to force reuse of the server socket (i.e. do not wait for the time
   // out to pass). Using backlog one can set the desirable queue length
   // for pending connections. If port is 0 a port scan will be done to
   // find a free port. This option is mutual exlusive with the reuse option.
   // Use tcpwindowsize to specify the size of the receive buffer, it has
   // to be specified here to make sure the window scale option is set (for
   // tcpwindowsize > 65KB and for platforms supporting window scaling).
   // Use IsValid() to check the validity of the
   // server socket. In case server socket is not valid use GetErrorCode()
   // to obtain the specific error value. These values are:
   //  0 = no error (socket is valid)
   // -1 = low level socket() call failed
   // -2 = low level bind() call failed
   // -3 = low level listen() call failed
   // Every valid server socket is added to the TROOT sockets list which
   // will make sure that any open sockets are properly closed on
   // program termination.

   R__ASSERT(gROOT);
   R__ASSERT(gSystem);

   SetName("ServerSocket");

   fSecContext = 0;
   fSecContexts = new TList;
   fService = gSystem->GetServiceByPort(port);
   SetTitle(fService);

   fSocket = gSystem->AnnounceTcpService(port, reuse, backlog, tcpwindowsize);
   if (fSocket >= 0) {
      R__LOCKGUARD2(gROOTMutex);
      gROOT->GetListOfSockets()->Add(this);
   }
}

//______________________________________________________________________________
TServerSocket::~TServerSocket()
{
   // Destructor: cleanup authentication stuff (if any) and close

   R__LOCKGUARD2(gSrvAuthenticateMutex);
   if (fSecContexts) {
      if (fgSrvAuthClupHook) {
         // Cleanup the security contexts
         (*fgSrvAuthClupHook)(fSecContexts);
      }
      // Remove the list
      fSecContexts->Delete();
      SafeDelete(fSecContexts);
      fSecContexts = 0;
   }

   Close();
}

//______________________________________________________________________________
TSocket *TServerSocket::Accept(UChar_t opt)
{
   // Accept a connection on a server socket. Returns a full-duplex
   // communication TSocket object. If no pending connections are
   // present on the queue and nonblocking mode has not been enabled
   // with SetOption(kNoBlock,1) the call blocks until a connection is
   // present. The returned socket must be deleted by the user. The socket
   // is also added to the TROOT sockets list which will make sure that
   // any open sockets are properly closed on program termination.
   // In case of error 0 is returned and in case non-blocking I/O is
   // enabled and no connections are available -1 is returned.
   //
   // The opt can be used to require client authentication; valid options are
   //
   //    kSrvAuth   =   require client authentication
   //    kSrvNoAuth =   force no client authentication
   //
   // Example: use Opt = kSrvAuth to require client authentication.
   //
   // Default options are taken from fgAcceptOpt and are initially
   // equivalent to kSrvNoAuth; they can be changed with the static
   // method TServerSocket::SetAcceptOptions(Opt).
   // The active defaults can be visualized using the static method
   // TServerSocket::ShowAcceptOptions().
   //

   if (fSocket == -1) { return 0; }

   TSocket *socket = new TSocket;

   Int_t soc = gSystem->AcceptConnection(fSocket);
   if (soc == -1) { delete socket; return 0; }
   if (soc == -2) { delete socket; return (TSocket*) -1; }

   // Parse Opt
   UChar_t acceptOpt = fgAcceptOpt;
   SetAuthOpt(acceptOpt, opt);
   Bool_t auth = (Bool_t)(acceptOpt & kSrvAuth);

   socket->fSocket  = soc;
   socket->fSecContext = 0;
   socket->fService = fService;
   if (!TestBit(TSocket::kIsUnix))
      socket->fAddress = gSystem->GetPeerName(socket->fSocket);
   if (socket->fSocket >= 0) {
      R__LOCKGUARD2(gROOTMutex);
      gROOT->GetListOfSockets()->Add(socket);
   }

   // Perform authentication, if required
   if (auth) {
      if (!Authenticate(socket)) {
         delete socket;
         socket = 0;
      }
   }

   return socket;
}

//______________________________________________________________________________
TInetAddress TServerSocket::GetLocalInetAddress()
{
   // Return internet address of host to which the server socket is bound,
   // i.e. the local host. In case of error TInetAddress::IsValid() returns
   // kFALSE.

   if (fSocket != -1) {
      if (fAddress.GetPort() == -1)
         fAddress = gSystem->GetSockName(fSocket);
      return fAddress;
   }
   return TInetAddress();
}

//______________________________________________________________________________
Int_t TServerSocket::GetLocalPort()
{
   // Get port # to which server socket is bound. In case of error returns -1.

   if (fSocket != -1) {
      if (fAddress.GetPort() == -1)
         fAddress = GetLocalInetAddress();
      return fAddress.GetPort();
   }
   return -1;
}

//______________________________________________________________________________
UChar_t TServerSocket::GetAcceptOptions()
{
   // Return default options for Accept

   return fgAcceptOpt;
}

//______________________________________________________________________________
void TServerSocket::SetAcceptOptions(UChar_t mod)
{
   // Set default options for Accept according to modifier 'mod'.
   // Use:
   //   kSrvAuth                 require client authentication
   //   kSrvNoAuth               do not require client authentication

   SetAuthOpt(fgAcceptOpt, mod);
}

//______________________________________________________________________________
void TServerSocket::ShowAcceptOptions()
{
   // Print default options for Accept.

   ::Info("ShowAcceptOptions", "Use authentication: %s", (fgAcceptOpt & kSrvAuth) ? "yes" : "no");
}

//______________________________________________________________________________
Bool_t TServerSocket::Authenticate(TSocket *sock)
{
   // Check authentication request from the client on new
   // open connection

   if (!fgSrvAuthHook) {
      R__LOCKGUARD2(gSrvAuthenticateMutex);

      // Load libraries needed for (server) authentication ...
      TString srvlib = "libSrvAuth";
      char *p = 0;
      // The generic one
      if ((p = gSystem->DynamicPathName(srvlib, kTRUE))) {
         delete[] p;
         if (gSystem->Load(srvlib) == -1) {
            Error("Authenticate", "can't load %s",srvlib.Data());
            return kFALSE;
         }
      } else {
         Error("Authenticate", "can't locate %s",srvlib.Data());
         return kFALSE;
      }
      //
      // Locate SrvAuthenticate
      Func_t f = gSystem->DynFindSymbol(srvlib,"SrvAuthenticate");
      if (f)
         fgSrvAuthHook = (SrvAuth_t)(f);
      else {
         Error("Authenticate", "can't find SrvAuthenticate");
         return kFALSE;
      }
      //
      // Locate SrvAuthCleanup
      f = gSystem->DynFindSymbol(srvlib,"SrvAuthCleanup");
      if (f)
         fgSrvAuthClupHook = (SrvClup_t)(f);
      else {
         Warning("Authenticate", "can't find SrvAuthCleanup");
      }
   }

   TString confdir;
#ifndef ROOTPREFIX
   // try to guess the config directory...
   if (gSystem->Getenv("ROOTSYS")) {
      confdir = TString(gSystem->Getenv("ROOTSYS"));
   } else {
      // Try to guess it from 'root.exe' path
      char *rootexe = gSystem->Which(gSystem->Getenv("PATH"),
                                     "root.exe", kExecutePermission);
      confdir = rootexe;
      confdir.Resize(confdir.Last('/'));
      delete [] rootexe;
   }
#else
   confdir = TString(ROOTPREFIX);
#endif
   if (!confdir.Length()) {
      Error("Authenticate", "config dir undefined");
      return kFALSE;
   }

   // dir for temporary files
   TString tmpdir = TString(gSystem->TempDirectory());
   if (gSystem->AccessPathName(tmpdir, kWritePermission))
      tmpdir = TString("/tmp");

   // Get Host name
   TString openhost(sock->GetInetAddress().GetHostName());
   if (gDebug > 2)
      Info("Authenticate","OpenHost = %s", openhost.Data());

   // Run Authentication now
   std::string user;
   Int_t meth = -1;
   Int_t auth = 0;
   Int_t type = 0;
   std::string ctkn = "";
   if (fgSrvAuthHook)
      auth = (*fgSrvAuthHook)(sock, confdir, tmpdir, user,
                              meth, type, ctkn, fSecContexts);

   if (gDebug > 2)
      Info("Authenticate","auth = %d, type= %d, ctkn= %s",
            auth, type, ctkn.c_str());

   return auth;
}
<|endoftext|>