<commit_before>#include <node.h>
#include <nan.h>
#include <v8.h>
#include <vector>
#include "mouse.h"
#include "deadbeef_rand.h"
#include "keypress.h"
#include "screen.h"
#include "screengrab.h"
#include "MMBitmap.h"

using namespace v8;

/*
 __  __
|  \/  | ___  _   _ ___  ___
| |\/| |/ _ \| | | / __|/ _ \
| |  | | (_) | |_| \__ \  __/
|_|  |_|\___/ \__,_|___/\___|

*/

NAN_METHOD(moveMouse)
{
	NanScope();
	if (args.Length() < 2)
	{
		return NanThrowError("Invalid number of arguments.");
	}
	size_t x = args[0]->Int32Value();
	size_t y = args[1]->Int32Value();

	MMPoint point;
	point = MMPointMake(x, y);
	moveMouse(point);
	NanReturnValue(NanNew("1"));
}

NAN_METHOD(moveMouseSmooth)
{
	NanScope();
	if (args.Length() < 2)
	{
		return NanThrowError("Invalid number of arguments.");
	}
	size_t x = args[0]->Int32Value();
	size_t y = args[1]->Int32Value();

	MMPoint point;
	point = MMPointMake(x, y);
	smoothlyMoveMouse(point);
	NanReturnValue(NanNew("1"));
}

NAN_METHOD(getMousePos)
{
	NanScope();

	MMPoint pos = getMousePos();

 	//Return object with .x and .y.
	Local<Object> obj = NanNew<Object>();
	obj->Set(NanNew<String>("x"), NanNew<Number>(pos.x));
	obj->Set(NanNew<String>("y"), NanNew<Number>(pos.y));
	NanReturnValue(obj);
}

NAN_METHOD(mouseClick)
{
	NanScope();

	MMMouseButton button = LEFT_BUTTON;

	if (args.Length() == 1)
	{
		char *b = (*v8::String::Utf8Value(args[0]->ToString()));

		if (strcmp(b, "left") == 0)
		{
			button = LEFT_BUTTON;
		}
		else if (strcmp(b, "right") == 0)
		{
			button = RIGHT_BUTTON;
		}
		else if (strcmp(b, "middle") == 0)
		{
			button = CENTER_BUTTON;
		}
		else
		{
			return NanThrowError("Invalid mouse button specified.");
		}
	}
	else if (args.Length() > 1)
	{
		return NanThrowError("Invalid number of arguments.");
	}

	clickMouse(button);

	NanReturnValue(NanNew("1"));
}

NAN_METHOD(mouseToggle)
{
	NanScope();

	MMMouseButton button = LEFT_BUTTON;
	bool down;

	if (args.Length() > 0)
	{
		const char *d = (*v8::String::Utf8Value(args[0]->ToString()));

		if (strcmp(d, "down") == 0)
		{
			down = true;;
		}
		else if (strcmp(d, "up") == 0)
		{
			down = false;
		}
		else
		{
			return NanThrowError("Invalid mouse button state specified.");
		}
	}

	if (args.Length() == 2)
	{
		char *b = (*v8::String::Utf8Value(args[1]->ToString()));

		if (strcmp(b, "left") == 0)
		{
			button = LEFT_BUTTON;
		}
		else if (strcmp(b, "right") == 0)
		{
			button = RIGHT_BUTTON;
		}
		else if (strcmp(b, "middle") == 0)
		{
			button = CENTER_BUTTON;
		}
		else
		{
			return NanThrowError("Invalid mouse button specified.");
		}
	}
	else if (args.Length() > 2)
	{
		return NanThrowError("Invalid number of arguments.");
	}

	toggleMouse(down, button);

	NanReturnValue(NanNew("1"));
}

/*
 _  __          _                         _
| |/ /___ _   _| |__   ___   __ _ _ __ __| |
| ' // _ \ | | | '_ \ / _ \ / _` | '__/ _` |
| . \  __/ |_| | |_) | (_) | (_| | | | (_| |
|_|\_\___|\__, |_.__/ \___/ \__,_|_|  \__,_|
          |___/
*/

int CheckKeyCodes(char* k, MMKeyCode *key)
{
	if (!key) return -1;

	if (strcmp(k, "alt") == 0)
	{
		*key = K_ALT;
	}
  	else if (strcmp(k, "command") == 0)
	{
		*key = K_META;
	}
  	else if (strcmp(k, "control") == 0)
	{
		*key = K_CONTROL;
	}
  	else if (strcmp(k, "shift") == 0)
	{
		*key = K_SHIFT;
	}
	else if (strcmp(k, "backspace") == 0)
	{
		*key = K_BACKSPACE;
	}
	else if (strcmp(k, "enter") == 0)
	{
		*key = K_RETURN;
	}
	else if (strcmp(k, "tab") == 0)
	{
		*key = K_TAB;
	}
	else if (strcmp(k, "up") == 0)
	{
		*key = K_UP;
	}
	else if (strcmp(k, "down") == 0)
	{
		*key = K_DOWN;
	}
	else if (strcmp(k, "left") == 0)
	{
		*key = K_LEFT;
	}
	else if (strcmp(k, "right") == 0)
	{
		*key = K_RIGHT;
	}
	else if (strcmp(k, "escape") == 0)
	{
		*key = K_ESCAPE;
	}
	else if (strcmp(k, "delete") == 0)
	{
		*key = K_DELETE;
	}
	else if (strcmp(k, "home") == 0)
	{
		*key = K_HOME;
	}
	else if (strcmp(k, "end") == 0)
	{
		*key = K_END;
	}
	else if (strcmp(k, "pageup") == 0)
	{
		*key = K_PAGEUP;
	}
	else if (strcmp(k, "pagedown") == 0)
	{
		*key = K_PAGEDOWN;
	}
	else if (strlen(k) == 1)
	{
		*key = keyCodeForChar(*k);
	}
	else
	{
		return -2;
	}

	return 0;
}

int CheckKeyFlags(char* f, MMKeyFlags* flags)
{
	if (!flags) return -1;

	if (strcmp(f, "alt") == 0)
	{
    	*flags = MOD_ALT;
  	}
  	else if(strcmp(f, "command") == 0)
	{
    	*flags = MOD_META;
  	}
  	else if(strcmp(f, "control") == 0)
	{
    	*flags = MOD_CONTROL;
  	}
  	else if(strcmp(f, "shift") == 0)
	{
    	*flags = MOD_SHIFT;
	}
	else if(strcmp(f, "none") == 0)
	{
    	*flags = MOD_NONE;
  	}
 	else
	{
    	return -2;
  	}

	return 0;
}

int mssleep(unsigned long millisecond)
{
	struct timespec req;
	time_t sec=(int)(millisecond/1000);
	millisecond=millisecond-(sec*1000);
	req.tv_sec=sec;
	req.tv_nsec=millisecond*1000000L;
	while(nanosleep(&req,&req)==-1)
		continue;
	return 1;
}

NAN_METHOD(keyTap)
{
	NanScope();

	MMKeyFlags flags = MOD_NONE;
	MMKeyCode key;

  	char *k;
  	char *f;

  	v8::String::Utf8Value fstr(args[1]->ToString());
  	v8::String::Utf8Value kstr(args[0]->ToString());
  	k = *kstr;
  	f = *fstr;

	switch (args.Length())
	{
    	case 2:
			break;
    	case 1:
			f = NULL;
			break;
    	default:
      		return NanThrowError("Invalid number of arguments.");
	}

  	if (f)
	{
    	switch(CheckKeyFlags(f, &flags))
    	{
      		case -1:
        		return NanThrowError("Null pointer in key flag.");
        		break;
      		case -2:
        		return NanThrowError("Invalid key flag specified.");
        		break;
    	}
  	}

	switch(CheckKeyCodes(k, &key))
	{
    	case -1:
      		return NanThrowError("Null pointer in key code.");
      		break;
    	case -2:
      		return NanThrowError("Invalid key code specified.");
      		break;
    	default:
      		tapKeyCode(key, flags);
      		mssleep(10);
	}

	NanReturnValue(NanNew("1"));
}

NAN_METHOD(keyToggle)
{
	NanScope();

	MMKeyFlags flags = MOD_NONE;
	MMKeyCode key;

	char *k;
	bool down;
	char *f;

	v8::String::Utf8Value kstr(args[0]->ToString());
	v8::String::Utf8Value fstr(args[2]->ToString());
	down = args[1]->BooleanValue();
	k = *kstr;
	f = *fstr;

	switch (args.Length())
	{
    	case 3:
      		break;
    	case 2:
      		f = NULL;
      		break;
    	default:
      		return NanThrowError("Invalid number of arguments.");
	}

	if (f)
	{
		switch(CheckKeyFlags(f, &flags))
		{
			case -1:
        		return NanThrowError("Null pointer in key flag.");
        		break;
			case -2:
        		return NanThrowError("Invalid key flag specified.");
        		break;
		}
	}

	switch(CheckKeyCodes(k, &key))
	{
		case -1:
    		return NanThrowError("Null pointer in key code.");
			break;
		case -2:
			return NanThrowError("Invalid key code specified.");
			break;
		default:
			toggleKeyCode(key, down, flags);
      		mssleep(10);
	}

	NanReturnValue(NanNew("1"));
}

NAN_METHOD(typeString)
{
	NanScope();

	char *str;
	NanUtf8String string(args[0]);

	str = *string;

	typeString(str);

	NanReturnValue(NanNew("1"));
}

/*
  ____
 / ___|  ___ _ __ ___  ___ _ __
 \___ \ / __| '__/ _ \/ _ \ '_ \
  ___) | (__| | |  __/  __/ | | |
 |____/ \___|_|  \___|\___|_| |_|

*/

NAN_METHOD(getPixelColor)
{
	NanScope();

	MMBitmapRef bitmap;
	MMRGBHex color;

	size_t x = args[0]->Int32Value();
	size_t y = args[1]->Int32Value();

	bitmap = copyMMBitmapFromDisplayInRect(MMRectMake(x, y, 1, 1));

	color = MMRGBHexAtPoint(bitmap, 0, 0);

	char hex [6];

	//Length needs to be 7 because snprintf includes a terminating null.
	//Use %06x to pad hex value with leading 0s.
	snprintf(hex, 7, "%06x", color);

	destroyMMBitmap(bitmap);

	NanReturnValue(NanNew(hex));
}

NAN_METHOD(getScreenSize)
{
	NanScope();

	//Get display size.
	MMSize displaySize = getMainDisplaySize();

	//Create our return object.
	Local<Object> obj = NanNew<Object>();
	obj->Set(NanNew<String>("width"), NanNew<Number>(displaySize.width));
	obj->Set(NanNew<String>("height"), NanNew<Number>(displaySize.height));

	//Return our object with .width and .height.
	NanReturnValue(obj);
}

void init(Handle<Object> target)
{

	target->Set(NanNew<String>("moveMouse"),
		NanNew<FunctionTemplate>(moveMouse)->GetFunction());

	target->Set(NanNew<String>("moveMouseSmooth"),
		NanNew<FunctionTemplate>(moveMouseSmooth)->GetFunction());

	target->Set(NanNew<String>("getMousePos"),
		NanNew<FunctionTemplate>(getMousePos)->GetFunction());

	target->Set(NanNew<String>("mouseClick"),
		NanNew<FunctionTemplate>(mouseClick)->GetFunction());

	target->Set(NanNew<String>("mouseToggle"),
		NanNew<FunctionTemplate>(mouseToggle)->GetFunction());

	target->Set(NanNew<String>("keyTap"),
		NanNew<FunctionTemplate>(keyTap)->GetFunction());

	target->Set(NanNew<String>("keyToggle"),
		NanNew<FunctionTemplate>(keyToggle)->GetFunction());

	target->Set(NanNew<String>("typeString"),
		NanNew<FunctionTemplate>(typeString)->GetFunction());

	target->Set(NanNew<String>("getPixelColor"),
		NanNew<FunctionTemplate>(getPixelColor)->GetFunction());

	target->Set(NanNew<String>("getScreenSize"),
		NanNew<FunctionTemplate>(getScreenSize)->GetFunction());

}

NODE_MODULE(robotjs, init)
<commit_msg>Spaces to tabs.<commit_after>#include <node.h>
#include <nan.h>
#include <v8.h>
#include <vector>
#include "mouse.h"
#include "deadbeef_rand.h"
#include "keypress.h"
#include "screen.h"
#include "screengrab.h"
#include "MMBitmap.h"

using namespace v8;

/*
 __  __
|  \/  | ___  _   _ ___  ___
| |\/| |/ _ \| | | / __|/ _ \
| |  | | (_) | |_| \__ \  __/
|_|  |_|\___/ \__,_|___/\___|

*/

NAN_METHOD(moveMouse)
{
	NanScope();
	if (args.Length() < 2)
	{
		return NanThrowError("Invalid number of arguments.");
	}
	size_t x = args[0]->Int32Value();
	size_t y = args[1]->Int32Value();

	MMPoint point;
	point = MMPointMake(x, y);
	moveMouse(point);
	NanReturnValue(NanNew("1"));
}

NAN_METHOD(moveMouseSmooth)
{
	NanScope();
	if (args.Length() < 2)
	{
		return NanThrowError("Invalid number of arguments.");
	}
	size_t x = args[0]->Int32Value();
	size_t y = args[1]->Int32Value();

	MMPoint point;
	point = MMPointMake(x, y);
	smoothlyMoveMouse(point);
	NanReturnValue(NanNew("1"));
}

NAN_METHOD(getMousePos)
{
	NanScope();

	MMPoint pos = getMousePos();

 	//Return object with .x and .y.
	Local<Object> obj = NanNew<Object>();
	obj->Set(NanNew<String>("x"), NanNew<Number>(pos.x));
	obj->Set(NanNew<String>("y"), NanNew<Number>(pos.y));
	NanReturnValue(obj);
}

NAN_METHOD(mouseClick)
{
	NanScope();

	MMMouseButton button = LEFT_BUTTON;

	if (args.Length() == 1)
	{
		char *b = (*v8::String::Utf8Value(args[0]->ToString()));

		if (strcmp(b, "left") == 0)
		{
			button = LEFT_BUTTON;
		}
		else if (strcmp(b, "right") == 0)
		{
			button = RIGHT_BUTTON;
		}
		else if (strcmp(b, "middle") == 0)
		{
			button = CENTER_BUTTON;
		}
		else
		{
			return NanThrowError("Invalid mouse button specified.");
		}
	}
	else if (args.Length() > 1)
	{
		return NanThrowError("Invalid number of arguments.");
	}

	clickMouse(button);

	NanReturnValue(NanNew("1"));
}

NAN_METHOD(mouseToggle)
{
	NanScope();

	MMMouseButton button = LEFT_BUTTON;
	bool down;

	if (args.Length() > 0)
	{
		const char *d = (*v8::String::Utf8Value(args[0]->ToString()));

		if (strcmp(d, "down") == 0)
		{
			down = true;;
		}
		else if (strcmp(d, "up") == 0)
		{
			down = false;
		}
		else
		{
			return NanThrowError("Invalid mouse button state specified.");
		}
	}

	if (args.Length() == 2)
	{
		char *b = (*v8::String::Utf8Value(args[1]->ToString()));

		if (strcmp(b, "left") == 0)
		{
			button = LEFT_BUTTON;
		}
		else if (strcmp(b, "right") == 0)
		{
			button = RIGHT_BUTTON;
		}
		else if (strcmp(b, "middle") == 0)
		{
			button = CENTER_BUTTON;
		}
		else
		{
			return NanThrowError("Invalid mouse button specified.");
		}
	}
	else if (args.Length() > 2)
	{
		return NanThrowError("Invalid number of arguments.");
	}

	toggleMouse(down, button);

	NanReturnValue(NanNew("1"));
}

/*
 _  __          _                         _
| |/ /___ _   _| |__   ___   __ _ _ __ __| |
| ' // _ \ | | | '_ \ / _ \ / _` | '__/ _` |
| . \  __/ |_| | |_) | (_) | (_| | | | (_| |
|_|\_\___|\__, |_.__/ \___/ \__,_|_|  \__,_|
          |___/
*/

int CheckKeyCodes(char* k, MMKeyCode *key)
{
	if (!key) return -1;

	if (strcmp(k, "alt") == 0)
	{
		*key = K_ALT;
	}
  	else if (strcmp(k, "command") == 0)
	{
		*key = K_META;
	}
  	else if (strcmp(k, "control") == 0)
	{
		*key = K_CONTROL;
	}
  	else if (strcmp(k, "shift") == 0)
	{
		*key = K_SHIFT;
	}
	else if (strcmp(k, "backspace") == 0)
	{
		*key = K_BACKSPACE;
	}
	else if (strcmp(k, "enter") == 0)
	{
		*key = K_RETURN;
	}
	else if (strcmp(k, "tab") == 0)
	{
		*key = K_TAB;
	}
	else if (strcmp(k, "up") == 0)
	{
		*key = K_UP;
	}
	else if (strcmp(k, "down") == 0)
	{
		*key = K_DOWN;
	}
	else if (strcmp(k, "left") == 0)
	{
		*key = K_LEFT;
	}
	else if (strcmp(k, "right") == 0)
	{
		*key = K_RIGHT;
	}
	else if (strcmp(k, "escape") == 0)
	{
		*key = K_ESCAPE;
	}
	else if (strcmp(k, "delete") == 0)
	{
		*key = K_DELETE;
	}
	else if (strcmp(k, "home") == 0)
	{
		*key = K_HOME;
	}
	else if (strcmp(k, "end") == 0)
	{
		*key = K_END;
	}
	else if (strcmp(k, "pageup") == 0)
	{
		*key = K_PAGEUP;
	}
	else if (strcmp(k, "pagedown") == 0)
	{
		*key = K_PAGEDOWN;
	}
	else if (strlen(k) == 1)
	{
		*key = keyCodeForChar(*k);
	}
	else
	{
		return -2;
	}

	return 0;
}

int CheckKeyFlags(char* f, MMKeyFlags* flags)
{
	if (!flags) return -1;

	if (strcmp(f, "alt") == 0)
	{
    	*flags = MOD_ALT;
  	}
  	else if(strcmp(f, "command") == 0)
	{
    	*flags = MOD_META;
  	}
  	else if(strcmp(f, "control") == 0)
	{
    	*flags = MOD_CONTROL;
  	}
  	else if(strcmp(f, "shift") == 0)
	{
    	*flags = MOD_SHIFT;
	}
	else if(strcmp(f, "none") == 0)
	{
    	*flags = MOD_NONE;
  	}
 	else
	{
    	return -2;
  	}

	return 0;
}

int mssleep(unsigned long millisecond)
{
	struct timespec req;
	time_t sec=(int)(millisecond/1000);
	millisecond=millisecond-(sec*1000);
	req.tv_sec=sec;
	req.tv_nsec=millisecond*1000000L;
	while(nanosleep(&req,&req)==-1)
		continue;
	return 1;
}

NAN_METHOD(keyTap)
{
	NanScope();

	MMKeyFlags flags = MOD_NONE;
	MMKeyCode key;

  	char *k;
  	char *f;

  	v8::String::Utf8Value fstr(args[1]->ToString());
  	v8::String::Utf8Value kstr(args[0]->ToString());
  	k = *kstr;
  	f = *fstr;

	switch (args.Length())
	{
    	case 2:
			break;
    	case 1:
			f = NULL;
			break;
    	default:
      		return NanThrowError("Invalid number of arguments.");
	}

  	if (f)
	{
		switch(CheckKeyFlags(f, &flags))
    	{
			case -1:
        		return NanThrowError("Null pointer in key flag.");
        		break;
			case -2:
        		return NanThrowError("Invalid key flag specified.");
        		break;
    	}
	}

	switch(CheckKeyCodes(k, &key))
	{
		case -1:
			return NanThrowError("Null pointer in key code.");
			break;
    	case -2:
			return NanThrowError("Invalid key code specified.");
			break;
		default:
			tapKeyCode(key, flags);
			mssleep(10);
	}

	NanReturnValue(NanNew("1"));
}

NAN_METHOD(keyToggle)
{
	NanScope();

	MMKeyFlags flags = MOD_NONE;
	MMKeyCode key;

	char *k;
	bool down;
	char *f;

	v8::String::Utf8Value kstr(args[0]->ToString());
	v8::String::Utf8Value fstr(args[2]->ToString());
	down = args[1]->BooleanValue();
	k = *kstr;
	f = *fstr;

	switch (args.Length())
	{
    	case 3:
      		break;
    	case 2:
      		f = NULL;
      		break;
    	default:
      		return NanThrowError("Invalid number of arguments.");
	}

	if (f)
	{
		switch(CheckKeyFlags(f, &flags))
		{
			case -1:
        		return NanThrowError("Null pointer in key flag.");
        		break;
			case -2:
        		return NanThrowError("Invalid key flag specified.");
        		break;
		}
	}

	switch(CheckKeyCodes(k, &key))
	{
		case -1:
    		return NanThrowError("Null pointer in key code.");
			break;
		case -2:
			return NanThrowError("Invalid key code specified.");
			break;
		default:
			toggleKeyCode(key, down, flags);
      		mssleep(10);
	}

	NanReturnValue(NanNew("1"));
}

NAN_METHOD(typeString)
{
	NanScope();

	char *str;
	NanUtf8String string(args[0]);

	str = *string;

	typeString(str);

	NanReturnValue(NanNew("1"));
}

/*
  ____
 / ___|  ___ _ __ ___  ___ _ __
 \___ \ / __| '__/ _ \/ _ \ '_ \
  ___) | (__| | |  __/  __/ | | |
 |____/ \___|_|  \___|\___|_| |_|

*/

NAN_METHOD(getPixelColor)
{
	NanScope();

	MMBitmapRef bitmap;
	MMRGBHex color;

	size_t x = args[0]->Int32Value();
	size_t y = args[1]->Int32Value();

	bitmap = copyMMBitmapFromDisplayInRect(MMRectMake(x, y, 1, 1));

	color = MMRGBHexAtPoint(bitmap, 0, 0);

	char hex [6];

	//Length needs to be 7 because snprintf includes a terminating null.
	//Use %06x to pad hex value with leading 0s.
	snprintf(hex, 7, "%06x", color);

	destroyMMBitmap(bitmap);

	NanReturnValue(NanNew(hex));
}

NAN_METHOD(getScreenSize)
{
	NanScope();

	//Get display size.
	MMSize displaySize = getMainDisplaySize();

	//Create our return object.
	Local<Object> obj = NanNew<Object>();
	obj->Set(NanNew<String>("width"), NanNew<Number>(displaySize.width));
	obj->Set(NanNew<String>("height"), NanNew<Number>(displaySize.height));

	//Return our object with .width and .height.
	NanReturnValue(obj);
}

void init(Handle<Object> target)
{

	target->Set(NanNew<String>("moveMouse"),
		NanNew<FunctionTemplate>(moveMouse)->GetFunction());

	target->Set(NanNew<String>("moveMouseSmooth"),
		NanNew<FunctionTemplate>(moveMouseSmooth)->GetFunction());

	target->Set(NanNew<String>("getMousePos"),
		NanNew<FunctionTemplate>(getMousePos)->GetFunction());

	target->Set(NanNew<String>("mouseClick"),
		NanNew<FunctionTemplate>(mouseClick)->GetFunction());

	target->Set(NanNew<String>("mouseToggle"),
		NanNew<FunctionTemplate>(mouseToggle)->GetFunction());

	target->Set(NanNew<String>("keyTap"),
		NanNew<FunctionTemplate>(keyTap)->GetFunction());

	target->Set(NanNew<String>("keyToggle"),
		NanNew<FunctionTemplate>(keyToggle)->GetFunction());

	target->Set(NanNew<String>("typeString"),
		NanNew<FunctionTemplate>(typeString)->GetFunction());

	target->Set(NanNew<String>("getPixelColor"),
		NanNew<FunctionTemplate>(getPixelColor)->GetFunction());

	target->Set(NanNew<String>("getScreenSize"),
		NanNew<FunctionTemplate>(getScreenSize)->GetFunction());

}

NODE_MODULE(robotjs, init)
<|endoftext|>


<commit_before>// Copyright 2017 Esri.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <QSettings>
#include <QGuiApplication>
#include <QQuickView>
#include <QCommandLineParser>
#include <QDir>
#include <QQmlEngine>
#include <QSurfaceFormat>

#define STRINGIZE(x) #x
#define QUOTE(x) STRINGIZE(x)

int main(int argc, char *argv[])
{
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
    // Linux requires 3.2 OpenGL Context
    // in order to instance 3D symbols
    QSurfaceFormat fmt = QSurfaceFormat::defaultFormat();
    fmt.setVersion(3, 2);
    QSurfaceFormat::setDefaultFormat(fmt);
#endif

    QGuiApplication app(argc, argv);

#ifdef Q_OS_WIN
    // Force usage of OpenGL ES through ANGLE on Windows
    QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
#endif

    // Intialize application view
    QQuickView view;
    view.setResizeMode(QQuickView::SizeRootObjectToView);

    QString arcGISRuntimeImportPath = QUOTE(ARCGIS_RUNTIME_IMPORT_PATH);
    QString arcGISToolkitImportPath = QUOTE(ARCGIS_TOOLKIT_IMPORT_PATH);

#if defined(LINUX_PLATFORM_REPLACEMENT)
    // on some linux platforms the string 'linux' is replaced with 1
    // fix the replacement paths which were created
    QString replaceString = QUOTE(LINUX_PLATFORM_REPLACEMENT);
    arcGISRuntimeImportPath = arcGISRuntimeImportPath.replace(replaceString, "linux", Qt::CaseSensitive);
    arcGISToolkitImportPath = arcGISToolkitImportPath.replace(replaceString, "linux", Qt::CaseSensitive);
#endif

    // Add the import Path
    view.engine()->addImportPath(QDir(QCoreApplication::applicationDirPath()).filePath("qml"));
    // Add the Runtime and Extras path
    view.engine()->addImportPath(arcGISRuntimeImportPath);
    // Add the Toolkit path
    view.engine()->addImportPath(arcGISToolkitImportPath);

    // Set the source
    view.setSource(QUrl("qrc:/Samples/Analysis/FeatureLayerExtrusion/FeatureLayerExtrusion.qml"));

    view.show();

    return app.exec();
}
<commit_msg>Changed category from Analysis to Scenes<commit_after>// Copyright 2017 Esri.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <QSettings>
#include <QGuiApplication>
#include <QQuickView>
#include <QCommandLineParser>
#include <QDir>
#include <QQmlEngine>
#include <QSurfaceFormat>

#define STRINGIZE(x) #x
#define QUOTE(x) STRINGIZE(x)

int main(int argc, char *argv[])
{
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
    // Linux requires 3.2 OpenGL Context
    // in order to instance 3D symbols
    QSurfaceFormat fmt = QSurfaceFormat::defaultFormat();
    fmt.setVersion(3, 2);
    QSurfaceFormat::setDefaultFormat(fmt);
#endif

    QGuiApplication app(argc, argv);

#ifdef Q_OS_WIN
    // Force usage of OpenGL ES through ANGLE on Windows
    QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
#endif

    // Intialize application view
    QQuickView view;
    view.setResizeMode(QQuickView::SizeRootObjectToView);

    QString arcGISRuntimeImportPath = QUOTE(ARCGIS_RUNTIME_IMPORT_PATH);
    QString arcGISToolkitImportPath = QUOTE(ARCGIS_TOOLKIT_IMPORT_PATH);

#if defined(LINUX_PLATFORM_REPLACEMENT)
    // on some linux platforms the string 'linux' is replaced with 1
    // fix the replacement paths which were created
    QString replaceString = QUOTE(LINUX_PLATFORM_REPLACEMENT);
    arcGISRuntimeImportPath = arcGISRuntimeImportPath.replace(replaceString, "linux", Qt::CaseSensitive);
    arcGISToolkitImportPath = arcGISToolkitImportPath.replace(replaceString, "linux", Qt::CaseSensitive);
#endif

    // Add the import Path
    view.engine()->addImportPath(QDir(QCoreApplication::applicationDirPath()).filePath("qml"));
    // Add the Runtime and Extras path
    view.engine()->addImportPath(arcGISRuntimeImportPath);
    // Add the Toolkit path
    view.engine()->addImportPath(arcGISToolkitImportPath);

    // Set the source
    view.setSource(QUrl("qrc:/Samples/Scenes/FeatureLayerExtrusion/FeatureLayerExtrusion.qml"));

    view.show();

    return app.exec();
}
<|endoftext|>


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

#include <votca/tools/version.h>
#include <iostream>
#include "version.h"

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#if GMX == 45
#include <gromacs/copyrite.h>
#elif GMX == 40
    extern "C"
    {
        #include <copyrite.h>
    }
#endif

#ifdef GMX
// this one is needed because of bool is defined in one of the headers included by gmx
#undef bool
#endif

namespace votca { namespace csg {

#ifdef HGVERSION
  static const std::string version_str = VERSION " " HGVERSION " (compiled " __DATE__ ", " __TIME__ ")";
#else
  static const std::string version_str = VERSION "(compiled " __DATE__ ", " __TIME__ ")";
#endif

const std::string &CsgVersionStr()
{
    return version_str;
}

void HelpTextHeader(const std::string &tool_name)
{
    std::cout
         << "==================================================\n"
         << "========   VOTCA (http://www.votca.org)   ========\n"
         << "==================================================\n\n"
	 << "please submit bugs to " PACKAGE_BUGREPORT "\n\n"
	 << tool_name << ", version " << votca::csg::CsgVersionStr()
         << "\nvotca_tools, version " << votca::tools::ToolsVersionStr()
#ifdef GMX
         << "\ngromacs, " << GromacsVersion()
#else
	 << "\n"
#endif
         << "\n\n";
}

}}

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

#include <votca/tools/version.h>
#include <iostream>
#include "version.h"

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#if GMX == 45
#include <gromacs/copyrite.h>
#elif GMX == 40
    extern "C"
    {
        #include <copyrite.h>
    }
#endif

#ifdef GMX
// this one is needed because of bool is defined in one of the headers included by gmx
#undef bool
#endif

namespace votca { namespace csg {

#ifdef HGVERSION
  static const std::string version_str = VERSION " " HGVERSION " (compiled " __DATE__ ", " __TIME__ ")";
#else
  static const std::string version_str = VERSION "(compiled " __DATE__ ", " __TIME__ ")";
#endif

const std::string &CsgVersionStr()
{
    return version_str;
}

void HelpTextHeader(const std::string &tool_name)
{
    std::cout
         << "==================================================\n"
         << "========   VOTCA (http://www.votca.org)   ========\n"
         << "==================================================\n\n"
	 << "please submit bugs to " PACKAGE_BUGREPORT "\n\n"
	 << tool_name << ", version " << votca::csg::CsgVersionStr()
         << "\nvotca_tools, version " << votca::tools::ToolsVersionStr()
#ifdef GMX
         << "\ngromacs, " << GromacsVersion()
#ifdef GMX_DOUBLE
	 << " (double precision)"
#else
	 << " (single precision)"
#endif
#else
	 << "\n"
#endif
         << "\n\n";
}

}}

<|endoftext|>


<commit_before>#include "LdapClient.h"

//------------------------------------------------------------------------------

#ifdef OPENLDAP

#include <cstdlib>     // free()
#include <sys/time.h>  // struct timeval
#include <sstream>     // std::stringstream

/** OpenLDAP client implementation */
class OpenLdapClient : public LdapClient
{
public:
    OpenLdapClient() : LdapClient(), ldap(NULL), retval(LDAP_SUCCESS) { }
    ~OpenLdapClient();

    bool bind(const std::string& dn,
              const std::string& pass);

    int getLastError()            { return this->retval; }
    std::string getLastErrorMsg() { return std::string(ldap_err2string(this->retval)); }

    struct berval** getValuesLen(LDAPMessage* entry,
                                 const char* attr);

    int countEntries(LDAPMessage* result);

    LDAPMessage* firstEntry(LDAPMessage* result);

    bool init(const std::string& host,
              int port);

    bool msgFree(LDAPMessage* msg);

    LDAPMessage* nextEntry(LDAPMessage* entry);

    bool search(const std::string& basedn,
                int scope,
                const std::string& filter,
                char* attrs[],
                int attrsonly,
                LDAPControl** serverctrls,
                LDAPControl** clientctrls,
                const LdapClient::TimeVal& timeout,
                int sizelimit,
                LDAPMessage** results);

    bool setOption(int option,
                   void *invalue);

    bool valueFreeLen(struct berval** val);

private:
    void setTimeval(const LdapClient::TimeVal& src, struct timeval& dest);

private:
    LDAP* ldap;
    int retval;
};

OpenLdapClient::~OpenLdapClient()
{
    ldap_unbind_ext(this->ldap, NULL, NULL);
    free(this->ldap);
    this->ldap = NULL;
}

bool OpenLdapClient::bind(const std::string& dn,
                          const std::string& passwd)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    LDAPControl *serverctrls=NULL, *clientctrls=NULL;
    struct berval *servercredp=NULL;
    struct berval creds;
    creds.bv_val = strdup( passwd.c_str() );
    creds.bv_len = passwd.length();

    this->retval = ldap_sasl_bind_s(ldap,
                                    dn.c_str(),
                                    LDAP_SASL_SIMPLE,
                                    &creds,
                                    &serverctrls,
                                    &clientctrls,
                                    &servercredp);

    return this->retval == LDAP_SUCCESS;
}

int OpenLdapClient::countEntries(LDAPMessage* result)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    int num_entries = ldap_count_entries(ldap, result);

    this->retval = LDAP_OTHER;

    return num_entries;
}

LDAPMessage* OpenLdapClient::firstEntry(LDAPMessage* result)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    LDAPMessage* msg = ldap_first_message(ldap, result);

    this->retval = LDAP_OTHER;

    return msg;
}

struct berval** OpenLdapClient::getValuesLen(LDAPMessage* entry,
                                             const char* attr)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    return ldap_get_values_len(this->ldap, entry, attr);
}

bool OpenLdapClient::init(const std::string& host, int port)
{
    if (this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    std::stringstream uri_buf;
    uri_buf << "ldap://" << host << ':' << port;

    this->retval = ldap_initialize(&this->ldap, uri_buf.str().c_str());

    return this->retval == LDAP_SUCCESS;
}

bool OpenLdapClient::msgFree(LDAPMessage* msg)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    this->retval = ldap_msgfree(msg);

    return this->retval == LDAP_SUCCESS;
}

LDAPMessage* OpenLdapClient::nextEntry(LDAPMessage* entry)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    return ldap_next_entry(this->ldap, entry);
}

bool OpenLdapClient::search(const std::string& basedn,
                            int scope,
                            const std::string& filter,
                            char* attrs[],
                            int attrsonly,
                            LDAPControl** serverctrls,
                            LDAPControl** clientctrls,
                            const LdapClient::TimeVal& timeout,
                            int sizelimit,
                            LDAPMessage** results)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    struct timeval openldap_timeout;

    this->setTimeval(timeout, openldap_timeout);

    ldap_search_ext_s(this->ldap,
                      basedn.c_str(),
                      scope,
                      filter.c_str(),
                      attrs,
                      attrsonly,
                      serverctrls,
                      clientctrls,
                      &openldap_timeout,
                      sizelimit,
                      results);

    return this->retval == LDAP_SUCCESS;
}

bool OpenLdapClient::setOption(int option, void* invalue)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    this->retval = ldap_set_option(this->ldap,
                                   option,
                                   invalue);

    return this->retval == LDAP_SUCCESS;
}

void OpenLdapClient::setTimeval(const LdapClient::TimeVal& src, struct timeval& dest)
{
    dest.tv_sec  = src.tv_sec;
    dest.tv_usec = src.tv_usec;
}

bool OpenLdapClient::valueFreeLen(struct berval** val)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    ldap_value_free_len(val);
    this->retval = LDAP_SUCCESS;

    return this->retval == LDAP_SUCCESS;
}

#endif  // OPENLDAP

//------------------------------------------------------------------------------

#ifdef WINLDAP

/** Microsoft Windows LDAP client implementation */
class WinLdapClient : public LdapClient
{
public:
    WinLdapClient() : ldap(NULL), retval(LDAP_SUCCESS) { }
    ~WinLdapClient();

    bool bind(const std::string& dn,
              const std::string& passwd);

    int countEntries(LDAPMessage* result);

    LDAPMessage* firstEntry(LDAPMessage* result);

    int getLastError()            { return this->retval; }
    std::string getLastErrorMsg() { return std::string(ldap_err2string(this->retval)); }

    struct berval** getValuesLen(LDAPMessage* entry,
                                 const char* attr);

    bool init(const std::string& host,
              int port);

    bool msgFree(LDAPMessage* msg);

    LDAPMessage* nextEntry(LDAPMessage* entry);

    bool search(const std::string& basedn,
                int scope,
                const std::string& filter,
                char* attrs[],
                int attrsonly,
                LDAPControl** serverctrls,
                LDAPControl** clientctrls,
                const LdapClient::TimeVal& timeout,
                int sizelimit,
                LDAPMessage** results);

    bool setOption(int option,
                   void *invalue);

    bool valueFreeLen(struct berval** val);

private:
    void setTimeval(const LdapClient::TimeVal& src, struct l_timeval& dest);

private:
    LDAP* ldap;
    int retval;
};

WinLdapClient::~WinLdapClient()
{
    ldap_unbind(this->ldap);
    free(this->ldap);
    this->ldap = NULL;
}

bool WinLdapClient::bind(const std::string& dn,
                         const std::string& passwd)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    this->retval = ldap_simple_bind_s(this->ldap,
                                      (char*) dn.c_str(),
                                      (char*) passwd.c_str());

    return this->retval == LDAP_SUCCESS;
}

int WinLdapClient::countEntries(LDAPMessage* result)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    int num_entries = ldap_count_entries(ldap, result);

    this->retval = LDAP_OTHER;

    return num_entries;
}

LDAPMessage* WinLdapClient::firstEntry(LDAPMessage* result)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    LDAPMessage* msg = ldap_first_entry(ldap, result);

    this->retval = LDAP_OTHER;

    return msg;
}

struct berval** WinLdapClient::getValuesLen(LDAPMessage* entry,
                                            const char* attr)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    return ldap_get_values_len(this->ldap, entry, (char*) attr);
}

bool WinLdapClient::init(const std::string &host, int port)
{
    this->ldap = ldap_init((char*) host.c_str(), port);
    this->retval = LdapGetLastError();
    return this->retval == LDAP_SUCCESS;
}

bool WinLdapClient::msgFree(LDAPMessage* msg)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    this->retval = ldap_msgfree(msg);

    return this->retval == LDAP_SUCCESS;
}

LDAPMessage* WinLdapClient::nextEntry(LDAPMessage* entry)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    return ldap_next_entry(this->ldap, entry);
}

bool WinLdapClient::search(const std::string& basedn,
                            int scope,
                            const std::string& filter,
                            char* attrs[],
                            int attrsonly,
                            LDAPControl** serverctrls,
                            LDAPControl** clientctrls,
                            const LdapClient::TimeVal& timeout,
                            int sizelimit,
                            LDAPMessage** results)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    struct l_timeval winldap_timeout;

    this->setTimeval(timeout, winldap_timeout);

    ldap_search_ext_s(this->ldap,
                      (char*) basedn.c_str(),
                      scope,
                      (char*) filter.c_str(),
                      attrs,
                      attrsonly,
                      serverctrls,
                      clientctrls,
                      &winldap_timeout,
                      sizelimit,
                      results);

    return this->retval == LDAP_SUCCESS;
}

bool WinLdapClient::setOption(int option, void* invalue)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    this->retval = ldap_set_option(this->ldap,
                                   option,
                                   invalue);

    return this->retval == LDAP_SUCCESS;
}

void WinLdapClient::setTimeval(const LdapClient::TimeVal& src, struct l_timeval& dest)
{
    dest.tv_sec  = (long) src.tv_sec;
    dest.tv_usec = (long) src.tv_usec;
}

bool WinLdapClient::valueFreeLen(struct berval** val)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    this->retval = ldap_value_free_len(val);

    return this->retval == LDAP_SUCCESS;
}

#endif // WINLDAP

//------------------------------------------------------------------------------

LdapClient* LdapClient::createInstance()
{
    LdapClient* ldap = NULL;

#ifdef OPENLDAP
    ldap = new OpenLdapClient();
#elif  WINLDAP
    ldap = new WinLdapClient();
#else
    #error "You must specify an LDAP define for LdapClient."
#endif

    return ldap;
}

//------------------------------------------------------------------------------
<commit_msg>fixed retval handling on ldap search<commit_after>#include "LdapClient.h"

//------------------------------------------------------------------------------

#ifdef OPENLDAP

#include <cstdlib>     // free()
#include <sys/time.h>  // struct timeval
#include <sstream>     // std::stringstream

/** OpenLDAP client implementation */
class OpenLdapClient : public LdapClient
{
public:
    OpenLdapClient() : LdapClient(), ldap(NULL), retval(LDAP_SUCCESS) { }
    ~OpenLdapClient();

    bool bind(const std::string& dn,
              const std::string& pass);

    int getLastError()            { return this->retval; }
    std::string getLastErrorMsg() { return std::string(ldap_err2string(this->retval)); }

    struct berval** getValuesLen(LDAPMessage* entry,
                                 const char* attr);

    int countEntries(LDAPMessage* result);

    LDAPMessage* firstEntry(LDAPMessage* result);

    bool init(const std::string& host,
              int port);

    bool msgFree(LDAPMessage* msg);

    LDAPMessage* nextEntry(LDAPMessage* entry);

    bool search(const std::string& basedn,
                int scope,
                const std::string& filter,
                char* attrs[],
                int attrsonly,
                LDAPControl** serverctrls,
                LDAPControl** clientctrls,
                const LdapClient::TimeVal& timeout,
                int sizelimit,
                LDAPMessage** results);

    bool setOption(int option,
                   void *invalue);

    bool valueFreeLen(struct berval** val);

private:
    void setTimeval(const LdapClient::TimeVal& src, struct timeval& dest);

private:
    LDAP* ldap;
    int retval;
};

OpenLdapClient::~OpenLdapClient()
{
    ldap_unbind_ext(this->ldap, NULL, NULL);
    free(this->ldap);
    this->ldap = NULL;
}

bool OpenLdapClient::bind(const std::string& dn,
                          const std::string& passwd)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    LDAPControl *serverctrls=NULL, *clientctrls=NULL;
    struct berval *servercredp=NULL;
    struct berval creds;
    creds.bv_val = strdup( passwd.c_str() );
    creds.bv_len = passwd.length();

    this->retval = ldap_sasl_bind_s(ldap,
                                    dn.c_str(),
                                    LDAP_SASL_SIMPLE,
                                    &creds,
                                    &serverctrls,
                                    &clientctrls,
                                    &servercredp);

    return this->retval == LDAP_SUCCESS;
}

int OpenLdapClient::countEntries(LDAPMessage* result)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    int num_entries = ldap_count_entries(ldap, result);

    this->retval = LDAP_OTHER;

    return num_entries;
}

LDAPMessage* OpenLdapClient::firstEntry(LDAPMessage* result)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    LDAPMessage* msg = ldap_first_message(ldap, result);

    this->retval = LDAP_OTHER;

    return msg;
}

struct berval** OpenLdapClient::getValuesLen(LDAPMessage* entry,
                                             const char* attr)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    return ldap_get_values_len(this->ldap, entry, attr);
}

bool OpenLdapClient::init(const std::string& host, int port)
{
    if (this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    std::stringstream uri_buf;
    uri_buf << "ldap://" << host << ':' << port;

    this->retval = ldap_initialize(&this->ldap, uri_buf.str().c_str());

    return this->retval == LDAP_SUCCESS;
}

bool OpenLdapClient::msgFree(LDAPMessage* msg)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    this->retval = ldap_msgfree(msg);

    return this->retval == LDAP_SUCCESS;
}

LDAPMessage* OpenLdapClient::nextEntry(LDAPMessage* entry)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    return ldap_next_entry(this->ldap, entry);
}

bool OpenLdapClient::search(const std::string& basedn,
                            int scope,
                            const std::string& filter,
                            char* attrs[],
                            int attrsonly,
                            LDAPControl** serverctrls,
                            LDAPControl** clientctrls,
                            const LdapClient::TimeVal& timeout,
                            int sizelimit,
                            LDAPMessage** results)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    struct timeval openldap_timeout;

    this->setTimeval(timeout, openldap_timeout);

    ldap_search_ext_s(this->ldap,
                      basedn.c_str(),
                      scope,
                      filter.c_str(),
                      attrs,
                      attrsonly,
                      serverctrls,
                      clientctrls,
                      &openldap_timeout,
                      sizelimit,
                      results);

    return this->retval == LDAP_SUCCESS;
}

bool OpenLdapClient::setOption(int option, void* invalue)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    this->retval = ldap_set_option(this->ldap,
                                   option,
                                   invalue);

    return this->retval == LDAP_SUCCESS;
}

void OpenLdapClient::setTimeval(const LdapClient::TimeVal& src, struct timeval& dest)
{
    dest.tv_sec  = src.tv_sec;
    dest.tv_usec = src.tv_usec;
}

bool OpenLdapClient::valueFreeLen(struct berval** val)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    ldap_value_free_len(val);
    this->retval = LDAP_SUCCESS;

    return this->retval == LDAP_SUCCESS;
}

#endif  // OPENLDAP

//------------------------------------------------------------------------------

#ifdef WINLDAP

/** Microsoft Windows LDAP client implementation */
class WinLdapClient : public LdapClient
{
public:
    WinLdapClient() : ldap(NULL), retval(LDAP_SUCCESS) { }
    ~WinLdapClient();

    bool bind(const std::string& dn,
              const std::string& passwd);

    int countEntries(LDAPMessage* result);

    LDAPMessage* firstEntry(LDAPMessage* result);

    int getLastError()            { return this->retval; }
    std::string getLastErrorMsg() { return std::string(ldap_err2string(this->retval)); }

    struct berval** getValuesLen(LDAPMessage* entry,
                                 const char* attr);

    bool init(const std::string& host,
              int port);

    bool msgFree(LDAPMessage* msg);

    LDAPMessage* nextEntry(LDAPMessage* entry);

    bool search(const std::string& basedn,
                int scope,
                const std::string& filter,
                char* attrs[],
                int attrsonly,
                LDAPControl** serverctrls,
                LDAPControl** clientctrls,
                const LdapClient::TimeVal& timeout,
                int sizelimit,
                LDAPMessage** results);

    bool setOption(int option,
                   void *invalue);

    bool valueFreeLen(struct berval** val);

private:
    void setTimeval(const LdapClient::TimeVal& src, struct l_timeval& dest);

private:
    LDAP* ldap;
    int retval;
};

WinLdapClient::~WinLdapClient()
{
    ldap_unbind(this->ldap);
    free(this->ldap);
    this->ldap = NULL;
}

bool WinLdapClient::bind(const std::string& dn,
                         const std::string& passwd)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    this->retval = ldap_simple_bind_s(this->ldap,
                                      (char*) dn.c_str(),
                                      (char*) passwd.c_str());

    return this->retval == LDAP_SUCCESS;
}

int WinLdapClient::countEntries(LDAPMessage* result)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    int num_entries = ldap_count_entries(ldap, result);

    this->retval = LDAP_OTHER;

    return num_entries;
}

LDAPMessage* WinLdapClient::firstEntry(LDAPMessage* result)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    LDAPMessage* msg = ldap_first_entry(ldap, result);

    this->retval = LDAP_OTHER;

    return msg;
}

struct berval** WinLdapClient::getValuesLen(LDAPMessage* entry,
                                            const char* attr)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    return ldap_get_values_len(this->ldap, entry, (char*) attr);
}

bool WinLdapClient::init(const std::string &host, int port)
{
    this->ldap = ldap_init((char*) host.c_str(), port);
    this->retval = LdapGetLastError();
    return this->retval == LDAP_SUCCESS;
}

bool WinLdapClient::msgFree(LDAPMessage* msg)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    this->retval = ldap_msgfree(msg);

    return this->retval == LDAP_SUCCESS;
}

LDAPMessage* WinLdapClient::nextEntry(LDAPMessage* entry)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    return ldap_next_entry(this->ldap, entry);
}

bool WinLdapClient::search(const std::string& basedn,
                            int scope,
                            const std::string& filter,
                            char* attrs[],
                            int attrsonly,
                            LDAPControl** serverctrls,
                            LDAPControl** clientctrls,
                            const LdapClient::TimeVal& timeout,
                            int sizelimit,
                            LDAPMessage** results)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    struct l_timeval winldap_timeout;

    this->setTimeval(timeout, winldap_timeout);

    this->retval = ldap_search_ext_s(this->ldap,
                                     (char*) basedn.c_str(),
                                     scope,
                                     (char*) filter.c_str(),
                                     attrs,
                                     attrsonly,
                                     serverctrls,
                                     clientctrls,
                                     &winldap_timeout,
                                     sizelimit,
                                     results);

    return this->retval == LDAP_SUCCESS;
}

bool WinLdapClient::setOption(int option, void* invalue)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    this->retval = ldap_set_option(this->ldap,
                                   option,
                                   invalue);

    return this->retval == LDAP_SUCCESS;
}

void WinLdapClient::setTimeval(const LdapClient::TimeVal& src, struct l_timeval& dest)
{
    dest.tv_sec  = (long) src.tv_sec;
    dest.tv_usec = (long) src.tv_usec;
}

bool WinLdapClient::valueFreeLen(struct berval** val)
{
    if (!this->ldap) {
        this->retval = LDAP_CONNECT_ERROR;
        return false;
    }

    this->retval = ldap_value_free_len(val);

    return this->retval == LDAP_SUCCESS;
}

#endif // WINLDAP

//------------------------------------------------------------------------------

LdapClient* LdapClient::createInstance()
{
    LdapClient* ldap = NULL;

#ifdef OPENLDAP
    ldap = new OpenLdapClient();
#elif  WINLDAP
    ldap = new WinLdapClient();
#else
    #error "You must specify an LDAP define for LdapClient."
#endif

    return ldap;
}

//------------------------------------------------------------------------------
<|endoftext|>


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

#include <fstream>
#include <vector>
#include <boost/lexical_cast.hpp>
#include "tokenizer.h"
#include "table.h"
#include <stdexcept>
#include <iostream>
#include <boost/algorithm/string/replace.hpp>

using namespace boost;
using namespace std;

void Table::resize(int N, bool preserve)
{
    _x.resize(N, preserve);
    _y.resize(N, preserve);
    _flags.resize(N, preserve);
    if (_has_yerr) {
        _yerr.resize(N, preserve);
    }
}

void Table::Load(string filename)
{
    ifstream in;
    in.open(filename.c_str());
    if(!in)
        throw runtime_error(string("error, cannot open file ") + filename);

    in >> *this;

    in.close();
}

void Table::Save(string filename) const
{
    ofstream out;
    out.open(filename.c_str());
    if(!out)
        throw runtime_error(string("error, cannot open file ") + filename);

    if (_has_comment) {
        string str = "# " + _comment_line;
        boost::replace_all(str, "\\n", "\n# ");
        out << str <<endl;
    }
    out << (*this);

    out.close();
}

void Table::clear(void)
{
    _x.clear();
    _y.clear();
    _flags.clear();
    _yerr.clear();
}

// TODO: this functon is weired, reading occours twice, cleanup!!
// TODO: modify function to work properly, when _has_yerr is true
inline istream &operator>>(istream &in, Table& t)
{
    size_t N;
    bool bHasN=false;
    string line;

   t.clear();

    // read till the first data line
    while(getline(in, line)) {
        // remove comments and xmgrace stuff
        line = line.substr(0, line.find("#"));
        line = line.substr(0, line.find("@"));

        // tokenize string and put it to vector
        Tokenizer tok(line, " \t");
        vector<string> tokens;
        tok.ToVector(tokens);

        // skip empty lines
        if(tokens.size()==0) continue;

        // if first line is only 1 token, it's the size
        if(tokens.size() == 1) {
            N = lexical_cast<int>(tokens[0]);
            bHasN = true;
        }
        // it's the first data line with 2 or 3 entries
        else if(tokens.size() == 2) {
            t.push_back(lexical_cast<double>(tokens[0]), lexical_cast<double>(tokens[1]), 'i');
        }
        else if(tokens.size() > 2) {
           char flag='i';
            if(tokens[2] == "i" || tokens[2] == "o" || tokens[2] == "u")
                flag = tokens[2].c_str()[0];
            t.push_back(lexical_cast<double>(tokens[0]), lexical_cast<double>(tokens[1]), flag);
        }
        else throw runtime_error("error, wrong table format");
    }

    // read the rest
    while(getline(in, line)) {
        // remove comments and xmgrace stuff
        line = line.substr(0, line.find("#"));
        line = line.substr(0, line.find("@"));

        // tokenize string and put it to vector
        Tokenizer tok(line, " \t");
        vector<string> tokens;
        tok.ToVector(tokens);

        // skip empty lines
        if(tokens.size()==0) continue;

        // it's a data line
        if(tokens.size() == 2) {
            t.push_back(lexical_cast<double>(tokens[0]), lexical_cast<double>(tokens[1]), 'i');
        }
        else if(tokens.size() > 2) {
            char flag='i';
            if(tokens[2] == "i" || tokens[2] == "o" || tokens[2] == "u")
                flag = tokens[2].c_str()[0];
            t.push_back(lexical_cast<double>(tokens[0]), lexical_cast<double>(tokens[1]), flag);
        }
        // otherwise error
        else throw runtime_error("error, wrong table format");

        // was size given and did we read N values?
        if(bHasN)
            if(--N == 0) break;
    }

    return in;
}

void Table::GenerateGridSpacing(double min, double max, double spacing)
{
    int n = floor((max - min)/spacing + 1.000000001);
    resize(n);
    int i=0;
    for(double x=min; i<n; x+=spacing, ++i)
        _x[i] = x;
}

void Table::Smooth(int Nsmooth)
{
    while(Nsmooth-- > 0)
        for(int i=1; i<size()-1; ++i)
            _y[i] =0.25*(_y[i-1] + 2*_y[i] +  _y[i+1]);
}

<commit_msg>table, also replace normal \n<commit_after>/*
 * Copyright 2009 The VOTCA Development Team (http://www.votca.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <fstream>
#include <vector>
#include <boost/lexical_cast.hpp>
#include "tokenizer.h"
#include "table.h"
#include <stdexcept>
#include <iostream>
#include <boost/algorithm/string/replace.hpp>

using namespace boost;
using namespace std;

void Table::resize(int N, bool preserve)
{
    _x.resize(N, preserve);
    _y.resize(N, preserve);
    _flags.resize(N, preserve);
    if (_has_yerr) {
        _yerr.resize(N, preserve);
    }
}

void Table::Load(string filename)
{
    ifstream in;
    in.open(filename.c_str());
    if(!in)
        throw runtime_error(string("error, cannot open file ") + filename);

    in >> *this;

    in.close();
}

void Table::Save(string filename) const
{
    ofstream out;
    out.open(filename.c_str());
    if(!out)
        throw runtime_error(string("error, cannot open file ") + filename);

    if (_has_comment) {
        string str = "# " + _comment_line;
        boost::replace_all(str, "\n", "\n# ");
        boost::replace_all(str, "\\n", "\n# ");
        out << str <<endl;
    }
    out << (*this);

    out.close();
}

void Table::clear(void)
{
    _x.clear();
    _y.clear();
    _flags.clear();
    _yerr.clear();
}

// TODO: this functon is weired, reading occours twice, cleanup!!
// TODO: modify function to work properly, when _has_yerr is true
inline istream &operator>>(istream &in, Table& t)
{
    size_t N;
    bool bHasN=false;
    string line;

   t.clear();

    // read till the first data line
    while(getline(in, line)) {
        // remove comments and xmgrace stuff
        line = line.substr(0, line.find("#"));
        line = line.substr(0, line.find("@"));

        // tokenize string and put it to vector
        Tokenizer tok(line, " \t");
        vector<string> tokens;
        tok.ToVector(tokens);

        // skip empty lines
        if(tokens.size()==0) continue;

        // if first line is only 1 token, it's the size
        if(tokens.size() == 1) {
            N = lexical_cast<int>(tokens[0]);
            bHasN = true;
        }
        // it's the first data line with 2 or 3 entries
        else if(tokens.size() == 2) {
            t.push_back(lexical_cast<double>(tokens[0]), lexical_cast<double>(tokens[1]), 'i');
        }
        else if(tokens.size() > 2) {
           char flag='i';
            if(tokens[2] == "i" || tokens[2] == "o" || tokens[2] == "u")
                flag = tokens[2].c_str()[0];
            t.push_back(lexical_cast<double>(tokens[0]), lexical_cast<double>(tokens[1]), flag);
        }
        else throw runtime_error("error, wrong table format");
    }

    // read the rest
    while(getline(in, line)) {
        // remove comments and xmgrace stuff
        line = line.substr(0, line.find("#"));
        line = line.substr(0, line.find("@"));

        // tokenize string and put it to vector
        Tokenizer tok(line, " \t");
        vector<string> tokens;
        tok.ToVector(tokens);

        // skip empty lines
        if(tokens.size()==0) continue;

        // it's a data line
        if(tokens.size() == 2) {
            t.push_back(lexical_cast<double>(tokens[0]), lexical_cast<double>(tokens[1]), 'i');
        }
        else if(tokens.size() > 2) {
            char flag='i';
            if(tokens[2] == "i" || tokens[2] == "o" || tokens[2] == "u")
                flag = tokens[2].c_str()[0];
            t.push_back(lexical_cast<double>(tokens[0]), lexical_cast<double>(tokens[1]), flag);
        }
        // otherwise error
        else throw runtime_error("error, wrong table format");

        // was size given and did we read N values?
        if(bHasN)
            if(--N == 0) break;
    }

    return in;
}

void Table::GenerateGridSpacing(double min, double max, double spacing)
{
    int n = floor((max - min)/spacing + 1.000000001);
    resize(n);
    int i=0;
    for(double x=min; i<n; x+=spacing, ++i)
        _x[i] = x;
}

void Table::Smooth(int Nsmooth)
{
    while(Nsmooth-- > 0)
        for(int i=1; i<size()-1; ++i)
            _y[i] =0.25*(_y[i-1] + 2*_y[i] +  _y[i+1]);
}

<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include <sstream>
#include <string>

#include <stdio.h>
#include <string.h>
#include "config.h"

// opaque version number increments on protocol incompatibility
#ifndef BZ_PROTO_VERSION
#define BZ_PROTO_VERSION	"0021"
#endif

#ifndef BZ_MAJOR_VERSION
#define BZ_MAJOR_VERSION	1
#endif

#ifndef BZ_MINOR_VERSION
#define BZ_MINOR_VERSION	11
#endif

#ifndef BZ_REV
#define BZ_REV			31
#endif

// DEVEL | STABLE | MAINT
#ifndef BZ_BUILD_TYPE
#define BZ_BUILD_TYPE		"DEVEL"
#endif

const char *bzfcopyright = "Copyright (c) 1993 - 2004 Tim Riker";

#ifndef BZ_BUILD_DATE
/* to get the version in the right format YYYYMMDD */
/* yes this is horible but it needs to be done to get it right */
/* windows should pull from a resouce */
/* *nix gets this from the passed from my the Makefile */
char buildDate[] = {__DATE__};

int getBuildDate()
{
  int year = 1900, month = 0, day = 0;
  char monthStr[512];
  sscanf(buildDate, "%s %d %d", monthStr, &day, &year);

  // we want it not as a name but a number
  if (strcmp(monthStr, "Jan") == 0)
    month = 1;
  else if (strcmp(monthStr, "Feb") == 0)
    month = 2;
  else if (strcmp(monthStr, "Mar") == 0)
    month = 3;
  else if (strcmp(monthStr, "Apr") == 0)
    month = 4;
  else if (strcmp(monthStr, "May") == 0)
    month = 5;
  else if (strcmp(monthStr, "Jun") == 0)
    month = 6;
  else if (strcmp(monthStr, "Jul") == 0)
    month = 7;
  else if (strcmp(monthStr, "Aug") == 0)
    month = 8;
  else if (strcmp(monthStr, "Sep") == 0)
    month = 9;
  else if (strcmp(monthStr, "Oct") == 0)
    month = 10;
  else if (strcmp(monthStr, "Nov") == 0)
    month = 11;
  else if (strcmp(monthStr, "Dec") == 0)
    month = 12;

  return (year*10000) + (month*100)+ day;
}
#endif
// down here so above gets created
#include "version.h"

const char*		getProtocolVersion()
{
  static std::string protVersion = BZ_PROTO_VERSION;
  return protVersion.c_str();
}

const char*		getServerVersion()
{
  static std::string serverVersion = std::string("BZFS") + getProtocolVersion();
  return serverVersion.c_str();
}

const char*		getAppVersion()
{
  static std::string	appVersion = "";
  if (!appVersion.size()){
    std::ostringstream	appVersionStream;
    // TODO add current platform, release, cpu, etc
    appVersionStream << BZ_MAJOR_VERSION << "." << BZ_MINOR_VERSION << "." << BZ_REV << "." << BZ_BUILD_DATE
	<< "-" << BZ_BUILD_TYPE << "-" << BZ_BUILD_OS;
#ifdef HAVE_SDL
    appVersionStream << "-SDL";
#endif
    appVersion = appVersionStream.str();
  }
  return appVersion.c_str();
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>places to touch<commit_after>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include <sstream>
#include <string>

#include <stdio.h>
#include <string.h>
#include "config.h"

// opaque version number increments on protocol incompatibility
#ifndef BZ_PROTO_VERSION
#define BZ_PROTO_VERSION	"0021"
#endif

// version numbers - also update:
//  ChangeLog
//  README
//  package/win32/nsis/*.nsi
//  package/win32/*.nsi
//  src/platform/MacOSX/BZFlag-Info.plist
//  tools/TextTool-W32/TextTool.rc
//  win32/VC6/installer.dsp
#ifndef BZ_MAJOR_VERSION
#define BZ_MAJOR_VERSION	1
#endif

#ifndef BZ_MINOR_VERSION
#define BZ_MINOR_VERSION	11
#endif

#ifndef BZ_REV
#define BZ_REV			31
#endif

// DEVEL | STABLE | MAINT
#ifndef BZ_BUILD_TYPE
#define BZ_BUILD_TYPE		"DEVEL"
#endif

const char *bzfcopyright = "Copyright (c) 1993 - 2004 Tim Riker";

#ifndef BZ_BUILD_DATE
/* to get the version in the right format YYYYMMDD */
/* yes this is horible but it needs to be done to get it right */
/* windows should pull from a resouce */
/* *nix gets this from the passed from my the Makefile */
char buildDate[] = {__DATE__};

int getBuildDate()
{
  int year = 1900, month = 0, day = 0;
  char monthStr[512];
  sscanf(buildDate, "%s %d %d", monthStr, &day, &year);

  // we want it not as a name but a number
  if (strcmp(monthStr, "Jan") == 0)
    month = 1;
  else if (strcmp(monthStr, "Feb") == 0)
    month = 2;
  else if (strcmp(monthStr, "Mar") == 0)
    month = 3;
  else if (strcmp(monthStr, "Apr") == 0)
    month = 4;
  else if (strcmp(monthStr, "May") == 0)
    month = 5;
  else if (strcmp(monthStr, "Jun") == 0)
    month = 6;
  else if (strcmp(monthStr, "Jul") == 0)
    month = 7;
  else if (strcmp(monthStr, "Aug") == 0)
    month = 8;
  else if (strcmp(monthStr, "Sep") == 0)
    month = 9;
  else if (strcmp(monthStr, "Oct") == 0)
    month = 10;
  else if (strcmp(monthStr, "Nov") == 0)
    month = 11;
  else if (strcmp(monthStr, "Dec") == 0)
    month = 12;

  return (year*10000) + (month*100)+ day;
}
#endif
// down here so above gets created
#include "version.h"

const char*		getProtocolVersion()
{
  static std::string protVersion = BZ_PROTO_VERSION;
  return protVersion.c_str();
}

const char*		getServerVersion()
{
  static std::string serverVersion = std::string("BZFS") + getProtocolVersion();
  return serverVersion.c_str();
}

const char*		getAppVersion()
{
  static std::string	appVersion = "";
  if (!appVersion.size()){
    std::ostringstream	appVersionStream;
    // TODO add current platform, release, cpu, etc
    appVersionStream << BZ_MAJOR_VERSION << "." << BZ_MINOR_VERSION << "." << BZ_REV << "." << BZ_BUILD_DATE
	<< "-" << BZ_BUILD_TYPE << "-" << BZ_BUILD_OS;
#ifdef HAVE_SDL
    appVersionStream << "-SDL";
#endif
    appVersion = appVersionStream.str();
  }
  return appVersion.c_str();
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkInformation.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkInformation.h"

#include "vtkInformationExecutivePortKey.h"
#include "vtkInformationExecutivePortVectorKey.h"
#include "vtkInformationKeyVectorKey.h"

//----------------------------------------------------------------------------
void vtkInformation::CopyEntry(vtkInformation* from,
                               vtkInformationExecutivePortKey* key, int)
{
  key->ShallowCopy(from, this);
}

//----------------------------------------------------------------------------
void vtkInformation::Append(vtkInformationKeyVectorKey* key,
                            vtkInformationExecutivePortKey* value)
{
  key->Append(this, value);
}

//----------------------------------------------------------------------------
void vtkInformation::AppendUnique(vtkInformationKeyVectorKey* key,
                                  vtkInformationExecutivePortKey* value)
{
  key->AppendUnique(this, value);
}

//----------------------------------------------------------------------------
void vtkInformation::Set(vtkInformationExecutivePortKey* key,
                         vtkExecutive* executive, int port)
{
  key->Set(this, executive, port);
}

//----------------------------------------------------------------------------
void vtkInformation::Remove(vtkInformationExecutivePortKey* key)
{
  key->Remove(this);
}

//----------------------------------------------------------------------------
vtkExecutive* vtkInformation::GetExecutive(vtkInformationExecutivePortKey* key)
{
  return key->GetExecutive(this);
}

//----------------------------------------------------------------------------
int vtkInformation::GetPort(vtkInformationExecutivePortKey* key)
{
  return key->GetPort(this);
}

//----------------------------------------------------------------------------
void vtkInformation::Get(vtkInformationExecutivePortKey* key,
                         vtkExecutive*& executive, int &port)
{
  key->Get(this,executive,port);
}

//----------------------------------------------------------------------------
int vtkInformation::Has(vtkInformationExecutivePortKey* key)
{
  return key->Has(this);
}

//----------------------------------------------------------------------------
void vtkInformation::Append(vtkInformationExecutivePortVectorKey* key,
                            vtkExecutive* executive, int port)
{
  key->Append(this, executive, port);
}

//----------------------------------------------------------------------------
void vtkInformation::Remove(vtkInformationExecutivePortVectorKey* key,
                            vtkExecutive* executive, int port)
{
  key->Remove(this, executive, port);
}

//----------------------------------------------------------------------------
void vtkInformation::Set(vtkInformationExecutivePortVectorKey* key,
                         vtkExecutive** executives, int* ports, int length)
{
  key->Set(this, executives, ports, length);
}

//----------------------------------------------------------------------------
vtkExecutive**
vtkInformation::GetExecutives(vtkInformationExecutivePortVectorKey* key)
{
  return key->GetExecutives(this);
}

//----------------------------------------------------------------------------
int*
vtkInformation::GetPorts(vtkInformationExecutivePortVectorKey* key)
{
  return key->GetPorts(this);
}

//----------------------------------------------------------------------------
void vtkInformation::Get(vtkInformationExecutivePortVectorKey* key,
                         vtkExecutive** executives, int* ports)
{
  key->Get(this, executives, ports);
}

//----------------------------------------------------------------------------
int vtkInformation::Length(vtkInformationExecutivePortVectorKey* key)
{
  return key->Length(this);
}

//----------------------------------------------------------------------------
void vtkInformation::Remove(vtkInformationExecutivePortVectorKey* key)
{
  key->Remove(this);
}

//----------------------------------------------------------------------------
int vtkInformation::Has(vtkInformationExecutivePortVectorKey* key)
{
  return key->Has(this);
}

//----------------------------------------------------------------------------
vtkInformationKey* vtkInformation::GetKey(vtkInformationExecutivePortKey* key)
{
  return key;
}

<commit_msg>COMP: Try to eliminate "inconsistent DLL linkage" warnings on Win32/64.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkInformation.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkInformationExecutivePortKey.h"
#include "vtkInformationExecutivePortVectorKey.h"
#include "vtkInformationKeyVectorKey.h"

#include "vtkObject.h"
#ifdef __vtkInformation_h
#  error "vtkInformation.h must not be included before this line."
#endif // __vtkInformation_h
#undef VTK_COMMON_EXPORT
#define VTK_COMMON_EXPORT VTK_FILTERING_EXPORT
#include "vtkInformation.h" // Must be last include

//----------------------------------------------------------------------------
void vtkInformation::CopyEntry(vtkInformation* from,
                               vtkInformationExecutivePortKey* key, int)
{
  key->ShallowCopy(from, this);
}

//----------------------------------------------------------------------------
void vtkInformation::Append(vtkInformationKeyVectorKey* key,
                            vtkInformationExecutivePortKey* value)
{
  key->Append(this, value);
}

//----------------------------------------------------------------------------
void vtkInformation::AppendUnique(vtkInformationKeyVectorKey* key,
                                  vtkInformationExecutivePortKey* value)
{
  key->AppendUnique(this, value);
}

//----------------------------------------------------------------------------
void vtkInformation::Set(vtkInformationExecutivePortKey* key,
                         vtkExecutive* executive, int port)
{
  key->Set(this, executive, port);
}

//----------------------------------------------------------------------------
void vtkInformation::Remove(vtkInformationExecutivePortKey* key)
{
  key->Remove(this);
}

//----------------------------------------------------------------------------
vtkExecutive* vtkInformation::GetExecutive(vtkInformationExecutivePortKey* key)
{
  return key->GetExecutive(this);
}

//----------------------------------------------------------------------------
int vtkInformation::GetPort(vtkInformationExecutivePortKey* key)
{
  return key->GetPort(this);
}

//----------------------------------------------------------------------------
void vtkInformation::Get(vtkInformationExecutivePortKey* key,
                         vtkExecutive*& executive, int &port)
{
  key->Get(this,executive,port);
}

//----------------------------------------------------------------------------
int vtkInformation::Has(vtkInformationExecutivePortKey* key)
{
  return key->Has(this);
}

//----------------------------------------------------------------------------
void vtkInformation::Append(vtkInformationExecutivePortVectorKey* key,
                            vtkExecutive* executive, int port)
{
  key->Append(this, executive, port);
}

//----------------------------------------------------------------------------
void vtkInformation::Remove(vtkInformationExecutivePortVectorKey* key,
                            vtkExecutive* executive, int port)
{
  key->Remove(this, executive, port);
}

//----------------------------------------------------------------------------
void vtkInformation::Set(vtkInformationExecutivePortVectorKey* key,
                         vtkExecutive** executives, int* ports, int length)
{
  key->Set(this, executives, ports, length);
}

//----------------------------------------------------------------------------
vtkExecutive**
vtkInformation::GetExecutives(vtkInformationExecutivePortVectorKey* key)
{
  return key->GetExecutives(this);
}

//----------------------------------------------------------------------------
int*
vtkInformation::GetPorts(vtkInformationExecutivePortVectorKey* key)
{
  return key->GetPorts(this);
}

//----------------------------------------------------------------------------
void vtkInformation::Get(vtkInformationExecutivePortVectorKey* key,
                         vtkExecutive** executives, int* ports)
{
  key->Get(this, executives, ports);
}

//----------------------------------------------------------------------------
int vtkInformation::Length(vtkInformationExecutivePortVectorKey* key)
{
  return key->Length(this);
}

//----------------------------------------------------------------------------
void vtkInformation::Remove(vtkInformationExecutivePortVectorKey* key)
{
  key->Remove(this);
}

//----------------------------------------------------------------------------
int vtkInformation::Has(vtkInformationExecutivePortVectorKey* key)
{
  return key->Has(this);
}

//----------------------------------------------------------------------------
vtkInformationKey* vtkInformation::GetKey(vtkInformationExecutivePortKey* key)
{
  return key;
}

<|endoftext|>


<commit_before>/// XXX add licence
//

#ifndef HAVE_LLVM
# error "Need LLVM for LLVMDependenceGraph"
#endif

#ifndef ENABLE_CFG
 #error "Need CFG enabled for building LLVM Dependence Graph"
#endif

#include <llvm/IR/Instruction.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/Value.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Constants.h>
#include <llvm/IR/GlobalVariable.h>
#include <llvm/Support/raw_ostream.h>

#include "LLVMNode.h"
#include "LLVMDependenceGraph.h"

using llvm::errs;

namespace dg {

LLVMNode::~LLVMNode()
{
    if (owns_key)
        delete getKey();

    delete memoryobj;
    delete[] operands;
}

void LLVMNode::dump() const
{
    getKey()->dump();
}

LLVMNode **LLVMNode::findOperands()
{
    using namespace llvm;
    const Value *val = getKey();

    // FIXME use op_begin() and op_end() and do it generic
    // for all the instructions (+ maybe some speacial handling
    // like CallInst?)

    // we have Function nodes stored in globals
    if (isa<AllocaInst>(val)) {
        operands = new LLVMNode *[1];
        operands[0] = dg->getNode(val);
        operands_num = 1;
    } else if (const StoreInst *Inst = dyn_cast<StoreInst>(val)) {
        operands = new LLVMNode *[2];
        operands[0] = dg->getNode(Inst->getPointerOperand());
        operands[1] = dg->getNode(Inst->getValueOperand());
#ifdef DEBUG_ENABLED
        if (!operands[0] && !isa<Constant>(Inst->getPointerOperand()))
            errs() << "WARN: Didn't found pointer for " << *Inst << "\n";
        if (!operands[1] && !isa<Constant>(Inst->getValueOperand()))
            errs() << "WARN: Didn't found value for " << *Inst << "\n";
#endif
        operands_num = 2;
    } else if (const LoadInst *Inst = dyn_cast<LoadInst>(val)) {
        operands = new LLVMNode *[1];
        const Value *op = Inst->getPointerOperand();
        operands[0] = dg->getNode(op);
#ifdef DEBUG_ENABLED
        if (!operands[0])
            errs() << "WARN: Didn't found pointer for " << *Inst << "\n";
#endif
        operands_num = 1;
    } else if (const GetElementPtrInst *Inst = dyn_cast<GetElementPtrInst>(val)) {
        operands = new LLVMNode *[1];
        operands[0] = dg->getNode(Inst->getPointerOperand());
        operands_num = 1;
    } else if (const CallInst *Inst = dyn_cast<CallInst>(val)) {
        // we store the called function as a first operand
        // and all the arguments as the other operands
        operands_num = Inst->getNumArgOperands() + 1;
        operands = new LLVMNode *[operands_num];
        operands[0] = dg->getNode(Inst->getCalledValue());
        for (unsigned i = 0; i < operands_num - 1; ++i)
            operands[i + 1] = dg->getNode(Inst->getArgOperand(i));
    } else if (const ReturnInst *Inst = dyn_cast<ReturnInst>(val)) {
        operands = new LLVMNode *[1];
        operands[0] = dg->getNode(Inst->getReturnValue());
        operands_num = 1;
    } else if (const CastInst *Inst = dyn_cast<CastInst>(val)) {
        operands = new LLVMNode *[1];
        operands[0] = dg->getNode(Inst->stripPointerCasts());
        if (!operands[0])
            errs() << "WARN: CastInst with unstrippable pointer cast" << *Inst << "\n";
        operands_num = 1;
    }

    if (!operands) {
        errs() << "Unhandled instruction: " << *val
               << "Type: " << *val->getType() << "\n";
        abort();
    }

    return operands;
}

void LLVMNode::addActualParameters(LLVMDependenceGraph *funcGraph)
{
    using namespace llvm;

    const CallInst *CInst = dyn_cast<CallInst>(key);
    assert(CInst && "addActualParameters called on non-CallInst");

    // do not add redundant nodes
    const Function *func = CInst->getCalledFunction();
    if (!func || func->arg_size() == 0)
        return;

    addActualParameters(funcGraph, func);
}

void LLVMNode::addActualParameters(LLVMDependenceGraph *funcGraph,
                                   const llvm::Function *func)
{
    using namespace llvm;

    const CallInst *CInst = dyn_cast<CallInst>(key);
    assert(CInst && "addActualParameters called on non-CallInst");

    // do not do nothing if we have parameters.
    // This is probably adding subgraph due to function
    // pointer in data-flow analysis
    if (getParameters())
        return;

    LLVMDGParameters *formal = funcGraph->getParameters();
    LLVMDGParameters *params = new LLVMDGParameters();
    LLVMDGParameters *old = addParameters(params);
    assert(old == nullptr && "Replaced parameters");

    // we need to add edges from actual parameters to formal parameteres
    // so if the params exists, just add the edges. If the params
    // do not exists, create them and then add the edges

    LLVMNode *in, *out;
    int idx = 0;
    for (auto A = func->arg_begin(), E = func->arg_end();
         A != E; ++A, ++idx) {
        const Value *opval = CInst->getArgOperand(idx);
        LLVMDGParameter *fp = formal->find(&*A);
        if (!fp) {
            errs() << "ERR: no formal param for value: " << *opval << "\n";
            continue;
        }

        in = new LLVMNode(opval);
        out = new LLVMNode(opval);
        params->add(opval, in, out, fp);

        // add control edges from the call-site node
        // to the parameters
        addControlDependence(in);
        addControlDependence(out);

        // from actual in to formal in
        in->addDataDependence(fp->in);
        // from formal out to actual out
        fp->out->addDataDependence(out);
    }
}

LLVMNode **LLVMNode::getOperands()
{
    if (!operands)
        findOperands();

    return operands;
}

size_t LLVMNode::getOperandsNum()
{
    if (!operands)
        findOperands();

    return operands_num;
}

LLVMNode *LLVMNode::getOperand(unsigned int idx)
{
    if (!operands)
        findOperands();

    assert(operands_num > idx && "idx is too high");
    return operands[idx];
}

LLVMNode *LLVMNode::setOperand(LLVMNode *op, unsigned int idx)
{
    assert(operands && "Operands has not been found yet");
    assert(operands_num > idx && "idx is too high");

    LLVMNode *old = operands[idx];
    operands[idx] = op;

    return old;
}

} // namespace dg
<commit_msg>llvmnode: make actual params be aware of function pointers<commit_after>/// XXX add licence
//

#ifndef HAVE_LLVM
# error "Need LLVM for LLVMDependenceGraph"
#endif

#ifndef ENABLE_CFG
 #error "Need CFG enabled for building LLVM Dependence Graph"
#endif

#include <llvm/IR/Instruction.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/Value.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Constants.h>
#include <llvm/IR/GlobalVariable.h>
#include <llvm/Support/raw_ostream.h>

#include "LLVMNode.h"
#include "LLVMDependenceGraph.h"

using llvm::errs;

namespace dg {

LLVMNode::~LLVMNode()
{
    if (owns_key)
        delete getKey();

    delete memoryobj;
    delete[] operands;
}

void LLVMNode::dump() const
{
    getKey()->dump();
}

LLVMNode **LLVMNode::findOperands()
{
    using namespace llvm;
    const Value *val = getKey();

    // FIXME use op_begin() and op_end() and do it generic
    // for all the instructions (+ maybe some speacial handling
    // like CallInst?)

    // we have Function nodes stored in globals
    if (isa<AllocaInst>(val)) {
        operands = new LLVMNode *[1];
        operands[0] = dg->getNode(val);
        operands_num = 1;
    } else if (const StoreInst *Inst = dyn_cast<StoreInst>(val)) {
        operands = new LLVMNode *[2];
        operands[0] = dg->getNode(Inst->getPointerOperand());
        operands[1] = dg->getNode(Inst->getValueOperand());
#ifdef DEBUG_ENABLED
        if (!operands[0] && !isa<Constant>(Inst->getPointerOperand()))
            errs() << "WARN: Didn't found pointer for " << *Inst << "\n";
        if (!operands[1] && !isa<Constant>(Inst->getValueOperand()))
            errs() << "WARN: Didn't found value for " << *Inst << "\n";
#endif
        operands_num = 2;
    } else if (const LoadInst *Inst = dyn_cast<LoadInst>(val)) {
        operands = new LLVMNode *[1];
        const Value *op = Inst->getPointerOperand();
        operands[0] = dg->getNode(op);
#ifdef DEBUG_ENABLED
        if (!operands[0])
            errs() << "WARN: Didn't found pointer for " << *Inst << "\n";
#endif
        operands_num = 1;
    } else if (const GetElementPtrInst *Inst = dyn_cast<GetElementPtrInst>(val)) {
        operands = new LLVMNode *[1];
        operands[0] = dg->getNode(Inst->getPointerOperand());
        operands_num = 1;
    } else if (const CallInst *Inst = dyn_cast<CallInst>(val)) {
        // we store the called function as a first operand
        // and all the arguments as the other operands
        operands_num = Inst->getNumArgOperands() + 1;
        operands = new LLVMNode *[operands_num];
        operands[0] = dg->getNode(Inst->getCalledValue());
        for (unsigned i = 0; i < operands_num - 1; ++i)
            operands[i + 1] = dg->getNode(Inst->getArgOperand(i));
    } else if (const ReturnInst *Inst = dyn_cast<ReturnInst>(val)) {
        operands = new LLVMNode *[1];
        operands[0] = dg->getNode(Inst->getReturnValue());
        operands_num = 1;
    } else if (const CastInst *Inst = dyn_cast<CastInst>(val)) {
        operands = new LLVMNode *[1];
        operands[0] = dg->getNode(Inst->stripPointerCasts());
        if (!operands[0])
            errs() << "WARN: CastInst with unstrippable pointer cast" << *Inst << "\n";
        operands_num = 1;
    }

    if (!operands) {
        errs() << "Unhandled instruction: " << *val
               << "Type: " << *val->getType() << "\n";
        abort();
    }

    return operands;
}

void LLVMNode::addActualParameters(LLVMDependenceGraph *funcGraph)
{
    using namespace llvm;

    const CallInst *CInst = dyn_cast<CallInst>(key);
    assert(CInst && "addActualParameters called on non-CallInst");

    // do not add redundant nodes
    const Function *func = CInst->getCalledFunction();
    if (!func || func->arg_size() == 0)
        return;

    addActualParameters(funcGraph, func);
}

void LLVMNode::addActualParameters(LLVMDependenceGraph *funcGraph,
                                   const llvm::Function *func)
{
    using namespace llvm;

    const CallInst *CInst = dyn_cast<CallInst>(key);
    assert(CInst && "addActualParameters called on non-CallInst");

    // if we have parameters, then use them and just
    // add edges to formal parameters (a call-site can
    // have more destinations if it is via function pointer)
    LLVMDGParameters *params = getParameters();
    if (!params) {
        params = new LLVMDGParameters();
        LLVMDGParameters *old = addParameters(params);
        assert(old == nullptr && "Replaced parameters");
    }

    LLVMDGParameters *formal = funcGraph->getParameters();

    LLVMNode *in, *out;
    int idx = 0;
    for (auto A = func->arg_begin(), E = func->arg_end();
         A != E; ++A, ++idx) {
        const Value *opval = CInst->getArgOperand(idx);
        LLVMDGParameter *fp = formal->find(&*A);
        if (!fp) {
            errs() << "ERR: no formal param for value: " << *opval << "\n";
            continue;
        }

        LLVMDGParameter *ap = params->find(opval);
        if (!ap) {
            in = new LLVMNode(opval);
            out = new LLVMNode(opval);
            params->add(opval, in, out);
        } else {
            in = ap->in;
            out = ap->out;
        }

        // add control edges from the call-site node
        // to the parameters
        addControlDependence(in);
        addControlDependence(out);

        // from actual in to formal in
        in->addDataDependence(fp->in);
        // from formal out to actual out
        fp->out->addDataDependence(out);
    }
}

LLVMNode **LLVMNode::getOperands()
{
    if (!operands)
        findOperands();

    return operands;
}

size_t LLVMNode::getOperandsNum()
{
    if (!operands)
        findOperands();

    return operands_num;
}

LLVMNode *LLVMNode::getOperand(unsigned int idx)
{
    if (!operands)
        findOperands();

    assert(operands_num > idx && "idx is too high");
    return operands[idx];
}

LLVMNode *LLVMNode::setOperand(LLVMNode *op, unsigned int idx)
{
    assert(operands && "Operands has not been found yet");
    assert(operands_num > idx && "idx is too high");

    LLVMNode *old = operands[idx];
    operands[idx] = op;

    return old;
}

} // namespace dg
<|endoftext|>


<commit_before>/*
 * Delegate helper pooling.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "Stock.hxx"
#include "stock/MapStock.hxx"
#include "stock/Class.hxx"
#include "stock/Item.hxx"
#include "async.hxx"
#include "failure.hxx"
#include "system/fd_util.h"
#include "event/Event.hxx"
#include "event/Callback.hxx"
#include "spawn/Spawn.hxx"
#include "spawn/Prepared.hxx"
#include "spawn/ChildOptions.hxx"
#include "gerrno.h"
#include "pool.hxx"

#include <daemon/log.h>

#include <assert.h>
#include <unistd.h>
#include <sys/un.h>
#include <sys/socket.h>

struct DelegateArgs {
    const char *executable_path;

    const ChildOptions &options;

    DelegateArgs(const char *_executable_path,
                 const ChildOptions &_options)
        :executable_path(_executable_path), options(_options) {}
};

struct DelegateProcess final : HeapStockItem {
    const pid_t pid;
    const int fd;

    Event event;

    explicit DelegateProcess(CreateStockItem c,
                             pid_t _pid, int _fd)
        :HeapStockItem(c), pid(_pid), fd(_fd) {
        event.Set(fd, EV_READ|EV_TIMEOUT,
                  MakeEventCallback(DelegateProcess, EventCallback), this);
    }

    ~DelegateProcess() override {
        if (fd >= 0) {
            event.Delete();
            close(fd);
        }
    }

    void EventCallback(int fd, short event);

    /* virtual methods from class StockItem */
    bool Borrow(gcc_unused void *ctx) override {
        event.Delete();
        return true;
    }

    bool Release(gcc_unused void *ctx) override {
        static constexpr struct timeval tv = {
            .tv_sec = 60,
            .tv_usec = 0,
        };

        event.Add(tv);
        return true;
    }
};

/*
 * libevent callback
 *
 */

inline void
DelegateProcess::EventCallback(gcc_unused int _fd, short events)
{
    assert(_fd == fd);

    if ((events & EV_TIMEOUT) == 0) {
        assert((events & EV_READ) != 0);

        char buffer;
        ssize_t nbytes = recv(fd, &buffer, sizeof(buffer), MSG_DONTWAIT);
        if (nbytes < 0)
            daemon_log(2, "error on idle delegate process: %s\n",
                       strerror(errno));
        else if (nbytes > 0)
            daemon_log(2, "unexpected data from idle delegate process\n");
    }

    InvokeIdleDisconnect();
    pool_commit();
}

/*
 * stock class
 *
 */

static void
delegate_stock_create(gcc_unused void *ctx,
                      gcc_unused struct pool &parent_pool, CreateStockItem c,
                      gcc_unused const char *uri, void *_info,
                      gcc_unused struct pool &caller_pool,
                      gcc_unused struct async_operation_ref &async_ref)
{
    auto &info = *(DelegateArgs *)_info;

    PreparedChildProcess p;
    p.Append(info.executable_path);

    GError *error = nullptr;
    if (!info.options.CopyTo(p, true, nullptr, &error)) {
        c.InvokeCreateError(error);
        return;
    }

    int fds[2];
    if (socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
        error = new_error_errno_msg("socketpair() failed: %s");
        c.InvokeCreateError(error);
        return;
    }

    p.stdin_fd = fds[1];

    pid_t pid = SpawnChildProcess(std::move(p));
    if (pid < 0) {
        error = new_error_errno_msg2(-pid, "clone() failed");
        close(fds[0]);
        c.InvokeCreateError(error);
        return;
    }

    auto *process = new DelegateProcess(c, pid, fds[0]);
    process->InvokeCreateSuccess();
}

static constexpr StockClass delegate_stock_class = {
    .create = delegate_stock_create,
};

/*
 * interface
 *
 */

StockMap *
delegate_stock_new(struct pool *pool)
{
    return hstock_new(*pool, delegate_stock_class, nullptr, 0, 16);
}

StockItem *
delegate_stock_get(StockMap *delegate_stock, struct pool *pool,
                   const char *helper,
                   const ChildOptions &options,
                   GError **error_r)
{
    const char *uri = helper;

    char options_buffer[4096];
    *options.MakeId(options_buffer) = 0;
    if (*options_buffer != 0)
        uri = p_strcat(pool, helper, "|", options_buffer, nullptr);

    DelegateArgs args(helper, options);
    return hstock_get_now(*delegate_stock, *pool, uri, &args, error_r);
}

int
delegate_stock_item_get(StockItem &item)
{
    auto *process = (DelegateProcess *)&item;

    return process->fd;
}
<commit_msg>delegate/Stock: move code to DelegateArgs::GetStockKey()<commit_after>/*
 * Delegate helper pooling.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "Stock.hxx"
#include "stock/MapStock.hxx"
#include "stock/Class.hxx"
#include "stock/Item.hxx"
#include "async.hxx"
#include "failure.hxx"
#include "system/fd_util.h"
#include "event/Event.hxx"
#include "event/Callback.hxx"
#include "spawn/Spawn.hxx"
#include "spawn/Prepared.hxx"
#include "spawn/ChildOptions.hxx"
#include "gerrno.h"
#include "pool.hxx"

#include <daemon/log.h>

#include <assert.h>
#include <unistd.h>
#include <sys/un.h>
#include <sys/socket.h>

struct DelegateArgs {
    const char *executable_path;

    const ChildOptions &options;

    DelegateArgs(const char *_executable_path,
                 const ChildOptions &_options)
        :executable_path(_executable_path), options(_options) {}

    const char *GetStockKey(struct pool &pool) const {
        const char *key = executable_path;

        char options_buffer[4096];
        *options.MakeId(options_buffer) = 0;
        if (*options_buffer != 0)
            key = p_strcat(&pool, key, "|", options_buffer, nullptr);

        return key;
    }
};

struct DelegateProcess final : HeapStockItem {
    const pid_t pid;
    const int fd;

    Event event;

    explicit DelegateProcess(CreateStockItem c,
                             pid_t _pid, int _fd)
        :HeapStockItem(c), pid(_pid), fd(_fd) {
        event.Set(fd, EV_READ|EV_TIMEOUT,
                  MakeEventCallback(DelegateProcess, EventCallback), this);
    }

    ~DelegateProcess() override {
        if (fd >= 0) {
            event.Delete();
            close(fd);
        }
    }

    void EventCallback(int fd, short event);

    /* virtual methods from class StockItem */
    bool Borrow(gcc_unused void *ctx) override {
        event.Delete();
        return true;
    }

    bool Release(gcc_unused void *ctx) override {
        static constexpr struct timeval tv = {
            .tv_sec = 60,
            .tv_usec = 0,
        };

        event.Add(tv);
        return true;
    }
};

/*
 * libevent callback
 *
 */

inline void
DelegateProcess::EventCallback(gcc_unused int _fd, short events)
{
    assert(_fd == fd);

    if ((events & EV_TIMEOUT) == 0) {
        assert((events & EV_READ) != 0);

        char buffer;
        ssize_t nbytes = recv(fd, &buffer, sizeof(buffer), MSG_DONTWAIT);
        if (nbytes < 0)
            daemon_log(2, "error on idle delegate process: %s\n",
                       strerror(errno));
        else if (nbytes > 0)
            daemon_log(2, "unexpected data from idle delegate process\n");
    }

    InvokeIdleDisconnect();
    pool_commit();
}

/*
 * stock class
 *
 */

static void
delegate_stock_create(gcc_unused void *ctx,
                      gcc_unused struct pool &parent_pool, CreateStockItem c,
                      gcc_unused const char *uri, void *_info,
                      gcc_unused struct pool &caller_pool,
                      gcc_unused struct async_operation_ref &async_ref)
{
    auto &info = *(DelegateArgs *)_info;

    PreparedChildProcess p;
    p.Append(info.executable_path);

    GError *error = nullptr;
    if (!info.options.CopyTo(p, true, nullptr, &error)) {
        c.InvokeCreateError(error);
        return;
    }

    int fds[2];
    if (socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
        error = new_error_errno_msg("socketpair() failed: %s");
        c.InvokeCreateError(error);
        return;
    }

    p.stdin_fd = fds[1];

    pid_t pid = SpawnChildProcess(std::move(p));
    if (pid < 0) {
        error = new_error_errno_msg2(-pid, "clone() failed");
        close(fds[0]);
        c.InvokeCreateError(error);
        return;
    }

    auto *process = new DelegateProcess(c, pid, fds[0]);
    process->InvokeCreateSuccess();
}

static constexpr StockClass delegate_stock_class = {
    .create = delegate_stock_create,
};

/*
 * interface
 *
 */

StockMap *
delegate_stock_new(struct pool *pool)
{
    return hstock_new(*pool, delegate_stock_class, nullptr, 0, 16);
}

StockItem *
delegate_stock_get(StockMap *delegate_stock, struct pool *pool,
                   const char *helper,
                   const ChildOptions &options,
                   GError **error_r)
{
    DelegateArgs args(helper, options);
    return hstock_get_now(*delegate_stock, *pool, args.GetStockKey(*pool),
                          &args, error_r);
}

int
delegate_stock_item_get(StockItem &item)
{
    auto *process = (DelegateProcess *)&item;

    return process->fd;
}
<|endoftext|>